diff --git a/ghost/core/core/server/services/recommendations/RecommendationEnablerService.js b/ghost/core/core/server/services/recommendations/RecommendationEnablerService.js new file mode 100644 index 0000000000..69a6bfd488 --- /dev/null +++ b/ghost/core/core/server/services/recommendations/RecommendationEnablerService.js @@ -0,0 +1,28 @@ +module.exports = class RecommendationEnablerService { + /** @type {import('../settings/SettingsBREADService')} */ + #settingsService; + + /** + * @param {object} deps + * @param {import('../settings/SettingsBREADService')} deps.settingsService + */ + constructor(deps) { + this.#settingsService = deps.settingsService; + } + + /** + * @returns {string} + */ + getSetting() { + this.#settingsService.read('recommendations_enabled'); + } + + /** + * + * @param {string} value + * @returns Promise + */ + async setSetting(value) { + this.#settingsService.edit([{key: 'recommendations_enabled', value}], {context: {internal: true}}); + } +}; diff --git a/ghost/core/core/server/services/recommendations/RecommendationServiceWrapper.js b/ghost/core/core/server/services/recommendations/RecommendationServiceWrapper.js index f674a8a155..aacecd9215 100644 --- a/ghost/core/core/server/services/recommendations/RecommendationServiceWrapper.js +++ b/ghost/core/core/server/services/recommendations/RecommendationServiceWrapper.js @@ -23,7 +23,14 @@ class RecommendationServiceWrapper { const urlUtils = require('../../../shared/url-utils'); const models = require('../../models'); const sentry = require('../../../shared/sentry'); - const {BookshelfRecommendationRepository, RecommendationService, RecommendationController, WellknownService} = require('@tryghost/recommendations'); + const settings = require('../settings'); + const RecommendationEnablerService = require('./RecommendationEnablerService'); + const { + BookshelfRecommendationRepository, + RecommendationService, + RecommendationController, + WellknownService + } = require('@tryghost/recommendations'); const mentions = require('../mentions'); @@ -37,11 +44,15 @@ class RecommendationServiceWrapper { urlUtils }); + const settingsService = settings.getSettingsBREADServiceInstance(); + const recommendationEnablerService = new RecommendationEnablerService({settingsService}); + this.repository = new BookshelfRecommendationRepository(models.Recommendation, { sentry }); this.service = new RecommendationService({ repository: this.repository, + recommendationEnablerService, wellknownService, mentionSendingService: mentions.sendingService }); diff --git a/ghost/core/core/server/services/settings/SettingsBREADService.js b/ghost/core/core/server/services/settings/SettingsBREADService.js index 28ff6fb6f5..1ce7942908 100644 --- a/ghost/core/core/server/services/settings/SettingsBREADService.js +++ b/ghost/core/core/server/services/settings/SettingsBREADService.js @@ -147,7 +147,7 @@ class SettingsBREADService { * @param {Object[]} settings * @param {Object} options * @param {Object} [options.context] - * @param {Object} [stripeConnectData] + * @param {Object|null} [stripeConnectData] * @returns */ async edit(settings, options, stripeConnectData) { diff --git a/ghost/recommendations/src/RecommendationService.ts b/ghost/recommendations/src/RecommendationService.ts index 4614984ac3..0dfff73a1a 100644 --- a/ghost/recommendations/src/RecommendationService.ts +++ b/ghost/recommendations/src/RecommendationService.ts @@ -8,6 +8,11 @@ type MentionSendingService = { sendAll(options: {url: URL, links: URL[]}): Promise } +type RecommendationEnablerService = { + getSetting(): string, + setSetting(value: string): Promise +} + const messages = { notFound: "Recommendation with id {id} not found" } @@ -16,22 +21,40 @@ export class RecommendationService { repository: RecommendationRepository; wellknownService: WellknownService; mentionSendingService: MentionSendingService; + recommendationEnablerService: RecommendationEnablerService; - constructor(deps: {repository: RecommendationRepository, wellknownService: WellknownService, mentionSendingService: MentionSendingService}) { + constructor(deps: { + repository: RecommendationRepository, + wellknownService: WellknownService, + mentionSendingService: MentionSendingService, + recommendationEnablerService: RecommendationEnablerService, + }) { this.repository = deps.repository; this.wellknownService = deps.wellknownService; this.mentionSendingService = deps.mentionSendingService; + this.recommendationEnablerService = deps.recommendationEnablerService; } async init() { - await this.updateWellknown(); + const recommendations = await this.listRecommendations(); + await this.updateWellknown(recommendations); } - async updateWellknown() { - const recommendations = await this.listRecommendations(); + async updateWellknown(recommendations: Recommendation[]) { await this.wellknownService.set(recommendations); } + async updateRecommendationsEnabledSetting(recommendations: Recommendation[]) { + const expectedSetting = (recommendations.length > 0).toString(); + const currentSetting = this.recommendationEnablerService.getSetting(); + + if (currentSetting && currentSetting === expectedSetting) { + return; + } + + await this.recommendationEnablerService.setSetting(expectedSetting); + } + private sendMentionToRecommendation(recommendation: Recommendation) { this.mentionSendingService.sendAll({ url: this.wellknownService.getURL(), @@ -44,7 +67,10 @@ export class RecommendationService { async addRecommendation(addRecommendation: AddRecommendation) { const recommendation = Recommendation.create(addRecommendation); await this.repository.save(recommendation); - await this.updateWellknown(); + + const recommendations = await this.listRecommendations(); + await this.updateWellknown(recommendations); + await this.updateRecommendationsEnabledSetting(recommendations); // Only send an update for the mentioned URL this.sendMentionToRecommendation(recommendation); @@ -63,7 +89,9 @@ export class RecommendationService { existing.edit(recommendationEdit); await this.repository.save(existing); - await this.updateWellknown(); + const recommendations = await this.listRecommendations(); + await this.updateWellknown(recommendations); + this.sendMentionToRecommendation(existing); return existing; } @@ -78,7 +106,10 @@ export class RecommendationService { existing.delete(); await this.repository.save(existing); - await this.updateWellknown(); + + const recommendations = await this.listRecommendations(); + await this.updateWellknown(recommendations); + await this.updateRecommendationsEnabledSetting(recommendations); // Send a mention (because it was deleted, according to the webmentions spec) this.sendMentionToRecommendation(existing);