root/trunk/framework/Web/TUrlMapping.php
| Revision 2527, 20.3 kB (checked in by mikl, 5 weeks ago) | |
|---|---|
|
|
| Line | |
|---|---|
| 1 | <?php |
| 2 | /** |
| 3 | * TUrlMapping and TUrlMappingPattern class file. |
| 4 | * |
| 5 | * @author Wei Zhuo <weizhuo[at]gamil[dot]com> |
| 6 | * @link http://www.pradosoft.com/ |
| 7 | * @copyright Copyright © 2005-2008 PradoSoft |
| 8 | * @license http://www.pradosoft.com/license/ |
| 9 | * @version $Id$ |
| 10 | * @package System.Web |
| 11 | */ |
| 12 | |
| 13 | Prado::using('System.Web.TUrlManager'); |
| 14 | Prado::using('System.Collections.TAttributeCollection'); |
| 15 | |
| 16 | /** |
| 17 | * TUrlMapping Class |
| 18 | * |
| 19 | * The TUrlMapping module allows PRADO to construct and recognize URLs |
| 20 | * based on specific patterns. |
| 21 | * |
| 22 | * TUrlMapping consists of a list of URL patterns which are used to match |
| 23 | * against the currently requested URL. The first matching pattern will then |
| 24 | * be used to decompose the URL into request parameters (accessible through |
| 25 | * <code>$this->Request['paramname']</code>). |
| 26 | * |
| 27 | * The patterns can also be used to construct customized URLs. In this case, |
| 28 | * the parameters in an applied pattern will be replaced with the corresponding |
| 29 | * GET variable values. |
| 30 | * |
| 31 | * Since it is derived from {@link TUrlManager}, it should be configured globally |
| 32 | * in the application configuration like the following, |
| 33 | * <code> |
| 34 | * <module id="request" class="THttpRequest" UrlManager="friendly-url" /> |
| 35 | * <module id="friendly-url" class="System.Web.TUrlMapping" EnableCustomUrl="true"> |
| 36 | * <url ServiceParameter="Posts.ViewPost" pattern="post/{id}/" parameters.id="\d+" /> |
| 37 | * <url ServiceParameter="Posts.ListPost" pattern="archive/{time}/" parameters.time="\d{6}" /> |
| 38 | * <url ServiceParameter="Posts.ListPost" pattern="category/{cat}/" parameters.cat="\d+" /> |
| 39 | * </module> |
| 40 | * </code> |
| 41 | * |
| 42 | * In the above, each <tt><url></tt> element specifies a URL pattern represented |
| 43 | * as a {@link TUrlMappingPattern} internally. You may create your own pattern classes |
| 44 | * by extending {@link TUrlMappingPattern} and specifying the <tt><class></tt> attribute |
| 45 | * in the element. |
| 46 | * |
| 47 | * The patterns can be also be specified in an external file using the {@link setConfigFile ConfigFile} property. |
| 48 | * |
| 49 | * The URL mapping are evaluated in order, only the first mapping that matches |
| 50 | * the URL will be used. Cascaded mapping can be achieved by placing the URL mappings |
| 51 | * in particular order. For example, placing the most specific mappings first. |
| 52 | * |
| 53 | * Only the PATH_INFO part of the URL is used to match the available patterns. The matching |
| 54 | * is strict in the sense that the whole pattern must match the whole PATH_INFO of the URL. |
| 55 | * |
| 56 | * From PRADO v3.1.1, TUrlMapping also provides support for constructing URLs according to |
| 57 | * the specified pattern. You may enable this functionality by setting {@link setEnableCustomUrl EnableCustomUrl} to true. |
| 58 | * When you call THttpRequest::constructUrl() (or via TPageService::constructUrl()), |
| 59 | * TUrlMapping will examine the available URL mapping patterns using their {@link TUrlMappingPattern::getServiceParameter ServiceParameter} |
| 60 | * and {@link TUrlMappingPattern::getPattern Pattern} properties. A pattern is applied if its |
| 61 | * {@link TUrlMappingPattern::getServiceParameter ServiceParameter} matches the service parameter passed |
| 62 | * to constructUrl() and every parameter in the {@link getPattern Pattern} is found |
| 63 | * in the GET variables. |
| 64 | * |
| 65 | * @author Wei Zhuo <weizhuo[at]gmail[dot]com> |
| 66 | * @version $Id$ |
| 67 | * @package System.Web |
| 68 | * @since 3.0.5 |
| 69 | */ |
| 70 | class TUrlMapping extends TUrlManager |
| 71 | { |
| 72 | /** |
| 73 | * File extension of external configuration file |
| 74 | */ |
| 75 | const CONFIG_FILE_EXT='.xml'; |
| 76 | /** |
| 77 | * @var TUrlMappingPattern[] list of patterns. |
| 78 | */ |
| 79 | protected $_patterns=array(); |
| 80 | /** |
| 81 | * @var TUrlMappingPattern matched pattern. |
| 82 | */ |
| 83 | private $_matched; |
| 84 | /** |
| 85 | * @var string external configuration file |
| 86 | */ |
| 87 | private $_configFile=null; |
| 88 | /** |
| 89 | * @var boolean whether to enable custom contructUrl |
| 90 | */ |
| 91 | private $_customUrl=false; |
| 92 | /** |
| 93 | * @var array rules for constructing URLs |
| 94 | */ |
| 95 | protected $_constructRules=array(); |
| 96 | |
| 97 | private $_urlPrefix=''; |
| 98 | |
| 99 | private $_defaultMappingClass='TUrlMappingPattern'; |
| 100 | |
| 101 | /** |
| 102 | * Initializes this module. |
| 103 | * This method is required by the IModule interface. |
| 104 | * @param TXmlElement configuration for this module, can be null |
| 105 | * @throws TConfigurationException if module is configured in the global scope. |
| 106 | */ |
| 107 | public function init($xml) |
| 108 | { |
| 109 | parent::init($xml); |
| 110 | if($this->getRequest()->getRequestResolved()) |
| 111 | throw new TConfigurationException('urlmapping_global_required'); |
| 112 | if($this->_configFile!==null) |
| 113 | $this->loadConfigFile(); |
| 114 | $this->loadUrlMappings($xml); |
| 115 | if($this->_urlPrefix==='') |
| 116 | $this->_urlPrefix=$this->getRequest()->getApplicationUrl(); |
| 117 | $this->_urlPrefix=rtrim($this->_urlPrefix,'/'); |
| 118 | } |
| 119 | |
| 120 | /** |
| 121 | * Initialize the module from configuration file. |
| 122 | * @throws TConfigurationException if {@link getConfigFile ConfigFile} is invalid. |
| 123 | */ |
| 124 | protected function loadConfigFile() |
| 125 | { |
| 126 | if(is_file($this->_configFile)) |
| 127 | { |
| 128 | $dom=new TXmlDocument; |
| 129 | $dom->loadFromFile($this->_configFile); |
| 130 | $this->loadUrlMappings($dom); |
| 131 | } |
| 132 | else |
| 133 | throw new TConfigurationException('urlmapping_configfile_inexistent',$this->_configFile); |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * Returns a value indicating whether to enable custom constructUrl. |
| 138 | * If true, constructUrl() will make use of the URL mapping rules to |
| 139 | * construct valid URLs. |
| 140 | * @return boolean whether to enable custom constructUrl. Defaults to false. |
| 141 | * @since 3.1.1 |
| 142 | */ |
| 143 | public function getEnableCustomUrl() |
| 144 | { |
| 145 | return $this->_customUrl; |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * Sets a value indicating whether to enable custom constructUrl. |
| 150 | * If true, constructUrl() will make use of the URL mapping rules to |
| 151 | * construct valid URLs. |
| 152 | * @param boolean whether to enable custom constructUrl. |
| 153 | * @since 3.1.1 |
| 154 | */ |
| 155 | public function setEnableCustomUrl($value) |
| 156 | { |
| 157 | $this->_customUrl=TPropertyValue::ensureBoolean($value); |
| 158 | } |
| 159 | |
| 160 | /** |
| 161 | * @return string the part that will be prefixed to the constructed URLs. Defaults to the requested script path (e.g. /path/to/index.php for a URL http://hostname/path/to/index.php) |
| 162 | * @since 3.1.1 |
| 163 | */ |
| 164 | public function getUrlPrefix() |
| 165 | { |
| 166 | return $this->_urlPrefix; |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * @param string the part that will be prefixed to the constructed URLs. This is used by constructUrl() when EnableCustomUrl is set true. |
| 171 | * @see getUrlPrefix |
| 172 | * @since 3.1.1 |
| 173 | */ |
| 174 | public function setUrlPrefix($value) |
| 175 | { |
| 176 | $this->_urlPrefix=$value; |
| 177 | } |
| 178 | |
| 179 | /** |
| 180 | * @return string external configuration file. Defaults to null. |
| 181 | */ |
| 182 | public function getConfigFile() |
| 183 | { |
| 184 | return $this->_configFile; |
| 185 | } |
| 186 | |
| 187 | /** |
| 188 | * @param string external configuration file in namespace format. The file |
| 189 | * must be suffixed with '.xml'. |
| 190 | * @throws TInvalidDataValueException if the file is invalid. |
| 191 | */ |
| 192 | public function setConfigFile($value) |
| 193 | { |
| 194 | if(($this->_configFile=Prado::getPathOfNamespace($value,self::CONFIG_FILE_EXT))===null) |
| 195 | throw new TConfigurationException('urlmapping_configfile_invalid',$value); |
| 196 | } |
| 197 | |
| 198 | /** |
| 199 | * @return string the default class of URL mapping patterns. Defaults to TUrlMappingPattern. |
| 200 | * @since 3.1.1 |
| 201 | */ |
| 202 | public function getDefaultMappingClass() |
| 203 | { |
| 204 | return $this->_defaultMappingClass; |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Sets the default class of URL mapping patterns. |
| 209 | * When a URL matching pattern does not specify "class" attribute, it will default to the class |
| 210 | * specified by this property. You may use either a class name or a namespace format of class (if the class needs to be included first.) |
| 211 | * @param string the default class of URL mapping patterns. |
| 212 | * @since 3.1.1 |
| 213 | */ |
| 214 | public function setDefaultMappingClass($value) |
| 215 | { |
| 216 | $this->_defaultMappingClass=$value; |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * Load and configure each url mapping pattern. |
| 221 | * @param TXmlElement configuration node |
| 222 | * @throws TConfigurationException if specific pattern class is invalid |
| 223 | */ |
| 224 | protected function loadUrlMappings($xml) |
| 225 | { |
| 226 | foreach($xml->getElementsByTagName('url') as $url) |
| 227 | { |
| 228 | $properties=$url->getAttributes(); |
| 229 | if(($class=$properties->remove('class'))===null) |
| 230 | $class=$this->getDefaultMappingClass(); |
| 231 | $pattern=Prado::createComponent($class,$this); |
| 232 | if(!($pattern instanceof TUrlMappingPattern)) |
| 233 | throw new TConfigurationException('urlmapping_urlmappingpattern_required'); |
| 234 | foreach($properties as $name=>$value) |
| 235 | $pattern->setSubproperty($name,$value); |
| 236 | $this->_patterns[]=$pattern; |
| 237 | $pattern->init($url); |
| 238 | |
| 239 | $key=$pattern->getServiceID().':'.$pattern->getServiceParameter(); |
| 240 | $this->_constructRules[$key][]=$pattern; |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | /** |
| 245 | * Parses the request URL and returns an array of input parameters. |
| 246 | * This method overrides the parent implementation. |
| 247 | * The input parameters do not include GET and POST variables. |
| 248 | * This method uses the request URL path to find the first matching pattern. If found |
| 249 | * the matched pattern parameters are used to return as the input parameters. |
| 250 | * @return array list of input parameters |
| 251 | */ |
| 252 | public function parseUrl() |
| 253 | { |
| 254 | $request=$this->getRequest(); |
| 255 | foreach($this->_patterns as $pattern) |
| 256 | { |
| 257 | $matches=$pattern->getPatternMatches($request); |
| 258 | if(count($matches)>0) |
| 259 | { |
| 260 | $this->_matched=$pattern; |
| 261 | $params=array(); |
| 262 | foreach($matches as $key=>$value) |
| 263 | { |
| 264 | if(is_string($key)) |
| 265 | $params[$key]=$value; |
| 266 | } |
| 267 | $params[$pattern->getServiceID()]=$pattern->getServiceParameter(); |
| 268 | return $params; |
| 269 | } |
| 270 | } |
| 271 | return parent::parseUrl(); |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * Constructs a URL that can be recognized by PRADO. |
| 276 | * |
| 277 | * This method provides the actual implementation used by {@link THttpRequest::constructUrl}. |
| 278 | * Override this method if you want to provide your own way of URL formatting. |
| 279 | * If you do so, you may also need to override {@link parseUrl} so that the URL can be properly parsed. |
| 280 | * |
| 281 | * The URL is constructed as the following format: |
| 282 | * /entryscript.php?serviceID=serviceParameter&get1=value1&... |
| 283 | * If {@link THttpRequest::setUrlFormat THttpRequest.UrlFormat} is 'Path', |
| 284 | * the following format is used instead: |
| 285 | * /entryscript.php/serviceID/serviceParameter/get1,value1/get2,value2... |
| 286 | * @param string service ID |
| 287 | * @param string service parameter |
| 288 | * @param array GET parameters, null if not provided |
| 289 | * @param boolean whether to encode the ampersand in URL |
| 290 | * @param boolean whether to encode the GET parameters (their names and values) |
| 291 | * @return string URL |
| 292 | * @see parseUrl |
| 293 | * @since 3.1.1 |
| 294 | */ |
| 295 | public function constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems) |
| 296 | { |
| 297 | if($this->_customUrl) |
| 298 | { |
| 299 | if(!(is_array($getItems) || ($getItems instanceof Traversable))) |
| 300 | $getItems=array(); |
| 301 | $key=$serviceID.':'.$serviceParam; |
| 302 | if(isset($this->_constructRules[$key])) |
| 303 | { |
| 304 | foreach($this->_constructRules[$key] as $rule) |
| 305 | { |
| 306 | if($rule->supportCustomUrl($getItems)) |
| 307 | return $rule->constructUrl($getItems,$encodeAmpersand,$encodeGetItems); |
| 308 | } |
| 309 | } |
| 310 | } |
| 311 | return parent::constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems); |
| 312 | } |
| 313 | |
| 314 | /** |
| 315 | * @return TUrlMappingPattern the matched pattern, null if not found. |
| 316 | */ |
| 317 | public function getMatchingPattern() |
| 318 | { |
| 319 | return $this->_matched; |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | /** |
| 324 | * TUrlMappingPattern class. |
| 325 | * |
| 326 | * TUrlMappingPattern represents a pattern used to parse and construct URLs. |
| 327 | * If the currently requested URL matches the pattern, it will alter |
| 328 | * the THttpRequest parameters. If a constructUrl() call matches the pattern |
| 329 | * parameters, the pattern will generate a valid URL. In both case, only the PATH_INFO |
| 330 | * part of a URL is parsed/constructed using the pattern. |
| 331 | * |
| 332 | * To specify the pattern, set the {@link setPattern Pattern} property. |
| 333 | * {@link setPattern Pattern} takes a string expression with |
| 334 | * parameter names enclosed between a left brace '{' and a right brace '}'. |
| 335 | * The patterns for each parameter can be set using {@link getParameters Parameters} |
| 336 | * attribute collection. For example |
| 337 | * <code> |
| 338 | * <url ... pattern="articles/{year}/{month}/{day}" |
| 339 | * parameters.year="\d{4}" parameters.month="\d{2}" parameters.day="\d+" /> |
| 340 | * </code> |
| 341 | * |
| 342 | * In the above example, the pattern contains 3 parameters named "year", |
| 343 | * "month" and "day". The pattern for these parameters are, respectively, |
| 344 | * "\d{4}" (4 digits), "\d{2}" (2 digits) and "\d+" (1 or more digits). |
| 345 | * Essentially, the <tt>Parameters</tt> attribute name and values are used |
| 346 | * as substrings in replacing the placeholders in the <tt>Pattern</tt> string |
| 347 | * to form a complete regular expression string. |
| 348 | * |
| 349 | * For more complicated patterns, one may specify the pattern using a regular expression |
| 350 | * by {@link setRegularExpression RegularExpression}. For example, the above pattern |
| 351 | * is equivalent to the following regular expression-based pattern: |
| 352 | * <code> |
| 353 | * /^articles\/(?P<year>\d{4})\/(?P<month>\d{2})\/(?P<day>\d+)$/u |
| 354 | * </code> |
| 355 | * The above regular expression used the "named group" feature available in PHP. |
| 356 | * Notice that you need to escape the slash in regular expressions. |
| 357 | * |
| 358 | * Thus, only an url that matches the pattern will be valid. For example, |
| 359 | * a URL <tt>http://example.com/index.php/articles/2006/07/21</tt> will match the above pattern, |
| 360 | * while <tt>http://example.com/index.php/articles/2006/07/hello</tt> will not |
| 361 | * since the "day" parameter pattern is not satisfied. |
| 362 | * |
| 363 | * The parameter values are available through the <tt>THttpRequest</tt> instance (e.g. |
| 364 | * <tt>$this->Request['year']</tt>). |
| 365 | * |
| 366 | * The {@link setServiceParameter ServiceParameter} and {@link setServiceID ServiceID} |
| 367 | * (the default ID is 'page') set the service parameter and service id respectively. |
| 368 | * |
| 369 | * @author Wei Zhuo <weizhuo[at]gmail[dot]com> |
| 370 | * @version $Id$ |
| 371 | * @package System.Web |
| 372 | * @since 3.0.5 |
| 373 | */ |
| 374 | class TUrlMappingPattern extends TComponent |
| 375 | { |
| 376 | /** |
| 377 | * @var string service parameter such as Page class name. |
| 378 | */ |
| 379 | private $_serviceParameter; |
| 380 | /** |
| 381 | * @var string service ID, default is 'page'. |
| 382 | */ |
| 383 | private $_serviceID='page'; |
| 384 | /** |
| 385 | * @var string url pattern to match. |
| 386 | */ |
| 387 | private $_pattern; |
| 388 | /** |
| 389 | * @var TMap parameter regular expressions. |
| 390 | */ |
| 391 | private $_parameters; |
| 392 | /** |
| 393 | * @var string regular expression pattern. |
| 394 | */ |
| 395 | private $_regexp=''; |
| 396 | |
| 397 | private $_customUrl=true; |
| 398 | |
| 399 | private $_manager; |
| 400 | |
| 401 | private $_caseSensitive=true; |
| 402 | |
| 403 | /** |
| 404 | * Constructor. |
| 405 | * @param TUrlManager the URL manager instance |
| 406 | */ |
| 407 | public function __construct(TUrlManager $manager) |
| 408 | { |
| 409 | $this->_manager=$manager; |
| 410 | $this->_parameters=new TAttributeCollection; |
| 411 | $this->_parameters->setCaseSensitive(true); |
| 412 | } |
| 413 | |
| 414 | /** |
| 415 | * @return TUrlManager the URL manager instance |
| 416 | */ |
| 417 | public function getManager() |
| 418 | { |
| 419 | return $this->_manager; |
| 420 | } |
| 421 | |
| 422 | /** |
| 423 | * Initializes the pattern. |
| 424 | * @param TXmlElement configuration for this module. |
| 425 | * @throws TConfigurationException if service parameter is not specified |
| 426 | */ |
| 427 | public function init($config) |
| 428 | { |
| 429 | if($this->_serviceParameter===null) |
| 430 | throw new TConfigurationException('urlmappingpattern_serviceparameter_required', $this->getPattern()); |
| 431 | } |
| 432 | |
| 433 | /** |
| 434 | * Substitute the parameter key value pairs as named groupings |
| 435 | * in the regular expression matching pattern. |
| 436 | * @return string regular expression pattern with parameter subsitution |
| 437 | */ |
| 438 | protected function getParameterizedPattern() |
| 439 | { |
| 440 | $params=array(); |
| 441 | $values=array(); |
| 442 | foreach($this->_parameters as $key=>$value) |
| 443 | { |
| 444 | $params[]='{'.$key.'}'; |
| 445 | $values[]='(?P<'.$key.'>'.$value.')'; |
| 446 | } |
| 447 | $params[]='/'; |
| 448 | $values[]='\\/'; |
| 449 | $regexp=str_replace($params,$values,trim($this->getPattern(),'/').'/'); |
| 450 | $regexp='/^'.$regexp.'$/u'; |
| 451 | if(!$this->getCaseSensitive()) |
| 452 | $regexp.='i'; |
| 453 | return $regexp; |
| 454 | } |
| 455 | |
| 456 | /** |
| 457 | * @return string full regular expression mapping pattern |
| 458 | */ |
| 459 | public function getRegularExpression() |
| 460 | { |
| 461 | return $this->_regexp; |
| 462 | } |
| 463 | |
| 464 | /** |
| 465 | * @param string full regular expression mapping pattern. |
| 466 | */ |
| 467 | public function setRegularExpression($value) |
| 468 | { |
| 469 | $this->_regexp=$value; |
| 470 | } |
| 471 | |
| 472 | /** |
| 473 | * @return boolean whether the {@link getPattern Pattern} should be treated as case sensititve. Defaults to true. |
| 474 | */ |
| 475 | public function getCaseSensitive() |
| 476 | { |
| 477 | return $this->_caseSensitive; |
| 478 | } |
| 479 | |
| 480 | /** |
| 481 | * @param boolean whether the {@link getPattern Pattern} should be treated as case sensititve. |
| 482 | */ |
| 483 | public function setCaseSensitive($value) |
| 484 | { |
| 485 | $this->_caseSensitive=TPropertyValue::ensureBoolean($value); |
| 486 | } |
| 487 | |
| 488 | /** |
| 489 | * @param string service parameter, such as page class name. |
| 490 | */ |
| 491 | public function setServiceParameter($value) |
| 492 | { |
| 493 | $this->_serviceParameter=$value; |
| 494 | } |
| 495 | |
| 496 | /** |
| 497 | * @return string service parameter, such as page class name. |
| 498 | */ |
| 499 | public function getServiceParameter() |
| 500 | { |
| 501 | return $this->_serviceParameter; |
| 502 | } |
| 503 | |
| 504 | /** |
| 505 | * @param string service id to handle. |
| 506 | */ |
| 507 | public function setServiceID($value) |
| 508 | { |
| 509 | $this->_serviceID=$value; |
| 510 | } |
| 511 | |
| 512 | /** |
| 513 | * @return string service id. |
| 514 | */ |
| 515 | public function getServiceID() |
| 516 | { |
| 517 | return $this->_serviceID; |
| 518 | } |
| 519 | |
| 520 | /** |
| 521 | * @return string url pattern to match. Defaults to ''. |
| 522 | */ |
| 523 | public function getPattern() |
| 524 | { |
| 525 | return $this->_pattern; |
| 526 | } |
| 527 | |
| 528 | /** |
| 529 | * @param string url pattern to match. |
| 530 | */ |
| 531 | public function setPattern($value) |
| 532 | { |
| 533 | $this->_pattern = $value; |
| 534 | } |
| 535 | |
| 536 | /** |
| 537 | * @return TAttributeCollection parameter key value pairs. |
| 538 | */ |
| 539 | public function getParameters() |
| 540 | { |
| 541 | return $this->_parameters; |
| 542 | } |
| 543 | |
| 544 | /** |
| 545 | * @param TAttributeCollection new parameter key value pairs. |
| 546 | */ |
| 547 | public function setParameters($value) |
| 548 | { |
| 549 | $this->_parameters=$value; |
| 550 | } |
| 551 | |
| 552 | /** |
| 553 | * Uses URL pattern (or full regular expression if available) to |
| 554 | * match the given url path. |
| 555 | * @param THttpRequest the request module |
| 556 | * @return array matched parameters, empty if no matches. |
| 557 | */ |
| 558 | public function getPatternMatches($request) |
| 559 | { |
| 560 | $matches=array(); |
| 561 | if(($pattern=$this->getRegularExpression())!=='') |
| 562 | preg_match($pattern,$request->getPathInfo(),$matches); |
| 563 | else |
| 564 | preg_match($this->getParameterizedPattern(),trim($request->getPathInfo(),'/').'/',$matches); |
| 565 | return $matches; |
| 566 | } |
| 567 | |
| 568 | /** |
| 569 | * Returns a value indicating whether to use this pattern to construct URL. |
| 570 | * @return boolean whether to enable custom constructUrl. Defaults to true. |
| 571 | * @since 3.1.1 |
| 572 | */ |
| 573 | public function getEnableCustomUrl() |
| 574 | { |
| 575 | return $this->_customUrl; |
| 576 | } |
| 577 | |
| 578 | /** |
| 579 | * Sets a value indicating whether to enable custom constructUrl using this pattern |
| 580 | * @param boolean whether to enable custom constructUrl. |
| 581 | */ |
| 582 | public function setEnableCustomUrl($value) |
| 583 | { |
| 584 | $this->_customUrl=TPropertyValue::ensureBoolean($value); |
| 585 | } |
| 586 | |
| 587 | /** |
| 588 | * @param array list of GET items to be put in the constructed URL |
| 589 | * @return boolean whether this pattern IS the one for constructing the URL with the specified GET items. |
| 590 | * @since 3.1.1 |
| 591 | */ |
| 592 | public function supportCustomUrl($getItems) |
| 593 | { |
| 594 | if(!$this->_customUrl || $this->getPattern()===null) |
| 595 | return false; |
| 596 | foreach($this->_parameters as $key=>$value) |
| 597 | { |
| 598 | if(!isset($getItems[$key])) |
| 599 | return false; |
| 600 | } |
| 601 | return true; |
| 602 | } |
| 603 | |
| 604 | /** |
| 605 | * Constructs a URL using this pattern. |
| 606 | * @param array list of GET variables |
| 607 | * @param boolean whether the ampersand should be encoded in the constructed URL |
| 608 | * @param boolean whether the GET variables should be encoded in the constructed URL |
| 609 | * @return string the constructed URL |
| 610 | * @since 3.1.1 |
| 611 | */ |
| 612 | public function constructUrl($getItems,$encodeAmpersand,$encodeGetItems) |
| 613 | { |
| 614 | $extra=array(); |
| 615 | $replace=array(); |
| 616 | // for the GET variables matching the pattern, put them in the URL path |
| 617 | foreach($getItems as $key=>$value) |
| 618 | { |
| 619 | if($encodeGetItems) |
| 620 | $value=rawurlencode($value); |
| 621 | if($this->_parameters->contains($key)) |
| 622 | $replace['{'.$key.'}']=$value; |
| 623 | else |
| 624 | $extra[$key]=$value; |
| 625 | } |
| 626 | |
| 627 | $url=$this->_manager->getUrlPrefix().'/'.ltrim(strtr($this->getPattern(),$replace),'/'); |
| 628 | |
| 629 | // for the rest of the GET variables, put them in the query string |
| 630 | if(count($extra)>0) |
| 631 | { |
| 632 | $url2=''; |
| 633 | $amp=$encodeAmpersand?'&':'&'; |
| 634 | if($encodeGetItems) |
| 635 | { |
| 636 | foreach($extra as $name=>$value) |
| 637 | { |
| 638 | if(is_array($value)) |
| 639 | { |
| 640 | $name=rawurlencode($name.'[]'); |
| 641 | foreach($value as $v) |
| 642 | $url2.=$amp.$name.'='.rawurlencode($v); |
| 643 | } |
| 644 | else |
| 645 | $url2.=$amp.rawurlencode($name).'='.rawurlencode($value); |
| 646 | } |
| 647 | } |
| 648 | else |
| 649 | { |
| 650 | foreach($extra as $name=>$value) |
| 651 | { |
| 652 | if(is_array($value)) |
| 653 | { |
| 654 | foreach($value as $v) |
| 655 | $url2.=$amp.$name.'[]='.$v; |
| 656 | } |
| 657 | else |
| 658 | $url2.=$amp.$name.'='.$value; |
| 659 | } |
| 660 | } |
| 661 | $url=$url.'?'.substr($url2,strlen($amp)); |
| 662 | } |
| 663 | return $url; |
| 664 | } |
| 665 |
