diff --git a/ghost/core/core/frontend/helpers/foreach.js b/ghost/core/core/frontend/helpers/foreach.js index 51a1c78632..1dbabf9c25 100644 --- a/ghost/core/core/frontend/helpers/foreach.js +++ b/ghost/core/core/frontend/helpers/foreach.js @@ -31,6 +31,14 @@ module.exports = function foreach(items, options) { if (Object.values(items).length > 0 && checks.isPost(Object.values(items)[0])) { visibility = visibility || 'all'; } + } + + if (_.isArray(items) && items.length > 0 && checks.isNewsletter(items[0])) { + visibility = visibility || 'all'; + } else if (_.isObject(items) && _.isArray(Object.values(items))) { + if (Object.values(items).length > 0 && checks.isNewsletter(Object.values(items)[0])) { + visibility = visibility || 'all'; + } } // Exclude items which should not be visible in the theme items = ghostHelperUtils.visibility.filter(items, visibility); diff --git a/ghost/core/core/frontend/helpers/get.js b/ghost/core/core/frontend/helpers/get.js index 5be21279e9..e682f3bd3a 100644 --- a/ghost/core/core/frontend/helpers/get.js +++ b/ghost/core/core/frontend/helpers/get.js @@ -33,6 +33,9 @@ const RESOURCES = { }, tiers: { alias: 'tiersPublic' + }, + newsletters: { + alias: 'newslettersPublic' } }; diff --git a/ghost/core/core/frontend/services/data/checks.js b/ghost/core/core/frontend/services/data/checks.js index 4308ea1315..76b43fa5b5 100644 --- a/ghost/core/core/frontend/services/data/checks.js +++ b/ghost/core/core/frontend/services/data/checks.js @@ -3,6 +3,11 @@ function isPost(jsonData) { Object.prototype.hasOwnProperty.call(jsonData, 'title') && Object.prototype.hasOwnProperty.call(jsonData, 'slug'); } +function isNewsletter(jsonData) { + return Object.prototype.hasOwnProperty.call(jsonData, 'name') && + Object.prototype.hasOwnProperty.call(jsonData, 'subscribe_on_signup') && Object.prototype.hasOwnProperty.call(jsonData, 'visibility'); +} + function isPage(jsonData = {}) { return Object.prototype.hasOwnProperty.call(jsonData, 'show_title_and_feature_image'); } @@ -24,6 +29,7 @@ function isNav(jsonData) { module.exports = { isPost, + isNewsletter, isPage, isTag, isUser, diff --git a/ghost/core/test/unit/frontend/helpers/foreach.test.js b/ghost/core/test/unit/frontend/helpers/foreach.test.js index 9f7a199de8..2e23503948 100644 --- a/ghost/core/test/unit/frontend/helpers/foreach.test.js +++ b/ghost/core/test/unit/frontend/helpers/foreach.test.js @@ -402,6 +402,27 @@ describe('{{#foreach}} helper', function () { shouldCompileToExpected(templateString, objectHashWithVis, expected); }); + it('foreach with newsletters with members visibility', function () { + const newsletterObjectHashWithVisibility = { + newsletters: { + first: {name: 'first', visibility: 'members', subscribe_on_signup: true}, + second: {name: 'second', visibility: 'members', subscribe_on_signup: true}, + third: {name: 'third', visibility: 'paid', subscribe_on_signup: false} + } + }; + const newsletterArrayHashWithVisibility = { + newsletters: [ + {name: 'first', visibility: 'members', subscribe_on_signup: true}, + {name: 'second', visibility: 'members', subscribe_on_signup: true}, + {name: 'third', visibility: 'paid', subscribe_on_signup: false} + ] + }; + const templateString = ''; + const expected = ''; + shouldCompileToExpected(templateString, newsletterObjectHashWithVisibility, expected); + shouldCompileToExpected(templateString, newsletterArrayHashWithVisibility, expected); + }); + it('foreach with from 2', function () { const templateString = ''; const expected = ''; diff --git a/ghost/core/test/unit/frontend/helpers/get.test.js b/ghost/core/test/unit/frontend/helpers/get.test.js index 0f84b60496..1a2d2ad687 100644 --- a/ghost/core/test/unit/frontend/helpers/get.test.js +++ b/ghost/core/test/unit/frontend/helpers/get.test.js @@ -96,6 +96,35 @@ describe('{{#get}} helper', function () { }); }); + describe('newsletters', function () { + const meta = {pagination: {}}; + + beforeEach(function () { + locals = {root: {_locals: {}}}; + + sinon.stub(api, 'newslettersPublic').get(() => { + return { + browse: sinon.stub().resolves({newsletters: [], meta: meta}) + }; + }); + }); + + it('browse newsletters', function (done) { + get.call( + {}, + 'newsletters', + {hash: {}, data: locals, fn: fn, inverse: inverse} + ).then(function () { + fn.called.should.be.true(); + fn.firstCall.args[0].should.be.an.Object().with.property('newsletters'); + fn.firstCall.args[0].newsletters.should.eql([]); + inverse.called.should.be.false(); + + done(); + }).catch(done); + }); + }); + describe('general error handling', function () { it('should return an error for an unknown resource', function (done) { get.call( diff --git a/ghost/core/test/unit/frontend/services/data/checks.test.js b/ghost/core/test/unit/frontend/services/data/checks.test.js index 47b30f0df4..4d08040654 100644 --- a/ghost/core/test/unit/frontend/services/data/checks.test.js +++ b/ghost/core/test/unit/frontend/services/data/checks.test.js @@ -5,6 +5,7 @@ describe('Checks', function () { it('methods', function () { Object.keys(checks).should.eql([ 'isPost', + 'isNewsletter', 'isPage', 'isTag', 'isUser', @@ -26,6 +27,13 @@ describe('Checks', function () { checks.isPage({title: 'Test', show_title_and_feature_image: true}).should.eql(true); }); + it('isNewsletter', function () { + checks.isNewsletter({}).should.eql(false); + checks.isNewsletter({name: 'Test'}).should.eql(false); + checks.isNewsletter({name: 'Test', visibility: 'members', subscribe_on_signup: true}).should.eql(true); + checks.isNewsletter({name: 'Test', visibility: 'paid', subscribe_on_signup: false}).should.eql(true); + }); + it('isTag', function () { checks.isTag({}).should.eql(false); checks.isTag({name: 'Test'}).should.eql(false);