Merge pull request #16020 from strapi/review-workflow/refactor-raw-query

This commit is contained in:
Jamie Howard 2023-03-09 09:37:06 +00:00 committed by GitHub
commit f8a9174dd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 120 additions and 15 deletions

View File

@ -106,21 +106,45 @@ function enableReviewWorkflow({ strapi }) {
const { joinTable } = strapi.db.metadata.get(target).attributes[morphBy];
const { idColumn, typeColumn } = joinTable.morphColumn;
// Execute a raw SQL query to insert records into the join table mapping the specified content type with the first stage of the default workflow.
const connection = strapi.db.getConnection();
// Execute an SQL query to insert records into the join table mapping the specified content type with the first stage of the default workflow.
// Only entities that do not have a record in the join table yet are selected.
await strapi.db.connection
.raw(`INSERT INTO ${joinTable.name} (${idColumn.name}, field, "order", ${joinTable.joinColumn.name}, ${typeColumn.name})
SELECT
entity.id as ${idColumn.name},
'${ENTITY_STAGE_ATTRIBUTE}' as field,
1 as "order",
${firstStage.id} as ${joinTable.joinColumn.name},
'${contentTypeUID}' as ${typeColumn.name}
FROM ${contentTypeMetadata.tableName} entity
LEFT JOIN ${joinTable.name} jointable
ON entity.id = jointable.${idColumn.name}
AND jointable.${typeColumn.name} = '${contentTypeUID}'
WHERE jointable.${idColumn.name} IS NULL`);
const selectStatement = connection
.select({
[idColumn.name]: 'entity.id',
field: connection.raw('?', [ENTITY_STAGE_ATTRIBUTE]),
order: 1,
[joinTable.joinColumn.name]: firstStage.id,
[typeColumn.name]: connection.raw('?', [contentTypeUID]),
})
.leftJoin(`${joinTable.name} AS jointable`, function () {
this.on('entity.id', '=', `jointable.${idColumn.name}`).andOn(
`jointable.${typeColumn.name}`,
'=',
connection.raw('?', [contentTypeUID])
);
})
.where(`jointable.${idColumn.name}`, null)
.from(`${contentTypeMetadata.tableName} AS entity`)
.toSQL();
const columnsToInsert = [
idColumn.name,
'field',
connection.raw('??', ['order']),
joinTable.joinColumn.name,
typeColumn.name,
];
// Insert rows for all entries of the content type that do not have a
// default stage
await connection(joinTable.name).insert(
connection.raw(
`(${columnsToInsert.join(',')}) ${selectStatement.sql}`,
selectStatement.bindings
)
);
};
return pipe([

View File

@ -2,12 +2,31 @@
const { createStrapiInstance } = require('../../../../../../test/helpers/strapi');
const { createAuthRequest, createRequest } = require('../../../../../../test/helpers/request');
const { createTestBuilder } = require('../../../../../../test/helpers/builder');
const { describeOnCondition } = require('../utils/test');
const { STAGE_MODEL_UID, WORKFLOW_MODEL_UID } = require('../constants/workflows');
const edition = process.env.STRAPI_DISABLE_EE === 'true' ? 'CE' : 'EE';
const productUID = 'api::product.product';
const model = {
draftAndPublish: true,
pluginOptions: {},
singularName: 'product',
pluralName: 'products',
displayName: 'Product',
kind: 'collectionType',
attributes: {
name: {
type: 'string',
},
},
};
describeOnCondition(edition === 'EE')('Review workflows', () => {
const builder = createTestBuilder();
const requests = {
public: null,
admin: null,
@ -18,11 +37,37 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
let secondStage;
let testWorkflow;
beforeAll(async () => {
const createEntry = async (uid, data) => {
const { body } = await requests.admin({
method: 'POST',
url: `/content-manager/collection-types/${uid}`,
body: data,
});
return body;
};
const updateContentType = async (uid, data) => {
const result = await requests.admin({
method: 'PUT',
url: `/content-type-builder/content-types/${uid}`,
body: data,
});
expect(result.statusCode).toBe(201);
};
const restart = async () => {
await strapi.destroy();
strapi = await createStrapiInstance();
requests.admin = await createAuthRequest({ strapi });
};
beforeAll(async () => {
await builder.addContentTypes([model]).build();
// eslint-disable-next-line node/no-extraneous-require
hasRW = require('@strapi/strapi/lib/utils/ee').features.isEnabled('review-workflows');
strapi = await createStrapiInstance();
requests.public = createRequest({ strapi });
requests.admin = await createAuthRequest({ strapi });
@ -42,6 +87,7 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
afterAll(async () => {
await strapi.destroy();
await builder.cleanup();
});
describe('Get workflows', () => {
@ -269,4 +315,39 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
}
});
});
describe('Enable review workflows on a content type', () => {
test('when enabled on a content type, entries of this type should be added to the first stage of the workflow', async () => {
await createEntry(productUID, { name: 'Product' });
await createEntry(productUID, { name: 'Product 1' });
await createEntry(productUID, { name: 'Product 2' });
await updateContentType(productUID, {
components: [],
contentType: { ...model, reviewWorkflows: true },
});
await restart();
const res = await requests.admin({
method: 'GET',
url: `/content-type-builder/content-types/api::product.product`,
});
expect(res.body.data.schema.reviewWorkflows).toBeTruthy();
const connection = strapi.db.getConnection();
const RWMorphTableResults = await connection
.select('*')
.from('strapi_workflows_stages_related_morphs')
.where('related_type', productUID);
expect(RWMorphTableResults.length).toEqual(3);
for (let i = 0; i < RWMorphTableResults.length; i += 1) {
const entry = RWMorphTableResults[i];
expect(entry.related_id).toEqual(i + 1);
expect(entry.order).toEqual(1);
}
});
});
});