Skip to content
This repository was archived by the owner on Sep 16, 2025. It is now read-only.

Commit 6ca8086

Browse files
feat(slugification): add compound references (#22)
* feat(sugification): add compound reference support resolves #17 * chore(ReADME): update references data type to String or Array * chore(README): add new `skipUndefinedReferences` setting
1 parent 1463e67 commit 6ca8086

File tree

5 files changed

+30
-11
lines changed

5 files changed

+30
-11
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ This will listen for any record created or updated in the article content type a
6767
| contentTypes | The Content Types to add auto slugification and search findOne by slug search utility to | Object | {} | No |
6868
| contentTypes[modelName] | The model name of the content type (it is the `singularName` in the [model schema](https://docs.strapi.io/developer-docs/latest/development/backend-customization/models.html#model-schema)) | String | N/A | Yes |
6969
| contentTypes[modelName]field | The name of the field to add the slug | String | N/A | Yes |
70-
| contentTypes[modelName]references | The name of the field that is used to build the slug | String | N/A | Yes |
70+
| contentTypes[modelName]references | The name(s) of the field(s) used to build the slug. If an array of fields is set it will result in a compound slug | String or Array | N/A | Yes |
7171
| SlugifyWithCount | Duplicate strings will have their occurrence appended to the end of the slug | Boolean | false | No |
72+
| skipUndefinedReferences | Skip reference fields that have no data. Mostly applicable to compound slug | Boolean | false | No |
7273
| slugifyOptions | The options to pass the the slugify function. All options can be found in the [slugify docs](https://github.com/sindresorhus/slugify#api) | Object | {} | No |
7374

7475
## Usage

server/config/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module.exports = {
88
contentTypes: {},
99
slugifyOptions: {},
1010
slugifyWithCount: false,
11+
skipUndefinedReferences: false,
1112
};
1213
},
1314
async validator(config) {

server/config/schema.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ const pluginConfigSchema = yup.object().shape({
1010
_.each(obj, (_value, key) => {
1111
shape[key] = yup.object().shape({
1212
field: yup.string().required(),
13-
references: yup.string().required(),
13+
references: yup.lazy((v) =>
14+
_.isArray(v) ? yup.array().of(yup.string()).required() : yup.string().required()
15+
),
1416
});
1517
});
1618
return yup.object().shape(shape);
1719
}),
1820
slugifyWithCount: yup.bool(),
21+
skipUndefinedReferences: yup.bool(),
1922
});
2023

2124
module.exports = {

server/services/settings-service.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,26 @@ module.exports = ({ strapi }) => ({
1414
build(settings) {
1515
// build models
1616
settings.models = {};
17-
_.filter(strapi.contentTypes, (contentType, uid) => {
17+
_.each(strapi.contentTypes, (contentType, uid) => {
1818
const model = settings.contentTypes[contentType.modelName];
1919
if (!model) {
2020
return;
2121
}
2222

2323
// ensure provided fields are present on the model
24-
const hasField = isValidModelField(model, model.field);
25-
const hasReference = isValidModelField(model, model.references);
26-
if (!hasField || !hasReference) {
24+
const hasField = isValidModelField(contentType, model.field);
25+
if (!hasField) {
2726
strapi.log.warn(
28-
`[slugify] skipping ${contentType.info.singularName} registration, invalid field and/or reference provided.`
27+
`[slugify] skipping ${contentType.info.singularName} registration, invalid field provided.`
28+
);
29+
return;
30+
}
31+
32+
let references = _.isArray(model.references) ? model.references : [model.references];
33+
const hasReferences = references.every((r) => isValidModelField(contentType, r));
34+
if (!hasReferences) {
35+
strapi.log.warn(
36+
`[slugify] skipping ${contentType.info.singularName} registration, invalid reference field provided.`
2937
);
3038
return;
3139
}
@@ -34,6 +42,7 @@ module.exports = ({ strapi }) => ({
3442
uid,
3543
...model,
3644
contentType,
45+
references,
3746
};
3847
settings.models[uid] = data;
3948
settings.models[contentType.modelName] = data;

server/services/slug-service.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,24 @@ module.exports = ({ strapi }) => ({
1717
}
1818

1919
const { field, references } = model;
20-
const referenceFieldValue = data[references];
2120

2221
// ensure the reference field has data
23-
if (typeof referenceFieldValue === 'undefined') {
22+
let referenceFieldValues = references
23+
.filter((r) => typeof data[r] !== 'undefined' && data[r].length)
24+
.map((r) => data[r]);
25+
26+
const hasUndefinedFields = referenceFieldValues.length < references.length;
27+
if ((!settings.skipUndefinedReferences && hasUndefinedFields) || !referenceFieldValues.length) {
2428
return;
2529
}
2630

31+
referenceFieldValues = referenceFieldValues.join(' ');
2732
if (settings.slugifyWithCount) {
28-
data[field] = toSlugWithCount(referenceFieldValue, settings.slugifyOptions);
33+
data[field] = toSlugWithCount(referenceFieldValues, settings.slugifyOptions);
2934
return;
3035
}
3136

32-
data[field] = toSlug(referenceFieldValue, settings.slugifyOptions);
37+
data[field] = toSlug(referenceFieldValues, settings.slugifyOptions);
3338
},
3439

3540
async findOne(uid, query) {

0 commit comments

Comments
 (0)