1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PhpXmlRpc; |
4
|
|
|
|
5
|
|
|
use PhpXmlRpc\Helper\Charset; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* This class enables the creation of values for XML-RPC, by encapsulating plain php values. |
9
|
|
|
*/ |
10
|
|
|
class Value implements \Countable, \IteratorAggregate, \ArrayAccess |
11
|
|
|
{ |
12
|
|
|
public static $xmlrpcI4 = "i4"; |
13
|
|
|
public static $xmlrpcI8 = "i8"; |
14
|
|
|
public static $xmlrpcInt = "int"; |
15
|
|
|
public static $xmlrpcBoolean = "boolean"; |
16
|
|
|
public static $xmlrpcDouble = "double"; |
17
|
|
|
public static $xmlrpcString = "string"; |
18
|
|
|
public static $xmlrpcDateTime = "dateTime.iso8601"; |
19
|
|
|
public static $xmlrpcBase64 = "base64"; |
20
|
|
|
public static $xmlrpcArray = "array"; |
21
|
|
|
public static $xmlrpcStruct = "struct"; |
22
|
|
|
public static $xmlrpcValue = "undefined"; |
23
|
|
|
public static $xmlrpcNull = "null"; |
24
|
|
|
|
25
|
|
|
public static $xmlrpcTypes = array( |
26
|
|
|
"i4" => 1, |
27
|
|
|
"i8" => 1, |
28
|
|
|
"int" => 1, |
29
|
|
|
"boolean" => 1, |
30
|
|
|
"double" => 1, |
31
|
|
|
"string" => 1, |
32
|
|
|
"dateTime.iso8601" => 1, |
33
|
|
|
"base64" => 1, |
34
|
|
|
"array" => 2, |
35
|
|
|
"struct" => 3, |
36
|
|
|
"null" => 1, |
37
|
|
|
); |
38
|
|
|
|
39
|
|
|
/// @todo: do these need to be public? |
40
|
|
|
public $me = array(); |
41
|
|
|
public $mytype = 0; |
42
|
|
|
public $_php_class = null; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Build an xmlrpc value. |
46
|
|
|
* |
47
|
|
|
* When no value or type is passed in, the value is left uninitialized, and the value can be added later. |
48
|
|
|
* |
49
|
|
|
* @param mixed $val if passing in an array, all array elements should be PhpXmlRpc\Value themselves |
50
|
|
|
* @param string $type any valid xmlrpc type name (lowercase): i4, int, boolean, string, double, dateTime.iso8601, |
51
|
|
|
* base64, array, struct, null. |
52
|
|
|
* If null, 'string' is assumed. |
53
|
|
|
* You should refer to http://www.xmlrpc.com/spec for more information on what each of these mean. |
54
|
|
|
*/ |
55
|
619 |
|
public function __construct($val = -1, $type = '') |
56
|
|
|
{ |
57
|
|
|
// optimization creep - do not call addXX, do it all inline. |
58
|
|
|
// downside: booleans will not be coerced anymore |
59
|
619 |
|
if ($val !== -1 || $type != '') { |
60
|
618 |
|
switch ($type) { |
61
|
618 |
|
case '': |
62
|
258 |
|
$this->mytype = 1; |
63
|
258 |
|
$this->me['string'] = $val; |
64
|
258 |
|
break; |
65
|
612 |
|
case 'i4': |
66
|
612 |
|
case 'i8': |
67
|
612 |
|
case 'int': |
68
|
558 |
|
case 'double': |
69
|
539 |
|
case 'string': |
70
|
378 |
|
case 'boolean': |
71
|
361 |
|
case 'dateTime.iso8601': |
72
|
342 |
|
case 'base64': |
73
|
323 |
|
case 'null': |
74
|
591 |
|
$this->mytype = 1; |
75
|
591 |
|
$this->me[$type] = $val; |
76
|
591 |
|
break; |
77
|
320 |
|
case 'array': |
78
|
202 |
|
$this->mytype = 2; |
79
|
202 |
|
$this->me['array'] = $val; |
80
|
202 |
|
break; |
81
|
228 |
|
case 'struct': |
82
|
228 |
|
$this->mytype = 3; |
83
|
228 |
|
$this->me['struct'] = $val; |
84
|
228 |
|
break; |
85
|
|
|
default: |
86
|
|
|
error_log("XML-RPC: " . __METHOD__ . ": not a known type ($type)"); |
87
|
|
|
} |
88
|
|
|
} |
89
|
619 |
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Add a single php value to an xmlrpc value. |
93
|
|
|
* |
94
|
|
|
* If the xmlrpc value is an array, the php value is added as its last element. |
95
|
|
|
* If the xmlrpc value is empty (uninitialized), this method makes it a scalar value, and sets that value. |
96
|
|
|
* Fails if the xmlrpc value is not an array and already initialized. |
97
|
|
|
* |
98
|
|
|
* @param mixed $val |
99
|
|
|
* @param string $type allowed values: i4, i8, int, boolean, string, double, dateTime.iso8601, base64, null. |
100
|
|
|
* |
101
|
|
|
* @return int 1 or 0 on failure |
102
|
|
|
*/ |
103
|
1 |
|
public function addScalar($val, $type = 'string') |
104
|
|
|
{ |
105
|
1 |
|
$typeOf = null; |
106
|
1 |
|
if (isset(static::$xmlrpcTypes[$type])) { |
107
|
1 |
|
$typeOf = static::$xmlrpcTypes[$type]; |
108
|
|
|
} |
109
|
|
|
|
110
|
1 |
|
if ($typeOf !== 1) { |
111
|
|
|
error_log("XML-RPC: " . __METHOD__ . ": not a scalar type ($type)"); |
112
|
|
|
return 0; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
// coerce booleans into correct values |
116
|
|
|
// NB: we should either do it for datetimes, integers, i8 and doubles, too, |
117
|
|
|
// or just plain remove this check, implemented on booleans only... |
118
|
1 |
|
if ($type == static::$xmlrpcBoolean) { |
119
|
|
|
if (strcasecmp($val, 'true') == 0 || $val == 1 || ($val == true && strcasecmp($val, 'false'))) { |
120
|
|
|
$val = true; |
121
|
|
|
} else { |
122
|
|
|
$val = false; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
|
126
|
1 |
|
switch ($this->mytype) { |
127
|
1 |
|
case 1: |
128
|
|
|
error_log('XML-RPC: ' . __METHOD__ . ': scalar xmlrpc value can have only one value'); |
129
|
|
|
return 0; |
130
|
1 |
|
case 3: |
131
|
1 |
|
error_log('XML-RPC: ' . __METHOD__ . ': cannot add anonymous scalar to struct xmlrpc value'); |
132
|
1 |
|
return 0; |
133
|
|
|
case 2: |
134
|
|
|
// we're adding a scalar value to an array here |
135
|
|
|
$this->me['array'][] = new Value($val, $type); |
136
|
|
|
|
137
|
|
|
return 1; |
138
|
|
|
default: |
139
|
|
|
// a scalar, so set the value and remember we're scalar |
140
|
|
|
$this->me[$type] = $val; |
141
|
|
|
$this->mytype = $typeOf; |
142
|
|
|
|
143
|
|
|
return 1; |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Add an array of xmlrpc value objects to an xmlrpc value. |
149
|
|
|
* |
150
|
|
|
* If the xmlrpc value is an array, the elements are appended to the existing ones. |
151
|
|
|
* If the xmlrpc value is empty (uninitialized), this method makes it an array value, and sets that value. |
152
|
|
|
* Fails otherwise. |
153
|
|
|
* |
154
|
|
|
* @param Value[] $values |
155
|
|
|
* |
156
|
|
|
* @return int 1 or 0 on failure |
157
|
|
|
* |
158
|
|
|
* @todo add some checking for $values to be an array of xmlrpc values? |
159
|
|
|
*/ |
160
|
1 |
View Code Duplication |
public function addArray($values) |
|
|
|
|
161
|
|
|
{ |
162
|
1 |
|
if ($this->mytype == 0) { |
163
|
|
|
$this->mytype = static::$xmlrpcTypes['array']; |
164
|
|
|
$this->me['array'] = $values; |
165
|
|
|
|
166
|
|
|
return 1; |
167
|
1 |
|
} elseif ($this->mytype == 2) { |
168
|
|
|
// we're adding to an array here |
169
|
1 |
|
$this->me['array'] = array_merge($this->me['array'], $values); |
170
|
|
|
|
171
|
1 |
|
return 1; |
172
|
|
|
} else { |
173
|
|
|
error_log('XML-RPC: ' . __METHOD__ . ': already initialized as a [' . $this->kindOf() . ']'); |
174
|
|
|
return 0; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Merges an array of named xmlrpc value objects into an xmlrpc value. |
180
|
|
|
* |
181
|
|
|
* If the xmlrpc value is a struct, the elements are merged with the existing ones (overwriting existing ones). |
182
|
|
|
* If the xmlrpc value is empty (uninitialized), this method makes it a struct value, and sets that value. |
183
|
|
|
* Fails otherwise. |
184
|
|
|
* |
185
|
|
|
* @param Value[] $values |
186
|
|
|
* |
187
|
|
|
* @return int 1 or 0 on failure |
188
|
|
|
* |
189
|
|
|
* @todo add some checking for $values to be an array? |
190
|
|
|
*/ |
191
|
1 |
View Code Duplication |
public function addStruct($values) |
|
|
|
|
192
|
|
|
{ |
193
|
1 |
|
if ($this->mytype == 0) { |
194
|
|
|
$this->mytype = static::$xmlrpcTypes['struct']; |
195
|
|
|
$this->me['struct'] = $values; |
196
|
|
|
|
197
|
|
|
return 1; |
198
|
1 |
|
} elseif ($this->mytype == 3) { |
199
|
|
|
// we're adding to a struct here |
200
|
1 |
|
$this->me['struct'] = array_merge($this->me['struct'], $values); |
201
|
|
|
|
202
|
1 |
|
return 1; |
203
|
|
|
} else { |
204
|
|
|
error_log('XML-RPC: ' . __METHOD__ . ': already initialized as a [' . $this->kindOf() . ']'); |
205
|
|
|
return 0; |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Returns a string containing either "struct", "array", "scalar" or "undef", describing the base type of the value. |
211
|
|
|
* |
212
|
|
|
* @return string |
213
|
|
|
*/ |
214
|
489 |
|
public function kindOf() |
215
|
|
|
{ |
216
|
489 |
|
switch ($this->mytype) { |
217
|
489 |
|
case 3: |
218
|
120 |
|
return 'struct'; |
219
|
|
|
break; |
|
|
|
|
220
|
472 |
|
case 2: |
221
|
172 |
|
return 'array'; |
222
|
|
|
break; |
|
|
|
|
223
|
454 |
|
case 1: |
224
|
454 |
|
return 'scalar'; |
225
|
|
|
break; |
|
|
|
|
226
|
|
|
default: |
227
|
|
|
return 'undef'; |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
231
|
584 |
|
protected function serializedata($typ, $val, $charsetEncoding = '') |
232
|
|
|
{ |
233
|
584 |
|
$rs = ''; |
234
|
|
|
|
235
|
584 |
|
if (!isset(static::$xmlrpcTypes[$typ])) { |
236
|
2 |
|
return $rs; |
237
|
|
|
} |
238
|
|
|
|
239
|
584 |
|
switch (static::$xmlrpcTypes[$typ]) { |
240
|
584 |
|
case 1: |
241
|
|
|
switch ($typ) { |
242
|
567 |
|
case static::$xmlrpcBase64: |
243
|
20 |
|
$rs .= "<${typ}>" . base64_encode($val) . "</${typ}>"; |
244
|
20 |
|
break; |
245
|
565 |
|
case static::$xmlrpcBoolean: |
246
|
38 |
|
$rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>"; |
247
|
38 |
|
break; |
248
|
546 |
|
case static::$xmlrpcString: |
249
|
|
|
// G. Giunta 2005/2/13: do NOT use htmlentities, since |
250
|
|
|
// it will produce named html entities, which are invalid xml |
251
|
451 |
|
$rs .= "<${typ}>" . Charset::instance()->encodeEntities($val, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</${typ}>"; |
252
|
451 |
|
break; |
253
|
396 |
|
case static::$xmlrpcInt: |
254
|
60 |
|
case static::$xmlrpcI4: |
255
|
60 |
|
case static::$xmlrpcI8: |
256
|
357 |
|
$rs .= "<${typ}>" . (int)$val . "</${typ}>"; |
257
|
357 |
|
break; |
258
|
60 |
|
case static::$xmlrpcDouble: |
259
|
|
|
// avoid using standard conversion of float to string because it is locale-dependent, |
260
|
|
|
// and also because the xmlrpc spec forbids exponential notation. |
261
|
|
|
// sprintf('%F') could be most likely ok but it fails eg. on 2e-14. |
262
|
|
|
// The code below tries its best at keeping max precision while avoiding exp notation, |
263
|
|
|
// but there is of course no limit in the number of decimal places to be used... |
264
|
21 |
|
$rs .= "<${typ}>" . preg_replace('/\\.?0+$/', '', number_format((double)$val, 128, '.', '')) . "</${typ}>"; |
265
|
21 |
|
break; |
266
|
41 |
|
case static::$xmlrpcDateTime: |
267
|
21 |
|
if (is_string($val)) { |
268
|
21 |
|
$rs .= "<${typ}>${val}</${typ}>"; |
269
|
20 |
|
} elseif (is_a($val, 'DateTime')) { |
270
|
20 |
|
$rs .= "<${typ}>" . $val->format('Ymd\TH:i:s') . "</${typ}>"; |
271
|
20 |
|
} elseif (is_int($val)) { |
272
|
20 |
|
$rs .= "<${typ}>" . strftime("%Y%m%dT%H:%M:%S", $val) . "</${typ}>"; |
273
|
|
|
} else { |
274
|
|
|
// not really a good idea here: but what shall we output anyway? left for backward compat... |
275
|
|
|
$rs .= "<${typ}>${val}</${typ}>"; |
276
|
|
|
} |
277
|
21 |
|
break; |
278
|
21 |
|
case static::$xmlrpcNull: |
279
|
21 |
|
if (PhpXmlRpc::$xmlrpc_null_apache_encoding) { |
280
|
21 |
|
$rs .= "<ex:nil/>"; |
281
|
|
|
} else { |
282
|
1 |
|
$rs .= "<nil/>"; |
283
|
|
|
} |
284
|
21 |
|
break; |
285
|
|
|
default: |
286
|
|
|
// no standard type value should arrive here, but provide a possibility |
287
|
|
|
// for xmlrpc values of unknown type... |
288
|
|
|
$rs .= "<${typ}>${val}</${typ}>"; |
289
|
|
|
} |
290
|
567 |
|
break; |
291
|
185 |
|
case 3: |
292
|
|
|
// struct |
293
|
113 |
|
if ($this->_php_class) { |
294
|
1 |
|
$rs .= '<struct php_class="' . $this->_php_class . "\">\n"; |
295
|
|
|
} else { |
296
|
113 |
|
$rs .= "<struct>\n"; |
297
|
|
|
} |
298
|
113 |
|
$charsetEncoder = Charset::instance(); |
299
|
|
|
/** @var Value $val2 */ |
300
|
113 |
|
foreach ($val as $key2 => $val2) { |
301
|
96 |
|
$rs .= '<member><name>' . $charsetEncoder->encodeEntities($key2, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</name>\n"; |
302
|
|
|
//$rs.=$this->serializeval($val2); |
303
|
96 |
|
$rs .= $val2->serialize($charsetEncoding); |
304
|
96 |
|
$rs .= "</member>\n"; |
305
|
|
|
} |
306
|
113 |
|
$rs .= '</struct>'; |
307
|
113 |
|
break; |
308
|
131 |
|
case 2: |
309
|
|
|
// array |
310
|
131 |
|
$rs .= "<array>\n<data>\n"; |
311
|
|
|
/** @var Value $element */ |
312
|
131 |
|
foreach ($val as $element) { |
313
|
|
|
//$rs.=$this->serializeval($val[$i]); |
314
|
129 |
|
$rs .= $element->serialize($charsetEncoding); |
315
|
|
|
} |
316
|
131 |
|
$rs .= "</data>\n</array>"; |
317
|
131 |
|
break; |
318
|
|
|
default: |
319
|
|
|
break; |
320
|
|
|
} |
321
|
|
|
|
322
|
584 |
|
return $rs; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Returns the xml representation of the value. XML prologue not included. |
327
|
|
|
* |
328
|
|
|
* @param string $charsetEncoding the charset to be used for serialization. if null, US-ASCII is assumed |
329
|
|
|
* |
330
|
|
|
* @return string |
331
|
|
|
*/ |
332
|
|
|
public function serialize($charsetEncoding = '') |
333
|
|
|
{ |
334
|
584 |
|
$val = reset($this->me); |
335
|
584 |
|
$typ = key($this->me); |
336
|
|
|
|
337
|
584 |
|
return '<value>' . $this->serializedata($typ, $val, $charsetEncoding) . "</value>\n"; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Checks whether a struct member with a given name is present. |
342
|
|
|
* |
343
|
|
|
* Works only on xmlrpc values of type struct. |
344
|
|
|
* |
345
|
|
|
* @param string $key the name of the struct member to be looked up |
346
|
|
|
* |
347
|
|
|
* @return boolean |
348
|
|
|
* |
349
|
|
|
* @deprecated use array access, e.g. isset($val[$key]) |
350
|
|
|
*/ |
351
|
|
|
public function structmemexists($key) |
352
|
|
|
{ |
353
|
2 |
|
return array_key_exists($key, $this->me['struct']); |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
/** |
357
|
|
|
* Returns the value of a given struct member (an xmlrpc value object in itself). |
358
|
|
|
* Will raise a php warning if struct member of given name does not exist. |
359
|
|
|
* |
360
|
|
|
* @param string $key the name of the struct member to be looked up |
361
|
|
|
* |
362
|
|
|
* @return Value |
363
|
|
|
* |
364
|
|
|
* @deprecated use array access, e.g. $val[$key] |
365
|
|
|
*/ |
366
|
|
|
public function structmem($key) |
367
|
|
|
{ |
368
|
25 |
|
return $this->me['struct'][$key]; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
/** |
372
|
|
|
* Reset internal pointer for xmlrpc values of type struct. |
373
|
|
|
* @deprecated iterate directly over the object using foreach instead |
374
|
|
|
*/ |
375
|
|
|
public function structreset() |
376
|
|
|
{ |
377
|
|
|
reset($this->me['struct']); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Return next member element for xmlrpc values of type struct. |
382
|
|
|
* |
383
|
|
|
* @return Value |
384
|
|
|
* |
385
|
|
|
* @deprecated iterate directly over the object using foreach instead |
386
|
|
|
*/ |
387
|
|
|
public function structeach() |
388
|
|
|
{ |
389
|
|
|
return each($this->me['struct']); |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
/** |
393
|
|
|
* Returns the value of a scalar xmlrpc value (base 64 decoding is automatically handled here) |
394
|
|
|
* |
395
|
|
|
* @return mixed |
396
|
|
|
*/ |
397
|
|
|
public function scalarval() |
398
|
|
|
{ |
399
|
500 |
|
$b = reset($this->me); |
400
|
|
|
|
401
|
500 |
|
return $b; |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Returns the type of the xmlrpc value. |
406
|
|
|
* |
407
|
|
|
* For integers, 'int' is always returned in place of 'i4'. 'i8' is considered a separate type and returned as such |
408
|
|
|
* |
409
|
|
|
* @return string |
410
|
|
|
*/ |
411
|
|
|
public function scalartyp() |
412
|
|
|
{ |
413
|
352 |
|
reset($this->me); |
414
|
352 |
|
$a = key($this->me); |
415
|
352 |
|
if ($a == static::$xmlrpcI4) { |
416
|
|
|
$a = static::$xmlrpcInt; |
417
|
|
|
} |
418
|
|
|
|
419
|
352 |
|
return $a; |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* Returns the m-th member of an xmlrpc value of array type. |
424
|
|
|
* |
425
|
|
|
* @param integer $key the index of the value to be retrieved (zero based) |
426
|
|
|
* |
427
|
|
|
* @return Value |
428
|
|
|
* |
429
|
|
|
* @deprecated use array access, e.g. $val[$key] |
430
|
|
|
*/ |
431
|
|
|
public function arraymem($key) |
432
|
|
|
{ |
433
|
35 |
|
return $this->me['array'][$key]; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Returns the number of members in an xmlrpc value of array type. |
438
|
|
|
* |
439
|
|
|
* @return integer |
440
|
|
|
* |
441
|
|
|
* @deprecated use count() instead |
442
|
|
|
*/ |
443
|
|
|
public function arraysize() |
444
|
|
|
{ |
445
|
36 |
|
return count($this->me['array']); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
/** |
449
|
|
|
* Returns the number of members in an xmlrpc value of struct type. |
450
|
|
|
* |
451
|
|
|
* @return integer |
452
|
|
|
* |
453
|
|
|
* @deprecated use count() instead |
454
|
|
|
*/ |
455
|
|
|
public function structsize() |
456
|
|
|
{ |
457
|
19 |
|
return count($this->me['struct']); |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Returns the number of members in an xmlrpc value: |
462
|
|
|
* - 0 for uninitialized values |
463
|
|
|
* - 1 for scalar values |
464
|
|
|
* - the number of elements for struct and array values |
465
|
|
|
* |
466
|
|
|
* @return integer |
467
|
|
|
*/ |
468
|
|
|
public function count() |
469
|
|
|
{ |
470
|
19 |
|
switch ($this->mytype) { |
471
|
19 |
|
case 3: |
472
|
|
|
return count($this->me['struct']); |
473
|
19 |
|
case 2: |
474
|
19 |
|
return count($this->me['array']); |
475
|
|
|
case 1: |
476
|
|
|
return 1; |
477
|
|
|
default: |
478
|
|
|
return 0; |
479
|
|
|
} |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
/** |
483
|
|
|
* Implements the IteratorAggregate interface |
484
|
|
|
* |
485
|
|
|
* @return \ArrayIterator |
486
|
|
|
*/ |
487
|
|
|
public function getIterator() { |
488
|
206 |
|
switch ($this->mytype) { |
489
|
206 |
|
case 3: |
490
|
52 |
|
return new \ArrayIterator($this->me['struct']); |
491
|
172 |
|
case 2: |
492
|
172 |
|
return new \ArrayIterator($this->me['array']); |
493
|
|
|
case 1: |
494
|
|
|
return new \ArrayIterator($this->me); |
495
|
|
|
default: |
496
|
|
|
return new \ArrayIterator(); |
497
|
|
|
} |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
public function offsetSet($offset, $value) { |
501
|
|
|
|
502
|
18 |
|
switch ($this->mytype) { |
503
|
18 |
|
case 3: |
504
|
|
|
if (!($value instanceof \PhpXmlRpc\Value)) { |
505
|
|
|
throw new \Exception('It is only possible to add Value objects to an XML-RPC Struct'); |
506
|
|
|
} |
507
|
|
|
if (is_null($offset)) { |
508
|
|
|
// disallow struct members with empty names |
509
|
|
|
throw new \Exception('It is not possible to add anonymous members to an XML-RPC Struct'); |
510
|
|
|
} else { |
511
|
|
|
$this->me['struct'][$offset] = $value; |
512
|
|
|
} |
513
|
|
|
return; |
514
|
18 |
|
case 2: |
515
|
18 |
|
if (!($value instanceof \PhpXmlRpc\Value)) { |
516
|
|
|
throw new \Exception('It is only possible to add Value objects to an XML-RPC Array'); |
517
|
|
|
} |
518
|
18 |
|
if (is_null($offset)) { |
519
|
18 |
|
$this->me['array'][] = $value; |
520
|
|
|
} else { |
521
|
|
|
// nb: we are not checking that $offset is above the existing array range... |
522
|
|
|
$this->me['array'][$offset] = $value; |
523
|
|
|
} |
524
|
18 |
|
return; |
525
|
|
|
case 1: |
526
|
|
|
// todo: handle i4 vs int |
527
|
|
|
reset($this->me); |
528
|
|
|
$type = key($this->me); |
529
|
|
|
if ($type != $offset) { |
530
|
|
|
throw new \Exception(''); |
531
|
|
|
} |
532
|
|
|
$this->me[$type] = $value; |
533
|
|
|
return; |
534
|
|
|
default: |
535
|
|
|
// it would be nice to allow empty values to be be turned into non-empty ones this way, but we miss info to do so |
536
|
|
|
throw new \Exception("XML-RPC Value is of type 'undef' and its value can not be set using array index"); |
537
|
|
|
} |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
public function offsetExists($offset) { |
541
|
|
|
switch ($this->mytype) { |
542
|
|
|
case 3: |
543
|
|
|
return isset($this->me['struct'][$offset]); |
544
|
|
|
case 2: |
545
|
|
|
return isset($this->me['array'][$offset]); |
546
|
|
|
case 1: |
547
|
|
|
// todo: handle i4 vs int |
548
|
|
|
return $offset == $this->scalartyp(); |
549
|
|
|
default: |
550
|
|
|
return false; |
551
|
|
|
} |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
public function offsetUnset($offset) { |
555
|
|
|
switch ($this->mytype) { |
556
|
|
|
case 3: |
557
|
|
|
unset($this->me['struct'][$offset]); |
558
|
|
|
return; |
559
|
|
|
case 2: |
560
|
|
|
unset($this->me['array'][$offset]); |
561
|
|
|
return; |
562
|
|
|
case 1: |
563
|
|
|
// can not remove value from a scalar |
564
|
|
|
throw new \Exception("XML-RPC Value is of type 'scalar' and its value can not be unset using array index"); |
565
|
|
|
default: |
566
|
|
|
throw new \Exception("XML-RPC Value is of type 'undef' and its value can not be unset using array index"); |
567
|
|
|
} |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
public function offsetGet($offset) { |
571
|
123 |
|
switch ($this->mytype) { |
572
|
123 |
|
case 3: |
573
|
123 |
|
return isset($this->me['struct'][$offset]) ? $this->me['struct'][$offset] : null; |
574
|
18 |
|
case 2: |
575
|
18 |
|
return isset($this->me['array'][$offset]) ? $this->me['array'][$offset] : null; |
576
|
|
|
case 1: |
577
|
|
|
// on bad type: null or exception? |
578
|
|
|
$value = reset($this->me); |
579
|
|
|
$type = key($this->me); |
580
|
|
|
return $type == $offset ? $value : null; |
581
|
|
|
default: |
582
|
|
|
// return null or exception? |
583
|
|
|
throw new \Exception("XML-RPC Value is of type 'undef' and can not be accessed using array index"); |
584
|
|
|
} |
585
|
|
|
} |
586
|
|
|
} |
587
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.