File indexing completed on 2024-12-29 05:27:32
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Controller 0017 * @subpackage Router 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @version $Id$ 0020 * @license http://framework.zend.com/license/new-bsd New BSD License 0021 */ 0022 0023 /** Zend_Controller_Router_Route_Abstract */ 0024 // require_once 'Zend/Controller/Router/Route/Abstract.php'; 0025 0026 /** 0027 * Hostname Route 0028 * 0029 * @package Zend_Controller 0030 * @subpackage Router 0031 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0032 * @license http://framework.zend.com/license/new-bsd New BSD License 0033 * @see http://manuals.rubyonrails.com/read/chapter/65 0034 */ 0035 class Zend_Controller_Router_Route_Hostname extends Zend_Controller_Router_Route_Abstract 0036 { 0037 0038 /** 0039 * Host variable 0040 * 0041 * @var string 0042 */ 0043 protected $_hostVariable = ':'; 0044 0045 /** 0046 * Regex delimiter 0047 * 0048 * @var string 0049 */ 0050 protected $_regexDelimiter = '#'; 0051 0052 /** 0053 * Default regex string 0054 * 0055 * @var string|null 0056 */ 0057 protected $_defaultRegex = null; 0058 0059 /** 0060 * Holds names of all route's pattern variable names. Array index holds a position in host. 0061 * 0062 * @var array 0063 */ 0064 protected $_variables = array(); 0065 0066 /** 0067 * Holds Route patterns for all host parts. In case of a variable it stores it's regex 0068 * requirement or null. In case of a static part, it holds only it's direct value. 0069 * 0070 * @var array 0071 */ 0072 protected $_parts = array(); 0073 0074 /** 0075 * Holds user submitted default values for route's variables. Name and value pairs. 0076 * 0077 * @var array 0078 */ 0079 protected $_defaults = array(); 0080 0081 /** 0082 * Holds user submitted regular expression patterns for route's variables' values. 0083 * Name and value pairs. 0084 * 0085 * @var array 0086 */ 0087 protected $_requirements = array(); 0088 0089 /** 0090 * Default scheme 0091 * 0092 * @var string 0093 */ 0094 protected $_scheme = null; 0095 0096 /** 0097 * Associative array filled on match() that holds matched path values 0098 * for given variable names. 0099 * 0100 * @var array 0101 */ 0102 protected $_values = array(); 0103 0104 /** 0105 * Current request object 0106 * 0107 * @var Zend_Controller_Request_Abstract 0108 */ 0109 protected $_request; 0110 0111 /** 0112 * Helper var that holds a count of route pattern's static parts 0113 * for validation 0114 * 0115 * @var int 0116 */ 0117 private $_staticCount = 0; 0118 0119 /** 0120 * Set the request object 0121 * 0122 * @param Zend_Controller_Request_Abstract|null $request 0123 */ 0124 public function setRequest(Zend_Controller_Request_Abstract $request = null) 0125 { 0126 $this->_request = $request; 0127 } 0128 0129 /** 0130 * Get the request object 0131 * 0132 * @return Zend_Controller_Request_Abstract $request 0133 */ 0134 public function getRequest() 0135 { 0136 if ($this->_request === null) { 0137 // require_once 'Zend/Controller/Front.php'; 0138 $this->_request = Zend_Controller_Front::getInstance()->getRequest(); 0139 } 0140 0141 return $this->_request; 0142 } 0143 0144 /** 0145 * Instantiates route based on passed Zend_Config structure 0146 * 0147 * @param Zend_Config $config Configuration object 0148 * @return Zend_Controller_Router_Route_Hostname 0149 */ 0150 public static function getInstance(Zend_Config $config) 0151 { 0152 $reqs = ($config->reqs instanceof Zend_Config) ? $config->reqs->toArray() : array(); 0153 $defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); 0154 $scheme = (isset($config->scheme)) ? $config->scheme : null; 0155 0156 return new self($config->route, $defs, $reqs, $scheme); 0157 } 0158 0159 /** 0160 * Prepares the route for mapping by splitting (exploding) it 0161 * to a corresponding atomic parts. These parts are assigned 0162 * a position which is later used for matching and preparing values. 0163 * 0164 * @param string $route Map used to match with later submitted hostname 0165 * @param array $defaults Defaults for map variables with keys as variable names 0166 * @param array $reqs Regular expression requirements for variables (keys as variable names) 0167 * @param string $scheme 0168 */ 0169 public function __construct($route, $defaults = array(), $reqs = array(), $scheme = null) 0170 { 0171 $route = trim($route, '.'); 0172 $this->_defaults = (array) $defaults; 0173 $this->_requirements = (array) $reqs; 0174 $this->_scheme = $scheme; 0175 0176 if ($route != '') { 0177 foreach (explode('.', $route) as $pos => $part) { 0178 if (substr($part, 0, 1) == $this->_hostVariable) { 0179 $name = substr($part, 1); 0180 $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex); 0181 $this->_variables[$pos] = $name; 0182 } else { 0183 $this->_parts[$pos] = $part; 0184 $this->_staticCount++; 0185 } 0186 } 0187 } 0188 } 0189 0190 /** 0191 * Matches a user submitted path with parts defined by a map. Assigns and 0192 * returns an array of variables on a successful match. 0193 * 0194 * @param Zend_Controller_Request_Http $request Request to get the host from 0195 * @return array|false An array of assigned values or a false on a mismatch 0196 */ 0197 public function match($request) 0198 { 0199 // Check the scheme if required 0200 if ($this->_scheme !== null) { 0201 $scheme = $request->getScheme(); 0202 0203 if ($scheme !== $this->_scheme) { 0204 return false; 0205 } 0206 } 0207 0208 // Get the host and remove unnecessary port information 0209 $host = $request->getHttpHost(); 0210 if (preg_match('#:\d+$#', $host, $result) === 1) { 0211 $host = substr($host, 0, -strlen($result[0])); 0212 } 0213 0214 $hostStaticCount = 0; 0215 $values = array(); 0216 0217 $host = trim($host, '.'); 0218 0219 if ($host != '') { 0220 $host = explode('.', $host); 0221 0222 foreach ($host as $pos => $hostPart) { 0223 // Host is longer than a route, it's not a match 0224 if (!array_key_exists($pos, $this->_parts)) { 0225 return false; 0226 } 0227 0228 $name = isset($this->_variables[$pos]) ? $this->_variables[$pos] : null; 0229 $hostPart = urldecode($hostPart); 0230 0231 // If it's a static part, match directly 0232 if ($name === null && $this->_parts[$pos] != $hostPart) { 0233 return false; 0234 } 0235 0236 // If it's a variable with requirement, match a regex. If not - everything matches 0237 if ($this->_parts[$pos] !== null 0238 && !preg_match( 0239 $this->_regexDelimiter . '^' . $this->_parts[$pos] . '$' . $this->_regexDelimiter . 'iu', 0240 $hostPart 0241 ) 0242 ) { 0243 return false; 0244 } 0245 0246 // If it's a variable store it's value for later 0247 if ($name !== null) { 0248 $values[$name] = $hostPart; 0249 } else { 0250 $hostStaticCount++; 0251 } 0252 } 0253 } 0254 0255 // Check if all static mappings have been matched 0256 if ($this->_staticCount != $hostStaticCount) { 0257 return false; 0258 } 0259 0260 $return = $values + $this->_defaults; 0261 0262 // Check if all map variables have been initialized 0263 foreach ($this->_variables as $var) { 0264 if (!array_key_exists($var, $return)) { 0265 return false; 0266 } 0267 } 0268 0269 $this->_values = $values; 0270 0271 return $return; 0272 } 0273 0274 /** 0275 * Assembles user submitted parameters forming a hostname defined by this route 0276 * 0277 * @param array $data An array of variable and value pairs used as parameters 0278 * @param boolean $reset Whether or not to set route defaults with those provided in $data 0279 * @param boolean $encode 0280 * @param boolean $partial 0281 * @throws Zend_Controller_Router_Exception 0282 * @return string Route path with user submitted parameters 0283 */ 0284 public function assemble($data = array(), $reset = false, $encode = false, $partial = false) 0285 { 0286 $host = array(); 0287 $flag = false; 0288 0289 foreach ($this->_parts as $key => $part) { 0290 $name = isset($this->_variables[$key]) ? $this->_variables[$key] : null; 0291 0292 $useDefault = false; 0293 if (isset($name) && array_key_exists($name, $data) && $data[$name] === null) { 0294 $useDefault = true; 0295 } 0296 0297 if (isset($name)) { 0298 if (isset($data[$name]) && !$useDefault) { 0299 $host[$key] = $data[$name]; 0300 unset($data[$name]); 0301 } elseif (!$reset && !$useDefault && isset($this->_values[$name])) { 0302 $host[$key] = $this->_values[$name]; 0303 } elseif (isset($this->_defaults[$name])) { 0304 $host[$key] = $this->_defaults[$name]; 0305 } else { 0306 // require_once 'Zend/Controller/Router/Exception.php'; 0307 throw new Zend_Controller_Router_Exception($name . ' is not specified'); 0308 } 0309 } else { 0310 $host[$key] = $part; 0311 } 0312 } 0313 0314 $return = ''; 0315 0316 foreach (array_reverse($host, true) as $key => $value) { 0317 if ($flag || !isset($this->_variables[$key]) || $value !== $this->getDefault($this->_variables[$key]) 0318 || $partial 0319 ) { 0320 if ($encode) { 0321 $value = urlencode($value); 0322 } 0323 $return = '.' . $value . $return; 0324 $flag = true; 0325 } 0326 } 0327 0328 $url = trim($return, '.'); 0329 0330 if ($this->_scheme !== null) { 0331 $scheme = $this->_scheme; 0332 } else { 0333 $request = $this->getRequest(); 0334 if ($request instanceof Zend_Controller_Request_Http) { 0335 $scheme = $request->getScheme(); 0336 } else { 0337 $scheme = 'http'; 0338 } 0339 } 0340 0341 $url = $scheme . '://' . $url; 0342 0343 return $url; 0344 } 0345 0346 /** 0347 * Return a single parameter of route's defaults 0348 * 0349 * @param string $name Array key of the parameter 0350 * @return string Previously set default 0351 */ 0352 public function getDefault($name) 0353 { 0354 if (isset($this->_defaults[$name])) { 0355 return $this->_defaults[$name]; 0356 } 0357 0358 return null; 0359 } 0360 0361 /** 0362 * Return an array of defaults 0363 * 0364 * @return array Route defaults 0365 */ 0366 public function getDefaults() 0367 { 0368 return $this->_defaults; 0369 } 0370 0371 /** 0372 * Get all variables which are used by the route 0373 * 0374 * @return array 0375 */ 0376 public function getVariables() 0377 { 0378 return $this->_variables; 0379 } 0380 }