Overview

Namespaces

  • Alpha
    • Controller
      • Front
    • Exception
    • Model
      • Type
    • Task
    • Util
      • Backup
      • Cache
      • Code
        • Highlight
        • Metric
      • Config
      • Convertor
      • Email
      • Extension
      • Feed
      • File
      • Graph
      • Helper
      • Http
        • Filter
        • Session
      • Image
      • Logging
      • Search
      • Security
    • View
      • Renderer
        • Html
        • Json
      • Widget

Classes

  • AgentUtils
  • PHPServerUtils
  • Request
  • Response
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: namespace Alpha\Util\Http;
  4: 
  5: use Alpha\Exception\IllegalArguementException;
  6: use Alpha\Util\Config\ConfigProvider;
  7: 
  8: /**
  9:  * A class to encapsulate a HTTP request.
 10:  *
 11:  * @since 2.0
 12:  *
 13:  * @author John Collins <dev@alphaframework.org>
 14:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
 15:  * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
 16:  * All rights reserved.
 17:  *
 18:  * <pre>
 19:  * Redistribution and use in source and binary forms, with or
 20:  * without modification, are permitted provided that the
 21:  * following conditions are met:
 22:  *
 23:  * * Redistributions of source code must retain the above
 24:  *   copyright notice, this list of conditions and the
 25:  *   following disclaimer.
 26:  * * Redistributions in binary form must reproduce the above
 27:  *   copyright notice, this list of conditions and the
 28:  *   following disclaimer in the documentation and/or other
 29:  *   materials provided with the distribution.
 30:  * * Neither the name of the Alpha Framework nor the names
 31:  *   of its contributors may be used to endorse or promote
 32:  *   products derived from this software without specific
 33:  *   prior written permission.
 34:  *
 35:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 36:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 37:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 38:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 39:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 40:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 41:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 42:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 43:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 44:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 45:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 46:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 47:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 48:  * </pre>
 49:  */
 50: class Request
 51: {
 52:     /**
 53:      * Array of supported HTTP methods.
 54:      *
 55:      * @var array
 56:      *
 57:      * @since 2.0
 58:      */
 59:     private $HTTPMethods = array('HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'TRACE');
 60: 
 61:     /**
 62:      * The HTTP method of this request (must be in HTTPMethods array).
 63:      *
 64:      * @var string
 65:      *
 66:      * @since 2.0
 67:      */
 68:     private $method;
 69: 
 70:     /**
 71:      * An associative array of HTTP headers on this request.
 72:      *
 73:      * @var array
 74:      *
 75:      * @since 2.0
 76:      */
 77:     private $headers;
 78: 
 79:     /**
 80:      * An associative array of HTTP cookies on this request.
 81:      *
 82:      * @var array
 83:      *
 84:      * @since 2.0
 85:      */
 86:     private $cookies;
 87: 
 88:     /**
 89:      * The HTTP params (form data and query string) on this request.
 90:      *
 91:      * @var array
 92:      *
 93:      * @since 2.0
 94:      */
 95:     private $params;
 96: 
 97:     /**
 98:      * An associative 3D array of uploaded files.
 99:      *
100:      * @var array
101:      *
102:      * @since 2.0
103:      */
104:     private $files;
105: 
106:     /**
107:      * The request body if one was provided.
108:      *
109:      * @var string
110:      *
111:      * @since 2.0
112:      */
113:     private $body;
114: 
115:     /**
116:      * The host header provided on the request.
117:      *
118:      * @var string
119:      *
120:      * @since 2.0
121:      */
122:     private $host;
123: 
124:     /**
125:      * The IP of the client making the request.
126:      *
127:      * @var string
128:      *
129:      * @since 2.0
130:      */
131:     private $IP;
132: 
133:     /**
134:      * The URI requested.
135:      *
136:      * @var string
137:      *
138:      * @since 2.0
139:      */
140:     private $URI;
141: 
142:     /**
143:      * The query string provided on the request (if any).
144:      *
145:      * @var string
146:      *
147:      * @since 2.0
148:      */
149:     private $queryString;
150: 
151:     /**
152:      * Builds up the request based on available PHP super globals, in addition to
153:      * any overrides provided (useful for testing).
154:      *
155:      * @param array $overrides Hash array of PHP super globals to override
156:      *
157:      * @throws Alpha\Exception\IllegalArguementException
158:      *
159:      * @since 2.0
160:      */
161:     public function __construct($overrides = array())
162:     {
163:         // set HTTP headers
164:         if (isset($overrides['headers']) && is_array($overrides['headers'])) {
165:             $this->headers = $overrides['headers'];
166:         } else {
167:             $this->headers = $this->getGlobalHeaders();
168:         }
169: 
170:         // set HTTP method
171:         if (isset($overrides['method']) && in_array($overrides['method'], $this->HTTPMethods)) {
172:             $this->method = $overrides['method'];
173:         } elseif (isset($_SERVER['REQUEST_METHOD']) && in_array($_SERVER['REQUEST_METHOD'], $this->HTTPMethods)) {
174:             $this->method = $_SERVER['REQUEST_METHOD'];
175:         }
176: 
177:         // allow the POST param _METHOD to override the HTTP method
178:         if (isset($_POST['_METHOD']) && in_array($_POST['_METHOD'], $this->HTTPMethods)) {
179:             $this->method = $_POST['_METHOD'];
180:         }
181: 
182:         // allow the POST param X-HTTP-Method-Override to override the HTTP method
183:         if (isset($this->headers['X-HTTP-Method-Override']) && in_array($this->headers['X-HTTP-Method-Override'], $this->HTTPMethods)) {
184:             $this->method = $this->headers['X-HTTP-Method-Override'];
185:         }
186: 
187:         if ($this->method == '') {
188:             throw new IllegalArguementException('No valid HTTP method provided when creating new Request object');
189:         }
190: 
191:         // set HTTP cookies
192:         if (isset($overrides['cookies']) && is_array($overrides['cookies'])) {
193:             $this->cookies = $overrides['cookies'];
194:         } elseif (isset($_COOKIE)) {
195:             $this->cookies = $_COOKIE;
196:         } else {
197:             $this->cookies = array();
198:         }
199: 
200:         // set HTTP params
201:         if (isset($overrides['params']) && is_array($overrides['params'])) {
202:             $this->params = $overrides['params'];
203:         } else {
204:             $this->params = array();
205: 
206:             if (isset($_GET)) {
207:                 $this->params = array_merge($this->params, $_GET);
208:             }
209: 
210:             if (isset($_POST)) {
211:                 $this->params = array_merge($this->params, $_POST);
212:             }
213:         }
214: 
215:         // set HTTP body
216:         if (isset($overrides['body'])) {
217:             $this->body = $overrides['body'];
218:         } else {
219:             $this->body = $this->getGlobalBody();
220:         }
221: 
222:         // set HTTP host
223:         if (isset($overrides['host'])) {
224:             $this->host = $overrides['host'];
225:         } elseif (isset($_SERVER['HTTP_HOST'])) {
226:             $this->host = $_SERVER['HTTP_HOST'];
227:         } else {
228:             $this->host = 'localhost';
229:         }
230: 
231:         // set IP of the client
232:         if (isset($overrides['IP'])) {
233:             $this->IP = $overrides['IP'];
234:         } elseif (isset($_SERVER['REMOTE_ADDR'])) {
235:             $this->IP = $_SERVER['REMOTE_ADDR'];
236:         } else {
237:             $this->IP = '127.0.0.1';
238:         }
239: 
240:         // set requested URI
241:         if (isset($overrides['URI'])) {
242:             $this->URI = $overrides['URI'];
243:         } elseif (isset($_SERVER['REQUEST_URI'])) {
244:             $this->URI = $_SERVER['REQUEST_URI'];
245:         }
246: 
247:         // set uploaded files (if any)
248:         if (isset($overrides['files'])) {
249:             $this->files = $overrides['files'];
250:         } elseif (isset($_FILES)) {
251:             $this->files = $_FILES;
252:         }
253:     }
254: 
255:     /**
256:      * Get the HTTP method of this request.
257:      *
258:      * @return string
259:      *
260:      * @since 2.0
261:      */
262:     public function getMethod()
263:     {
264:         return $this->method;
265:     }
266: 
267:     /**
268:      * Set the HTTP method of this request.
269:      *
270:      * @param string $method
271:      *
272:      * @throws Alpha\Exception\IllegalArguementException
273:      *
274:      * @since 2.0
275:      */
276:     public function setMethod($method)
277:     {
278:         if (in_array($method, $this->HTTPMethods)) {
279:             $this->method = $method;
280:         } else {
281:             throw new IllegalArguementException('The method provided ['.$method.'] is not valid!');
282:         }
283:     }
284: 
285:     /**
286:      * Return all headers on this request.
287:      *
288:      * @return array
289:      *
290:      * @since 2.0
291:      */
292:     public function getHeaders()
293:     {
294:         return $this->headers;
295:     }
296: 
297:     /**
298:      * Get the header matching the key provided.
299:      *
300:      * @param string $key     The key to search for
301:      * @param mixed  $default If key is not found, return this instead
302:      *
303:      * @return mixed
304:      *
305:      * @since 2.0
306:      */
307:     public function getHeader($key, $default = null)
308:     {
309:         if (array_key_exists($key, $this->headers)) {
310:             return $this->headers[$key];
311:         } else {
312:             return $default;
313:         }
314:     }
315: 
316:     /**
317:      * Tries to get the current HTTP request headers from supoer globals.
318:      *
319:      * @return array
320:      *
321:      * @since 2.0
322:      */
323:     private function getGlobalHeaders()
324:     {
325:         if (!function_exists('getallheaders')) {
326:             $headers = array();
327:             foreach ($_SERVER as $name => $value) {
328:                 if (substr($name, 0, 5) == 'HTTP_') {
329:                     $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
330:                 }
331:                 if ($name == 'CONTENT_TYPE') {
332:                     $headers['Content-Type'] = $value;
333:                 }
334:                 if ($name == 'CONTENT_LENGTH') {
335:                     $headers['Content-Length'] = $value;
336:                 }
337:             }
338: 
339:             return $headers;
340:         } else {
341:             return getallheaders();
342:         }
343:     }
344: 
345:     /**
346:      * Return all cookies on this request.
347:      *
348:      * @return array
349:      *
350:      * @since 2.0
351:      */
352:     public function getCookies()
353:     {
354:         return $this->cookies;
355:     }
356: 
357:     /**
358:      * Get the cookie matching the key provided.
359:      *
360:      * @param string $key     The key to search for
361:      * @param mixed  $default If key is not found, return this instead
362:      *
363:      * @return mixed
364:      *
365:      * @since 2.0
366:      */
367:     public function getCookie($key, $default = null)
368:     {
369:         if (array_key_exists($key, $this->cookies)) {
370:             return $this->cookies[$key];
371:         } else {
372:             return $default;
373:         }
374:     }
375: 
376:     /**
377:      * Return all params on this request.
378:      *
379:      * @return array
380:      *
381:      * @since 2.0
382:      */
383:     public function getParams()
384:     {
385:         return $this->params;
386:     }
387: 
388:     /**
389:      * Get the param matching the key provided.
390:      *
391:      * @param string $key     The key to search for
392:      * @param mixed  $default If key is not found, return this instead
393:      *
394:      * @return mixed
395:      *
396:      * @since 2.0
397:      */
398:     public function getParam($key, $default = null)
399:     {
400:         if (array_key_exists($key, $this->params)) {
401:             return $this->params[$key];
402:         } else {
403:             return $default;
404:         }
405:     }
406: 
407:     /**
408:      * Append the hash array provided to the params for this request.
409:      *
410:      * @param array A hash array of values to add to the request params
411:      *
412:      * @since 2.0
413:      */
414:     public function addParams($params)
415:     {
416:         if (is_array($params)) {
417:             $this->params = array_merge($this->params, $params);
418:         }
419:     }
420: 
421:     /**
422:      * Set the params array.
423:      *
424:      * @param array A hash array of values to set as the request params
425:      *
426:      * @since 2.0
427:      */
428:     public function setParams($params)
429:     {
430:         if (is_array($params)) {
431:             $this->params = $params;
432:         }
433:     }
434: 
435:     /**
436:      * Return all files on this request.
437:      *
438:      * @return array
439:      *
440:      * @since 2.0
441:      */
442:     public function getFiles()
443:     {
444:         return $this->files;
445:     }
446: 
447:     /**
448:      * Get the file matching the key provided.
449:      *
450:      * @param string $key     The key to search for
451:      * @param mixed  $default If key is not found, return this instead
452:      *
453:      * @return mixed
454:      *
455:      * @since 2.0
456:      */
457:     public function getFile($key, $default = null)
458:     {
459:         if (array_key_exists($key, $this->files)) {
460:             return $this->files[$key];
461:         } else {
462:             return $default;
463:         }
464:     }
465: 
466:     /**
467:      * Get the request body if one was provided.
468:      *
469:      * @return string
470:      *
471:      * @since 2.0
472:      */
473:     public function getBody()
474:     {
475:         return $this->body;
476:     }
477: 
478:     /**
479:      * Attempts to get the raw body of the current request from super globals.
480:      *
481:      * @return string
482:      *
483:      * @since 2.0
484:      */
485:     private function getGlobalBody()
486:     {
487:         if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
488:             return $GLOBALS['HTTP_RAW_POST_DATA'];
489:         } else {
490:             return file_get_contents('php://input');
491:         }
492:     }
493: 
494:     /**
495:      * Get the Accept header of the request.
496:      *
497:      * @return string
498:      *
499:      * @since 2.0
500:      */
501:     public function getAccept()
502:     {
503:         return $this->getHeader('Accept');
504:     }
505: 
506:     /**
507:      * Get the Content-Type header of the request.
508:      *
509:      * @return string
510:      *
511:      * @since 2.0
512:      */
513:     public function getContentType()
514:     {
515:         return $this->getHeader('Content-Type');
516:     }
517: 
518:     /**
519:      * Get the Content-Length header of the request.
520:      *
521:      * @return string
522:      *
523:      * @since 2.0
524:      */
525:     public function getContentLength()
526:     {
527:         return $this->getHeader('Content-Length');
528:     }
529: 
530:     /**
531:      * Get the host name of the client that sent the request.
532:      *
533:      * @return string
534:      *
535:      * @since 2.0
536:      */
537:     public function getHost()
538:     {
539:         return $this->host;
540:     }
541: 
542:     /**
543:      * Get the URI that was requested.
544:      *
545:      * @return string
546:      *
547:      * @since 2.0
548:      */
549:     public function getURI()
550:     {
551:         return $this->URI;
552:     }
553: 
554:     /**
555:      * Get the URL that was requested.
556:      *
557:      * @return string
558:      *
559:      * @since 2.0
560:      */
561:     public function getURL()
562:     {
563:         $config = ConfigProvider::getInstance();
564: 
565:         return $config->get('app.url').$this->getURI();
566:     }
567: 
568:     /**
569:      * Get the IP address of the client that sent the request.
570:      *
571:      * @return string
572:      *
573:      * @since 2.0
574:      */
575:     public function getIP()
576:     {
577:         return $this->IP;
578:     }
579: 
580:     /**
581:      * Get the Referrer header of the request.
582:      *
583:      * @return string
584:      *
585:      * @since 2.0
586:      */
587:     public function getReferrer()
588:     {
589:         return $this->getHeader('Referrer');
590:     }
591: 
592:     /**
593:      * Get the User-Agent header of the request.
594:      *
595:      * @return string
596:      *
597:      * @since 2.0
598:      */
599:     public function getUserAgent()
600:     {
601:         return $this->getHeader('User-Agent');
602:     }
603: 
604:     /**
605:      * Get the query string provided on the request.
606:      *
607:      * @return string
608:      *
609:      * @since 2.0
610:      */
611:     public function getQueryString()
612:     {
613:         return $this->queryString;
614:     }
615: 
616:     /**
617:      * Parses the route provided to extract matching params of the route from this request's URI.
618:      *
619:      * @param string $route         The route with parameter names, e.g. /user/{username}
620:      * @param array  $defaultParams Optional hash array of default request param values to use if they are missing from URI
621:      *
622:      * @since 2.0
623:      */
624:     public function parseParamsFromRoute($route, $defaultParams = array())
625:     {
626:         // if the URI has a query-string, we will ignore it for now
627:         if (mb_strpos($this->URI, '?') !== false) {
628:             $URI = mb_substr($this->URI, 0, mb_strpos($this->URI, '?'));
629: 
630:             // let's take this opportunity to pass query string params to $this->params
631:             $queryString = mb_substr($this->URI, (mb_strpos($this->URI, '?') + 1));
632:             $this->queryString = $queryString;
633:             parse_str($queryString, $this->params);
634:         } else {
635:             $URI = $this->URI;
636:         }
637: 
638:         $paramNames = explode('/', $route);
639:         $paramValues = explode('/', $URI);
640: 
641:         for ($i = 0; $i < count($paramNames); ++$i) {
642:             $name = $paramNames[$i];
643: 
644:             if (!isset($this->params[trim($name, '{}')])) {
645:                 if (isset($paramValues[$i]) && substr($name, 0, 1) == '{' && substr($name, strlen($name) - 1, 1) == '}') {
646:                     $this->params[trim($name, '{}')] = $paramValues[$i];
647:                 }
648:                 if (!isset($paramValues[$i]) && isset($defaultParams[trim($name, '{}')])) {
649:                     $this->params[trim($name, '{}')] = $defaultParams[trim($name, '{}')];
650:                 }
651:             }
652:         }
653:     }
654: 
655:     /**
656:      * Checks to see if the request contains a secure/encrypted token.
657:      *
658:      * @return bool
659:      *
660:      * @since 2.0
661:      */
662:     public function isSecureURI()
663:     {
664:         if (isset($this->params['act']) && mb_strpos($this->URI, '/tk/') !== false) {
665:             return true;
666:         } else {
667:             return false;
668:         }
669:     }
670: }
671: 
Alpha Framework 2.0.4 API Documentation API documentation generated by ApiGen 2.8.0