統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Controller / Component / RequestHandlerComponent.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (24.041 KB)

1
<?php
2
/**
3
 * Request object for handling alternative HTTP requests
4
 *
5
 * Alternative HTTP requests can come from wireless units like mobile phones, palmtop computers,
6
 * and the like. These units have no use for Ajax requests, and this Component can tell how Cake
7
 * should respond to the different needs of a handheld computer and a desktop machine.
8
 *
9
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
10
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 *
12
 * Licensed under The MIT License
13
 * For full copyright and license information, please see the LICENSE.txt
14
 * Redistributions of files must retain the above copyright notice.
15
 *
16
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
17
 * @link          http://cakephp.org CakePHP(tm) Project
18
 * @package       Cake.Controller.Component
19
 * @since         CakePHP(tm) v 0.10.4.1076
20
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
21
 */
22

    
23
App::uses('Component', 'Controller');
24
App::uses('Xml', 'Utility');
25

    
26
/**
27
 * Request object for handling alternative HTTP requests
28
 *
29
 * Alternative HTTP requests can come from wireless units like mobile phones, palmtop computers,
30
 * and the like. These units have no use for Ajax requests, and this Component can tell how Cake
31
 * should respond to the different needs of a handheld computer and a desktop machine.
32
 *
33
 * @package       Cake.Controller.Component
34
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/request-handling.html
35
 */
36
class RequestHandlerComponent extends Component {
37

    
38
/**
39
 * The layout that will be switched to for Ajax requests
40
 *
41
 * @var string
42
 * @see RequestHandler::setAjax()
43
 */
44
        public $ajaxLayout = 'ajax';
45

    
46
/**
47
 * Determines whether or not callbacks will be fired on this component
48
 *
49
 * @var bool
50
 */
51
        public $enabled = true;
52

    
53
/**
54
 * Holds the reference to Controller::$request
55
 *
56
 * @var CakeRequest
57
 */
58
        public $request;
59

    
60
/**
61
 * Holds the reference to Controller::$response
62
 *
63
 * @var CakeResponse
64
 */
65
        public $response;
66

    
67
/**
68
 * Contains the file extension parsed out by the Router
69
 *
70
 * @var string
71
 * @see Router::parseExtensions()
72
 */
73
        public $ext = null;
74

    
75
/**
76
 * The template to use when rendering the given content type.
77
 *
78
 * @var string
79
 */
80
        protected $_renderType = null;
81

    
82
/**
83
 * A mapping between extensions and deserializers for request bodies of that type.
84
 * By default only JSON and XML are mapped, use RequestHandlerComponent::addInputType()
85
 *
86
 * @var array
87
 */
88
        protected $_inputTypeMap = array(
89
                'json' => array('json_decode', true)
90
        );
91

    
92
/**
93
 * A mapping between type and viewClass
94
 * By default only JSON and XML are mapped, use RequestHandlerComponent::viewClassMap()
95
 *
96
 * @var array
97
 */
98
        protected $_viewClassMap = array(
99
                'json' => 'Json',
100
                'xml' => 'Xml'
101
        );
102

    
103
/**
104
 * Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
105
 *
106
 * @param ComponentCollection $collection ComponentCollection object.
107
 * @param array $settings Array of settings.
108
 */
109
        public function __construct(ComponentCollection $collection, $settings = array()) {
110
                parent::__construct($collection, $settings + array('checkHttpCache' => true));
111
                $this->addInputType('xml', array(array($this, 'convertXml')));
112

    
113
                $Controller = $collection->getController();
114
                $this->request = $Controller->request;
115
                $this->response = $Controller->response;
116
        }
117

    
118
/**
119
 * Checks to see if a file extension has been parsed by the Router, or if the
120
 * HTTP_ACCEPT_TYPE has matches only one content type with the supported extensions.
121
 * If there is only one matching type between the supported content types & extensions,
122
 * and the requested mime-types, RequestHandler::$ext is set to that value.
123
 *
124
 * @param Controller $controller A reference to the controller
125
 * @return void
126
 * @see Router::parseExtensions()
127
 */
128
        public function initialize(Controller $controller) {
129
                if (isset($this->request->params['ext'])) {
130
                        $this->ext = $this->request->params['ext'];
131
                }
132
                if (empty($this->ext) || $this->ext === 'html') {
133
                        $this->_setExtension();
134
                }
135
                $this->params = $controller->params;
136
                if (!empty($this->settings['viewClassMap'])) {
137
                        $this->viewClassMap($this->settings['viewClassMap']);
138
                }
139
        }
140

    
141
/**
142
 * Set the extension based on the accept headers.
143
 * Compares the accepted types and configured extensions.
144
 * If there is one common type, that is assigned as the ext/content type
145
 * for the response.
146
 * Type with the highest weight will be set. If the highest weight has more
147
 * then one type matching the extensions, the order in which extensions are specified
148
 * determines which type will be set.
149
 *
150
 * If html is one of the preferred types, no content type will be set, this
151
 * is to avoid issues with browsers that prefer html and several other content types.
152
 *
153
 * @return void
154
 */
155
        protected function _setExtension() {
156
                $accept = $this->request->parseAccept();
157
                if (empty($accept)) {
158
                        return;
159
                }
160

    
161
                $accepts = $this->response->mapType($accept);
162
                $preferedTypes = current($accepts);
163
                if (array_intersect($preferedTypes, array('html', 'xhtml'))) {
164
                        return;
165
                }
166

    
167
                $extensions = Router::extensions();
168
                foreach ($accepts as $types) {
169
                        $ext = array_intersect($extensions, $types);
170
                        if ($ext) {
171
                                $this->ext = current($ext);
172
                                break;
173
                        }
174
                }
175
        }
176

    
177
/**
178
 * The startup method of the RequestHandler enables several automatic behaviors
179
 * related to the detection of certain properties of the HTTP request, including:
180
 *
181
 * - Disabling layout rendering for Ajax requests (based on the HTTP_X_REQUESTED_WITH header)
182
 * - If Router::parseExtensions() is enabled, the layout and template type are
183
 *   switched based on the parsed extension or Accept-Type header. For example, if `controller/action.xml`
184
 *   is requested, the view path becomes `app/View/Controller/xml/action.ctp`. Also if
185
 *   `controller/action` is requested with `Accept-Type: application/xml` in the headers
186
 *   the view path will become `app/View/Controller/xml/action.ctp`. Layout and template
187
 *   types will only switch to mime-types recognized by CakeResponse. If you need to declare
188
 *   additional mime-types, you can do so using CakeResponse::type() in your controllers beforeFilter()
189
 *   method.
190
 * - If a helper with the same name as the extension exists, it is added to the controller.
191
 * - If the extension is of a type that RequestHandler understands, it will set that
192
 *   Content-type in the response header.
193
 * - If the XML data is POSTed, the data is parsed into an XML object, which is assigned
194
 *   to the $data property of the controller, which can then be saved to a model object.
195
 *
196
 * @param Controller $controller A reference to the controller
197
 * @return void
198
 */
199
        public function startup(Controller $controller) {
200
                $controller->request->params['isAjax'] = $this->request->is('ajax');
201
                $isRecognized = (
202
                        !in_array($this->ext, array('html', 'htm')) &&
203
                        $this->response->getMimeType($this->ext)
204
                );
205

    
206
                if (!empty($this->ext) && $isRecognized) {
207
                        $this->renderAs($controller, $this->ext);
208
                } elseif ($this->request->is('ajax')) {
209
                        $this->renderAs($controller, 'ajax');
210
                } elseif (empty($this->ext) || in_array($this->ext, array('html', 'htm'))) {
211
                        $this->respondAs('html', array('charset' => Configure::read('App.encoding')));
212
                }
213

    
214
                foreach ($this->_inputTypeMap as $type => $handler) {
215
                        if ($this->requestedWith($type)) {
216
                                $input = call_user_func_array(array($controller->request, 'input'), $handler);
217
                                $controller->request->data = $input;
218
                        }
219
                }
220
        }
221

    
222
/**
223
 * Helper method to parse xml input data, due to lack of anonymous functions
224
 * this lives here.
225
 *
226
 * @param string $xml XML string.
227
 * @return array Xml array data
228
 */
229
        public function convertXml($xml) {
230
                try {
231
                        $xml = Xml::build($xml, array('readFile' => false));
232
                        if (isset($xml->data)) {
233
                                return Xml::toArray($xml->data);
234
                        }
235
                        return Xml::toArray($xml);
236
                } catch (XmlException $e) {
237
                        return array();
238
                }
239
        }
240

    
241
/**
242
 * Handles (fakes) redirects for Ajax requests using requestAction()
243
 * Modifies the $_POST and $_SERVER['REQUEST_METHOD'] to simulate a new GET request.
244
 *
245
 * @param Controller $controller A reference to the controller
246
 * @param string|array $url A string or array containing the redirect location
247
 * @param int|array $status HTTP Status for redirect
248
 * @param bool $exit Whether to exit script, defaults to `true`.
249
 * @return void
250
 */
251
        public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true) {
252
                if (!$this->request->is('ajax')) {
253
                        return;
254
                }
255
                if (empty($url)) {
256
                        return;
257
                }
258
                $_SERVER['REQUEST_METHOD'] = 'GET';
259
                foreach ($_POST as $key => $val) {
260
                        unset($_POST[$key]);
261
                }
262
                if (is_array($url)) {
263
                        $url = Router::url($url + array('base' => false));
264
                }
265
                if (!empty($status)) {
266
                        $statusCode = $this->response->httpCodes($status);
267
                        $code = key($statusCode);
268
                        $this->response->statusCode($code);
269
                }
270
                $this->response->body($this->requestAction($url, array('return', 'bare' => false)));
271
                $this->response->send();
272
                $this->_stop();
273
        }
274

    
275
/**
276
 * Checks if the response can be considered different according to the request
277
 * headers, and the caching response headers. If it was not modified, then the
278
 * render process is skipped. And the client will get a blank response with a
279
 * "304 Not Modified" header.
280
 *
281
 * @param Controller $controller Controller instance.
282
 * @return bool False if the render process should be aborted.
283
 */
284
        public function beforeRender(Controller $controller) {
285
                if ($this->settings['checkHttpCache'] && $this->response->checkNotModified($this->request)) {
286
                        return false;
287
                }
288
        }
289

    
290
/**
291
 * Returns true if the current HTTP request is Ajax, false otherwise
292
 *
293
 * @return bool True if call is Ajax
294
 * @deprecated 3.0.0 Use `$this->request->is('ajax')` instead.
295
 */
296
        public function isAjax() {
297
                return $this->request->is('ajax');
298
        }
299

    
300
/**
301
 * Returns true if the current HTTP request is coming from a Flash-based client
302
 *
303
 * @return bool True if call is from Flash
304
 * @deprecated 3.0.0 Use `$this->request->is('flash')` instead.
305
 */
306
        public function isFlash() {
307
                return $this->request->is('flash');
308
        }
309

    
310
/**
311
 * Returns true if the current request is over HTTPS, false otherwise.
312
 *
313
 * @return bool True if call is over HTTPS
314
 * @deprecated 3.0.0 Use `$this->request->is('ssl')` instead.
315
 */
316
        public function isSSL() {
317
                return $this->request->is('ssl');
318
        }
319

    
320
/**
321
 * Returns true if the current call accepts an XML response, false otherwise
322
 *
323
 * @return bool True if client accepts an XML response
324
 */
325
        public function isXml() {
326
                return $this->prefers('xml');
327
        }
328

    
329
/**
330
 * Returns true if the current call accepts an RSS response, false otherwise
331
 *
332
 * @return bool True if client accepts an RSS response
333
 */
334
        public function isRss() {
335
                return $this->prefers('rss');
336
        }
337

    
338
/**
339
 * Returns true if the current call accepts an Atom response, false otherwise
340
 *
341
 * @return bool True if client accepts an RSS response
342
 */
343
        public function isAtom() {
344
                return $this->prefers('atom');
345
        }
346

    
347
/**
348
 * Returns true if user agent string matches a mobile web browser, or if the
349
 * client accepts WAP content.
350
 *
351
 * @return bool True if user agent is a mobile web browser
352
 */
353
        public function isMobile() {
354
                return $this->request->is('mobile') || $this->accepts('wap');
355
        }
356

    
357
/**
358
 * Returns true if the client accepts WAP content
359
 *
360
 * @return bool
361
 */
362
        public function isWap() {
363
                return $this->prefers('wap');
364
        }
365

    
366
/**
367
 * Returns true if the current call a POST request
368
 *
369
 * @return bool True if call is a POST
370
 * @deprecated 3.0.0 Use $this->request->is('post'); from your controller.
371
 */
372
        public function isPost() {
373
                return $this->request->is('post');
374
        }
375

    
376
/**
377
 * Returns true if the current call a PUT request
378
 *
379
 * @return bool True if call is a PUT
380
 * @deprecated 3.0.0 Use $this->request->is('put'); from your controller.
381
 */
382
        public function isPut() {
383
                return $this->request->is('put');
384
        }
385

    
386
/**
387
 * Returns true if the current call a GET request
388
 *
389
 * @return bool True if call is a GET
390
 * @deprecated 3.0.0 Use $this->request->is('get'); from your controller.
391
 */
392
        public function isGet() {
393
                return $this->request->is('get');
394
        }
395

    
396
/**
397
 * Returns true if the current call a DELETE request
398
 *
399
 * @return bool True if call is a DELETE
400
 * @deprecated 3.0.0 Use $this->request->is('delete'); from your controller.
401
 */
402
        public function isDelete() {
403
                return $this->request->is('delete');
404
        }
405

    
406
/**
407
 * Gets Prototype version if call is Ajax, otherwise empty string.
408
 * The Prototype library sets a special "Prototype version" HTTP header.
409
 *
410
 * @return string|bool When Ajax the prototype version of component making the call otherwise false
411
 */
412
        public function getAjaxVersion() {
413
                $httpX = env('HTTP_X_PROTOTYPE_VERSION');
414
                return ($httpX === null) ? false : $httpX;
415
        }
416

    
417
/**
418
 * Adds/sets the Content-type(s) for the given name. This method allows
419
 * content-types to be mapped to friendly aliases (or extensions), which allows
420
 * RequestHandler to automatically respond to requests of that type in the
421
 * startup method.
422
 *
423
 * @param string $name The name of the Content-type, i.e. "html", "xml", "css"
424
 * @param string|array $type The Content-type or array of Content-types assigned to the name,
425
 *    i.e. "text/html", or "application/xml"
426
 * @return void
427
 * @deprecated 3.0.0 Use `$this->response->type()` instead.
428
 */
429
        public function setContent($name, $type = null) {
430
                $this->response->type(array($name => $type));
431
        }
432

    
433
/**
434
 * Gets the server name from which this request was referred
435
 *
436
 * @return string Server address
437
 * @deprecated 3.0.0 Use $this->request->referer() from your controller instead
438
 */
439
        public function getReferer() {
440
                return $this->request->referer(false);
441
        }
442

    
443
/**
444
 * Gets remote client IP
445
 *
446
 * @param bool $safe Use safe = false when you think the user might manipulate
447
 *   their HTTP_CLIENT_IP header. Setting $safe = false will also look at HTTP_X_FORWARDED_FOR
448
 * @return string Client IP address
449
 * @deprecated 3.0.0 Use $this->request->clientIp() from your, controller instead.
450
 */
451
        public function getClientIP($safe = true) {
452
                return $this->request->clientIp($safe);
453
        }
454

    
455
/**
456
 * Determines which content types the client accepts. Acceptance is based on
457
 * the file extension parsed by the Router (if present), and by the HTTP_ACCEPT
458
 * header. Unlike CakeRequest::accepts() this method deals entirely with mapped content types.
459
 *
460
 * Usage:
461
 *
462
 * `$this->RequestHandler->accepts(array('xml', 'html', 'json'));`
463
 *
464
 * Returns true if the client accepts any of the supplied types.
465
 *
466
 * `$this->RequestHandler->accepts('xml');`
467
 *
468
 * Returns true if the client accepts xml.
469
 *
470
 * @param string|array $type Can be null (or no parameter), a string type name, or an
471
 *   array of types
472
 * @return mixed If null or no parameter is passed, returns an array of content
473
 *   types the client accepts. If a string is passed, returns true
474
 *   if the client accepts it. If an array is passed, returns true
475
 *   if the client accepts one or more elements in the array.
476
 * @see RequestHandlerComponent::setContent()
477
 */
478
        public function accepts($type = null) {
479
                $accepted = $this->request->accepts();
480

    
481
                if (!$type) {
482
                        return $this->mapType($accepted);
483
                }
484
                if (is_array($type)) {
485
                        foreach ($type as $t) {
486
                                $t = $this->mapAlias($t);
487
                                if (in_array($t, $accepted)) {
488
                                        return true;
489
                                }
490
                        }
491
                        return false;
492
                }
493
                if (is_string($type)) {
494
                        return in_array($this->mapAlias($type), $accepted);
495
                }
496
                return false;
497
        }
498

    
499
/**
500
 * Determines the content type of the data the client has sent (i.e. in a POST request)
501
 *
502
 * @param string|array $type Can be null (or no parameter), a string type name, or an array of types
503
 * @return mixed If a single type is supplied a boolean will be returned. If no type is provided
504
 *   The mapped value of CONTENT_TYPE will be returned. If an array is supplied the first type
505
 *   in the request content type will be returned.
506
 */
507
        public function requestedWith($type = null) {
508
                if (!$this->request->is('post') && !$this->request->is('put') && !$this->request->is('delete')) {
509
                        return null;
510
                }
511
                if (is_array($type)) {
512
                        foreach ($type as $t) {
513
                                if ($this->requestedWith($t)) {
514
                                        return $t;
515
                                }
516
                        }
517
                        return false;
518
                }
519

    
520
                list($contentType) = explode(';', env('CONTENT_TYPE'));
521
                if ($contentType === '') {
522
                        list($contentType) = explode(';', CakeRequest::header('CONTENT_TYPE'));
523
                }
524
                if (!$type) {
525
                        return $this->mapType($contentType);
526
                }
527
                if (is_string($type)) {
528
                        return ($type === $this->mapType($contentType));
529
                }
530
        }
531

    
532
/**
533
 * Determines which content-types the client prefers. If no parameters are given,
534
 * the single content-type that the client most likely prefers is returned. If $type is
535
 * an array, the first item in the array that the client accepts is returned.
536
 * Preference is determined primarily by the file extension parsed by the Router
537
 * if provided, and secondarily by the list of content-types provided in
538
 * HTTP_ACCEPT.
539
 *
540
 * @param string|array $type An optional array of 'friendly' content-type names, i.e.
541
 *   'html', 'xml', 'js', etc.
542
 * @return mixed If $type is null or not provided, the first content-type in the
543
 *    list, based on preference, is returned. If a single type is provided
544
 *    a boolean will be returned if that type is preferred.
545
 *    If an array of types are provided then the first preferred type is returned.
546
 *    If no type is provided the first preferred type is returned.
547
 * @see RequestHandlerComponent::setContent()
548
 */
549
        public function prefers($type = null) {
550
                $acceptRaw = $this->request->parseAccept();
551

    
552
                if (empty($acceptRaw)) {
553
                        return $this->ext;
554
                }
555
                $accepts = $this->mapType(array_shift($acceptRaw));
556

    
557
                if (!$type) {
558
                        if (empty($this->ext) && !empty($accepts)) {
559
                                return $accepts[0];
560
                        }
561
                        return $this->ext;
562
                }
563

    
564
                $types = (array)$type;
565

    
566
                if (count($types) === 1) {
567
                        if (!empty($this->ext)) {
568
                                return in_array($this->ext, $types);
569
                        }
570
                        return in_array($types[0], $accepts);
571
                }
572

    
573
                $intersect = array_values(array_intersect($accepts, $types));
574
                if (empty($intersect)) {
575
                        return false;
576
                }
577
                return $intersect[0];
578
        }
579

    
580
/**
581
 * Sets the layout and template paths for the content type defined by $type.
582
 *
583
 * ### Usage:
584
 *
585
 * Render the response as an 'ajax' response.
586
 *
587
 * `$this->RequestHandler->renderAs($this, 'ajax');`
588
 *
589
 * Render the response as an xml file and force the result as a file download.
590
 *
591
 * `$this->RequestHandler->renderAs($this, 'xml', array('attachment' => 'myfile.xml');`
592
 *
593
 * @param Controller $controller A reference to a controller object
594
 * @param string $type Type of response to send (e.g: 'ajax')
595
 * @param array $options Array of options to use
596
 * @return void
597
 * @see RequestHandlerComponent::setContent()
598
 * @see RequestHandlerComponent::respondAs()
599
 */
600
        public function renderAs(Controller $controller, $type, $options = array()) {
601
                $defaults = array('charset' => 'UTF-8');
602

    
603
                if (Configure::read('App.encoding') !== null) {
604
                        $defaults['charset'] = Configure::read('App.encoding');
605
                }
606
                $options += $defaults;
607

    
608
                if ($type === 'ajax') {
609
                        $controller->layout = $this->ajaxLayout;
610
                        return $this->respondAs('html', $options);
611
                }
612

    
613
                $pluginDot = null;
614
                $viewClassMap = $this->viewClassMap();
615
                if (array_key_exists($type, $viewClassMap)) {
616
                        list($pluginDot, $viewClass) = pluginSplit($viewClassMap[$type], true);
617
                } else {
618
                        $viewClass = Inflector::classify($type);
619
                }
620
                $viewName = $viewClass . 'View';
621
                if (!class_exists($viewName)) {
622
                        App::uses($viewName, $pluginDot . 'View');
623
                }
624
                if (class_exists($viewName)) {
625
                        $controller->viewClass = $viewClass;
626
                } elseif (empty($this->_renderType)) {
627
                        $controller->viewPath .= DS . $type;
628
                } else {
629
                        $controller->viewPath = preg_replace(
630
                                "/([\/\\\\]{$this->_renderType})$/",
631
                                DS . $type,
632
                                $controller->viewPath
633
                        );
634
                }
635
                $this->_renderType = $type;
636
                $controller->layoutPath = $type;
637

    
638
                if ($this->response->getMimeType($type)) {
639
                        $this->respondAs($type, $options);
640
                }
641

    
642
                $helper = ucfirst($type);
643

    
644
                if (!in_array($helper, $controller->helpers) && empty($controller->helpers[$helper])) {
645
                        App::uses('AppHelper', 'View/Helper');
646
                        App::uses($helper . 'Helper', 'View/Helper');
647
                        if (class_exists($helper . 'Helper')) {
648
                                $controller->helpers[] = $helper;
649
                        }
650
                }
651
        }
652

    
653
/**
654
 * Sets the response header based on type map index name. This wraps several methods
655
 * available on CakeResponse. It also allows you to use Content-Type aliases.
656
 *
657
 * @param string|array $type Friendly type name, i.e. 'html' or 'xml', or a full content-type,
658
 *    like 'application/x-shockwave'.
659
 * @param array $options If $type is a friendly type name that is associated with
660
 *    more than one type of content, $index is used to select which content-type to use.
661
 * @return bool Returns false if the friendly type name given in $type does
662
 *    not exist in the type map, or if the Content-type header has
663
 *    already been set by this method.
664
 * @see RequestHandlerComponent::setContent()
665
 */
666
        public function respondAs($type, $options = array()) {
667
                $defaults = array('index' => null, 'charset' => null, 'attachment' => false);
668
                $options = $options + $defaults;
669

    
670
                $cType = $type;
671
                if (strpos($type, '/') === false) {
672
                        $cType = $this->response->getMimeType($type);
673
                }
674
                if (is_array($cType)) {
675
                        if (isset($cType[$options['index']])) {
676
                                $cType = $cType[$options['index']];
677
                        }
678

    
679
                        if ($this->prefers($cType)) {
680
                                $cType = $this->prefers($cType);
681
                        } else {
682
                                $cType = $cType[0];
683
                        }
684
                }
685

    
686
                if (!$type) {
687
                        return false;
688
                }
689
                if (empty($this->request->params['requested'])) {
690
                        $this->response->type($cType);
691
                }
692
                if (!empty($options['charset'])) {
693
                        $this->response->charset($options['charset']);
694
                }
695
                if (!empty($options['attachment'])) {
696
                        $this->response->download($options['attachment']);
697
                }
698
                return true;
699
        }
700

    
701
/**
702
 * Returns the current response type (Content-type header), or null if not alias exists
703
 *
704
 * @return mixed A string content type alias, or raw content type if no alias map exists,
705
 *        otherwise null
706
 */
707
        public function responseType() {
708
                return $this->mapType($this->response->type());
709
        }
710

    
711
/**
712
 * Maps a content-type back to an alias
713
 *
714
 * @param string|array $cType Either a string content type to map, or an array of types.
715
 * @return string|array Aliases for the types provided.
716
 * @deprecated 3.0.0 Use $this->response->mapType() in your controller instead.
717
 */
718
        public function mapType($cType) {
719
                return $this->response->mapType($cType);
720
        }
721

    
722
/**
723
 * Maps a content type alias back to its mime-type(s)
724
 *
725
 * @param string|array $alias String alias to convert back into a content type. Or an array of aliases to map.
726
 * @return string|null Null on an undefined alias. String value of the mapped alias type. If an
727
 *   alias maps to more than one content type, the first one will be returned.
728
 */
729
        public function mapAlias($alias) {
730
                if (is_array($alias)) {
731
                        return array_map(array($this, 'mapAlias'), $alias);
732
                }
733
                $type = $this->response->getMimeType($alias);
734
                if ($type) {
735
                        if (is_array($type)) {
736
                                return $type[0];
737
                        }
738
                        return $type;
739
                }
740
                return null;
741
        }
742

    
743
/**
744
 * Add a new mapped input type. Mapped input types are automatically
745
 * converted by RequestHandlerComponent during the startup() callback.
746
 *
747
 * @param string $type The type alias being converted, ie. json
748
 * @param array $handler The handler array for the type. The first index should
749
 *    be the handling callback, all other arguments should be additional parameters
750
 *    for the handler.
751
 * @return void
752
 * @throws CakeException
753
 */
754
        public function addInputType($type, $handler) {
755
                if (!is_array($handler) || !isset($handler[0]) || !is_callable($handler[0])) {
756
                        throw new CakeException(__d('cake_dev', 'You must give a handler callback.'));
757
                }
758
                $this->_inputTypeMap[$type] = $handler;
759
        }
760

    
761
/**
762
 * Getter/setter for viewClassMap
763
 *
764
 * @param array|string $type The type string or array with format `array('type' => 'viewClass')` to map one or more
765
 * @param array $viewClass The viewClass to be used for the type without `View` appended
766
 * @return array|string Returns viewClass when only string $type is set, else array with viewClassMap
767
 */
768
        public function viewClassMap($type = null, $viewClass = null) {
769
                if (!$viewClass && is_string($type) && isset($this->_viewClassMap[$type])) {
770
                        return $this->_viewClassMap[$type];
771
                }
772
                if (is_string($type)) {
773
                        $this->_viewClassMap[$type] = $viewClass;
774
                } elseif (is_array($type)) {
775
                        foreach ($type as $key => $value) {
776
                                $this->viewClassMap($key, $value);
777
                        }
778
                }
779
                return $this->_viewClassMap;
780
        }
781

    
782
}