From e0b8f151717038fa111f8258354b893445a278f2 Mon Sep 17 00:00:00 2001 From: Hamish Friedlander Date: Mon, 27 Aug 2012 16:03:03 +1200 Subject: [PATCH] FIX Config wasnt filtering wildcards properly When specifying a specific before rule and a wildcard after rule (or vice versa), the config system was filtering out any fragment from the list of fragments that matched the wildcard if it matched _any_ componenet of the specific rule, not all of them. Fixed, and added handling of two semi wild-card rules, where a rule with less wildcards wins over a rule with more. See http://open.silverstripe.org/ticket/7765 for more --- _config/routes.yml | 10 ++++- core/manifest/ConfigManifest.php | 75 ++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/_config/routes.yml b/_config/routes.yml index 95273ebc4..947adfbe7 100644 --- a/_config/routes.yml +++ b/_config/routes.yml @@ -7,8 +7,10 @@ Director: '': 'Controller' --- Name: coreroutes -After: cms/routes#modelascontrollerroutes Before: '*' +After: + - framework/routes#rootroutes + - cms/routes#modelascontrollerroutes --- Director: rules: @@ -21,7 +23,11 @@ Director: 'interactive': 'SapphireREPL' --- Name: adminroutes -After: framework/routes#coreroutes +Before: '*' +After: + - framework/routes#rootroutes + - framework/routes#coreroutes + - cms/routes#modelascontrollerroutes --- Director: rules: diff --git a/core/manifest/ConfigManifest.php b/core/manifest/ConfigManifest.php index 86d0d2c60..75c35eaee 100644 --- a/core/manifest/ConfigManifest.php +++ b/core/manifest/ConfigManifest.php @@ -280,46 +280,55 @@ class SS_ConfigManifest { * @return string "after", "before" or "undefined" */ protected function relativeOrder($a, $b) { - $matchesSomeRule = array(); - + $matches = array(); + // Do the same thing for after and before - foreach (array('after'=>'before', 'before'=>'after') as $rulename => $opposite) { - $matchesSomeRule[$rulename] = false; - - // If no rule specified, we don't match it - if (isset($a[$rulename])) { - - foreach ($a[$rulename] as $rule) { - $matchesRule = true; - - foreach(array('module', 'file', 'name') as $part) { - $partMatches = true; - - // If part is *, we match _unless_ the opposite rule has a non-* matcher than also matches $b - if ($rule[$part] == '*') { - if (isset($a[$opposite])) foreach($a[$opposite] as $oppositeRule) { - if ($oppositeRule[$part] == $b[$part]) { $partMatches = false; break; } - } - } - else { - $partMatches = ($rule[$part] == $b[$part]); - } - - $matchesRule = $matchesRule && $partMatches; - if (!$matchesRule) break; + foreach (array('before', 'after') as $rulename) { + $matches[$rulename] = array(); + + // Figure out for each rule, which part matches + if (isset($a[$rulename])) foreach ($a[$rulename] as $rule) { + $match = array(); + + foreach(array('module', 'file', 'name') as $part) { + // If part is *, we match _unless_ the opposite rule has a non-* matcher than also matches $b + if ($rule[$part] == '*') { + $match[$part] = 'wild'; + } + else { + $match[$part] = ($rule[$part] == $b[$part]); } - - $matchesSomeRule[$rulename] = $matchesSomeRule[$rulename] || $matchesRule; } + + $matches[$rulename][] = $match; } } - - // Check if it matches both rules - problem if so - if ($matchesSomeRule['before'] && $matchesSomeRule['after']) { + + // Figure out the specificness of each match. 1 an actual match, 0 for a wildcard match, remove if no match + $matchlevel = array('before' => -1, 'after' => -1); + + foreach (array('before', 'after') as $rulename) { + foreach ($matches[$rulename] as $i => $rule) { + $level = 0; + + foreach ($rule as $part => $partmatches) { + if ($partmatches === false) continue 2; + if ($partmatches === true) $level += 1; + } + + if ($matchlevel[$rulename] === false || $level > $matchlevel[$rulename]) $matchlevel[$rulename] = $level; + } + } + + if ($matchlevel['before'] === -1 && $matchlevel['after'] === -1) { + return 'undefined'; + } + else if ($matchlevel['before'] === $matchlevel['after']) { user_error('Config fragment requires itself to be both before _and_ after another fragment', E_USER_ERROR); } - - return $matchesSomeRule['before'] ? 'before' : ($matchesSomeRule['after'] ? 'after' : 'undefined'); + else { + return ($matchlevel['before'] > $matchlevel['after']) ? 'before' : 'after'; + } } /**