Completed
Push — master ( 239c78...0c4744 )
by Fabio
21:35 queued 09:37
created

THttpRequest::getServerSoftware()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * THttpRequest, THttpCookie, THttpCookieCollection, TUri class file
4
 *
5
 * @author Qiang Xue <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 * @package Prado\Web
10
 */
11
12
namespace Prado\Web;
13
use Prado\Collections\TMapIterator;
14
use Prado\Caching\TFileCacheDependency;
15
use Prado\Exceptions\TConfigurationException;
16
use Prado\Exceptions\TInvalidDataValueException;
17
use Prado\Exceptions\TPhpErrorException;
18
use Prado\Prado;
19
use Prado\TPropertyValue;
20
use Prado\TApplicationMode;
21
22
/**
23
 * THttpRequest class
24
 *
25
 * THttpRequest provides storage and access scheme for user request sent via HTTP.
26
 * It also encapsulates a uniform way to parse and construct URLs.
27
 *
28
 * User post data can be retrieved from THttpRequest by using it like an associative array.
29
 * For example, to test if a user supplies a variable named 'param1', you can use,
30
 * <code>
31
 *   if(isset($request['param1'])) ...
32
 *   // equivalent to:
33
 *   // if($request->contains('param1')) ...
34
 * </code>
35
 * To get the value of 'param1', use,
36
 * <code>
37
 *   $value=$request['param1'];
38
 *   // equivalent to:
39
 *   //   $value=$request->itemAt('param1');
40
 * </code>
41
 * To traverse the user post data, use
42
 * <code>
43
 *   foreach($request as $name=>$value) ...
44
 * </code>
45
 * Note, POST and GET variables are merged together in THttpRequest.
46
 * If a variable name appears in both POST and GET data, then POST data
47
 * takes precedence.
48
 *
49
 * To construct a URL that can be recognized by Prado, use {@link constructUrl()}.
50
 * The format of the recognizable URLs is determined according to
51
 * {@link setUrlManager UrlManager}. By default, the following two formats
52
 * are recognized:
53
 * <code>
54
 * /index.php?ServiceID=ServiceParameter&Name1=Value1&Name2=Value2
55
 * /index.php/ServiceID,ServiceParameter/Name1,Value1/Name2,Value2
56
 * </code>
57
 * The first format is called 'Get' while the second 'Path', which is specified
58
 * via {@link setUrlFormat UrlFormat}. For advanced users who want to use
59
 * their own URL formats, they can write customized URL management modules
60
 * and install the managers as application modules and set {@link setUrlManager UrlManager}.
61
 *
62
 * The ServiceID in the above URLs is as defined in the application configuration
63
 * (e.g. the default page service's service ID is 'page').
64
 * As a consequence, your GET variable names should not conflict with the service
65
 * IDs that your application supports.
66
 *
67
 * THttpRequest also provides the cookies sent by the user, user information such
68
 * as his browser capabilities, accepted languages, etc.
69
 *
70
 * By default, THttpRequest is registered with {@link TApplication} as the
71
 * request module. It can be accessed via {@link TApplication::getRequest()}.
72
 *
73
 * @author Qiang Xue <[email protected]>
74
 * @package Prado\Web
75
 * @since 3.0
76
 */
77
class THttpRequest extends \Prado\TApplicationComponent implements \IteratorAggregate, \ArrayAccess, \Countable, \Prado\IModule
78
{
79
	const CGIFIX__PATH_INFO		= 1;
80
	const CGIFIX__SCRIPT_NAME	= 2;
81
	/**
82
	 * @var TUrlManager the URL manager module
83
	 */
84
	private $_urlManager=null;
85
	/**
86
	 * @var string the ID of the URL manager module
87
	 */
88
	private $_urlManagerID='';
89
	/**
90
	 * @var string Separator used to separate GET variable name and value when URL format is Path.
91
	 */
92
	private $_separator=',';
93
	/**
94
	 * @var string requested service ID
95
	 */
96
	private $_serviceID=null;
97
	/**
98
	 * @var string requested service parameter
99
	 */
100
	private $_serviceParam=null;
101
	/**
102
	 * @var THttpCookieCollection cookies sent from user
103
	 */
104
	private $_cookies=null;
105
	/**
106
	 * @var string requested URI (URL w/o host info)
107
	 */
108
	private $_requestUri;
109
	/**
110
	 * @var string path info of URL
111
	 */
112
	private $_pathInfo;
113
	/**
114
	 * @var boolean whether the session ID should be kept in cookie only
115
	 */
116
	private $_cookieOnly=null;
117
	private $_urlFormat=THttpRequestUrlFormat::Get;
118
	private $_services;
0 ignored issues
show
Unused Code introduced by
The property $_services is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
119
	private $_requestResolved=false;
120
	private $_enableCookieValidation=false;
121
	private $_cgiFix=0;
122
	/**
123
	 * @var boolean whether to cache the TUrlManager class (useful with a lot of TUrlMappings)
124
	 */
125
	private $_enableCache=false;
126
	/**
127
	 * @var string request URL
128
	 */
129
	private $_url=null;
130
131
	/**
132
	 * @var string module id
133
	 */
134
	private $_id;
135
136
	/**
137
	 * @var array contains all request variables
138
	 */
139
	private $_items=array();
140
141
	/**
142
	 * @return string id of this module
143
	 */
144
	public function getID()
145
	{
146
		return $this->_id;
147
	}
148
149
	/**
150
	 * @param string id of this module
151
	 */
152
	public function setID($value)
153
	{
154
		$this->_id=$value;
155
	}
156
157
	/**
158
	 * Initializes the module.
159
	 * This method is required by IModule and is invoked by application.
160
	 * @param TXmlElement module configuration
161
	 */
162
	public function init($config)
0 ignored issues
show
Coding Style introduced by
init uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
init uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
init uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
init uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
init uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
163
	{
164
		// Fill in default request info when the script is run in command line
165
		if(php_sapi_name()==='cli')
166
		{
167
			$_SERVER['REMOTE_ADDR']='127.0.0.1';
168
			$_SERVER['REQUEST_METHOD']='GET';
169
			$_SERVER['SERVER_NAME']='localhost';
170
			$_SERVER['SERVER_PORT']=80;
171
			$_SERVER['HTTP_USER_AGENT']='';
172
		}
173
174
		// Info about server variables:
175
		// PHP_SELF contains real URI (w/ path info, w/o query string)
176
		// SCRIPT_NAME is the real URI for the requested script (w/o path info and query string)
177
		// QUERY_STRING is the string following the '?' in the ur (eg the a=x part in http://foo/bar?a=x)
178
		// REQUEST_URI contains the URI part entered in the browser address bar
179
		// SCRIPT_FILENAME is the file path to the executing script
180
		if(isset($_SERVER['REQUEST_URI']))
181
			$this->_requestUri=$_SERVER['REQUEST_URI'];
0 ignored issues
show
Documentation Bug introduced by
It seems like $_SERVER['REQUEST_URI'] can also be of type integer. However, the property $_requestUri is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
182
		else  // TBD: in this case, SCRIPT_NAME need to be escaped
183
			$this->_requestUri=$_SERVER['SCRIPT_NAME'].(empty($_SERVER['QUERY_STRING'])?'':'?'.$_SERVER['QUERY_STRING']);
184
185
		if($this->_cgiFix&self::CGIFIX__PATH_INFO && isset($_SERVER['ORIG_PATH_INFO']))
186
			$this->_pathInfo=substr($_SERVER['ORIG_PATH_INFO'], strlen($_SERVER['SCRIPT_NAME']));
187
		elseif(isset($_SERVER['PATH_INFO']))
188
			$this->_pathInfo=$_SERVER['PATH_INFO'];
189
		else if(strpos($_SERVER['PHP_SELF'],$_SERVER['SCRIPT_NAME'])===0 && $_SERVER['PHP_SELF']!==$_SERVER['SCRIPT_NAME'])
190
			$this->_pathInfo=substr($_SERVER['PHP_SELF'],strlen($_SERVER['SCRIPT_NAME']));
191
		else
192
			$this->_pathInfo='';
193
194
		if(get_magic_quotes_gpc())
195
		{
196
			if(isset($_GET))
197
				$_GET=$this->stripSlashes($_GET);
198
			if(isset($_POST))
199
				$_POST=$this->stripSlashes($_POST);
200
			if(isset($_REQUEST))
201
				$_REQUEST=$this->stripSlashes($_REQUEST);
202
			if(isset($_COOKIE))
203
				$_COOKIE=$this->stripSlashes($_COOKIE);
204
		}
205
206
		$this->getApplication()->setRequest($this);
207
	}
208
209
	/**
210
	 * Strips slashes from input data.
211
	 * This method is applied when magic quotes is enabled.
212
	 * @param mixed input data to be processed
213
	 * @return mixed processed data
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array|string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
214
	 */
215
	public function stripSlashes(&$data)
216
	{
217
		return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);
218
	}
219
220
	/**
221
	 * @return TUri the request URL
222
	 */
223
	public function getUrl()
0 ignored issues
show
Coding Style introduced by
getUrl uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
224
	{
225
		if($this->_url===null)
226
		{
227
			$secure=$this->getIsSecureConnection();
228
			$url=$secure?'https://':'http://';
229
			if(empty($_SERVER['HTTP_HOST']))
230
			{
231
				$url.=$_SERVER['SERVER_NAME'];
232
				$port=$_SERVER['SERVER_PORT'];
233
				if(($port!=80 && !$secure) || ($port!=443 && $secure))
234
					$url.=':'.$port;
235
			}
236
			else
237
				$url.=$_SERVER['HTTP_HOST'];
238
			$url.=$this->getRequestUri();
239
			$this->_url=new TUri($url);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Prado\Web\TUri($url) of type object<Prado\Web\TUri> is incompatible with the declared type string of property $_url.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
240
		}
241
		return $this->_url;
242
	}
243
244
	/**
245
	 * Set true to cache the UrlManager instance. Consider to enable this cache
246
	 * when the application defines a lot of TUrlMappingPatterns
247
	 * @param boolean true to cache urlmanager instance.
248
	 */
249
	public function setEnableCache($value)
250
	{
251
		$this->_enableCache = TPropertyValue::ensureBoolean($value);
252
	}
253
254
	/**
255
	 * @return boolean true if urlmanager instance should be cached, false otherwise.
256
	 */
257
	public function getEnableCache()
258
	{
259
		return $this->_enableCache;
260
	}
261
262
	protected function getCacheKey()
263
	{
264
		return $this->getID();
265
	}
266
267
	/**
268
	 * Saves the current UrlManager instance to cache.
269
	 * @return boolean true if UrlManager instance was cached, false otherwise.
270
	 */
271
	protected function cacheUrlManager($manager)
272
	{
273
		if($this->getEnableCache())
274
		{
275
			$cache = $this->getApplication()->getCache();
276
			if($cache !== null)
277
			{
278
				$dependencies = null;
279
				if($this->getApplication()->getMode() !== TApplicationMode::Performance)
280
					if ($manager instanceof TUrlMapping && $fn = $manager->getConfigFile())
281
					{
282
						$fn = Prado::getPathOfNamespace($fn,$this->getApplication()->getConfigurationFileExt());
283
						$dependencies = new TFileCacheDependency($fn);
284
					}
285
				return $cache->set($this->getCacheKey(), $manager, 0, $dependencies);
286
			}
287
		}
288
		return false;
289
	}
290
291
	/**
292
	 * Loads UrlManager instance from cache.
293
	 * @return TUrlManager intance if load was successful, null otherwise.
294
	 */
295
	protected function loadCachedUrlManager()
296
	{
297
		if($this->getEnableCache())
298
		{
299
			$cache = $this->getApplication()->getCache();
300
			if($cache !== null)
301
			{
302
				$manager = $cache->get($this->getCacheKey());
303
				if($manager instanceof TUrlManager)
304
					return $manager;
305
			}
306
		}
307
		return null;
308
	}
309
310
	/**
311
	 * @return string the ID of the URL manager module
312
	 */
313
	public function getUrlManager()
314
	{
315
		return $this->_urlManagerID;
316
	}
317
318
	/**
319
	 * Sets the URL manager module.
320
	 * By default, {@link TUrlManager} is used for managing URLs.
321
	 * You may specify a different module for URL managing tasks
322
	 * by loading it as an application module and setting this property
323
	 * with the module ID.
324
	 * @param string the ID of the URL manager module
325
	 */
326
	public function setUrlManager($value)
327
	{
328
		$this->_urlManagerID=$value;
329
	}
330
331
	/**
332
	 * @return TUrlManager the URL manager module
333
	 */
334
	public function getUrlManagerModule()
335
	{
336
		if($this->_urlManager===null)
337
		{
338
			if(($this->_urlManager = $this->loadCachedUrlManager())===null)
339
			{
340
				if(empty($this->_urlManagerID))
341
				{
342
					$this->_urlManager=new TUrlManager;
343
					$this->_urlManager->init(null);
344
				}
345
				else
346
				{
347
					$this->_urlManager=$this->getApplication()->getModule($this->_urlManagerID);
348
					if($this->_urlManager===null)
349
						throw new TConfigurationException('httprequest_urlmanager_inexist',$this->_urlManagerID);
350
					if(!($this->_urlManager instanceof TUrlManager))
351
						throw new TConfigurationException('httprequest_urlmanager_invalid',$this->_urlManagerID);
352
				}
353
				$this->cacheUrlManager($this->_urlManager);
354
			}
355
		}
356
		return $this->_urlManager;
357
	}
358
359
	/**
360
	 * @return THttpRequestUrlFormat the format of URLs. Defaults to THttpRequestUrlFormat::Get.
361
	 */
362
	public function getUrlFormat()
363
	{
364
		return $this->_urlFormat;
365
	}
366
367
	/**
368
	 * Sets the format of URLs constructed and interpretted by the request module.
369
	 * A Get URL format is like index.php?name1=value1&name2=value2
370
	 * while a Path URL format is like index.php/name1,value1/name2,value.
371
	 * Changing the UrlFormat will affect {@link constructUrl} and how GET variables
372
	 * are parsed.
373
	 * @param THttpRequestUrlFormat the format of URLs.
374
	 */
375
	public function setUrlFormat($value)
376
	{
377
		$this->_urlFormat=TPropertyValue::ensureEnum($value,'Prado\\Web\\THttpRequestUrlFormat');
378
	}
379
380
	/**
381
	 * @return string separator used to separate GET variable name and value when URL format is Path. Defaults to comma ','.
382
	 */
383
	public function getUrlParamSeparator()
384
	{
385
		return $this->_separator;
386
	}
387
388
	/**
389
	 * @param string separator used to separate GET variable name and value when URL format is Path.
390
	 * @throws TInvalidDataValueException if the separator is not a single character
391
	 */
392
	public function setUrlParamSeparator($value)
393
	{
394
		if(strlen($value)===1)
395
			$this->_separator=$value;
396
		else
397
			throw new TInvalidDataValueException('httprequest_separator_invalid');
398
	}
399
400
	/**
401
	 * @return string request type, can be GET, POST, HEAD, or PUT
402
	 */
403
	public function getRequestType()
0 ignored issues
show
Coding Style introduced by
getRequestType uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
404
	{
405
		return isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:null;
406
	}
407
408
	/**
409
	 * @param boolean $mimetypeOnly whether to return only the mimetype (default: true)
410
	 * @return string content type (e.g. 'application/json' or 'text/html; encoding=gzip') or null if not specified
411
	 */
412
	public function getContentType($mimetypeOnly = true)
0 ignored issues
show
Coding Style introduced by
getContentType uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
413
	{
414
		if(!isset($_SERVER['CONTENT_TYPE']))
415
			return null;
416
417
		if($mimetypeOnly === true && ($_pos = strpos(';', $_SERVER['CONTENT_TYPE'])) !== false)
418
			return substr($_SERVER['CONTENT_TYPE'], 0, $_pos);
419
420
		return $_SERVER['CONTENT_TYPE'];
421
	}
422
423
	/**
424
	 * @return boolean if the request is sent via secure channel (https)
425
	 */
426
	public function getIsSecureConnection()
0 ignored issues
show
Coding Style introduced by
getIsSecureConnection uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
427
	{
428
			return isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'],'off');
429
	}
430
431
	/**
432
	 * @return string part of the request URL after script name and before question mark.
433
	 */
434
	public function getPathInfo()
435
	{
436
		return $this->_pathInfo;
437
	}
438
439
	/**
440
	 * @return string part of that request URL after the question mark
441
	 */
442
	public function getQueryString()
0 ignored issues
show
Coding Style introduced by
getQueryString uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
443
	{
444
		return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:null;
445
	}
446
447
	/**
448
	 * @return string the requested http procolol. Blank string if not defined.
449
	 */
450
	public function getHttpProtocolVersion()
0 ignored issues
show
Coding Style introduced by
getHttpProtocolVersion uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
451
	{
452
		return isset($_SERVER['SERVER_PROTOCOL'])?$_SERVER['SERVER_PROTOCOL']:null;
453
	}
454
455
	/**
456
	 * @param integer|null Either {@link CASE_UPPER} or {@link CASE_LOWER} or as is null (default)
457
	 * @return array
458
	 */
459
	public function getHeaders($case=null)
0 ignored issues
show
Coding Style introduced by
getHeaders uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
460
	{
461
		static $result;
462
463
		if($result === null && function_exists('apache_request_headers')) {
464
			$result = apache_request_headers();
465
		}
466
		elseif($result === null) {
467
			$result = array();
468
			foreach($_SERVER as $key=>$value) {
469
				if(strncasecmp($key, 'HTTP_', 5) !== 0) continue;
470
					$key = str_replace(' ','-', ucwords(strtolower(str_replace('_',' ', substr($key, 5)))));
471
					$result[$key] = $value;
472
			}
473
		}
474
475
		if($case !== null)
476
			return array_change_key_case($result, $case);
477
478
		return $result;
479
	}
480
481
	/**
482
	 * @return string part of that request URL after the host info (including pathinfo and query string)
483
	 */
484
	public function getRequestUri()
485
	{
486
		return $this->_requestUri;
487
	}
488
489
	/**
490
	 * @param boolean|null whether to use HTTPS instead of HTTP even if the current request is sent via HTTP or vice versa
491
	 * 						null - keep current schema
492
	 * 						true - force https
493
	 * 						false - force http
494
	 * @return string schema and hostname of the requested URL
495
	 */
496
	public function getBaseUrl($forceSecureConnection=null)
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $forceSecureConnection exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
497
	{
498
		$url=$this->getUrl();
499
		$scheme=($forceSecureConnection)?"https": (($forceSecureConnection === null)?$url->getScheme():'http');
500
		$host=$url->getHost();
501
		if (($port=$url->getPort())) $host.=':'.$port;
502
		return $scheme.'://'.$host;
503
	}
504
505
	/**
506
	 * @return string entry script URL (w/o host part)
507
	 */
508
	public function getApplicationUrl()
0 ignored issues
show
Coding Style introduced by
getApplicationUrl uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
509
	{
510
		if($this->_cgiFix&self::CGIFIX__SCRIPT_NAME && isset($_SERVER['ORIG_SCRIPT_NAME']))
511
			return $_SERVER['ORIG_SCRIPT_NAME'];
512
513
		return isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:null;
514
	}
515
516
	/**
517
	 * @param boolean|null whether to use HTTPS instead of HTTP even if the current request is sent via HTTP or vice versa
518
	 * 						null - keep current schema
519
	 * 						true - force https
520
	 * 						false - force http
521
	 * @return string entry script URL (w/ host part)
522
	 */
523
	public function getAbsoluteApplicationUrl($forceSecureConnection=null)
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $forceSecureConnection exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
524
	{
525
		return $this->getBaseUrl($forceSecureConnection) . $this->getApplicationUrl();
526
	}
527
528
	/**
529
	 * @return string application entry script file path (processed w/ realpath())
530
	 */
531
	public function getApplicationFilePath()
0 ignored issues
show
Coding Style introduced by
getApplicationFilePath uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
532
	{
533
		return realpath(isset($_SERVER['SCRIPT_FILENAME'])?$_SERVER['SCRIPT_FILENAME']:null);
534
	}
535
536
	/**
537
	 * @return string server name
538
	 */
539
	public function getServerName()
0 ignored issues
show
Coding Style introduced by
getServerName uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
540
	{
541
		return isset($_SERVER['SERVER_NAME'])?$_SERVER['SERVER_NAME']:null;
542
	}
543
544
	/**
545
	 * @return integer server port number
546
	 */
547
	public function getServerPort()
0 ignored issues
show
Coding Style introduced by
getServerPort uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
548
	{
549
		return isset($_SERVER['SERVER_PORT'])?$_SERVER['SERVER_PORT']:null;
550
	}
551
552
	/**
553
	 * @return string URL referrer, null if not present
554
	 */
555
	public function getUrlReferrer()
0 ignored issues
show
Coding Style introduced by
getUrlReferrer uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
556
	{
557
		return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;
558
	}
559
560
	/**
561
	 * @return string server software
562
	 * @since 3.3.3
563
	 */
564
	public function getServerSoftware()
0 ignored issues
show
Coding Style introduced by
getServerSoftware uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
565
	{
566
		return isset($_SERVER['SERVER_SOFTWARE'])?$_SERVER['SERVER_SOFTWARE']:null;
567
	}
568
569
	/**
570
	 * @return array user browser capabilities
571
	 * @see get_browser
572
	 */
573
	public function getBrowser()
574
	{
575
		try
576
		{
577
			return get_browser();
578
		}
579
		catch(TPhpErrorException $e)
580
		{
581
			throw new TConfigurationException('httprequest_browscap_required');
582
		}
583
	}
584
585
	/**
586
	 * @return string user agent
587
	 */
588
	public function getUserAgent()
0 ignored issues
show
Coding Style introduced by
getUserAgent uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
589
	{
590
		return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null;
591
	}
592
593
	/**
594
	 * @return string user IP address
595
	 */
596
	public function getUserHostAddress()
0 ignored issues
show
Coding Style introduced by
getUserHostAddress uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
597
	{
598
		return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:null;
599
	}
600
601
	/**
602
	 * @return string user host name, null if cannot be determined
603
	 */
604
	public function getUserHost()
0 ignored issues
show
Coding Style introduced by
getUserHost uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
605
	{
606
		return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;
607
	}
608
609
	/**
610
	 * @return string user browser accept types
611
	 */
612
	public function getAcceptTypes()
0 ignored issues
show
Coding Style introduced by
getAcceptTypes uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
613
	{
614
		// TBD: break it into array??
615
		return isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:null;
616
	}
617
618
	/**
619
	 * Returns a list of user preferred languages.
620
	 * The languages are returned as an array. Each array element
621
	 * represents a single language preference. The languages are ordered
622
	 * according to user preferences. The first language is the most preferred.
623
	 * @return array list of user preferred languages.
624
	 */
625
	public function getUserLanguages()
626
	{
627
		return Prado::getUserLanguages();
628
	}
629
630
	/**
631
	 * @return boolean whether cookies should be validated. Defaults to false.
632
	 */
633
	public function getEnableCookieValidation()
634
	{
635
		return $this->_enableCookieValidation;
636
	}
637
638
	/**
639
	 * @param boolean whether cookies should be validated.
640
	 */
641
	public function setEnableCookieValidation($value)
642
	{
643
		$this->_enableCookieValidation=TPropertyValue::ensureBoolean($value);
644
	}
645
646
	/**
647
	 * @return integer whether to use ORIG_PATH_INFO and/or ORIG_SCRIPT_NAME. Defaults to 0.
648
	 * @see THttpRequest::CGIFIX__PATH_INFO, THttpRequest::CGIFIX__SCRIPT_NAME
649
	 */
650
	public function getCgiFix()
651
	{
652
		return $this->_cgiFix;
653
	}
654
655
	/**
656
	 * Enable this, if you're using PHP via CGI with php.ini setting "cgi.fix_pathinfo=1"
657
	 * and have trouble with friendly URL feature. Enable this only if you really know what you are doing!
658
	 * @param integer enable bitwise to use ORIG_PATH_INFO and/or ORIG_SCRIPT_NAME.
659
	 * @see THttpRequest::CGIFIX__PATH_INFO, THttpRequest::CGIFIX__SCRIPT_NAME
660
	 */
661
	public function setCgiFix($value)
662
	{
663
		$this->_cgiFix=TPropertyValue::ensureInteger($value);
664
	}
665
666
	/**
667
	 * @return THttpCookieCollection list of cookies to be sent
668
	 */
669
	public function getCookies()
0 ignored issues
show
Coding Style introduced by
getCookies uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
670
	{
671
		if($this->_cookies===null)
672
		{
673
			$this->_cookies=new THttpCookieCollection;
674
			if($this->getEnableCookieValidation())
675
			{
676
				$sm=$this->getApplication()->getSecurityManager();
677
				foreach($_COOKIE as $key=>$value)
678
				{
679
					if(($value=$sm->validateData($value))!==false)
680
						$this->_cookies->add(new THttpCookie($key,$value));
681
				}
682
			}
683
			else
684
			{
685
				foreach($_COOKIE as $key=>$value)
686
					$this->_cookies->add(new THttpCookie($key,$value));
687
			}
688
		}
689
		return $this->_cookies;
690
	}
691
692
	/**
693
	 * @return array list of uploaded files.
694
	 */
695
	public function getUploadedFiles()
0 ignored issues
show
Coding Style introduced by
getUploadedFiles uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
696
	{
697
		return $_FILES;
698
	}
699
700
	/**
701
	 * @return array list of server variables.
702
	 */
703
	public function getServerVariables()
0 ignored issues
show
Coding Style introduced by
getServerVariables uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
704
	{
705
		return $_SERVER;
706
	}
707
708
	/**
709
	 * @return array list of environment variables.
710
	 */
711
	public function getEnvironmentVariables()
0 ignored issues
show
Coding Style introduced by
getEnvironmentVariables uses the super-global variable $_ENV which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
712
	{
713
		return $_ENV;
714
	}
715
716
	/**
717
	 * Constructs a URL that can be recognized by PRADO.
718
	 * The actual construction work is done by the URL manager module.
719
	 * This method may append session information to the generated URL if needed.
720
	 * You may provide your own URL manager module by setting {@link setUrlManager UrlManager}
721
	 * to provide your own URL scheme.
722
	 *
723
	 * Note, the constructed URL does not contain the protocol and hostname part.
724
	 * You may obtain an absolute URL by prepending the constructed URL with {@link getBaseUrl BaseUrl}.
725
	 * @param string service ID
726
	 * @param string service parameter
727
	 * @param array GET parameters, null if not needed
728
	 * @param boolean whether to encode the ampersand in URL, defaults to true.
729
	 * @param boolean whether to encode the GET parameters (their names and values), defaults to false.
730
	 * @return string URL
731
	 * @see TUrlManager::constructUrl
732
	 */
733
	public function constructUrl($serviceID,$serviceParam,$getItems=null,$encodeAmpersand=true,$encodeGetItems=true)
734
	{
735
		if ($this->_cookieOnly===null)
736
				$this->_cookieOnly=(int)ini_get('session.use_cookies') && (int)ini_get('session.use_only_cookies');
737
		$url=$this->getUrlManagerModule()->constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems);
738
		if(defined('SID') && SID != '' && !$this->_cookieOnly)
739
			return $url . (strpos($url,'?')===false? '?' : ($encodeAmpersand?'&amp;':'&')) . SID;
740
		else
741
			return $url;
742
	}
743
744
	/**
745
	 * Parses the request URL and returns an array of input parameters (excluding GET variables).
746
	 * You may override this method to support customized URL format.
747
	 * @return array list of input parameters, indexed by parameter names
748
	 * @see TUrlManager::parseUrl
749
	 */
750
	protected function parseUrl()
751
	{
752
		return $this->getUrlManagerModule()->parseUrl();
753
	}
754
755
	/**
756
	 * Resolves the requested service.
757
	 * This method implements a URL-based service resolution.
758
	 * A URL in the format of /index.php?sp=serviceID.serviceParameter
759
	 * will be resolved with the serviceID and the serviceParameter.
760
	 * You may override this method to provide your own way of service resolution.
761
	 * @param array list of valid service IDs
762
	 * @return string the currently requested service ID, null if no service ID is found
763
	 * @see constructUrl
764
	 */
765
	public function resolveRequest($serviceIDs)
0 ignored issues
show
Coding Style introduced by
resolveRequest uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
resolveRequest uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
resolveRequest uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
766
	{
767
		Prado::trace("Resolving request from ".$_SERVER['REMOTE_ADDR'],'Prado\Web\THttpRequest');
768
		$getParams=$this->parseUrl();
769
		foreach($getParams as $name=>$value)
770
			$_GET[$name]=$value;
771
		$this->_items=array_merge($_GET,$_POST);
772
		$this->_requestResolved=true;
773
		foreach($serviceIDs as $serviceID)
774
		{
775
			if($this->contains($serviceID))
776
			{
777
				$this->setServiceID($serviceID);
778
				$this->setServiceParameter($this->itemAt($serviceID));
779
				return $serviceID;
780
			}
781
		}
782
		return null;
783
	}
784
785
	/**
786
	 * @return boolean true if request is already resolved, false otherwise.
787
	 */
788
	public function getRequestResolved()
789
	{
790
		return $this->_requestResolved;
791
	}
792
793
	/**
794
	 * @return string requested service ID
795
	 */
796
	public function getServiceID()
797
	{
798
		return $this->_serviceID;
799
	}
800
801
	/**
802
	 * Sets the requested service ID.
803
	 * @param string requested service ID
804
	 */
805
	public function setServiceID($value)
806
	{
807
		$this->_serviceID=$value;
808
	}
809
810
	/**
811
	 * @return string requested service parameter
812
	 */
813
	public function getServiceParameter()
814
	{
815
		return $this->_serviceParam;
816
	}
817
818
	/**
819
	 * Sets the requested service parameter.
820
	 * @param string requested service parameter
821
	 */
822
	public function setServiceParameter($value)
823
	{
824
		$this->_serviceParam=$value;
825
	}
826
827
	//------ The following methods enable THttpRequest to be TMap-like -----
828
829
	/**
830
	 * Returns an iterator for traversing the items in the list.
831
	 * This method is required by the interface \IteratorAggregate.
832
	 * @return Iterator an iterator for traversing the items in the list.
833
	 */
834
	public function getIterator()
835
	{
836
		return new \ArrayIterator($this->_items);
837
	}
838
839
	/**
840
	 * @return integer the number of items in the request
841
	 */
842
	public function getCount()
843
	{
844
		return count($this->_items);
845
	}
846
847
	/**
848
	 * Returns the number of items in the request.
849
	 * This method is required by \Countable interface.
850
	 * @return integer number of items in the request.
851
	 */
852
	public function count()
853
	{
854
		return $this->getCount();
855
	}
856
857
	/**
858
	 * @return array the key list
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<integer|string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
859
	 */
860
	public function getKeys()
861
	{
862
		return array_keys($this->_items);
863
	}
864
865
	/**
866
	 * Returns the item with the specified key.
867
	 * This method is exactly the same as {@link offsetGet}.
868
	 * @param mixed the key
869
	 * @return mixed the element at the offset, null if no element is found at the offset
870
	 */
871
	public function itemAt($key)
872
	{
873
		return isset($this->_items[$key]) ? $this->_items[$key] : null;
874
	}
875
876
	/**
877
	 * Adds an item into the request.
878
	 * Note, if the specified key already exists, the old value will be overwritten.
879
	 * @param mixed key
880
	 * @param mixed value
881
	 */
882
	public function add($key,$value)
883
	{
884
		$this->_items[$key]=$value;
885
	}
886
887
	/**
888
	 * Removes an item from the request by its key.
889
	 * @param mixed the key of the item to be removed
890
	 * @return mixed the removed value, null if no such key exists.
891
	 * @throws TInvalidOperationException if the item cannot be removed
892
	 */
893
	public function remove($key)
894
	{
895
		if(isset($this->_items[$key]) || array_key_exists($key,$this->_items))
896
		{
897
			$value=$this->_items[$key];
898
			unset($this->_items[$key]);
899
			return $value;
900
		}
901
		else
902
			return null;
903
	}
904
905
	/**
906
	 * Removes all items in the request.
907
	 */
908
	public function clear()
909
	{
910
		foreach(array_keys($this->_items) as $key)
911
			$this->remove($key);
912
	}
913
914
	/**
915
	 * @param mixed the key
916
	 * @return boolean whether the request contains an item with the specified key
917
	 */
918
	public function contains($key)
919
	{
920
		return isset($this->_items[$key]) || array_key_exists($key,$this->_items);
921
	}
922
923
	/**
924
	 * @return array the list of items in array
925
	 */
926
	public function toArray()
927
	{
928
		return $this->_items;
929
	}
930
931
	/**
932
	 * Returns whether there is an element at the specified offset.
933
	 * This method is required by the interface \ArrayAccess.
934
	 * @param mixed the offset to check on
935
	 * @return boolean
936
	 */
937
	public function offsetExists($offset)
938
	{
939
		return $this->contains($offset);
940
	}
941
942
	/**
943
	 * Returns the element at the specified offset.
944
	 * This method is required by the interface \ArrayAccess.
945
	 * @param integer the offset to retrieve element.
946
	 * @return mixed the element at the offset, null if no element is found at the offset
947
	 */
948
	public function offsetGet($offset)
949
	{
950
		return $this->itemAt($offset);
951
	}
952
953
	/**
954
	 * Sets the element at the specified offset.
955
	 * This method is required by the interface \ArrayAccess.
956
	 * @param integer the offset to set element
957
	 * @param mixed the element value
958
	 */
959
	public function offsetSet($offset,$item)
960
	{
961
		$this->add($offset,$item);
962
	}
963
964
	/**
965
	 * Unsets the element at the specified offset.
966
	 * This method is required by the interface \ArrayAccess.
967
	 * @param mixed the offset to unset element
968
	 */
969
	public function offsetUnset($offset)
970
	{
971
		$this->remove($offset);
972
	}
973
}