all files / keystone/lib/schemaPlugins/methods/ getRelated.js

6.15% Statements 4/65
0% Branches 0/50
0% Functions 0/9
6.56% Lines 4/61
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                                                                                                                                                                                                                          
var keystone = require('../../../');
var _ = require('lodash');
var async = require('async');
 
module.exports = function getRelated (paths, callback, nocollapse) {
 
	var item = this;
	var list = this.list;
	var queue = {};
 
	if (typeof callback !== 'function') {
		throw new Error('List.getRelated(paths, callback, nocollapse) requires a callback function.');
	}
 
	if (typeof paths === 'string') {
		var pathsArr = paths.split(' ');
		var lastPath = '';
		paths = [];
		for (var i = 0; i < pathsArr.length; i++) {
			lastPath += (lastPath.length ? ' ' : '') + pathsArr[i];
			if (lastPath.indexOf('[') < 0 || lastPath.charAt(lastPath.length - 1) === ']') {
				paths.push(lastPath);
				lastPath = '';
			}
		}
	}
 
	_.forEach(paths, function (options) {
 
		var populateString = '';
 
		if (typeof options === 'string') {
			if (options.indexOf('[') > 0) {
				populateString = options.substring(options.indexOf('[') + 1, options.indexOf(']'));
				options = options.substr(0, options.indexOf('['));
			}
			options = { path: options };
		}
		options.populate = options.populate || [];
		options.related = options.related || [];
 
		var relationship = list.relationships[options.path];
		if (!relationship) throw new Error('List.getRelated: list ' + list.key + ' does not have a relationship ' + options.path + '.');
 
		var refList = keystone.list(relationship.ref);
		if (!refList) throw new Error('List.getRelated: list ' + relationship.ref + ' does not exist.');
 
		var relField = refList.fields[relationship.refPath];
		if (!relField || relField.type !== 'relationship') throw new Error('List.getRelated: relationship ' + relationship.ref + ' on list ' + list.key + ' refers to a path (' + relationship.refPath + ') which is not a relationship field.');
 
		if (populateString.length) {
 
			_.forEach(populateString.split(' '), function (key) {
				if (refList.relationships[key]) {
					options.related.push(key);
				} else {
					options.populate.push(key);
				}
			});
 
		}
 
		queue[relationship.path] = function (done) {
 
			var query = refList.model.find().where(relField.path);
 
			if (options.populate) {
				query.populate(options.populate);
			}
 
			if (relField.many) {
				query.in([item.id]);
			} else {
				query.equals(item.id);
			}
 
			query.sort(options.sort || relationship.sort || refList.defaultSort);
 
			if (options.related.length) {
				query.exec(function (err, results) {
					if (err || !results.length) {
						return done(err, results);
					}
					async.parallel(results.map(function (item) {
						return function (done) {
							item.populateRelated(options.related, done);
						};
					}),
						function (err) {
							done(err, results);
						}
					);
				});
			} else {
				query.exec(done);
			}
 
		};
 
		if (!item._populatedRelationships) item._populatedRelationships = {};
		item._populatedRelationships[relationship.path] = true;
 
	});
 
	async.parallel(queue, function (err, results) {
		if (!nocollapse && results && paths.length === 1) {
			results = results[paths[0]];
		}
		callback(err, results);
	});
 
};