From 5365094dfc69fb5d7b1f3a0f9b32c5a81262e40f Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Mon, 4 Feb 2019 15:19:00 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Provided=20get=20helper=20filter?= =?UTF-8?q?s=20access=20to=20globals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- core/server/helpers/get.js | 17 +++++++++++------ core/test/unit/helpers/get_spec.js | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/core/server/helpers/get.js b/core/server/helpers/get.js index 45d7c6a2f2..1e8354bbdf 100644 --- a/core/server/helpers/get.js +++ b/core/server/helpers/get.js @@ -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; diff --git a/core/test/unit/helpers/get_spec.js b/core/test/unit/helpers/get_spec.js index c3f7ce827a..2e1b9638a1 100644 --- a/core/test/unit/helpers/get_spec.js +++ b/core/test/unit/helpers/get_spec.js @@ -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); + }); }); });