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.8 Red Velvet API

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