Skip to content

Commit

Permalink
feat: discard drafts when enabling draft and publish on ct (#20257)
Browse files Browse the repository at this point in the history
* feat: discard drafts when enabling draft and publish on ct

* fix: migration tests
  • Loading branch information
Marc-Roig committed May 6, 2024
1 parent cffafe7 commit 01187db
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Knex = Parameters<Migration['up']>[0];
* Versions with only a draft version will be ignored.
* Only versions with a published version (which always have a draft version) will be discarded.
*/
async function* getBatchToDiscard({
export async function* getBatchToDiscard({
db,
trx,
uid,
Expand Down
90 changes: 31 additions & 59 deletions packages/core/core/src/migrations/draft-publish.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { contentTypes as contentTypesUtils } from '@strapi/utils';
import { contentTypes as contentTypesUtils, async } from '@strapi/utils';
import { Schema } from '@strapi/types';

import { getBatchToDiscard } from './database/5.0.0-discard-drafts';

interface Input {
oldContentTypes: Record<string, Schema.ContentType>;
contentTypes: Record<string, Schema.ContentType>;
Expand All @@ -20,66 +22,36 @@ const enableDraftAndPublish = async ({ oldContentTypes, contentTypes }: Input) =
}

// run the after content types migrations

for (const uid in contentTypes) {
if (!oldContentTypes[uid]) {
continue;
}

const oldContentType = oldContentTypes[uid];
const contentType = contentTypes[uid];

// if d&p was enabled set publishedAt to eq createdAt
if (
!contentTypesUtils.hasDraftAndPublish(oldContentType) &&
contentTypesUtils.hasDraftAndPublish(contentType)
) {
const metadata = strapi.db.metadata.get(uid);

// Extract all scalar attributes to use in the insert query
const attributes = Object.values(metadata.attributes).reduce((acc, attribute: any) => {
if (['id'].includes(attribute.columnName)) {
return acc;
}

if (contentTypesUtils.isScalarAttribute(attribute)) {
acc.push(attribute.columnName);
return strapi.db.transaction(async (trx) => {
for (const uid in contentTypes) {
if (!oldContentTypes[uid]) {
continue;
}

const oldContentType = oldContentTypes[uid];
const contentType = contentTypes[uid];

// if d&p was enabled set publishedAt to eq createdAt
if (
!contentTypesUtils.hasDraftAndPublish(oldContentType) &&
contentTypesUtils.hasDraftAndPublish(contentType)
) {
const discardDraft = async (entry: { documentId: string; locale: string }) =>
strapi
.documents(uid as any)
// Discard draft by referencing the documentId and locale
.discardDraft({ documentId: entry.documentId, locale: entry.locale });

/**
* Load a batch of entries (batched to prevent loading millions of rows at once ),
* and discard them using the document service.
*/
for await (const batch of getBatchToDiscard({ db: strapi.db, trx, uid })) {
await async.map(batch, discardDraft, { concurrency: 10 });
}

return acc;
}, [] as string[]);

/**
* INSERT INTO tableName (columnName1, columnName2, columnName3, ...)
* SELECT columnName1, columnName2, columnName3, ...
* FROM tableName
*/
const qb = strapi.db?.getConnection();
await qb
// INSERT INTO tableName (columnName1, columnName2, columnName3, ...)
.into(qb.raw(`${metadata.tableName} (${attributes.join(', ')})`))
.insert((subQb: typeof qb) => {
// SELECT columnName1, columnName2, columnName3, ...
subQb
.select(
...attributes.map((att) => {
// Override 'publishedAt' and 'updatedAt' attributes
if (att === 'published_at') {
return qb.raw('NULL as published_at');
}

if (att === 'updated_at') {
return qb.raw(`? as updated_at`, [new Date()]);
}

return att;
})
)
.from(metadata.tableName)
.whereNotNull('published_at');
});
}
}
}
});
};

const disableDraftAndPublish = async ({ oldContentTypes, contentTypes }: Input) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ describe('Migration - draft and publish', () => {

// Published dog should have a publishedAt value
expect(draftDog.publishedAt).toBe(null);
// Updated at value should be different
expect(draftDog.updatedAt).not.toBe(publishedDog.updatedAt);
// Updated at value should be the same
expect(draftDog.updatedAt).toBe(publishedDog.updatedAt);
});

data.dogs = sortDogs(dogs.filter((dog) => dog.publishedAt));
Expand Down

0 comments on commit 01187db

Please sign in to comment.