mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Extracted ordering into separate bookshelf plugin
refs #11729 - Having a plugin allows to reason about ordering better and gives way to further extraction away form the core. - Just like with filtering, ordering falls into similar category of having effect on knex'es query builder object extension through additional statements - ORDER BY in this case. - Because there were bugs associated with use of permittedAttributes inside of `parseOrderOption` method, introduced separate `orderAttributes` function which returns only those fields which are orderable (https://github.com/TryGhost/Ghost/issues/11729#issuecomment-685740836)
This commit is contained in:
parent
5766b39be6
commit
84c8bcc457
3 changed files with 56 additions and 38 deletions
|
@ -43,6 +43,9 @@ ghostBookshelf.plugin(plugins.customQuery);
|
||||||
// Load the Ghost filter plugin, which handles applying a 'filter' to findPage requests
|
// Load the Ghost filter plugin, which handles applying a 'filter' to findPage requests
|
||||||
ghostBookshelf.plugin(plugins.filter);
|
ghostBookshelf.plugin(plugins.filter);
|
||||||
|
|
||||||
|
// Load the Ghost filter plugin, which handles applying a 'order' to findPage requests
|
||||||
|
ghostBookshelf.plugin(plugins.order);
|
||||||
|
|
||||||
// Load the Ghost search plugin, which handles applying a search query to findPage requests
|
// Load the Ghost search plugin, which handles applying a search query to findPage requests
|
||||||
ghostBookshelf.plugin(plugins.search);
|
ghostBookshelf.plugin(plugins.search);
|
||||||
|
|
||||||
|
@ -170,6 +173,11 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||||
return _.keys(schema.tables[this.tableName]);
|
return _.keys(schema.tables[this.tableName]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Ghost ordering handling, allows to order by permitted attributes by default and can be overriden on specific model level
|
||||||
|
orderAttributes: function orderAttributes() {
|
||||||
|
return this.permittedAttributes();
|
||||||
|
},
|
||||||
|
|
||||||
// When loading an instance, subclasses can specify default to fetch
|
// When loading an instance, subclasses can specify default to fetch
|
||||||
defaultColumnsToFetch: function defaultColumnsToFetch() {
|
defaultColumnsToFetch: function defaultColumnsToFetch() {
|
||||||
return [];
|
return [];
|
||||||
|
@ -912,7 +920,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.order) {
|
if (options.order) {
|
||||||
options.order = this.parseOrderOption(options.order, options.withRelated);
|
options.order = itemCollection.parseOrderOption(options.order, options.withRelated);
|
||||||
} else if (options.autoOrder) {
|
} else if (options.autoOrder) {
|
||||||
options.orderRaw = options.autoOrder;
|
options.orderRaw = options.autoOrder;
|
||||||
} else if (this.orderDefaultRaw) {
|
} else if (this.orderDefaultRaw) {
|
||||||
|
@ -1165,43 +1173,6 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||||
return checkIfSlugExists(slug);
|
return checkIfSlugExists(slug);
|
||||||
},
|
},
|
||||||
|
|
||||||
parseOrderOption: function (order, withRelated) {
|
|
||||||
let permittedAttributes;
|
|
||||||
let result;
|
|
||||||
let rules;
|
|
||||||
|
|
||||||
permittedAttributes = this.prototype.permittedAttributes();
|
|
||||||
if (withRelated && withRelated.indexOf('count.posts') > -1) {
|
|
||||||
permittedAttributes.push('count.posts');
|
|
||||||
}
|
|
||||||
result = {};
|
|
||||||
rules = order.split(',');
|
|
||||||
|
|
||||||
_.each(rules, function (rule) {
|
|
||||||
let match;
|
|
||||||
let field;
|
|
||||||
let direction;
|
|
||||||
|
|
||||||
match = /^([a-z0-9_.]+)\s+(asc|desc)$/i.exec(rule.trim());
|
|
||||||
|
|
||||||
// invalid order syntax
|
|
||||||
if (!match) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
field = match[1].toLowerCase();
|
|
||||||
direction = match[2].toUpperCase();
|
|
||||||
|
|
||||||
if (permittedAttributes.indexOf(field) === -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result[field] = direction;
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If you want to fetch all data fast, i recommend using this function.
|
* If you want to fetch all data fast, i recommend using this function.
|
||||||
* Bookshelf is just too slow, too much ORM overhead.
|
* Bookshelf is just too slow, too much ORM overhead.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
filter: require('./filter'),
|
filter: require('./filter'),
|
||||||
|
order: require('./order'),
|
||||||
customQuery: require('./custom-query'),
|
customQuery: require('./custom-query'),
|
||||||
search: require('./search'),
|
search: require('./search'),
|
||||||
includeCount: require('./include-count'),
|
includeCount: require('./include-count'),
|
||||||
|
|
46
core/server/models/plugins/order.js
Normal file
46
core/server/models/plugins/order.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const order = function order(Bookshelf) {
|
||||||
|
Bookshelf.Model = Bookshelf.Model.extend({
|
||||||
|
orderAttributes() {},
|
||||||
|
|
||||||
|
parseOrderOption: function (orderQueryString, withRelated) {
|
||||||
|
let orderAttributes;
|
||||||
|
let result;
|
||||||
|
let rules;
|
||||||
|
|
||||||
|
orderAttributes = this.orderAttributes();
|
||||||
|
if (withRelated && withRelated.indexOf('count.posts') > -1) {
|
||||||
|
orderAttributes.push('count.posts');
|
||||||
|
}
|
||||||
|
result = {};
|
||||||
|
rules = orderQueryString.split(',');
|
||||||
|
|
||||||
|
_.each(rules, function (rule) {
|
||||||
|
let match;
|
||||||
|
let field;
|
||||||
|
let direction;
|
||||||
|
|
||||||
|
match = /^([a-z0-9_.]+)\s+(asc|desc)$/i.exec(rule.trim());
|
||||||
|
|
||||||
|
// invalid order syntax
|
||||||
|
if (!match) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
field = match[1].toLowerCase();
|
||||||
|
direction = match[2].toUpperCase();
|
||||||
|
|
||||||
|
if (orderAttributes.indexOf(field) === -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[field] = direction;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = order;
|
Loading…
Add table
Reference in a new issue