]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/api/ApiResult.php
MediaWiki 1.14.0
[autoinstallsdev/mediawiki.git] / includes / api / ApiResult.php
1 <?php
2
3 /*
4  * Created on Sep 4, 2006
5  *
6  * API for MediaWiki 1.8+
7  *
8  * Copyright (C) 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  * http://www.gnu.org/copyleft/gpl.html
24  */
25
26 if (!defined('MEDIAWIKI')) {
27         // Eclipse helper - will be ignored in production
28         require_once ('ApiBase.php');
29 }
30
31 /**
32  * This class represents the result of the API operations.
33  * It simply wraps a nested array() structure, adding some functions to simplify array's modifications.
34  * As various modules execute, they add different pieces of information to this result,
35  * structuring it as it will be given to the client.
36  *
37  * Each subarray may either be a dictionary - key-value pairs with unique keys,
38  * or lists, where the items are added using $data[] = $value notation.
39  *
40  * There are two special key values that change how XML output is generated:
41  *   '_element' This key sets the tag name for the rest of the elements in the current array.
42  *              It is only inserted if the formatter returned true for getNeedsRawData()
43  *   '*'        This key has special meaning only to the XML formatter, and is outputed as is
44  *                              for all others. In XML it becomes the content of the current element.
45  *
46  * @ingroup API
47  */
48 class ApiResult extends ApiBase {
49
50         private $mData, $mIsRawMode;
51
52         /**
53         * Constructor
54         */
55         public function __construct($main) {
56                 parent :: __construct($main, 'result');
57                 $this->mIsRawMode = false;
58                 $this->reset();
59         }
60
61         /**
62          * Clear the current result data.
63          */
64         public function reset() {
65                 $this->mData = array ();
66         }
67
68         /**
69          * Call this function when special elements such as '_element'
70          * are needed by the formatter, for example in XML printing.
71          */
72         public function setRawMode() {
73                 $this->mIsRawMode = true;
74         }
75
76         /**
77          * Returns true if the result is being created for the formatter that requested raw data.
78          */
79         public function getIsRawMode() {
80                 return $this->mIsRawMode;
81         }
82
83         /**
84          * Get result's internal data array
85          */
86         public function & getData() {
87                 return $this->mData;
88         }
89
90         /**
91          * Add an output value to the array by name.
92          * Verifies that value with the same name has not been added before.
93          */
94         public static function setElement(& $arr, $name, $value) {
95                 if ($arr === null || $name === null || $value === null || !is_array($arr) || is_array($name))
96                         ApiBase :: dieDebug(__METHOD__, 'Bad parameter');
97
98                 if (!isset ($arr[$name])) {
99                         $arr[$name] = $value;
100                 }
101                 elseif (is_array($arr[$name]) && is_array($value)) {
102                         $merged = array_intersect_key($arr[$name], $value);
103                         if (!count($merged))
104                                 $arr[$name] += $value;
105                         else
106                                 ApiBase :: dieDebug(__METHOD__, "Attempting to merge element $name");
107                 } else
108                         ApiBase :: dieDebug(__METHOD__, "Attempting to add element $name=$value, existing value is {$arr[$name]}");
109         }
110
111         /**
112          * Adds the content element to the array.
113          * Use this function instead of hardcoding the '*' element.
114          * @param string $subElemName when present, content element is created as a sub item of the arr.
115          *  Use this parameter to create elements in format <elem>text</elem> without attributes
116          */
117         public static function setContent(& $arr, $value, $subElemName = null) {
118                 if (is_array($value))
119                         ApiBase :: dieDebug(__METHOD__, 'Bad parameter');
120                 if (is_null($subElemName)) {
121                         ApiResult :: setElement($arr, '*', $value);
122                 } else {
123                         if (!isset ($arr[$subElemName]))
124                                 $arr[$subElemName] = array ();
125                         ApiResult :: setElement($arr[$subElemName], '*', $value);
126                 }
127         }
128
129         /**
130          * In case the array contains indexed values (in addition to named),
131          * all indexed values will have the given tag name.
132          */
133         public function setIndexedTagName(& $arr, $tag) {
134                 // In raw mode, add the '_element', otherwise just ignore
135                 if (!$this->getIsRawMode())
136                         return;
137                 if ($arr === null || $tag === null || !is_array($arr) || is_array($tag))
138                         ApiBase :: dieDebug(__METHOD__, 'Bad parameter');
139                 // Do not use setElement() as it is ok to call this more than once
140                 $arr['_element'] = $tag;
141         }
142
143         /**
144          * Calls setIndexedTagName() on $arr and each sub-array
145          */
146         public function setIndexedTagName_recursive(&$arr, $tag)
147         {
148                         if(!is_array($arr))
149                                         return;
150                         foreach($arr as &$a)
151                         {
152                                         if(!is_array($a))
153                                                         continue;
154                                         $this->setIndexedTagName($a, $tag);
155                                         $this->setIndexedTagName_recursive($a, $tag);
156                         }
157         }
158
159         /**
160          * Add value to the output data at the given path.
161          * Path is an indexed array, each element specifing the branch at which to add the new value
162          * Setting $path to array('a','b','c') is equivalent to data['a']['b']['c'] = $value
163          * If $name is empty, the $value is added as a next list element data[] = $value
164          */
165         public function addValue($path, $name, $value) {
166
167                 $data = & $this->getData();
168
169                 if (!is_null($path)) {
170                         if (is_array($path)) {
171                                 foreach ($path as $p) {
172                                         if (!isset ($data[$p]))
173                                                 $data[$p] = array ();
174                                         $data = & $data[$p];
175                                 }
176                         } else {
177                                 if (!isset ($data[$path]))
178                                         $data[$path] = array ();
179                                 $data = & $data[$path];
180                         }
181                 }
182
183                 if (!$name)
184                         $data[] = $value;       // Add list element
185                 else
186                         ApiResult :: setElement($data, $name, $value);  // Add named element
187         }
188
189         /**
190          * Ensure all values in this result are valid UTF-8.
191          */
192         public function cleanUpUTF8()
193         {
194                 $data = & $this->getData();
195                 array_walk_recursive($data, array('UtfNormal', 'cleanUp'));
196         }
197
198         public function execute() {
199                 ApiBase :: dieDebug(__METHOD__, 'execute() is not supported on Result object');
200         }
201
202         public function getVersion() {
203                 return __CLASS__ . ': $Id: ApiResult.php 45752 2009-01-14 21:36:57Z catrope $';
204         }
205 }
206
207 /* For compatibility with PHP versions < 5.1.0, define our own array_intersect_key function. */
208 if (!function_exists('array_intersect_key')) {
209         function array_intersect_key($isec, $keys) {
210                 $argc = func_num_args();
211
212                 if ($argc > 2) {
213                         for ($i = 1; $isec && $i < $argc; $i++) {
214                                 $arr = func_get_arg($i);
215
216                                 foreach (array_keys($isec) as $key) {
217                                         if (!isset($arr[$key]))
218                                                 unset($isec[$key]);
219                                 }
220                         }
221
222                         return $isec;
223                 } else {
224                         $res = array();
225                         foreach (array_keys($isec) as $key) {
226                                 if (isset($keys[$key]))
227                                         $res[$key] = $isec[$key];
228                         }
229
230                         return $res;
231                 }
232         }
233 }