# RouterHostnameRule.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 RouterHostnameRule extends RouterBaseRule
    00013     {
    00014         const SCHEME_HTTP           = 'http';
    00015         const SCHEME_HTTPS          = 'https';
    00016
    00017         protected $hostVariable     = ':';
    00018         protected $regexDelimiter   = '#';
    00019
    00020         protected $scheme           = null;
    00021         protected $defaultRegex     = null;
    00022         protected $route            = null;
    00023         protected $routeProcessed   = false;
    00024         protected $variables        = array();
    00025         protected $parts            = array();
    00026         protected $requirements     = array();
    00027         protected $values           = array();
    00028
    00029         protected $staticCount      = 0;
    00030
    00034         public static function create($route)
    00035         {
    00036             return new self($route);
    00037         }
    00038
    00039         public function __construct($route)
    00040         {
    00041             $this->route = trim($route, '.');
    00042             $this->scheme = self::SCHEME_HTTP;
    00043         }
    00044
    00048         public function setRequirements(array $reqirements)
    00049         {
    00050             $this->requirements = $reqirements;
    00051
    00052             return $this;
    00053         }
    00054
    00055         public function getRequirements()
    00056         {
    00057             return $this->requirements;
    00058         }
    00059
    00063         public function setSecure()
    00064         {
    00065             $this->scheme = self::SCHEME_HTTPS;
    00066
    00067             return $this;
    00068         }
    00069
    00070         public function isSecure()
    00071         {
    00072             return $this->scheme == self::SCHEME_HTTPS;
    00073         }
    00074
    00078         public function setScheme($schema)
    00079         {
    00080             $this->scheme = $schema;
    00081
    00082             return $this;
    00083         }
    00084
    00085         public function getScheme()
    00086         {
    00087             return $this->scheme;
    00088         }
    00089
    00090         public function match(HttpRequest $request)
    00091         {
    00092             $this->processRoute();
    00093
    00094             if (
    00095                 $this->isSecureRequest($request)
    00096                 && !$this->isSecure()
    00097             )
    00098                 return array();
    00099
    00100             if ($request->hasServerVar('HTTP_HOST'))
    00101                 $host = $request->getServerVar('HTTP_HOST');
    00102             else
    00103                 throw new RouterException('Can not find host');
    00104
    00105             $result = array();
    00106
    00107             if (preg_match('#:\d+$#', $host, $result) === 1)
    00108                 $host = substr($host, 0, -strlen($result[0]));
    00109
    00110             $hostStaticCount = 0;
    00111             $values = array();
    00112
    00113             $host = trim($host, '.');
    00114
    00115             // FIXME: strpos('.', ...), probably?
    00116             if ($host) {
    00117                 $host = explode('.', $host);
    00118
    00119                 foreach ($host as $pos => $hostPart) {
    00120                     if (!array_key_exists($pos, $this->parts)) {
    00121                         return array();
    00122                     }
    00123
    00124                     $name =
    00125                         isset($this->variables[$pos])
    00126                             ? $this->variables[$pos]
    00127                             : null;
    00128
    00129                     $hostPart = urldecode($hostPart);
    00130
    00131                     if (
    00132                         ($name === null)
    00133                         && ($this->parts[$pos] != $hostPart)
    00134                     ) {
    00135                         return array();
    00136                     }
    00137
    00138                     if (
    00139                         ($this->parts[$pos] !== null)
    00140                         && !preg_match(
    00141                             $this->regexDelimiter
    00142                             .'^'.$this->parts[$pos].'$'
    00143                             .$this->regexDelimiter.'iu',
    00144
    00145                             $hostPart
    00146                         )
    00147                     ) {
    00148                         return array();
    00149                     }
    00150
    00151                     if ($name !== null) {
    00152                         $values[$name] = $hostPart;
    00153                     } else {
    00154                         ++$hostStaticCount;
    00155                     }
    00156                 }
    00157             }
    00158
    00159             if ($this->staticCount != $hostStaticCount)
    00160                 return array();
    00161
    00162             $return = $values + $this->defaults;
    00163
    00164             foreach ($this->variables as $var) {
    00165                 if (!array_key_exists($var, $return))
    00166                     return array();
    00167             }
    00168
    00169             $this->values = $values;
    00170
    00171             return $return;
    00172         }
    00173
    00174         public function assembly(
    00175             array $data = array(),
    00176             $reset = false,
    00177             $encode = false
    00178         )
    00179         {
    00180             $this->processRoute();
    00181
    00182             $host = array();
    00183             $flag = false;
    00184
    00185             foreach ($this->parts as $key => $part) {
    00186                 $name =
    00187                     isset($this->variables[$key])
    00188                         ? $this->variables[$key]
    00189                         : null;
    00190
    00191                 $useDefault = false;
    00192
    00193                 if (
    00194                     isset($name)
    00195                     && array_key_exists($name, $data)
    00196                     && ($data[$name] === null)
    00197                 ) {
    00198                     $useDefault = true;
    00199                 }
    00200
    00201                 if ($name) {
    00202                     if (isset($data[$name]) && !$useDefault) {
    00203                         $host[$key] = $data[$name];
    00204                         unset($data[$name]);
    00205                     } elseif (
    00206                         !$reset
    00207                         && !$useDefault
    00208                         && isset($this->values[$name])
    00209                     ) {
    00210                         $host[$key] = $this->values[$name];
    00211                     } elseif (isset($this->defaults[$name])) {
    00212                         $host[$key] = $this->defaults[$name];
    00213                     } else {
    00214                         // FIXME: bogus message
    00215                         throw new RouterException($name . ' is not specified');
    00216                     }
    00217                 } else {
    00218                     $host[$key] = $part;
    00219                 }
    00220             }
    00221
    00222             $return = null;
    00223
    00224             foreach (array_reverse($host, true) as $key => $value) {
    00225                 if (
    00226                     $flag
    00227                     || !isset($this->variables[$key])
    00228                     || ($value !== $this->getDefault($this->variables[$key]))
    00229                 ) {
    00230                     if ($encode)
    00231                         $value = urlencode($value);
    00232
    00233                     $return = '.'.$value.$return;
    00234                     $flag = true;
    00235                 }
    00236             }
    00237
    00238             // FIXME: rtrim, probably?
    00239             $host = trim($return, '.');
    00240
    00241             return $this->resolveSchema() . '://' . $host . $this->resolvePath();
    00242
    00243         }
    00244
    00248         protected function processRoute()
    00249         {
    00250             if ($this->routeProcessed)
    00251                 return $this;
    00252
    00253             // FIXME: if (strpos('.', ...), probably?
    00254             if ($this->route) {
    00255                 foreach (explode('.', $this->route) as $pos => $part) {
    00256                     if (substr($part, 0, 1) == $this->hostVariable) {
    00257                         $name = substr($part, 1);
    00258
    00259                         $this->parts[$pos] = (
    00260                             isset($this->requirements[$name])
    00261                                 ? $this->requirements[$name]
    00262                                 : $this->defaultRegex
    00263                             );
    00264
    00265                         $this->variables[$pos] = $name;
    00266                     } else {
    00267                         $this->parts[$pos] = $part;
    00268                         ++$this->staticCount;
    00269                     }
    00270                 }
    00271             }
    00272
    00273             $this->routeProcessed = true;
    00274
    00275             return $this;
    00276         }
    00277
    00278         protected function isSecureRequest(HttpRequest $request)
    00279         {
    00280             return (
    00281                 $request->hasServerVar('HTTPS')
    00282                 && $request->getServerVar('HTTPS') == 'on'
    00283             ) || (
    00284                 $request->hasServerVar('SERVER_PORT')
    00285                 && (int) $request->getServerVar('SERVER_PORT') === 443
    00286             );
    00287         }
    00288
    00289         protected function resolveSchema()
    00290         {
    00291             $base = RouterRewrite::me()->getBaseUrl();
    00292
    00293             if ($this->scheme) {
    00294                 return $this->scheme;
    00295             } elseif (
    00296                 ($base instanceof HttpUrl)
    00297                 && $base->getScheme()
    00298             ) {
    00299                 return $base->getScheme();
    00300             } else {
    00301                 throw new RouterException('Cannot resolve scheme');
    00302             }
    00303         }
    00304
    00305         protected function resolvePath()
    00306         {
    00307             if (
    00308                 ($base = RouterRewrite::me()->getBaseUrl())
    00309                 && ($this->scheme == $base->getScheme())
    00310             ) {
    00311                 return rtrim($base->getPath(), '/');
    00312             } else {
    00313                 return '';
    00314             }
    00315         }
    00316     }
    00317 ?>