Ghost/ghost/custom-theme-settings-service/lib/service.js
Kevin Ansfield c4f364996b Removed model dependency in custom theme settings cache
refs https://github.com/TryGhost/Team/issues/1070

- having a dependency on a model in the cache service meant that Ghost had to know about that and pre-initialize the cache during boot, even though that didn't actually do anything except create a cache instance
- by making the cache a simple key/value store able to be populated from the cache settings service when a theme is activated it means that Ghost doesn't need to perform any extra initialization when the cache is initialized via `require`
2021-09-23 09:16:59 +01:00

78 lines
3.2 KiB
JavaScript

const _ = require('lodash');
const BREAD = require('./bread');
const debug = require('@tryghost/debug')('custom-theme-settings-service');
module.exports = class CustomThemeSettingsService {
constructor({model, cache}) {
this.repository = new BREAD({model});
this.cache = cache;
}
// add/remove/edit theme setting records to match theme settings
async activateTheme(theme) {
const knownSettingsCollection = await this.repository.browse({theme: theme.name});
// convert to JSON so we can use a standard array rather than a bookshelf collection
let knownSettings = knownSettingsCollection.toJSON();
const themeSettings = theme.customSettings || {};
// exit early if there's nothing to sync for this theme
if (knownSettings.length === 0 && _.isEmpty(themeSettings)) {
return;
}
let removedIds = [];
// sync any knownSettings that have changed in the theme
for (const knownSetting of knownSettings) {
const themeSetting = themeSettings[knownSetting.key];
const hasBeenRemoved = !themeSetting;
const hasChangedType = themeSetting && themeSetting.type !== knownSetting.type;
if (hasBeenRemoved || hasChangedType) {
debug(`Removing custom theme setting '${theme.name}.${themeSetting.key}' - ${hasBeenRemoved ? 'not found in theme' : 'type changed'}`);
await this.repository.destroy({id: knownSetting.id});
removedIds.push(knownSetting.id);
return;
}
// replace value with default if it's not a valid select option
if (themeSetting.options && !themeSetting.options.includes(knownSetting.value)) {
debug(`Resetting custom theme setting value '${theme.name}.${themeSetting.key}' - "${knownSetting.value}" is not a valid option`);
await this.repository.edit({value: themeSetting.default}, {id: knownSetting.id});
}
}
// clean up any removed knownSettings now that we've finished looping over them
knownSettings = knownSettings.filter(setting => !removedIds.includes(setting.id));
// add any new settings found in theme (or re-add settings that were removed due to type change)
const knownSettingsKeys = knownSettings.map(setting => setting.key);
for (const [key, setting] of Object.entries(themeSettings)) {
if (!knownSettingsKeys.includes(key)) {
const newSettingValues = {
theme: theme.name,
key,
type: setting.type,
value: setting.default
};
debug(`Adding custom theme setting '${theme.name}.${key}'`);
await this.repository.add(newSettingValues);
}
}
// populate the cache with all key/value pairs for this theme
this.populateCacheForTheme(theme);
}
async populateCacheForTheme(theme) {
const settingsCollection = await this.repository.browse({theme: theme.themeName});
const settings = settingsCollection.toJSON();
this.cache.populate(settings);
}
};