Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • Net
  • None
  • PHP
  • system
    • base
    • caching
      • dependencies
    • collections
    • console
    • db
      • ar
      • schema
        • cubrid
        • mssql
        • mysql
        • oci
        • pgsql
        • sqlite
    • i18n
      • gettext
    • logging
    • test
    • utils
    • validators
    • web
      • actions
      • auth
      • filters
      • form
      • helpers
      • renderers
      • services
      • widgets
        • captcha
        • pagers
  • Text
    • Highlighter
  • zii
    • behaviors
    • widgets
      • grid
      • jui

Classes

  • ActionFormModelBase
  • CActiveDataProvider
  • CalendarEventFormModel
  • CallFormModel
  • CArrayDataProvider
  • CAssetManager
  • CBaseController
  • CBaseUrlRule
  • CCacheHttpSession
  • CClientScript
  • CController
  • CCookieCollection
  • CDataProvider
  • CDataProviderIterator
  • CDbHttpSession
  • CExtController
  • CFormModel
  • CHttpCookie
  • CHttpRequest
  • CHttpSession
  • CHttpSessionIterator
  • COutputEvent
  • CPagination
  • CreatePageFormModel
  • CSort
  • CSqlDataProvider
  • CTheme
  • CThemeManager
  • CUploadedFile
  • CUrlManager
  • CUrlRule
  • CWebApplication
  • CWebModule
  • CWidgetFactory
  • EditMobileFormsFormModel
  • EventCommentPublisherFormModel
  • EventFormModel
  • EventPublisherFormModel
  • FileSystemObjectDataProvider
  • MassActionFormModel
  • MobilePagination
  • NoteFormModel
  • NotificationsController
  • TimeFormModel
  • UploadLogoFormModel
  • X2FormModel
  • X2HttpRequest

Interfaces

  • IDataProvider
  • IWidgetFactory
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * CUrlManager class file
  4:  *
  5:  * @author Qiang Xue <qiang.xue@gmail.com>
  6:  * @link http://www.yiiframework.com/
  7:  * @copyright 2008-2013 Yii Software LLC
  8:  * @license http://www.yiiframework.com/license/
  9:  */
 10: 
 11: /**
 12:  * CUrlManager manages the URLs of Yii Web applications.
 13:  *
 14:  * It provides URL construction ({@link createUrl()}) as well as parsing ({@link parseUrl()}) functionality.
 15:  *
 16:  * URLs managed via CUrlManager can be in one of the following two formats,
 17:  * by setting {@link setUrlFormat urlFormat} property:
 18:  * <ul>
 19:  * <li>'path' format: /path/to/EntryScript.php/name1/value1/name2/value2...</li>
 20:  * <li>'get' format:  /path/to/EntryScript.php?name1=value1&name2=value2...</li>
 21:  * </ul>
 22:  *
 23:  * When using 'path' format, CUrlManager uses a set of {@link setRules rules} to:
 24:  * <ul>
 25:  * <li>parse the requested URL into a route ('ControllerID/ActionID') and GET parameters;</li>
 26:  * <li>create URLs based on the given route and GET parameters.</li>
 27:  * </ul>
 28:  *
 29:  * A rule consists of a route and a pattern. The latter is used by CUrlManager to determine
 30:  * which rule is used for parsing/creating URLs. A pattern is meant to match the path info
 31:  * part of a URL. It may contain named parameters using the syntax '&lt;ParamName:RegExp&gt;'.
 32:  *
 33:  * When parsing a URL, a matching rule will extract the named parameters from the path info
 34:  * and put them into the $_GET variable; when creating a URL, a matching rule will extract
 35:  * the named parameters from $_GET and put them into the path info part of the created URL.
 36:  *
 37:  * If a pattern ends with '/*', it means additional GET parameters may be appended to the path
 38:  * info part of the URL; otherwise, the GET parameters can only appear in the query string part.
 39:  *
 40:  * To specify URL rules, set the {@link setRules rules} property as an array of rules (pattern=>route).
 41:  * For example,
 42:  * <pre>
 43:  * array(
 44:  *     'articles'=>'article/list',
 45:  *     'article/<id:\d+>/*'=>'article/read',
 46:  * )
 47:  * </pre>
 48:  * Two rules are specified in the above:
 49:  * <ul>
 50:  * <li>The first rule says that if the user requests the URL '/path/to/index.php/articles',
 51:  *   it should be treated as '/path/to/index.php/article/list'; and vice versa applies
 52:  *   when constructing such a URL.</li>
 53:  * <li>The second rule contains a named parameter 'id' which is specified using
 54:  *   the &lt;ParamName:RegExp&gt; syntax. It says that if the user requests the URL
 55:  *   '/path/to/index.php/article/13', it should be treated as '/path/to/index.php/article/read?id=13';
 56:  *   and vice versa applies when constructing such a URL.</li>
 57:  * </ul>
 58:  *
 59:  * The route part may contain references to named parameters defined in the pattern part.
 60:  * This allows a rule to be applied to different routes based on matching criteria.
 61:  * For example,
 62:  * <pre>
 63:  * array(
 64:  *      '<_c:(post|comment)>/<id:\d+>/<_a:(create|update|delete)>'=>'<_c>/<_a>',
 65:  *      '<_c:(post|comment)>/<id:\d+>'=>'<_c>/view',
 66:  *      '<_c:(post|comment)>s/*'=>'<_c>/list',
 67:  * )
 68:  * </pre>
 69:  * In the above, we use two named parameters '<_c>' and '<_a>' in the route part. The '<_c>'
 70:  * parameter matches either 'post' or 'comment', while the '<_a>' parameter matches an action ID.
 71:  *
 72:  * Like normal rules, these rules can be used for both parsing and creating URLs.
 73:  * For example, using the rules above, the URL '/index.php/post/123/create'
 74:  * would be parsed as the route 'post/create' with GET parameter 'id' being 123.
 75:  * And given the route 'post/list' and GET parameter 'page' being 2, we should get a URL
 76:  * '/index.php/posts/page/2'.
 77:  *
 78:  * It is also possible to include hostname into the rules for parsing and creating URLs.
 79:  * One may extract part of the hostname to be a GET parameter.
 80:  * For example, the URL <code>http://admin.example.com/en/profile</code> may be parsed into GET parameters
 81:  * <code>user=admin</code> and <code>lang=en</code>. On the other hand, rules with hostname may also be used to
 82:  * create URLs with parameterized hostnames.
 83:  *
 84:  * In order to use parameterized hostnames, simply declare URL rules with host info, e.g.:
 85:  * <pre>
 86:  * array(
 87:  *     'http://<user:\w+>.example.com/<lang:\w+>/profile' => 'user/profile',
 88:  * )
 89:  * </pre>
 90:  *
 91:  * Starting from version 1.1.8, one can write custom URL rule classes and use them for one or several URL rules.
 92:  * For example,
 93:  * <pre>
 94:  * array(
 95:  *   // a standard rule
 96:  *   '<action:(login|logout)>' => 'site/<action>',
 97:  *   // a custom rule using data in DB
 98:  *   array(
 99:  *     'class' => 'application.components.MyUrlRule',
100:  *     'connectionID' => 'db',
101:  *   ),
102:  * )
103:  * </pre>
104:  * Please note that the custom URL rule class should extend from {@link CBaseUrlRule} and
105:  * implement the following two methods,
106:  * <ul>
107:  *    <li>{@link CBaseUrlRule::createUrl()}</li>
108:  *    <li>{@link CBaseUrlRule::parseUrl()}</li>
109:  * </ul>
110:  *
111:  * CUrlManager is a default application component that may be accessed via
112:  * {@link CWebApplication::getUrlManager()}.
113:  *
114:  * @property string $baseUrl The base URL of the application (the part after host name and before query string).
115:  * If {@link showScriptName} is true, it will include the script name part.
116:  * Otherwise, it will not, and the ending slashes are stripped off.
117:  * @property string $urlFormat The URL format. Defaults to 'path'. Valid values include 'path' and 'get'.
118:  * Please refer to the guide for more details about the difference between these two formats.
119:  *
120:  * @author Qiang Xue <qiang.xue@gmail.com>
121:  * @package system.web
122:  * @since 1.0
123:  */
124: class CUrlManager extends CApplicationComponent
125: {
126:     const CACHE_KEY='Yii.CUrlManager.rules';
127:     const GET_FORMAT='get';
128:     const PATH_FORMAT='path';
129: 
130:     /**
131:      * @var array the URL rules (pattern=>route).
132:      */
133:     public $rules=array();
134:     /**
135:      * @var string the URL suffix used when in 'path' format.
136:      * For example, ".html" can be used so that the URL looks like pointing to a static HTML page. Defaults to empty.
137:      */
138:     public $urlSuffix='';
139:     /**
140:      * @var boolean whether to show entry script name in the constructed URL. Defaults to true.
141:      */
142:     public $showScriptName=true;
143:     /**
144:      * @var boolean whether to append GET parameters to the path info part. Defaults to true.
145:      * This property is only effective when {@link urlFormat} is 'path' and is mainly used when
146:      * creating URLs. When it is true, GET parameters will be appended to the path info and
147:      * separate from each other using slashes. If this is false, GET parameters will be in query part.
148:      */
149:     public $appendParams=true;
150:     /**
151:      * @var string the GET variable name for route. Defaults to 'r'.
152:      */
153:     public $routeVar='r';
154:     /**
155:      * @var boolean whether routes are case-sensitive. Defaults to true. By setting this to false,
156:      * the route in the incoming request will be turned to lower case first before further processing.
157:      * As a result, you should follow the convention that you use lower case when specifying
158:      * controller mapping ({@link CWebApplication::controllerMap}) and action mapping
159:      * ({@link CController::actions}). Also, the directory names for organizing controllers should
160:      * be in lower case.
161:      */
162:     public $caseSensitive=true;
163:     /**
164:      * @var boolean whether the GET parameter values should match the corresponding
165:      * sub-patterns in a rule before using it to create a URL. Defaults to false, meaning
166:      * a rule will be used for creating a URL only if its route and parameter names match the given ones.
167:      * If this property is set true, then the given parameter values must also match the corresponding
168:      * parameter sub-patterns. Note that setting this property to true will degrade performance.
169:      * @since 1.1.0
170:      */
171:     public $matchValue=false;
172:     /**
173:      * @var string the ID of the cache application component that is used to cache the parsed URL rules.
174:      * Defaults to 'cache' which refers to the primary cache application component.
175:      * Set this property to false if you want to disable caching URL rules.
176:      */
177:     public $cacheID='cache';
178:     /**
179:      * @var boolean whether to enable strict URL parsing.
180:      * This property is only effective when {@link urlFormat} is 'path'.
181:      * If it is set true, then an incoming URL must match one of the {@link rules URL rules}.
182:      * Otherwise, it will be treated as an invalid request and trigger a 404 HTTP exception.
183:      * Defaults to false.
184:      */
185:     public $useStrictParsing=false;
186:     /**
187:      * @var string the class name or path alias for the URL rule instances. Defaults to 'CUrlRule'.
188:      * If you change this to something else, please make sure that the new class must extend from
189:      * {@link CBaseUrlRule} and have the same constructor signature as {@link CUrlRule}.
190:      * It must also be serializable and autoloadable.
191:      * @since 1.1.8
192:      */
193:     public $urlRuleClass='CUrlRule';
194: 
195:     private $_urlFormat=self::GET_FORMAT;
196:     private $_rules=array();
197:     private $_baseUrl;
198: 
199: 
200:     /**
201:      * Initializes the application component.
202:      */
203:     public function init()
204:     {
205:         parent::init();
206:         $this->processRules();
207:     }
208: 
209:     /**
210:      * Processes the URL rules.
211:      */
212:     protected function processRules()
213:     {
214:         if(empty($this->rules) || $this->getUrlFormat()===self::GET_FORMAT)
215:             return;
216:         if($this->cacheID!==false && ($cache=Yii::app()->getComponent($this->cacheID))!==null)
217:         {
218:             $hash=md5(serialize($this->rules));
219:             if(($data=$cache->get(self::CACHE_KEY))!==false && isset($data[1]) && $data[1]===$hash)
220:             {
221:                 $this->_rules=$data[0];
222:                 return;
223:             }
224:         }
225:         foreach($this->rules as $pattern=>$route)
226:             $this->_rules[]=$this->createUrlRule($route,$pattern);
227:         if(isset($cache))
228:             $cache->set(self::CACHE_KEY,array($this->_rules,$hash));
229:     }
230: 
231:     /**
232:      * Adds new URL rules.
233:      * In order to make the new rules effective, this method must be called BEFORE
234:      * {@link CWebApplication::processRequest}.
235:      * @param array $rules new URL rules (pattern=>route).
236:      * @param boolean $append whether the new URL rules should be appended to the existing ones. If false,
237:      * they will be inserted at the beginning.
238:      * @since 1.1.4
239:      */
240:     public function addRules($rules,$append=true)
241:     {
242:         if ($append)
243:         {
244:             foreach($rules as $pattern=>$route)
245:                 $this->_rules[]=$this->createUrlRule($route,$pattern);
246:         }
247:         else
248:         {
249:             $rules=array_reverse($rules);
250:             foreach($rules as $pattern=>$route)
251:                 array_unshift($this->_rules, $this->createUrlRule($route,$pattern));
252:         }
253:     }
254: 
255:     /**
256:      * Creates a URL rule instance.
257:      * The default implementation returns a CUrlRule object.
258:      * @param mixed $route the route part of the rule. This could be a string or an array
259:      * @param string $pattern the pattern part of the rule
260:      * @return CUrlRule the URL rule instance
261:      * @since 1.1.0
262:      */
263:     protected function createUrlRule($route,$pattern)
264:     {
265:         if(is_array($route) && isset($route['class']))
266:             return $route;
267:         else
268:         {
269:             $urlRuleClass=Yii::import($this->urlRuleClass,true);
270:             return new $urlRuleClass($route,$pattern);
271:         }
272:     }
273: 
274:     /**
275:      * Constructs a URL.
276:      * @param string $route the controller and the action (e.g. article/read)
277:      * @param array $params list of GET parameters (name=>value). Both the name and value will be URL-encoded.
278:      * If the name is '#', the corresponding value will be treated as an anchor
279:      * and will be appended at the end of the URL.
280:      * @param string $ampersand the token separating name-value pairs in the URL. Defaults to '&'.
281:      * @return string the constructed URL
282:      */
283:     public function createUrl($route,$params=array(),$ampersand='&')
284:     {
285:         unset($params[$this->routeVar]);
286:         foreach($params as $i=>$param)
287:             if($param===null)
288:                 $params[$i]='';
289: 
290:         if(isset($params['#']))
291:         {
292:             $anchor='#'.$params['#'];
293:             unset($params['#']);
294:         }
295:         else
296:             $anchor='';
297:         $route=trim($route,'/');
298:         foreach($this->_rules as $i=>$rule)
299:         {
300:             if(is_array($rule))
301:                 $this->_rules[$i]=$rule=Yii::createComponent($rule);
302:             if(($url=$rule->createUrl($this,$route,$params,$ampersand))!==false)
303:             {
304:                 if($rule->hasHostInfo)
305:                     return $url==='' ? '/'.$anchor : $url.$anchor;
306:                 else
307:                     return $this->getBaseUrl().'/'.$url.$anchor;
308:             }
309:         }
310:         return $this->createUrlDefault($route,$params,$ampersand).$anchor;
311:     }
312: 
313:     /**
314:      * Creates a URL based on default settings.
315:      * @param string $route the controller and the action (e.g. article/read)
316:      * @param array $params list of GET parameters
317:      * @param string $ampersand the token separating name-value pairs in the URL.
318:      * @return string the constructed URL
319:      */
320:     protected function createUrlDefault($route,$params,$ampersand)
321:     {
322:         if($this->getUrlFormat()===self::PATH_FORMAT)
323:         {
324:             $url=rtrim($this->getBaseUrl().'/'.$route,'/');
325:             if($this->appendParams)
326:             {
327:                 $url=rtrim($url.'/'.$this->createPathInfo($params,'/','/'),'/');
328:                 return $route==='' ? $url : $url.$this->urlSuffix;
329:             }
330:             else
331:             {
332:                 if($route!=='')
333:                     $url.=$this->urlSuffix;
334:                 $query=$this->createPathInfo($params,'=',$ampersand);
335:                 return $query==='' ? $url : $url.'?'.$query;
336:             }
337:         }
338:         else
339:         {
340:             $url=$this->getBaseUrl();
341:             if(!$this->showScriptName)
342:                 $url.='/';
343:             if($route!=='')
344:             {
345:                 $url.='?'.$this->routeVar.'='.$route;
346:                 if(($query=$this->createPathInfo($params,'=',$ampersand))!=='')
347:                     $url.=$ampersand.$query;
348:             }
349:             elseif(($query=$this->createPathInfo($params,'=',$ampersand))!=='')
350:                 $url.='?'.$query;
351:             return $url;
352:         }
353:     }
354: 
355:     /**
356:      * Parses the user request.
357:      * @param CHttpRequest $request the request application component
358:      * @return string the route (controllerID/actionID) and perhaps GET parameters in path format.
359:      */
360:     public function parseUrl($request)
361:     {
362:         if($this->getUrlFormat()===self::PATH_FORMAT)
363:         {
364:             $rawPathInfo=$request->getPathInfo();
365:             $pathInfo=$this->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
366:             foreach($this->_rules as $i=>$rule)
367:             {
368:                 if(is_array($rule))
369:                     $this->_rules[$i]=$rule=Yii::createComponent($rule);
370:                 if(($r=$rule->parseUrl($this,$request,$pathInfo,$rawPathInfo))!==false)
371:                     return isset($_GET[$this->routeVar]) ? $_GET[$this->routeVar] : $r;
372:             }
373:             if($this->useStrictParsing)
374:                 throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
375:                     array('{route}'=>$pathInfo)));
376:             else
377:                 return $pathInfo;
378:         }
379:         elseif(isset($_GET[$this->routeVar]))
380:             return $_GET[$this->routeVar];
381:         elseif(isset($_POST[$this->routeVar]))
382:             return $_POST[$this->routeVar];
383:         else
384:             return '';
385:     }
386: 
387:     /**
388:      * Parses a path info into URL segments and saves them to $_GET and $_REQUEST.
389:      * @param string $pathInfo path info
390:      */
391:     public function parsePathInfo($pathInfo)
392:     {
393:         if($pathInfo==='')
394:             return;
395:         $segs=explode('/',$pathInfo.'/');
396:         $n=count($segs);
397:         for($i=0;$i<$n-1;$i+=2)
398:         {
399:             $key=$segs[$i];
400:             if($key==='') continue;
401:             $value=$segs[$i+1];
402:             if(($pos=strpos($key,'['))!==false && ($m=preg_match_all('/\[(.*?)\]/',$key,$matches))>0)
403:             {
404:                 $name=substr($key,0,$pos);
405:                 for($j=$m-1;$j>=0;--$j)
406:                 {
407:                     if($matches[1][$j]==='')
408:                         $value=array($value);
409:                     else
410:                         $value=array($matches[1][$j]=>$value);
411:                 }
412:                 if(isset($_GET[$name]) && is_array($_GET[$name]))
413:                     $value=CMap::mergeArray($_GET[$name],$value);
414:                 $_REQUEST[$name]=$_GET[$name]=$value;
415:             }
416:             else
417:                 $_REQUEST[$key]=$_GET[$key]=$value;
418:         }
419:     }
420: 
421:     /**
422:      * Creates a path info based on the given parameters.
423:      * @param array $params list of GET parameters
424:      * @param string $equal the separator between name and value
425:      * @param string $ampersand the separator between name-value pairs
426:      * @param string $key this is used internally.
427:      * @return string the created path info
428:      */
429:     public function createPathInfo($params,$equal,$ampersand, $key=null)
430:     {
431:         $pairs = array();
432:         foreach($params as $k => $v)
433:         {
434:             if ($key!==null)
435:                 $k = $key.'['.$k.']';
436: 
437:             if (is_array($v))
438:                 $pairs[]=$this->createPathInfo($v,$equal,$ampersand, $k);
439:             else
440:                 $pairs[]=urlencode($k).$equal.urlencode($v);
441:         }
442:         return implode($ampersand,$pairs);
443:     }
444: 
445:     /**
446:      * Removes the URL suffix from path info.
447:      * @param string $pathInfo path info part in the URL
448:      * @param string $urlSuffix the URL suffix to be removed
449:      * @return string path info with URL suffix removed.
450:      */
451:     public function removeUrlSuffix($pathInfo,$urlSuffix)
452:     {
453:         if($urlSuffix!=='' && substr($pathInfo,-strlen($urlSuffix))===$urlSuffix)
454:             return substr($pathInfo,0,-strlen($urlSuffix));
455:         else
456:             return $pathInfo;
457:     }
458: 
459:     /**
460:      * Returns the base URL of the application.
461:      * @return string the base URL of the application (the part after host name and before query string).
462:      * If {@link showScriptName} is true, it will include the script name part.
463:      * Otherwise, it will not, and the ending slashes are stripped off.
464:      */
465:     public function getBaseUrl()
466:     {
467:         if($this->_baseUrl!==null)
468:             return $this->_baseUrl;
469:         else
470:         {
471:             if($this->showScriptName)
472:                 $this->_baseUrl=Yii::app()->getRequest()->getScriptUrl();
473:             else
474:                 $this->_baseUrl=Yii::app()->getRequest()->getBaseUrl();
475:             return $this->_baseUrl;
476:         }
477:     }
478: 
479:     /**
480:      * Sets the base URL of the application (the part after host name and before query string).
481:      * This method is provided in case the {@link baseUrl} cannot be determined automatically.
482:      * The ending slashes should be stripped off. And you are also responsible to remove the script name
483:      * if you set {@link showScriptName} to be false.
484:      * @param string $value the base URL of the application
485:      * @since 1.1.1
486:      */
487:     public function setBaseUrl($value)
488:     {
489:         $this->_baseUrl=$value;
490:     }
491: 
492:     /**
493:      * Returns the URL format.
494:      * @return string the URL format. Defaults to 'path'. Valid values include 'path' and 'get'.
495:      * Please refer to the guide for more details about the difference between these two formats.
496:      */
497:     public function getUrlFormat()
498:     {
499:         return $this->_urlFormat;
500:     }
501: 
502:     /**
503:      * Sets the URL format.
504:      * @param string $value the URL format. It must be either 'path' or 'get'.
505:      */
506:     public function setUrlFormat($value)
507:     {
508:         if($value===self::PATH_FORMAT || $value===self::GET_FORMAT)
509:             $this->_urlFormat=$value;
510:         else
511:             throw new CException(Yii::t('yii','CUrlManager.UrlFormat must be either "path" or "get".'));
512:     }
513: }
514: 
515: 
516: /**
517:  * CBaseUrlRule is the base class for a URL rule class.
518:  *
519:  * Custom URL rule classes should extend from this class and implement two methods:
520:  * {@link createUrl} and {@link parseUrl}.
521:  *
522:  * @author Qiang Xue <qiang.xue@gmail.com>
523:  * @package system.web
524:  * @since 1.1.8
525:  */
526: abstract class CBaseUrlRule extends CComponent
527: {
528:     /**
529:      * @var boolean whether this rule will also parse the host info part. Defaults to false.
530:      */
531:     public $hasHostInfo=false;
532:     /**
533:      * Creates a URL based on this rule.
534:      * @param CUrlManager $manager the manager
535:      * @param string $route the route
536:      * @param array $params list of parameters (name=>value) associated with the route
537:      * @param string $ampersand the token separating name-value pairs in the URL.
538:      * @return mixed the constructed URL. False if this rule does not apply.
539:      */
540:     abstract public function createUrl($manager,$route,$params,$ampersand);
541:     /**
542:      * Parses a URL based on this rule.
543:      * @param CUrlManager $manager the URL manager
544:      * @param CHttpRequest $request the request object
545:      * @param string $pathInfo path info part of the URL (URL suffix is already removed based on {@link CUrlManager::urlSuffix})
546:      * @param string $rawPathInfo path info that contains the potential URL suffix
547:      * @return mixed the route that consists of the controller ID and action ID. False if this rule does not apply.
548:      */
549:     abstract public function parseUrl($manager,$request,$pathInfo,$rawPathInfo);
550: }
551: 
552: /**
553:  * CUrlRule represents a URL formatting/parsing rule.
554:  *
555:  * It mainly consists of two parts: route and pattern. The former classifies
556:  * the rule so that it only applies to specific controller-action route.
557:  * The latter performs the actual formatting and parsing role. The pattern
558:  * may have a set of named parameters.
559:  *
560:  * @author Qiang Xue <qiang.xue@gmail.com>
561:  * @package system.web
562:  * @since 1.0
563:  */
564: class CUrlRule extends CBaseUrlRule
565: {
566:     /**
567:      * @var string the URL suffix used for this rule.
568:      * For example, ".html" can be used so that the URL looks like pointing to a static HTML page.
569:      * Defaults to null, meaning using the value of {@link CUrlManager::urlSuffix}.
570:      */
571:     public $urlSuffix;
572:     /**
573:      * @var boolean whether the rule is case sensitive. Defaults to null, meaning
574:      * using the value of {@link CUrlManager::caseSensitive}.
575:      */
576:     public $caseSensitive;
577:     /**
578:      * @var array the default GET parameters (name=>value) that this rule provides.
579:      * When this rule is used to parse the incoming request, the values declared in this property
580:      * will be injected into $_GET.
581:      */
582:     public $defaultParams=array();
583:     /**
584:      * @var boolean whether the GET parameter values should match the corresponding
585:      * sub-patterns in the rule when creating a URL. Defaults to null, meaning using the value
586:      * of {@link CUrlManager::matchValue}. When this property is false, it means
587:      * a rule will be used for creating a URL if its route and parameter names match the given ones.
588:      * If this property is set true, then the given parameter values must also match the corresponding
589:      * parameter sub-patterns. Note that setting this property to true will degrade performance.
590:      * @since 1.1.0
591:      */
592:     public $matchValue;
593:     /**
594:      * @var string the HTTP verb (e.g. GET, POST, DELETE) that this rule should match.
595:      * If this rule can match multiple verbs, please separate them with commas.
596:      * If this property is not set, the rule can match any verb.
597:      * Note that this property is only used when parsing a request. It is ignored for URL creation.
598:      * @since 1.1.7
599:      */
600:     public $verb;
601:     /**
602:      * @var boolean whether this rule is only used for request parsing.
603:      * Defaults to false, meaning the rule is used for both URL parsing and creation.
604:      * @since 1.1.7
605:      */
606:     public $parsingOnly=false;
607:     /**
608:      * @var string the controller/action pair
609:      */
610:     public $route;
611:     /**
612:      * @var array the mapping from route param name to token name (e.g. _r1=><1>)
613:      */
614:     public $references=array();
615:     /**
616:      * @var string the pattern used to match route
617:      */
618:     public $routePattern;
619:     /**
620:      * @var string regular expression used to parse a URL
621:      */
622:     public $pattern;
623:     /**
624:      * @var string template used to construct a URL
625:      */
626:     public $template;
627:     /**
628:      * @var array list of parameters (name=>regular expression)
629:      */
630:     public $params=array();
631:     /**
632:      * @var boolean whether the URL allows additional parameters at the end of the path info.
633:      */
634:     public $append;
635:     /**
636:      * @var boolean whether host info should be considered for this rule
637:      */
638:     public $hasHostInfo;
639: 
640:     /**
641:      * Constructor.
642:      * @param string $route the route of the URL (controller/action)
643:      * @param string $pattern the pattern for matching the URL
644:      */
645:     public function __construct($route,$pattern)
646:     {
647:         if(is_array($route))
648:         {
649:             foreach(array('urlSuffix', 'caseSensitive', 'defaultParams', 'matchValue', 'verb', 'parsingOnly') as $name)
650:             {
651:                 if(isset($route[$name]))
652:                     $this->$name=$route[$name];
653:             }
654:             if(isset($route['pattern']))
655:                 $pattern=$route['pattern'];
656:             $route=$route[0];
657:         }
658:         $this->route=trim($route,'/');
659: 
660:         $tr2['/']=$tr['/']='\\/';
661:         $tr['.']='\\.';
662: 
663:         if(strpos($route,'<')!==false && preg_match_all('/<(\w+)>/',$route,$matches2))
664:         {
665:             foreach($matches2[1] as $name)
666:                 $this->references[$name]="<$name>";
667:         }
668: 
669:         $this->hasHostInfo=!strncasecmp($pattern,'http://',7) || !strncasecmp($pattern,'https://',8);
670: 
671:         if($this->verb!==null)
672:             $this->verb=preg_split('/[\s,]+/',strtoupper($this->verb),-1,PREG_SPLIT_NO_EMPTY);
673: 
674:         if(preg_match_all('/<(\w+):?(.*?)?>/',$pattern,$matches))
675:         {
676:             $tokens=array_combine($matches[1],$matches[2]);
677:             foreach($tokens as $name=>$value)
678:             {
679:                 if($value==='')
680:                     $value='[^\/]+';
681:                 $tr["<$name>"]="(?P<$name>$value)";
682:                 if(isset($this->references[$name]))
683:                     $tr2["<$name>"]=$tr["<$name>"];
684:                 else
685:                     $this->params[$name]=$value;
686:             }
687:         }
688:         $p=rtrim($pattern,'*');
689:         $this->append=$p!==$pattern;
690:         $p=trim($p,'/');
691:         $this->template=preg_replace('/<(\w+):?.*?>/','<$1>',$p);
692:         $this->pattern='/^'.strtr($this->template,$tr).'\/';
693:         if($this->append)
694:             $this->pattern.='/u';
695:         else
696:             $this->pattern.='$/u';
697: 
698:         if($this->references!==array())
699:             $this->routePattern='/^'.strtr($this->route,$tr2).'$/u';
700: 
701:         if(YII_DEBUG && @preg_match($this->pattern,'test')===false)
702:             throw new CException(Yii::t('yii','The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.',
703:                 array('{route}'=>$route,'{pattern}'=>$pattern)));
704:     }
705: 
706:     /**
707:      * Creates a URL based on this rule.
708:      * @param CUrlManager $manager the manager
709:      * @param string $route the route
710:      * @param array $params list of parameters
711:      * @param string $ampersand the token separating name-value pairs in the URL.
712:      * @return mixed the constructed URL or false on error
713:      */
714:     public function createUrl($manager,$route,$params,$ampersand)
715:     {
716:         if($this->parsingOnly)
717:             return false;
718: 
719:         if($manager->caseSensitive && $this->caseSensitive===null || $this->caseSensitive)
720:             $case='';
721:         else
722:             $case='i';
723: 
724:         $tr=array();
725:         if($route!==$this->route)
726:         {
727:             if($this->routePattern!==null && preg_match($this->routePattern.$case,$route,$matches))
728:             {
729:                 foreach($this->references as $key=>$name)
730:                     $tr[$name]=$matches[$key];
731:             }
732:             else
733:                 return false;
734:         }
735: 
736:         foreach($this->defaultParams as $key=>$value)
737:         {
738:             if(isset($params[$key]))
739:             {
740:                 if($params[$key]==$value)
741:                     unset($params[$key]);
742:                 else
743:                     return false;
744:             }
745:         }
746: 
747:         foreach($this->params as $key=>$value)
748:             if(!isset($params[$key]))
749:                 return false;
750: 
751:         if($manager->matchValue && $this->matchValue===null || $this->matchValue)
752:         {
753:             foreach($this->params as $key=>$value)
754:             {
755:                 if(!preg_match('/\A'.$value.'\z/u'.$case,$params[$key]))
756:                     return false;
757:             }
758:         }
759: 
760:         foreach($this->params as $key=>$value)
761:         {
762:             $tr["<$key>"]=urlencode($params[$key]);
763:             unset($params[$key]);
764:         }
765: 
766:         $suffix=$this->urlSuffix===null ? $manager->urlSuffix : $this->urlSuffix;
767: 
768:         $url=strtr($this->template,$tr);
769: 
770:         if($this->hasHostInfo)
771:         {
772:             $hostInfo=Yii::app()->getRequest()->getHostInfo();
773:             if(stripos($url,$hostInfo)===0)
774:                 $url=substr($url,strlen($hostInfo));
775:         }
776: 
777:         if(empty($params))
778:             return $url!=='' ? $url.$suffix : $url;
779: 
780:         if($this->append)
781:             $url.='/'.$manager->createPathInfo($params,'/','/').$suffix;
782:         else
783:         {
784:             if($url!=='')
785:                 $url.=$suffix;
786:             $url.='?'.$manager->createPathInfo($params,'=',$ampersand);
787:         }
788: 
789:         return $url;
790:     }
791: 
792:     /**
793:      * Parses a URL based on this rule.
794:      * @param CUrlManager $manager the URL manager
795:      * @param CHttpRequest $request the request object
796:      * @param string $pathInfo path info part of the URL
797:      * @param string $rawPathInfo path info that contains the potential URL suffix
798:      * @return mixed the route that consists of the controller ID and action ID or false on error
799:      */
800:     public function parseUrl($manager,$request,$pathInfo,$rawPathInfo)
801:     {
802:         if($this->verb!==null && !in_array($request->getRequestType(), $this->verb, true))
803:             return false;
804: 
805:         if($manager->caseSensitive && $this->caseSensitive===null || $this->caseSensitive)
806:             $case='';
807:         else
808:             $case='i';
809: 
810:         if($this->urlSuffix!==null)
811:             $pathInfo=$manager->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
812: 
813:         // URL suffix required, but not found in the requested URL
814:         if($manager->useStrictParsing && $pathInfo===$rawPathInfo)
815:         {
816:             $urlSuffix=$this->urlSuffix===null ? $manager->urlSuffix : $this->urlSuffix;
817:             if($urlSuffix!='' && $urlSuffix!=='/')
818:                 return false;
819:         }
820: 
821:         if($this->hasHostInfo)
822:             $pathInfo=strtolower($request->getHostInfo()).rtrim('/'.$pathInfo,'/');
823: 
824:         $pathInfo.='/';
825: 
826:         if(preg_match($this->pattern.$case,$pathInfo,$matches))
827:         {
828:             foreach($this->defaultParams as $name=>$value)
829:             {
830:                 if(!isset($_GET[$name]))
831:                     $_REQUEST[$name]=$_GET[$name]=$value;
832:             }
833:             $tr=array();
834:             foreach($matches as $key=>$value)
835:             {
836:                 if(isset($this->references[$key]))
837:                     $tr[$this->references[$key]]=$value;
838:                 elseif(isset($this->params[$key]))
839:                     $_REQUEST[$key]=$_GET[$key]=$value;
840:             }
841:             if($pathInfo!==$matches[0]) // there're additional GET params
842:                 $manager->parsePathInfo(ltrim(substr($pathInfo,strlen($matches[0])),'/'));
843:             if($this->routePattern!==null)
844:                 return strtr($this->route,$tr);
845:             else
846:                 return $this->route;
847:         }
848:         else
849:             return false;
850:     }
851: }
852: 
API documentation generated by ApiGen 2.8.0