Skip to content
This repository
Browse code

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
  • Loading branch information...
commit e0b8f151717038fa111f8258354b893445a278f2 1 parent c7ca47f
Hamish Friedlander authored August 27, 2012
10  _config/routes.yml
@@ -7,8 +7,10 @@ Director:
7 7
     '': 'Controller'
8 8
 ---
9 9
 Name: coreroutes
10  
-After: cms/routes#modelascontrollerroutes
11 10
 Before: '*'
  11
+After:
  12
+  - framework/routes#rootroutes
  13
+  - cms/routes#modelascontrollerroutes
12 14
 ---
13 15
 Director:
14 16
   rules:
@@ -21,7 +23,11 @@ Director:
21 23
     'interactive': 'SapphireREPL'
22 24
 ---
23 25
 Name: adminroutes
24  
-After: framework/routes#coreroutes
  26
+Before: '*'
  27
+After:
  28
+  - framework/routes#rootroutes
  29
+  - framework/routes#coreroutes
  30
+  - cms/routes#modelascontrollerroutes
25 31
 ---
26 32
 Director:
27 33
   rules:
75  core/manifest/ConfigManifest.php
@@ -280,46 +280,55 @@ protected function sortYamlFragments() {
280 280
 	 * @return string "after", "before" or "undefined"
281 281
 	 */
282 282
 	protected function relativeOrder($a, $b) {
283  
-		$matchesSomeRule = array();
284  
-		
  283
+		$matches = array();
  284
+
285 285
 		// Do the same thing for after and before
286  
-		foreach (array('after'=>'before', 'before'=>'after') as $rulename => $opposite) {
287  
-			$matchesSomeRule[$rulename] = false;
288  
-			
289  
-			// If no rule specified, we don't match it
290  
-			if (isset($a[$rulename])) {
291  
-				
292  
-				foreach ($a[$rulename] as $rule) {
293  
-					$matchesRule = true;
294  
-					
295  
-					foreach(array('module', 'file', 'name') as $part) {
296  
-						$partMatches = true;
297  
-						
298  
-						// If part is *, we match _unless_ the opposite rule has a non-* matcher than also matches $b
299  
-						if ($rule[$part] == '*') {
300  
-							if (isset($a[$opposite])) foreach($a[$opposite] as $oppositeRule) {
301  
-								if ($oppositeRule[$part] == $b[$part]) { $partMatches = false; break; }
302  
-							}
303  
-						}
304  
-						else {
305  
-							$partMatches = ($rule[$part] == $b[$part]);
306  
-						}
307  
-						
308  
-						$matchesRule = $matchesRule && $partMatches;
309  
-						if (!$matchesRule) break;
  286
+		foreach (array('before', 'after') as $rulename) {
  287
+			$matches[$rulename] = array();
  288
+
  289
+			// Figure out for each rule, which part matches
  290
+			if (isset($a[$rulename])) foreach ($a[$rulename] as $rule) {
  291
+				$match = array();
  292
+
  293
+				foreach(array('module', 'file', 'name') as $part) {
  294
+					// If part is *, we match _unless_ the opposite rule has a non-* matcher than also matches $b
  295
+					if ($rule[$part] == '*') {
  296
+						$match[$part] = 'wild';
  297
+					}
  298
+					else {
  299
+						$match[$part] = ($rule[$part] == $b[$part]);
310 300
 					}
311  
-					
312  
-					$matchesSomeRule[$rulename] = $matchesSomeRule[$rulename] || $matchesRule;
313 301
 				}
  302
+
  303
+				$matches[$rulename][] = $match;
314 304
 			}
315 305
 		}
316  
-		
317  
-		// Check if it matches both rules - problem if so
318  
-		if ($matchesSomeRule['before'] && $matchesSomeRule['after']) {
  306
+
  307
+		// Figure out the specificness of each match. 1 an actual match, 0 for a wildcard match, remove if no match
  308
+		$matchlevel = array('before' => -1, 'after' => -1);
  309
+
  310
+		foreach (array('before', 'after') as $rulename) {
  311
+			foreach ($matches[$rulename] as $i => $rule) {
  312
+				$level = 0;
  313
+
  314
+				foreach ($rule as $part => $partmatches) {
  315
+					if ($partmatches === false) continue 2;
  316
+					if ($partmatches === true) $level += 1;
  317
+				}
  318
+
  319
+				if ($matchlevel[$rulename] === false || $level > $matchlevel[$rulename]) $matchlevel[$rulename] = $level;
  320
+			}
  321
+		}
  322
+
  323
+		if ($matchlevel['before'] === -1 && $matchlevel['after'] === -1) {
  324
+			return 'undefined';
  325
+		}
  326
+		else if ($matchlevel['before'] === $matchlevel['after']) {
319 327
 			user_error('Config fragment requires itself to be both before _and_ after another fragment', E_USER_ERROR);
320 328
 		}
321  
-		
322  
-		return $matchesSomeRule['before'] ? 'before' : ($matchesSomeRule['after'] ? 'after' : 'undefined');
  329
+		else {
  330
+			return ($matchlevel['before'] > $matchlevel['after']) ? 'before' : 'after';
  331
+		}
323 332
 	}
324 333
 
325 334
 	/**

0 notes on commit e0b8f15

Please sign in to comment.
Something went wrong with that request. Please try again.