Issues (17)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

uri.lib.php (17 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * PHP URI Library
4
 * 
5
 * A PHP library for working with URI's, that is designed around the URI
6
 * standard. Requires PHP 5.4 or later. This library replaces and extends all
7
 * of PHP's parse_url() features, and even has some handy aliases.
8
 * 
9
 * Originally inspired by P Guardiario's work.
10
 * 
11
 * @author    Nicholas Jordon
12
 * @link      https://github.com/ProjectCleverWeb/PHP-URI
13
 * @copyright 2014 Nicholas Jordon - All Rights Reserved
14
 * @version   1.0.0
15
 * @license   http://opensource.org/licenses/MIT
16
 * @see       http://en.wikipedia.org/wiki/URI_scheme
17
 */
18
19
namespace {
20
	/**
21
	 * URI Class
22
	 * 
23
	 * This class acts as a callable alias to the \uri\main abstract class.
24
	 */
25
	class uri extends \uri\main {}
26
}
27
28
namespace uri {
29
	
30
	/**
31
	 * Main URI Class
32
	 * 
33
	 * This class parses URI string into a dynamic and easy to use object. In
34
	 * many ways, this class simply acts as an extension of a PHP string. Calling
35
	 * this class as if it were a string will result in the current URI string
36
	 * being used throughout PHP.
37
	 */
38
	abstract class main {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
39
		/*** Variables ***/
40
		
41
		public $error;
42
		public $input;
43
		
44
		/*
45
		"Ghost" Variables
46
		=================
47
		These variables can be accesed from within the class, but as far as the rest
48
		of PHP is concerned, these variables simply don't exist.
49
		*/
50
		public $object;
51
		private $chain;
52
		
53
		/*
54
		Sudo-Private Variables
55
		======================
56
		These variables can be accessed just like normal public variables, and can
57
		even be changed like public variables. This implementation of private
58
		variables combined with the __get(), __set(), __isset(), & __unset() magic
59
		constants allow each variable to stay in sync with the group, and still be
60
		accessable.
61
		*/
62
		private $authority;
63
		private $domain;
64
		private $fqdn;
65
		private $fragment;
66
		private $host;
67
		private $protocol;
68
		private $pass;
69
		private $password;
70
		private $path;
71
		private $port;
72
		private $query;
73
		private $scheme;
74
		private $scheme_name;
75
		private $scheme_symbols;
76
		private $user;
77
		private $username;
78
		
79
		
80
		
81
		/*** Magic Methods ***/
82
		
83
		/**
84
		 * Parses the input as a URI and populates the variables. Fails if input is
85
		 * not a string or if the string cannot be parsed as a URI.
86
		 * 
87
		 * @param string $input The URI to parse.
88
		 */
89 38
		public function __construct($input) {
90 38
			$this->input  = $input;
91 38
			$this->object = \uri\parser::parse($input);
92
			
93 38
			if (!empty($this->object->host)) {
94 37
				\uri\generate::authority($this->object);
95 37
				\uri\generate::aliases($this->object);
96
				
97
				// Enable Chain Events
98 37
				$this->chain = new \uri\chain($this);
99
				
100
				// References required for Sudo-Private Variables
101 37
				$this->authority      = &$this->object->authority;
102 37
				$this->domain         = &$this->object->domain;
103 37
				$this->fqdn           = &$this->object->fqdn;
104 37
				$this->fragment       = &$this->object->fragment;
105 37
				$this->host           = &$this->object->host;
106 37
				$this->protocol       = &$this->object->protocol;
107 37
				$this->pass           = &$this->object->pass;
108 37
				$this->password       = &$this->object->password;
109 37
				$this->path           = &$this->object->path;
110 37
				$this->port           = &$this->object->port;
111 37
				$this->query          = &$this->object->query;
112 37
				$this->scheme         = &$this->object->scheme;
113 37
				$this->scheme_name    = &$this->object->scheme_name;
114 37
				$this->scheme_symbols = &$this->object->scheme_symbols;
115 37
				$this->user           = &$this->object->user;
116 37
				$this->username       = &$this->object->username;
117 37
			} else {
118 1
				$this->error = 'Input could not be parsed as a URI';
119
			}
120 38
		}
121
		
122
		/**
123
		 * In the event this class is called as or converted to a string, it will
124
		 * return the current URI string, and NOT cause any errors.
125
		 * 
126
		 * @return string The current URI as a string
127
		 */
128 1
		public function __toString() {
129 1
			return \uri\generate::string($this->object);
130
		}
131
		
132
		/**
133
		 * Invoked? just return the current URI as a string, nothing fancy.
134
		 * 
135
		 * @return string The current URI as a string
136
		 */
137 1
		public function __invoke() {
138 1
			return \uri\generate::string($this->object);
139
		}
140
		
141
		/**
142
		 * Because of how references are created within this class, cloning doesn't
143
		 * work as expected. This magic method warn's people until the issue can be
144
		 * correctly addressed. (It may be impossible to resolve this issue, with
145
		 * the current configuration)
146
		 * 
147
		 * @return void
148
		 */
149 1
		public function __clone() {
150 1
			$this->_err('CLONE', debug_backtrace(), 'clone');
151 1
		}
152
		
153
		/**
154
		 * Allows access to the different parts of the URI to be synchronized. This
155
		 * means that what is returned should always be accurate. Triggers a notice
156
		 * if the variable cannot be accessed.
157
		 * 
158
		 * @param  string $name The requested variable
159
		 * @return string|null  The value of the variable, or NULL if it can't be accessed
160
		 */
161 6 View Code Duplication
		public function __get($name) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162 6
			if (isset($this->object->$name)) {
163 6
				\uri\generate::scheme($this->object);
164 6
				\uri\generate::authority($this->object);
165 6
				return $this->object->$name;
166
			} else {
167 1
				$this->_err('UNDEFINED', debug_backtrace(), $name);
168 1
				return NULL;
169
			}
170
		}
171
		
172
		/**
173
		 * Allows access to the different parts of the URI to be synchronized. This
174
		 * means that what is returned should always be accurate. Triggers a notice
175
		 * if the variable cannot be accessed.
176
		 * 
177
		 * @param  string $name  The requested variable
178
		 * @param  string $value The new value for the variable
179
		 * @return string|null   The new value of the variable, or NULL if it can't be accessed
180
		 */
181 3
		public function __set($name, $value) {
182 3
			if (isset($this->object->$name) && $name != 'authority') {
183 3
				\uri\actions::modify($this->object, 'replace', $name, $value);
184 3
				return $value;
185
			} else {
186 1
				$this->_err('FORBIDDEN', debug_backtrace(), $name);
187 1
				return NULL;
188
			}
189
		}
190
		
191
		/**
192
		 * Allows access to the different parts of the URI to be synchronized. This
193
		 * means that what is returned should always be accurate.
194
		 * 
195
		 * @param  string  $name The requested variable
196
		 * @return boolean       Returns TRUE if the variable is not empty, FALSE otherwise
197
		 */
198 1 View Code Duplication
		public function __isset($name) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
199 1
			\uri\generate::scheme($this->object);
200 1
			\uri\generate::authority($this->object);
201 1
			if (isset($this->object->$name)) {
202 1
				return !empty($this->object->$name);
203
			}
204 1
			return FALSE;
205
		}
206
		
207
		/**
208
		 * Allows access to the different parts of the URI to be synchronized. This
209
		 * means that what is returned should always be accurate. Triggers a notice
210
		 * if the variable cannot be accessed.
211
		 * 
212
		 * @param  string $name The requested variable
213
		 * @return boolean      Returns TRUE if the varaible was successfully emptied, FALSE otherwise.
214
		 */
215 1
		public function __unset($name) {
216 1
			if (isset($this->object->$name) && $name != 'host' && $name != 'authority') {
217 1
				\uri\actions::modify($this->object, 'replace', $name, '');
218 1
				return TRUE;
219 1
			} elseif (isset($this->object->$name)) {
220 1
				$this->_err('FORBIDDEN', debug_backtrace(), $name);
221 1
			} else {
222 1
				$this->_err('UNDEFINED', debug_backtrace(), $name);
223
			}
224 1
			return FALSE;
225
		}
226
		
227
		
228
		
229
		/*** Methods ***/
230
		
231
		/**
232
		 * Returns the current URI as a string.
233
		 * 
234
		 * @return string The current URI as a string
235
		 */
236 12
		public function str() {
237 12
			return \uri\generate::string($this->object);
238
		}
239
		
240
		/**
241
		 * Alias of str()
242
		 * 
243
		 * @return string The current URI as a string
244
		 */
245 1
		public function to_string() {
246 1
			return \uri\generate::string($this->object);
247
		}
248
		
249
		/**
250
		 * Prints the current URI as a string
251
		 * 
252
		 * @param  string $prepend The string to prepend to the output
253
		 * @param  string $append  The string to append to the output
254
		 * @return void
255
		 */
256 1
		public function p_str($prepend = '', $append = '') {
257 1
			echo $prepend.\uri\generate::string($this->object).$append;
258 1
		}
259
		
260
		/**
261
		 * Returns the current URI as an array
262
		 * 
263
		 * @return array The current URI as an array
264
		 */
265 2
		public function arr() {
266 2
			return \uri\generate::to_array($this->object);
267
		}
268
		
269
		/**
270
		 * Alias of arr()
271
		 * 
272
		 * @return array The current URI as an array
273
		 */
274 1
		public function to_array() {
275 1
			return \uri\generate::to_array($this->object);
276
		}
277
		
278
		/**
279
		 * The path broken down into dirname, basename, extension, filename, & array
280
		 * 
281
		 * @return array The information array
282
		 */
283 1
		public function path_info() {
284 1
			return \uri\generate::path_info($this->object);
285
		}
286
		
287
		/**
288
		 * The query parsed into an array
289
		 * 
290
		 * @return array The query array
291
		 */
292 1
		public function query_arr() {
293 1
			return \uri\generate::query_array($this->object);
294
		}
295
		
296
		/**
297
		 * Replaces $section of the URI with $str, given $str is a valid replacement
298
		 * 
299
		 * @param  string $section The section to replace
300
		 * @param  string $str     The string to replace the section with
301
		 * @return string|false    The resulting URI if the modification is valid, FALSE otherwise
302
		 */
303 16
		public function replace($section, $str) {
304 16
			return \uri\actions::modify($this->object, 'replace', $section, $str);
305
		}
306
		
307
		/**
308
		 * Prepends $section of the URI with $str, given the $section is still valid
309
		 * once $str is in place
310
		 * 
311
		 * @param  string $section The section to prepend
312
		 * @param  string $str     The string to prepend the section with
313
		 * @return string|false    The resulting URI if the modification is valid, FALSE otherwise
314
		 */
315 11
		public function prepend($section, $str) {
316 11
			return \uri\actions::modify($this->object, 'prepend', $section, $str);
317
		}
318
		
319
		/**
320
		 * Appends $section of the URI with $str, given $section is still valid
321
		 * once $str is in place
322
		 * 
323
		 * @param  string $section The section to append
324
		 * @param  string $str     The string to append the section with
325
		 * @return string|false    The resulting URI if the modification is valid, FALSE otherwise
326
		 */
327 11
		public function append($section, $str) {
328 11
			return \uri\actions::modify($this->object, 'append', $section, $str);
329
		}
330
		
331
		/**
332
		 * Adds query var to the query string if it is not already set and returns
333
		 * TRUE. Otherwise it returns FALSE
334
		 * 
335
		 * @param  string $key   The key to add
336
		 * @param  mixed  $value The value of $key
337
		 * @return boolean       TRUE on success, FALSE otherwise
338
		 */
339 1
		public function query_add($key, $value) {
340 1
			return \uri\query::add($this->object, $key, $value);
341
		}
342
		
343
		/**
344
		 * Adds query var to the query string regardless if it already set or not
345
		 * 
346
		 * @param  string $key   The key to replace
347
		 * @param  mixed  $value The value of $key
348
		 * @return void
349
		 */
350 1
		public function query_replace($key, $value) {
351 1
			\uri\query::replace($this->object, $key, $value);
352 1
		}
353
		
354
		/**
355
		 * Removes $key from the query if it exists
356
		 * 
357
		 * @param  string $key The key to remove
358
		 * @return void
359
		 */
360 1
		public function query_remove($key) {
361 1
			\uri\query::remove($this->object, $key);
362 1
		}
363
		
364
		/**
365
		 * Checks if $key exists in the query
366
		 * 
367
		 * @param  string $key The key to search for
368
		 * @return boolean     TRUE if the $key exists, FALSE otherwise
369
		 */
370 1
		public function query_exists($key) {
371 1
			return \uri\query::exists($this->object, $key);
372
		}
373
		
374
		/**
375
		 * Gets a specific var's value from the query. It is HIGHLY recommended
376
		 * that you use query_arr() instead, when fetching multiple values from
377
		 * the same query string. Returns NULL if $key does not exist.
378
		 * 
379
		 * @param  string $key The key to get
380
		 * @return mixed|null  The value of $key, or NULL if it does not exist.
381
		 */
382 1
		public function query_get($key) {
383 1
			return \uri\query::get($this->object, $key);
384
		}
385
		
386
		/**
387
		 * Renames a specific $key within the query. If the key exists within query
388
		 * string and is successfully renamed, the TRUE is returned. Otherwise
389
		 * FALSE is returned.
390
		 * 
391
		 * @param  string $key     The key to rename
392
		 * @param  string $new_key The new name of $key
393
		 * @return boolean         TRUE on success, FALSE otherwise
394
		 */
395 1
		public function query_rename($key, $new_key) {
396 1
			return \uri\query::rename($this->object, $key, $new_key);
397
		}
398
		
399
		/**
400
		 * Returns the chain class, which allows events to be chained together
401
		 * rather than the reference being called several times. see \uri\chain
402
		 * 
403
		 * @return object The chain class
404
		 */
405 4
		public function chain() {
406 4
			return $this->chain;
407
		}
408
		
409
		/**
410
		 * Resets the current object to its initial state
411
		 * 
412
		 * @return void
413
		 */
414 2
		public function reset() {
415 2
			$this->__construct($this->input);
416 2
		}
417
		
418
		/**
419
		 * A unknown/forbidden property has been called. trigger an error
420
		 * 
421
		 * @param  string $type  Type of error
422
		 * @param  array  $trace The output from debug_backtrace()
423
		 * @param  string $name  Property name
424
		 * @return void
425
		 */
426 2
		private function _err($type, $trace, $name) {
427 2
			$fmt = 'Undifined property via <code>%1$s::%2$s()</code>: Property <code>%3$s</code> cannot be unset in <b>%4$s</b> on line <b>%5$s</b>. Error triggered';
428 2
			if ($type == 'FORBIDDEN') {
429 1
				$fmt = 'Forbidden property via <code>%1$s::%2$s()</code>: Property <code>%3$s</code> cannot be unset in <b>%4$s</b> on line <b>%5$s</b>. Error triggered';
430 2
			} elseif($type == 'CLONE') {
431 1
				$fmt = 'Invalid clone in <b>%4$s</b> on line <b>%5$s</b>. Because of how cloning works, and how references are configured within the class, extensions of %1$s cannot be cloned. Please make a new instance instead, like so: <code>$clone = new \\uri($original->str()); $clone->input = $original->input;</code>. Error triggered';
432 1
			}
433
			
434 2
			trigger_error(
435 2
				sprintf(
436 2
					$fmt,
437 2
					$trace[0]['class'],
438 2
					$trace[0]['function'],
439 2
					$name,
440 2
					$trace[0]['file'],
441 2
					$trace[0]['line']
442 2
				),
443
				E_USER_NOTICE
444 2
			);
445 2
		}
446
	}
447
	
448
	
449
	
450
	/**
451
	 * The Parser Class
452
	 * 
453
	 * This class controls how the initial input is parsed. This class is
454
	 * designed to be easily upgraded to use different types of parsing. should
455
	 * it be desired.
456
	 */
457
	class parser {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
458
		/*** Constants ***/
459
		
460
		// This regex is broken down to be readable in regex_parse()
461
		const REGEX = '/^(([a-z]+)?(\:\/\/|\:|\/\/))?(?:([a-z0-9$_\.\+!\*\'\(\),;&=\-]+)(?:\:([a-z0-9$_\.\+!\*\'\(\),;&=\-]*))?@)?((?:\d{3}.\d{3}.\d{3}.\d{3})|(?:[a-z0-9\-_]+(?:\.[a-z0-9\-_]+)*))(?:\:([0-9]+))?((?:\:|\/)[a-z0-9\-_\/\.]+)?(?:\?([a-z0-9$_\.\+!\*\'\(\),;:@&=\-%]*))?(?:#([a-z0-9\-_]*))?/i';
462
		
463
		/*** Methods ***/
464
		
465
		/**
466
		 * Wrapper function for parsing a string into a URI object
467
		 * 
468
		 * @param  string $uri  The input to be parsed as a URI
469
		 * @return object       If the input can be correctly parsed, then it returns an object with at least the 'host' populated
470
		 */
471 38
		public static function parse($uri) {
472 38
			if (!is_string($uri)) {
473 1
				return FALSE;
474
			}
475
			
476 38
			$parsed = self::regex_parse($uri);
477
			
478
			// Could not be parsed correctly
479 38
			if (empty($parsed)) {
480 1
				$parsed = array_fill(1, 10, '');
481 1
			}
482
			
483
			return (object) array(
484 38
				'scheme'         => $parsed[1],
485 38
				'scheme_name'    => $parsed[2],
486 38
				'scheme_symbols' => $parsed[3],
487 38
				'user'           => $parsed[4],
488 38
				'pass'           => $parsed[5],
489 38
				'host'           => $parsed[6],
490 38
				'port'           => $parsed[7],
491 38
				'path'           => $parsed[8],
492 38
				'query'          => $parsed[9],
493 38
				'fragment'       => $parsed[10],
494 38
			);
495
		}
496
		
497
		/**
498
		 * Parses a URI string into a usable array.
499
		 * 
500
		 * @param  string $uri The URI to be parsed
501
		 * @return array|false Returns an array if the sting could be correctly parsed, FALSE otherwise
502
		 */
503 38
		private static function regex_parse($uri) {
504
			// $regex = (
505
			//   '/'.
506
			//   '^(([a-z]+)?(\:\/\/|\:|\/\/))?'.              // Scheme, Scheme Name, & Scheme Symbols
507
			//   '(?:'.                                        // Auth Start
508
			//     '([a-z0-9$_\.\+!\*\'\(\),;&=\-]+)'.         // Username
509
			//     '(?:\:([a-z0-9$_\.\+!\*\'\(\),;&=\-]*))?'.  // Password
510
			//   '@)?'.                                        // Auth End
511
			//   '('.                                          // Host Start
512
			//     '(?:\d{3}.\d{3}.\d{3}.\d{3})'.              // IP Address
513
			//     '|'.                                        // -OR-
514
			//     '(?:[a-z0-9\-_]+(?:\.[a-z0-9\-_]+)*)'.      // Domain Name
515
			//   ')'.                                          // Host End
516
			//   '(?:\:([0-9]+))?'.                            // Port
517
			//   '((?:\:|\/)[a-z0-9\-_\/\.]+)?'.               // Path
518
			//   '(?:\?([a-z0-9$_\.\+!\*\'\(\),;:@&=\-%]*))?'. // Query
519
			//   '(?:#([a-z0-9\-_]*))?'.                       // Fragment
520
			//   '/i'
521
			// );
522 38
			preg_match_all(self::REGEX, $uri, $parsed, PREG_SET_ORDER);
523
			
524
			// Host is required
525 38
			if (!isset($parsed[0][6])) {
526 1
				return FALSE;
527
			}
528
			
529
			// Return what was parsed, but make sure that each offset is set regardless
530 37
			return $parsed[0] + array_fill(0, 11, '');
531
		}
532
	}
533
	
534
	
535
	
536
	/**
537
	 * The Modifier Class
538
	 * 
539
	 * This class is in charge of making user-based changes.
540
	 */
541
	class modify {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
542
		/*** Methods ***/
543
		
544
		/**
545
		 * Modfies the Scheme Name
546
		 * 
547
		 * @param  object $object  The object to modify
548
		 * @param  string $action  The action to take
549
		 * @param  string $str     The modfication
550
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
551
		 */
552 3
		public static function scheme_name(&$object, $action, $str) {
553 3
			$org = $object->scheme_name;
554 3
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
555 3
			if (!(preg_match('/\A[a-z]{1,10}\Z/', $object->scheme_name) || empty($str))) {
556 1
				$object->scheme_name = $org;
557 1
				return FALSE;
558 2
			} elseif (empty($object->scheme_symbols)) {
559 2
				$object->scheme_symbols = '://';
560 2
			}
561
			
562 2
			return \uri\generate::string($object);
563
		}
564
		
565
		/**
566
		 * Modfies the Scheme Symbols
567
		 * 
568
		 * @param  object $object  The object to modify
569
		 * @param  string $action  The action to take
570
		 * @param  string $str     The modfication
571
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
572
		 */
573 3 View Code Duplication
		public static function scheme_symbols(&$object, $action, $str) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
574 3
			$org = $object->scheme_symbols;
575 3
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
576 3
			if (!(preg_match('/\A(:)?([\/]{2,3})?\Z/', $object->scheme_symbols) || empty($str))) {
577 1
				$object->scheme_symbols = $org;
578 1
				return FALSE;
579
			}
580
			
581 2
			return \uri\generate::string($object);
582
		}
583
		
584
		/**
585
		 * Modfies the Scheme
586
		 * 
587
		 * @param  object $object  The object to modify
588
		 * @param  string $action  The action to take
589
		 * @param  string $str     The modfication
590
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
591
		 */
592 5
		public static function scheme(&$object, $action, $str) {
593 5
			$org = array($object->scheme, $object->scheme_name, $object->scheme_symbols);
594 5
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
595 5
			if (empty($object->scheme)) {
596 1
				$object->scheme = $object->scheme_name = $object->scheme_symbols = '';
597 1
			} else {
598 5
				preg_match('/\A([a-z]{1,10})?(\:|:\/\/|\/\/|:\/\/\/)\Z/i', $object->scheme, $matches);
599 5
				if (empty($matches[1]) && empty($matches[2])) {
600
					// restore values
601 2
					$object->scheme         = $org[0];
602 2
					$object->scheme_name    = $org[1];
603 2
					$object->scheme_symbols = $org[2];
604 2
					return FALSE;
605
				} else {
606
					// apply changes
607 3
					$matches                = $matches + array('', '', '');
608 3
					$object->scheme         = $matches[0];
609 3
					$object->scheme_name    = $matches[1];
610 3
					$object->scheme_symbols = $matches[2];
611
				}
612
			}
613
			
614 3
			return \uri\generate::string($object);
615
		}
616
		
617
		/**
618
		 * Alias of scheme()
619
		 * 
620
		 * @param  object $object  The object to modify
621
		 * @param  string $action  The action to take
622
		 * @param  string $str     The modfication
623
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
624
		 */
625 1
		public static function protocol(&$object, $action, $str) {
626 1
			return self::scheme($object, $action, $str);
627
		}
628
		
629
		/**
630
		 * Modfies the Username
631
		 * 
632
		 * @param  object $object  The object to modify
633
		 * @param  string $action  The action to take
634
		 * @param  string $str     The modfication
635
		 * @return string          Returns the resulting URI on success, FALSE otherwise
636
		 */
637 2
		public static function user(&$object, $action, $str) {
638 2
			$str = rawurlencode($str);
639
			
640 2
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
641 2
			return \uri\generate::string($object);
642
		}
643
		
644
		/**
645
		 * Alias of user()
646
		 * 
647
		 * @param  object $object  The object to modify
648
		 * @param  string $action  The action to take
649
		 * @param  string $str     The modfication
650
		 * @return string          Returns the resulting URI on success, FALSE otherwise
651
		 */
652 1
		public static function username(&$object, $action, $str) {
653 1
			return self::user($object, $action, $str);
654
		}
655
		
656
		/**
657
		 * Modfies the Password
658
		 * 
659
		 * @param  object $object  The object to modify
660
		 * @param  string $action  The action to take
661
		 * @param  string $str     The modfication
662
		 * @return string          Returns the resulting URI on success, FALSE otherwise
663
		 */
664 2
		public static function pass(&$object, $action, $str) {
665 2
			$str = rawurlencode($str);
666
			
667 2
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
668 2
			return \uri\generate::string($object);
669
		}
670
		
671
		/**
672
		 * Alias of pass()
673
		 * 
674
		 * @param  object $object  The object to modify
675
		 * @param  string $action  The action to take
676
		 * @param  string $str     The modfication
677
		 * @return string          Returns the resulting URI on success, FALSE otherwise
678
		 */
679 1
		public static function password(&$object, $action, $str) {
680 1
			return self::pass($object, $action, $str);
681
		}
682
		
683
		/**
684
		 * Modfies the Host
685
		 * 
686
		 * @param  object $object  The object to modify
687
		 * @param  string $action  The action to take
688
		 * @param  string $str     The modfication
689
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
690
		 */
691 5 View Code Duplication
		public static function host(&$object, $action, $str) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
692 5
			$org = $object->host;
693 5
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
694
			if ((
695 5
				!preg_match('/\A(([a-z0-9_]([a-z0-9\-_]+)?)\.)+[a-z0-9]([a-z0-9\-]+)?\Z/i', $object->host) // fqdn
696 5
				&&
697 1
				!preg_match('/\A([0-9]\.){3}[0-9]\Z/i', $object->host) // ip
698 5
			)) {
699 1
				$object->host = $org;
700 1
				return FALSE;
701
			}
702
			
703 4
			return \uri\generate::string($object);
704
		}
705
		
706
		/**
707
		 * Alias of host()
708
		 * 
709
		 * @param  object $object  The object to modify
710
		 * @param  string $action  The action to take
711
		 * @param  string $str     The modfication
712
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
713
		 */
714 1
		public static function domain(&$object, $action, $str) {
715 1
			return self::host($object, $action, $str);
716
		}
717
		
718
		/**
719
		 * Alias of host()
720
		 * 
721
		 * @param  object $object  The object to modify
722
		 * @param  string $action  The action to take
723
		 * @param  string $str     The modfication
724
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
725
		 */
726 1
		public static function fqdn(&$object, $action, $str) {
727 1
			return self::host($object, $action, $str);
728
		}
729
		
730
		/**
731
		 * Modfies the Port
732
		 * 
733
		 * @param  object $object  The object to modify
734
		 * @param  string $action  The action to take
735
		 * @param  string $str     The modfication
736
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
737
		 */
738 3
		public static function port(&$object, $action, $str) {
739 3
			$org = $object->port;
740 3
			if (isset($str[0]) && $str[0] == ':') {
741 1
				$str = substr($str, 1);
742 1
			}
743 3
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
744 3
			if (!(preg_match('/\A[0-9]{0,5}\Z/', $object->port) || empty($str))) {
745 1
				$object->port = $org;
746 1
				return FALSE;
747
			}
748
			
749 2
			return \uri\generate::string($object);
750
		}
751
		
752
		/**
753
		 * Modfies the Path
754
		 * 
755
		 * @param  object $object  The object to modify
756
		 * @param  string $action  The action to take
757
		 * @param  string $str     The modfication
758
		 * @return string          Returns the resulting URI on success, FALSE otherwise
759
		 */
760 4
		public static function path(&$object, $action, $str) {
761 4
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
762 4
			return \uri\generate::string($object);
763
		}
764
		
765
		/**
766
		 * Modfies the Query
767
		 * 
768
		 * @param  object $object  The object to modify
769
		 * @param  string $action  The action to take
770
		 * @param  string $str     The modfication
771
		 * @return string          Returns the resulting URI on success, FALSE otherwise
772
		 */
773 7 View Code Duplication
		public static function query(&$object, $action, $str) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
774 7
			if (isset($str[0]) && $str[0] == '?') {
775 1
				$str = substr($str, 1);
776 1
			}
777
			
778 7
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
779 7
			return \uri\generate::string($object);
780
		}
781
		
782
		/**
783
		 * Modfies the Fragment
784
		 * 
785
		 * @param  object $object  The object to modify
786
		 * @param  string $action  The action to take
787
		 * @param  string $str     The modfication
788
		 * @return string          Returns the resulting URI on success, FALSE otherwise
789
		 */
790 2 View Code Duplication
		public static function fragment(&$object, $action, $str) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
791 2
			if (isset($str[0]) && $str[0] == '#') {
792 1
				$str = substr($str, 1);
793 1
			}
794 2
			$str = urlencode($str);
795
			
796 2
			\uri\actions::callback($object, $action, __FUNCTION__, $str);
797 2
			return \uri\generate::string($object);
798
		}
799
	}
800
	
801
	
802
	
803
	/**
804
	 * The Actions Class
805
	 * 
806
	 * This class handlles the available actions
807
	 */
808
	class actions {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
809
		
810
		/**
811
		 * Acts as universal alias to the modify class, ensuring the call is viable
812
		 * 
813
		 * @param  object $object  The object to modify
814
		 * @param  string $action  The action to take
815
		 * @param  string $section The section of the object to modify
816
		 * @param  string $str     The modfication
817
		 * @return string|false    Returns the resulting URI on success, FALSE otherwise
818
		 */
819 26
		public static function modify(&$object, $action, $section, $str) {
820 26
			settype($section, 'string');
821 26
			settype($str, 'string');
822 26
			$section = strtolower($section);
823
			
824 26
			if (is_callable(array('\\uri\\modify', $section))) {
825 25
				return call_user_func_array(array('\\uri\\modify', $section), array(&$object, $action, $str));
826
			} else {
827 1
				return FALSE;
828
			}
829
		}
830
		
831
		/**
832
		 * Handles which action is taken; since there are only 3 very simple
833
		 * actions, it makes sense to put them all in 1 method.
834
		 * 
835
		 * @param  object $object  The object to modify
836
		 * @param  string $action  The action to take
837
		 * @param  string $section The section of the object to modify
838
		 * @param  string $str     The modfication
839
		 * @return void
840
		 */
841 25
		public static function callback(&$object, $action, $section, $str) {
842
			switch ($action) {
843 25
				case 'replace':
844 25
					$object->$section = $str;
845 25
					break;
846 12
				case 'prepend':
847 12
					$object->$section = $str.$object->$section;
848 12
					break;
849 12
				case 'append':
850 12
					$object->$section = $object->$section.$str;
851 12
			}
852 25
		}
853
		
854
	}
855
	
856
	
857
	
858
	/**
859
	 * The Generator Class
860
	 * 
861
	 * This class makes sure everything stays in sync and is produced correctly.
862
	 * Unlike the the modify class, this class only changes $object to keep
863
	 * things syncronized. It's primary purpose is to use the information in
864
	 * $object to create some type of returnable value.
865
	 */
866
	class generate {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
867
		
868
		/*** Methods ***/
869
		
870
		/**
871
		 * Generates all the aliases for $object
872
		 * 
873
		 * @param  object $object The object to modify
874
		 * @return void
875
		 */
876 37
		public static function aliases(&$object) {
877 37
			$object->protocol = &$object->scheme;
878 37
			$object->username = &$object->user;
879 37
			$object->password = &$object->pass;
880 37
			$object->domain   = &$object->host;
881 37
			$object->fqdn     = &$object->host;
882 37
		}
883
		
884
		/**
885
		 * Generate the scheme. This method exists to make changing how the scheme
886
		 * is generated easier; and will likely help prevent redundant code in the
887
		 * future
888
		 * 
889
		 * @param  object $object The object to modify
890
		 * @return void
891
		 */
892 28
		public static function scheme(&$object) {
893 28
			$object->scheme = $object->scheme_name.$object->scheme_symbols;
894 28
		}
895
		
896
		/**
897
		 * Regenerates the Authority string
898
		 * 
899
		 * @param  object $object The object to modify
900
		 * @return void
901
		 */
902 37
		public static function authority(&$object) {
903 37
			$str_arr = array($object->user);
904 37
			if (empty($object->user) == FALSE && empty($object->pass)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
905 3
				$str_arr[] = '@';
906 37
			} elseif (!empty($object->user)) {
907 27
				$str_arr[] = ':'.$object->pass.'@';
908 27
			}
909 37
			$str_arr[] = $object->host;
910 37
			if (!empty($object->port)) {
911 27
				$str_arr[] = ':'.$object->port;
912 27
			}
913 37
			$object->authority = implode('', $str_arr);
914 37
		}
915
		
916
		/**
917
		 * Generate a the full URI as a string, from the current object
918
		 * 
919
		 * @param  object $object The object to use
920
		 * @return string         The current URI string
921
		 */
922 25
		public static function string(&$object) {
923 25
			self::scheme($object);
924 25
			self::authority($object);
925 25
			$str_arr = array($object->scheme, $object->authority, $object->path);
926 25
			if (!empty($object->query)) {
927 18
				$str_arr[] = '?'.$object->query;
928 18
			}
929 25
			if (!empty($object->fragment)) {
930 17
				$str_arr[] = '#'.$object->fragment;
931 17
			}
932 25
			return implode('', $str_arr);
933
		}
934
		
935
		/**
936
		 * Generate a the full URI as a string, from the current object
937
		 * 
938
		 * @param  object $object The object to use
939
		 * @return array          The current URI as an array
940
		 */
941 2
		public static function to_array(&$object) {
942
			$arr = array(
943 2
				'authority'      => $object->authority,
944 2
				'fragment'       => $object->fragment,
945 2
				'host'           => $object->host,
946 2
				'pass'           => $object->pass,
947 2
				'path'           => $object->path,
948 2
				'port'           => $object->port,
949 2
				'query'          => $object->query,
950 2
				'scheme'         => $object->scheme,
951 2
				'scheme_name'    => $object->scheme_name,
952 2
				'scheme_symbols' => $object->scheme_symbols,
953 2
				'user'           => $object->user,
954 2
			);
955
			
956 2
			$arr['domain']   = &$arr['host'];
957 2
			$arr['fqdn']     = &$arr['host'];
958 2
			$arr['password'] = &$arr['pass'];
959 2
			$arr['protocol'] = &$arr['scheme'];
960 2
			$arr['username'] = &$arr['user'];
961
			
962 2
			ksort($arr);
963 2
			return $arr;
964
		}
965
		
966
		/**
967
		 * Returns various information about the current $path
968
		 * 
969
		 * @param  object $object The object to use
970
		 * @return array          Associative array of information about the current $path
971
		 */
972 1
		public static function path_info(&$object) {
973
			$defaults = array(
974 1
				'dirname' => '',
975 1
				'basename' => '',
976 1
				'extension' => '',
977 1
				'filename' => '',
978 1
				'array' => array()
979 1
			);
980
			
981 1
			$info          = pathinfo($object->path) + $defaults;
982 1
			$info['array'] = array_values(array_filter(explode('/', $object->path)));
983 1
			ksort($info);
984
			
985 1
			return $info;
986
		}
987
		
988
		/**
989
		 * The current $query string parsed into an array
990
		 * 
991
		 * @param  object $object The object to use
992
		 * @return array          The query string as an array
993
		 */
994 9
		public static function query_array(&$object) {
995 9
			parse_str($object->query, $return);
996 9
			return (array) $return;
997
		}
998
		
999
	}
1000
	
1001
	
1002
	/**
1003
	 * The Query Class
1004
	 * 
1005
	 * This class is resposible for checking and taking actions on the query
1006
	 * string. It should be noted that this class relies heavily on
1007
	 * generate::query_arr() and that excessive modification to the query
1008
	 * string should be done manually through generate::query_arr() and then
1009
	 * \uri\main::$query should be set (use http_build_query()).
1010
	 */
1011
	class query {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1012
		
1013
		/*** Methods ***/
1014
		
1015
		/**
1016
		 * Builds the query under RFC3986. RFC3986 is used as a replacement for
1017
		 * RFC1738 because it is more portable.
1018
		 * 
1019
		 * @param  array $query_array The array to build the query string from
1020
		 * @return string             The resulting query string
1021
		 */
1022 5
		private static function build_query($query_array) {
1023 5
			return http_build_query($query_array, '', '&', PHP_QUERY_RFC3986);
1024
		}
1025
		
1026
		/**
1027
		 * Adds query var to the query string if it is not already set and returns
1028
		 * TRUE. Otherwise it returns FALSE
1029
		 * 
1030
		 * @param  object $object The object to modify
1031
		 * @param  string $key    The key to add
1032
		 * @param  string $value  The value of $key
1033
		 * @return boolean        TRUE on success, FALSE otherwise
1034
		 */
1035 2
		public static function add(&$object, $key, $value) {
1036 2
			$qarray = \uri\generate::query_array($object);
1037 2 View Code Duplication
			if (!isset($qarray[$key])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1038 2
				$qarray[$key] = $value;
1039 2
				\uri\actions::modify($object, 'replace', 'QUERY', self::build_query($qarray));
1040 2
				return TRUE;
1041
			}
1042 1
			return FALSE;
1043
		}
1044
		
1045
		/**
1046
		 * Adds query var to the query string regardless if it already set or not
1047
		 * 
1048
		 * @param  object $object The object to modify
1049
		 * @param  string $key    The key to replace
1050
		 * @param  string $value  The value of $key
1051
		 * @return void
1052
		 */
1053 2
		public static function replace(&$object, $key, $value) {
1054 2
			$qarray       = \uri\generate::query_array($object);
1055 2
			$qarray[$key] = $value;
1056 2
			\uri\actions::modify($object, 'replace', 'QUERY', self::build_query($qarray));
1057 2
		}
1058
		
1059
		/**
1060
		 * Removes $key from the query if it exists
1061
		 * 
1062
		 * @param  object $object The object to modify
1063
		 * @param  string $key    The key to remove
1064
		 * @return void
1065
		 */
1066 2
		public static function remove(&$object, $key) {
1067 2
			$qarray = \uri\generate::query_array($object);
1068 2 View Code Duplication
			if (isset($qarray[$key])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1069 2
				unset($qarray[$key]);
1070 2
				\uri\actions::modify($object, 'replace', 'QUERY', self::build_query($qarray));
1071 2
			}
1072 2
		}
1073
		
1074
		/**
1075
		 * Checks if $key exists in the query
1076
		 * 
1077
		 * @param  object $object The object to use
1078
		 * @param  string $key    The key to search for
1079
		 * @return boolean        TRUE if the $key exists, FALSE otherwise
1080
		 */
1081 1
		public static function exists(&$object, $key) {
1082 1
			$qarray = \uri\generate::query_array($object);
1083 1
			return isset($qarray[$key]);
1084
		}
1085
		
1086
		/**
1087
		 * Gets a specific var's value from the query. It is HIGHLY recommended
1088
		 * that you use query_arr() instead, when fetching multiple values from
1089
		 * the same query string. Returns NULL if $key does not exist.
1090
		 * 
1091
		 * @param  object $object The object to use
1092
		 * @param  string $key    The key to get
1093
		 * @return mixed|null     The value of $key, or NULL if it does not exist.
1094
		 */
1095 1
		public static function get(&$object, $key) {
1096 1
			$qarray = \uri\generate::query_array($object);
1097 1
			if (isset($qarray[$key])) {
1098 1
				return $qarray[$key];
1099
			}
1100 1
			return NULL;
1101
		}
1102
		
1103
		/**
1104
		 * Renames a specific $key within the query. If the key exists within query
1105
		 * string and is successfully renamed, the TRUE is returned. Otherwise
1106
		 * FALSE is returned.
1107
		 * 
1108
		 * @param  object $object  The object to modify
1109
		 * @param  string $key     The key to rename
1110
		 * @param  string $new_key The new name of $key
1111
		 * @return boolean         TRUE on success, FALSE otherwise
1112
		 */
1113 3
		public static function rename(&$object, $key, $new_key) {
1114 3
			$qarray = \uri\generate::query_array($object);
1115 3
			if (isset($qarray[$key])) {
1116 2
				$qarray[$new_key] = $qarray[$key];
1117 2
				unset($qarray[$key]);
1118 2
				\uri\actions::modify($object, 'replace', 'QUERY', self::build_query($qarray));
1119 2
				return TRUE;
1120
			}
1121 2
			return FALSE;
1122
		}
1123
	}
1124
	
1125
	/**
1126
	 * The Chaining Class
1127
	 * 
1128
	 * This class is like \uri\main except that only actionable methods can be
1129
	 * called. This mean they must either modify $object or print something. It
1130
	 * also means that the normal return of all methods is replaced with this
1131
	 * class in its' current instance.
1132
	 */
1133
	class chain {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1134
		
1135
		/*** Variables ***/
1136
		private $class;
1137
		private $object;
1138
		public  $error_count;
1139
		
1140
		/*** Magic Methods ***/
1141
		
1142
		/**
1143
		 * Simple method to init a chainable object
1144
		 * 
1145
		 * @param object $class The current instance of \uri\main
1146
		 */
1147 37
		public function __construct(&$class) {
1148 37
			$this->class       = &$class;
1149 37
			$this->object      = &$class->object;
1150 37
			$this->error_count = 0;
1151 37
			return $this;
0 ignored issues
show
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
1152
		}
1153
		
1154
		/*** Methods ***/
1155
		
1156
		/**
1157
		 * Chainable alias to \uri\main::replace() within the current instance
1158
		 * 
1159
		 * @return object This instance
1160
		 */
1161 1
		public function p_str($prepend = '', $append = '') {
1162 1
			echo $prepend.\uri\generate::string($this->object).$append;
1163 1
			return $this;
1164
		}
1165
		
1166
		/**
1167
		 * Chainable alias to \uri\main::replace() within the current instance
1168
		 * 
1169
		 * @param  string $section The section to replace
1170
		 * @param  string $str     The string to replace the section with
1171
		 * @return object          This instance
1172
		 */
1173 3
		public function replace($section, $str) {
1174 3
			if (\uri\actions::modify($this->object, 'replace', $section, $str) === FALSE) {
1175 1
				$this->error_count++;
1176 1
			}
1177 3
			return $this;
1178
		}
1179
		
1180
		/**
1181
		 * Chainable alias to \uri\main::prepend() within the current instance
1182
		 * 
1183
		 * @param  string $section The section to prepend
1184
		 * @param  string $str     The string to prepend the section with
1185
		 * @return object          This instance
1186
		 */
1187 2
		public function prepend($section, $str) {
1188 2
			if (\uri\actions::modify($this->object, 'prepend', $section, $str) === FALSE) {
1189 1
				$this->error_count++;
1190 1
			}
1191 2
			return $this;
1192
		}
1193
		
1194
		/**
1195
		 * Chainable alias to \uri\main::append() within the current instance
1196
		 * 
1197
		 * @param  string $section The section to append
1198
		 * @param  string $str     The string to append the section with
1199
		 * @return object          This instance
1200
		 */
1201 2
		public function append($section, $str) {
1202 2
			if (\uri\actions::modify($this->object, 'append', $section, $str) === FALSE) {
1203 1
				$this->error_count++;
1204 1
			}
1205 2
			return $this;
1206
		}
1207
		
1208
		/**
1209
		 * Chainable alias to \uri\main::query_add() within the current instance
1210
		 * 
1211
		 * @param  string $key   The key to add
1212
		 * @param  mixed  $value The value of $key
1213
		 * @return object        This instance
1214
		 */
1215 1
		public function query_add($key, $value) {
1216 1
			\uri\query::add($this->object, $key, $value);
1217 1
			return $this;
1218
		}
1219
		
1220
		/**
1221
		 * Chainable alias to \uri\main::query_replace() within the current instance
1222
		 * 
1223
		 * @param  string $key   The key to replace
1224
		 * @param  mixed  $value The value of $key
1225
		 * @return object        This instance
1226
		 */
1227 1
		public function query_replace($key, $value) {
1228 1
			\uri\query::replace($this->object, $key, $value);
1229 1
			return $this;
1230
		}
1231
		
1232
		/**
1233
		 * Chainable alias to \uri\main::query_remove() within the current instance
1234
		 * 
1235
		 * @param  string $key The key to remove
1236
		 * @return object      This instance
1237
		 */
1238 1
		public function query_remove($key) {
1239 1
			\uri\query::remove($this->object, $key);
1240 1
			return $this;
1241
		}
1242
		
1243
		/**
1244
		 * Chainable alias to \uri\main::query_rename() within the current instance
1245
		 * 
1246
		 * @param  string $key     The key to rename
1247
		 * @param  string $new_key The new name of $key
1248
		 * @return object          This instance
1249
		 */
1250 2
		public function query_rename($key, $new_key) {
1251 2
			if (\uri\query::rename($this->object, $key, $new_key) === FALSE) {
1252 1
				$this->error_count++;
1253 1
			}
1254 2
			return $this;
1255
		}
1256
		
1257
		/**
1258
		 * Chainable alias to \uri\main::reset() within the current instance
1259
		 * 
1260
		 * @return object This instance
1261
		 */
1262 1
		public function reset() {
1263 1
			$this->class->__construct($this->class->input);
1264 1
			return $this;
1265
		}
1266
		
1267
		/**
1268
		 * Provides a simple error handle for invalid chainable methods
1269
		 * 
1270
		 * @param  array $trace Debug Backtrace
1271
		 * @return void
1272
		 */
1273 1
		private function _err($trace) {
1274 1
			$this->error_count++;
1275 1
			trigger_error(
1276 1
				sprintf(
1277 1
					'The method <code>%1$s()</code> cannot be chained in <b>%2$s</b> on line <b>%3$s</b>. Error triggered',
1278 1
					$trace[0]['function'],
1279 1
					$trace[0]['file'],
1280 1
					$trace[0]['line']
1281 1
				),
1282
				E_USER_NOTICE
1283 1
			);
1284 1
		}
1285
		
1286
		/*** Invalid Chaining Methods ***/
1287
		
1288
		/**
1289
		 * Invalid Chaining Method
1290
		 */
1291 1
		public function str() {
1292 1
			$this->_err(debug_backtrace());
1293 1
			return $this;
1294
		}
1295
		
1296
		/**
1297
		 * Invalid Chaining Method
1298
		 */
1299 1
		public function to_string() {
1300 1
			$this->_err(debug_backtrace());
1301 1
			return $this;
1302
		}
1303
		
1304
		/**
1305
		 * Invalid Chaining Method
1306
		 */
1307 1
		public function arr() {
1308 1
			$this->_err(debug_backtrace());
1309 1
			return $this;
1310
		}
1311
		
1312
		/**
1313
		 * Invalid Chaining Method
1314
		 */
1315 1
		public function to_array() {
1316 1
			$this->_err(debug_backtrace());
1317 1
			return $this;
1318
		}
1319
		
1320
		/**
1321
		 * Invalid Chaining Method
1322
		 */
1323 1
		public function path_info() {
1324 1
			$this->_err(debug_backtrace());
1325 1
			return $this;
1326
		}
1327
		
1328
		/**
1329
		 * Invalid Chaining Method
1330
		 */
1331 1
		public function query_array() {
1332 1
			$this->_err(debug_backtrace());
1333 1
			return $this;
1334
		}
1335
		
1336
		/**
1337
		 * Invalid Chaining Method
1338
		 */
1339 1
		public function query_exists() {
1340 1
			$this->_err(debug_backtrace());
1341 1
			return $this;
1342
		}
1343
		
1344
		/**
1345
		 * Invalid Chaining Method
1346
		 */
1347 1
		public function query_get() {
1348 1
			$this->_err(debug_backtrace());
1349 1
			return $this;
1350
		}
1351
	}
1352
}