🐛 Provided get helper filters access to globals

closes #10448

- using @site.lang to read posts is a valid use case for the get helper filters
- get helper filters have special treatment of anything wrapped in {{}}, in the form of resolvePaths
- resolvePaths uses some custom logic + jsonpath to find the right bit of data to inject
- this function had no handling for globals starting with `@`, and also didn't have access to them
This commit is contained in:
Hannah Wolfe 2019-02-04 15:19:00 +00:00
parent 9d8a450ede
commit 5365094dfc
2 changed files with 26 additions and 7 deletions

View File

@ -74,7 +74,7 @@ function isBrowse(options) {
* @param {String} value
* @returns {String}
*/
function resolvePaths(data, value) {
function resolvePaths(globals, data, value) {
var regex = /\{\{(.*?)\}\}/g;
value = value.replace(regex, function (match, path) {
@ -85,8 +85,12 @@ function resolvePaths(data, value) {
// Handle Handlebars .[] style arrays
path = path.replace(/\.\[/g, '[');
// Do the query, which always returns an array of matches
result = jsonpath.query(data, path);
if (path.charAt(0) === '@') {
result = jsonpath.query(globals, path.substr(1));
} else {
// Do the query, which always returns an array of matches
result = jsonpath.query(data, path);
}
// Handle the case where the single data property we return is a Date
// Data.toString() is not DB compatible, so use `toISOString()` instead
@ -109,9 +113,9 @@ function resolvePaths(data, value) {
* @param {Object} options
* @returns {*}
*/
function parseOptions(data, options) {
function parseOptions(globals, data, options) {
if (_.isString(options.filter)) {
options.filter = resolvePaths(data, options.filter);
options.filter = resolvePaths(globals, data, options.filter);
}
return options;
@ -130,6 +134,7 @@ get = function get(resource, options) {
const self = this;
const data = createFrame(options.data);
const ghostGlobals = _.omit(data, ['_parent', 'root']);
const apiVersion = _.get(data, 'root._locals.apiVersion');
let apiOptions = options.hash;
@ -156,7 +161,7 @@ get = function get(resource, options) {
}
// Parse the options we're going to pass to the API
apiOptions = parseOptions(this, apiOptions);
apiOptions = parseOptions(ghostGlobals, this, apiOptions);
return api[apiVersion][controller][action](apiOptions).then(function success(result) {
var blockParams;

View File

@ -22,7 +22,7 @@ describe('{{#get}} helper', function () {
inverse = sinon.spy();
labsStub = sinon.stub(labs, 'isSet').returns(true);
locals = {root: {_locals: {apiVersion: 'v0.1'}}};
locals = {root: {_locals: {apiVersion: 'v0.1'}}, globalProp: {foo: 'bar'}};
});
afterEach(function () {
@ -512,5 +512,19 @@ describe('{{#get}} helper', function () {
done();
}).catch(done);
});
it('should resolve global props', function (done) {
helpers.get.call(
resource,
'posts',
{hash: {filter: 'slug:{{@globalProp.foo}}'}, data: locals, fn: fn, inverse: inverse}
).then(function () {
browseStub.firstCall.args.should.be.an.Array().with.lengthOf(1);
browseStub.firstCall.args[0].should.be.an.Object().with.property('filter');
browseStub.firstCall.args[0].filter.should.eql('slug:bar');
done();
}).catch(done);
});
});
});