Filter priorities

Add the ability to specify a priority level when registering filters.
Also change doFilter to execute filters in priority order.

Closes #86
This commit is contained in:
Jacob Gable 2013-06-09 11:16:25 -05:00
parent c733a1ac62
commit 55d8ff75b4
3 changed files with 92 additions and 14 deletions

View File

@ -2,10 +2,11 @@
"use strict";
var _ = require('underscore'),
defaultCoreFilterPriority = 4,
coreFilters;
coreFilters = function (ghost) {
ghost.registerFilter('ghostNavItems', function (args) {
ghost.registerFilter('ghostNavItems', defaultCoreFilterPriority, function (args) {
var selectedItem;
// Set the nav items based on the config

View File

@ -18,8 +18,18 @@
ExampleFilter = require('../content/plugins/exampleFilters'),
Ghost,
instance,
defaults,
statuses;
// ## Default values
/**
* A hash of default values to use instead of 'magic' numbers/strings.
* @type {Object}
*/
defaults = {
filterPriority: 5,
maxPriority: 9
};
// ## Article Statuses
/**
@ -121,14 +131,20 @@
/**
* @param {string} name
* @param {integer} priority
* @param {Function} fn
*/
Ghost.prototype.registerFilter = function (name, fn) {
if (!this.filterCallbacks.hasOwnProperty(name)) {
this.filterCallbacks[name] = [];
Ghost.prototype.registerFilter = function (name, priority, fn) {
// Curry the priority optional parameter to a default of 5
if (_.isFunction(priority)) {
fn = priority;
priority = defaults.filterPriority;
}
console.log('registering filter for ', name);
this.filterCallbacks[name].push(fn);
this.filterCallbacks[name] = this.filterCallbacks[name] || {};
this.filterCallbacks[name][priority] = this.filterCallbacks[name][priority] || [];
this.filterCallbacks[name][priority].push(fn);
};
/**
@ -138,17 +154,25 @@
* @return {method} callback
*/
Ghost.prototype.doFilter = function (name, args, callback) {
var fn;
var callbacks = this.filterCallbacks[name];
if (this.filterCallbacks.hasOwnProperty(name)) {
for (fn in this.filterCallbacks[name]) {
if (this.filterCallbacks[name].hasOwnProperty(fn)) {
console.log('doing filter for ', name);
args = this.filterCallbacks[name][fn](args);
}
}
// Bug out early if no callbacks by that name
if (!callbacks) {
return callback(args);
}
_.times(defaults.maxPriority + 1, function (priority) {
// Bug out if no handlers on this priority
if (!_.isArray(callbacks[priority])) {
return;
}
// Call each handler for this priority level
_.each(callbacks[priority], function (filterHandler) {
args = filterHandler(args);
});
});
callback(args);
};
@ -180,5 +204,8 @@
};
};
// TODO: Expose the defaults for other people to see/manipulate as a static value?
// Ghost.defaults = defaults;
module.exports = Ghost;
}());

View File

@ -46,6 +46,56 @@
});
it("can register filters with specific priority", function () {
var ghost = new Ghost(),
filterName = 'test',
filterPriority = 9,
testFilterHandler = sinon.spy();
ghost.registerFilter(filterName, filterPriority, testFilterHandler);
should.exist(ghost.filterCallbacks[filterName]);
should.exist(ghost.filterCallbacks[filterName][filterPriority]);
ghost.filterCallbacks[filterName][filterPriority].should.include(testFilterHandler);
});
it("can register filters with default priority", function () {
var ghost = new Ghost(),
filterName = 'test',
defaultPriority = 5,
testFilterHandler = sinon.spy();
ghost.registerFilter(filterName, testFilterHandler);
should.exist(ghost.filterCallbacks[filterName]);
should.exist(ghost.filterCallbacks[filterName][defaultPriority]);
ghost.filterCallbacks[filterName][defaultPriority].should.include(testFilterHandler);
});
it("executes filters in priority order", function (done) {
var ghost = new Ghost(),
filterName = 'testpriority',
testFilterHandler1 = sinon.spy(),
testFilterHandler2 = sinon.spy(),
testFilterHandler3 = sinon.spy();
ghost.registerFilter(filterName, 0, testFilterHandler1);
ghost.registerFilter(filterName, 2, testFilterHandler2);
ghost.registerFilter(filterName, 9, testFilterHandler3);
ghost.doFilter(filterName, null, function () {
testFilterHandler1.calledBefore(testFilterHandler2).should.equal(true);
testFilterHandler2.calledBefore(testFilterHandler3).should.equal(true);
testFilterHandler3.called.should.equal(true);
done();
});
});
});
}());