diff --git a/src/js/rulesAssistant.js b/src/js/rulesAssistant.js index 648662d4f70f25a0929acfdad9705243ffc214a0..047aa8bde13a62faff9ddf2482dc9087fa91d949 100644 --- a/src/js/rulesAssistant.js +++ b/src/js/rulesAssistant.js @@ -58,23 +58,51 @@ window.lastPregRule = function(slave, rules) { }; /** - * @param {App.RA.Rule[]} rules + * @param {App.RA.RuleSetters[]} rules * @returns {App.RA.RuleSetters} */ -window.mergeRules = function (rules) { - const combinedRule = {}; - rules.forEach(rule => { - // A rule overrides any preceding ones if, - // * there are no preceding ones, - // * or it sets autoBrand, - // * or it does not set autoBrand and is not null - Object.keys(rule).forEach(key => { - const applies = (combinedRule[key] === undefined || - (key === "autoBrand" && rule[key]) || - (key !== "autoBrand" && rule[key] !== null)); - if (!applies) return; - combinedRule[key] = rule[key]; - }); +window.mergeRules = function(rules) { + if (rules.length === 0) { + return emptyDefaultRule().set; + } else if (rules.length === 1) { + return rules[0]; + } + + function isObject(o) { + return (o !== undefined && o !== null && typeof o === 'object' && !Array.isArray(o)); + } + + function deepAssign(target, source) { + for (const key in source) { + if (!source.hasOwnProperty(key)) { + continue; + } + if (isObject(source[key])) { + if (!target.hasOwnProperty(key) || target[key] === null) { + target[key] = {}; + } + deepAssign(target[key], source[key]); + } else { + // A rule overrides any preceding ones if, + // * there are no preceding ones, + // * or it sets autoBrand, + // * or it does not set autoBrand and is not null + const overrides = ( + target[key] === undefined || target[key] === null || + (key === "autoBrand" && source[key]) || + (key !== "autoBrand" && source[key] !== null)); + if (overrides) { + target[key] = source[key]; + } + } + } + } + + const combinedRule = rules[0]; + const otherRules = rules.slice(1); + + otherRules.forEach(rule => { + deepAssign(combinedRule, rule); }); return combinedRule; };