From b3ed676e53a52245ae22adcd38033658b29657ed Mon Sep 17 00:00:00 2001 From: Fabien O'Carroll Date: Tue, 5 Oct 2021 16:24:47 +0200 Subject: [PATCH] Moved redirect handling outside of repository no-issue The redirect handling is more of an application concern that can happen at the top level, rather than the lower level of the repository. --- ghost/offers/index.js | 38 ++++++++++++++++++++-- ghost/offers/lib/OfferRepository.js | 12 ++++--- ghost/offers/lib/events/OfferCodeChange.js | 27 +++++++++++++++ 3 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 ghost/offers/lib/events/OfferCodeChange.js diff --git a/ghost/offers/index.js b/ghost/offers/index.js index 0e872a785b..a953475f92 100644 --- a/ghost/offers/index.js +++ b/ghost/offers/index.js @@ -1,12 +1,44 @@ +const DomainEvents = require('@tryghost/domain-events'); +const OfferCodeChangeEvent = require('./lib/events/OfferCodeChange'); const OfferRepository = require('./lib/OfferRepository'); const OffersAPI = require('./lib/OffersAPI'); class OffersModule { /** * @param {OffersAPI} offersAPI + * @param {import('@tryghost/express-dynamic-redirects')} redirectManager */ - constructor(offersAPI) { + constructor(offersAPI, redirectManager) { this.api = offersAPI; + this.redirectManager = redirectManager; + } + + /** + * @returns {Promise} + */ + async init() { + DomainEvents.subscribe(OfferCodeChangeEvent, (event) => { + if (event.data.previousCodes) { + for (const previousCode of event.data.previousCodes) { + this.redirectManager.removeRedirect(`/${previousCode}`); + } + } + this.redirectManager.addRedirect( + `/${event.data.currentCode}`, + `/#/portal/offers/${event.data.offerId}`, + {permanent: false} + ); + }); + + const offers = await this.api.listOffers(); + + for (const offer of offers) { + this.redirectManager.addRedirect( + `/${offer.code}`, + `/#/portal/offers/${offer.id}`, + {permanent: false} + ); + } } /** @@ -18,9 +50,9 @@ class OffersModule { * @returns {OffersModule} */ static create(deps) { - const repository = new OfferRepository(deps.OfferModel, deps.stripeAPIService, deps.redirectManager); + const repository = new OfferRepository(deps.OfferModel, deps.stripeAPIService); const offersAPI = new OffersAPI(repository); - return new OffersModule(offersAPI); + return new OffersModule(offersAPI, deps.redirectManager); } } diff --git a/ghost/offers/lib/OfferRepository.js b/ghost/offers/lib/OfferRepository.js index c076e7a962..71be7be219 100644 --- a/ghost/offers/lib/OfferRepository.js +++ b/ghost/offers/lib/OfferRepository.js @@ -1,3 +1,5 @@ +const DomainEvents = require('@tryghost/domain-events'); +const OfferCodeChangeEvent = require('./events/OfferCodeChange'); const Offer = require('./Offer'); /** @@ -125,12 +127,12 @@ class OfferRepository { }); if (offer.codeChanged || offer.isNew) { - offer.oldCodes.forEach((code) => { - this.redirectManager.removeRedirect(code); - }); - this.redirectManager.addRedirect(`/${offer.code}`, `/#/portal/offers/${offer.id}`, { - permanent: false + const event = OfferCodeChangeEvent.create({ + offerId: offer.id, + previousCodes: offer.isNew ? null : offer.oldCodes, + currentCode: offer.code }); + DomainEvents.dispatch(event); } if (offer.isNew) { diff --git a/ghost/offers/lib/events/OfferCodeChange.js b/ghost/offers/lib/events/OfferCodeChange.js new file mode 100644 index 0000000000..e944926918 --- /dev/null +++ b/ghost/offers/lib/events/OfferCodeChange.js @@ -0,0 +1,27 @@ +/** + * @typedef {object} OfferCodeChangeEventData + * @prop {string} offerId + * @prop {string[]} previousCodes + * @prop {string} currentCode + */ + +class OfferCodeChangeEvent { + /** + * @param {OfferCodeChangeEventData} data + * @param {Date} timestamp + */ + constructor(data, timestamp) { + this.data = data; + this.timestamp = timestamp; + } + + /** + * @param {OfferCodeChangeEventData} data + * @param {Date} [timestamp] + */ + static create(data, timestamp) { + return new OfferCodeChangeEvent(data, timestamp || new Date); + } +} + +module.exports = OfferCodeChangeEvent;