'use strict'; /** * Module dependencies */ // Public node modules. const _ = require('lodash'); /* * Set of utils for models */ module.exports = { /** * Find relation nature with verbose */ getNature: function (association, key, models) { const strapi = _.isUndefined(global['strapi']) && !_.isUndefined(models) ? _.set({}, 'models', models) : global['strapi']; const types = { current: '', other: '' }; if (association.hasOwnProperty('via') && association.hasOwnProperty('collection')) { const relatedAttribute = strapi.models[association.collection].attributes[association.via]; types.current = 'collection'; if (relatedAttribute.hasOwnProperty('collection')) { types.other = 'collection'; } else if (relatedAttribute.hasOwnProperty('model')) { types.other = 'model'; } } else if (association.hasOwnProperty('via') && association.hasOwnProperty('model')) { types.current = 'modelD'; // We have to find if they are a model linked to this key _.forIn(strapi.models, function (model) { _.forIn(model.attributes, function (attribute) { if (attribute.hasOwnProperty('via') && attribute.via === key && attribute.hasOwnProperty('collection')) { types.other = 'collection'; // Break loop return false; } else if (attribute.hasOwnProperty('model')) { types.other = 'model'; // Break loop return false; } }); }); } else if (association.hasOwnProperty('model')) { types.current = 'model'; // We have to find if they are a model linked to this key _.forIn(strapi.models, function (model) { _.forIn(model.attributes, function (attribute) { if (attribute.hasOwnProperty('via') && attribute.via === key) { if (attribute.hasOwnProperty('collection')) { types.other = 'collection'; // Break loop return false; } else if (attribute.hasOwnProperty('model')) { types.other = 'modelD'; // Break loop return false; } } }); }); } if (types.current === 'modelD' && types.other === 'model') { return { nature: 'oneToOne', verbose: 'belongsTo' }; } else if (types.current === 'model' && types.other === 'modelD') { return { nature: 'oneToOne', verbose: 'hasOne' }; } else if (types.current === 'model' && types.other === 'collection') { return { nature: 'oneToMany', verbose: 'belongsTo' }; } else if (types.current === 'collection' && types.other === 'model') { return { nature: 'manyToOne', verbose: 'hasMany' }; } else if (types.current === 'collection' && types.other === 'collection') { return { nature: 'manyToMany', verbose: 'belongsToMany' }; } else if (types.current === 'model' && types.other === '') { return { nature: 'oneWay', verbose: 'belongsTo' }; } return undefined; }, /** * Return ORM used for this collection. */ getORM: function (collectionIdentity) { return _.get(strapi.models, collectionIdentity.toLowerCase() + '.orm'); }, /** * Define associations key to models */ defineAssociations: function (model, definition, association, key) { // Initialize associations object definition.associations = []; // Exclude non-relational attribute if (!association.hasOwnProperty('collection') && !association.hasOwnProperty('model')) { return undefined; } // Get relation nature const infos = this.getNature(association, key); // Build associations object if (association.hasOwnProperty('collection')) { definition.associations.push({ alias: key, type: 'collection', collection: association.collection, via: association.via || undefined, nature: infos.nature, autoPopulate: _.get(association, 'autoPopulate') === true }); } else if (association.hasOwnProperty('model')) { definition.associations.push({ alias: key, type: 'model', model: association.model, via: association.via || undefined, nature: infos.nature, autoPopulate: _.get(association, 'autoPopulate') === true }); } } };