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
This commit is contained in:
Hamish Friedlander 2012-08-27 16:03:03 +12:00
parent c7ca47f2b1
commit e0b8f15171
2 changed files with 50 additions and 35 deletions

View File

@ -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:

View File

@ -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';
}
}
/**