CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.7 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.7
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • ActionDispatcher
  • BaseApplication
  • Client
  • ControllerFactory
  • CorsBuilder
  • MiddlewareQueue
  • Response
  • ResponseEmitter
  • Runner
  • Server
  • ServerRequest
  • ServerRequestFactory
  • Session
   1: <?php
   2: /**
   3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
   4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
   5:  *
   6:  * Licensed under The MIT License
   7:  * For full copyright and license information, please see the LICENSE.txt
   8:  * Redistributions of files must retain the above copyright notice.
   9:  *
  10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11:  * @link          https://cakephp.org CakePHP(tm) Project
  12:  * @since         2.0.0
  13:  * @license       https://opensource.org/licenses/mit-license.php MIT License
  14:  */
  15: namespace Cake\Http;
  16: 
  17: use ArrayAccess;
  18: use BadMethodCallException;
  19: use Cake\Core\Configure;
  20: use Cake\Http\Cookie\CookieCollection;
  21: use Cake\Http\Exception\MethodNotAllowedException;
  22: use Cake\Http\Session;
  23: use Cake\Utility\Hash;
  24: use InvalidArgumentException;
  25: use Psr\Http\Message\ServerRequestInterface;
  26: use Psr\Http\Message\StreamInterface;
  27: use Psr\Http\Message\UploadedFileInterface;
  28: use Psr\Http\Message\UriInterface;
  29: use Zend\Diactoros\PhpInputStream;
  30: use Zend\Diactoros\Stream;
  31: use Zend\Diactoros\UploadedFile;
  32: 
  33: /**
  34:  * A class that helps wrap Request information and particulars about a single request.
  35:  * Provides methods commonly used to introspect on the request headers and request body.
  36:  */
  37: class ServerRequest implements ArrayAccess, ServerRequestInterface
  38: {
  39: 
  40:     /**
  41:      * Array of parameters parsed from the URL.
  42:      *
  43:      * @var array
  44:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getParam() instead.
  45:      */
  46:     protected $params = [
  47:         'plugin' => null,
  48:         'controller' => null,
  49:         'action' => null,
  50:         '_ext' => null,
  51:         'pass' => []
  52:     ];
  53: 
  54:     /**
  55:      * Array of POST data. Will contain form data as well as uploaded files.
  56:      * In PUT/PATCH/DELETE requests this property will contain the form-urlencoded
  57:      * data.
  58:      *
  59:      * @var null|array|object
  60:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getData() instead.
  61:      */
  62:     protected $data = [];
  63: 
  64:     /**
  65:      * Array of query string arguments
  66:      *
  67:      * @var array
  68:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getQuery() or getQueryParams() instead.
  69:      */
  70:     protected $query = [];
  71: 
  72:     /**
  73:      * Array of cookie data.
  74:      *
  75:      * @var array
  76:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getCookie() instead.
  77:      */
  78:     protected $cookies = [];
  79: 
  80:     /**
  81:      * Array of environment data.
  82:      *
  83:      * @var array
  84:      */
  85:     protected $_environment = [];
  86: 
  87:     /**
  88:      * The URL string used for the request.
  89:      *
  90:      * @var string
  91:      * @deprecated 3.6.0 This public property will be removed in 4.0.0. Use getPath() instead.
  92:      */
  93:     protected $url;
  94: 
  95:     /**
  96:      * Base URL path.
  97:      *
  98:      * @var string
  99:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getAttribute('base') instead.
 100:      */
 101:     protected $base;
 102: 
 103:     /**
 104:      * webroot path segment for the request.
 105:      *
 106:      * @var string
 107:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getAttribute('webroot') instead.
 108:      */
 109:     protected $webroot = '/';
 110: 
 111:     /**
 112:      * The full address to the current request
 113:      *
 114:      * @var string
 115:      * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getAttribute('here') or getUri()->getPath() instead.
 116:      */
 117:     protected $here;
 118: 
 119:     /**
 120:      * Whether or not to trust HTTP_X headers set by most load balancers.
 121:      * Only set to true if your application runs behind load balancers/proxies
 122:      * that you control.
 123:      *
 124:      * @var bool
 125:      */
 126:     public $trustProxy = false;
 127: 
 128:     /**
 129:      * trusted proxies list
 130:      *
 131:      * @var array
 132:      */
 133:     protected $trustedProxies = [];
 134: 
 135:     /**
 136:      * Contents of php://input
 137:      *
 138:      * @var string
 139:      */
 140:     protected $_input;
 141: 
 142:     /**
 143:      * The built in detectors used with `is()` can be modified with `addDetector()`.
 144:      *
 145:      * There are several ways to specify a detector, see \Cake\Http\ServerRequest::addDetector() for the
 146:      * various formats and ways to define detectors.
 147:      *
 148:      * @var array
 149:      */
 150:     protected static $_detectors = [
 151:         'get' => ['env' => 'REQUEST_METHOD', 'value' => 'GET'],
 152:         'post' => ['env' => 'REQUEST_METHOD', 'value' => 'POST'],
 153:         'put' => ['env' => 'REQUEST_METHOD', 'value' => 'PUT'],
 154:         'patch' => ['env' => 'REQUEST_METHOD', 'value' => 'PATCH'],
 155:         'delete' => ['env' => 'REQUEST_METHOD', 'value' => 'DELETE'],
 156:         'head' => ['env' => 'REQUEST_METHOD', 'value' => 'HEAD'],
 157:         'options' => ['env' => 'REQUEST_METHOD', 'value' => 'OPTIONS'],
 158:         'ssl' => ['env' => 'HTTPS', 'options' => [1, 'on']],
 159:         'ajax' => ['env' => 'HTTP_X_REQUESTED_WITH', 'value' => 'XMLHttpRequest'],
 160:         'flash' => ['env' => 'HTTP_USER_AGENT', 'pattern' => '/^(Shockwave|Adobe) Flash/'],
 161:         'requested' => ['param' => 'requested', 'value' => 1],
 162:         'json' => ['accept' => ['application/json'], 'param' => '_ext', 'value' => 'json'],
 163:         'xml' => ['accept' => ['application/xml', 'text/xml'], 'param' => '_ext', 'value' => 'xml'],
 164:     ];
 165: 
 166:     /**
 167:      * Instance cache for results of is(something) calls
 168:      *
 169:      * @var array
 170:      */
 171:     protected $_detectorCache = [];
 172: 
 173:     /**
 174:      * Request body stream. Contains php://input unless `input` constructor option is used.
 175:      *
 176:      * @var \Psr\Http\Message\StreamInterface
 177:      */
 178:     protected $stream;
 179: 
 180:     /**
 181:      * Uri instance
 182:      *
 183:      * @var \Psr\Http\Message\UriInterface
 184:      */
 185:     protected $uri;
 186: 
 187:     /**
 188:      * Instance of a Session object relative to this request
 189:      *
 190:      * @var \Cake\Http\Session
 191:      */
 192:     protected $session;
 193: 
 194:     /**
 195:      * Store the additional attributes attached to the request.
 196:      *
 197:      * @var array
 198:      */
 199:     protected $attributes = [];
 200: 
 201:     /**
 202:      * A list of propertes that emulated by the PSR7 attribute methods.
 203:      *
 204:      * @var array
 205:      */
 206:     protected $emulatedAttributes = ['session', 'webroot', 'base', 'params', 'here'];
 207: 
 208:     /**
 209:      * Array of Psr\Http\Message\UploadedFileInterface objects.
 210:      *
 211:      * @var array
 212:      */
 213:     protected $uploadedFiles = [];
 214: 
 215:     /**
 216:      * The HTTP protocol version used.
 217:      *
 218:      * @var string|null
 219:      */
 220:     protected $protocol;
 221: 
 222:     /**
 223:      * The request target if overridden
 224:      *
 225:      * @var string|null
 226:      */
 227:     protected $requestTarget;
 228: 
 229:     /**
 230:      * List of deprecated properties that have backwards
 231:      * compatibility offered through magic methods.
 232:      *
 233:      * @var array
 234:      */
 235:     private $deprecatedProperties = [
 236:         'data' => ['get' => 'getData()', 'set' => 'withData()'],
 237:         'query' => ['get' => 'getQuery()', 'set' => 'withQueryParams()'],
 238:         'params' => ['get' => 'getParam()', 'set' => 'withParam()'],
 239:         'cookies' => ['get' => 'getCookie()', 'set' => 'withCookieParams()'],
 240:         'url' => ['get' => 'getPath()', 'set' => 'withRequestTarget()'],
 241:         'base' => ['get' => 'getAttribute("base")', 'set' => 'withAttribute("base")'],
 242:         'webroot' => ['get' => 'getAttribute("webroot")', 'set' => 'withAttribute("webroot")'],
 243:         'here' => ['get' => 'getAttribute("here")', 'set' => 'withAttribute("here")'],
 244:     ];
 245: 
 246:     /**
 247:      * Wrapper method to create a new request from PHP superglobals.
 248:      *
 249:      * Uses the $_GET, $_POST, $_FILES, $_COOKIE, $_SERVER, $_ENV and php://input data to construct
 250:      * the request.
 251:      *
 252:      * @return self
 253:      * @deprecated 3.4.0 Use `Cake\Http\ServerRequestFactory` instead.
 254:      */
 255:     public static function createFromGlobals()
 256:     {
 257:         deprecationWarning(
 258:             'ServerRequest::createFromGlobals() is deprecated. ' .
 259:             'Use `Cake\Http\ServerRequestFactory` instead.'
 260:         );
 261: 
 262:         return ServerRequestFactory::fromGlobals();
 263:     }
 264: 
 265:     /**
 266:      * Create a new request object.
 267:      *
 268:      * You can supply the data as either an array or as a string. If you use
 269:      * a string you can only supply the URL for the request. Using an array will
 270:      * let you provide the following keys:
 271:      *
 272:      * - `post` POST data or non query string data
 273:      * - `query` Additional data from the query string.
 274:      * - `files` Uploaded file data formatted like $_FILES.
 275:      * - `cookies` Cookies for this request.
 276:      * - `environment` $_SERVER and $_ENV data.
 277:      * - `url` The URL without the base path for the request.
 278:      * - `uri` The PSR7 UriInterface object. If null, one will be created.
 279:      * - `base` The base URL for the request.
 280:      * - `webroot` The webroot directory for the request.
 281:      * - `input` The data that would come from php://input this is useful for simulating
 282:      *   requests with put, patch or delete data.
 283:      * - `session` An instance of a Session object
 284:      *
 285:      * @param string|array $config An array of request data to create a request with.
 286:      *   The string version of this argument is *deprecated* and will be removed in 4.0.0
 287:      */
 288:     public function __construct($config = [])
 289:     {
 290:         if (is_string($config)) {
 291:             $config = ['url' => $config];
 292:         }
 293:         $config += [
 294:             'params' => $this->params,
 295:             'query' => [],
 296:             'post' => [],
 297:             'files' => [],
 298:             'cookies' => [],
 299:             'environment' => [],
 300:             'url' => '',
 301:             'uri' => null,
 302:             'base' => '',
 303:             'webroot' => '',
 304:             'input' => null,
 305:         ];
 306: 
 307:         $this->_setConfig($config);
 308:     }
 309: 
 310:     /**
 311:      * Process the config/settings data into properties.
 312:      *
 313:      * @param array $config The config data to use.
 314:      * @return void
 315:      */
 316:     protected function _setConfig($config)
 317:     {
 318:         if (strlen($config['url']) > 1 && $config['url'][0] === '/') {
 319:             $config['url'] = substr($config['url'], 1);
 320:         }
 321: 
 322:         if (empty($config['session'])) {
 323:             $config['session'] = new Session([
 324:                 'cookiePath' => $config['base']
 325:             ]);
 326:         }
 327: 
 328:         $this->_environment = $config['environment'];
 329:         $this->cookies = $config['cookies'];
 330: 
 331:         if (isset($config['uri']) && $config['uri'] instanceof UriInterface) {
 332:             $uri = $config['uri'];
 333:         } else {
 334:             $uri = ServerRequestFactory::createUri($config['environment']);
 335:         }
 336: 
 337:         // Extract a query string from config[url] if present.
 338:         // This is required for backwards compatibility and keeping
 339:         // UriInterface implementations happy.
 340:         $querystr = '';
 341:         if (strpos($config['url'], '?') !== false) {
 342:             list($config['url'], $querystr) = explode('?', $config['url']);
 343:         }
 344:         if (strlen($config['url'])) {
 345:             $uri = $uri->withPath('/' . $config['url']);
 346:         }
 347:         if (strlen($querystr)) {
 348:             $uri = $uri->withQuery($querystr);
 349:         }
 350: 
 351:         $this->uri = $uri;
 352:         $this->base = $config['base'];
 353:         $this->webroot = $config['webroot'];
 354: 
 355:         $this->url = substr($uri->getPath(), 1);
 356:         $this->here = $this->base . '/' . $this->url;
 357: 
 358:         if (isset($config['input'])) {
 359:             $stream = new Stream('php://memory', 'rw');
 360:             $stream->write($config['input']);
 361:             $stream->rewind();
 362:         } else {
 363:             $stream = new PhpInputStream();
 364:         }
 365:         $this->stream = $stream;
 366: 
 367:         $config['post'] = $this->_processPost($config['post']);
 368:         $this->data = $this->_processFiles($config['post'], $config['files']);
 369:         $this->query = $this->_processGet($config['query'], $querystr);
 370:         $this->params = $config['params'];
 371:         $this->session = $config['session'];
 372:     }
 373: 
 374:     /**
 375:      * Sets the REQUEST_METHOD environment variable based on the simulated _method
 376:      * HTTP override value. The 'ORIGINAL_REQUEST_METHOD' is also preserved, if you
 377:      * want the read the non-simulated HTTP method the client used.
 378:      *
 379:      * @param array $data Array of post data.
 380:      * @return array
 381:      */
 382:     protected function _processPost($data)
 383:     {
 384:         $method = $this->getEnv('REQUEST_METHOD');
 385:         $override = false;
 386: 
 387:         if (in_array($method, ['PUT', 'DELETE', 'PATCH']) &&
 388:             strpos($this->contentType(), 'application/x-www-form-urlencoded') === 0
 389:         ) {
 390:             $data = $this->input();
 391:             parse_str($data, $data);
 392:         }
 393:         if ($this->hasHeader('X-Http-Method-Override')) {
 394:             $data['_method'] = $this->getHeaderLine('X-Http-Method-Override');
 395:             $override = true;
 396:         }
 397:         $this->_environment['ORIGINAL_REQUEST_METHOD'] = $method;
 398:         if (isset($data['_method'])) {
 399:             $this->_environment['REQUEST_METHOD'] = $data['_method'];
 400:             unset($data['_method']);
 401:             $override = true;
 402:         }
 403: 
 404:         if ($override && !in_array($this->_environment['REQUEST_METHOD'], ['PUT', 'POST', 'DELETE', 'PATCH'])) {
 405:             $data = [];
 406:         }
 407: 
 408:         return $data;
 409:     }
 410: 
 411:     /**
 412:      * Process the GET parameters and move things into the object.
 413:      *
 414:      * @param array $query The array to which the parsed keys/values are being added.
 415:      * @param string $queryString A query string from the URL if provided
 416:      * @return array An array containing the parsed query string as keys/values.
 417:      */
 418:     protected function _processGet($query, $queryString = '')
 419:     {
 420:         $unsetUrl = '/' . str_replace(['.', ' '], '_', urldecode($this->url));
 421:         unset($query[$unsetUrl], $query[$this->base . $unsetUrl]);
 422:         if (strlen($queryString)) {
 423:             parse_str($queryString, $queryArgs);
 424:             $query += $queryArgs;
 425:         }
 426: 
 427:         return $query;
 428:     }
 429: 
 430:     /**
 431:      * Process uploaded files and move things onto the post data.
 432:      *
 433:      * @param array $post Post data to merge files onto.
 434:      * @param array $files Uploaded files to merge in.
 435:      * @return array merged post + file data.
 436:      */
 437:     protected function _processFiles($post, $files)
 438:     {
 439:         if (!is_array($files)) {
 440:             return $post;
 441:         }
 442:         $fileData = [];
 443:         foreach ($files as $key => $value) {
 444:             if ($value instanceof UploadedFileInterface) {
 445:                 $fileData[$key] = $value;
 446:                 continue;
 447:             }
 448: 
 449:             if (is_array($value) && isset($value['tmp_name'])) {
 450:                 $fileData[$key] = $this->_createUploadedFile($value);
 451:                 continue;
 452:             }
 453: 
 454:             throw new InvalidArgumentException(sprintf(
 455:                 'Invalid value in FILES "%s"',
 456:                 json_encode($value)
 457:             ));
 458:         }
 459:         $this->uploadedFiles = $fileData;
 460: 
 461:         // Make a flat map that can be inserted into $post for BC.
 462:         $fileMap = Hash::flatten($fileData);
 463:         foreach ($fileMap as $key => $file) {
 464:             $error = $file->getError();
 465:             $tmpName = '';
 466:             if ($error === UPLOAD_ERR_OK) {
 467:                 $tmpName = $file->getStream()->getMetadata('uri');
 468:             }
 469:             $post = Hash::insert($post, $key, [
 470:                 'tmp_name' => $tmpName,
 471:                 'error' => $error,
 472:                 'name' => $file->getClientFilename(),
 473:                 'type' => $file->getClientMediaType(),
 474:                 'size' => $file->getSize(),
 475:             ]);
 476:         }
 477: 
 478:         return $post;
 479:     }
 480: 
 481:     /**
 482:      * Create an UploadedFile instance from a $_FILES array.
 483:      *
 484:      * If the value represents an array of values, this method will
 485:      * recursively process the data.
 486:      *
 487:      * @param array $value $_FILES struct
 488:      * @return array|UploadedFileInterface
 489:      */
 490:     protected function _createUploadedFile(array $value)
 491:     {
 492:         if (is_array($value['tmp_name'])) {
 493:             return $this->_normalizeNestedFiles($value);
 494:         }
 495: 
 496:         return new UploadedFile(
 497:             $value['tmp_name'],
 498:             $value['size'],
 499:             $value['error'],
 500:             $value['name'],
 501:             $value['type']
 502:         );
 503:     }
 504: 
 505:     /**
 506:      * Normalize an array of file specifications.
 507:      *
 508:      * Loops through all nested files and returns a normalized array of
 509:      * UploadedFileInterface instances.
 510:      *
 511:      * @param array $files The file data to normalize & convert.
 512:      * @return array An array of UploadedFileInterface objects.
 513:      */
 514:     protected function _normalizeNestedFiles(array $files = [])
 515:     {
 516:         $normalizedFiles = [];
 517:         foreach (array_keys($files['tmp_name']) as $key) {
 518:             $spec = [
 519:                 'tmp_name' => $files['tmp_name'][$key],
 520:                 'size' => $files['size'][$key],
 521:                 'error' => $files['error'][$key],
 522:                 'name' => $files['name'][$key],
 523:                 'type' => $files['type'][$key],
 524:             ];
 525:             $normalizedFiles[$key] = $this->_createUploadedFile($spec);
 526:         }
 527: 
 528:         return $normalizedFiles;
 529:     }
 530: 
 531:     /**
 532:      * Get the content type used in this request.
 533:      *
 534:      * @return string
 535:      */
 536:     public function contentType()
 537:     {
 538:         $type = $this->getEnv('CONTENT_TYPE');
 539:         if ($type) {
 540:             return $type;
 541:         }
 542: 
 543:         return $this->getEnv('HTTP_CONTENT_TYPE');
 544:     }
 545: 
 546:     /**
 547:      * Returns the instance of the Session object for this request
 548:      *
 549:      * @return \Cake\Http\Session
 550:      */
 551:     public function getSession()
 552:     {
 553:         return $this->session;
 554:     }
 555: 
 556:     /**
 557:      * Returns the instance of the Session object for this request
 558:      *
 559:      * If a session object is passed as first argument it will be set as
 560:      * the session to use for this request
 561:      *
 562:      * @deprecated 3.5.0 Use getSession() instead. The setter part will be removed.
 563:      * @param \Cake\Http\Session|null $session the session object to use
 564:      * @return \Cake\Http\Session
 565:      */
 566:     public function session(Session $session = null)
 567:     {
 568:         deprecationWarning(
 569:             'ServerRequest::session() is deprecated. ' .
 570:             'Use getSession() instead. The setter part will be removed.'
 571:         );
 572: 
 573:         if ($session === null) {
 574:             return $this->session;
 575:         }
 576: 
 577:         return $this->session = $session;
 578:     }
 579: 
 580:     /**
 581:      * Get the IP the client is using, or says they are using.
 582:      *
 583:      * @return string The client IP.
 584:      */
 585:     public function clientIp()
 586:     {
 587:         if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_FOR')) {
 588:             $addresses = array_map('trim', explode(',', $this->getEnv('HTTP_X_FORWARDED_FOR')));
 589:             $trusted = (count($this->trustedProxies) > 0);
 590:             $n = count($addresses);
 591: 
 592:             if ($trusted) {
 593:                 $trusted = array_diff($addresses, $this->trustedProxies);
 594:                 $trusted = (count($trusted) === 1);
 595:             }
 596: 
 597:             if ($trusted) {
 598:                 return $addresses[0];
 599:             }
 600: 
 601:             return $addresses[$n - 1];
 602:         }
 603: 
 604:         if ($this->trustProxy && $this->getEnv('HTTP_X_REAL_IP')) {
 605:             $ipaddr = $this->getEnv('HTTP_X_REAL_IP');
 606:         } elseif ($this->trustProxy && $this->getEnv('HTTP_CLIENT_IP')) {
 607:             $ipaddr = $this->getEnv('HTTP_CLIENT_IP');
 608:         } else {
 609:             $ipaddr = $this->getEnv('REMOTE_ADDR');
 610:         }
 611: 
 612:         return trim($ipaddr);
 613:     }
 614: 
 615:     /**
 616:      * register trusted proxies
 617:      *
 618:      * @param array $proxies ips list of trusted proxies
 619:      * @return void
 620:      */
 621:     public function setTrustedProxies(array $proxies)
 622:     {
 623:         $this->trustedProxies = $proxies;
 624:         $this->trustProxy = true;
 625:     }
 626: 
 627:     /**
 628:      * Get trusted proxies
 629:      *
 630:      * @return array
 631:      */
 632:     public function getTrustedProxies()
 633:     {
 634:         return $this->trustedProxies;
 635:     }
 636: 
 637:     /**
 638:      * Returns the referer that referred this request.
 639:      *
 640:      * @param bool $local Attempt to return a local address.
 641:      *   Local addresses do not contain hostnames.
 642:      * @return string The referring address for this request.
 643:      */
 644:     public function referer($local = false)
 645:     {
 646:         $ref = $this->getEnv('HTTP_REFERER');
 647: 
 648:         $base = Configure::read('App.fullBaseUrl') . $this->webroot;
 649:         if (!empty($ref) && !empty($base)) {
 650:             if ($local && strpos($ref, $base) === 0) {
 651:                 $ref = substr($ref, strlen($base));
 652:                 if (!strlen($ref) || strpos($ref, '//') === 0) {
 653:                     $ref = '/';
 654:                 }
 655:                 if ($ref[0] !== '/') {
 656:                     $ref = '/' . $ref;
 657:                 }
 658: 
 659:                 return $ref;
 660:             }
 661:             if (!$local) {
 662:                 return $ref;
 663:             }
 664:         }
 665: 
 666:         return '/';
 667:     }
 668: 
 669:     /**
 670:      * Missing method handler, handles wrapping older style isAjax() type methods
 671:      *
 672:      * @param string $name The method called
 673:      * @param array $params Array of parameters for the method call
 674:      * @return mixed
 675:      * @throws \BadMethodCallException when an invalid method is called.
 676:      */
 677:     public function __call($name, $params)
 678:     {
 679:         if (strpos($name, 'is') === 0) {
 680:             $type = strtolower(substr($name, 2));
 681: 
 682:             array_unshift($params, $type);
 683: 
 684:             return $this->is(...$params);
 685:         }
 686:         throw new BadMethodCallException(sprintf('Method %s does not exist', $name));
 687:     }
 688: 
 689:     /**
 690:      * Magic set method allows backward compatibility for former public properties
 691:      *
 692:      *
 693:      * @param string $name The property being accessed.
 694:      * @param mixed $value The property value.
 695:      * @return mixed Either the value of the parameter or null.
 696:      * @deprecated 3.6.0 Public properties will be removed in 4.0.0.
 697:      *   Use appropriate setters instead.
 698:      */
 699:     public function __set($name, $value)
 700:     {
 701:         if (isset($this->deprecatedProperties[$name])) {
 702:             $method = $this->deprecatedProperties[$name]['set'];
 703:             deprecationWarning(
 704:                 "Setting {$name} as a property will be removed in 4.0.0. " .
 705:                 "Use {$method} instead."
 706:             );
 707: 
 708:             return $this->{$name} = $value;
 709:         }
 710:         throw new BadMethodCallException("Cannot set {$name} it is not a known property.");
 711:     }
 712: 
 713:     /**
 714:      * Magic get method allows access to parsed routing parameters directly on the object.
 715:      *
 716:      * Allows access to `$this->params['controller']` via `$this->controller`
 717:      *
 718:      * @param string $name The property being accessed.
 719:      * @return mixed Either the value of the parameter or null.
 720:      * @deprecated 3.4.0 Accessing routing parameters through __get will removed in 4.0.0.
 721:      *   Use getParam() instead.
 722:      */
 723:     public function &__get($name)
 724:     {
 725:         if (isset($this->deprecatedProperties[$name])) {
 726:             $method = $this->deprecatedProperties[$name]['get'];
 727:             deprecationWarning(
 728:                 "Accessing `{$name}` as a property will be removed in 4.0.0. " .
 729:                 "Use request->{$method} instead."
 730:             );
 731: 
 732:             return $this->{$name};
 733:         }
 734: 
 735:         deprecationWarning(sprintf(
 736:             'Accessing routing parameters through `%s` will removed in 4.0.0. ' .
 737:             'Use `getParam()` instead.',
 738:             $name
 739:         ));
 740: 
 741:         if (isset($this->params[$name])) {
 742:             return $this->params[$name];
 743:         }
 744:         $value = null;
 745: 
 746:         return $value;
 747:     }
 748: 
 749:     /**
 750:      * Magic isset method allows isset/empty checks
 751:      * on routing parameters.
 752:      *
 753:      * @param string $name The property being accessed.
 754:      * @return bool Existence
 755:      * @deprecated 3.4.0 Accessing routing parameters through __isset will removed in 4.0.0.
 756:      *   Use getParam() instead.
 757:      */
 758:     public function __isset($name)
 759:     {
 760:         if (isset($this->deprecatedProperties[$name])) {
 761:             $method = $this->deprecatedProperties[$name]['get'];
 762:             deprecationWarning(
 763:                 "Accessing {$name} as a property will be removed in 4.0.0. " .
 764:                 "Use {$method} instead."
 765:             );
 766: 
 767:             return isset($this->{$name});
 768:         }
 769: 
 770:         deprecationWarning(
 771:             'Accessing routing parameters through __isset will removed in 4.0.0. ' .
 772:             'Use getParam() instead.'
 773:         );
 774: 
 775:         return isset($this->params[$name]);
 776:     }
 777: 
 778:     /**
 779:      * Check whether or not a Request is a certain type.
 780:      *
 781:      * Uses the built in detection rules as well as additional rules
 782:      * defined with Cake\Http\ServerRequest::addDetector(). Any detector can be called
 783:      * as `is($type)` or `is$Type()`.
 784:      *
 785:      * @param string|array $type The type of request you want to check. If an array
 786:      *   this method will return true if the request matches any type.
 787:      * @param array ...$args List of arguments
 788:      * @return bool Whether or not the request is the type you are checking.
 789:      */
 790:     public function is($type, ...$args)
 791:     {
 792:         if (is_array($type)) {
 793:             $result = array_map([$this, 'is'], $type);
 794: 
 795:             return count(array_filter($result)) > 0;
 796:         }
 797: 
 798:         $type = strtolower($type);
 799:         if (!isset(static::$_detectors[$type])) {
 800:             return false;
 801:         }
 802:         if ($args) {
 803:             return $this->_is($type, $args);
 804:         }
 805:         if (!isset($this->_detectorCache[$type])) {
 806:             $this->_detectorCache[$type] = $this->_is($type, $args);
 807:         }
 808: 
 809:         return $this->_detectorCache[$type];
 810:     }
 811: 
 812:     /**
 813:      * Clears the instance detector cache, used by the is() function
 814:      *
 815:      * @return void
 816:      */
 817:     public function clearDetectorCache()
 818:     {
 819:         $this->_detectorCache = [];
 820:     }
 821: 
 822:     /**
 823:      * Worker for the public is() function
 824:      *
 825:      * @param string $type The type of request you want to check.
 826:      * @param array $args Array of custom detector arguments.
 827:      * @return bool Whether or not the request is the type you are checking.
 828:      */
 829:     protected function _is($type, $args)
 830:     {
 831:         $detect = static::$_detectors[$type];
 832:         if (is_callable($detect)) {
 833:             array_unshift($args, $this);
 834: 
 835:             return $detect(...$args);
 836:         }
 837:         if (isset($detect['env']) && $this->_environmentDetector($detect)) {
 838:             return true;
 839:         }
 840:         if (isset($detect['header']) && $this->_headerDetector($detect)) {
 841:             return true;
 842:         }
 843:         if (isset($detect['accept']) && $this->_acceptHeaderDetector($detect)) {
 844:             return true;
 845:         }
 846:         if (isset($detect['param']) && $this->_paramDetector($detect)) {
 847:             return true;
 848:         }
 849: 
 850:         return false;
 851:     }
 852: 
 853:     /**
 854:      * Detects if a specific accept header is present.
 855:      *
 856:      * @param array $detect Detector options array.
 857:      * @return bool Whether or not the request is the type you are checking.
 858:      */
 859:     protected function _acceptHeaderDetector($detect)
 860:     {
 861:         $acceptHeaders = explode(',', $this->getEnv('HTTP_ACCEPT'));
 862:         foreach ($detect['accept'] as $header) {
 863:             if (in_array($header, $acceptHeaders)) {
 864:                 return true;
 865:             }
 866:         }
 867: 
 868:         return false;
 869:     }
 870: 
 871:     /**
 872:      * Detects if a specific header is present.
 873:      *
 874:      * @param array $detect Detector options array.
 875:      * @return bool Whether or not the request is the type you are checking.
 876:      */
 877:     protected function _headerDetector($detect)
 878:     {
 879:         foreach ($detect['header'] as $header => $value) {
 880:             $header = $this->getEnv('http_' . $header);
 881:             if ($header !== null) {
 882:                 if (!is_string($value) && !is_bool($value) && is_callable($value)) {
 883:                     return call_user_func($value, $header);
 884:                 }
 885: 
 886:                 return ($header === $value);
 887:             }
 888:         }
 889: 
 890:         return false;
 891:     }
 892: 
 893:     /**
 894:      * Detects if a specific request parameter is present.
 895:      *
 896:      * @param array $detect Detector options array.
 897:      * @return bool Whether or not the request is the type you are checking.
 898:      */
 899:     protected function _paramDetector($detect)
 900:     {
 901:         $key = $detect['param'];
 902:         if (isset($detect['value'])) {
 903:             $value = $detect['value'];
 904: 
 905:             return isset($this->params[$key]) ? $this->params[$key] == $value : false;
 906:         }
 907:         if (isset($detect['options'])) {
 908:             return isset($this->params[$key]) ? in_array($this->params[$key], $detect['options']) : false;
 909:         }
 910: 
 911:         return false;
 912:     }
 913: 
 914:     /**
 915:      * Detects if a specific environment variable is present.
 916:      *
 917:      * @param array $detect Detector options array.
 918:      * @return bool Whether or not the request is the type you are checking.
 919:      */
 920:     protected function _environmentDetector($detect)
 921:     {
 922:         if (isset($detect['env'])) {
 923:             if (isset($detect['value'])) {
 924:                 return $this->getEnv($detect['env']) == $detect['value'];
 925:             }
 926:             if (isset($detect['pattern'])) {
 927:                 return (bool)preg_match($detect['pattern'], $this->getEnv($detect['env']));
 928:             }
 929:             if (isset($detect['options'])) {
 930:                 $pattern = '/' . implode('|', $detect['options']) . '/i';
 931: 
 932:                 return (bool)preg_match($pattern, $this->getEnv($detect['env']));
 933:             }
 934:         }
 935: 
 936:         return false;
 937:     }
 938: 
 939:     /**
 940:      * Check that a request matches all the given types.
 941:      *
 942:      * Allows you to test multiple types and union the results.
 943:      * See Request::is() for how to add additional types and the
 944:      * built-in types.
 945:      *
 946:      * @param array $types The types to check.
 947:      * @return bool Success.
 948:      * @see \Cake\Http\ServerRequest::is()
 949:      */
 950:     public function isAll(array $types)
 951:     {
 952:         $result = array_filter(array_map([$this, 'is'], $types));
 953: 
 954:         return count($result) === count($types);
 955:     }
 956: 
 957:     /**
 958:      * Add a new detector to the list of detectors that a request can use.
 959:      * There are several different formats and types of detectors that can be set.
 960:      *
 961:      * ### Callback detectors
 962:      *
 963:      * Callback detectors allow you to provide a callable to handle the check.
 964:      * The callback will receive the request object as its only parameter.
 965:      *
 966:      * ```
 967:      * addDetector('custom', function ($request) { //Return a boolean });
 968:      * addDetector('custom', ['SomeClass', 'somemethod']);
 969:      * ```
 970:      *
 971:      * ### Environment value comparison
 972:      *
 973:      * An environment value comparison, compares a value fetched from `env()` to a known value
 974:      * the environment value is equality checked against the provided value.
 975:      *
 976:      * e.g `addDetector('post', ['env' => 'REQUEST_METHOD', 'value' => 'POST'])`
 977:      *
 978:      * ### Pattern value comparison
 979:      *
 980:      * Pattern value comparison allows you to compare a value fetched from `env()` to a regular expression.
 981:      *
 982:      * ```
 983:      * addDetector('iphone', ['env' => 'HTTP_USER_AGENT', 'pattern' => '/iPhone/i']);
 984:      * ```
 985:      *
 986:      * ### Option based comparison
 987:      *
 988:      * Option based comparisons use a list of options to create a regular expression. Subsequent calls
 989:      * to add an already defined options detector will merge the options.
 990:      *
 991:      * ```
 992:      * addDetector('mobile', ['env' => 'HTTP_USER_AGENT', 'options' => ['Fennec']]);
 993:      * ```
 994:      *
 995:      * ### Request parameter detectors
 996:      *
 997:      * Allows for custom detectors on the request parameters.
 998:      *
 999:      * e.g `addDetector('requested', ['param' => 'requested', 'value' => 1]`
1000:      *
1001:      * You can also make parameter detectors that accept multiple values
1002:      * using the `options` key. This is useful when you want to check
1003:      * if a request parameter is in a list of options.
1004:      *
1005:      * `addDetector('extension', ['param' => 'ext', 'options' => ['pdf', 'csv']]`
1006:      *
1007:      * @param string $name The name of the detector.
1008:      * @param callable|array $callable A callable or options array for the detector definition.
1009:      * @return void
1010:      */
1011:     public static function addDetector($name, $callable)
1012:     {
1013:         $name = strtolower($name);
1014:         if (is_callable($callable)) {
1015:             static::$_detectors[$name] = $callable;
1016: 
1017:             return;
1018:         }
1019:         if (isset(static::$_detectors[$name], $callable['options'])) {
1020:             $callable = Hash::merge(static::$_detectors[$name], $callable);
1021:         }
1022:         static::$_detectors[$name] = $callable;
1023:     }
1024: 
1025:     /**
1026:      * Add parameters to the request's parsed parameter set. This will overwrite any existing parameters.
1027:      * This modifies the parameters available through `$request->getParam()`.
1028:      *
1029:      * @param array $params Array of parameters to merge in
1030:      * @return $this The current object, you can chain this method.
1031:      * @deprecated 3.6.0 ServerRequest::addParams() is deprecated. Use `withParam()` or
1032:      *   `withAttribute('params')` instead.
1033:      */
1034:     public function addParams(array $params)
1035:     {
1036:         deprecationWarning(
1037:             'ServerRequest::addParams() is deprecated. ' .
1038:             'Use `withParam()` or `withAttribute("params", $params)` instead.'
1039:         );
1040:         $this->params = array_merge($this->params, $params);
1041: 
1042:         return $this;
1043:     }
1044: 
1045:     /**
1046:      * Add paths to the requests' paths vars. This will overwrite any existing paths.
1047:      * Provides an easy way to modify, here, webroot and base.
1048:      *
1049:      * @param array $paths Array of paths to merge in
1050:      * @return $this The current object, you can chain this method.
1051:      * @deprecated 3.6.0 Mutating a request in place is deprecated. Use `withAttribute()` to modify paths instead.
1052:      */
1053:     public function addPaths(array $paths)
1054:     {
1055:         deprecationWarning(
1056:             'ServerRequest::addPaths() is deprecated. ' .
1057:             'Use `withAttribute($key, $value)` instead.'
1058:         );
1059:         foreach (['webroot', 'here', 'base'] as $element) {
1060:             if (isset($paths[$element])) {
1061:                 $this->{$element} = $paths[$element];
1062:             }
1063:         }
1064: 
1065:         return $this;
1066:     }
1067: 
1068:     /**
1069:      * Get the value of the current requests URL. Will include the query string arguments.
1070:      *
1071:      * @param bool $base Include the base path, set to false to trim the base path off.
1072:      * @return string The current request URL including query string args.
1073:      * @deprecated 3.4.0 This method will be removed in 4.0.0. You should use getRequestTarget() instead.
1074:      */
1075:     public function here($base = true)
1076:     {
1077:         deprecationWarning(
1078:             'ServerRequest::here() will be removed in 4.0.0. You should use getRequestTarget() instead.'
1079:         );
1080: 
1081:         $url = $this->here;
1082:         if (!empty($this->query)) {
1083:             $url .= '?' . http_build_query($this->query, null, '&');
1084:         }
1085:         if (!$base) {
1086:             $url = preg_replace('/^' . preg_quote($this->base, '/') . '/', '', $url, 1);
1087:         }
1088: 
1089:         return $url;
1090:     }
1091: 
1092:     /**
1093:      * Normalize a header name into the SERVER version.
1094:      *
1095:      * @param string $name The header name.
1096:      * @return string The normalized header name.
1097:      */
1098:     protected function normalizeHeaderName($name)
1099:     {
1100:         $name = str_replace('-', '_', strtoupper($name));
1101:         if (!in_array($name, ['CONTENT_LENGTH', 'CONTENT_TYPE'])) {
1102:             $name = 'HTTP_' . $name;
1103:         }
1104: 
1105:         return $name;
1106:     }
1107: 
1108:     /**
1109:      * Read an HTTP header from the Request information.
1110:      *
1111:      * If the header is not defined in the request, this method
1112:      * will fallback to reading data from $_SERVER and $_ENV.
1113:      * This fallback behavior is deprecated, and will be removed in 4.0.0
1114:      *
1115:      * @param string $name Name of the header you want.
1116:      * @return string|null Either null on no header being set or the value of the header.
1117:      * @deprecated 4.0.0 The automatic fallback to env() will be removed in 4.0.0, see getHeader()
1118:      */
1119:     public function header($name)
1120:     {
1121:         deprecationWarning(
1122:             'ServerRequest::header() is deprecated. ' .
1123:             'The automatic fallback to env() will be removed in 4.0.0, see getHeader()'
1124:         );
1125: 
1126:         $name = $this->normalizeHeaderName($name);
1127: 
1128:         return $this->getEnv($name);
1129:     }
1130: 
1131:     /**
1132:      * Get all headers in the request.
1133:      *
1134:      * Returns an associative array where the header names are
1135:      * the keys and the values are a list of header values.
1136:      *
1137:      * While header names are not case-sensitive, getHeaders() will normalize
1138:      * the headers.
1139:      *
1140:      * @return array An associative array of headers and their values.
1141:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1142:      */
1143:     public function getHeaders()
1144:     {
1145:         $headers = [];
1146:         foreach ($this->_environment as $key => $value) {
1147:             $name = null;
1148:             if (strpos($key, 'HTTP_') === 0) {
1149:                 $name = substr($key, 5);
1150:             }
1151:             if (strpos($key, 'CONTENT_') === 0) {
1152:                 $name = $key;
1153:             }
1154:             if ($name !== null) {
1155:                 $name = str_replace('_', ' ', strtolower($name));
1156:                 $name = str_replace(' ', '-', ucwords($name));
1157:                 $headers[$name] = (array)$value;
1158:             }
1159:         }
1160: 
1161:         return $headers;
1162:     }
1163: 
1164:     /**
1165:      * Check if a header is set in the request.
1166:      *
1167:      * @param string $name The header you want to get (case-insensitive)
1168:      * @return bool Whether or not the header is defined.
1169:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1170:      */
1171:     public function hasHeader($name)
1172:     {
1173:         $name = $this->normalizeHeaderName($name);
1174: 
1175:         return isset($this->_environment[$name]);
1176:     }
1177: 
1178:     /**
1179:      * Get a single header from the request.
1180:      *
1181:      * Return the header value as an array. If the header
1182:      * is not present an empty array will be returned.
1183:      *
1184:      * @param string $name The header you want to get (case-insensitive)
1185:      * @return array An associative array of headers and their values.
1186:      *   If the header doesn't exist, an empty array will be returned.
1187:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1188:      */
1189:     public function getHeader($name)
1190:     {
1191:         $name = $this->normalizeHeaderName($name);
1192:         if (isset($this->_environment[$name])) {
1193:             return (array)$this->_environment[$name];
1194:         }
1195: 
1196:         return [];
1197:     }
1198: 
1199:     /**
1200:      * Get a single header as a string from the request.
1201:      *
1202:      * @param string $name The header you want to get (case-insensitive)
1203:      * @return string Header values collapsed into a comma separated string.
1204:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1205:      */
1206:     public function getHeaderLine($name)
1207:     {
1208:         $value = $this->getHeader($name);
1209: 
1210:         return implode(', ', $value);
1211:     }
1212: 
1213:     /**
1214:      * Get a modified request with the provided header.
1215:      *
1216:      * @param string $name The header name.
1217:      * @param string|array $value The header value
1218:      * @return static
1219:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1220:      */
1221:     public function withHeader($name, $value)
1222:     {
1223:         $new = clone $this;
1224:         $name = $this->normalizeHeaderName($name);
1225:         $new->_environment[$name] = $value;
1226: 
1227:         return $new;
1228:     }
1229: 
1230:     /**
1231:      * Get a modified request with the provided header.
1232:      *
1233:      * Existing header values will be retained. The provided value
1234:      * will be appended into the existing values.
1235:      *
1236:      * @param string $name The header name.
1237:      * @param string|array $value The header value
1238:      * @return static
1239:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1240:      */
1241:     public function withAddedHeader($name, $value)
1242:     {
1243:         $new = clone $this;
1244:         $name = $this->normalizeHeaderName($name);
1245:         $existing = [];
1246:         if (isset($new->_environment[$name])) {
1247:             $existing = (array)$new->_environment[$name];
1248:         }
1249:         $existing = array_merge($existing, (array)$value);
1250:         $new->_environment[$name] = $existing;
1251: 
1252:         return $new;
1253:     }
1254: 
1255:     /**
1256:      * Get a modified request without a provided header.
1257:      *
1258:      * @param string $name The header name to remove.
1259:      * @return static
1260:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1261:      */
1262:     public function withoutHeader($name)
1263:     {
1264:         $new = clone $this;
1265:         $name = $this->normalizeHeaderName($name);
1266:         unset($new->_environment[$name]);
1267: 
1268:         return $new;
1269:     }
1270: 
1271:     /**
1272:      * Get the HTTP method used for this request.
1273:      *
1274:      * @return string The name of the HTTP method used.
1275:      * @deprecated 3.4.0 This method will be removed in 4.0.0. Use getMethod() instead.
1276:      */
1277:     public function method()
1278:     {
1279:         deprecationWarning(
1280:             'ServerRequest::method() is deprecated. ' .
1281:             'This method will be removed in 4.0.0. Use getMethod() instead.'
1282:         );
1283: 
1284:         return $this->getEnv('REQUEST_METHOD');
1285:     }
1286: 
1287:     /**
1288:      * Get the HTTP method used for this request.
1289:      * There are a few ways to specify a method.
1290:      *
1291:      * - If your client supports it you can use native HTTP methods.
1292:      * - You can set the HTTP-X-Method-Override header.
1293:      * - You can submit an input with the name `_method`
1294:      *
1295:      * Any of these 3 approaches can be used to set the HTTP method used
1296:      * by CakePHP internally, and will effect the result of this method.
1297:      *
1298:      * @return string The name of the HTTP method used.
1299:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1300:      */
1301:     public function getMethod()
1302:     {
1303:         return $this->getEnv('REQUEST_METHOD');
1304:     }
1305: 
1306:     /**
1307:      * Update the request method and get a new instance.
1308:      *
1309:      * @param string $method The HTTP method to use.
1310:      * @return static A new instance with the updated method.
1311:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1312:      */
1313:     public function withMethod($method)
1314:     {
1315:         $new = clone $this;
1316: 
1317:         if (!is_string($method) ||
1318:             !preg_match('/^[!#$%&\'*+.^_`\|~0-9a-z-]+$/i', $method)
1319:         ) {
1320:             throw new InvalidArgumentException(sprintf(
1321:                 'Unsupported HTTP method "%s" provided',
1322:                 $method
1323:             ));
1324:         }
1325:         $new->_environment['REQUEST_METHOD'] = $method;
1326: 
1327:         return $new;
1328:     }
1329: 
1330:     /**
1331:      * Get all the server environment parameters.
1332:      *
1333:      * Read all of the 'environment' or 'server' data that was
1334:      * used to create this request.
1335:      *
1336:      * @return array
1337:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1338:      */
1339:     public function getServerParams()
1340:     {
1341:         return $this->_environment;
1342:     }
1343: 
1344:     /**
1345:      * Get all the query parameters in accordance to the PSR-7 specifications. To read specific query values
1346:      * use the alternative getQuery() method.
1347:      *
1348:      * @return array
1349:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1350:      */
1351:     public function getQueryParams()
1352:     {
1353:         return $this->query;
1354:     }
1355: 
1356:     /**
1357:      * Update the query string data and get a new instance.
1358:      *
1359:      * @param array $query The query string data to use
1360:      * @return static A new instance with the updated query string data.
1361:      * @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
1362:      */
1363:     public function withQueryParams(array $query)
1364:     {
1365:         $new = clone $this;
1366:         $new->query = $query;
1367: 
1368:         return $new;
1369:     }
1370: 
1371:     /**
1372:      * Get the host that the request was handled on.
1373:      *
1374:      * @return string
1375:      */
1376:     public function host()
1377:     {
1378:         if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_HOST')) {
1379:             return $this->getEnv('HTTP_X_FORWARDED_HOST');
1380:         }
1381: 
1382:         return $this->getEnv('HTTP_HOST');
1383:     }
1384: 
1385:     /**
1386:      * Get the port the request was handled on.
1387:      *
1388:      * @return string
1389:      */
1390:     public function port()
1391:     {
1392:         if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_PORT')) {
1393:             return $this->getEnv('HTTP_X_FORWARDED_PORT');
1394:         }
1395: 
1396:         return $this->getEnv('SERVER_PORT');
1397:     }
1398: 
1399:     /**
1400:      * Get the current url scheme used for the request.
1401:      *
1402:      * e.g. 'http', or 'https'
1403:      *
1404:      * @return string The scheme used for the request.
1405:      */
1406:     public function scheme()
1407:     {
1408:         if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_PROTO')) {
1409:             return $this->getEnv('HTTP_X_FORWARDED_PROTO');
1410:         }
1411: 
1412:         return $this->getEnv('HTTPS') ? 'https' : 'http';
1413:     }
1414: 
1415:     /**
1416:      * Get the domain name and include $tldLength segments of the tld.
1417:      *
1418:      * @param int $tldLength Number of segments your tld contains. For example: `example.com` contains 1 tld.
1419:      *   While `example.co.uk` contains 2.
1420:      * @return string Domain name without subdomains.
1421:      */
1422:     public function domain($tldLength = 1)
1423:     {
1424:         $segments = explode('.', $this->host());
1425:         $domain = array_slice($segments, -1 * ($tldLength + 1));
1426: 
1427:         return implode('.', $domain);
1428:     }
1429: 
1430:     /**
1431:      * Get the subdomains for a host.
1432:      *
1433:      * @param int $tldLength Number of segments your tld contains. For example: `example.com` contains 1 tld.
1434:      *   While `example.co.uk` contains 2.
1435:      * @return array An array of subdomains.
1436:      */
1437:     public function subdomains($tldLength = 1)
1438:     {
1439:         $segments = explode('.', $this->host());
1440: 
1441:         return array_slice($segments, 0, -1 * ($tldLength + 1));
1442:     }
1443: 
1444:     /**
1445:      * Find out which content types the client accepts or check if they accept a
1446:      * particular type of content.
1447:      *
1448:      * #### Get all types:
1449:      *
1450:      * ```
1451:      * $this->request->accepts();
1452:      * ```
1453:      *
1454:      * #### Check for a single type:
1455:      *
1456:      * ```
1457:      * $this->request->accepts('application/json');
1458:      * ```
1459:      *
1460:      * This method will order the returned content types by the preference values indicated
1461:      * by the client.
1462:      *
1463:      * @param string|null $type The content type to check for. Leave null to get all types a client accepts.
1464:      * @return array|bool Either an array of all the types the client accepts or a boolean if they accept the
1465:      *   provided type.
1466:      */
1467:     public function accepts($type = null)
1468:     {
1469:         $raw = $this->parseAccept();
1470:         $accept = [];
1471:         foreach ($raw as $types) {
1472:             $accept = array_merge($accept, $types);
1473:         }
1474:         if ($type === null) {
1475:             return $accept;
1476:         }
1477: 
1478:         return in_array($type, $accept);
1479:     }
1480: 
1481:     /**
1482:      * Parse the HTTP_ACCEPT header and return a sorted array with content types
1483:      * as the keys, and pref values as the values.
1484:      *
1485:      * Generally you want to use Cake\Http\ServerRequest::accept() to get a simple list
1486:      * of the accepted content types.
1487:      *
1488:      * @return array An array of prefValue => [content/types]
1489:      */
1490:     public function parseAccept()
1491:     {
1492:         return $this->_parseAcceptWithQualifier($this->getHeaderLine('Accept'));
1493:     }
1494: 
1495:     /**
1496:      * Get the languages accepted by the client, or check if a specific language is accepted.
1497:      *
1498:      * Get the list of accepted languages:
1499:      *
1500:      * ``` \Cake\Http\ServerRequest::acceptLanguage(); ```
1501:      *
1502:      * Check if a specific language is accepted:
1503:      *
1504:      * ``` \Cake\Http\ServerRequest::acceptLanguage('es-es'); ```
1505:      *
1506:      * @param string|null $language The language to test.
1507:      * @return array|bool If a $language is provided, a boolean. Otherwise the array of accepted languages.
1508:      */
1509:     public function acceptLanguage($language = null)
1510:     {
1511:         $raw = $this->_parseAcceptWithQualifier($this->getHeaderLine('Accept-Language'));
1512:         $accept = [];
1513:         foreach ($raw as $languages) {
1514:             foreach ($languages as &$lang) {
1515:                 if (strpos($lang, '_')) {
1516:                     $lang = str_replace('_', '-', $lang);
1517:                 }
1518:                 $lang = strtolower($lang);
1519:             }
1520:             $accept = array_merge($accept, $languages);
1521:         }
1522:         if ($language === null) {
1523:             return $accept;
1524:         }
1525: 
1526:         return in_array(strtolower($language), $accept);
1527:     }
1528: 
1529:     /**
1530:      * Parse Accept* headers with qualifier options.
1531:      *
1532:      * Only qualifiers will be extracted, any other accept extensions will be
1533:      * discarded as they are not frequently used.
1534:      *
1535:      * @param string $header Header to parse.
1536:      * @return array
1537:      */
1538:     protected function _parseAcceptWithQualifier($header)
1539:     {
1540:         $accept = [];
1541:         $headers = explode(',', $header);
1542:         foreach (array_filter($headers) as $value) {
1543:             $prefValue = '1.0';
1544:             $value = trim($value);
1545: 
1546:             $semiPos = strpos($value, ';');
1547:             if ($semiPos !== false) {
1548:                 $params = explode(';', $value);
1549:                 $value = trim($params[0]);
1550:                 foreach ($params as $param) {
1551:                     $qPos = strpos($param, 'q=');
1552:                     if ($qPos !== false) {
1553:                         $prefValue = substr($param, $qPos + 2);
1554:                     }
1555:                 }
1556:             }
1557: 
1558:             if (!isset($accept[$prefValue])) {
1559:                 $accept[$prefValue] = [];
1560:             }
1561:             if ($prefValue) {
1562:                 $accept[$prefValue][] = $value;
1563:             }
1564:         }
1565:         krsort($accept);
1566: 
1567:         return $accept;
1568:     }
1569: 
1570:     /**
1571:      * Provides a read accessor for `$this->query`.
1572:      * Allows you to use a `Hash::get()` compatible syntax for reading post data.
1573:      *
1574:      * @param string|null $name Query string variable name or null to read all.
1575:      * @return string|array|null The value being read
1576:      * @deprecated 3.4.0 Use getQuery() or the PSR-7 getQueryParams() and withQueryParams() methods instead.
1577:      */
1578:     public function query($name = null)
1579:     {
1580:         deprecationWarning(
1581:             'ServerRequest::query() is deprecated. ' .
1582:             'Use getQuery() or the PSR-7 getQueryParams() and withQueryParams() methods instead.'
1583:         );
1584: 
1585:         if ($name === null) {
1586:             return $this->query;
1587:         }
1588: 
1589:         return $this->getQuery($name);
1590:     }
1591: 
1592:     /**
1593:      * Read a specific query value or dotted path.
1594:      *
1595:      * Developers are encouraged to use getQueryParams() when possible as it is PSR-7 compliant, and this method
1596:      * is not.
1597:      *
1598:      * ### PSR-7 Alternative
1599:      *
1600:      * ```
1601:      * $value = Hash::get($request->getQueryParams(), 'Post.id', null);
1602:      * ```
1603:      *
1604:      * @param string|null $name The name or dotted path to the query param or null to read all.
1605:      * @param mixed $default The default value if the named parameter is not set, and $name is not null.
1606:      * @return null|string|array Query data.
1607:      * @see ServerRequest::getQueryParams()
1608:      */
1609:     public function getQuery($name = null, $default = null)
1610:     {
1611:         if ($name === null) {
1612:             return $this->query;
1613:         }
1614: 
1615:         return Hash::get($this->query, $name, $default);
1616:     }
1617: 
1618:     /**
1619:      * Provides a read/write accessor for `$this->data`.
1620:      * Allows you to use a `Hash::get()` compatible syntax for reading post data.
1621:      *
1622:      * ### Reading values.
1623:      *
1624:      * ```
1625:      * $request->data('Post.title');
1626:      * ```
1627:      *
1628:      * When reading values you will get `null` for keys/values that do not exist.
1629:      *
1630:      * ### Writing values
1631:      *
1632:      * ```
1633:      * $request->data('Post.title', 'New post!');
1634:      * ```
1635:      *
1636:      * You can write to any value, even paths/keys that do not exist, and the arrays
1637:      * will be created for you.
1638:      *
1639:      * @param string|null $name Dot separated name of the value to read/write
1640:      * @param mixed ...$args The data to set (deprecated)
1641:      * @return mixed|$this Either the value being read, or this so you can chain consecutive writes.
1642:      * @deprecated 3.4.0 Use withData() and getData() or getParsedBody() instead.
1643:      */
1644:     public function data($name = null, ...$args)
1645:     {
1646:         deprecationWarning(
1647:             'ServerRequest::data() is deprecated. ' .
1648:             'Use withData() and getData() or getParsedBody() instead.'
1649:         );
1650: 
1651:         if (count($args) === 1) {
1652:             $this->data = Hash::insert($this->data, $name, $args[0]);
1653: 
1654:             return $this;
1655:         }
1656:         if ($name !== null) {
1657:             return Hash::get($this->data, $name);
1658:         }
1659: 
1660:         return $this->data;
1661:     }
1662: 
1663:     /**
1664:      * Provides a safe accessor for request data. Allows
1665:      * you to use Hash::get() compatible paths.
1666:      *
1667:      * ### Reading values.
1668:      *
1669:      * ```
1670:      * // get all data
1671:      * $request->getData();
1672:      *
1673:      * // Read a specific field.
1674:      * $request->getData('Post.title');
1675:      *
1676:      * // With a default value.
1677:      * $request->getData('Post.not there', 'default value');
1678:      * ```
1679:      *
1680:      * When reading values you will get `null` for keys/values that do not exist.
1681:      *
1682:      * @param string|null $name Dot separated name of the value to read. Or null to read all data.
1683:      * @param mixed $default The default data.
1684:      * @return null|string|array The value being read.
1685:      */
1686:     public function getData($name = null, $default = null)
1687:     {
1688:         if ($name === null) {
1689:             return $this->data;
1690:         }
1691:         if (!is_array($this->data) && $name) {
1692:             return $default;
1693:         }
1694: 
1695:         return Hash::get($this->data, $name, $default);
1696:     }
1697: 
1698:     /**
1699:      * Safely access the values in $this->params.
1700:      *
1701:      * @param string $name The name of the parameter to get.
1702:      * @param mixed ...$args Value to set (deprecated).
1703:      * @return mixed|$this The value of the provided parameter. Will
1704:      *   return false if the parameter doesn't exist or is falsey.
1705:      * @deprecated 3.4.0 Use getParam() and withParam() instead.
1706:      */
1707:     public function param($name, ...$args)
1708:     {
1709:         deprecationWarning(
1710:             'ServerRequest::param() is deprecated. ' .
1711:             'Use getParam() and withParam() instead.'
1712:         );
1713: 
1714:         if (count($args) === 1) {
1715:             $this->params = Hash::insert($this->params, $name, $args[0]);
1716: 
1717:             return $this;
1718:         }
1719: 
1720:         return $this->getParam($name);
1721:     }
1722: 
1723:     /**
1724:      * Read data from `php://input`. Useful when interacting with XML or JSON
1725:      * request body content.
1726:      *
1727:      * Getting input with a decoding function:
1728:      *
1729:      * ```
1730:      * $this->request->input('json_decode');
1731:      * ```
1732:      *
1733:      * Getting input using a decoding function, and additional params:
1734:      *
1735:      * ```
1736:      * $this->request->input('Xml::build', ['return' => 'DOMDocument']);
1737:      * ```
1738:      *
1739:      * Any additional parameters are applied to the callback in the order they are given.
1740:      *
1741:      * @param string|null $callback A decoding callback that will convert the string data to another
1742:      *     representation. Leave empty to access the raw input data. You can also
1743:      *     supply additional parameters for the decoding callback using var args, see above.
1744:      * @param array ...$args The additional arguments
1745:      * @return string The decoded/processed request data.
1746:      */
1747:     public function input($callback = null, ...$args)
1748:     {
1749:         $this->stream->rewind();
1750:         $input = $this->stream->getContents();
1751:         if ($callback) {
1752:             array_unshift($args, $input);
1753: 
1754:             return call_user_func_array($callback, $args);
1755:         }
1756: 
1757:         return $input;
1758:     }
1759: 
1760:     /**
1761:      * Read cookie data from the request's cookie data.
1762:      *
1763:      * @param string $key The key you want to read.
1764:      * @return null|string Either the cookie value, or null if the value doesn't exist.
1765:      * @deprecated 3.4.0 Use getCookie() instead.
1766:      */
1767:     public function cookie($key)
1768:     {
1769:         deprecationWarning(
1770:             'ServerRequest::cookie() is deprecated. ' .
1771:             'Use getCookie() instead.'
1772:         );
1773: 
1774:         if (isset($this->cookies[$key])) {
1775:             return $this->cookies[$key];
1776:         }
1777: 
1778:         return null;
1779:     }
1780: 
1781:     /**
1782:      * Read cookie data from the request's cookie data.
1783:      *
1784:      * @param string $key The key or dotted path you want to read.
1785:      * @param string $default The default value if the cookie is not set.
1786:      * @return null|array|string Either the cookie value, or null if the value doesn't exist.
1787:      */
1788:     public function getCookie($key, $default = null)
1789:     {
1790:         return Hash::get($this->cookies, $key, $default);
1791:     }
1792: 
1793:     /**
1794:      * Get a cookie collection based on the request's cookies
1795:      *
1796:      * The CookieCollection lets you interact with request cookies using
1797:      * `\Cake\Http\Cookie\Cookie` objects and can make converting request cookies
1798:      * into response cookies easier.
1799:      *
1800:      * This method will create a new cookie collection each time it is called.
1801:      * This is an optimization that allows fewer objects to be allocated until
1802:      * the more complex CookieCollection is needed. In general you should prefer
1803:      * `getCookie()` and `getCookieParams()` over this method. Using a CookieCollection
1804:      * is ideal if your cookies contain complex JSON encoded data.
1805:      *
1806:      * @return \Cake\Http\Cookie\CookieCollection
1807:      */
1808:     public function getCookieCollection()
1809:     {
1810:         return CookieCollection::createFromServerRequest($this);
1811:     }
1812: 
1813:     /**
1814:      * Replace the cookies in the request with those contained in
1815:      * the provided CookieCollection.
1816:      *
1817:      * @param \Cake\Http\Cookie\CookieCollection $cookies The cookie collection
1818:      * @return static
1819:      */
1820:     public function withCookieCollection(CookieCollection $cookies)
1821:     {
1822:         $new = clone $this;
1823:         $values = [];
1824:         foreach ($cookies as $cookie) {
1825:             $values[$cookie->getName()] = $cookie->getValue();
1826:         }
1827:         $new->cookies = $values;
1828: 
1829:         return $new;
1830:     }
1831: 
1832:     /**
1833:      * Get all the cookie data from the request.
1834:      *
1835:      * @return array An array of cookie data.
1836:      */
1837:     public function getCookieParams()
1838:     {
1839:         return $this->cookies;
1840:     }
1841: 
1842:     /**
1843:      * Replace the cookies and get a new request instance.
1844:      *
1845:      * @param array $cookies The new cookie data to use.
1846:      * @return static
1847:      */
1848:     public function withCookieParams(array $cookies)
1849:     {
1850:         $new = clone $this;
1851:         $new->cookies = $cookies;
1852: 
1853:         return $new;
1854:     }
1855: 
1856:     /**
1857:      * Get the parsed request body data.
1858:      *
1859:      * If the request Content-Type is either application/x-www-form-urlencoded
1860:      * or multipart/form-data, and the request method is POST, this will be the
1861:      * post data. For other content types, it may be the deserialized request
1862:      * body.
1863:      *
1864:      * @return null|array|object The deserialized body parameters, if any.
1865:      *     These will typically be an array or object.
1866:      */
1867:     public function getParsedBody()
1868:     {
1869:         return $this->data;
1870:     }
1871: 
1872:     /**
1873:      * Update the parsed body and get a new instance.
1874:      *
1875:      * @param null|array|object $data The deserialized body data. This will
1876:      *     typically be in an array or object.
1877:      * @return static
1878:      */
1879:     public function withParsedBody($data)
1880:     {
1881:         $new = clone $this;
1882:         $new->data = $data;
1883: 
1884:         return $new;
1885:     }
1886: 
1887:     /**
1888:      * Retrieves the HTTP protocol version as a string.
1889:      *
1890:      * @return string HTTP protocol version.
1891:      */
1892:     public function getProtocolVersion()
1893:     {
1894:         if ($this->protocol) {
1895:             return $this->protocol;
1896:         }
1897: 
1898:         // Lazily populate this data as it is generally not used.
1899:         preg_match('/^HTTP\/([\d.]+)$/', $this->getEnv('SERVER_PROTOCOL'), $match);
1900:         $protocol = '1.1';
1901:         if (isset($match[1])) {
1902:             $protocol = $match[1];
1903:         }
1904:         $this->protocol = $protocol;
1905: 
1906:         return $this->protocol;
1907:     }
1908: 
1909:     /**
1910:      * Return an instance with the specified HTTP protocol version.
1911:      *
1912:      * The version string MUST contain only the HTTP version number (e.g.,
1913:      * "1.1", "1.0").
1914:      *
1915:      * @param string $version HTTP protocol version
1916:      * @return static
1917:      */
1918:     public function withProtocolVersion($version)
1919:     {
1920:         if (!preg_match('/^(1\.[01]|2)$/', $version)) {
1921:             throw new InvalidArgumentException("Unsupported protocol version '{$version}' provided");
1922:         }
1923:         $new = clone $this;
1924:         $new->protocol = $version;
1925: 
1926:         return $new;
1927:     }
1928: 
1929:     /**
1930:      * Get a value from the request's environment data.
1931:      * Fallback to using env() if the key is not set in the $environment property.
1932:      *
1933:      * @param string $key The key you want to read from.
1934:      * @param string|null $default Default value when trying to retrieve an environment
1935:      *   variable's value that does not exist.
1936:      * @return string|null Either the environment value, or null if the value doesn't exist.
1937:      */
1938:     public function getEnv($key, $default = null)
1939:     {
1940:         $key = strtoupper($key);
1941:         if (!array_key_exists($key, $this->_environment)) {
1942:             $this->_environment[$key] = env($key);
1943:         }
1944: 
1945:         return $this->_environment[$key] !== null ? $this->_environment[$key] : $default;
1946:     }
1947: 
1948:     /**
1949:      * Update the request with a new environment data element.
1950:      *
1951:      * Returns an updated request object. This method returns
1952:      * a *new* request object and does not mutate the request in-place.
1953:      *
1954:      * @param string $key The key you want to write to.
1955:      * @param string $value Value to set
1956:      * @return static
1957:      */
1958:     public function withEnv($key, $value)
1959:     {
1960:         $new = clone $this;
1961:         $new->_environment[$key] = $value;
1962:         $new->clearDetectorCache();
1963: 
1964:         return $new;
1965:     }
1966: 
1967:     /**
1968:      * Get/Set value from the request's environment data.
1969:      * Fallback to using env() if key not set in $environment property.
1970:      *
1971:      * @deprecated 3.5.0 Use getEnv()/withEnv() instead.
1972:      * @param string $key The key you want to read/write from/to.
1973:      * @param string|null $value Value to set. Default null.
1974:      * @param string|null $default Default value when trying to retrieve an environment
1975:      *   variable's value that does not exist. The value parameter must be null.
1976:      * @return $this|string|null This instance if used as setter,
1977:      *   if used as getter either the environment value, or null if the value doesn't exist.
1978:      */
1979:     public function env($key, $value = null, $default = null)
1980:     {
1981:         deprecationWarning(
1982:             'ServerRequest::env() is deprecated. ' .
1983:             'Use getEnv()/withEnv() instead.'
1984:         );
1985: 
1986:         if ($value !== null) {
1987:             $this->_environment[$key] = $value;
1988:             $this->clearDetectorCache();
1989: 
1990:             return $this;
1991:         }
1992: 
1993:         $key = strtoupper($key);
1994:         if (!array_key_exists($key, $this->_environment)) {
1995:             $this->_environment[$key] = env($key);
1996:         }
1997: 
1998:         return $this->_environment[$key] !== null ? $this->_environment[$key] : $default;
1999:     }
2000: 
2001:     /**
2002:      * Allow only certain HTTP request methods, if the request method does not match
2003:      * a 405 error will be shown and the required "Allow" response header will be set.
2004:      *
2005:      * Example:
2006:      *
2007:      * $this->request->allowMethod('post');
2008:      * or
2009:      * $this->request->allowMethod(['post', 'delete']);
2010:      *
2011:      * If the request would be GET, response header "Allow: POST, DELETE" will be set
2012:      * and a 405 error will be returned.
2013:      *
2014:      * @param string|array $methods Allowed HTTP request methods.
2015:      * @return bool true
2016:      * @throws \Cake\Http\Exception\MethodNotAllowedException
2017:      */
2018:     public function allowMethod($methods)
2019:     {
2020:         $methods = (array)$methods;
2021:         foreach ($methods as $method) {
2022:             if ($this->is($method)) {
2023:                 return true;
2024:             }
2025:         }
2026:         $allowed = strtoupper(implode(', ', $methods));
2027:         $e = new MethodNotAllowedException();
2028:         $e->responseHeader('Allow', $allowed);
2029:         throw $e;
2030:     }
2031: 
2032:     /**
2033:      * Read data from php://input, mocked in tests.
2034:      *
2035:      * @return string contents of php://input
2036:      */
2037:     protected function _readInput()
2038:     {
2039:         if (empty($this->_input)) {
2040:             $fh = fopen('php://input', 'rb');
2041:             $content = stream_get_contents($fh);
2042:             fclose($fh);
2043:             $this->_input = $content;
2044:         }
2045: 
2046:         return $this->_input;
2047:     }
2048: 
2049:     /**
2050:      * Modify data originally from `php://input`. Useful for altering json/xml data
2051:      * in middleware or DispatcherFilters before it gets to RequestHandlerComponent
2052:      *
2053:      * @param string $input A string to replace original parsed data from input()
2054:      * @return void
2055:      * @deprecated 3.4.0 This method will be removed in 4.0.0. Use withBody() instead.
2056:      */
2057:     public function setInput($input)
2058:     {
2059:         deprecationWarning(
2060:             'This method will be removed in 4.0.0.' .
2061:             'Use withBody() instead.'
2062:         );
2063: 
2064:         $stream = new Stream('php://memory', 'rw');
2065:         $stream->write($input);
2066:         $stream->rewind();
2067:         $this->stream = $stream;
2068:     }
2069: 
2070:     /**
2071:      * Update the request with a new request data element.
2072:      *
2073:      * Returns an updated request object. This method returns
2074:      * a *new* request object and does not mutate the request in-place.
2075:      *
2076:      * Use `withParsedBody()` if you need to replace the all request data.
2077:      *
2078:      * @param string $name The dot separated path to insert $value at.
2079:      * @param mixed $value The value to insert into the request data.
2080:      * @return static
2081:      */
2082:     public function withData($name, $value)
2083:     {
2084:         $copy = clone $this;
2085:         $copy->data = Hash::insert($copy->data, $name, $value);
2086: 
2087:         return $copy;
2088:     }
2089: 
2090:     /**
2091:      * Update the request removing a data element.
2092:      *
2093:      * Returns an updated request object. This method returns
2094:      * a *new* request object and does not mutate the request in-place.
2095:      *
2096:      * @param string $name The dot separated path to remove.
2097:      * @return static
2098:      */
2099:     public function withoutData($name)
2100:     {
2101:         $copy = clone $this;
2102:         $copy->data = Hash::remove($copy->data, $name);
2103: 
2104:         return $copy;
2105:     }
2106: 
2107:     /**
2108:      * Update the request with a new routing parameter
2109:      *
2110:      * Returns an updated request object. This method returns
2111:      * a *new* request object and does not mutate the request in-place.
2112:      *
2113:      * @param string $name The dot separated path to insert $value at.
2114:      * @param mixed $value The value to insert into the the request parameters.
2115:      * @return static
2116:      */
2117:     public function withParam($name, $value)
2118:     {
2119:         $copy = clone $this;
2120:         $copy->params = Hash::insert($copy->params, $name, $value);
2121: 
2122:         return $copy;
2123:     }
2124: 
2125:     /**
2126:      * Safely access the values in $this->params.
2127:      *
2128:      * @param string $name The name or dotted path to parameter.
2129:      * @param mixed $default The default value if `$name` is not set. Default `false`.
2130:      * @return mixed
2131:      */
2132:     public function getParam($name, $default = false)
2133:     {
2134:         return Hash::get($this->params, $name, $default);
2135:     }
2136: 
2137:     /**
2138:      * Return an instance with the specified request attribute.
2139:      *
2140:      * @param string $name The attribute name.
2141:      * @param mixed $value The value of the attribute.
2142:      * @return static
2143:      */
2144:     public function withAttribute($name, $value)
2145:     {
2146:         $new = clone $this;
2147:         if (in_array($name, $this->emulatedAttributes, true)) {
2148:             $new->{$name} = $value;
2149:         } else {
2150:             $new->attributes[$name] = $value;
2151:         }
2152: 
2153:         return $new;
2154:     }
2155: 
2156:     /**
2157:      * Return an instance without the specified request attribute.
2158:      *
2159:      * @param string $name The attribute name.
2160:      * @return static
2161:      * @throws \InvalidArgumentException
2162:      */
2163:     public function withoutAttribute($name)
2164:     {
2165:         $new = clone $this;
2166:         if (in_array($name, $this->emulatedAttributes, true)) {
2167:             throw new InvalidArgumentException(
2168:                 "You cannot unset '$name'. It is a required CakePHP attribute."
2169:             );
2170:         }
2171:         unset($new->attributes[$name]);
2172: 
2173:         return $new;
2174:     }
2175: 
2176:     /**
2177:      * Read an attribute from the request, or get the default
2178:      *
2179:      * @param string $name The attribute name.
2180:      * @param mixed|null $default The default value if the attribute has not been set.
2181:      * @return mixed
2182:      */
2183:     public function getAttribute($name, $default = null)
2184:     {
2185:         if (in_array($name, $this->emulatedAttributes, true)) {
2186:             return $this->{$name};
2187:         }
2188:         if (array_key_exists($name, $this->attributes)) {
2189:             return $this->attributes[$name];
2190:         }
2191: 
2192:         return $default;
2193:     }
2194: 
2195:     /**
2196:      * Get all the attributes in the request.
2197:      *
2198:      * This will include the params, webroot, base, and here attributes that CakePHP
2199:      * provides.
2200:      *
2201:      * @return array
2202:      */
2203:     public function getAttributes()
2204:     {
2205:         $emulated = [
2206:             'params' => $this->params,
2207:             'webroot' => $this->webroot,
2208:             'base' => $this->base,
2209:             'here' => $this->here
2210:         ];
2211: 
2212:         return $this->attributes + $emulated;
2213:     }
2214: 
2215:     /**
2216:      * Get the uploaded file from a dotted path.
2217:      *
2218:      * @param string $path The dot separated path to the file you want.
2219:      * @return null|\Psr\Http\Message\UploadedFileInterface
2220:      */
2221:     public function getUploadedFile($path)
2222:     {
2223:         $file = Hash::get($this->uploadedFiles, $path);
2224:         if (!$file instanceof UploadedFile) {
2225:             return null;
2226:         }
2227: 
2228:         return $file;
2229:     }
2230: 
2231:     /**
2232:      * Get the array of uploaded files from the request.
2233:      *
2234:      * @return array
2235:      */
2236:     public function getUploadedFiles()
2237:     {
2238:         return $this->uploadedFiles;
2239:     }
2240: 
2241:     /**
2242:      * Update the request replacing the files, and creating a new instance.
2243:      *
2244:      * @param array $files An array of uploaded file objects.
2245:      * @return static
2246:      * @throws \InvalidArgumentException when $files contains an invalid object.
2247:      */
2248:     public function withUploadedFiles(array $files)
2249:     {
2250:         $this->validateUploadedFiles($files, '');
2251:         $new = clone $this;
2252:         $new->uploadedFiles = $files;
2253: 
2254:         return $new;
2255:     }
2256: 
2257:     /**
2258:      * Recursively validate uploaded file data.
2259:      *
2260:      * @param array $uploadedFiles The new files array to validate.
2261:      * @param string $path The path thus far.
2262:      * @return void
2263:      * @throws \InvalidArgumentException If any leaf elements are not valid files.
2264:      */
2265:     protected function validateUploadedFiles(array $uploadedFiles, $path)
2266:     {
2267:         foreach ($uploadedFiles as $key => $file) {
2268:             if (is_array($file)) {
2269:                 $this->validateUploadedFiles($file, $key . '.');
2270:                 continue;
2271:             }
2272: 
2273:             if (!$file instanceof UploadedFileInterface) {
2274:                 throw new InvalidArgumentException("Invalid file at '{$path}{$key}'");
2275:             }
2276:         }
2277:     }
2278: 
2279:     /**
2280:      * Gets the body of the message.
2281:      *
2282:      * @return \Psr\Http\Message\StreamInterface Returns the body as a stream.
2283:      */
2284:     public function getBody()
2285:     {
2286:         return $this->stream;
2287:     }
2288: 
2289:     /**
2290:      * Return an instance with the specified message body.
2291:      *
2292:      * @param \Psr\Http\Message\StreamInterface $body The new request body
2293:      * @return static
2294:      */
2295:     public function withBody(StreamInterface $body)
2296:     {
2297:         $new = clone $this;
2298:         $new->stream = $body;
2299: 
2300:         return $new;
2301:     }
2302: 
2303:     /**
2304:      * Retrieves the URI instance.
2305:      *
2306:      * @return \Psr\Http\Message\UriInterface Returns a UriInterface instance
2307:      *   representing the URI of the request.
2308:      */
2309:     public function getUri()
2310:     {
2311:         return $this->uri;
2312:     }
2313: 
2314:     /**
2315:      * Return an instance with the specified uri
2316:      *
2317:      * *Warning* Replacing the Uri will not update the `base`, `webroot`,
2318:      * and `url` attributes.
2319:      *
2320:      * @param \Psr\Http\Message\UriInterface $uri The new request uri
2321:      * @param bool $preserveHost Whether or not the host should be retained.
2322:      * @return static
2323:      */
2324:     public function withUri(UriInterface $uri, $preserveHost = false)
2325:     {
2326:         $new = clone $this;
2327:         $new->uri = $uri;
2328: 
2329:         if ($preserveHost && $this->hasHeader('Host')) {
2330:             return $new;
2331:         }
2332: 
2333:         $host = $uri->getHost();
2334:         if (!$host) {
2335:             return $new;
2336:         }
2337:         if ($uri->getPort()) {
2338:             $host .= ':' . $uri->getPort();
2339:         }
2340:         $new->_environment['HTTP_HOST'] = $host;
2341: 
2342:         return $new;
2343:     }
2344: 
2345:     /**
2346:      * Create a new instance with a specific request-target.
2347:      *
2348:      * You can use this method to overwrite the request target that is
2349:      * inferred from the request's Uri. This also lets you change the request
2350:      * target's form to an absolute-form, authority-form or asterisk-form
2351:      *
2352:      * @link https://tools.ietf.org/html/rfc7230#section-2.7 (for the various
2353:      *   request-target forms allowed in request messages)
2354:      * @param string $target The request target.
2355:      * @return static
2356:      */
2357:     public function withRequestTarget($target)
2358:     {
2359:         $new = clone $this;
2360:         $new->requestTarget = $target;
2361: 
2362:         return $new;
2363:     }
2364: 
2365:     /**
2366:      * Retrieves the request's target.
2367:      *
2368:      * Retrieves the message's request-target either as it was requested,
2369:      * or as set with `withRequestTarget()`. By default this will return the
2370:      * application relative path without base directory, and the query string
2371:      * defined in the SERVER environment.
2372:      *
2373:      * @return string
2374:      */
2375:     public function getRequestTarget()
2376:     {
2377:         if ($this->requestTarget !== null) {
2378:             return $this->requestTarget;
2379:         }
2380: 
2381:         $target = $this->uri->getPath();
2382:         if ($this->uri->getQuery()) {
2383:             $target .= '?' . $this->uri->getQuery();
2384:         }
2385: 
2386:         if (empty($target)) {
2387:             $target = '/';
2388:         }
2389: 
2390:         return $target;
2391:     }
2392: 
2393:     /**
2394:      * Get the path of current request.
2395:      *
2396:      * @return string
2397:      * @since 3.6.1
2398:      */
2399:     public function getPath()
2400:     {
2401:         if ($this->requestTarget === null) {
2402:             return $this->uri->getPath();
2403:         }
2404: 
2405:         list($path) = explode('?', $this->requestTarget);
2406: 
2407:         return $path;
2408:     }
2409: 
2410:     /**
2411:      * Array access read implementation
2412:      *
2413:      * @param string $name Name of the key being accessed.
2414:      * @return mixed
2415:      * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use getParam(), getData() and getQuery() instead.
2416:      */
2417:     public function offsetGet($name)
2418:     {
2419:         deprecationWarning(
2420:             'The ArrayAccess methods will be removed in 4.0.0.' .
2421:             'Use getParam(), getData() and getQuery() instead.'
2422:         );
2423: 
2424:         if (isset($this->params[$name])) {
2425:             return $this->params[$name];
2426:         }
2427:         if ($name === 'url') {
2428:             return $this->query;
2429:         }
2430:         if ($name === 'data') {
2431:             return $this->data;
2432:         }
2433: 
2434:         return null;
2435:     }
2436: 
2437:     /**
2438:      * Array access write implementation
2439:      *
2440:      * @param string $name Name of the key being written
2441:      * @param mixed $value The value being written.
2442:      * @return void
2443:      * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use withParam() instead.
2444:      */
2445:     public function offsetSet($name, $value)
2446:     {
2447:         deprecationWarning(
2448:             'The ArrayAccess methods will be removed in 4.0.0.' .
2449:             'Use withParam() instead.'
2450:         );
2451: 
2452:         $this->params[$name] = $value;
2453:     }
2454: 
2455:     /**
2456:      * Array access isset() implementation
2457:      *
2458:      * @param string $name thing to check.
2459:      * @return bool
2460:      * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use getParam() instead.
2461:      */
2462:     public function offsetExists($name)
2463:     {
2464:         deprecationWarning(
2465:             'The ArrayAccess methods will be removed in 4.0.0.' .
2466:             'Use getParam() instead.'
2467:         );
2468: 
2469:         if ($name === 'url' || $name === 'data') {
2470:             return true;
2471:         }
2472: 
2473:         return isset($this->params[$name]);
2474:     }
2475: 
2476:     /**
2477:      * Array access unset() implementation
2478:      *
2479:      * @param string $name Name to unset.
2480:      * @return void
2481:      * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use withParam() instead.
2482:      */
2483:     public function offsetUnset($name)
2484:     {
2485:         deprecationWarning(
2486:             'The ArrayAccess methods will be removed in 4.0.0.' .
2487:             'Use withParam() instead.'
2488:         );
2489: 
2490:         unset($this->params[$name]);
2491:     }
2492: }
2493: 
2494: // @deprecated 3.4.0 Add backwards compat alias.
2495: class_alias('Cake\Http\ServerRequest', 'Cake\Network\Request');
2496: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs