0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Merge pull request #4772 from ekulabuhov/4262_NextPrevPostWIP

[API] Retrieve next and previous post
This commit is contained in:
Sebastian Gierlinger 2015-01-14 10:32:07 +01:00
commit 023a37b074
6 changed files with 81 additions and 9 deletions

View file

@ -8,7 +8,7 @@ var Promise = require('bluebird'),
utils = require('./utils'),
docName = 'posts',
allowedIncludes = ['created_by', 'updated_by', 'published_by', 'author', 'tags', 'fields'],
allowedIncludes = ['created_by', 'updated_by', 'published_by', 'author', 'tags', 'fields', 'next', 'previous'],
posts;
// ## Helpers

View file

@ -525,6 +525,9 @@ Post = ghostBookshelf.Model.extend({
findOne: function (data, options) {
options = options || {};
var withNext = _.contains(options.include, 'next'),
withPrev = _.contains(options.include, 'previous');
data = _.extend({
status: 'published'
}, data || {});
@ -533,10 +536,50 @@ Post = ghostBookshelf.Model.extend({
delete data.status;
}
// Add related objects
options.withRelated = _.union(options.withRelated, options.include);
// 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'));
return ghostBookshelf.Model.findOne.call(this, data, options);
return ghostBookshelf.Model.findOne.call(this, data, options).then(function (post) {
if ((withNext || withPrev) && post && !post.page) {
var postData = post.toJSON(),
publishedAt = postData.published_at,
prev,
next;
if (withNext) {
next = Post.forge().query(function (qb) {
qb.where('status', '=', 'published')
.andWhere('page', '=', 0)
.andWhere('published_at', '>', publishedAt)
.orderBy('published_at', 'asc')
.limit(1);
}).fetch();
}
if (withPrev) {
prev = Post.forge().query(function (qb) {
qb.where('status', '=', 'published')
.andWhere('page', '=', 0)
.andWhere('published_at', '<', publishedAt)
.orderBy('published_at', 'desc')
.limit(1);
}).fetch();
}
return Promise.join(next, prev)
.then(function (nextAndPrev) {
if (nextAndPrev[0]) {
post.relations.next = nextAndPrev[0];
}
if (nextAndPrev[1]) {
post.relations.previous = nextAndPrev[1];
}
return post;
});
}
return post;
});
},
/**

View file

@ -235,6 +235,32 @@ describe('Post API', function () {
});
});
it('can retrieve next and previous posts', function (done) {
request.get(testUtils.API.getApiQuery('posts/3/?include=next,previous'))
.set('Authorization', 'Bearer ' + accesstoken)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules['private'])
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
jsonResponse.should.exist;
jsonResponse.posts.should.exist;
testUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['next', 'previous']);
jsonResponse.posts[0].page.should.not.be.ok;
jsonResponse.posts[0].next.should.be.an.Object;
testUtils.API.checkResponse(jsonResponse.posts[0].next, 'post');
jsonResponse.posts[0].previous.should.be.an.Object;
testUtils.API.checkResponse(jsonResponse.posts[0].previous, 'post');
done();
});
});
it('can retrieve a static page', function (done) {
request.get(testUtils.API.getApiQuery('posts/7/'))
.set('Authorization', 'Bearer ' + accesstoken)

View file

@ -162,7 +162,7 @@ describe('Post Model', function () {
it('can findOne, returning a dated permalink', function (done) {
var firstPost = 1,
today = new Date(),
today = testUtils.DataGenerator.Content.posts[0].published_at,
dd = ('0' + today.getDate()).slice(-2),
mm = ('0' + (today.getMonth() + 1)).slice(-2),
yyyy = today.getFullYear(),

View file

@ -242,7 +242,7 @@ describe('Config', function () {
var permalinkSetting = '/:year/:month/:day/:slug/',
/*jshint unused:false*/
testData = testUtils.DataGenerator.Content.posts[2],
today = new Date(),
today = testData.published_at,
dd = ('0' + today.getDate()).slice(-2),
mm = ('0' + (today.getMonth() + 1)).slice(-2),
yyyy = today.getFullYear(),

View file

@ -9,18 +9,21 @@ DataGenerator.Content = {
{
title: "HTML Ipsum",
slug: "html-ipsum",
markdown: "<h1>HTML Ipsum Presents</h1><p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a href=\"#\">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p><h2>Header Level 2</h2><ol><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ol><blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote><h3>Header Level 3</h3><ul><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ul><pre><code>#header h1 a{display: block;width: 300px;height: 80px;}</code></pre>"
markdown: "<h1>HTML Ipsum Presents</h1><p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a href=\"#\">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p><h2>Header Level 2</h2><ol><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ol><blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote><h3>Header Level 3</h3><ul><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ul><pre><code>#header h1 a{display: block;width: 300px;height: 80px;}</code></pre>",
published_at: new Date("2015-01-01")
},
{
title: "Ghostly Kitchen Sink",
slug: "ghostly-kitchen-sink",
markdown: "<h1>HTML Ipsum Presents</h1><p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a href=\"#\">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p><h2>Header Level 2</h2><ol><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ol><blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote><h3>Header Level 3</h3><ul><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ul><pre><code>#header h1 a{display: block;width: 300px;height: 80px;}</code></pre>"
markdown: "<h1>HTML Ipsum Presents</h1><p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a href=\"#\">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p><h2>Header Level 2</h2><ol><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ol><blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote><h3>Header Level 3</h3><ul><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ul><pre><code>#header h1 a{display: block;width: 300px;height: 80px;}</code></pre>",
published_at: new Date("2015-01-02")
},
{
title: "Short and Sweet",
slug: "short-and-sweet",
markdown: "## testing\n\nmctesters\n\n- test\n- line\n- items",
html: "<h2 id=\"testing\">testing</h2>\n\n<p>mctesters</p>\n\n<ul>\n<li>test</li>\n<li>line</li>\n<li>items</li>\n</ul>"
html: "<h2 id=\"testing\">testing</h2>\n\n<p>mctesters</p>\n\n<ul>\n<li>test</li>\n<li>line</li>\n<li>items</li>\n</ul>",
published_at: new Date("2015-01-03")
},
{
title: "Not finished yet",