mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-24 06:35:49 +03: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
@ -43,6 +43,9 @@ ghostBookshelf.plugin(plugins.customQuery);
|
||||
// Load the Ghost filter plugin, which handles applying a 'filter' to findPage requests
|
||||
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
|
||||
ghostBookshelf.plugin(plugins.search);
|
||||
|
||||
@ -170,6 +173,11 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
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
|
||||
defaultColumnsToFetch: function defaultColumnsToFetch() {
|
||||
return [];
|
||||
@ -912,7 +920,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
}
|
||||
|
||||
if (options.order) {
|
||||
options.order = this.parseOrderOption(options.order, options.withRelated);
|
||||
options.order = itemCollection.parseOrderOption(options.order, options.withRelated);
|
||||
} else if (options.autoOrder) {
|
||||
options.orderRaw = options.autoOrder;
|
||||
} else if (this.orderDefaultRaw) {
|
||||
@ -1165,43 +1173,6 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
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.
|
||||
* Bookshelf is just too slow, too much ORM overhead.
|
||||
|
@ -1,5 +1,6 @@
|
||||
module.exports = {
|
||||
filter: require('./filter'),
|
||||
order: require('./order'),
|
||||
customQuery: require('./custom-query'),
|
||||
search: require('./search'),
|
||||
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…
Reference in New Issue
Block a user