diff options
author | xue <> | 2007-08-11 14:30:07 +0000 |
---|---|---|
committer | xue <> | 2007-08-11 14:30:07 +0000 |
commit | 2143fc9d208c82a43cf9ea39f13c724e99f66d16 (patch) | |
tree | d9eb876ca5be488f09e6c188a6c78afa652face5 /framework | |
parent | c93842f81958447d70fd46ad2a6d8b2ac686d34e (diff) |
further enhanced TUrlMapping.
Diffstat (limited to 'framework')
-rw-r--r-- | framework/Exceptions/messages.txt | 6 | ||||
-rw-r--r-- | framework/Web/TUrlMapping.php | 216 |
2 files changed, 106 insertions, 116 deletions
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 372b8501..f4b5678f 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -420,4 +420,8 @@ cachesession_cachemodule_inexistent = TCacheHttpSession.CacheModuleID '{0}' poi cachesession_cachemodule_invalid = TCacheHttpSession.CacheModuleID '{0}' points to a module that does not implement ICache interface. urlmapping_urlmappingpattern_required = TUrlMapping can only contain TUrlMappingPattern or its child classes. -urlmappingpattern_serviceparameter_required = TUrlMappingPattern.ServiceParameter is required for pattern '{0}'.
\ No newline at end of file +urlmapping_global_required = TUrlMapping must be configured as a global module. +urlmapping_configfile_inexistent = TUrlMapping.ConfigFile '{0}' is not a file. +urlmapping_configfile_invalid = TUrlMapping.ConfigFile '{0}' must point to an XML file in namespace format. + +urlmappingpattern_serviceparameter_required = TUrlMappingPattern.ServiceParameter is required for pattern '{0}'. diff --git a/framework/Web/TUrlMapping.php b/framework/Web/TUrlMapping.php index 23c3295b..960f32a3 100644 --- a/framework/Web/TUrlMapping.php +++ b/framework/Web/TUrlMapping.php @@ -16,40 +16,49 @@ Prado::using('System.Collections.TAttributeCollection'); /**
* TUrlMapping Class
*
- * The TUrlMapping module allows aributary URL path to be mapped to a
- * particular service and page class. This module must be configured
- * before a service is initialized, thus this module should be configured
- * globally in the <tt>application.xml</tt> file and before any services.
+ * The TUrlMapping module allows PRADO to construct and recognize URLs
+ * based on specific patterns.
+ *
+ * TUrlMapping consists of a list of URL patterns which are used to match
+ * against the currently requested URL. The first matching pattern will then
+ * be used to decompose the URL into request parameters (accessible through
+ * <code>$this->Request['paramname']</code>).
+ *
+ * The patterns can also be used to construct customized URLs. In this case,
+ * the parameters in an applied pattern will be replaced with the corresponding
+ * GET variable values.
+ *
+ * Since it is derived from {@link TUrlManager}, it should be configured globally
+ * in the application configuration like the following,
* <code>
* <module id="request" class="THttpRequest" UrlManager="friendly-url" />
- * <module id="friendly-url" class="System.Web.TUrlMapping">
- * <url ServiceParameter="Posts.ViewPost" pattern="post/{id}/?" parameters.id="\d+" />
- * <url ServiceParameter="Posts.ListPost" pattern="archive/{time}/?" parameters.time="\d{6}" />
- * <url ServiceParameter="Posts.ListPost" pattern="category/{cat}/?" parameters.cat="\d+" />
+ * <module id="friendly-url" class="System.Web.TUrlMapping" EnableCustomUrl="true">
+ * <url ServiceParameter="Posts.ViewPost" pattern="post/{id}/" parameters.id="\d+" />
+ * <url ServiceParameter="Posts.ListPost" pattern="archive/{time}/" parameters.time="\d{6}" />
+ * <url ServiceParameter="Posts.ListPost" pattern="category/{cat}/" parameters.cat="\d+" />
* </module>
* </code>
*
- * See {@link TUrlMappingPattern} for details regarding the mapping patterns.
- * Similar to other modules, the <tt><url /></tt> configuration class
- * can be customised using the <tt>class</tt> property.
+ * In the above, each <tt><url></tt> element specifies a URL pattern represented
+ * as a {@link TUrlMappingPattern} internally. You may create your own pattern classes
+ * by extending {@link TUrlMappingPattern} and specifying the <tt><class></tt> attribute
+ * in the element.
+ *
+ * The patterns can be also be specified in an external file using the {@link setConfigFile ConfigFile} property.
*
* The URL mapping are evaluated in order, only the first mapping that matches
* the URL will be used. Cascaded mapping can be achieved by placing the URL mappings
* in particular order. For example, placing the most specific mappings first.
*
- * The mapping can be loaded from an external file by specifying a configuration
- * file using the {@link setConfigFile ConfigFile} property.
- *
- * Since TUrlMapping is a URL manager extending from {@link TUrlManager},
- * you may override {@link TUrlManager::constructUrl} to support your pattern-based
- * URL scheme.
+ * Only the PATH_INFO part of the URL is used to match the available patterns. The matching
+ * is strict in the sense that the whole pattern must match the whole PATH_INFO of the URL.
*
- * From PRADO v3.1.1, TUrlMapping also provides support to construct URLs according to
- * the specified the pattern. You may enable this functionality by setting {@link setEnableCustomUrl EnableCustomUrl} to true.
+ * From PRADO v3.1.1, TUrlMapping also provides support for constructing URLs according to
+ * the specified pattern. You may enable this functionality by setting {@link setEnableCustomUrl EnableCustomUrl} to true.
* When you call THttpRequest::constructUrl() (or via TPageService::constructUrl()),
- * TUrlMapping will examine the available URL mapping patterns using their {@link getServiceParameter ServiceParameter}
- * and {@link getPattern Pattern} properties. A pattern is applied if its
- * {@link getServiceParameter ServiceParameter} matches the service parameter passed
+ * TUrlMapping will examine the available URL mapping patterns using their {@link TUrlMappingPattern::getServiceParameter ServiceParameter}
+ * and {@link TUrlMappingPattern::getPattern Pattern} properties. A pattern is applied if its
+ * {@link TUrlMappingPattern::getServiceParameter ServiceParameter} matches the service parameter passed
* to constructUrl() and every parameter in the {@link getPattern Pattern} is found
* in the GET variables.
*
@@ -99,7 +108,7 @@ class TUrlMapping extends TUrlManager {
parent::init($xml);
if($this->getRequest()->getRequestResolved())
- throw new TConfigurationException('urlpath_dispatch_module_must_be_global');
+ throw new TConfigurationException('urlmapping_global_required');
if($this->_configFile!==null)
$this->loadConfigFile();
$this->loadUrlMappings($xml);
@@ -121,8 +130,7 @@ class TUrlMapping extends TUrlManager $this->loadUrlMappings($dom);
}
else
- throw new TConfigurationException(
- 'urlpath_dispatch_configfile_invalid',$this->_configFile);
+ throw new TConfigurationException('urlmapping_configfile_inexistent',$this->_configFile);
}
/**
@@ -130,6 +138,7 @@ class TUrlMapping extends TUrlManager * If true, constructUrl() will make use of the URL mapping rules to
* construct valid URLs.
* @return boolean whether to enable custom constructUrl. Defaults to false.
+ * @since 3.1.1
*/
public function getEnableCustomUrl()
{
@@ -141,6 +150,7 @@ class TUrlMapping extends TUrlManager * If true, constructUrl() will make use of the URL mapping rules to
* construct valid URLs.
* @param boolean whether to enable custom constructUrl.
+ * @since 3.1.1
*/
public function setEnableCustomUrl($value)
{
@@ -149,6 +159,7 @@ class TUrlMapping extends TUrlManager /**
* @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)
+ * @since 3.1.1
*/
public function getUrlPrefix()
{
@@ -158,6 +169,7 @@ class TUrlMapping extends TUrlManager /**
* @param string the part that will be prefixed to the constructed URLs. This is used by constructUrl() when EnableCustomUrl is set true.
* @see getUrlPrefix
+ * @since 3.1.1
*/
public function setUrlPrefix($value)
{
@@ -180,7 +192,7 @@ class TUrlMapping extends TUrlManager public function setConfigFile($value)
{
if(($this->_configFile=Prado::getPathOfNamespace($value,self::CONFIG_FILE_EXT))===null)
- throw new TConfigurationException('urlpath_configfile_invalid',$value);
+ throw new TConfigurationException('urlmapping_configfile_invalid',$value);
}
/**
@@ -216,12 +228,12 @@ class TUrlMapping extends TUrlManager $properties=$url->getAttributes();
if(($class=$properties->remove('class'))===null)
$class=$this->getDefaultMappingClass();
- $pattern = Prado::createComponent($class,$this);
+ $pattern=Prado::createComponent($class,$this);
if(!($pattern instanceof TUrlMappingPattern))
throw new TConfigurationException('urlmapping_urlmappingpattern_required');
foreach($properties as $name=>$value)
$pattern->setSubproperty($name,$value);
- $this->_patterns[] = $pattern;
+ $this->_patterns[]=$pattern;
$pattern->init($url);
$key=$pattern->getServiceID().':'.$pattern->getServiceParameter();
@@ -239,17 +251,19 @@ class TUrlMapping extends TUrlManager */
public function parseUrl()
{
- $url = $this->getRequest()->getUrl();
+ $request=$this->getRequest();
foreach($this->_patterns as $pattern)
{
- $matches = $pattern->getPatternMatches($url);
- if(count($matches) > 0)
+ $matches=$pattern->getPatternMatches($request);
+ if(count($matches)>0)
{
$this->_matched=$pattern;
$params=array();
foreach($matches as $key=>$value)
+ {
if(is_string($key))
$params[$key]=$value;
+ }
$params[$pattern->getServiceID()]=$pattern->getServiceParameter();
return $params;
}
@@ -280,17 +294,18 @@ class TUrlMapping extends TUrlManager */
public function constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems)
{
- if(!$this->_customUrl)
- return parent::constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems);
- if(!(is_array($getItems) || ($getItems instanceof Traversable)))
- $getItems=array();
- $key=$serviceID.':'.$serviceParam;
- if(isset($this->_constructRules[$key]))
+ if($this->_customUrl)
{
- foreach($this->_constructRules[$key] as $rule)
+ if(!(is_array($getItems) || ($getItems instanceof Traversable)))
+ $getItems=array();
+ $key=$serviceID.':'.$serviceParam;
+ if(isset($this->_constructRules[$key]))
{
- if($rule->supportCustomUrl($getItems))
- return $rule->constructUrl($getItems,$encodeAmpersand,$encodeGetItems);
+ foreach($this->_constructRules[$key] as $rule)
+ {
+ if($rule->supportCustomUrl($getItems))
+ return $rule->constructUrl($getItems,$encodeAmpersand,$encodeGetItems);
+ }
}
}
return parent::constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems);
@@ -306,13 +321,16 @@ class TUrlMapping extends TUrlManager }
/**
- * URL Mapping Pattern Class
+ * TUrlMappingPattern class.
*
- * Describes an URL mapping pattern, if a given URL matches the pattern, the
- * TUrlMapping class will alter the THttpRequest parameters. The
- * url matching is done using patterns and regular expressions.
+ * TUrlMappingPattern represents a pattern used to parse and construct URLs.
+ * If the currently requested URL matches the pattern, it will alter
+ * the THttpRequest parameters. If a constructUrl() call matches the pattern
+ * parameters, the pattern will generate a valid URL. In both case, only the PATH_INFO
+ * part of a URL is parsed/constructed using the pattern.
*
- * The {@link setPattern Pattern} property takes an string expression with
+ * To specify the pattern, set the {@link setPattern Pattern} property.
+ * {@link setPattern Pattern} takes a string expression with
* parameter names enclosed between a left brace '{' and a right brace '}'.
* The patterns for each parameter can be set using {@link getParameters Parameters}
* attribute collection. For example
@@ -326,34 +344,27 @@ class TUrlMapping extends TUrlManager * "\d{4}" (4 digits), "\d{2}" (2 digits) and "\d+" (1 or more digits).
* Essentially, the <tt>Parameters</tt> attribute name and values are used
* as substrings in replacing the placeholders in the <tt>Pattern</tt> string
- * to form a complete regular expression string. A full regular expression
- * may be expressed using the <tt>RegularExpression</tt> attribute or
- * as the body content of the <module> tag. The above pattern is equivalent
- * to the following regular expression pattern.
+ * to form a complete regular expression string.
+ *
+ * For more complicated patterns, one may specify the pattern using a regular expression
+ * by {@link setRegularExpression RegularExpression}. For example, the above pattern
+ * is equivalent to the following regular expression-based pattern:
* <code>
- * /articles\/(?P<year>\d{4})\/(?P<month>\d{2})\/(?P<day>\d+)/u
+ * /^articles\/(?P<year>\d{4})\/(?P<month>\d{2})\/(?P<day>\d+)$/u
* </code>
* The above regular expression used the "named group" feature available in PHP.
* Notice that you need to escape the slash in regular expressions.
*
- * In the TUrlMappingPattern class, the pattern is matched against the
- * <b>path</b> property of the url only.
- *
* Thus, only an url that matches the pattern will be valid. For example,
- * an url "<tt>http://example.com/articles/2006/07/21</tt>" will matches and is valid.
- * However, "<tt>http://example.com/articles/2006/07/hello</tt>" is not
- * valid since the "day" parameter pattern is not satisfied.
+ * a URL <tt>http://example.com/index.php/articles/2006/07/21</tt> will match the above pattern,
+ * while <tt>http://example.com/index.php/articles/2006/07/hello</tt> will not
+ * since the "day" parameter pattern is not satisfied.
*
- * The parameter values are available through the standard <tt>Request</tt>
- * object. For example, <tt>$this->Request['year']</tt>.
+ * The parameter values are available through the <tt>THttpRequest</tt> instance (e.g.
+ * <tt>$this->Request['year']</tt>).
*
* The {@link setServiceParameter ServiceParameter} and {@link setServiceID ServiceID}
* (the default ID is 'page') set the service parameter and service id respectively.
- * The service parameter for the TPageService is the Page class name, other service
- * may use the service parameter differently.
- *
- * For more complicated mappings, the body of the <tt><url></tt>
- * can be used to specify the mapping pattern.
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @version $Id$
@@ -382,15 +393,15 @@ class TUrlMappingPattern extends TComponent * @var string regular expression pattern.
*/
private $_regexp='';
- /**
- * @var boolean case sensitive matching, default is true
- */
- private $_caseSensitive=true;
private $_customUrl=true;
private $_manager;
+ /**
+ * Constructor.
+ * @param TUrlManager the URL manager instance
+ */
public function __construct(TUrlManager $manager)
{
$this->_manager=$manager;
@@ -398,20 +409,21 @@ class TUrlMappingPattern extends TComponent $this->_parameters->setCaseSensitive(true);
}
+ /**
+ * @return TUrlManager the URL manager instance
+ */
public function getManager()
{
return $this->_manager;
}
/**
- * Initialize the pattern, uses the body content as pattern is available.
+ * Initializes the pattern.
* @param TXmlElement configuration for this module.
- * @throws TConfigurationException if page class is not specified.
+ * @throws TConfigurationException if service parameter is not specified
*/
public function init($config)
{
- if(($body=trim($config->getValue()))!=='')
- $this->setRegularExpression($body);
if($this->_serviceParameter===null)
throw new TConfigurationException('urlmappingpattern_serviceparameter_required', $this->getPattern());
}
@@ -423,18 +435,17 @@ class TUrlMappingPattern extends TComponent */
protected function getParameterizedPattern()
{
- $params= array();
- $values = array();
- foreach($this->parameters as $key => $value)
+ $params=array();
+ $values=array();
+ foreach($this->_parameters as $key=>$value)
{
- $params[] = '{'.$key.'}';
- $values[] = '(?P<'.$key.'>'.$value.')';
+ $params[]='{'.$key.'}';
+ $values[]='(?P<'.$key.'>'.$value.')';
}
- $params[] = '/';
- $values[] = '\\/';
- $regexp = str_replace($params,$values,$this->getPattern());
- $modifiers = $this->getModifiers();
- return '/'.$regexp.'/'.$modifiers;
+ $params[]='/';
+ $values[]='\\/';
+ $regexp=str_replace($params,$values,trim($this->getPattern(),'/'));
+ return '/^'.$regexp.'$/u';
}
/**
@@ -502,22 +513,6 @@ class TUrlMappingPattern extends TComponent }
/**
- * @param boolean case sensitive pattern matching, default is true.
- */
- public function setCaseSensitive($value)
- {
- $this->_caseSensitive=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * @return boolean case sensitive pattern matching, default is true.
- */
- public function getCaseSensitive()
- {
- return $this->_caseSensitive;
- }
-
- /**
* @return TAttributeCollection parameter key value pairs.
*/
public function getParameters()
@@ -536,30 +531,20 @@ class TUrlMappingPattern extends TComponent /**
* Uses URL pattern (or full regular expression if available) to
* match the given url path.
- * @param TUri url to match against
+ * @param THttpRequest the request module
* @return array matched parameters, empty if no matches.
*/
- public function getPatternMatches($url)
+ public function getPatternMatches($request)
{
$matches=array();
- if(($pattern=$this->getRegularExpression())==='')
- $pattern=$this->getParameterizedPattern();
- preg_match($pattern,$url->getPath(),$matches);
+ if(($pattern=$this->getRegularExpression())!=='')
+ preg_match($pattern,$request->getPathInfo(),$matches);
+ else
+ preg_match($this->getParameterizedPattern(),trim($request->getPathInfo(),'/'),$matches);
return $matches;
}
/**
- * @return string regular expression matching modifiers.
- */
- protected function getModifiers()
- {
- $modifiers = 'u';
- if(!$this->getCaseSensitive())
- $modifiers .= 'i';
- return $modifiers;
- }
-
- /**
* Returns a value indicating whether to use this pattern to construct URL.
* @return boolean whether to enable custom constructUrl. Defaults to true.
* @since 3.1.1
@@ -588,9 +573,10 @@ class TUrlMappingPattern extends TComponent if(!$this->_customUrl || $this->getPattern()==='')
return false;
foreach($this->_parameters as $key=>$value)
+ {
if(!isset($getItems[$key]))
return false;
-
+ }
return true;
}
@@ -617,7 +603,7 @@ class TUrlMappingPattern extends TComponent $extra[$key]=$value;
}
- $url=$this->_manager->getUrlPrefix().'/'.trim(strtr($this->getPattern(),$replace),'/');
+ $url=$this->_manager->getUrlPrefix().'/'.ltrim(strtr($this->getPattern(),$replace),'/');
// for the rest of the GET variables, put them in the query string
if(count($extra)>0)
|