From d4c8b69673a68bf1481e91f749abaaa34e204898 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Fri, 20 Nov 2015 21:20:00 +0000 Subject: [PATCH] Support ordering by count refs #6009 - super quick and dirty way to support ordering by counts - @TODO refactor :) --- core/server/models/base/index.js | 7 +- core/server/models/plugins/pagination.js | 6 +- .../integration/api/advanced_browse_spec.js | 98 +++++++++++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/core/server/models/base/index.js b/core/server/models/base/index.js index 9764d48f35..ced2303292 100644 --- a/core/server/models/base/index.js +++ b/core/server/models/base/index.js @@ -304,7 +304,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({ } if (options.order) { - options.order = self.parseOrderOption(options.order); + options.order = self.parseOrderOption(options.order, options.include); } else { options.order = self.orderDefaultOptions(); } @@ -463,10 +463,13 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({ }); }, - parseOrderOption: function (order) { + parseOrderOption: function (order, include) { var permittedAttributes, result, rules; permittedAttributes = this.prototype.permittedAttributes(); + if (include && include.indexOf('count.posts') > -1) { + permittedAttributes.push('count.posts'); + } result = {}; rules = order.split(','); diff --git a/core/server/models/plugins/pagination.js b/core/server/models/plugins/pagination.js index a5aee72168..012f048adb 100644 --- a/core/server/models/plugins/pagination.js +++ b/core/server/models/plugins/pagination.js @@ -162,7 +162,11 @@ pagination = function pagination(bookshelf) { // Apply ordering options if they are present if (options.order && !_.isEmpty(options.order)) { _.forOwn(options.order, function (direction, property) { - self.query('orderBy', tableName + '.' + property, direction); + if (property === 'count.posts') { + self.query('orderBy', 'count__posts', direction); + } else { + self.query('orderBy', tableName + '.' + property, direction); + } }); } diff --git a/core/test/integration/api/advanced_browse_spec.js b/core/test/integration/api/advanced_browse_spec.js index 74985ea390..6b6a24fc2e 100644 --- a/core/test/integration/api/advanced_browse_spec.js +++ b/core/test/integration/api/advanced_browse_spec.js @@ -369,6 +369,61 @@ describe('Filter Param Spec', function () { }).catch(done); }); + it('can fetch and order by `count.posts` for tags (public data only)', function (done) { + TagAPI.browse({include: 'count.posts', order: 'count.posts DESC'}).then(function (result) { + var ids; + + // 1. Result should have the correct base structure + should.exist(result); + result.should.have.property('tags'); + result.should.have.property('meta'); + + // 2. The data part of the response should be correct + // We should have 5 matching items + result.tags.should.be.an.Array.with.lengthOf(6); + + // Each tag should have the correct count + _.find(result.tags, function (tag) { + return tag.name === 'Getting Started'; + }).count.posts.should.eql(4); + + _.find(result.tags, function (tag) { + return tag.name === 'photo'; + }).count.posts.should.eql(4); + + _.find(result.tags, function (tag) { + return tag.name === 'Video'; + }).count.posts.should.eql(5); + + _.find(result.tags, function (tag) { + return tag.name === 'Audio'; + }).count.posts.should.eql(6); + + _.find(result.tags, function (tag) { + return tag.name === 'No Posts'; + }).count.posts.should.eql(0); + + _.find(result.tags, function (tag) { + return tag.name === 'Special'; + }).count.posts.should.eql(3); + + ids = _.pluck(result.tags, 'id'); + ids.should.eql([4, 3, 1, 2, 6, 5]); + + // 3. The meta object should contain the right details + result.meta.should.have.property('pagination'); + result.meta.pagination.should.be.an.Object.with.properties(['page', 'limit', 'pages', 'total', 'next', 'prev']); + result.meta.pagination.page.should.eql(1); + result.meta.pagination.limit.should.eql(15); + result.meta.pagination.pages.should.eql(1); + result.meta.pagination.total.should.eql(6); + should.equal(result.meta.pagination.next, null); + should.equal(result.meta.pagination.prev, null); + + done(); + }).catch(done); + }); + it.skip('can fetch `count.posts` for tags (all data)', function (done) { // This is tested elsewhere for now using user context // No way to override it for public requests @@ -413,6 +468,49 @@ describe('Filter Param Spec', function () { }).catch(done); }); + it('can fetch and order by `count.posts` for users (published only)', function (done) { + UserAPI.browse({include: 'count.posts', order: 'count.posts ASC'}).then(function (result) { + var ids; + + // 1. Result should have the correct base structure + should.exist(result); + result.should.have.property('users'); + result.should.have.property('meta'); + + // 2. The data part of the response should be correct + // We should have 5 matching items + result.users.should.be.an.Array.with.lengthOf(3); + + // Each user should have the correct count + _.find(result.users, function (user) { + return user.slug === 'leslie'; + }).count.posts.should.eql(15); + + _.find(result.users, function (user) { + return user.slug === 'pat-smith'; + }).count.posts.should.eql(3); + + _.find(result.users, function (user) { + return user.slug === 'camhowe'; + }).count.posts.should.eql(0); + + ids = _.pluck(result.users, 'id'); + ids.should.eql([3, 2, 1]); + + // 3. The meta object should contain the right details + result.meta.should.have.property('pagination'); + result.meta.pagination.should.be.an.Object.with.properties(['page', 'limit', 'pages', 'total', 'next', 'prev']); + result.meta.pagination.page.should.eql(1); + result.meta.pagination.limit.should.eql(15); + result.meta.pagination.pages.should.eql(1); + result.meta.pagination.total.should.eql(3); + should.equal(result.meta.pagination.next, null); + should.equal(result.meta.pagination.prev, null); + + done(); + }).catch(done); + }); + it.skip('can fetch `posts.all.count` for users (all posts)', function (done) { done(); });