Overview
  • Namespace
  • Class
  • Tree

Namespaces

  • Modulework
    • Modules
      • Http
        • Exceptions
        • Utilities
  • PHP

Classes

  • Cookie
  • JsonResponse
  • RedirectResponse
  • Request
  • Response
  1 <?php namespace Modulework\Modules\Http;
  2 /*
  3  * (c) Christian Gärtner <christiangaertner.film@googlemail.com>
  4  * This file is part of the Modulework Framework
  5  * License: View distributed LICENSE file
  6  */
  7 
  8 use Modulework\Modules\Http\Utilities\FileCase;
  9 use Modulework\Modules\Http\Utilities\ArrayCase;
 10 use Modulework\Modules\Http\Utilities\HeaderCase;
 11 use Modulework\Modules\Http\Utilities\ServerCase;
 12 
 13 /**
 14 * Request
 15 * This class represents the current HTTP request.
 16 * It exposes 6 public vars (objects) for getting information
 17 * For some there are methods for convience.
 18 */
 19 class Request
 20 {
 21 
 22     /**
 23      * The ArrayCase for the QueryString (_GET)
 24      * @var \Modulework\Modules\Http\ArrayCase
 25      */
 26     public $query;
 27 
 28     /**
 29      * The ArrayCase for the POST request (_POST)
 30      * @var \Modulework\Modules\Http\ArrayCase
 31      */
 32     public $request;
 33 
 34     /**
 35      * The ArrayCase for the server varibales (_SERVER)
 36      * @var \Modulework\Modules\Http\ServerCase
 37      */
 38     public $server;
 39 
 40     /**
 41      * The ArrayCase for the files attached to the request (_FILES)
 42      * @var \Modulework\Modules\Http\FileCase
 43      */
 44     public $files;
 45 
 46     /**
 47      * The ArrayCase for the cookies (_COOKIE)
 48      * @var \Modulework\Modules\Http\ArrayCase
 49      */
 50     public $cookies;
 51 
 52     /**
 53      * The ArrayCase for the HTTP headers
 54      * @var \Modulework\Modules\Http\HeaderCase
 55      */
 56     public $headers;
 57 
 58     /**
 59      * The URI of this request
 60      * @var string
 61      */
 62     protected $uri;
 63 
 64     /**
 65      * The path information of this request
 66      * @var string
 67      */
 68     protected $path;
 69 
 70     /**
 71      * The base URL of this request
 72      * @var string
 73      */
 74     protected $baseUrl;
 75 
 76     /**
 77      * The base path of this request
 78      * @var string
 79      */
 80     protected $basePath;
 81 
 82     /**
 83      * The HTTP verb (GET/POST/PUT/DELETE)
 84      * @var string
 85      */
 86     protected $method;
 87 
 88     /**
 89      * Create the Request object from PHP _ENV (or superglobals)
 90      * @return \Modulework\Modules\Http\Request The new Request object
 91      */
 92     public static function makeFromGlobals()
 93     {
 94         return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
 95     }
 96 
 97     /**
 98      * Constructor
 99      * @param  array  $query   GET
100      * @param  array  $request POST
101      * @param  array  $cookies COOKIE
102      * @param  array  $files   FILES
103      * @param  array  $server  SERVER
104      */
105     public function __construct(array $query = array(), array $request = array(), array $cookies = array(), array $files = array(), array $server = array())
106     {
107         $this->init($query, $request, $cookies, $files, $server);
108     }
109 
110     /**
111      * Displays the Request in the following format:
112      * PROTOCOLL VERB >> BASEURI
113      * @return string [description]
114      */
115     public function __toString()
116     {
117         return sprintf('%s %s >> %s', $this->server->get('SERVER_PROTOCOL'), $this->getMethod(), $this->getBaseUri());
118     }
119 
120     /**
121      * Initialize all parameters
122      * @param  array  $query   GET
123      * @param  array  $request POST
124      * @param  array  $cookies COOKIE
125      * @param  array  $files   FILES
126      * @param  array  $server  SERVER
127      */
128     public function init(array $query = array(), array $request = array(), array $cookies = array(), array $files = array(), array $server = array())
129     {
130         $this->query = new ArrayCase($query);
131         $this->request = new ArrayCase($request);
132         $this->cookies = new ArrayCase($cookies);
133         $this->files = new FileCase($files);
134         $this->server = new ServerCase($server);
135         $this->headers = new HeaderCase($this->server->getHeaders());
136 
137         // Reset propertys
138         $this->uri = null;
139         $this->path = null;
140         $this->baseUrl = null;
141         $this->basePath = null;
142         $this->method = null;
143     }
144 
145     /**
146      * Write changes to the Request to the globals
147      */
148     public function applyChanges()
149     {
150         $_GET = $this->query->all();
151         $_POST = $this->request->all();
152         $_SERVER = $this->server->all();
153         $_COOKIE = $this->cookies->all();
154     }
155 
156     /**
157      * Mock an request by providing a URI only, to feed more info is still possible
158      * @param  string $uri     The URI
159      * @param  string $method  The HTTP request method
160      * @param  array  $request The _POST values
161      * @param  array  $cookies The _COOKIES
162      * @param  array  $files   The _FILES
163      * @param  array  $server  The _SERVER values
164      * 
165      * @return \Modulework\Modules\Http\Request          A new instance based on the info provided
166      */
167     public static function mock($uri, $method = 'GET', array $request = array(), array $cookies = array(), array $files = array(), array $server = array())
168     {
169         $server = array_replace(array(
170                                 'SERVER_PROTOCOL' => 'HTTP/1.1',
171                                 'SERVER_NAME' => 'localhost',
172                                 'SERVER_PORT' => 80,
173                                 'SCRIPT_NAME' => '',
174                                 'SCRIPT_FILENAME' => '',
175                                 'HTTP_HOST' => 'localhost',
176                                 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
177                                 'HTTP_USER_AGENT' => 'Modulework/Release',
178                                 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
179                                 'REQUEST_TIME' => time(),
180         ), $server);
181 
182         $server['REQUEST_METHOD'] = strtoupper($method);
183 
184 
185         $parsed = parse_url($uri);
186 
187         if (isset($parsed['host'])) {
188             $server['SERVER_NAME'] = $parsed['host'];
189             $server['HTTP_HOST'] = $parsed['host'];
190         }
191 
192         if (isset($parsed['scheme'])) {
193             if ($parsed['scheme'] === 'https') {
194                 $server['SERVER_PORT'] = 443;
195                 $server['HTTPS'] = 'on';
196             } else {
197                 $server['SERVER_PORT'] = 80;
198                 unset($server['HTTPS']);
199             }
200         }
201 
202         if (isset($parsed['port'])) {
203             $server['SERVER_PORT'] = $parsed['port'];
204             $server['HTTP_HOST'] .= ':' . $parsed['port'];
205         }
206 
207         
208 
209         if (!isset($parsed['path'])) {
210             $parsed['path'] = '/';
211         }
212 
213         $query = array();
214         if (isset($parsed['query'])) {
215             parse_str(html_entity_decode($parsed['query']), $query);
216         }
217 
218         $queryString = http_build_query($query, '', '&');
219         $server['QUERY_STRING'] = $queryString;
220 
221 
222         $server['REQUEST_URI'] = $parsed['path'] . ('' == $queryString ? '' : '?' . $queryString);
223 
224 
225         return new static($query, $request, $cookies, $files, $server);
226     }
227 
228     /**
229      * Normalize a query string
230      * @param  string $query Query String
231      * @return string        The normalized version of $query
232      */
233     public static function normalizeQuery($query)
234     {
235         if ('' == $query) {
236             return '';
237         }
238 
239         $parts = array();
240         $sort = array();
241 
242         $split = explode('&', $query);
243 
244         foreach ($split as $value) {
245             if ('' == $value || '=' === $value[0]) continue;
246 
247             $pair = explode('=', $value, 2);
248 
249             if (isset($pair[1])) {
250                 $parts[] = rawurlencode(urldecode($pair[0])) . '=' . rawurlencode(urldecode($pair[1]));
251             } else {
252                 $parts[] = rawurlencode(urldecode($pair[0]));
253             }
254 
255             $sort[] = urldecode($pair[0]);
256         }
257 
258         array_multisort($sort, SORT_ASC, $parts);
259 
260         return implode('&', $parts);
261     }
262 
263     /**
264      * Returns the request method
265      * @return string The request method
266      */
267     public function getMethod()
268     {
269         if ($this->method === null) {
270             $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
271         }
272         return $this->method;
273     }
274 
275     /**
276      * Mock the request method
277      * @param string $method The request method
278      */
279     public function setMethod($method)
280     {
281         $this->$method = null; //Reset, so it' s getting regenerated properly.
282         $this->server->set('REQUEST_METHOD', strtoupper($method), true);
283     }
284 
285     /**
286      * Returns either http or https
287      * calls isSecure()
288      * @return string The scheme (http | https)
289      */
290     public function getScheme()
291     {
292         return $this->isSecure() ? 'https' : 'http';
293     }
294 
295     /**
296      * Returns the HTTP Host (with port if not default)
297      * 
298      * For example:
299      *  localhost
300      * or
301      *  localhost:4000
302      * 
303      * @return string The host
304      */
305     public function getHttpHost()
306     {
307         $port = $this->getPort();
308         $scheme = $this->getScheme();
309 
310         if (('https' == $scheme && $port == 443) || ('http' == $scheme && $port == 80)) {
311             // if standard ports then don' t add em
312             return $this->getHost();
313         }
314 
315         return $this->getHost() . ':' . $port;
316 
317     }
318 
319     /**
320      * Returns the host of the server
321      * @return string The host of this server
322      */
323     public function getHost()
324     {
325         if (!$host = $this->headers->get('HOST')) {
326             if (!$host = $this->server->get('SERVER_ADDR')) {
327                 $host = $this->server->get('SERVER_NAME', '');
328             }
329         }
330 
331         $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));
332 
333         return $host;
334     }
335 
336     /**
337      * Set the host in the header
338      * @param string $host The new host
339      */
340     public function setHost($host)
341     {
342         $this->headers->set('HOST', $host, true);
343     }
344 
345     /**
346      * Port for the Request
347      * @return string the port
348      */
349     public function getPort()
350     {
351         return $this->server->get('SERVER_PORT');
352     }
353 
354     /**
355      * Retrieve the accepted encoding types from the HTTP headers
356      * @return array The accepted encodings
357      */
358     public function getAcceptedEncodings()
359     {
360         return explode(',', $this->headers->get('ACCEPT_ENCODING'));
361     }
362 
363     /**
364      * Get the BaseUri
365      * Calls once: generateBaseUri()
366      * @return string The base uri for the request
367      */
368     public function getBaseUri()
369     {
370         if ($this->uri === null) {
371             $this->uri = $this->generateBaseUri();
372         }
373         return $this->uri;
374     }
375 
376     /**
377      * The base URL
378      * @return string The base URL
379      */
380     public function getBaseUrl()
381     {
382         if ($this->baseUrl === null) {
383             $this->baseUrl = $this->generateBaseUrl();
384         }
385         return $this->baseUrl;
386     }
387 
388     /**
389      * Returns the path.
390      * Examples (this class was initalized at /dev on localhost):
391      *
392      * * http://localhost/dev           ->  ''
393      * * http://localhost/dev/more      ->  '/more'
394      * * http://localhost/dev/more?foo  ->  '/more'
395      * @return string The path
396      */
397     public function getPath()
398     {
399         if ($this->path === null) {
400             $this->path = $this->generatePath();
401         }
402 
403         return $this->path;
404     }
405 
406     /**
407      * Returns the base path from the root,
408      * for example if this class was constructed in the subfolder
409      * 'foo' this method would return 'foo' for this uri:
410      * http://localhost/foo/index.php 
411      * @return string The raw path
412      */
413     public function getBasePath()
414     {
415         if ($this->basePath === null) {
416             $this->basePath = $this->generateBasePath();
417         }
418 
419         return $this->basePath;
420     }
421 
422     /**
423      * Returns the root URL
424      * @return string The root URL
425      */
426     public function root()
427     {
428         return rtrim($this->getScheme() . '://' . $this->getHost() .  $this->getPath(), '/');
429     }
430 
431     /**
432      * Returns the URL (without query string)
433      * @return string The URL
434      */
435     public function url()
436     {
437         return rtrim(preg_replace('/\?.*/', '', $this->getBaseUri()), '/');
438     }
439 
440     
441     /**
442      * Returns all URI segments
443      * (or empty array if path = '/')
444      * @return array The URI segments
445      */
446     public function segments()
447     {
448         $path = $this->getPath();
449 
450         $array = $path == '/' ? array() : explode('/', $path);
451         return array_filter($array, function($val) {
452             return $val != '';
453         });
454     }
455     
456     /**
457      * Get a URI segment
458      * 1 based index
459      * @param  int    $index   The index
460      * @param  mixed  $default If the segement does not exists this will get returned
461      * @return mixed           The URI segment | $default
462      */
463     public function segment($index, $default = null)
464     {
465         if ('/' === $path = $this->getPath()) {
466             return '/';
467         }
468 
469         $segments = explode('/', rtrim($path, '/'));
470 
471 
472         $segments = array_filter($segments, function($val) {
473             return $val != '';
474         });
475 
476         return (isset($segments[$index])) ? $segments[$index] : $default;
477     }
478 
479     /**
480      * Check if the request method equals the given
481      * @param  string  $method The method to test
482      * @return boolean         TRUE if match
483      */
484     public function isMethod($method)
485     {
486         return ($this->getMethod() === strtoupper($method));
487     }
488 
489     /**
490      * Wrapper for isXmlHttpRequest
491      * @return boolean TRUE if it is a XMLHttpRequest
492      */
493     public function isAjax()
494     {
495         return $this->isXmlHttpRequest();
496     }
497 
498     /**
499      * Is the request of type XMLHttpRequest
500      * @return boolean TRUE if it is a XMLHttpRequest
501      */
502     public function isXmlHttpRequest()
503     {
504         return ('XMLHttpRequest' == $this->headers->get('X-Requested-With'));
505     }
506 
507     /**
508      * Check for HTTPS connection
509      * @return boolean TRUE if it is a HTTPS connection
510      */
511     public function isSecure()
512     {
513         return (1 == $this->server->get('HTTPS') || strtolower($this->server->get('HTTPS') == 'on'));
514     }
515 
516     /**
517      * Returns the client' s IP address
518      * @return string The IP
519      */
520     public function getClientIp()
521     {
522         return $this->server->get('REMOTE_ADDR');
523     }
524 
525     /**
526      * Returns the current script name
527      * @return string  The script name
528      */
529     public function getScript()
530     {
531         return $this->server->get('SCRIPT_NAME');
532     }
533 
534 
535     /**
536      * Generate the BaseUri
537      * @return string The base uri
538      */
539     protected function generateBaseUri()
540     {
541         $uri = '';
542 
543         /*
544          * The first check is obvious, all these headers after REQUEST_URI are taken from the Zend Framework,
545          * they are for IIS and the like setups.
546          */
547         if ($this->server->has('REQUEST_URI')) {
548             $uri = $this->server->get('REQUEST_URI');
549             // this will be with scheme and host maybe....
550             // We' ll need to cut these out
551             $schemeHost = $this->getScheme() . '://' . $this->getHttpHost();
552             if (strpos($uri, $schemeHost) === 0) {
553                 $uri = substr($uri, strlen($schemeHost));
554             }
555 
556         } elseif ($this->server->has('ORIG_PATH_INFO')) {
557             $uri = $this->server->get('ORIG_PATH_INFO');
558             if ('' == $this->server->get('QUERY_STRING')) {
559                 $uri .= '?' . $this->server->get('QUERY_STRING');
560             }
561 
562         } elseif ($this->headers->has('X_ORIGINAL_URL')) {
563             $uri = $this->headers->get('X_ORIGINAL_URL');
564 
565         } elseif ($this->headers->has('X_REWRITE_URL')) {
566             $this->headers->has('X_REWRITE_URL');
567 
568         } elseif ($this->server->has('IIS_WasUrlRewritten') == '1' && ('' !== $this->server->get('UNENCODED_URL'))) {
569             $uri = $this->server->get('UNENCODED_URL');
570 
571         } elseif ($this->server->has('IIS_WasUrlRewritten') == '1' && ('' !== $this->server->get('UNENCODED_URL'))) {
572             $uri = $this->server->get('UNENCODED_URL');
573             
574         }
575 
576         $this->server->set('REQUEST_URI', $uri);
577 
578         return $uri;
579     }
580 
581     /**
582      * Generate the BaseUrl
583      * @return string The base url
584      */
585     protected function generateBaseUrl()
586     {
587         $filename = basename($this->server->get('SCRIPT_FILENAME'));
588         
589         if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
590             $baseUrl = $this->server->get('SCRIPT_NAME');
591         } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
592             $baseUrl = $this->server->get('PHP_SELF');
593         } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
594             $baseUrl = $this->server->get('ORIG_SCRIPT_NAME');
595         } else {            
596             $path = $this->server->get('PHP_SELF', '');
597             $file = $this->server->get('SCRIPT_FILENAME', '');
598 
599             $parts = array_reverse(explode('/', trim($file, '/')));
600 
601             $i = 0;
602 
603             $prev = count($parts);
604 
605             $baseUrl = '';
606 
607             do {
608                 $part = $parts[$i];
609                 $baseUrl = '/' . $part . $baseUrl;
610                 $i++;
611             } while (($prev > $i) && (($pos = strpos($path, $baseUrl)) !== false) && (0 !== $pos));
612         }
613 
614         $uri = $this->getBaseUri();
615 
616         if ($baseUrl && false !== $pre = self::getPrefixUrlEncoded($uri, $baseUrl)) return $pre;
617 
618         if ($baseUrl && false !== $pre = self::getPrefixUrlEncoded($uri, dirname($baseUrl))) return rtrim($prefix, '/');
619 
620         if (($pos = strpos($uri, '?')) !== false) {
621             $queryLessUri = substr($uri, 0, $pos);
622         } else {
623             $queryLessUri = $uri;
624         }
625 
626         $base = basename($baseUrl);
627 
628         if (empty($base) || !strpos(rawurldecode($queryLessUri), $base)) return '';
629         
630 
631 
632 
633         return rtrim($baseUrl, '/');
634 
635     }
636 
637     protected function generateBasePath()
638     {
639         $filename = basename($this->server->get('SCRIPT_FILENAME'));
640         $baseUrl = $this->getBaseUrl();
641 
642         if (empty($baseUrl)) return '';
643 
644         $basePath = (basename($baseUrl) === $filename) ? dirname($baseUrl) : $baseUrl;
645 
646         if ('\\' === DIRECTORY_SEPARATOR) { // We are on Windows
647             $basePath = str_replace('\\', '/', $basePath);
648         }
649 
650         return rtrim($basePath, '/');
651     }
652 
653     protected function generatePath()
654     {
655         $baseUrl = $this->getBaseUrl();
656 
657         if (($baseUri = $this->getBaseUri()) === null) return '/';
658 
659         $path = '/';
660 
661         if ($pos = strpos($baseUri, '?')) $baseUri = substr($baseUri, 0, $pos);
662 
663         if ((null !== $baseUrl) && (false === ($path = substr($baseUri, strlen($baseUrl))))) {
664             return '/';
665         } elseif ($baseUrl === null) {
666             return $baseUri;
667         }
668 
669         return $path;
670     }
671 
672     /**
673      * Returns the string prefix if it' s the string' s prefix (URL Encoded)
674      * false otherwise
675      * @param  string $str      The urlencoded string
676      * @param  string $pre      The NOT encoeded prefix
677      * @return string|false     The prefix as it is encoded in $str or false
678      */
679     protected static function getPrefixUrlEncoded($str, $pre)
680     {
681         if (strpos(rawurldecode($str), $pre) !== 0) return false;
682 
683         $length = strlen($pre);
684 
685         /*
686         NOTE! THIS REGEX is COPIED from the ZEND Framework (BSD License)
687          */
688         if (preg_match("#^(%[[:xdigit:]]{2}|.){{$length}}#", $str, $match)) return $match[0];
689 
690         return false;
691     }
692 
693     
694 
695 }
API documentation generated by ApiGen 2.8.0