CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.2 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.2
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 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

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • CakeRequest
  • CakeResponse
  • CakeSocket
   1: <?php
   2: /**
   3:  * CakeResponse
   4:  *
   5:  * PHP 5
   6:  *
   7:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
   8:  * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
   9:  *
  10:  * Licensed under The MIT License
  11:  * Redistributions of files must retain the above copyright notice.
  12:  *
  13:  * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14:  * @link          http://cakephp.org CakePHP(tm) Project
  15:  * @package       Cake.Network
  16:  * @since         CakePHP(tm) v 2.0
  17:  * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
  18:  */
  19: 
  20: /**
  21:  * CakeResponse is responsible for managing the response text, status and headers of a HTTP response.
  22:  *
  23:  * By default controllers will use this class to render their response. If you are going to use
  24:  * a custom response class it should subclass this object in order to ensure compatibility.
  25:  *
  26:  * @package       Cake.Network
  27:  */
  28: class CakeResponse {
  29: 
  30: /**
  31:  * Holds HTTP response statuses
  32:  *
  33:  * @var array
  34:  */
  35:     protected $_statusCodes = array(
  36:         100 => 'Continue',
  37:         101 => 'Switching Protocols',
  38:         200 => 'OK',
  39:         201 => 'Created',
  40:         202 => 'Accepted',
  41:         203 => 'Non-Authoritative Information',
  42:         204 => 'No Content',
  43:         205 => 'Reset Content',
  44:         206 => 'Partial Content',
  45:         300 => 'Multiple Choices',
  46:         301 => 'Moved Permanently',
  47:         302 => 'Found',
  48:         303 => 'See Other',
  49:         304 => 'Not Modified',
  50:         305 => 'Use Proxy',
  51:         307 => 'Temporary Redirect',
  52:         400 => 'Bad Request',
  53:         401 => 'Unauthorized',
  54:         402 => 'Payment Required',
  55:         403 => 'Forbidden',
  56:         404 => 'Not Found',
  57:         405 => 'Method Not Allowed',
  58:         406 => 'Not Acceptable',
  59:         407 => 'Proxy Authentication Required',
  60:         408 => 'Request Time-out',
  61:         409 => 'Conflict',
  62:         410 => 'Gone',
  63:         411 => 'Length Required',
  64:         412 => 'Precondition Failed',
  65:         413 => 'Request Entity Too Large',
  66:         414 => 'Request-URI Too Large',
  67:         415 => 'Unsupported Media Type',
  68:         416 => 'Requested range not satisfiable',
  69:         417 => 'Expectation Failed',
  70:         500 => 'Internal Server Error',
  71:         501 => 'Not Implemented',
  72:         502 => 'Bad Gateway',
  73:         503 => 'Service Unavailable',
  74:         504 => 'Gateway Time-out'
  75:     );
  76: 
  77: /**
  78:  * Holds known mime type mappings
  79:  *
  80:  * @var array
  81:  */
  82:     protected $_mimeTypes = array(
  83:         'html' => array('text/html', '*/*'),
  84:         'json' => 'application/json',
  85:         'xml' => array('application/xml', 'text/xml'),
  86:         'rss' => 'application/rss+xml',
  87:         'ai' => 'application/postscript',
  88:         'bcpio' => 'application/x-bcpio',
  89:         'bin' => 'application/octet-stream',
  90:         'ccad' => 'application/clariscad',
  91:         'cdf' => 'application/x-netcdf',
  92:         'class' => 'application/octet-stream',
  93:         'cpio' => 'application/x-cpio',
  94:         'cpt' => 'application/mac-compactpro',
  95:         'csh' => 'application/x-csh',
  96:         'csv' => array('text/csv', 'application/vnd.ms-excel', 'text/plain'),
  97:         'dcr' => 'application/x-director',
  98:         'dir' => 'application/x-director',
  99:         'dms' => 'application/octet-stream',
 100:         'doc' => 'application/msword',
 101:         'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
 102:         'drw' => 'application/drafting',
 103:         'dvi' => 'application/x-dvi',
 104:         'dwg' => 'application/acad',
 105:         'dxf' => 'application/dxf',
 106:         'dxr' => 'application/x-director',
 107:         'eot' => 'application/vnd.ms-fontobject',
 108:         'eps' => 'application/postscript',
 109:         'exe' => 'application/octet-stream',
 110:         'ez' => 'application/andrew-inset',
 111:         'flv' => 'video/x-flv',
 112:         'gtar' => 'application/x-gtar',
 113:         'gz' => 'application/x-gzip',
 114:         'bz2' => 'application/x-bzip',
 115:         '7z' => 'application/x-7z-compressed',
 116:         'hdf' => 'application/x-hdf',
 117:         'hqx' => 'application/mac-binhex40',
 118:         'ico' => 'image/vnd.microsoft.icon',
 119:         'ips' => 'application/x-ipscript',
 120:         'ipx' => 'application/x-ipix',
 121:         'js' => 'text/javascript',
 122:         'latex' => 'application/x-latex',
 123:         'lha' => 'application/octet-stream',
 124:         'lsp' => 'application/x-lisp',
 125:         'lzh' => 'application/octet-stream',
 126:         'man' => 'application/x-troff-man',
 127:         'me' => 'application/x-troff-me',
 128:         'mif' => 'application/vnd.mif',
 129:         'ms' => 'application/x-troff-ms',
 130:         'nc' => 'application/x-netcdf',
 131:         'oda' => 'application/oda',
 132:         'otf' => 'font/otf',
 133:         'pdf' => 'application/pdf',
 134:         'pgn' => 'application/x-chess-pgn',
 135:         'pot' => 'application/vnd.ms-powerpoint',
 136:         'pps' => 'application/vnd.ms-powerpoint',
 137:         'ppt' => 'application/vnd.ms-powerpoint',
 138:         'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
 139:         'ppz' => 'application/vnd.ms-powerpoint',
 140:         'pre' => 'application/x-freelance',
 141:         'prt' => 'application/pro_eng',
 142:         'ps' => 'application/postscript',
 143:         'roff' => 'application/x-troff',
 144:         'scm' => 'application/x-lotusscreencam',
 145:         'set' => 'application/set',
 146:         'sh' => 'application/x-sh',
 147:         'shar' => 'application/x-shar',
 148:         'sit' => 'application/x-stuffit',
 149:         'skd' => 'application/x-koan',
 150:         'skm' => 'application/x-koan',
 151:         'skp' => 'application/x-koan',
 152:         'skt' => 'application/x-koan',
 153:         'smi' => 'application/smil',
 154:         'smil' => 'application/smil',
 155:         'sol' => 'application/solids',
 156:         'spl' => 'application/x-futuresplash',
 157:         'src' => 'application/x-wais-source',
 158:         'step' => 'application/STEP',
 159:         'stl' => 'application/SLA',
 160:         'stp' => 'application/STEP',
 161:         'sv4cpio' => 'application/x-sv4cpio',
 162:         'sv4crc' => 'application/x-sv4crc',
 163:         'svg' => 'image/svg+xml',
 164:         'svgz' => 'image/svg+xml',
 165:         'swf' => 'application/x-shockwave-flash',
 166:         't' => 'application/x-troff',
 167:         'tar' => 'application/x-tar',
 168:         'tcl' => 'application/x-tcl',
 169:         'tex' => 'application/x-tex',
 170:         'texi' => 'application/x-texinfo',
 171:         'texinfo' => 'application/x-texinfo',
 172:         'tr' => 'application/x-troff',
 173:         'tsp' => 'application/dsptype',
 174:         'ttf' => 'font/ttf',
 175:         'unv' => 'application/i-deas',
 176:         'ustar' => 'application/x-ustar',
 177:         'vcd' => 'application/x-cdlink',
 178:         'vda' => 'application/vda',
 179:         'xlc' => 'application/vnd.ms-excel',
 180:         'xll' => 'application/vnd.ms-excel',
 181:         'xlm' => 'application/vnd.ms-excel',
 182:         'xls' => 'application/vnd.ms-excel',
 183:         'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
 184:         'xlw' => 'application/vnd.ms-excel',
 185:         'zip' => 'application/zip',
 186:         'aif' => 'audio/x-aiff',
 187:         'aifc' => 'audio/x-aiff',
 188:         'aiff' => 'audio/x-aiff',
 189:         'au' => 'audio/basic',
 190:         'kar' => 'audio/midi',
 191:         'mid' => 'audio/midi',
 192:         'midi' => 'audio/midi',
 193:         'mp2' => 'audio/mpeg',
 194:         'mp3' => 'audio/mpeg',
 195:         'mpga' => 'audio/mpeg',
 196:         'ogg' => 'audio/ogg',
 197:         'oga' => 'audio/ogg',
 198:         'spx' => 'audio/ogg',
 199:         'ra' => 'audio/x-realaudio',
 200:         'ram' => 'audio/x-pn-realaudio',
 201:         'rm' => 'audio/x-pn-realaudio',
 202:         'rpm' => 'audio/x-pn-realaudio-plugin',
 203:         'snd' => 'audio/basic',
 204:         'tsi' => 'audio/TSP-audio',
 205:         'wav' => 'audio/x-wav',
 206:         'aac' => 'audio/aac',
 207:         'asc' => 'text/plain',
 208:         'c' => 'text/plain',
 209:         'cc' => 'text/plain',
 210:         'css' => 'text/css',
 211:         'etx' => 'text/x-setext',
 212:         'f' => 'text/plain',
 213:         'f90' => 'text/plain',
 214:         'h' => 'text/plain',
 215:         'hh' => 'text/plain',
 216:         'htm' => array('text/html', '*/*'),
 217:         'ics' => 'text/calendar',
 218:         'm' => 'text/plain',
 219:         'rtf' => 'text/rtf',
 220:         'rtx' => 'text/richtext',
 221:         'sgm' => 'text/sgml',
 222:         'sgml' => 'text/sgml',
 223:         'tsv' => 'text/tab-separated-values',
 224:         'tpl' => 'text/template',
 225:         'txt' => 'text/plain',
 226:         'text' => 'text/plain',
 227:         'avi' => 'video/x-msvideo',
 228:         'fli' => 'video/x-fli',
 229:         'mov' => 'video/quicktime',
 230:         'movie' => 'video/x-sgi-movie',
 231:         'mpe' => 'video/mpeg',
 232:         'mpeg' => 'video/mpeg',
 233:         'mpg' => 'video/mpeg',
 234:         'qt' => 'video/quicktime',
 235:         'viv' => 'video/vnd.vivo',
 236:         'vivo' => 'video/vnd.vivo',
 237:         'ogv' => 'video/ogg',
 238:         'webm' => 'video/webm',
 239:         'mp4' => 'video/mp4',
 240:         'gif' => 'image/gif',
 241:         'ief' => 'image/ief',
 242:         'jpe' => 'image/jpeg',
 243:         'jpeg' => 'image/jpeg',
 244:         'jpg' => 'image/jpeg',
 245:         'pbm' => 'image/x-portable-bitmap',
 246:         'pgm' => 'image/x-portable-graymap',
 247:         'png' => 'image/png',
 248:         'pnm' => 'image/x-portable-anymap',
 249:         'ppm' => 'image/x-portable-pixmap',
 250:         'ras' => 'image/cmu-raster',
 251:         'rgb' => 'image/x-rgb',
 252:         'tif' => 'image/tiff',
 253:         'tiff' => 'image/tiff',
 254:         'xbm' => 'image/x-xbitmap',
 255:         'xpm' => 'image/x-xpixmap',
 256:         'xwd' => 'image/x-xwindowdump',
 257:         'ice' => 'x-conference/x-cooltalk',
 258:         'iges' => 'model/iges',
 259:         'igs' => 'model/iges',
 260:         'mesh' => 'model/mesh',
 261:         'msh' => 'model/mesh',
 262:         'silo' => 'model/mesh',
 263:         'vrml' => 'model/vrml',
 264:         'wrl' => 'model/vrml',
 265:         'mime' => 'www/mime',
 266:         'pdb' => 'chemical/x-pdb',
 267:         'xyz' => 'chemical/x-pdb',
 268:         'javascript' => 'text/javascript',
 269:         'form' => 'application/x-www-form-urlencoded',
 270:         'file' => 'multipart/form-data',
 271:         'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
 272:         'xhtml-mobile'  => 'application/vnd.wap.xhtml+xml',
 273:         'atom' => 'application/atom+xml',
 274:         'amf' => 'application/x-amf',
 275:         'wap' => array('text/vnd.wap.wml', 'text/vnd.wap.wmlscript', 'image/vnd.wap.wbmp'),
 276:         'wml' => 'text/vnd.wap.wml',
 277:         'wmlscript' => 'text/vnd.wap.wmlscript',
 278:         'wbmp' => 'image/vnd.wap.wbmp',
 279:     );
 280: 
 281: /**
 282:  * Protocol header to send to the client
 283:  *
 284:  * @var string
 285:  */
 286:     protected $_protocol = 'HTTP/1.1';
 287: 
 288: /**
 289:  * Status code to send to the client
 290:  *
 291:  * @var integer
 292:  */
 293:     protected $_status = 200;
 294: 
 295: /**
 296:  * Content type to send. This can be an 'extension' that will be transformed using the $_mimetypes array
 297:  * or a complete mime-type
 298:  *
 299:  * @var integer
 300:  */
 301:     protected $_contentType = 'text/html';
 302: 
 303: /**
 304:  * Buffer list of headers
 305:  *
 306:  * @var array
 307:  */
 308:     protected $_headers = array();
 309: 
 310: /**
 311:  * Buffer string for response message
 312:  *
 313:  * @var string
 314:  */
 315:     protected $_body = null;
 316: 
 317: /**
 318:  * The charset the response body is encoded with
 319:  *
 320:  * @var string
 321:  */
 322:     protected $_charset = 'UTF-8';
 323: 
 324: /**
 325:  * Holds all the cache directives that will be converted
 326:  * into headers when sending the request
 327:  *
 328:  * @var string
 329:  */
 330:     protected $_cacheDirectives = array();
 331: 
 332: /**
 333:  * Holds cookies to be sent to the client
 334:  *
 335:  * @var array
 336:  */
 337:     protected $_cookies = array();
 338: 
 339: /**
 340:  * Class constructor
 341:  *
 342:  * @param array $options list of parameters to setup the response. Possible values are:
 343:  *  - body: the response text that should be sent to the client
 344:  *  - status: the HTTP status code to respond with
 345:  *  - type: a complete mime-type string or an extension mapped in this class
 346:  *  - charset: the charset for the response body
 347:  */
 348:     public function __construct(array $options = array()) {
 349:         if (isset($options['body'])) {
 350:             $this->body($options['body']);
 351:         }
 352:         if (isset($options['status'])) {
 353:             $this->statusCode($options['status']);
 354:         }
 355:         if (isset($options['type'])) {
 356:             $this->type($options['type']);
 357:         }
 358:         if (isset($options['charset'])) {
 359:             $this->charset($options['charset']);
 360:         }
 361:     }
 362: 
 363: /**
 364:  * Sends the complete response to the client including headers and message body.
 365:  * Will echo out the content in the response body.
 366:  *
 367:  * @return void
 368:  */
 369:     public function send() {
 370:         if (isset($this->_headers['Location']) && $this->_status === 200) {
 371:             $this->statusCode(302);
 372:         }
 373: 
 374:         $codeMessage = $this->_statusCodes[$this->_status];
 375:         $this->_setCookies();
 376:         $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}");
 377:         $this->_setContent();
 378:         $this->_setContentLength();
 379:         $this->_setContentType();
 380:         foreach ($this->_headers as $header => $value) {
 381:             $this->_sendHeader($header, $value);
 382:         }
 383:         $this->_sendContent($this->_body);
 384:     }
 385: 
 386: /**
 387:  * Sets the cookies that have been added via static method CakeResponse::addCookie()
 388:  * before any other output is sent to the client.
 389:  * Will set the cookies in the order they have been set.
 390:  *
 391:  * @return void
 392:  */
 393:     protected function _setCookies() {
 394:         foreach ($this->_cookies as $name => $c) {
 395:             setcookie(
 396:                 $name, $c['value'], $c['expire'], $c['path'],
 397:                 $c['domain'], $c['secure'], $c['httpOnly']
 398:             );
 399:         }
 400:     }
 401: 
 402: /**
 403:  * Formats the Content-Type header based on the configured contentType and charset
 404:  * the charset will only be set in the header if the response is of type text/*
 405:  *
 406:  * @return void
 407:  */
 408:     protected function _setContentType() {
 409:         if (in_array($this->_status, array(304, 204))) {
 410:             return;
 411:         }
 412:         if (strpos($this->_contentType, 'text/') === 0) {
 413:             $this->header('Content-Type', "{$this->_contentType}; charset={$this->_charset}");
 414:         } elseif ($this->_contentType === 'application/json') {
 415:             $this->header('Content-Type', "{$this->_contentType}; charset=UTF-8");
 416:         } else {
 417:             $this->header('Content-Type', "{$this->_contentType}");
 418:         }
 419:     }
 420: 
 421: /**
 422:  * Sets the response body to an empty text if the status code is 204 or 304
 423:  *
 424:  * @return void
 425:  */
 426:     protected function _setContent() {
 427:         if (in_array($this->_status, array(304, 204))) {
 428:             $this->body('');
 429:         }
 430:     }
 431: 
 432: /**
 433:  * Calculates the correct Content-Length and sets it as a header in the response
 434:  * Will not set the value if already set or if the output is compressed.
 435:  *
 436:  * @return void
 437:  */
 438:     protected function _setContentLength() {
 439:         $shouldSetLength = !isset($this->_headers['Content-Length']) && !in_array($this->_status, range(301, 307));
 440:         if (isset($this->_headers['Content-Length']) && $this->_headers['Content-Length'] === false) {
 441:             unset($this->_headers['Content-Length']);
 442:             return;
 443:         }
 444:         if ($shouldSetLength && !$this->outputCompressed()) {
 445:             $offset = ob_get_level() ? ob_get_length() : 0;
 446:             if (ini_get('mbstring.func_overload') & 2 && function_exists('mb_strlen')) {
 447:                 $this->length($offset + mb_strlen($this->_body, '8bit'));
 448:             } else {
 449:                 $this->length($this->_headers['Content-Length'] = $offset + strlen($this->_body));
 450:             }
 451:         }
 452:     }
 453: 
 454: /**
 455:  * Sends a header to the client.
 456:  *
 457:  * @param string $name the header name
 458:  * @param string $value the header value
 459:  * @return void
 460:  */
 461:     protected function _sendHeader($name, $value = null) {
 462:         if (!headers_sent()) {
 463:             if (is_null($value)) {
 464:                 header($name);
 465:             } else {
 466:                 header("{$name}: {$value}");
 467:             }
 468:         }
 469:     }
 470: 
 471: /**
 472:  * Sends a content string to the client.
 473:  *
 474:  * @param string $content string to send as response body
 475:  * @return void
 476:  */
 477:     protected function _sendContent($content) {
 478:         echo $content;
 479:     }
 480: 
 481: /**
 482:  * Buffers a header string to be sent
 483:  * Returns the complete list of buffered headers
 484:  *
 485:  * ### Single header
 486:  * e.g `header('Location', 'http://example.com');`
 487:  *
 488:  * ### Multiple headers
 489:  * e.g `header(array('Location' => 'http://example.com', 'X-Extra' => 'My header'));`
 490:  *
 491:  * ### String header
 492:  * e.g `header('WWW-Authenticate: Negotiate');`
 493:  *
 494:  * ### Array of string headers
 495:  * e.g `header(array('WWW-Authenticate: Negotiate', 'Content-type: application/pdf'));`
 496:  *
 497:  * Multiple calls for setting the same header name will have the same effect as setting the header once
 498:  * with the last value sent for it
 499:  *  e.g `header('WWW-Authenticate: Negotiate'); header('WWW-Authenticate: Not-Negotiate');`
 500:  * will have the same effect as only doing `header('WWW-Authenticate: Not-Negotiate');`
 501:  *
 502:  * @param string|array $header. An array of header strings or a single header string
 503:  *  - an associative array of "header name" => "header value" is also accepted
 504:  *  - an array of string headers is also accepted
 505:  * @param string $value. The header value.
 506:  * @return array list of headers to be sent
 507:  */
 508:     public function header($header = null, $value = null) {
 509:         if (is_null($header)) {
 510:             return $this->_headers;
 511:         }
 512:         if (is_array($header)) {
 513:             foreach ($header as $h => $v) {
 514:                 if (is_numeric($h)) {
 515:                     $this->header($v);
 516:                     continue;
 517:                 }
 518:                 $this->_headers[$h] = trim($v);
 519:             }
 520:             return $this->_headers;
 521:         }
 522: 
 523:         if (!is_null($value)) {
 524:             $this->_headers[$header] = $value;
 525:             return $this->_headers;
 526:         }
 527: 
 528:         list($header, $value) = explode(':', $header, 2);
 529:         $this->_headers[$header] = trim($value);
 530:         return $this->_headers;
 531:     }
 532: 
 533: /**
 534:  * Buffers the response message to be sent
 535:  * if $content is null the current buffer is returned
 536:  *
 537:  * @param string $content the string message to be sent
 538:  * @return string current message buffer if $content param is passed as null
 539:  */
 540:     public function body($content = null) {
 541:         if (is_null($content)) {
 542:             return $this->_body;
 543:         }
 544:         return $this->_body = $content;
 545:     }
 546: 
 547: /**
 548:  * Sets the HTTP status code to be sent
 549:  * if $code is null the current code is returned
 550:  *
 551:  * @param integer $code
 552:  * @return integer current status code
 553:  * @throws CakeException When an unknown status code is reached.
 554:  */
 555:     public function statusCode($code = null) {
 556:         if (is_null($code)) {
 557:             return $this->_status;
 558:         }
 559:         if (!isset($this->_statusCodes[$code])) {
 560:             throw new CakeException(__d('cake_dev', 'Unknown status code'));
 561:         }
 562:         return $this->_status = $code;
 563:     }
 564: 
 565: /**
 566:  * Queries & sets valid HTTP response codes & messages.
 567:  *
 568:  * @param integer|array $code If $code is an integer, then the corresponding code/message is
 569:  *        returned if it exists, null if it does not exist. If $code is an array,
 570:  *        then the 'code' and 'message' keys of each nested array are added to the default
 571:  *        HTTP codes. Example:
 572:  *
 573:  *        httpCodes(404); // returns array(404 => 'Not Found')
 574:  *
 575:  *        httpCodes(array(
 576:  *            701 => 'Unicorn Moved',
 577:  *            800 => 'Unexpected Minotaur'
 578:  *        )); // sets these new values, and returns true
 579:  *
 580:  * @return mixed associative array of the HTTP codes as keys, and the message
 581:  *    strings as values, or null of the given $code does not exist.
 582:  */
 583:     public function httpCodes($code = null) {
 584:         if (empty($code)) {
 585:             return $this->_statusCodes;
 586:         }
 587: 
 588:         if (is_array($code)) {
 589:             $this->_statusCodes = $code + $this->_statusCodes;
 590:             return true;
 591:         }
 592: 
 593:         if (!isset($this->_statusCodes[$code])) {
 594:             return null;
 595:         }
 596:         return array($code => $this->_statusCodes[$code]);
 597:     }
 598: 
 599: /**
 600:  * Sets the response content type. It can be either a file extension
 601:  * which will be mapped internally to a mime-type or a string representing a mime-type
 602:  * if $contentType is null the current content type is returned
 603:  * if $contentType is an associative array, content type definitions will be stored/replaced
 604:  *
 605:  * ### Setting the content type
 606:  *
 607:  * e.g `type('jpg');`
 608:  *
 609:  * ### Returning the current content type
 610:  *
 611:  * e.g `type();`
 612:  *
 613:  * ### Storing content type definitions
 614:  *
 615:  * e.g `type(array('keynote' => 'application/keynote', 'bat' => 'application/bat'));`
 616:  *
 617:  * ### Replacing a content type definition
 618:  *
 619:  * e.g `type(array('jpg' => 'text/plain'));`
 620:  *
 621:  * @param string $contentType
 622:  * @return mixed current content type or false if supplied an invalid content type
 623:  */
 624:     public function type($contentType = null) {
 625:         if (is_null($contentType)) {
 626:             return $this->_contentType;
 627:         }
 628:         if (is_array($contentType)) {
 629:             foreach ($contentType as $type => $definition) {
 630:                 $this->_mimeTypes[$type] = $definition;
 631:             }
 632:             return $this->_contentType;
 633:         }
 634:         if (isset($this->_mimeTypes[$contentType])) {
 635:             $contentType = $this->_mimeTypes[$contentType];
 636:             $contentType = is_array($contentType) ? current($contentType) : $contentType;
 637:         }
 638:         if (strpos($contentType, '/') === false) {
 639:             return false;
 640:         }
 641:         return $this->_contentType = $contentType;
 642:     }
 643: 
 644: /**
 645:  * Returns the mime type definition for an alias
 646:  *
 647:  * e.g `getMimeType('pdf'); // returns 'application/pdf'`
 648:  *
 649:  * @param string $alias the content type alias to map
 650:  * @return mixed string mapped mime type or false if $alias is not mapped
 651:  */
 652:     public function getMimeType($alias) {
 653:         if (isset($this->_mimeTypes[$alias])) {
 654:             return $this->_mimeTypes[$alias];
 655:         }
 656:         return false;
 657:     }
 658: 
 659: /**
 660:  * Maps a content-type back to an alias
 661:  *
 662:  * e.g `mapType('application/pdf'); // returns 'pdf'`
 663:  *
 664:  * @param string|array $ctype Either a string content type to map, or an array of types.
 665:  * @return mixed Aliases for the types provided.
 666:  */
 667:     public function mapType($ctype) {
 668:         if (is_array($ctype)) {
 669:             return array_map(array($this, 'mapType'), $ctype);
 670:         }
 671: 
 672:         foreach ($this->_mimeTypes as $alias => $types) {
 673:             if (is_array($types) && in_array($ctype, $types)) {
 674:                 return $alias;
 675:             } elseif (is_string($types) && $types == $ctype) {
 676:                 return $alias;
 677:             }
 678:         }
 679:         return null;
 680:     }
 681: 
 682: /**
 683:  * Sets the response charset
 684:  * if $charset is null the current charset is returned
 685:  *
 686:  * @param string $charset
 687:  * @return string current charset
 688:  */
 689:     public function charset($charset = null) {
 690:         if (is_null($charset)) {
 691:             return $this->_charset;
 692:         }
 693:         return $this->_charset = $charset;
 694:     }
 695: 
 696: /**
 697:  * Sets the correct headers to instruct the client to not cache the response
 698:  *
 699:  * @return void
 700:  */
 701:     public function disableCache() {
 702:         $this->header(array(
 703:             'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
 704:             'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT",
 705:             'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
 706:         ));
 707:     }
 708: 
 709: /**
 710:  * Sets the correct headers to instruct the client to cache the response.
 711:  *
 712:  * @param string $since a valid time since the response text has not been modified
 713:  * @param string $time a valid time for cache expiry
 714:  * @return void
 715:  */
 716:     public function cache($since, $time = '+1 day') {
 717:         if (!is_integer($time)) {
 718:             $time = strtotime($time);
 719:         }
 720:         $this->header(array(
 721:             'Date' => gmdate("D, j M Y G:i:s ", time()) . 'GMT'
 722:         ));
 723:         $this->modified($since);
 724:         $this->expires($time);
 725:         $this->sharable(true);
 726:         $this->maxAge($time - time());
 727:     }
 728: 
 729: /**
 730:  * Sets whether a response is eligible to be cached by intermediate proxies
 731:  * This method controls the `public` or `private` directive in the Cache-Control
 732:  * header
 733:  *
 734:  * @param boolean $public  if set to true, the Cache-Control header will be set as public
 735:  * if set to false, the response will be set to private
 736:  * if no value is provided, it will return whether the response is sharable or not
 737:  * @param integer $time time in seconds after which the response should no longer be considered fresh
 738:  * @return boolean
 739:  */
 740:     public function sharable($public = null, $time = null) {
 741:         if ($public === null) {
 742:             $public = array_key_exists('public', $this->_cacheDirectives);
 743:             $private = array_key_exists('private', $this->_cacheDirectives);
 744:             $noCache = array_key_exists('no-cache', $this->_cacheDirectives);
 745:             if (!$public && !$private && !$noCache) {
 746:                 return null;
 747:             }
 748:             $sharable = $public || ! ($private || $noCache);
 749:             return $sharable;
 750:         }
 751:         if ($public) {
 752:             $this->_cacheDirectives['public'] = true;
 753:             unset($this->_cacheDirectives['private']);
 754:             $this->sharedMaxAge($time);
 755:         } else {
 756:             $this->_cacheDirectives['private'] = true;
 757:             unset($this->_cacheDirectives['public']);
 758:             $this->maxAge($time);
 759:         }
 760:         if ($time == null) {
 761:             $this->_setCacheControl();
 762:         }
 763:         return (bool)$public;
 764:     }
 765: 
 766: /**
 767:  * Sets the Cache-Control s-maxage directive.
 768:  * The max-age is the number of seconds after which the response should no longer be considered
 769:  * a good candidate to be fetched from a shared cache (like in a proxy server).
 770:  * If called with no parameters, this function will return the current max-age value if any
 771:  *
 772:  * @param integer $seconds if null, the method will return the current s-maxage value
 773:  * @return int
 774:  */
 775:     public function sharedMaxAge($seconds = null) {
 776:         if ($seconds !== null) {
 777:             $this->_cacheDirectives['s-maxage'] = $seconds;
 778:             $this->_setCacheControl();
 779:         }
 780:         if (isset($this->_cacheDirectives['s-maxage'])) {
 781:             return $this->_cacheDirectives['s-maxage'];
 782:         }
 783:         return null;
 784:     }
 785: 
 786: /**
 787:  * Sets the Cache-Control max-age directive.
 788:  * The max-age is the number of seconds after which the response should no longer be considered
 789:  * a good candidate to be fetched from the local (client) cache.
 790:  * If called with no parameters, this function will return the current max-age value if any
 791:  *
 792:  * @param integer $seconds if null, the method will return the current max-age value
 793:  * @return int
 794:  */
 795:     public function maxAge($seconds = null) {
 796:         if ($seconds !== null) {
 797:             $this->_cacheDirectives['max-age'] = $seconds;
 798:             $this->_setCacheControl();
 799:         }
 800:         if (isset($this->_cacheDirectives['max-age'])) {
 801:             return $this->_cacheDirectives['max-age'];
 802:         }
 803:         return null;
 804:     }
 805: 
 806: /**
 807:  * Sets the Cache-Control must-revalidate directive.
 808:  * must-revalidate indicates that the response should not be served
 809:  * stale by a cache under any cirumstance without first revalidating
 810:  * with the origin.
 811:  * If called with no parameters, this function will return wheter must-revalidate is present.
 812:  *
 813:  * @param integer $seconds if null, the method will return the current
 814:  * must-revalidate value
 815:  * @return boolean
 816:  */
 817:     public function mustRevalidate($enable = null) {
 818:         if ($enable !== null) {
 819:             if ($enable) {
 820:                 $this->_cacheDirectives['must-revalidate'] = true;
 821:             } else {
 822:                 unset($this->_cacheDirectives['must-revalidate']);
 823:             }
 824:             $this->_setCacheControl();
 825:         }
 826:         return array_key_exists('must-revalidate', $this->_cacheDirectives);
 827:     }
 828: 
 829: /**
 830:  * Helper method to generate a valid Cache-Control header from the options set
 831:  * in other methods
 832:  *
 833:  * @return void
 834:  */
 835:     protected function _setCacheControl() {
 836:         $control = '';
 837:         foreach ($this->_cacheDirectives as $key => $val) {
 838:             $control .= $val === true ? $key : sprintf('%s=%s', $key, $val);
 839:             $control .= ', ';
 840:         }
 841:         $control = rtrim($control, ', ');
 842:         $this->header('Cache-Control', $control);
 843:     }
 844: 
 845: /**
 846:  * Sets the Expires header for the response by taking an expiration time
 847:  * If called with no parameters it will return the current Expires value
 848:  *
 849:  * ## Examples:
 850:  *
 851:  * `$response->expires('now')` Will Expire the response cache now
 852:  * `$response->expires(new DateTime('+1 day'))` Will set the expiration in next 24 hours
 853:  * `$response->expires()` Will return the current expiration header value
 854:  *
 855:  * @param string|DateTime $time
 856:  * @return string
 857:  */
 858:     public function expires($time = null) {
 859:         if ($time !== null) {
 860:             $date = $this->_getUTCDate($time);
 861:             $this->_headers['Expires'] = $date->format('D, j M Y H:i:s') . ' GMT';
 862:         }
 863:         if (isset($this->_headers['Expires'])) {
 864:             return $this->_headers['Expires'];
 865:         }
 866:         return null;
 867:     }
 868: 
 869: /**
 870:  * Sets the Last-Modified header for the response by taking an modification time
 871:  * If called with no parameters it will return the current Last-Modified value
 872:  *
 873:  * ## Examples:
 874:  *
 875:  * `$response->modified('now')` Will set the Last-Modified to the current time
 876:  * `$response->modified(new DateTime('+1 day'))` Will set the modification date in the past 24 hours
 877:  * `$response->modified()` Will return the current Last-Modified header value
 878:  *
 879:  * @param string|DateTime $time
 880:  * @return string
 881:  */
 882:     public function modified($time = null) {
 883:         if ($time !== null) {
 884:             $date = $this->_getUTCDate($time);
 885:             $this->_headers['Last-Modified'] = $date->format('D, j M Y H:i:s') . ' GMT';
 886:         }
 887:         if (isset($this->_headers['Last-Modified'])) {
 888:             return $this->_headers['Last-Modified'];
 889:         }
 890:         return null;
 891:     }
 892: 
 893: /**
 894:  * Sets the response as Not Modified by removing any body contents
 895:  * setting the status code to "304 Not Modified" and removing all
 896:  * conflicting headers
 897:  *
 898:  * @return void
 899:  **/
 900:     public function notModified() {
 901:         $this->statusCode(304);
 902:         $this->body('');
 903:         $remove = array(
 904:             'Allow',
 905:             'Content-Encoding',
 906:             'Content-Language',
 907:             'Content-Length',
 908:             'Content-MD5',
 909:             'Content-Type',
 910:             'Last-Modified'
 911:         );
 912:         foreach ($remove as $header) {
 913:             unset($this->_headers[$header]);
 914:         }
 915:     }
 916: 
 917: /**
 918:  * Sets the Vary header for the response, if an array is passed,
 919:  * values will be imploded into a comma separated string. If no
 920:  * parameters are passed, then an array with the current Vary header
 921:  * value is returned
 922:  *
 923:  * @param string|array $cacheVariances a single Vary string or a array
 924:  * containig the list for variances.
 925:  * @return array
 926:  **/
 927:     public function vary($cacheVariances = null) {
 928:         if ($cacheVariances !== null) {
 929:             $cacheVariances = (array)$cacheVariances;
 930:             $this->_headers['Vary'] = implode(', ', $cacheVariances);
 931:         }
 932:         if (isset($this->_headers['Vary'])) {
 933:             return explode(', ', $this->_headers['Vary']);
 934:         }
 935:         return null;
 936:     }
 937: 
 938: /**
 939:  * Sets the response Etag, Etags are a strong indicative that a response
 940:  * can be cached by a HTTP client. A bad way of generaing Etags is
 941:  * creating a hash of the response output, instead generate a unique
 942:  * hash of the unique components that identifies a request, such as a
 943:  * modification time, a resource Id, and anything else you consider it
 944:  * makes it unique.
 945:  *
 946:  * Second parameter is used to instuct clients that the content has
 947:  * changed, but sematicallly, it can be used as the same thing. Think
 948:  * for instance of a page with a hit counter, two different page views
 949:  * are equivalent, but they differ by a few bytes. This leaves off to
 950:  * the Client the decision of using or not the cached page.
 951:  *
 952:  * If no parameters are passed, current Etag header is returned.
 953:  *
 954:  * @param string $hash the unique has that identifies this resposnse
 955:  * @param boolean $weak whether the response is semantically the same as
 956:  * other with th same hash or not
 957:  * @return string
 958:  **/
 959:     public function etag($tag = null, $weak = false) {
 960:         if ($tag !== null) {
 961:             $this->_headers['Etag'] = sprintf('%s"%s"', ($weak) ? 'W/' : null, $tag);
 962:         }
 963:         if (isset($this->_headers['Etag'])) {
 964:             return $this->_headers['Etag'];
 965:         }
 966:         return null;
 967:     }
 968: 
 969: /**
 970:  * Returns a DateTime object initialized at the $time param and using UTC
 971:  * as timezone
 972:  *
 973:  * @param string|integer|DateTime $time
 974:  * @return DateTime
 975:  */
 976:     protected function _getUTCDate($time = null) {
 977:         if ($time instanceof DateTime) {
 978:             $result = clone $time;
 979:         } elseif (is_integer($time)) {
 980:             $result = new DateTime(date('Y-m-d H:i:s', $time));
 981:         } else {
 982:             $result = new DateTime($time);
 983:         }
 984:         $result->setTimeZone(new DateTimeZone('UTC'));
 985:         return $result;
 986:     }
 987: 
 988: /**
 989:  * Sets the correct output buffering handler to send a compressed response. Responses will
 990:  * be compressed with zlib, if the extension is available.
 991:  *
 992:  * @return boolean false if client does not accept compressed responses or no handler is available, true otherwise
 993:  */
 994:     public function compress() {
 995:         $compressionEnabled = ini_get("zlib.output_compression") !== '1' &&
 996:             extension_loaded("zlib") &&
 997:             (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
 998:         return $compressionEnabled && ob_start('ob_gzhandler');
 999:     }
1000: 
1001: /**
1002:  * Returns whether the resulting output will be compressed by PHP
1003:  *
1004:  * @return boolean
1005:  */
1006:     public function outputCompressed() {
1007:         return strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false
1008:             && (ini_get("zlib.output_compression") === '1' || in_array('ob_gzhandler', ob_list_handlers()));
1009:     }
1010: 
1011: /**
1012:  * Sets the correct headers to instruct the browser to download the response as a file.
1013:  *
1014:  * @param string $filename the name of the file as the browser will download the response
1015:  * @return void
1016:  */
1017:     public function download($filename) {
1018:         $this->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
1019:     }
1020: 
1021: /**
1022:  * Sets the protocol to be used when sending the response. Defaults to HTTP/1.1
1023:  * If called with no arguments, it will return the current configured protocol
1024:  *
1025:  * @return string protocol to be used for sending response
1026:  */
1027:     public function protocol($protocol = null) {
1028:         if ($protocol !== null) {
1029:             $this->_protocol = $protocol;
1030:         }
1031:         return $this->_protocol;
1032:     }
1033: 
1034: /**
1035:  * Sets the Content-Length header for the response
1036:  * If called with no arguments returns the last Content-Length set
1037:  *
1038:  * @return int
1039:  */
1040:     public function length($bytes = null) {
1041:         if ($bytes !== null ) {
1042:             $this->_headers['Content-Length'] = $bytes;
1043:         }
1044:         if (isset($this->_headers['Content-Length'])) {
1045:             return $this->_headers['Content-Length'];
1046:         }
1047:         return null;
1048:     }
1049: 
1050: /**
1051:  * Checks whether a response has not been modified according to the 'If-None-Match'
1052:  * (Etags) and 'If-Modified-Since' (last modification date) request
1053:  * headers headers. If the response is detected to be not modified, it
1054:  * is marked as so accordingly so the client can be informed of that.
1055:  *
1056:  * In order to mark a response as not modified, you need to set at least
1057:  * the Last-Modified response header or a response etag to be compared
1058:  * with the request itself
1059:  *
1060:  * @return boolean whether the response was marked as not modified or
1061:  * not
1062:  **/
1063:     public function checkNotModified(CakeRequest $request) {
1064:         $etags = preg_split('/\s*,\s*/', $request->header('If-None-Match'), null, PREG_SPLIT_NO_EMPTY);
1065:         $modifiedSince = $request->header('If-Modified-Since');
1066:         if ($responseTag = $this->etag()) {
1067:             $etagMatches = in_array('*', $etags) || in_array($responseTag, $etags);
1068:         }
1069:         if ($modifiedSince) {
1070:             $timeMatches = strtotime($this->modified()) == strtotime($modifiedSince);
1071:         }
1072:         $checks = compact('etagMatches', 'timeMatches');
1073:         if (empty($checks)) {
1074:             return false;
1075:         }
1076:         $notModified = !in_array(false, $checks, true);
1077:         if ($notModified) {
1078:             $this->notModified();
1079:         }
1080:         return $notModified;
1081:     }
1082: 
1083: /**
1084:  * String conversion.  Fetches the response body as a string.
1085:  * Does *not* send headers.
1086:  *
1087:  * @return string
1088:  */
1089:     public function __toString() {
1090:         return (string)$this->_body;
1091:     }
1092: 
1093: /**
1094:  * Getter/Setter for cookie configs
1095:  *
1096:  * This method acts as a setter/getter depending on the type of the argument.
1097:  * If the method is called with no arguments, it returns all configurations.
1098:  *
1099:  * If the method is called with a string as argument, it returns either the
1100:  * given configuration if it is set, or null, if it's not set.
1101:  *
1102:  * If the method is called with an array as argument, it will set the cookie
1103:  * configuration to the cookie container.
1104:  *
1105:  * @param $options Either null to get all cookies, string for a specific cookie
1106:  *  or array to set cookie.
1107:  *
1108:  * ### Options (when setting a configuration)
1109:  *  - name: The Cookie name
1110:  *  - value: Value of the cookie
1111:  *  - expire: Time the cookie expires in
1112:  *  - path: Path the cookie applies to
1113:  *  - domain: Domain the cookie is for.
1114:  *  - secure: Is the cookie https?
1115:  *  - httpOnly: Is the cookie available in the client?
1116:  *
1117:  * ## Examples
1118:  *
1119:  * ### Getting all cookies
1120:  *
1121:  * `$this->cookie()`
1122:  *
1123:  * ### Getting a certain cookie configuration
1124:  *
1125:  * `$this->cookie('MyCookie')`
1126:  *
1127:  * ### Setting a cookie configuration
1128:  *
1129:  * `$this->cookie((array) $options)`
1130:  *
1131:  * @return mixed
1132:  */
1133:     public function cookie($options = null) {
1134:         if ($options === null) {
1135:             return $this->_cookies;
1136:         }
1137: 
1138:         if (is_string($options)) {
1139:             if (!isset($this->_cookies[$options])) {
1140:                 return null;
1141:             }
1142:             return $this->_cookies[$options];
1143:         }
1144: 
1145:         $defaults = array(
1146:             'name' => 'CakeCookie[default]',
1147:             'value' => '',
1148:             'expire' => 0,
1149:             'path' => '/',
1150:             'domain' => '',
1151:             'secure' => false,
1152:             'httpOnly' => false
1153:         );
1154:         $options += $defaults;
1155: 
1156:         $this->_cookies[$options['name']] = $options;
1157:     }
1158: 
1159: }
1160: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs