diff --git a/core/server/api/posts.js b/core/server/api/posts.js index 1b3a535e48..6697bc4207 100644 --- a/core/server/api/posts.js +++ b/core/server/api/posts.js @@ -45,7 +45,7 @@ posts = { * Can return posts for a particular tag by passing a tag slug in * * @public - * @param {{context, page, limit, status, staticPages, tag}} options (optional) + * @param {{context, page, limit, status, staticPages, tag, featured}} options (optional) * @returns {Promise(Posts)} Posts Collection with Meta */ browse: function browse(options) { diff --git a/core/server/models/post.js b/core/server/models/post.js index c2f24e65bf..f3e10eca94 100644 --- a/core/server/models/post.js +++ b/core/server/models/post.js @@ -288,7 +288,7 @@ Post = ghostBookshelf.Model.extend({ validOptions = { findAll: ['withRelated'], findOne: ['importing', 'withRelated'], - findPage: ['page', 'limit', 'status', 'staticPages'], + findPage: ['page', 'limit', 'status', 'staticPages', 'featured'], add: ['importing'] }; @@ -385,6 +385,14 @@ Post = ghostBookshelf.Model.extend({ options.where.page = options.staticPages; } + if (options.featured) { + // convert string true/false to boolean + if (!_.isBoolean(options.featured)) { + options.featured = options.featured === 'true' || options.featured === '1' ? true : false; + } + options.where.featured = options.featured; + } + // Unless `all` is passed as an option, filter on // the status provided. if (options.status !== 'all') { diff --git a/core/test/functional/routes/api/posts_spec.js b/core/test/functional/routes/api/posts_spec.js index 497a4240f4..5ab803efbb 100644 --- a/core/test/functional/routes/api/posts_spec.js +++ b/core/test/functional/routes/api/posts_spec.js @@ -127,6 +127,28 @@ describe('Post API', function () { }); }); + it('can retrieve just featured posts', function (done) { + request.get(testUtils.API.getApiQuery('posts/?featured=true')) + .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.posts.should.exist; + testUtils.API.checkResponse(jsonResponse, 'posts'); + jsonResponse.posts.should.have.length(4); + testUtils.API.checkResponse(jsonResponse.posts[0], 'post'); + testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); + done(); + }); + }); + it('can retrieve just draft posts', function (done) { request.get(testUtils.API.getApiQuery('posts/?status=draft')) .set('Authorization', 'Bearer ' + accesstoken) diff --git a/core/test/integration/model/model_posts_spec.js b/core/test/integration/model/model_posts_spec.js index 4ab165885b..239d846e53 100644 --- a/core/test/integration/model/model_posts_spec.js +++ b/core/test/integration/model/model_posts_spec.js @@ -158,6 +158,22 @@ describe('Post Model', function () { paginationResult.meta.pagination.pages.should.equal(1); paginationResult.posts.length.should.equal(1); + // Test featured pages + return PostModel.findPage({limit: 10, featured: true}); + }).then(function (paginationResult) { + paginationResult.meta.pagination.page.should.equal(1); + paginationResult.meta.pagination.limit.should.equal(10); + paginationResult.meta.pagination.pages.should.equal(6); + paginationResult.posts.length.should.equal(10); + + // Test both boolean formats for featured pages + return PostModel.findPage({limit: 10, featured: '1'}); + }).then(function (paginationResult) { + paginationResult.meta.pagination.page.should.equal(1); + paginationResult.meta.pagination.limit.should.equal(10); + paginationResult.meta.pagination.pages.should.equal(6); + paginationResult.posts.length.should.equal(10); + return PostModel.findPage({limit: 10, page: 2, status: 'all'}); }).then(function (paginationResult) { paginationResult.meta.pagination.pages.should.equal(11);