mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Merge pull request #5646 from ErisDS/issue-5150-nextprev
Next/Prev Post helpers include author & tags
This commit is contained in:
commit
9376bdf699
@ -9,7 +9,10 @@ var Promise = require('bluebird'),
|
||||
pipeline = require('../utils/pipeline'),
|
||||
|
||||
docName = 'posts',
|
||||
allowedIncludes = ['created_by', 'updated_by', 'published_by', 'author', 'tags', 'fields', 'next', 'previous'],
|
||||
allowedIncludes = [
|
||||
'created_by', 'updated_by', 'published_by', 'author', 'tags', 'fields',
|
||||
'next', 'previous', 'next.author', 'next.tags', 'previous.author', 'previous.tags'
|
||||
],
|
||||
posts;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@ prevNext = function (options) {
|
||||
options = options || {};
|
||||
|
||||
var apiOptions = {
|
||||
include: options.name === 'prev_post' ? 'previous' : 'next'
|
||||
include: options.name === 'prev_post' ? 'previous,previous.author,previous.tags' : 'next,next.author,next.tags'
|
||||
};
|
||||
|
||||
if (schema.isPost(this) && this.status === 'published') {
|
||||
|
@ -399,7 +399,21 @@ Post = ghostBookshelf.Model.extend({
|
||||
options = options || {};
|
||||
|
||||
var withNext = _.contains(options.include, 'next'),
|
||||
withPrev = _.contains(options.include, 'previous');
|
||||
withPrev = _.contains(options.include, 'previous'),
|
||||
nextRelations = _.transform(options.include, function (relations, include) {
|
||||
if (include === 'next.tags') {
|
||||
relations.push('tags');
|
||||
} else if (include === 'next.author') {
|
||||
relations.push('author');
|
||||
}
|
||||
}, []),
|
||||
prevRelations = _.transform(options.include, function (relations, include) {
|
||||
if (include === 'previous.tags') {
|
||||
relations.push('tags');
|
||||
} else if (include === 'previous.author') {
|
||||
relations.push('author');
|
||||
}
|
||||
}, []);
|
||||
|
||||
data = _.defaults(data || {}, {
|
||||
status: 'published'
|
||||
@ -410,7 +424,10 @@ Post = ghostBookshelf.Model.extend({
|
||||
}
|
||||
|
||||
// Add related objects, excluding next and previous as they are not real db objects
|
||||
options.withRelated = _.union(options.withRelated, _.pull([].concat(options.include), 'next', 'previous'));
|
||||
options.withRelated = _.union(options.withRelated, _.pull(
|
||||
[].concat(options.include),
|
||||
'next', 'next.author', 'next.tags', 'previous', 'previous.author', 'previous.tags')
|
||||
);
|
||||
|
||||
return ghostBookshelf.Model.findOne.call(this, data, options).then(function then(post) {
|
||||
if ((withNext || withPrev) && post && !post.page) {
|
||||
@ -425,7 +442,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
.andWhere('published_at', '>', publishedAt)
|
||||
.orderBy('published_at', 'asc')
|
||||
.limit(1);
|
||||
}).fetch();
|
||||
}).fetch({withRelated: nextRelations});
|
||||
}
|
||||
|
||||
if (withPrev) {
|
||||
@ -435,7 +452,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
.andWhere('published_at', '<', publishedAt)
|
||||
.orderBy('published_at', 'desc')
|
||||
.limit(1);
|
||||
}).fetch();
|
||||
}).fetch({withRelated: prevRelations});
|
||||
}
|
||||
|
||||
return Promise.join(next, prev)
|
||||
|
@ -320,6 +320,27 @@ describe('Post API', function () {
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('can include next post with author and tags', function (done) {
|
||||
PostAPI.read({context: {user: 1}, id: 3, include: 'next,next.tags,next.author'}).then(function (results) {
|
||||
should.exist(results.posts[0].next.slug);
|
||||
results.posts[0].next.slug.should.eql('not-so-short-bit-complex');
|
||||
results.posts[0].next.author.should.be.an.Object;
|
||||
results.posts[0].next.tags.should.be.an.Array;
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('can include next post with just tags', function (done) {
|
||||
PostAPI.read({context: {user: 1}, id: 2, include: 'next,next.tags'}).then(function (results) {
|
||||
should.exist(results.posts[0].next.slug);
|
||||
results.posts[0].next.slug.should.eql('short-and-sweet');
|
||||
results.posts[0].next.author.should.eql(1);
|
||||
results.posts[0].next.tags.should.be.an.Array;
|
||||
results.posts[0].next.tags[0].name.should.eql('chorizo');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('can include previous post', function (done) {
|
||||
PostAPI.read({context: {user: 1}, id: 3, include: 'previous'}).then(function (results) {
|
||||
should.exist(results.posts[0].previous.slug);
|
||||
@ -327,5 +348,29 @@ describe('Post API', function () {
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('can include previous post with author and tags', function (done) {
|
||||
PostAPI.read({context: {user: 1}, id: 3, include: 'previous,previous.author,previous.tags'}).then(function (results) {
|
||||
should.exist(results.posts[0].previous.slug);
|
||||
results.posts[0].previous.slug.should.eql('ghostly-kitchen-sink');
|
||||
results.posts[0].previous.author.should.be.an.Object;
|
||||
results.posts[0].previous.author.name.should.eql('Joe Bloggs');
|
||||
results.posts[0].previous.tags.should.be.an.Array;
|
||||
results.posts[0].previous.tags.should.have.lengthOf(2);
|
||||
results.posts[0].previous.tags[0].slug.should.eql('kitchen-sink');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('can include previous post with just author', function (done) {
|
||||
PostAPI.read({context: {user: 1}, id: 3, include: 'previous,previous.author'}).then(function (results) {
|
||||
should.exist(results.posts[0].previous.slug);
|
||||
should.not.exist(results.posts[0].previous.tags);
|
||||
results.posts[0].previous.slug.should.eql('ghostly-kitchen-sink');
|
||||
results.posts[0].previous.author.should.be.an.Object;
|
||||
results.posts[0].previous.author.name.should.eql('Joe Bloggs');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -9,16 +9,22 @@ var should = require('should'),
|
||||
// Stuff we are testing
|
||||
handlebars = hbs.handlebars,
|
||||
helpers = require('../../../server/helpers'),
|
||||
api = require('../../../server/api');
|
||||
api = require('../../../server/api'),
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
describe('{{next_post}} helper', function () {
|
||||
var readPostStub;
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe('with valid post data - ', function () {
|
||||
var sandbox;
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'next') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('next') === 0) {
|
||||
return Promise.resolve({
|
||||
posts: [{slug: '/current/', title: 'post 2', next: {slug: '/next/', title: 'post 3'}}]
|
||||
});
|
||||
@ -26,10 +32,6 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('has loaded next_post helper', function () {
|
||||
should.exist(handlebars.helpers.prev_post);
|
||||
});
|
||||
@ -46,8 +48,11 @@ describe('{{next_post}} helper', function () {
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'}, optionsData).then(function () {
|
||||
fn.called.should.be.true;
|
||||
inverse.called.should.be.false;
|
||||
fn.calledOnce.should.be.true;
|
||||
inverse.calledOnce.should.be.false;
|
||||
|
||||
readPostStub.calledOnce.should.be.true;
|
||||
readPostStub.firstCall.args[0].include.should.eql('next,next.author,next.tags');
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
console.log('err ', err);
|
||||
@ -57,22 +62,15 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
|
||||
describe('for valid post with no next post', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'next') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('next') === 0) {
|
||||
return Promise.resolve({posts: [{slug: '/current/', title: 'post 2'}]});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
@ -94,22 +92,15 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
|
||||
describe('for invalid post data', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'previous') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('next') === 0) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
@ -118,6 +109,7 @@ describe('{{next_post}} helper', function () {
|
||||
helpers.prev_post.call({}, optionsData).then(function () {
|
||||
fn.called.should.be.false;
|
||||
inverse.called.should.be.true;
|
||||
readPostStub.called.should.be.false;
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@ -126,13 +118,10 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
|
||||
describe('for unpublished post', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'next') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('next') === 0) {
|
||||
return Promise.resolve({
|
||||
posts: [{slug: '/current/', title: 'post 2', next: {slug: '/next/', title: 'post 3'}}]
|
||||
});
|
||||
@ -140,10 +129,6 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
|
@ -9,17 +9,22 @@ var should = require('should'),
|
||||
// Stuff we are testing
|
||||
handlebars = hbs.handlebars,
|
||||
helpers = require('../../../server/helpers'),
|
||||
api = require('../../../server/api');
|
||||
api = require('../../../server/api'),
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
describe('{{prev_post}} helper', function () {
|
||||
describe('with valid post data - ', function () {
|
||||
var sandbox;
|
||||
var readPostStub;
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe('with valid post data - ', function () {
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'previous') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('previous') === 0) {
|
||||
return Promise.resolve({
|
||||
posts: [{slug: '/current/', title: 'post 2', previous: {slug: '/previous/', title: 'post 1'}}]
|
||||
});
|
||||
@ -27,10 +32,6 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('has loaded prev_post helper', function () {
|
||||
should.exist(handlebars.helpers.prev_post);
|
||||
});
|
||||
@ -47,8 +48,12 @@ describe('{{prev_post}} helper', function () {
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'}, optionsData).then(function () {
|
||||
fn.called.should.be.true;
|
||||
inverse.called.should.be.false;
|
||||
fn.calledOnce.should.be.true;
|
||||
inverse.calledOnce.should.be.false;
|
||||
|
||||
readPostStub.calledOnce.should.be.true;
|
||||
readPostStub.firstCall.args[0].include.should.eql('previous,previous.author,previous.tags');
|
||||
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
console.log('err ', err);
|
||||
@ -58,22 +63,15 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
|
||||
describe('for valid post with no previous post', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'previous') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('previous') === 0) {
|
||||
return Promise.resolve({posts: [{slug: '/current/', title: 'post 2'}]});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
@ -96,22 +94,15 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
|
||||
describe('for invalid post data', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'previous') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('previous') === 0) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
@ -120,6 +111,7 @@ describe('{{prev_post}} helper', function () {
|
||||
helpers.prev_post.call({}, optionsData).then(function () {
|
||||
fn.called.should.be.false;
|
||||
inverse.called.should.be.true;
|
||||
readPostStub.called.should.be.false;
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@ -128,22 +120,15 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
|
||||
describe('for unpublished post', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
utils.loadHelpers();
|
||||
sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include === 'previous') {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function (options) {
|
||||
if (options.include.indexOf('previous') === 0) {
|
||||
return Promise.resolve({posts: [{slug: '/current/', title: 'post 2', previous: {slug: '/previous/', title: 'post 1'}}]});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
|
Loading…
Reference in New Issue
Block a user