multi-content-type-relation 2.1.2 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,28 +40,35 @@ const middleware = async (ctx, next) => {
40
40
  await next();
41
41
  if (!ctx.body) return;
42
42
  if (!ctx.body.data) return;
43
+ let hasSyncedRelations = false;
43
44
  if ([
44
45
  "collection-types.create",
45
46
  "collection-types.update",
46
47
  "single-types.createOrUpdate"
47
- ].includes(ctx?.state?.route?.handler)) {
48
+ ].includes(ctx?.state?.route?.handler) && !hasSyncedRelations) {
48
49
  const [, _, __, rest] = ctx?.request.url.split("/");
49
50
  const contentType = rest.split("?")[0];
50
51
  const isDraftAndPublish = strapi.contentTypes[contentType].options?.draftAndPublish;
51
52
  if (isDraftAndPublish) {
52
- log(`[MIDDLEWARE] ${contentType}is draft and publish`);
53
+ log(`[MIDDLEWARE] ${contentType} is draft and publish`);
53
54
  return;
54
55
  }
55
56
  const documentId = ctx.body.data.documentId;
56
- syncMctrRelation(documentId, contentType);
57
+ const locale = ctx.body.data.locale;
58
+ log(`[MIDDLEWARE] ${ctx?.state?.route?.handler} Syncing MCTR relation for ${contentType}, documentId: ${documentId}`);
59
+ syncMctrRelation(documentId, contentType, locale);
60
+ hasSyncedRelations = true;
57
61
  }
58
62
  if (["collection-types.publish", "single-types.publish"].includes(
59
63
  ctx?.state?.route?.handler
60
- )) {
64
+ ) && !hasSyncedRelations) {
61
65
  const [, _, __, rest] = ctx?.request.url.split("/");
62
66
  const contentType = rest.split("?")[0];
63
67
  const documentId = ctx.body.data.documentId;
64
- syncMctrRelation(documentId, contentType);
68
+ const locale = ctx.body.data.locale;
69
+ syncMctrRelation(documentId, contentType, locale);
70
+ log(`[MIDDLEWARE] ${ctx?.state?.route?.handler} Syncing MCTR relation for ${contentType}, documentId: ${documentId}`);
71
+ hasSyncedRelations = true;
65
72
  }
66
73
  if (!ctx?.request?.url?.startsWith("/api")) return;
67
74
  if (ctx.request.method !== "GET") return;
@@ -70,7 +77,7 @@ const middleware = async (ctx, next) => {
70
77
  const handler = ctx.state.route.handler;
71
78
  const contentTypes2 = Object.keys(strapi.contentTypes);
72
79
  log(`[MIDDLEWARE] URL: ${ctx.request.url} (${ctx.request.method})`);
73
- log(`[MIDDLEWARE] Strapi Route: ${JSON.stringify(ctx.state.route, null, 2)}`);
80
+ log(`[MIDDLEWARE] Strapi Route: ${ctx.state.route}`);
74
81
  if (typeof handler !== "string") return;
75
82
  const validHandler = contentTypes2.filter((contentType) => contentType.startsWith("api::")).some(
76
83
  (contentType) => handler.includes(`${contentType}.findOne`) || handler.includes(`${contentType}.findMany`) || handler.includes(`${contentType}.find`)
@@ -107,9 +114,9 @@ const hydrateMRCT = async (content, currentDepth, context) => {
107
114
  const field = JSON.parse(value);
108
115
  if (!Array.isArray(field)) continue;
109
116
  for (const item of field) {
110
- if (Object.keys(item).length !== 3 || !item.uid && typeof item.uid !== "string" || !item.documentId)
117
+ if (!item.uid && typeof item.uid !== "string" || !item.documentId)
111
118
  continue;
112
- const compositeID = `${item.uid}####${item.documentId}`;
119
+ const compositeID = `${item.uid}####${item.documentId}${item.locale ? `####${item.locale}` : ""}`;
113
120
  eligibleProperties.add(key);
114
121
  if (contentsToFetch.has(compositeID)) continue;
115
122
  else contentsToFetch.add(compositeID);
@@ -124,8 +131,12 @@ const hydrateMRCT = async (content, currentDepth, context) => {
124
131
  );
125
132
  const promises = [];
126
133
  for (const item of Array.from(contentsToFetch)) {
127
- const [uid, documentId] = item.split("####");
128
- const promise = strapi.documents(uid).findOne({ documentId, populate: "*", status: "published" }).then(async (response) => {
134
+ const [uid, documentId, locale] = item.split("####");
135
+ const options = { documentId, populate: "*", status: "published" };
136
+ if (locale) {
137
+ options.locale = locale;
138
+ }
139
+ const promise = strapi.documents(uid).findOne(options).then(async (response) => {
129
140
  if (!response) return { uid, response };
130
141
  if (configuration.recursive.enabled && currentDepth < configuration.recursive.maxDepth) {
131
142
  const hydratedResponse = await hydrateMRCT(
@@ -165,9 +176,16 @@ const hydrateMRCT = async (content, currentDepth, context) => {
165
176
  const hydratedArray = [];
166
177
  const unhydratedField = JSON.parse(flattenedProperties[key]);
167
178
  for (const item of unhydratedField) {
168
- const matchingContent = filteredLinkedEntries.find(
169
- (linkedEntry) => item.uid === linkedEntry.uid && item.documentId === linkedEntry.response.documentId
170
- );
179
+ let matchingContent = null;
180
+ if (item.locale) {
181
+ matchingContent = filteredLinkedEntries.find(
182
+ (linkedEntry) => item.uid === linkedEntry.uid && item.documentId === linkedEntry.response.documentId && item.locale === linkedEntry.response.locale
183
+ );
184
+ } else {
185
+ matchingContent = filteredLinkedEntries.find(
186
+ (linkedEntry) => item.uid === linkedEntry.uid && item.documentId === linkedEntry.response.documentId
187
+ );
188
+ }
171
189
  if (matchingContent) {
172
190
  hydratedArray.push({ uid: matchingContent.uid, ...matchingContent.response });
173
191
  }
@@ -180,26 +198,13 @@ const hydrateMRCT = async (content, currentDepth, context) => {
180
198
  ...newContent
181
199
  };
182
200
  };
183
- const syncMctrRelation = async (documentId, uid) => {
184
- const mctrDocuments = await strapi.documents("plugin::multi-content-type-relation.mctr-relation").findMany({
185
- filters: {
186
- sourceDocId: documentId
187
- }
188
- });
189
- if (mctrDocuments.length !== 0) {
190
- log(`[SYNC] Delete MCTR relations for ${documentId}`);
191
- await Promise.all(
192
- mctrDocuments.map(async ({ documentId: documentId2 }) => {
193
- await strapi.documents("plugin::multi-content-type-relation.mctr-relation").delete({
194
- documentId: documentId2
195
- });
196
- })
197
- );
201
+ const syncMctrRelation = async (documentId, uid, locale) => {
202
+ const configuration = getPluginConfiguration();
203
+ if (configuration.disableRevertRelations) {
204
+ log(`[SYNC] Revert relations are disabled, discarding sync`);
205
+ return;
198
206
  }
199
- log(`[SYNC] Find document ${documentId}`);
200
- const document = await strapi.documents(uid).findOne({
201
- documentId
202
- });
207
+ log(`[SYNC] Syncing MCTR relation for ${documentId}, uid: ${uid}, locale: ${locale}`);
203
208
  const contentTypeKey = Object.keys(strapi.contentTypes).find(
204
209
  (ct) => strapi.contentTypes[ct].uid === uid
205
210
  );
@@ -208,30 +213,67 @@ const syncMctrRelation = async (documentId, uid) => {
208
213
  const mctrFields = Object.keys(contentType.attributes).filter(
209
214
  (field) => contentType.attributes[field].customField === "plugin::multi-content-type-relation.multi-content-type-relation"
210
215
  );
211
- if (mctrFields.length === 0) return;
212
- const targetJSON = [];
213
- mctrFields.forEach(async (field) => {
214
- const fieldValue = document[field];
215
- if (!fieldValue) return;
216
- try {
217
- const mctrField = JSON.parse(fieldValue);
218
- mctrField.forEach((item) => {
219
- targetJSON.push(`${field}##${item.uid}##${item.documentId}`);
220
- });
221
- } catch (e) {
222
- log(`[SYNC] Error parsing field ${field} ${fieldValue}`);
216
+ if (mctrFields.length === 0) {
217
+ log(`[SYNC] No MCTR fields found for ${documentId}, discarding sync`);
218
+ return;
219
+ }
220
+ let mctrRelationDocumentId = documentId;
221
+ if (locale) {
222
+ mctrRelationDocumentId = `${documentId}####${locale}`;
223
+ }
224
+ try {
225
+ const mctrDocuments = await strapi.documents("plugin::multi-content-type-relation.mctr-relation").findMany({
226
+ filters: {
227
+ sourceDocId: mctrRelationDocumentId
228
+ }
229
+ });
230
+ log(`[SYNC] MCTR relations for ${mctrRelationDocumentId}: ${JSON.stringify(mctrDocuments, null, 2)}`);
231
+ if (mctrDocuments.length !== 0) {
232
+ log(`[SYNC] Delete MCTR relations for ${mctrRelationDocumentId}`);
233
+ await Promise.all(
234
+ mctrDocuments.map(async ({ documentId: documentId2 }) => {
235
+ await strapi.documents("plugin::multi-content-type-relation.mctr-relation").delete({
236
+ documentId: documentId2
237
+ });
238
+ })
239
+ );
223
240
  }
224
- });
225
- log(`[SYNC] Target JSON ${targetJSON}`);
226
- if (targetJSON.length === 0) return;
227
- await strapi.documents("plugin::multi-content-type-relation.mctr-relation").create({
228
- data: {
229
- sourceUID: uid,
230
- sourceDocId: documentId,
231
- target: targetJSON
241
+ log(`[SYNC] Find document ${documentId}`);
242
+ const options = {
243
+ documentId
244
+ };
245
+ if (locale) {
246
+ options.locale = locale;
232
247
  }
233
- });
234
- log(`[SYNC] MCTR relation created for ${documentId}`);
248
+ const document = await strapi.documents(uid).findOne(options);
249
+ log(`[SYNC] MCTR fields for ${documentId}: ${JSON.stringify(mctrFields, null, 2)}`);
250
+ const targetJSON = [];
251
+ mctrFields.forEach(async (field) => {
252
+ const fieldValue = document[field];
253
+ if (!fieldValue) return;
254
+ try {
255
+ const mctrField = JSON.parse(fieldValue);
256
+ mctrField.forEach((item) => {
257
+ targetJSON.push(`${field}##${item.uid}##${item.documentId}${locale ? `####${locale}` : ""}`);
258
+ });
259
+ } catch (e) {
260
+ log(`[SYNC] Error parsing field ${field} ${fieldValue}`);
261
+ }
262
+ });
263
+ log(`[SYNC] Target JSON for ${documentId}: ${JSON.stringify(targetJSON, null, 2)}`);
264
+ if (targetJSON.length === 0) return;
265
+ await strapi.documents("plugin::multi-content-type-relation.mctr-relation").create({
266
+ data: {
267
+ sourceUID: uid,
268
+ sourceDocId: mctrRelationDocumentId,
269
+ target: targetJSON
270
+ }
271
+ });
272
+ log(`[SYNC] MCTR relation created for ${documentId}`);
273
+ } catch (error) {
274
+ log(`[SYNC] Error creating MCTR relation for ${documentId}: ${error}`);
275
+ return;
276
+ }
235
277
  };
236
278
  const middlewares = {
237
279
  middleware
@@ -279,7 +321,7 @@ const schema = {
279
321
  },
280
322
  pluginOptions: {
281
323
  "content-manager": {
282
- visible: true
324
+ visible: false
283
325
  },
284
326
  "content-type-builder": {
285
327
  visible: false
@@ -361,11 +403,15 @@ const controller = ({ strapi: strapi2 }) => ({
361
403
  const body = ctx.request.body;
362
404
  const entries = body.entries;
363
405
  const promises = entries.map((entry) => {
364
- return strapi2.documents(entry.uid).findOne({
406
+ const findOneOptions = {
365
407
  documentId: entry.documentId,
366
408
  populate: "*",
367
409
  status: "published"
368
- }).then((result) => {
410
+ };
411
+ if (entry.locale) {
412
+ findOneOptions.locale = entry.locale;
413
+ }
414
+ return strapi2.documents(entry.uid).findOne(findOneOptions).then((result) => {
369
415
  return {
370
416
  uid: entry.uid,
371
417
  result
@@ -396,6 +442,7 @@ const controller = ({ strapi: strapi2 }) => ({
396
442
  let documentId = body.documentId;
397
443
  const uid = body.uid;
398
444
  const isSingleType = body.isSingleType;
445
+ const locale = body.locale;
399
446
  if (isSingleType) {
400
447
  const document = await strapi2.documents(uid).findFirst({
401
448
  populate: "*",
@@ -407,13 +454,19 @@ const controller = ({ strapi: strapi2 }) => ({
407
454
  const mctrRelations = await strapi2.documents("plugin::multi-content-type-relation.mctr-relation").findMany({
408
455
  filters: {
409
456
  target: {
410
- $containsi: `${uid}##${documentId}`
457
+ $containsi: `${uid}##${documentId}${locale ? `####${locale}` : ""}`
411
458
  }
412
459
  }
413
460
  });
414
461
  const relations = await Promise.all(
415
462
  mctrRelations.map(async (relation) => {
416
- const sourceDocumentId = relation.sourceDocId;
463
+ let sourceDocumentId = relation.sourceDocId;
464
+ let locale2 = null;
465
+ if (sourceDocumentId.includes("####")) {
466
+ const [documentId2, sourceLocale] = sourceDocumentId.split("####");
467
+ locale2 = sourceLocale;
468
+ sourceDocumentId = documentId2;
469
+ }
417
470
  const sourceUid = relation.sourceUID;
418
471
  const target = relation.target.find(
419
472
  (target2) => target2.includes(`${uid}##${documentId}`)
@@ -424,11 +477,15 @@ const controller = ({ strapi: strapi2 }) => ({
424
477
  );
425
478
  if (!contentTypeName) return null;
426
479
  const contentType = strapi2.contentTypes[contentTypeName];
427
- const document = await strapi2.documents(sourceUid).findOne({
480
+ const findOneOptions = {
428
481
  documentId: sourceDocumentId,
429
482
  populate: "*",
430
483
  status: "published"
431
- });
484
+ };
485
+ if (locale2) {
486
+ findOneOptions.locale = locale2;
487
+ }
488
+ const document = await strapi2.documents(sourceUid).findOne(findOneOptions);
432
489
  const searchableField = strapi2.plugin("multi-content-type-relation").service("service").getFirstStringFieldInContentType(contentType);
433
490
  return {
434
491
  title: document[searchableField],
@@ -441,6 +498,10 @@ const controller = ({ strapi: strapi2 }) => ({
441
498
  })
442
499
  );
443
500
  return relations.filter(Boolean);
501
+ },
502
+ getConfiguration: async function() {
503
+ const configuration = getPluginConfiguration();
504
+ return configuration;
444
505
  }
445
506
  });
446
507
  const controllers = {
@@ -480,6 +541,14 @@ const routes = [
480
541
  config: {
481
542
  policies: []
482
543
  }
544
+ },
545
+ {
546
+ method: "GET",
547
+ path: "/get-configuration",
548
+ handler: "controller.getConfiguration",
549
+ config: {
550
+ policies: []
551
+ }
483
552
  }
484
553
  ];
485
554
  const service = ({ strapi: strapi2 }) => ({
@@ -39,28 +39,35 @@ const middleware = async (ctx, next) => {
39
39
  await next();
40
40
  if (!ctx.body) return;
41
41
  if (!ctx.body.data) return;
42
+ let hasSyncedRelations = false;
42
43
  if ([
43
44
  "collection-types.create",
44
45
  "collection-types.update",
45
46
  "single-types.createOrUpdate"
46
- ].includes(ctx?.state?.route?.handler)) {
47
+ ].includes(ctx?.state?.route?.handler) && !hasSyncedRelations) {
47
48
  const [, _, __, rest] = ctx?.request.url.split("/");
48
49
  const contentType = rest.split("?")[0];
49
50
  const isDraftAndPublish = strapi.contentTypes[contentType].options?.draftAndPublish;
50
51
  if (isDraftAndPublish) {
51
- log(`[MIDDLEWARE] ${contentType}is draft and publish`);
52
+ log(`[MIDDLEWARE] ${contentType} is draft and publish`);
52
53
  return;
53
54
  }
54
55
  const documentId = ctx.body.data.documentId;
55
- syncMctrRelation(documentId, contentType);
56
+ const locale = ctx.body.data.locale;
57
+ log(`[MIDDLEWARE] ${ctx?.state?.route?.handler} Syncing MCTR relation for ${contentType}, documentId: ${documentId}`);
58
+ syncMctrRelation(documentId, contentType, locale);
59
+ hasSyncedRelations = true;
56
60
  }
57
61
  if (["collection-types.publish", "single-types.publish"].includes(
58
62
  ctx?.state?.route?.handler
59
- )) {
63
+ ) && !hasSyncedRelations) {
60
64
  const [, _, __, rest] = ctx?.request.url.split("/");
61
65
  const contentType = rest.split("?")[0];
62
66
  const documentId = ctx.body.data.documentId;
63
- syncMctrRelation(documentId, contentType);
67
+ const locale = ctx.body.data.locale;
68
+ syncMctrRelation(documentId, contentType, locale);
69
+ log(`[MIDDLEWARE] ${ctx?.state?.route?.handler} Syncing MCTR relation for ${contentType}, documentId: ${documentId}`);
70
+ hasSyncedRelations = true;
64
71
  }
65
72
  if (!ctx?.request?.url?.startsWith("/api")) return;
66
73
  if (ctx.request.method !== "GET") return;
@@ -69,7 +76,7 @@ const middleware = async (ctx, next) => {
69
76
  const handler = ctx.state.route.handler;
70
77
  const contentTypes2 = Object.keys(strapi.contentTypes);
71
78
  log(`[MIDDLEWARE] URL: ${ctx.request.url} (${ctx.request.method})`);
72
- log(`[MIDDLEWARE] Strapi Route: ${JSON.stringify(ctx.state.route, null, 2)}`);
79
+ log(`[MIDDLEWARE] Strapi Route: ${ctx.state.route}`);
73
80
  if (typeof handler !== "string") return;
74
81
  const validHandler = contentTypes2.filter((contentType) => contentType.startsWith("api::")).some(
75
82
  (contentType) => handler.includes(`${contentType}.findOne`) || handler.includes(`${contentType}.findMany`) || handler.includes(`${contentType}.find`)
@@ -106,9 +113,9 @@ const hydrateMRCT = async (content, currentDepth, context) => {
106
113
  const field = JSON.parse(value);
107
114
  if (!Array.isArray(field)) continue;
108
115
  for (const item of field) {
109
- if (Object.keys(item).length !== 3 || !item.uid && typeof item.uid !== "string" || !item.documentId)
116
+ if (!item.uid && typeof item.uid !== "string" || !item.documentId)
110
117
  continue;
111
- const compositeID = `${item.uid}####${item.documentId}`;
118
+ const compositeID = `${item.uid}####${item.documentId}${item.locale ? `####${item.locale}` : ""}`;
112
119
  eligibleProperties.add(key);
113
120
  if (contentsToFetch.has(compositeID)) continue;
114
121
  else contentsToFetch.add(compositeID);
@@ -123,8 +130,12 @@ const hydrateMRCT = async (content, currentDepth, context) => {
123
130
  );
124
131
  const promises = [];
125
132
  for (const item of Array.from(contentsToFetch)) {
126
- const [uid, documentId] = item.split("####");
127
- const promise = strapi.documents(uid).findOne({ documentId, populate: "*", status: "published" }).then(async (response) => {
133
+ const [uid, documentId, locale] = item.split("####");
134
+ const options = { documentId, populate: "*", status: "published" };
135
+ if (locale) {
136
+ options.locale = locale;
137
+ }
138
+ const promise = strapi.documents(uid).findOne(options).then(async (response) => {
128
139
  if (!response) return { uid, response };
129
140
  if (configuration.recursive.enabled && currentDepth < configuration.recursive.maxDepth) {
130
141
  const hydratedResponse = await hydrateMRCT(
@@ -164,9 +175,16 @@ const hydrateMRCT = async (content, currentDepth, context) => {
164
175
  const hydratedArray = [];
165
176
  const unhydratedField = JSON.parse(flattenedProperties[key]);
166
177
  for (const item of unhydratedField) {
167
- const matchingContent = filteredLinkedEntries.find(
168
- (linkedEntry) => item.uid === linkedEntry.uid && item.documentId === linkedEntry.response.documentId
169
- );
178
+ let matchingContent = null;
179
+ if (item.locale) {
180
+ matchingContent = filteredLinkedEntries.find(
181
+ (linkedEntry) => item.uid === linkedEntry.uid && item.documentId === linkedEntry.response.documentId && item.locale === linkedEntry.response.locale
182
+ );
183
+ } else {
184
+ matchingContent = filteredLinkedEntries.find(
185
+ (linkedEntry) => item.uid === linkedEntry.uid && item.documentId === linkedEntry.response.documentId
186
+ );
187
+ }
170
188
  if (matchingContent) {
171
189
  hydratedArray.push({ uid: matchingContent.uid, ...matchingContent.response });
172
190
  }
@@ -179,26 +197,13 @@ const hydrateMRCT = async (content, currentDepth, context) => {
179
197
  ...newContent
180
198
  };
181
199
  };
182
- const syncMctrRelation = async (documentId, uid) => {
183
- const mctrDocuments = await strapi.documents("plugin::multi-content-type-relation.mctr-relation").findMany({
184
- filters: {
185
- sourceDocId: documentId
186
- }
187
- });
188
- if (mctrDocuments.length !== 0) {
189
- log(`[SYNC] Delete MCTR relations for ${documentId}`);
190
- await Promise.all(
191
- mctrDocuments.map(async ({ documentId: documentId2 }) => {
192
- await strapi.documents("plugin::multi-content-type-relation.mctr-relation").delete({
193
- documentId: documentId2
194
- });
195
- })
196
- );
200
+ const syncMctrRelation = async (documentId, uid, locale) => {
201
+ const configuration = getPluginConfiguration();
202
+ if (configuration.disableRevertRelations) {
203
+ log(`[SYNC] Revert relations are disabled, discarding sync`);
204
+ return;
197
205
  }
198
- log(`[SYNC] Find document ${documentId}`);
199
- const document = await strapi.documents(uid).findOne({
200
- documentId
201
- });
206
+ log(`[SYNC] Syncing MCTR relation for ${documentId}, uid: ${uid}, locale: ${locale}`);
202
207
  const contentTypeKey = Object.keys(strapi.contentTypes).find(
203
208
  (ct) => strapi.contentTypes[ct].uid === uid
204
209
  );
@@ -207,30 +212,67 @@ const syncMctrRelation = async (documentId, uid) => {
207
212
  const mctrFields = Object.keys(contentType.attributes).filter(
208
213
  (field) => contentType.attributes[field].customField === "plugin::multi-content-type-relation.multi-content-type-relation"
209
214
  );
210
- if (mctrFields.length === 0) return;
211
- const targetJSON = [];
212
- mctrFields.forEach(async (field) => {
213
- const fieldValue = document[field];
214
- if (!fieldValue) return;
215
- try {
216
- const mctrField = JSON.parse(fieldValue);
217
- mctrField.forEach((item) => {
218
- targetJSON.push(`${field}##${item.uid}##${item.documentId}`);
219
- });
220
- } catch (e) {
221
- log(`[SYNC] Error parsing field ${field} ${fieldValue}`);
215
+ if (mctrFields.length === 0) {
216
+ log(`[SYNC] No MCTR fields found for ${documentId}, discarding sync`);
217
+ return;
218
+ }
219
+ let mctrRelationDocumentId = documentId;
220
+ if (locale) {
221
+ mctrRelationDocumentId = `${documentId}####${locale}`;
222
+ }
223
+ try {
224
+ const mctrDocuments = await strapi.documents("plugin::multi-content-type-relation.mctr-relation").findMany({
225
+ filters: {
226
+ sourceDocId: mctrRelationDocumentId
227
+ }
228
+ });
229
+ log(`[SYNC] MCTR relations for ${mctrRelationDocumentId}: ${JSON.stringify(mctrDocuments, null, 2)}`);
230
+ if (mctrDocuments.length !== 0) {
231
+ log(`[SYNC] Delete MCTR relations for ${mctrRelationDocumentId}`);
232
+ await Promise.all(
233
+ mctrDocuments.map(async ({ documentId: documentId2 }) => {
234
+ await strapi.documents("plugin::multi-content-type-relation.mctr-relation").delete({
235
+ documentId: documentId2
236
+ });
237
+ })
238
+ );
222
239
  }
223
- });
224
- log(`[SYNC] Target JSON ${targetJSON}`);
225
- if (targetJSON.length === 0) return;
226
- await strapi.documents("plugin::multi-content-type-relation.mctr-relation").create({
227
- data: {
228
- sourceUID: uid,
229
- sourceDocId: documentId,
230
- target: targetJSON
240
+ log(`[SYNC] Find document ${documentId}`);
241
+ const options = {
242
+ documentId
243
+ };
244
+ if (locale) {
245
+ options.locale = locale;
231
246
  }
232
- });
233
- log(`[SYNC] MCTR relation created for ${documentId}`);
247
+ const document = await strapi.documents(uid).findOne(options);
248
+ log(`[SYNC] MCTR fields for ${documentId}: ${JSON.stringify(mctrFields, null, 2)}`);
249
+ const targetJSON = [];
250
+ mctrFields.forEach(async (field) => {
251
+ const fieldValue = document[field];
252
+ if (!fieldValue) return;
253
+ try {
254
+ const mctrField = JSON.parse(fieldValue);
255
+ mctrField.forEach((item) => {
256
+ targetJSON.push(`${field}##${item.uid}##${item.documentId}${locale ? `####${locale}` : ""}`);
257
+ });
258
+ } catch (e) {
259
+ log(`[SYNC] Error parsing field ${field} ${fieldValue}`);
260
+ }
261
+ });
262
+ log(`[SYNC] Target JSON for ${documentId}: ${JSON.stringify(targetJSON, null, 2)}`);
263
+ if (targetJSON.length === 0) return;
264
+ await strapi.documents("plugin::multi-content-type-relation.mctr-relation").create({
265
+ data: {
266
+ sourceUID: uid,
267
+ sourceDocId: mctrRelationDocumentId,
268
+ target: targetJSON
269
+ }
270
+ });
271
+ log(`[SYNC] MCTR relation created for ${documentId}`);
272
+ } catch (error) {
273
+ log(`[SYNC] Error creating MCTR relation for ${documentId}: ${error}`);
274
+ return;
275
+ }
234
276
  };
235
277
  const middlewares = {
236
278
  middleware
@@ -278,7 +320,7 @@ const schema = {
278
320
  },
279
321
  pluginOptions: {
280
322
  "content-manager": {
281
- visible: true
323
+ visible: false
282
324
  },
283
325
  "content-type-builder": {
284
326
  visible: false
@@ -360,11 +402,15 @@ const controller = ({ strapi: strapi2 }) => ({
360
402
  const body = ctx.request.body;
361
403
  const entries = body.entries;
362
404
  const promises = entries.map((entry) => {
363
- return strapi2.documents(entry.uid).findOne({
405
+ const findOneOptions = {
364
406
  documentId: entry.documentId,
365
407
  populate: "*",
366
408
  status: "published"
367
- }).then((result) => {
409
+ };
410
+ if (entry.locale) {
411
+ findOneOptions.locale = entry.locale;
412
+ }
413
+ return strapi2.documents(entry.uid).findOne(findOneOptions).then((result) => {
368
414
  return {
369
415
  uid: entry.uid,
370
416
  result
@@ -395,6 +441,7 @@ const controller = ({ strapi: strapi2 }) => ({
395
441
  let documentId = body.documentId;
396
442
  const uid = body.uid;
397
443
  const isSingleType = body.isSingleType;
444
+ const locale = body.locale;
398
445
  if (isSingleType) {
399
446
  const document = await strapi2.documents(uid).findFirst({
400
447
  populate: "*",
@@ -406,13 +453,19 @@ const controller = ({ strapi: strapi2 }) => ({
406
453
  const mctrRelations = await strapi2.documents("plugin::multi-content-type-relation.mctr-relation").findMany({
407
454
  filters: {
408
455
  target: {
409
- $containsi: `${uid}##${documentId}`
456
+ $containsi: `${uid}##${documentId}${locale ? `####${locale}` : ""}`
410
457
  }
411
458
  }
412
459
  });
413
460
  const relations = await Promise.all(
414
461
  mctrRelations.map(async (relation) => {
415
- const sourceDocumentId = relation.sourceDocId;
462
+ let sourceDocumentId = relation.sourceDocId;
463
+ let locale2 = null;
464
+ if (sourceDocumentId.includes("####")) {
465
+ const [documentId2, sourceLocale] = sourceDocumentId.split("####");
466
+ locale2 = sourceLocale;
467
+ sourceDocumentId = documentId2;
468
+ }
416
469
  const sourceUid = relation.sourceUID;
417
470
  const target = relation.target.find(
418
471
  (target2) => target2.includes(`${uid}##${documentId}`)
@@ -423,11 +476,15 @@ const controller = ({ strapi: strapi2 }) => ({
423
476
  );
424
477
  if (!contentTypeName) return null;
425
478
  const contentType = strapi2.contentTypes[contentTypeName];
426
- const document = await strapi2.documents(sourceUid).findOne({
479
+ const findOneOptions = {
427
480
  documentId: sourceDocumentId,
428
481
  populate: "*",
429
482
  status: "published"
430
- });
483
+ };
484
+ if (locale2) {
485
+ findOneOptions.locale = locale2;
486
+ }
487
+ const document = await strapi2.documents(sourceUid).findOne(findOneOptions);
431
488
  const searchableField = strapi2.plugin("multi-content-type-relation").service("service").getFirstStringFieldInContentType(contentType);
432
489
  return {
433
490
  title: document[searchableField],
@@ -440,6 +497,10 @@ const controller = ({ strapi: strapi2 }) => ({
440
497
  })
441
498
  );
442
499
  return relations.filter(Boolean);
500
+ },
501
+ getConfiguration: async function() {
502
+ const configuration = getPluginConfiguration();
503
+ return configuration;
443
504
  }
444
505
  });
445
506
  const controllers = {
@@ -479,6 +540,14 @@ const routes = [
479
540
  config: {
480
541
  policies: []
481
542
  }
543
+ },
544
+ {
545
+ method: "GET",
546
+ path: "/get-configuration",
547
+ handler: "controller.getConfiguration",
548
+ config: {
549
+ policies: []
550
+ }
482
551
  }
483
552
  ];
484
553
  const service = ({ strapi: strapi2 }) => ({
@@ -23,5 +23,6 @@ declare const _default: ({ strapi }: {
23
23
  type: any;
24
24
  documentId: any;
25
25
  }[]>;
26
+ getConfiguration: () => Promise<import("../interface").Configuration>;
26
27
  };
27
28
  export default _default;
@@ -23,6 +23,7 @@ declare const _default: {
23
23
  type: any;
24
24
  documentId: any;
25
25
  }[]>;
26
+ getConfiguration: () => Promise<import("../interface").Configuration>;
26
27
  };
27
28
  };
28
29
  export default _default;
@@ -45,6 +45,7 @@ declare const _default: {
45
45
  type: any;
46
46
  documentId: any;
47
47
  }[]>;
48
+ getConfiguration: () => Promise<import("./interface").Configuration>;
48
49
  };
49
50
  };
50
51
  routes: ({
@@ -21,8 +21,10 @@ export type SelectedEntry = {
21
21
  export type FormattedStrapiEntry = {
22
22
  uid: string;
23
23
  documentId: string;
24
+ locale?: string;
24
25
  };
25
26
  export type Configuration = {
27
+ disableRevertRelations: boolean;
26
28
  recursive: {
27
29
  enabled: boolean;
28
30
  maxDepth: number;