RouterTransparentRule.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 RouterTransparentRule extends RouterBaseRule
00013     {
00014         protected $urlVariable      = ':';
00015         protected $urlDelimiter     = '/';
00016         protected $regexDelimiter   = '#';
00017         
00018         protected $defaultRegex     = null;
00019         protected $route            = null;
00020         protected $routeProcessed   = false;
00021         protected $variables        = array();
00022         protected $parts            = array();
00023         protected $requirements     = array();
00024         protected $values           = array();
00025         protected $wildcardData     = array();
00026         
00027         protected $staticCount      = 0;
00028         
00032         public static function create($route)
00033         {
00034             return new self($route);
00035         }
00036         
00037         public function __construct($route)
00038         {
00039             $this->route = trim($route, $this->urlDelimiter);
00040         }
00041         
00045         public function setRequirements(array $reqirements)
00046         {
00047             $this->requirements = $reqirements;
00048             
00049             return $this;
00050         }
00051         
00052         public function getRequirements()
00053         {
00054             return $this->requirements;
00055         }
00056         
00057         public function match(HttpRequest $request)
00058         {
00059             $this->processRoute();
00060             
00061             $path = $this->processPath($request)->toString();
00062             
00063             $pathStaticCount = 0;
00064             $values = array();
00065             
00066             $path = trim($path, $this->urlDelimiter);
00067             
00068             if ($path !== '') {
00069                 $path = explode($this->urlDelimiter, $path);
00070                 
00071                 foreach ($path as $pos => $pathPart) {
00072                     if (!array_key_exists($pos, $this->parts)) {
00073                         return array();
00074                     }
00075                     
00076                     if ($this->parts[$pos] === '*') {
00077                         $count = count($path);
00078                         
00079                         for ($i = $pos; $i < $count; $i += 2) {
00080                             $var = urldecode($path[$i]);
00081                             
00082                             if (
00083                                 !isset($this->wildcardData[$var])
00084                                 && !isset($this->defaults[$var])
00085                                 && !isset($values[$var])
00086                             ) {
00087                                 $this->wildcardData[$var] =
00088                                     (isset($path[$i+1]))
00089                                         ? urldecode($path[$i+1])
00090                                         : null;
00091                             }
00092                         }
00093                         
00094                         break;
00095                     }
00096                     
00097                     $name =
00098                         isset($this->variables[$pos])
00099                             ? $this->variables[$pos]
00100                             : null;
00101                     
00102                     $pathPart = urldecode($pathPart);
00103                     
00104                     if (
00105                         ($name === null)
00106                         && ($this->parts[$pos] != $pathPart)
00107                     ) {
00108                         return array();
00109                     }
00110                     
00111                     if (
00112                         $this->parts[$pos] !== null
00113                         && !preg_match(
00114                             $this->regexDelimiter
00115                             .'^'.$this->parts[$pos].'$'
00116                             .$this->regexDelimiter.'iu',
00117                             $pathPart
00118                         )
00119                     ) {
00120                         return array();
00121                     }
00122                     
00123                     if ($name !== null) {
00124                         $values[$name] = $pathPart;
00125                     } else {
00126                         ++$pathStaticCount;
00127                     }
00128                 }
00129             }
00130             
00131             if ($this->staticCount != $pathStaticCount)
00132                 return array();
00133             
00134             $return = $values + $this->wildcardData + $this->defaults;
00135             
00136             foreach ($this->variables as $var) {
00137                 if (!array_key_exists($var, $return))
00138                     return array();
00139             }
00140             
00141             $this->values = $values;
00142             
00143             return $return;
00144         }
00145         
00156         public function assembly(
00157             array $data = array(),
00158             $reset = false,
00159             $encode = false
00160         )
00161         {
00162             $this->processRoute();
00163             
00164             $url = array();
00165             $flag = false;
00166             
00167             foreach ($this->parts as $key => $part) {
00168                 $name =
00169                     isset($this->variables[$key])
00170                         ? $this->variables[$key]
00171                         : null;
00172                 
00173                 $useDefault = false;
00174                 
00175                 if (
00176                     $name
00177                     && array_key_exists($name, $data)
00178                     && ($data[$name] === null)
00179                 ) {
00180                     $useDefault = true;
00181                 }
00182                 
00183                 if ($name) {
00184                     if (
00185                         isset($data[$name])
00186                         && !$useDefault
00187                     ) {
00188                         $url[$key] = $data[$name];
00189                         unset($data[$name]);
00190                     } elseif (
00191                         !$reset
00192                         && !$useDefault
00193                         && isset($this->values[$name])
00194                     ) {
00195                         $url[$key] = $this->values[$name];
00196                     } elseif (
00197                         !$reset
00198                         && !$useDefault
00199                         && isset($this->wildcardData[$name])
00200                     ) {
00201                         $url[$key] = $this->wildcardData[$name];
00202                     } elseif (isset($this->defaults[$name])) {
00203                         $url[$key] = $this->defaults[$name];
00204                     } else {
00205                         // FIXME: bogus message
00206                         throw new RouterException("{$name} is not specified");
00207                     }
00208                 } elseif ($part !== '*') {
00209                     $url[$key] = $part;
00210                 } else {
00211                     if (!$reset)
00212                         $data += $this->wildcardData;
00213                     
00214                     foreach ($data as $var => $value) {
00215                         if ($value !== null) {
00216                             if (
00217                                 isset($this->defaults[$var])
00218                                 && ($this->defaults[$var] === $value)
00219                             ) {
00220                                 continue;
00221                             }
00222                             
00223                             $url[$key++] = $var;
00224                             $url[$key++] = $value;
00225                             $flag = true;
00226                         }
00227                     }
00228                 }
00229             }
00230             
00231             $return = null;
00232             
00233             foreach (array_reverse($url, true) as $key => $value) {
00234                 if (
00235                     $flag
00236                     || !isset($this->variables[$key])
00237                     || ($value !== $this->getDefault($this->variables[$key]))
00238                 ) {
00239                     if ($encode)
00240                         $value = urlencode($value);
00241                     
00242                     $return =
00243                         $this->urlDelimiter
00244                         .$value
00245                         .$return;
00246                     
00247                     $flag = true;
00248                 }
00249             }
00250             
00251             // FIXME: rtrim, probably?
00252             return trim($return, $this->urlDelimiter);
00253         }
00254         
00258         protected function processRoute()
00259         {
00260             if ($this->routeProcessed)
00261                 return $this;
00262             
00263             if ($this->route !== '') {
00264                 foreach (explode($this->urlDelimiter, $this->route) as $pos => $part) {
00265                     if (substr($part, 0, 1) == $this->urlVariable) {
00266                         $name = substr($part, 1);
00267                         
00268                         $this->parts[$pos] = (
00269                             isset($this->requirements[$name])
00270                                 ? $this->requirements[$name]
00271                                 : $this->defaultRegex
00272                         );
00273                         
00274                         $this->variables[$pos] = $name;
00275                     } else {
00276                         $this->parts[$pos] = $part;
00277                         
00278                         if ($part !== '*')
00279                             $this->staticCount++;
00280                     }
00281                 }
00282             }
00283             
00284             $this->routeProcessed = true;
00285             
00286             return $this;
00287         }
00288     }
00289 ?>