Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • CacheControlHeader
  • CallableDispatcher
  • ContentDispositionHeader
  • ContentTypeHeader
  • DateHeader
  • Dispatcher
  • File
  • FileList
  • Header
  • HeaderParameter
  • Headers
  • Helpers
  • RedirectResponse
  • Request
  • Response
  • WeightedDispatcher

Interfaces

  • IDispatcher

Exceptions

  • ForceRedirect
  • HTTPError
  • MethodNotSupported
  • NotFound
  • ServiceUnavailable
  • StatusCodeNotValid

Functions

  • dispatch
  • get_dispatcher
  • get_initial_request
  1 <?php
  2 
  3 /*
  4  * This file is part of the ICanBoogie package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
  7  *
  8  * For the full copyright and license information, please view the LICENSE
  9  * file that was distributed with this source code.
 10  */
 11 
 12 namespace ICanBoogie\HTTP;
 13 
 14 use ICanBoogie\PropertyNotWritable;
 15 
 16 /**
 17  * An HTTP request.
 18  *
 19  * <pre>
 20  * <?php
 21  *
 22  * use ICanBoogie\HTTP\Request;
 23  *
 24  * # Creating the main request
 25  *
 26  * $request = Request::from($_SERVER);
 27  *
 28  * # Creating a request from scratch, with the current environment.
 29  *
 30  * $request = Request::from(array(
 31  *
 32  *     'uri' => '/path/to/my/page.html?page=2',
 33  *     'user_agent' => 'Mozilla'
 34  *     'is_get' => true,
 35  *     'is_xhr' => true,
 36  *     'is_local' => true
 37  *
 38  * ), array($_SERVER));
 39  * </pre>
 40  *
 41  * @method Response connect() connect(array $params)
 42  * @method Response delete() delete(array $params)
 43  * @method Response get() get(array $params)
 44  * @method Response head() head(array $params)
 45  * @method Response options() options(array $params)
 46  * @method Response post() post(array $params)
 47  * @method Response put() put(array $params)
 48  * @method Response patch() patch(array $params)
 49  * @method Response trace() trace(array $params)
 50  *
 51  * @property-read \ICanBoogie\HTTP\Request\Context $context the request's context.
 52  * @property-read Request $previous Previous request.
 53  * @property-read FileList $files The files associated with the request.
 54  *
 55  * @property-read boolean $authorization Authorization of the request.
 56  * @property-read int $content_length Length of the request content.
 57  * @property-read int $cache_control A {@link \ICanBoogie\HTTP\CacheControlHeader} object.
 58  * @property-read string $ip Remote IP of the request.
 59  * @property-read boolean $is_delete Is this a `DELETE` request?
 60  * @property-read boolean $is_get Is this a `GET` request?
 61  * @property-read boolean $is_head Is this a `HEAD` request?
 62  * @property-read boolean $is_options Is this a `OPTIONS` request?
 63  * @property-read boolean $is_patch Is this a `PATCH` request?
 64  * @property-read boolean $is_post Is this a `POST` request?
 65  * @property-read boolean $is_put Is this a `PUT` request?
 66  * @property-read boolean $is_trace Is this a `TRACE` request?
 67  * @property-read boolean $is_local Is this a local request?
 68  * @property-read boolean $is_xhr Is this an Ajax request?
 69  * @property-read string $method Method of the request.
 70  * @property-read string $normalized_path Path of the request normalized using the {@link \ICanBoogie\normalize_url_path()} function.
 71  * @property-read string $path Path info of the request.
 72  * @property-read int $port Port of the request.
 73  * @property-read string $query_string Query string of the request.
 74  * @property-read string $script_name Name of the entered script.
 75  * @property-read string $referer Referer of the request.
 76  * @property-read string $user_agent User agent of the request.
 77  * @property-read string $uri URI of the request. The `QUERY_STRING` value of the environment
 78  * is overwritten when the instance is created with the {@link $uri} property.
 79  *
 80  * @see http://en.wikipedia.org/wiki/Uniform_resource_locator
 81  */
 82 class Request extends \ICanBoogie\Object implements \ArrayAccess, \IteratorAggregate
 83 {
 84     /*
 85      * HTTP methods as defined by the {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html Hypertext Transfert protocol 1.1}.
 86      */
 87     const METHOD_ANY = 'ANY';
 88     const METHOD_CONNECT = 'CONNECT';
 89     const METHOD_DELETE = 'DELETE';
 90     const METHOD_GET = 'GET';
 91     const METHOD_HEAD = 'HEAD';
 92     const METHOD_OPTIONS = 'OPTIONS';
 93     const METHOD_POST = 'POST';
 94     const METHOD_PUT = 'PUT';
 95     const METHOD_PATCH = 'PATCH';
 96     const METHOD_TRACE = 'TRACE';
 97 
 98     static public $methods = array
 99     (
100         self::METHOD_CONNECT,
101         self::METHOD_DELETE,
102         self::METHOD_GET,
103         self::METHOD_HEAD,
104         self::METHOD_OPTIONS,
105         self::METHOD_POST,
106         self::METHOD_PUT,
107         self::METHOD_PATCH,
108         self::METHOD_TRACE
109     );
110 
111     /**
112      * Current request.
113      *
114      * @var Request
115      */
116     static protected $current_request;
117 
118     /**
119      * Returns the current request.
120      *
121      * @return Request
122      */
123     static public function get_current_request()
124     {
125         return self::$current_request;
126     }
127 
128     /**
129      * Parameters extracted from the request path.
130      *
131      * @var array
132      */
133     public $path_params = array();
134 
135     /**
136      * Parameters defined by the query string.
137      *
138      * @var array
139      */
140     public $query_params = array();
141 
142     /**
143      * Parameters defined by the request body.
144      *
145      * @var array
146      */
147     public $request_params = array();
148 
149     /**
150      * Union of {@link $path_params}, {@link $request_params} and {@link $query_params}.
151      *
152      * @var array
153      */
154     public $params;
155 
156     /**
157      * General purpose container.
158      *
159      * @var Request\Context
160      */
161     protected $context;
162 
163     /**
164      * The headers of the request.
165      *
166      * @var Headers
167      */
168     public $headers;
169 
170     /**
171      * Request environment.
172      *
173      * @var array
174      */
175     protected $env;
176 
177     /**
178      * Files associated with the request.
179      *
180      * @var FileList
181      */
182     protected $files;
183 
184     protected function get_files()
185     {
186         if ($this->files instanceof FileList)
187         {
188             return $this->files;
189         }
190 
191         return $this->files = FileList::from($this->files);
192     }
193 
194     /**
195      * Previous request.
196      *
197      * @var Request
198      */
199     protected $previous;
200 
201     /**
202      * A request can be created from the `$_SERVER` super global array. In that case `$_SERVER` is
203      * used as environment the request is created with the following properties:
204      *
205      * - {@link $cookie}: a reference to the `$_COOKIE` super global array.
206      * - {@link $path_params}: initialized to an empty array.
207      * - {@link $query_params}: a reference to the `$_GET` super global array.
208      * - {@link $request_params}: a reference to the `$_POST` super global array.
209      * - {@link $files}: a reference to the `$_FILES` super global array.
210      *
211      * A request can also be created from an array of properties, in which case most of them are
212      * mapped to the `$env` constructor param. For instance, `is_xhr` set the
213      * `HTTP_X_REQUESTED_WITH` enviroment property to 'XMLHttpRequest'. In fact, only the
214      * following parameters are preserved:
215      *
216      * - `path_params`
217      * - `query_params`
218      * - `request_params`
219      * - `files`: The files associated with the request.
220      * - `headers`: The header fields of the request. If specified, the headers available in the
221      * environement are ignored.
222      *
223      * @param array $properties
224      * @param array $construct_args
225      * @param string $class_name
226      *
227      * @throws \InvalidArgumentException in attempt to use a property that is not mapped to an
228      * environment property.
229      *
230      * @return Request
231      */
232     static public function from($properties=null, array $construct_args=array(), $class_name=null)
233     {
234         if ($properties === $_SERVER)
235         {
236             return parent::from([
237 
238                 'cookies' => &$_COOKIE,
239                 'path_params' => [],
240                 'query_params' => &$_GET,
241                 'request_params' => &$_POST,
242                 'files' => &$_FILES
243 
244             ], [ $_SERVER ]);
245         }
246 
247         $env = isset($construct_args[0]) ? $construct_args[0] : [];
248 
249         if (is_string($properties))
250         {
251             $properties = [ 'uri' => $properties ];
252             $env['QUERY_STRING'] = '';
253         }
254 
255         if ($properties)
256         {
257             $mappers = self::get_properties_mappers();
258 
259             foreach ($properties as $property => &$value)
260             {
261                 if (empty($mappers[$property]))
262                 {
263                     throw new \InvalidArgumentException("Unsupported property: <q>$property</q>.");
264                 }
265 
266                 #
267                 # The mapper returns `true` if the property is to be preserved.
268                 #
269 
270                 $value = $mappers[$property]($value, $env);
271 
272                 if ($value === null)
273                 {
274                     unset($properties[$property]);
275 
276                     continue;
277                 }
278             }
279 
280             $construct_args[0] = $env;
281         }
282 
283         if (!empty($env['QUERY_STRING']))
284         {
285             parse_str($env['QUERY_STRING'], $properties['query_params']);
286         }
287 
288         #
289         # Because Object::from() serialize/unserialize the properties to create the instance,
290         # objects are recreated as well. For instance, if a `Headers` instance is provided using
291         # the `headers` property, a clone of that instance will be used by the instance. To
292         # circumvent that we set back objects that were defined in the properties. Depending on
293         # the future updates to `Object` the code might become obsolete.
294         #
295 
296         $instance = parent::from($properties, $construct_args, $class_name);
297 
298         foreach ($properties as $property => $value)
299         {
300             if (!is_object($value))
301             {
302                 continue;
303             }
304 
305             $instance->$property = $value;
306         }
307 
308         return $instance;
309     }
310 
311     /**
312      * Returns properties to env mappers.
313      *
314      * @return array
315      */
316     static public function get_properties_mappers()
317     {
318         static $mappers;
319 
320         if (!$mappers)
321         {
322             $mappers = array
323             (
324                 'path_params' =>    function($value) { return $value; },
325                 'query_params' =>   function($value) { return $value; },
326                 'request_params' => function($value) { return $value; },
327                 'files' =>          function($value) { return $value; },
328                 'headers' =>        function($value) { return ($value instanceof Headers) ? $value : new Headers($value); },
329 
330                 'cache_control' =>  function($value, array &$env) { $env['HTTP_CACHE_CONTROL'] = $value; },
331                 'content_length' => function($value, array &$env) { $env['CONTENT_LENGTH'] = $value; },
332                 'ip' =>             function($value, array &$env) { if ($value) $env['REMOTE_ADDR'] = $value; },
333                 'is_local' =>       function($value, array &$env) { if ($value) $env['REMOTE_ADDR'] = '::1'; },
334                 'is_delete' =>      function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_DELETE; },
335                 'is_connect' =>     function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_CONNECT; },
336                 'is_get' =>         function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_GET; },
337                 'is_head' =>        function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_HEAD; },
338                 'is_options' =>     function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_OPTIONS; },
339                 'is_patch' =>       function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_PATCH; },
340                 'is_post' =>        function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_POST; },
341                 'is_put' =>         function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_PUT; },
342                 'is_trace' =>       function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = Request::METHOD_TRACE; },
343                 'is_xhr' =>         function($value, array &$env) { if ($value) $env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; },
344                 'method' =>         function($value, array &$env) { if ($value) $env['REQUEST_METHOD'] = $value; },
345                 'path' =>           function($value, array &$env) { $env['REQUEST_URI'] = $value; }, // TODO-20130521: handle query string
346                 'referer' =>        function($value, array &$env) { $env['HTTP_REFERER'] = $value; },
347                 'uri' =>            function($value, array &$env) { $env['REQUEST_URI'] = $value; $qs = strpos($value, '?'); $env['QUERY_STRING'] = $qs === false ? '' : substr($value, $qs + 1); },
348                 'user_agent' =>     function($value, array &$env) { $env['HTTP_USER_AGENT'] = $value; }
349             );
350         }
351 
352         return $mappers;
353     }
354 
355     /**
356      * Initialize the properties {@link $env}, {@link $headers} and {@link $context}.
357      *
358      * If the {@link $params} property is `null` it is set with an usinon of {@link $path_params},
359      * {@link $request_params} and {@link $query_params}.
360      *
361      * @param array $env Environment of the request, usually the `$_SERVER` super global.
362      */
363     protected function __construct(array $env=[])
364     {
365         $this->env = $env;
366 
367         if (!$this->headers)
368         {
369             $this->headers = new Headers($env);
370         }
371 
372         $this->context = new Request\Context($this);
373 
374         if ($this->params === null)
375         {
376             $this->params = $this->path_params + $this->request_params + $this->query_params;
377         }
378     }
379 
380     /**
381      * Dispatch the request.
382      *
383      * The {@link previous} property is used for request chaining. The {@link $current_request}
384      * class property is set to the current request.
385      *
386      * @param string|null $method The request method. Use this parameter to override the request
387      * method.
388      * @param array|null $params The request parameters. Use this parameter to override the request
389      * parameters. The {@link $path_params}, {@link $query_params} and
390      * {@link $request_params} are set to empty arrays. The provided parameters are set to the
391      * {@link $params} property.
392      *
393      * Note: If an exception is thrown during dispatch {@link $current_request} is not updated!
394      *
395      * @return Response The response to the request.
396      */
397     public function __invoke($method=null, $params=null)
398     {
399         if ($method !== null)
400         {
401             $this->env['REQUEST_METHOD'] = $method;
402         }
403 
404         // FIXME-20130814: if the method is not the same, the instance should be cloned, or the method restored.
405 
406         if ($params !== null)
407         {
408             $this->path_params = array();
409             $this->query_params = array();
410             $this->request_params = array();
411             $this->params = $params;
412         }
413 
414         $this->previous = self::$current_request;
415 
416         self::$current_request = $this;
417 
418         $response = dispatch($this);
419 
420         self::$current_request = $this->previous;
421 
422         return $response;
423     }
424 
425     /**
426      * Overrides the method to provide a virtual method for each request method.
427      *
428      * Example:
429      *
430      * <pre>
431      * <?php
432      *
433      * Request::from('/api/core/aloha')->get();
434      * </pre>
435      */
436     public function __call($method, $arguments)
437     {
438         $http_method = strtoupper($method);
439 
440         if (in_array($http_method, self::$methods))
441         {
442             array_unshift($arguments, $http_method);
443 
444             return call_user_func_array(array($this, '__invoke'), $arguments);
445         }
446 
447         return parent::__call($method, $arguments);
448     }
449 
450     /**
451      * Checks if the specified param exists in the request.
452      */
453     public function offsetExists($param)
454     {
455         return isset($this->params[$param]);
456     }
457 
458     /**
459      * Get the specified param from the request.
460      */
461     public function offsetGet($param)
462     {
463         return isset($this->params[$param]) ? $this->params[$param] : null;
464     }
465 
466     /**
467      * Set the specified param to the specified value.
468      */
469     public function offsetSet($param, $value)
470     {
471         $this->params[$param] = $value;
472         $this->request_params[$param] = $value;
473     }
474 
475     /**
476      * Remove the specified param from the request.
477      */
478     public function offsetUnset($param)
479     {
480         unset($this->params[$param]);
481     }
482 
483     /**
484      * Returns an array iterator for the params.
485      *
486      * @return \ArrayIterator
487      */
488     public function getIterator()
489     {
490         return new \ArrayIterator($this->params);
491     }
492 
493     /**
494      * Returns the previous request.
495      *
496      * @return \ICanBoogie\HTTP\Request
497      */
498     protected function get_previous()
499     {
500         return $this->previous;
501     }
502 
503     /**
504      * Returns the request's context.
505      *
506      * @return Request\Context
507      */
508     protected function get_context()
509     {
510         return $this->context;
511     }
512 
513     /**
514      * Returns the `Cache-Control` header.
515      *
516      * @return \ICanBoogie\HTTP\CacheControlHeader
517      */
518     protected function get_cache_control()
519     {
520         return $this->headers['Cache-Control'];
521     }
522 
523     /**
524      * Returns the script name.
525      *
526      * The setter is volatile, the value is returned from the ENV key `SCRIPT_NAME`.
527      *
528      * @return string
529      */
530     protected function get_script_name()
531     {
532         return $this->env['SCRIPT_NAME'];
533     }
534 
535     /**
536      * Returns the request method.
537      *
538      * This is the getter for the `method` magic property.
539      *
540      * The method is retrieved from {@link $env}, if the key `REQUEST_METHOD` is not defined,
541      * the method defaults to {@link METHOD_GET}.
542      *
543      * @throws MethodNotSupported when the request method is not supported.
544      *
545      * @return string
546      */
547     protected function get_method()
548     {
549         $method = isset($this->env['REQUEST_METHOD']) ? $this->env['REQUEST_METHOD'] : self::METHOD_GET;
550 
551         if ($method == self::METHOD_POST && !empty($this->request_params['_method']))
552         {
553             $method = strtoupper($this->request_params['_method']);
554         }
555 
556         if (!in_array($method, self::$methods))
557         {
558             throw new MethodNotSupported($method);
559         }
560 
561         return $method;
562     }
563 
564     /**
565      * Returns the query string of the request.
566      *
567      * The value is obtained from the `QUERY_STRING` key of the {@link $env} array.
568      *
569      * @param string|null
570      */
571     protected function get_query_string()
572     {
573         return isset($this->env['QUERY_STRING']) ? $this->env['QUERY_STRING'] : null;
574     }
575 
576     /**
577      * Returns the content lenght of the request.
578      *
579      * The value is obtained from the `CONTENT_LENGTH` key of the {@link $env} array.
580      *
581      * @return int|null
582      */
583     protected function get_content_length()
584     {
585         return isset($this->env['CONTENT_LENGTH']) ? $this->env['CONTENT_LENGTH'] : null;
586     }
587 
588     /**
589      * Returns the referer of the request.
590      *
591      * The value is obtained from the `HTTP_REFERER` key of the {@link $env} array.
592      *
593      * @return string|null
594      */
595     protected function get_referer()
596     {
597         return isset($this->env['HTTP_REFERER']) ? $this->env['HTTP_REFERER'] : null;
598     }
599 
600     /**
601      * Returns the user agent of the request.
602      *
603      * The value is obtained from the `HTTP_USER_AGENT` key of the {@link $env} array.
604      *
605      * @return string|null
606      */
607     protected function get_user_agent()
608     {
609         return isset($this->env['HTTP_USER_AGENT']) ? $this->env['HTTP_USER_AGENT'] : null;
610     }
611 
612     /**
613      * Checks if the request method is `DELETE`.
614      *
615      * @return boolean
616      */
617     protected function get_is_delete()
618     {
619         return $this->method == self::METHOD_DELETE;
620     }
621 
622     /**
623      * Checks if the request method is `GET`.
624      *
625      * @return boolean
626      */
627     protected function get_is_get()
628     {
629         return $this->method == self::METHOD_GET;
630     }
631 
632     /**
633      * Checks if the request method is `HEAD`.
634      *
635      * @return boolean
636      */
637     protected function get_is_head()
638     {
639         return $this->method == self::METHOD_HEAD;
640     }
641 
642     /**
643      * Checks if the request method is `OPTIONS`.
644      *
645      * @return boolean
646      */
647     protected function get_is_options()
648     {
649         return $this->method == self::METHOD_OPTIONS;
650     }
651 
652     /**
653      * Checks if the request method is `PATCH`.
654      *
655      * @return boolean
656      */
657     protected function get_is_patch()
658     {
659         return $this->method == self::METHOD_PATCH;
660     }
661 
662     /**
663      * Checks if the request method is `POST`.
664      *
665      * @return boolean
666      */
667     protected function get_is_post()
668     {
669         return $this->method == self::METHOD_POST;
670     }
671 
672     /**
673      * Checks if the request method is `PUT`.
674      *
675      * @return boolean
676      */
677     protected function get_is_put()
678     {
679         return $this->method == self::METHOD_PUT;
680     }
681 
682     /**
683      * Checks if the request method is `TRACE`.
684      *
685      * @return boolean
686      */
687     protected function get_is_trace()
688     {
689         return $this->method == self::METHOD_TRACE;
690     }
691 
692     /**
693      * Checks if the request is a `XMLHTTPRequest`.
694      *
695      * @return boolean
696      */
697     protected function get_is_xhr()
698     {
699         return !empty($this->env['HTTP_X_REQUESTED_WITH']) && preg_match('/XMLHttpRequest/', $this->env['HTTP_X_REQUESTED_WITH']);
700     }
701 
702     /**
703      * Checks if the request is local.
704      *
705      * @return boolean
706      */
707     protected function get_is_local()
708     {
709         static $patterns = array('::1', '/^127\.0\.0\.\d{1,3}$/', '/^0:0:0:0:0:0:0:1(%.*)?$/');
710 
711         $ip = $this->ip;
712 
713         foreach ($patterns as $pattern)
714         {
715             if ($pattern{0} == '/')
716             {
717                 if (preg_match($pattern, $ip))
718                 {
719                     return true;
720                 }
721             }
722             else if ($pattern == $ip)
723             {
724                 return true;
725             }
726         }
727 
728         return false;
729     }
730 
731     /**
732      * Returns the remote IP of the request.
733      *
734      * If defined, the `HTTP_X_FORWARDED_FOR` header is used to retrieve the original IP.
735      *
736      * If the `REMOTE_ADDR` header is empty the request is considered local thus `::1` is returned.
737      *
738      * @see http://en.wikipedia.org/wiki/X-Forwarded-For
739      *
740      * @return string
741      */
742     protected function get_ip()
743     {
744         if (isset($this->env['HTTP_X_FORWARDED_FOR']))
745         {
746             $addr = $this->env['HTTP_X_FORWARDED_FOR'];
747 
748             list($addr) = explode(',', $addr);
749 
750             return $addr;
751         }
752 
753         return (isset($this->env['REMOTE_ADDR']) ? $this->env['REMOTE_ADDR'] : null) ?: '::1';
754     }
755 
756     protected function get_authorization()
757     {
758         if (isset($this->env['HTTP_AUTHORIZATION']))
759         {
760             return $this->env['HTTP_AUTHORIZATION'];
761         }
762         else if (isset($this->env['X-HTTP_AUTHORIZATION']))
763         {
764             return $this->env['X-HTTP_AUTHORIZATION'];
765         }
766         else if (isset($this->env['X_HTTP_AUTHORIZATION']))
767         {
768             return $this->env['X_HTTP_AUTHORIZATION'];
769         }
770         else if (isset($this->env['REDIRECT_X_HTTP_AUTHORIZATION']))
771         {
772             return $this->env['REDIRECT_X_HTTP_AUTHORIZATION'];
773         }
774     }
775 
776     /**
777      * Returns the `REQUEST_URI` environment key.
778      *
779      * If the `REQUEST_URI` key is not defined by the environment, the value is fetched from
780      * the `$_SERVER` array. If the key is not defined in the `$_SERVER` array `null` is returned.
781      *
782      * @return string
783      */
784     protected function get_uri()
785     {
786         return isset($this->env['REQUEST_URI']) ? $this->env['REQUEST_URI'] : (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null);
787     }
788 
789     /**
790      * Returns the port of the request.
791      *
792      * @return int
793      */
794     protected function get_port()
795     {
796         return $this->env['REQUEST_PORT'];
797     }
798 
799     /**
800      * Returns the path of the request, that is the `REQUEST_URI` without the query string.
801      *
802      * @return string
803      */
804     protected function get_path()
805     {
806         $uri = $this->uri;
807         $qs_pos = strpos($uri, '?');
808 
809         return ($qs_pos === false) ? $uri : substr($uri, 0, $qs_pos);
810     }
811 
812     /**
813      * Returns the {@link $path} property normalized using the
814      * {@link \ICanBoogie\normalize_url_path()} function.
815      *
816      * @return string
817      */
818     protected function get_normalized_path()
819     {
820         return \ICanBoogie\normalize_url_path($this->path);
821     }
822 
823     /**
824      * Returns the extension of the path info.
825      *
826      * @return mixed
827      */
828     protected function get_extension()
829     {
830         return pathinfo($this->path, PATHINFO_EXTENSION);
831     }
832 
833     protected function lazy_set_params($params)
834     {
835         return $params;
836     }
837 
838     /**
839      * Returns the union of the {@link path_params}, {@link request_params} and
840      * {@link query_params} properties.
841      *
842      * This method is the getter of the {@link $params} magic property.
843      *
844      * @return array
845      */
846     protected function lazy_get_params()
847     {
848         return $this->path_params + $this->request_params + $this->query_params;
849     }
850 }
851 
852 namespace ICanBoogie\HTTP\Request;
853 
854 use ICanBoogie\PropertyNotWritable;
855 
856 /**
857  * The context of a request.
858  *
859  * This is a general purpose container used to store the objects and variables related to a
860  * request.
861  *
862  * @property-read \ICanBoogie\HTTP\Request $request The request associated with the context.
863  * @property-read \ICanBoogie\HTTP\IDispatcher $dispatcher The dispatcher currently dispatching the request.
864  */
865 class Context extends \ICanBoogie\Object
866 {
867     /**
868      * The request the context belongs to.
869      *
870      * The variable is declared as private but is actually readable thanks to the
871      * {@link get_request} getter.
872      *
873      * @var \ICanBoogie\HTTP\Request
874      */
875     private $request;
876 
877     /**
878      * The dispatcher currently dispatching the request.
879      *
880      * @var \ICanBoogie\HTTP\IDispatcher|null
881      */
882     private $dispatcher;
883 
884     /**
885      * Constructor.
886      *
887      * @param \ICanBoogie\HTTP\Request $request The request the context belongs to.
888      */
889     public function __construct(\ICanBoogie\HTTP\Request $request)
890     {
891         $this->request = $request;
892     }
893 
894     /**
895      * Returns the {@link $request} property.
896      *
897      * @return \ICanBoogie\HTTP\Request
898      */
899     protected function get_request()
900     {
901         return $this->request;
902     }
903 
904     /**
905      * Sets the dispatcher currently dispatching the request.
906      *
907      * @param \ICanBoogie\HTTP\IDispatcher|null $dispatcher
908      *
909      * @throws \InvalidArgumentException if the value is not null and does not implements \ICanBoogie\HTTP\IDispatcher.
910      */
911     protected function set_dispatcher($dispatcher)
912     {
913         if ($dispatcher !== null && !($dispatcher instanceof \ICanBoogie\HTTP\IDispatcher))
914         {
915             throw new \InvalidArgumentException('$dispatcher must be an instance of ICanBoogie\HTTP\IDispatcher. Given: ' . get_class($dispatcher) . '.');
916         }
917 
918         $this->dispatcher = $dispatcher;
919     }
920 
921     /**
922      * Returns the {@link $dispatcher} property.
923      *
924      * @return \ICanBoogie\HTTP\IDispatcher
925      */
926     protected function get_dispatcher()
927     {
928         return $this->dispatcher;
929     }
930 }
Autodoc API documentation generated by ApiGen 2.8.0