Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix getRelatedModelsUid not always being right #86

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,119 +16,63 @@ function getRelatedModelsUid(strapi, uid) {
return [];
}

const models = strapi.contentTypes;

const { components } = strapi;
const modelObj = models[uid];
const modelAttributes = modelObj?.attributes ?? {};
/**
* @type {any[]}
*/
const relatedComponents = [];
/**
* @type {any}
*/
const relatedModels = {};

// first, look for direct relations in other contentTypes
for (const key in modelAttributes) {
if (!Object.hasOwnProperty.call(modelAttributes, key)) {
continue;
}

const attr = modelAttributes[key];

if (attr.type !== 'relation') continue;
if (!attr.target) continue;

relatedModels[attr.target] = models[attr.target];
}

// second, look for relations to current model in components
for (const compKey in components) {
if (!Object.hasOwnProperty.call(components, compKey)) {
continue;
}

const compObj = components[compKey];
const attributes = compObj?.attributes ?? {};

for (const key in attributes) {
if (!Object.hasOwnProperty.call(attributes, key)) {
let contentTypeList = [uid];
let componentList = [];
while (true) {
const componentListLenght = componentList.length;
for (const component of Object.values(strapi.components)) {
if (componentList.includes(component.uid)) {
continue;
}

const attr = attributes[key];

if (attr.type !== 'relation') continue;
if (!attr.target) continue;

if (attr.target === uid) {
relatedComponents.push(compKey);
for (const attribute of Object.values(component.attributes)) {
if (attribute.type === 'relation') {
if (
contentTypeList.includes(attribute.target) &&
!componentList.includes(component.uid)
) {
componentList.push(component.uid);
}
} else if (attribute.type === 'component') {
if (
componentList.includes(attribute.component) &&
!componentList.includes(component.uid)
) {
componentList.push(component.uid);
}
}
}
}
}

// third, look for nested components with relations to current model
for (const compKey in components) {
if (!Object.hasOwnProperty.call(components, compKey)) {
continue;
}
const compObj = components[compKey];
const attributes = compObj?.attributes ?? {};

// check if current component contains another component that contains a relation to the current model
// look one level deeper
for (const key in attributes) {
if (!Object.hasOwnProperty.call(attributes, key)) {
const contentTypeListLenght = contentTypeList.length;
for (const contentType of Object.values(strapi.contentTypes)) {
if (contentTypeList.includes(contentType.uid)) {
continue;
}

const attr = attributes[key];

if (attr.type !== 'component') continue;
if (!attr.component) continue;
if (!relatedComponents.includes(attr.component)) continue;
if (relatedComponents.includes(compKey)) continue;

relatedComponents.push(compKey);
}
}

// finally locate all the models that have the related components in their models
for (const modelKey in models) {
if (!Object.hasOwnProperty.call(models, modelKey)) {
continue;
}

const otherModelObj = models[modelKey];
const attributes = otherModelObj?.attributes ?? {};

for (const key in attributes) {
if (!Object.hasOwnProperty.call(attributes, key)) {
continue;
for (const attribute of Object.values(contentType.attributes)) {
if (attribute.type === 'relation') {
if (
contentTypeList.includes(attribute.target) &&
!contentTypeList.includes(contentType.uid)
) {
contentTypeList.push(contentType.uid);
}
} else if (attribute.type === 'component') {
if (
componentList.includes(attribute.component) &&
!contentTypeList.includes(contentType.uid)
) {
contentTypeList.push(contentType.uid);
}
}
}
const attr = attributes[key];

if (attr.type !== 'component') continue;
if (!attr.component) continue;
if (!relatedComponents.includes(attr.component)) continue;
if (relatedModels[modelKey]) continue;

relatedModels[modelKey] = models[modelKey];
}
}

const relatedModelUid = [];

Object.values(relatedModels).reduce((acc, model) => {
if (model.uid) {
acc.push(model.uid);
if (
contentTypeListLenght === contentTypeList.length &&
componentListLenght === componentList.length
) {
return contentTypeList;
}
return acc;
}, relatedModelUid);

return relatedModelUid;
}
}

module.exports = { getRelatedModelsUid };
Loading