From 0d0b078513bc6f2f4aeb4a3030eef7b7e6373ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Ch=C3=A1vez?= Date: Fri, 19 Jan 2024 15:09:15 +0100 Subject: [PATCH] fix(content-releases): Send the populate entry when publish (#19262) * fix(content-releases): Send the populate entry when publish * populating entries manually * prettier aws-s3 readme * apply marks feedback --- .../src/services/__tests__/release.test.ts | 47 ++++++++++++-- .../server/src/services/release.ts | 63 +++++++++++++++---- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/packages/core/content-releases/server/src/services/__tests__/release.test.ts b/packages/core/content-releases/server/src/services/__tests__/release.test.ts index 31d15c2e9c..492435a61f 100644 --- a/packages/core/content-releases/server/src/services/__tests__/release.test.ts +++ b/packages/core/content-releases/server/src/services/__tests__/release.test.ts @@ -238,16 +238,29 @@ describe('release service', () => { const mockPublishMany = jest.fn(); const mockUnpublishMany = jest.fn(); + const servicesMock = { + 'entity-manager': { + publishMany: mockPublishMany, + unpublishMany: mockUnpublishMany, + }, + 'populate-builder': () => ({ + default: jest.fn().mockReturnThis(), + populateDeep: jest.fn().mockReturnThis(), + build: jest.fn().mockReturnThis(), + }), + }; + const strapiMock = { ...baseStrapiMock, db: { transaction: jest.fn().mockImplementation((cb) => cb()), }, plugin: jest.fn().mockReturnValue({ - service: jest.fn().mockReturnValue({ - publishMany: mockPublishMany, - unpublishMany: mockUnpublishMany, - }), + service: jest + .fn() + .mockImplementation((service: 'entity-manager' | 'populate-builder') => { + return servicesMock[service]; + }), }), entityService: { findOne: jest.fn().mockReturnValue({ @@ -265,6 +278,7 @@ describe('release service', () => { }, ], }), + findMany: jest.fn(), update: jest.fn().mockReturnValue({}), }, }; @@ -272,10 +286,31 @@ describe('release service', () => { // @ts-expect-error Ignore missing properties const releaseService = createReleaseService({ strapi: strapiMock }); + strapiMock.entityService.findMany.mockReturnValueOnce([ + { + contentType: 'contentType', + type: 'publish', + entry: { id: 1 }, + }, + ]); + strapiMock.entityService.findMany.mockReturnValueOnce([ + { + contentType: 'contentType', + type: 'unpublish', + entry: { id: 2 }, + }, + ]); + await releaseService.publish(1); - expect(mockPublishMany).toHaveBeenCalledWith([{ id: 1 }], 'contentType'); - expect(mockUnpublishMany).toHaveBeenCalledWith([{ id: 2 }], 'contentType'); + expect(mockPublishMany).toHaveBeenCalledWith( + [{ contentType: 'contentType', entry: { id: 1 }, type: 'publish' }], + 'contentType' + ); + expect(mockUnpublishMany).toHaveBeenCalledWith( + [{ contentType: 'contentType', entry: { id: 2 }, type: 'unpublish' }], + 'contentType' + ); }); }); diff --git a/packages/core/content-releases/server/src/services/release.ts b/packages/core/content-releases/server/src/services/release.ts index 3683f247ea..7750f1f40d 100644 --- a/packages/core/content-releases/server/src/services/release.ts +++ b/packages/core/content-releases/server/src/services/release.ts @@ -420,7 +420,9 @@ const createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({ populate: { actions: { populate: { - entry: true, + entry: { + fields: ['id'], + }, }, }, }, @@ -441,11 +443,12 @@ const createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({ /** * We separate publish and unpublish actions group by content type + * And we keep only their ids to fetch them later to get all information needed */ const actions: { [key: UID.ContentType]: { - publish: ReleaseAction['entry'][]; - unpublish: ReleaseAction['entry'][]; + entriestoPublishIds: ReleaseAction['entry']['id'][]; + entriesToUnpublishIds: ReleaseAction['entry']['id'][]; }; } = {}; for (const action of releaseWithPopulatedActionEntries.actions) { @@ -453,31 +456,67 @@ const createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({ if (!actions[contentTypeUid]) { actions[contentTypeUid] = { - publish: [], - unpublish: [], + entriestoPublishIds: [], + entriesToUnpublishIds: [], }; } if (action.type === 'publish') { - actions[contentTypeUid].publish.push(action.entry); + actions[contentTypeUid].entriestoPublishIds.push(action.entry.id); } else { - actions[contentTypeUid].unpublish.push(action.entry); + actions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id); } } const entityManagerService = strapi.plugin('content-manager').service('entity-manager'); + const populateBuilderService = strapi.plugin('content-manager').service('populate-builder'); // Only publish the release if all action updates are applied successfully to their entry, otherwise leave everything as is await strapi.db.transaction(async () => { for (const contentTypeUid of Object.keys(actions)) { - const { publish, unpublish } = actions[contentTypeUid as UID.ContentType]; + // @ts-expect-error - populateBuilderService should be a function but is returning service + const populate = await populateBuilderService(contentTypeUid) + .populateDeep(Infinity) + .build(); - if (publish.length > 0) { - await entityManagerService.publishMany(publish, contentTypeUid); + const { entriestoPublishIds, entriesToUnpublishIds } = + actions[contentTypeUid as UID.ContentType]; + + /** + * We need to get the populate entries to be able to publish without errors on components/relations/dynamicZones + * Considering that populate doesn't work well with morph relations we can't get the entries from the Release model + * So, we need to fetch them manually + */ + const entriesToPublish = (await strapi.entityService.findMany( + contentTypeUid as UID.ContentType, + { + filters: { + id: { + $in: entriestoPublishIds, + }, + }, + populate, + } + )) as Entity[]; + + const entriesToUnpublish = (await strapi.entityService.findMany( + contentTypeUid as UID.ContentType, + { + filters: { + id: { + $in: entriesToUnpublishIds, + }, + }, + populate, + } + )) as Entity[]; + + if (entriesToPublish.length > 0) { + await entityManagerService.publishMany(entriesToPublish, contentTypeUid); } - if (unpublish.length > 0) { - await entityManagerService.unpublishMany(unpublish, contentTypeUid); + if (entriesToUnpublish.length > 0) { + await entityManagerService.unpublishMany(entriesToUnpublish, contentTypeUid); } } });