1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
11: * @link http://cakephp.org CakePHP(tm) Project
12: * @license http://www.opensource.org/licenses/mit-license.php MIT License
13: */
14:
15: App::uses('View', 'View');
16: App::uses('Xml', 'Utility');
17: App::uses('Hash', 'Utility');
18:
19: /**
20: * A view class that is used for creating XML responses.
21: *
22: * By setting the '_serialize' key in your controller, you can specify a view variable
23: * that should be serialized to XML and used as the response for the request.
24: * This allows you to omit views + layouts, if your just need to emit a single view
25: * variable as the XML response.
26: *
27: * In your controller, you could do the following:
28: *
29: * `$this->set(array('posts' => $posts, '_serialize' => 'posts'));`
30: *
31: * When the view is rendered, the `$posts` view variable will be serialized
32: * into XML.
33: *
34: * **Note** The view variable you specify must be compatible with Xml::fromArray().
35: *
36: * You can also define `'_serialize'` as an array. This will create an additional
37: * top level element named `<response>` containing all the named view variables:
38: *
39: * ```
40: * $this->set(compact('posts', 'users', 'stuff'));
41: * $this->set('_serialize', array('posts', 'users'));
42: * ```
43: *
44: * The above would generate a XML object that looks like:
45: *
46: * `<response><posts>...</posts><users>...</users></response>`
47: *
48: * If you don't use the `_serialize` key, you will need a view. You can use extended
49: * views to provide layout like functionality.
50: *
51: * @package Cake.View
52: * @since CakePHP(tm) v 2.1.0
53: */
54: class XmlView extends View {
55:
56: /**
57: * The subdirectory. XML views are always in xml.
58: *
59: * @var string
60: */
61: public $subDir = 'xml';
62:
63: /**
64: * Constructor
65: *
66: * @param Controller $controller Controller instance.
67: */
68: public function __construct(Controller $controller = null) {
69: parent::__construct($controller);
70:
71: if (isset($controller->response) && $controller->response instanceof CakeResponse) {
72: $controller->response->type('xml');
73: }
74: }
75:
76: /**
77: * Skip loading helpers if this is a _serialize based view.
78: *
79: * @return void
80: */
81: public function loadHelpers() {
82: if (isset($this->viewVars['_serialize'])) {
83: return;
84: }
85: parent::loadHelpers();
86: }
87:
88: /**
89: * Render a XML view.
90: *
91: * Uses the special '_serialize' parameter to convert a set of
92: * view variables into a XML response. Makes generating simple
93: * XML responses very easy. You can omit the '_serialize' parameter,
94: * and use a normal view + layout as well.
95: *
96: * @param string $view The view being rendered.
97: * @param string $layout The layout being rendered.
98: * @return string The rendered view.
99: */
100: public function render($view = null, $layout = null) {
101: if (isset($this->viewVars['_serialize'])) {
102: return $this->_serialize($this->viewVars['_serialize']);
103: }
104: if ($view !== false && $this->_getViewFileName($view)) {
105: return parent::render($view, false);
106: }
107: }
108:
109: /**
110: * Serialize view vars.
111: *
112: * ### Special parameters
113: * `_xmlOptions` You can set an array of custom options for Xml::fromArray() this way, e.g.
114: * 'format' as 'attributes' instead of 'tags'.
115: *
116: * @param array $serialize The viewVars that need to be serialized.
117: * @return string The serialized data
118: */
119: protected function _serialize($serialize) {
120: $rootNode = isset($this->viewVars['_rootNode']) ? $this->viewVars['_rootNode'] : 'response';
121:
122: if (is_array($serialize)) {
123: $data = array($rootNode => array());
124: foreach ($serialize as $alias => $key) {
125: if (is_numeric($alias)) {
126: $alias = $key;
127: }
128: $data[$rootNode][$alias] = $this->viewVars[$key];
129: }
130: } else {
131: $data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
132: if (is_array($data) && Hash::numeric(array_keys($data))) {
133: $data = array($rootNode => array($serialize => $data));
134: }
135: }
136:
137: $options = array();
138: if (isset($this->viewVars['_xmlOptions'])) {
139: $options = $this->viewVars['_xmlOptions'];
140: }
141: if (Configure::read('debug')) {
142: $options['pretty'] = true;
143: }
144:
145: return Xml::fromArray($data, $options)->asXML();
146: }
147:
148: }
149: