Added logic to update the recommendations_enabled setting on add/delete (#17975)

closes https://github.com/TryGhost/Product/issues/3799

- the recommendations_enabled setting is updated when a recommendation
is created or deleted. It's enabled as soon as there is at least one
recommendation in the database
- the recommendations_enabled setting exists to avoid fetching the
recommendation count from the database directly in themes. The setting
is cached and doesn't need a read every time from the database
This commit is contained in:
Sag 2023-09-05 20:31:48 +02:00 committed by GitHub
parent ca91b847f3
commit a08e0ed14e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 9 deletions

View File

@ -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<void>
*/
async setSetting(value) {
this.#settingsService.edit([{key: 'recommendations_enabled', value}], {context: {internal: true}});
}
};

View File

@ -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
});

View File

@ -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) {

View File

@ -8,6 +8,11 @@ type MentionSendingService = {
sendAll(options: {url: URL, links: URL[]}): Promise<void>
}
type RecommendationEnablerService = {
getSetting(): string,
setSetting(value: string): Promise<void>
}
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);