RouterRegexpRule.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2008 by Sergey S. Sergeev                               *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00012     final class RouterRegexpRule extends RouterBaseRule
00013     {
00014         protected $regexp   = null;
00015         protected $reverse  = null;
00016         protected $route    = null;
00017         
00018         protected $map      = array();
00019         protected $values   = array();
00020         
00024         public static function create($route)
00025         {
00026             return new self($route);
00027         }
00028         
00029         public function __construct($route)
00030         {
00031             $this->route = $route;
00032             $this->regexp = '#^' . $this->route . '$#i';
00033         }
00034         
00038         public function setMap(array $map)
00039         {
00040             $this->map = $map;
00041             
00042             return $this;
00043         }
00044         
00045         public function getMap()
00046         {
00047             return $this->map;
00048         }
00049         
00053         public function setReverse($reverse)
00054         {
00055             Assert::isString($reverse);
00056             
00057             $this->reverse = $reverse;
00058             
00059             return $this;
00060         }
00061         
00062         public function getReverse()
00063         {
00064             return $this->reverse;
00065         }
00066         
00067         public function match(HttpRequest $request)
00068         {
00069             $path = $this->processPath($request)->toString();
00070             
00071             // FIXME: rtrim. probably?
00072             $path = trim(urldecode($path), '/');
00073             $res = preg_match($this->regexp, $path, $values);
00074             
00075             if ($res === 0)
00076                 return array();
00077             
00081             foreach ($values as $i => $value) {
00082                 if (!is_int($i) || $i === 0) {
00083                     unset($values[$i]);
00084                 }
00085             }
00086             
00087             $this->values = $values;
00088             
00089             $values = $this->getMappedValues($values);
00090             $defaults = $this->getMappedValues($this->defaults, false, true);
00091             
00092             $return = $values + $defaults;
00093             
00094             return $return;
00095         }
00096         
00097         public function assembly(
00098             array $data = array(),
00099             $reset = false,
00100             $encode = false
00101         )
00102         {
00103             if ($this->reverse === null)
00104                 throw new RouterException(
00105                     'Can not assembly. Reversed route is not specified.'
00106                 );
00107             
00108             $defaultValuesMapped  = $this->getMappedValues($this->defaults, true, false);
00109             $matchedValuesMapped  = $this->getMappedValues($this->values, true, false);
00110             $dataValuesMapped     = $this->getMappedValues($data, true, false);
00111             
00112             if (($resetKeys = array_search(null, $dataValuesMapped, true)) !== false) {
00113                 foreach ((array) $resetKeys as $resetKey) {
00114                     if (isset($matchedValuesMapped[$resetKey])) {
00115                         unset($matchedValuesMapped[$resetKey]);
00116                         unset($dataValuesMapped[$resetKey]);
00117                     }
00118                 }
00119             }
00120             
00121             $mergedData = $defaultValuesMapped;
00122             $mergedData = $this->arrayMergeNumericKeys($mergedData, $matchedValuesMapped);
00123             $mergedData = $this->arrayMergeNumericKeys($mergedData, $dataValuesMapped);
00124             
00125             ksort($mergedData);
00126             
00127             try {
00128                 $return = vsprintf($this->reverse, $mergedData);
00129             } catch (BaseException $e) {
00130                 throw new RouterException(
00131                     'Can not assembly. Too few arguments? Error was: '
00132                     .$e->getMessage()
00133                 );
00134             }
00135             
00136             return $return;
00137         }
00138         
00142         protected function arrayMergeNumericKeys(array $array1, array $array2)
00143         {
00144             $returnArray = $array1;
00145             
00146             foreach ($array2 as $array2Index => $array2Value)
00147                 $returnArray[$array2Index] = $array2Value;
00148             
00149             return $returnArray;
00150         }
00151         
00163         protected function getMappedValues($values, $reversed = false, $preserve = false)
00164         {
00165             if (!count($this->map))
00166                 return $values;
00167             
00168             $return = array();
00169             
00170             foreach ($values as $key => $value) {
00171                 if (is_int($key) && !$reversed) {
00172                     if (array_key_exists($key, $this->map)) {
00173                         $index = $this->map[$key];
00174                     } elseif (($index = array_search($key, $this->map)) === false) {
00175                         $index = $key;
00176                     }
00177                     
00178                     $return[$index] = $values[$key];
00179                 } elseif ($reversed) {
00180                     $index =
00181                         (!is_int($key))
00182                             ? array_search($key, $this->map, true)
00183                             : $key;
00184                     
00185                     if (false !== $index) {
00186                         $return[$index] = $values[$key];
00187                     }
00188                 } elseif ($preserve) {
00189                     $return[$key] = $value;
00190                 }
00191             }
00192             
00193             return $return;
00194         }
00195     }
00196 ?>