summaryrefslogtreecommitdiff
path: root/framework/Web/TUrlManager.php
blob: 4b86644a6dd13c6ff451aa43a88a310d28f0498a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<?php
/**
 * TUrlManager class file
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.pradosoft.com/
 * @copyright Copyright &copy; 2005-2014 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @package Prado\Web
 */

namespace Prado\Web;

/**
 * TUrlManager class
 *
 * TUrlManager is the base class for managing URLs that can be
 * recognized by PRADO applications. It provides the default implementation
 * for parsing and constructing URLs.
 *
 * Derived classes may override {@link constructUrl} and {@link parseUrl}
 * to provide customized URL schemes.
 *
 * By default, {@link THttpRequest} uses TUrlManager as its URL manager.
 * If you want to use your customized URL manager, load your manager class
 * as an application module and set {@link THttpRequest::setUrlManager THttpRequest.UrlManager}
 * with the ID of your URL manager module.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @package Prado\Web
 * @since 3.0.6
 */
class TUrlManager extends TModule
{
	/**
	 * Constructs a URL that can be recognized by PRADO.
	 *
	 * This method provides the actual implementation used by {@link THttpRequest::constructUrl}.
	 * Override this method if you want to provide your own way of URL formatting.
	 * If you do so, you may also need to override {@link parseUrl} so that the URL can be properly parsed.
	 *
	 * The URL is constructed as the following format:
	 * /entryscript.php?serviceID=serviceParameter&get1=value1&...
	 * If {@link THttpRequest::setUrlFormat THttpRequest.UrlFormat} is 'Path',
	 * the following format is used instead:
	 * /entryscript.php/serviceID/serviceParameter/get1,value1/get2,value2...
	 * If {@link THttpRequest::setUrlFormat THttpRequest.UrlFormat} is 'HiddenPath',
	 * then entryscript.php will be hidden and the following format is used instead:
	 * /serviceID/serviceParameter/get1,value1/get2,value2...
	 * In order to use the 'HiddenPath' format you need proper url rewrite configuration;
	 * here's an example for Apache's .htaccess:
	 * <cdde>
	 * Options +FollowSymLinks
	 * RewriteEngine On
	 * RewriteCond %{REQUEST_FILENAME} !-d
	 * RewriteCond %{REQUEST_FILENAME} !-f
	 * RewriteRule ^(.*)$ index.php/$1 [L]
	 * </code>
	 * @param string service ID
	 * @param string service parameter
	 * @param array GET parameters, null if not provided
	 * @param boolean whether to encode the ampersand in URL
	 * @param boolean whether to encode the GET parameters (their names and values)
	 * @return string URL
	 * @see parseUrl
	 */
	public function constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems)
	{
		$url=$serviceID.'='.urlencode($serviceParam);
		$amp=$encodeAmpersand?'&amp;':'&';
		$request=$this->getRequest();
		if(is_array($getItems) || $getItems instanceof Traversable)
		{
			if($encodeGetItems)
			{
				foreach($getItems as $name=>$value)
				{
					if(is_array($value))
					{
						$name=urlencode($name.'[]');
						foreach($value as $v)
							$url.=$amp.$name.'='.urlencode($v);
					}
					else
						$url.=$amp.urlencode($name).'='.urlencode($value);
				}
			}
			else
			{
				foreach($getItems as $name=>$value)
				{
					if(is_array($value))
					{
						foreach($value as $v)
							$url.=$amp.$name.'[]='.$v;
					}
					else
						$url.=$amp.$name.'='.$value;
				}
			}
		}

		switch($request->getUrlFormat())
		{
			case THttpRequestUrlFormat::Path:
				return $request->getApplicationUrl().'/'.strtr($url,array($amp=>'/','?'=>'/','='=>$request->getUrlParamSeparator()));
			case THttpRequestUrlFormat::HiddenPath:
				return rtrim(dirname($request->getApplicationUrl()), '/').'/'.strtr($url,array($amp=>'/','?'=>'/','='=>$request->getUrlParamSeparator()));
			default:
				return $request->getApplicationUrl().'?'.$url;
		}
	}

	/**
	 * Parses the request URL and returns an array of input parameters.
	 * This method is automatically invoked by {@link THttpRequest} when
	 * handling a user request.
	 *
	 * In general, this method should parse the path info part of the requesting URL
	 * and generate an array of name-value pairs according to some scheme.
	 * The current implementation deals with both 'Get' and 'Path' URL formats.
	 *
	 * You may override this method to support customized URL format.
	 * @return array list of input parameters, indexed by parameter names
	 * @see constructUrl
	 */
	public function parseUrl()
	{
		$request=$this->getRequest();
		$pathInfo=trim($request->getPathInfo(),'/');
		if(($request->getUrlFormat()===THttpRequestUrlFormat::Path ||
			$request->getUrlFormat()===THttpRequestUrlFormat::HiddenPath) &&
			$pathInfo!=='')
		{
			$separator=$request->getUrlParamSeparator();
			$paths=explode('/',$pathInfo);
			$getVariables=array();
			foreach($paths as $path)
			{
				if(($path=trim($path))!=='')
				{
					if(($pos=strpos($path,$separator))!==false)
					{
						$name=substr($path,0,$pos);
						$value=substr($path,$pos+1);
						if(($pos=strpos($name,'[]'))!==false)
							$getVariables[substr($name,0,$pos)][]=$value;
						else
							$getVariables[$name]=$value;
					}
					else
						$getVariables[$path]='';
				}
			}
			return $getVariables;
		}
		else
			return array();
	}
}