# 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 ?>