|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Controller |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 */ |
|
20 |
|
21 /** |
|
22 * Zend_XmlRpc_Value |
|
23 */ |
|
24 require_once 'Zend/XmlRpc/Value.php'; |
|
25 |
|
26 /** |
|
27 * Zend_XmlRpc_Fault |
|
28 */ |
|
29 require_once 'Zend/XmlRpc/Fault.php'; |
|
30 |
|
31 /** |
|
32 * XmlRpc Request object |
|
33 * |
|
34 * Encapsulates an XmlRpc request, holding the method call and all parameters. |
|
35 * Provides accessors for these, as well as the ability to load from XML and to |
|
36 * create the XML request string. |
|
37 * |
|
38 * Additionally, if errors occur setting the method or parsing XML, a fault is |
|
39 * generated and stored in {@link $_fault}; developers may check for it using |
|
40 * {@link isFault()} and {@link getFault()}. |
|
41 * |
|
42 * @category Zend |
|
43 * @package Zend_XmlRpc |
|
44 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
45 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
46 * @version $Id: Request.php 20208 2010-01-11 22:37:37Z lars $ |
|
47 */ |
|
48 class Zend_XmlRpc_Request |
|
49 { |
|
50 /** |
|
51 * Request character encoding |
|
52 * @var string |
|
53 */ |
|
54 protected $_encoding = 'UTF-8'; |
|
55 |
|
56 /** |
|
57 * Method to call |
|
58 * @var string |
|
59 */ |
|
60 protected $_method; |
|
61 |
|
62 /** |
|
63 * XML request |
|
64 * @var string |
|
65 */ |
|
66 protected $_xml; |
|
67 |
|
68 /** |
|
69 * Method parameters |
|
70 * @var array |
|
71 */ |
|
72 protected $_params = array(); |
|
73 |
|
74 /** |
|
75 * Fault object, if any |
|
76 * @var Zend_XmlRpc_Fault |
|
77 */ |
|
78 protected $_fault = null; |
|
79 |
|
80 /** |
|
81 * XML-RPC type for each param |
|
82 * @var array |
|
83 */ |
|
84 protected $_types = array(); |
|
85 |
|
86 /** |
|
87 * XML-RPC request params |
|
88 * @var array |
|
89 */ |
|
90 protected $_xmlRpcParams = array(); |
|
91 |
|
92 /** |
|
93 * Create a new XML-RPC request |
|
94 * |
|
95 * @param string $method (optional) |
|
96 * @param array $params (optional) |
|
97 */ |
|
98 public function __construct($method = null, $params = null) |
|
99 { |
|
100 if ($method !== null) { |
|
101 $this->setMethod($method); |
|
102 } |
|
103 |
|
104 if ($params !== null) { |
|
105 $this->setParams($params); |
|
106 } |
|
107 } |
|
108 |
|
109 |
|
110 /** |
|
111 * Set encoding to use in request |
|
112 * |
|
113 * @param string $encoding |
|
114 * @return Zend_XmlRpc_Request |
|
115 */ |
|
116 public function setEncoding($encoding) |
|
117 { |
|
118 $this->_encoding = $encoding; |
|
119 Zend_XmlRpc_Value::setEncoding($encoding); |
|
120 return $this; |
|
121 } |
|
122 |
|
123 /** |
|
124 * Retrieve current request encoding |
|
125 * |
|
126 * @return string |
|
127 */ |
|
128 public function getEncoding() |
|
129 { |
|
130 return $this->_encoding; |
|
131 } |
|
132 |
|
133 /** |
|
134 * Set method to call |
|
135 * |
|
136 * @param string $method |
|
137 * @return boolean Returns true on success, false if method name is invalid |
|
138 */ |
|
139 public function setMethod($method) |
|
140 { |
|
141 if (!is_string($method) || !preg_match('/^[a-z0-9_.:\/]+$/i', $method)) { |
|
142 $this->_fault = new Zend_XmlRpc_Fault(634, 'Invalid method name ("' . $method . '")'); |
|
143 $this->_fault->setEncoding($this->getEncoding()); |
|
144 return false; |
|
145 } |
|
146 |
|
147 $this->_method = $method; |
|
148 return true; |
|
149 } |
|
150 |
|
151 /** |
|
152 * Retrieve call method |
|
153 * |
|
154 * @return string |
|
155 */ |
|
156 public function getMethod() |
|
157 { |
|
158 return $this->_method; |
|
159 } |
|
160 |
|
161 /** |
|
162 * Add a parameter to the parameter stack |
|
163 * |
|
164 * Adds a parameter to the parameter stack, associating it with the type |
|
165 * $type if provided |
|
166 * |
|
167 * @param mixed $value |
|
168 * @param string $type Optional; type hinting |
|
169 * @return void |
|
170 */ |
|
171 public function addParam($value, $type = null) |
|
172 { |
|
173 $this->_params[] = $value; |
|
174 if (null === $type) { |
|
175 // Detect type if not provided explicitly |
|
176 if ($value instanceof Zend_XmlRpc_Value) { |
|
177 $type = $value->getType(); |
|
178 } else { |
|
179 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($value); |
|
180 $type = $xmlRpcValue->getType(); |
|
181 } |
|
182 } |
|
183 $this->_types[] = $type; |
|
184 $this->_xmlRpcParams[] = array('value' => $value, 'type' => $type); |
|
185 } |
|
186 |
|
187 /** |
|
188 * Set the parameters array |
|
189 * |
|
190 * If called with a single, array value, that array is used to set the |
|
191 * parameters stack. If called with multiple values or a single non-array |
|
192 * value, the arguments are used to set the parameters stack. |
|
193 * |
|
194 * Best is to call with array of the format, in order to allow type hinting |
|
195 * when creating the XMLRPC values for each parameter: |
|
196 * <code> |
|
197 * $array = array( |
|
198 * array( |
|
199 * 'value' => $value, |
|
200 * 'type' => $type |
|
201 * )[, ... ] |
|
202 * ); |
|
203 * </code> |
|
204 * |
|
205 * @access public |
|
206 * @return void |
|
207 */ |
|
208 public function setParams() |
|
209 { |
|
210 $argc = func_num_args(); |
|
211 $argv = func_get_args(); |
|
212 if (0 == $argc) { |
|
213 return; |
|
214 } |
|
215 |
|
216 if ((1 == $argc) && is_array($argv[0])) { |
|
217 $params = array(); |
|
218 $types = array(); |
|
219 $wellFormed = true; |
|
220 foreach ($argv[0] as $arg) { |
|
221 if (!is_array($arg) || !isset($arg['value'])) { |
|
222 $wellFormed = false; |
|
223 break; |
|
224 } |
|
225 $params[] = $arg['value']; |
|
226 |
|
227 if (!isset($arg['type'])) { |
|
228 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg['value']); |
|
229 $arg['type'] = $xmlRpcValue->getType(); |
|
230 } |
|
231 $types[] = $arg['type']; |
|
232 } |
|
233 if ($wellFormed) { |
|
234 $this->_xmlRpcParams = $argv[0]; |
|
235 $this->_params = $params; |
|
236 $this->_types = $types; |
|
237 } else { |
|
238 $this->_params = $argv[0]; |
|
239 $this->_types = array(); |
|
240 $xmlRpcParams = array(); |
|
241 foreach ($argv[0] as $arg) { |
|
242 if ($arg instanceof Zend_XmlRpc_Value) { |
|
243 $type = $arg->getType(); |
|
244 } else { |
|
245 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg); |
|
246 $type = $xmlRpcValue->getType(); |
|
247 } |
|
248 $xmlRpcParams[] = array('value' => $arg, 'type' => $type); |
|
249 $this->_types[] = $type; |
|
250 } |
|
251 $this->_xmlRpcParams = $xmlRpcParams; |
|
252 } |
|
253 return; |
|
254 } |
|
255 |
|
256 $this->_params = $argv; |
|
257 $this->_types = array(); |
|
258 $xmlRpcParams = array(); |
|
259 foreach ($argv as $arg) { |
|
260 if ($arg instanceof Zend_XmlRpc_Value) { |
|
261 $type = $arg->getType(); |
|
262 } else { |
|
263 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg); |
|
264 $type = $xmlRpcValue->getType(); |
|
265 } |
|
266 $xmlRpcParams[] = array('value' => $arg, 'type' => $type); |
|
267 $this->_types[] = $type; |
|
268 } |
|
269 $this->_xmlRpcParams = $xmlRpcParams; |
|
270 } |
|
271 |
|
272 /** |
|
273 * Retrieve the array of parameters |
|
274 * |
|
275 * @return array |
|
276 */ |
|
277 public function getParams() |
|
278 { |
|
279 return $this->_params; |
|
280 } |
|
281 |
|
282 /** |
|
283 * Return parameter types |
|
284 * |
|
285 * @return array |
|
286 */ |
|
287 public function getTypes() |
|
288 { |
|
289 return $this->_types; |
|
290 } |
|
291 |
|
292 /** |
|
293 * Load XML and parse into request components |
|
294 * |
|
295 * @param string $request |
|
296 * @return boolean True on success, false if an error occurred. |
|
297 */ |
|
298 public function loadXml($request) |
|
299 { |
|
300 if (!is_string($request)) { |
|
301 $this->_fault = new Zend_XmlRpc_Fault(635); |
|
302 $this->_fault->setEncoding($this->getEncoding()); |
|
303 return false; |
|
304 } |
|
305 |
|
306 try { |
|
307 $xml = new SimpleXMLElement($request); |
|
308 } catch (Exception $e) { |
|
309 // Not valid XML |
|
310 $this->_fault = new Zend_XmlRpc_Fault(631); |
|
311 $this->_fault->setEncoding($this->getEncoding()); |
|
312 return false; |
|
313 } |
|
314 |
|
315 // Check for method name |
|
316 if (empty($xml->methodName)) { |
|
317 // Missing method name |
|
318 $this->_fault = new Zend_XmlRpc_Fault(632); |
|
319 $this->_fault->setEncoding($this->getEncoding()); |
|
320 return false; |
|
321 } |
|
322 |
|
323 $this->_method = (string) $xml->methodName; |
|
324 |
|
325 // Check for parameters |
|
326 if (!empty($xml->params)) { |
|
327 $types = array(); |
|
328 $argv = array(); |
|
329 foreach ($xml->params->children() as $param) { |
|
330 if (!isset($param->value)) { |
|
331 $this->_fault = new Zend_XmlRpc_Fault(633); |
|
332 $this->_fault->setEncoding($this->getEncoding()); |
|
333 return false; |
|
334 } |
|
335 |
|
336 try { |
|
337 $param = Zend_XmlRpc_Value::getXmlRpcValue($param->value, Zend_XmlRpc_Value::XML_STRING); |
|
338 $types[] = $param->getType(); |
|
339 $argv[] = $param->getValue(); |
|
340 } catch (Exception $e) { |
|
341 $this->_fault = new Zend_XmlRpc_Fault(636); |
|
342 $this->_fault->setEncoding($this->getEncoding()); |
|
343 return false; |
|
344 } |
|
345 } |
|
346 |
|
347 $this->_types = $types; |
|
348 $this->_params = $argv; |
|
349 } |
|
350 |
|
351 $this->_xml = $request; |
|
352 |
|
353 return true; |
|
354 } |
|
355 |
|
356 /** |
|
357 * Does the current request contain errors and should it return a fault |
|
358 * response? |
|
359 * |
|
360 * @return boolean |
|
361 */ |
|
362 public function isFault() |
|
363 { |
|
364 return $this->_fault instanceof Zend_XmlRpc_Fault; |
|
365 } |
|
366 |
|
367 /** |
|
368 * Retrieve the fault response, if any |
|
369 * |
|
370 * @return null|Zend_XmlRpc_Fault |
|
371 */ |
|
372 public function getFault() |
|
373 { |
|
374 return $this->_fault; |
|
375 } |
|
376 |
|
377 /** |
|
378 * Retrieve method parameters as XMLRPC values |
|
379 * |
|
380 * @return array |
|
381 */ |
|
382 protected function _getXmlRpcParams() |
|
383 { |
|
384 $params = array(); |
|
385 if (is_array($this->_xmlRpcParams)) { |
|
386 foreach ($this->_xmlRpcParams as $param) { |
|
387 $value = $param['value']; |
|
388 $type = isset($param['type']) ? $param['type'] : Zend_XmlRpc_Value::AUTO_DETECT_TYPE; |
|
389 |
|
390 if (!$value instanceof Zend_XmlRpc_Value) { |
|
391 $value = Zend_XmlRpc_Value::getXmlRpcValue($value, $type); |
|
392 } |
|
393 $params[] = $value; |
|
394 } |
|
395 } |
|
396 |
|
397 return $params; |
|
398 } |
|
399 |
|
400 /** |
|
401 * Create XML request |
|
402 * |
|
403 * @return string |
|
404 */ |
|
405 public function saveXml() |
|
406 { |
|
407 $args = $this->_getXmlRpcParams(); |
|
408 $method = $this->getMethod(); |
|
409 |
|
410 $generator = Zend_XmlRpc_Value::getGenerator(); |
|
411 $generator->openElement('methodCall') |
|
412 ->openElement('methodName', $method) |
|
413 ->closeElement('methodName'); |
|
414 |
|
415 if (is_array($args) && count($args)) { |
|
416 $generator->openElement('params'); |
|
417 |
|
418 foreach ($args as $arg) { |
|
419 $generator->openElement('param'); |
|
420 $arg->generateXml(); |
|
421 $generator->closeElement('param'); |
|
422 } |
|
423 $generator->closeElement('params'); |
|
424 } |
|
425 $generator->closeElement('methodCall'); |
|
426 |
|
427 return $generator->flush(); |
|
428 } |
|
429 |
|
430 /** |
|
431 * Return XML request |
|
432 * |
|
433 * @return string |
|
434 */ |
|
435 public function __toString() |
|
436 { |
|
437 return $this->saveXML(); |
|
438 } |
|
439 } |