Skip to content

Commit 2a25d47

Browse files
committed
feat: add the main middlewares
1 parent 4db2d2f commit 2a25d47

File tree

6 files changed

+456
-0
lines changed

6 files changed

+456
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { Data, Modules } from '@strapi/strapi';
2+
import { isContentTypeEnabled } from '../util/enabledContentTypes';
3+
import { getPluginService } from '../util/getPluginService';
4+
5+
const cloneMiddleware: Modules.Documents.Middleware.Middleware = async (context, next) => {
6+
const { uid, action } = context;
7+
const hasWT = isContentTypeEnabled(uid);
8+
9+
// If Webtools isn't enabled, do nothing.
10+
if (!hasWT) {
11+
return next();
12+
}
13+
14+
// Run this middleware only for the create action.
15+
if (action !== 'clone') {
16+
return next();
17+
}
18+
19+
// Fetch the URL pattern for this content type.
20+
let relations: string[] = [];
21+
let languages: string[] = [undefined];
22+
let urlAliasEntity: Data.ContentType<'plugin::webtools.url-alias'> | undefined;
23+
24+
if (strapi.plugin('i18n')) {
25+
languages = [];
26+
const locales = await strapi.entityService.findMany('plugin::i18n.locale', {});
27+
languages = locales.map((locale) => locale.code);
28+
}
29+
30+
await Promise.all(languages.map(async (lang) => {
31+
const urlPatterns = await getPluginService('url-pattern').findByUid(uid, lang);
32+
urlPatterns.forEach((urlPattern) => {
33+
const languageRelations = getPluginService('url-pattern').getRelationsFromPattern(urlPattern);
34+
// @todo check if this works
35+
relations = [...relations, ...languageRelations];
36+
});
37+
}));
38+
39+
// Create the cloned entity
40+
const newEntity = await next() as Modules.Documents.AnyDocument;
41+
42+
const fullEntity = await strapi.documents(uid as 'api::test.test').findOne({
43+
documentId: newEntity.documentId,
44+
populate: {
45+
...relations.reduce((obj, key) => ({ ...obj, [key]: {} }), {}),
46+
url_alias: {
47+
fields: ['id', 'generated'],
48+
},
49+
localizations: {
50+
populate: {
51+
url_alias: {
52+
fields: ['id'],
53+
},
54+
},
55+
},
56+
},
57+
});
58+
59+
if (!fullEntity) {
60+
throw new Error('Cloning failed, cloned entity is null or undefined');
61+
}
62+
63+
// Fetch the URL alias localizations.
64+
const urlAliasLocalizations = fullEntity.localizations
65+
?.map((loc) => loc.url_alias[0]?.documentId)
66+
?.filter((loc) => loc) || [];
67+
68+
const clonedEntityWithoutLocalizations = {
69+
...fullEntity,
70+
localizations: undefined,
71+
};
72+
73+
const combinedEntity = { ...clonedEntityWithoutLocalizations };
74+
75+
const urlPatterns = await getPluginService('url-pattern').findByUid(uid, combinedEntity.locale);
76+
await Promise.all(urlPatterns.map(async (urlPattern) => {
77+
const generatedPath = getPluginService('url-pattern').resolvePattern(uid, combinedEntity, urlPattern);
78+
// Create a new URL alias for the cloned entity
79+
urlAliasEntity = await getPluginService('url-alias').create({
80+
data: {
81+
url_path: generatedPath,
82+
generated: true,
83+
contenttype: uid,
84+
locale: combinedEntity.locale,
85+
localizations: urlAliasLocalizations,
86+
},
87+
});
88+
}));
89+
90+
// Update all the URL alias localizations.
91+
await Promise.all(urlAliasLocalizations.map(async (localization) => {
92+
await strapi.db.query('plugin::webtools.url-alias').update({
93+
where: {
94+
id: localization,
95+
},
96+
data: {
97+
localizations: [
98+
...(urlAliasLocalizations.filter((loc) => loc !== localization)),
99+
urlAliasEntity.documentId,
100+
],
101+
},
102+
});
103+
}));
104+
105+
// Update the cloned entity with the new URL alias id
106+
// Eventually update the entity to include the URL alias.
107+
const updatedEntity = await strapi.documents(uid as 'api::test.test').update({
108+
documentId: fullEntity.documentId,
109+
data: {
110+
url_alias: [urlAliasEntity.documentId],
111+
},
112+
});
113+
114+
return updatedEntity;
115+
};
116+
117+
export default cloneMiddleware;
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { Modules, Data } from '@strapi/strapi';
2+
import { isContentTypeEnabled } from '../util/enabledContentTypes';
3+
import { getPluginService } from '../util/getPluginService';
4+
5+
const createMiddleware: Modules.Documents.Middleware.Middleware = async (context, next) => {
6+
const { uid, action } = context;
7+
const hasWT = isContentTypeEnabled(uid);
8+
9+
// If Webtools isn't enabled, do nothing.
10+
if (!hasWT) {
11+
return next();
12+
}
13+
14+
// Run this middleware only for the create action.
15+
if (action !== 'create') {
16+
return next();
17+
}
18+
19+
const params = context.params as Modules.Documents.ServiceParams<'api::test.test'>['create'];
20+
21+
// Fetch the URL pattern for this content type.
22+
let relations: string[] = [];
23+
let languages: string[] = [undefined];
24+
let urlAliasEntity: Data.ContentType<'plugin::webtools.url-alias'> | undefined;
25+
26+
if (strapi.plugin('i18n')) {
27+
languages = [];
28+
const locales = await strapi.entityService.findMany('plugin::i18n.locale', {});
29+
languages = locales.map((locale) => locale.code);
30+
}
31+
32+
await Promise.all(languages.map(async (lang) => {
33+
const urlPatterns = await getPluginService('url-pattern').findByUid(uid, lang);
34+
urlPatterns.forEach((urlPattern) => {
35+
const languageRelations = getPluginService('url-pattern').getRelationsFromPattern(urlPattern);
36+
// @todo check if this works
37+
relations = [...relations, ...languageRelations];
38+
});
39+
}));
40+
41+
// If a URL alias was created, fetch it.
42+
if (params.data.url_alias?.[0]) {
43+
urlAliasEntity = await strapi.documents('plugin::webtools.url-alias').findOne({
44+
documentId: params.data.url_alias[0],
45+
});
46+
}
47+
48+
// If a URL alias was created and 'generated' is set to false, do nothing.
49+
if (urlAliasEntity?.generated === false) {
50+
return next();
51+
}
52+
53+
// Ideally here we would create the URL alias an directly fire
54+
// the `service.create.call` function with the new URL alias id.
55+
// Though it is possible that the `id` field is used in the URL.
56+
// In that case we have to create the entity first. Then when we know
57+
// the id, can we create the URL alias entity and can we update
58+
// the previously created entity.
59+
const newEntity = await next() as Modules.Documents.AnyDocument;
60+
61+
const fullEntity = await strapi.documents(uid as 'api::test.test').findOne({
62+
documentId: newEntity.documentId,
63+
populate: {
64+
localizations: {
65+
populate: {
66+
url_alias: true,
67+
},
68+
},
69+
},
70+
});
71+
72+
// Fetch the URL alias localizations.
73+
const urlAliasLocalizations = fullEntity.localizations
74+
// @todo check all url aliases, not just the first.
75+
?.map((loc) => loc.url_alias[0].documentId)
76+
?.filter((loc) => loc) || [];
77+
78+
const fullEntityWithoutLocalizations = {
79+
...fullEntity,
80+
localizations: undefined,
81+
};
82+
83+
const combinedEntity = { ...fullEntityWithoutLocalizations };
84+
const urlPatterns = await getPluginService('url-pattern').findByUid(uid, combinedEntity.locale);
85+
86+
await Promise.all(urlPatterns.map(async (urlPattern) => {
87+
const generatedPath = getPluginService('url-pattern').resolvePattern(uid, combinedEntity, urlPattern);
88+
89+
// If a URL alias was created and 'generated' is set to true, update the alias.
90+
if (urlAliasEntity?.generated === true) {
91+
urlAliasEntity = await getPluginService('url-alias').update(urlAliasEntity.documentId, {
92+
data: {
93+
url_path: generatedPath,
94+
generated: true,
95+
contenttype: uid,
96+
locale: combinedEntity.locale,
97+
localizations: urlAliasLocalizations,
98+
},
99+
});
100+
}
101+
102+
// If no URL alias was created, create one.
103+
if (!urlAliasEntity) {
104+
urlAliasEntity = await getPluginService('url-alias').create({
105+
data: {
106+
url_path: generatedPath,
107+
generated: true,
108+
contenttype: uid,
109+
locale: combinedEntity.locale,
110+
localizations: urlAliasLocalizations,
111+
},
112+
});
113+
}
114+
}));
115+
116+
// Update all the URL alias localizations.
117+
await Promise.all(urlAliasLocalizations.map(async (localization) => {
118+
await strapi.db.query('plugin::webtools.url-alias').update({
119+
where: {
120+
id: localization,
121+
},
122+
data: {
123+
localizations: [
124+
...(urlAliasLocalizations.filter((loc) => loc !== localization)),
125+
urlAliasEntity.documentId,
126+
],
127+
},
128+
});
129+
}));
130+
131+
// Eventually update the entity to include the URL alias.
132+
const updatedEntity = await strapi.documents(uid as 'api::test.test').update({
133+
documentId: fullEntity.documentId,
134+
data: {
135+
url_alias: [urlAliasEntity.documentId],
136+
},
137+
});
138+
139+
return updatedEntity;
140+
};
141+
142+
export default createMiddleware;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Modules } from '@strapi/strapi';
2+
import { isContentTypeEnabled } from '../util/enabledContentTypes';
3+
4+
const deleteMiddleware: Modules.Documents.Middleware.Middleware = async (context, next) => {
5+
const { uid, action, params } = context;
6+
const hasWT = isContentTypeEnabled(uid);
7+
8+
// If Webtools isn't enabled, do nothing.
9+
if (!hasWT) {
10+
return next();
11+
}
12+
13+
// Run this middleware only for the create action.
14+
if (action !== 'delete') {
15+
return next();
16+
}
17+
18+
// Fetch the entity because we need the url_alias id.
19+
const entity = await strapi.documents(uid as 'api::test.test').findOne({
20+
documentId: params.documentId,
21+
populate: {
22+
url_alias: {
23+
fields: ['id'],
24+
},
25+
},
26+
});
27+
28+
// If a URL alias is present, delete it.
29+
if (entity.url_alias[0]) {
30+
await Promise.all(entity.url_alias.map(async (url_alias) => {
31+
await strapi.documents('plugin::webtools.url-alias').delete({
32+
documentId: url_alias.documentId,
33+
});
34+
}));
35+
}
36+
37+
// Eventually delete the entity.
38+
return next();
39+
};
40+
41+
export default deleteMiddleware;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import cloneMiddleware from './clone';
2+
import deleteMiddleware from './delete';
3+
import creatMiddleware from './create';
4+
import updateMiddleware from './update';
5+
6+
export default {
7+
clone: cloneMiddleware,
8+
delete: deleteMiddleware,
9+
create: creatMiddleware,
10+
update: updateMiddleware,
11+
};

0 commit comments

Comments
 (0)