Example #1
0
 /**
  * Attempt to match a url array.  If the url matches the route parameters and settings, then
  * return a generated string url.  If the url doesn't match the route parameters, false will be returned.
  * This method handles the reverse routing or conversion of url arrays into string urls.
  *
  * @param array $url An array of parameters to check matching with.
  * @return mixed Either a string url for the parameters if they match or false.
  * @access public
  */
 function match($url)
 {
     if (!$this->compiled()) {
         $this->compile();
     }
     $defaults = $this->defaults;
     if (isset($defaults['prefix'])) {
         $url['prefix'] = $defaults['prefix'];
     }
     //check that all the key names are in the url
     $keyNames = array_flip($this->keys);
     if (array_intersect_key($keyNames, $url) != $keyNames) {
         return false;
     }
     $diffUnfiltered = Set::diff($url, $defaults);
     $diff = array();
     foreach ($diffUnfiltered as $key => $var) {
         if ($var === 0 || $var === '0' || !empty($var)) {
             $diff[$key] = $var;
         }
     }
     //if a not a greedy route, no extra params are allowed.
     if (!$this->_greedy && array_diff_key($diff, $keyNames) != array()) {
         return false;
     }
     //remove defaults that are also keys. They can cause match failures
     foreach ($this->keys as $key) {
         unset($defaults[$key]);
     }
     $filteredDefaults = array_filter($defaults);
     //if the difference between the url diff and defaults contains keys from defaults its not a match
     if (array_intersect_key($filteredDefaults, $diffUnfiltered) !== array()) {
         return false;
     }
     $passedArgsAndParams = array_diff_key($diff, $filteredDefaults, $keyNames);
     list($named, $params) = Router::getNamedElements($passedArgsAndParams, $url['controller'], $url['action']);
     //remove any pass params, they have numeric indexes, skip any params that are in the defaults
     $pass = array();
     $i = 0;
     while (isset($url[$i])) {
         if (!isset($diff[$i])) {
             $i++;
             continue;
         }
         $pass[] = $url[$i];
         unset($url[$i], $params[$i]);
         $i++;
     }
     //still some left over parameters that weren't named or passed args, bail.
     if (!empty($params)) {
         return false;
     }
     //check patterns for routed params
     if (!empty($this->options)) {
         foreach ($this->options as $key => $pattern) {
             if (array_key_exists($key, $url) && !preg_match('#^' . $pattern . '$#', $url[$key])) {
                 return false;
             }
         }
     }
     return $this->_writeUrl(array_merge($url, compact('pass', 'named')));
 }
Example #2
0
 /**
  * Maps a URL array onto a route and returns the string result, or false if no match
  *
  * @param array $route Route Route
  * @param array $url URL URL to map
  * @return mixed Result (as string) or false if no match
  * @access public
  * @static
  */
 function mapRouteElements($route, $url)
 {
     if (isset($route[3]['prefix'])) {
         $prefix = $route[3]['prefix'];
         unset($route[3]['prefix']);
     }
     $pass = array();
     $defaults = $route[3];
     $routeParams = $route[2];
     $params = Set::diff($url, $defaults);
     $urlInv = array_combine(array_values($url), array_keys($url));
     $i = 0;
     while (isset($defaults[$i])) {
         if (isset($urlInv[$defaults[$i]])) {
             if (!in_array($defaults[$i], $url) && is_int($urlInv[$defaults[$i]])) {
                 return false;
             }
             unset($urlInv[$defaults[$i]], $defaults[$i]);
         } else {
             return false;
         }
         $i++;
     }
     foreach ($params as $key => $value) {
         if (is_int($key)) {
             $pass[] = $value;
             unset($params[$key]);
         }
     }
     list($named, $params) = Router::getNamedElements($params);
     if (!strpos($route[0], '*') && (!empty($pass) || !empty($named))) {
         return false;
     }
     $urlKeys = array_keys($url);
     $paramsKeys = array_keys($params);
     $defaultsKeys = array_keys($defaults);
     if (!empty($params)) {
         if (array_diff($paramsKeys, $routeParams) != array()) {
             return false;
         }
         $required = array_values(array_diff($routeParams, $urlKeys));
         $reqCount = count($required);
         for ($i = 0; $i < $reqCount; $i++) {
             if (array_key_exists($required[$i], $defaults) && $defaults[$required[$i]] === null) {
                 unset($required[$i]);
             }
         }
     }
     $isFilled = true;
     if (!empty($routeParams)) {
         $filled = array_intersect_key($url, array_combine($routeParams, array_keys($routeParams)));
         $isFilled = array_diff($routeParams, array_keys($filled)) === array();
         if (!$isFilled && empty($params)) {
             return false;
         }
     }
     if (empty($params)) {
         return Router::__mapRoute($route, array_merge($url, compact('pass', 'named', 'prefix')));
     } elseif (!empty($routeParams) && !empty($route[3])) {
         if (!empty($required)) {
             return false;
         }
         foreach ($params as $key => $val) {
             if (!isset($url[$key]) || $url[$key] != $val || (!isset($defaults[$key]) || $defaults[$key] != $val) && !in_array($key, $routeParams)) {
                 if (!isset($defaults[$key])) {
                     continue;
                 }
                 return false;
             }
         }
     } else {
         if (empty($required) && $defaults['plugin'] === $url['plugin'] && $defaults['controller'] === $url['controller'] && $defaults['action'] === $url['action']) {
             return Router::__mapRoute($route, array_merge($url, compact('pass', 'named', 'prefix')));
         }
         return false;
     }
     if (!empty($route[4])) {
         foreach ($route[4] as $key => $reg) {
             if (array_key_exists($key, $url) && !preg_match('#' . $reg . '#', $url[$key])) {
                 return false;
             }
         }
     }
     return Router::__mapRoute($route, array_merge($filled, compact('pass', 'named', 'prefix')));
 }