Value   F
last analyzed

Complexity

Total Complexity 123

Size/Duplication

Total Lines 721
Duplicated Lines 0 %

Test Coverage

Coverage 65.49%

Importance

Changes 18
Bugs 4 Features 2
Metric Value
eloc 329
c 18
b 4
f 2
dl 0
loc 721
ccs 167
cts 255
cp 0.6549
rs 2
wmc 123

26 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetExists() 0 19 5
B offsetSet() 0 39 11
A structEach() 0 8 1
A structMemExists() 0 5 1
A structMem() 0 5 1
A offsetUnset() 0 16 4
A structSize() 0 5 1
A arrayMem() 0 5 1
A arraySize() 0 5 1
A structReset() 0 5 1
B addScalar() 0 43 11
A serialize() 0 6 1
A getIterator() 0 12 4
A scalarVal() 0 5 1
A scalarTyp() 0 9 2
D serializeData() 0 92 23
A kindOf() 0 11 4
A addArray() 0 15 3
A addStruct() 0 15 3
A count() 0 12 4
C __construct() 0 32 15
A __set() 0 13 4
A __isset() 0 10 4
A __unset() 0 13 4
A __get() 0 14 4
B offsetGet() 0 16 9

How to fix   Complexity   

Complex Class

Complex classes like Value often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Value, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace PhpXmlRpc;
4
5
use PhpXmlRpc\Exception\StateErrorException;
6
use PhpXmlRpc\Exception\TypeErrorException;
7
use PhpXmlRpc\Exception\ValueErrorException;
8
use PhpXmlRpc\Traits\CharsetEncoderAware;
9
use PhpXmlRpc\Traits\DeprecationLogger;
10
11
/**
12
 * This class enables the creation of values for XML-RPC, by encapsulating plain php values.
13
 *
14
 * @property Value[]|mixed $me deprecated - public access left in purely for BC. Access via scalarVal()/__construct()
15
 * @property int $params $mytype - public access left in purely for BC. Access via kindOf()/__construct()
16
 * @property string|null $_php_class deprecated - public access left in purely for BC.
17
 */
18
class Value implements \Countable, \IteratorAggregate, \ArrayAccess
19
{
20
    use CharsetEncoderAware;
21
    use DeprecationLogger;
22
23
    public static $xmlrpcI4 = "i4";
24
    public static $xmlrpcI8 = "i8";
25
    public static $xmlrpcInt = "int";
26
    public static $xmlrpcBoolean = "boolean";
27
    public static $xmlrpcDouble = "double";
28
    public static $xmlrpcString = "string";
29
    public static $xmlrpcDateTime = "dateTime.iso8601";
30
    public static $xmlrpcBase64 = "base64";
31
    public static $xmlrpcArray = "array";
32
    public static $xmlrpcStruct = "struct";
33
    public static $xmlrpcValue = "undefined";
34
    public static $xmlrpcNull = "null";
35
36
    public static $xmlrpcTypes = array(
37
        "i4" => 1,
38
        "i8" => 1,
39
        "int" => 1,
40
        "boolean" => 1,
41
        "double" => 1,
42
        "string" => 1,
43
        "dateTime.iso8601" => 1,
44
        "base64" => 1,
45
        "array" => 2,
46
        "struct" => 3,
47
        "null" => 1,
48
    );
49
50
    /** @var Value[]|mixed */
51
    protected $me = array();
52
    /**
53
     * @var int 0 for undef, 1 for scalar, 2 for array, 3 for struct
54 1
     */
55
    protected $mytype = 0;
56 1
    /** @var string|null */
57 1
    protected $_php_class = null;
58
59 1
    /**
60
     * Build an xml-rpc value.
61
     *
62
     * When no value or type is passed in, the value is left uninitialized, and the value can be added later.
63
     *
64
     * @param Value[]|mixed $val if passing in an array, all array elements should be PhpXmlRpc\Value themselves
65
     * @param string $type any valid xml-rpc type name (lowercase): i4, int, boolean, string, double, dateTime.iso8601,
66
     *                     base64, array, struct, null.
67 594
     *                     If null, 'string' is assumed.
68
     *                     You should refer to http://xmlrpc.com/spec.md for more information on what each of these mean.
69 594
     */
70 435
    public function __construct($val = -1, $type = '')
71
    {
72 594
        // optimization creep - do not call addXX, do it all inline.
73
        // downside: booleans will not be coerced anymore
74
        if ($val !== -1 || $type != '') {
75
            switch ($type) {
76
                case '':
77
                    $this->mytype = 1;
78
                    $this->me['string'] = $val;
79
                    break;
80
                case 'i4':
81
                case 'i8':
82
                case 'int':
83
                case 'double':
84
                case 'string':
85
                case 'boolean':
86
                case 'dateTime.iso8601':
87
                case 'base64':
88
                case 'null':
89
                    $this->mytype = 1;
90
                    $this->me[$type] = $val;
91 746
                    break;
92
                case 'array':
93
                    $this->mytype = 2;
94
                    $this->me['array'] = $val;
95 746
                    break;
96 745
                case 'struct':
97 745
                    $this->mytype = 3;
98 251
                    $this->me['struct'] = $val;
99 251
                    break;
100 251
                default:
101 743
                    $this->getLogger()->error("XML-RPC: " . __METHOD__ . ": not a known type ($type)");
102 743
            }
103 743
        }
104 698
    }
105 677
106 469
    /**
107 448
     * Add a single php value to an xml-rpc value.
108 425
     *
109 404
     * If the xml-rpc value is an array, the php value is added as its last element.
110 717
     * If the xml-rpc value is empty (uninitialized), this method makes it a scalar value, and sets that value.
111 717
     * Fails if the xml-rpc value is not an array (i.e. a struct or a scalar) and already initialized.
112 717
     *
113 403
     * @param mixed $val
114 241
     * @param string $type allowed values: i4, i8, int, boolean, string, double, dateTime.iso8601, base64, null.
115 241
     * @return int 1 or 0 on failure
116 241
     *
117 295
     * @todo arguably, as we have addArray to add elements to an Array value, and addStruct to add elements to a Struct
118 295
     *       value, we should not allow this method to add values to an Array. The 'scalar' in the method name refers to
119 295
     *       the expected state of the target object, not to the type of $val. Also, this works differently from
120 295
     *       addScalar/addStruct in that, when adding an element to an array, it wraps it into a new Value
121
     * @todo rename?
122
     */
123
    public function addScalar($val, $type = 'string')
124
    {
125 746
        $typeOf = null;
126
        if (isset(static::$xmlrpcTypes[$type])) {
127
            $typeOf = static::$xmlrpcTypes[$type];
128
        }
129
130
        if ($typeOf !== 1) {
131
            $this->getLogger()->error("XML-RPC: " . __METHOD__ . ": not a scalar type ($type)");
132
            return 0;
133
        }
134
135
        // coerce booleans into correct values
136
        /// @todo we should either do it for datetimes, integers, i8 and doubles, too, or just plain remove this check,
137
        ///       implemented on booleans only...
138
        if ($type == static::$xmlrpcBoolean) {
139 1
            if (strcasecmp($val, 'true') == 0 || $val == 1 || ($val == true && strcasecmp($val, 'false'))) {
140
                $val = true;
141 1
            } else {
142 1
                $val = false;
143 1
            }
144
        }
145
146 1
        switch ($this->mytype) {
147
            case 1:
148
                $this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': scalar xmlrpc value can have only one value');
149
                return 0;
150
            case 3:
151
                $this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': cannot add anonymous scalar to struct xmlrpc value');
152
                return 0;
153
            case 2:
154 1
                // we're adding a scalar value to an array here
155
                /// @todo should we try avoiding re-wrapping Value objects?
156
                $class = get_class($this);
157
                $this->me['array'][] = new $class($val, $type);
158
159
                return 1;
160
            default:
161
                // a scalar, so set the value and remember we're scalar
162 1
                $this->me[$type] = $val;
163 1
                $this->mytype = $typeOf;
164
165
                return 1;
166 1
        }
167 1
    }
168 1
169
    /**
170
     * Add an array of xml-rpc value objects to an xml-rpc value.
171
     *
172
     * If the xml-rpc value is an array, the elements are appended to the existing ones.
173
     * If the xml-rpc value is empty (uninitialized), this method makes it an array value, and sets that value.
174
     * Fails otherwise.
175
     *
176
     * @param Value[] $values
177
     * @return int 1 or 0 on failure
178
     *
179
     * @todo add some checking for $values to be an array of xml-rpc values?
180
     * @todo rename to addToArray?
181
     */
182
    public function addArray($values)
183
    {
184
        if ($this->mytype == 0) {
185
            $this->mytype = static::$xmlrpcTypes['array'];
186
            $this->me['array'] = $values;
187
188
            return 1;
189
        } elseif ($this->mytype == 2) {
190
            // we're adding to an array here
191
            $this->me['array'] = array_merge($this->me['array'], $values);
192
193
            return 1;
194
        } else {
195
            $this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': already initialized as a [' . $this->kindOf() . ']');
196 1
            return 0;
197
        }
198 1
    }
199
200
    /**
201
     * Merges an array of named xml-rpc value objects into an xml-rpc value.
202
     *
203 1
     * If the xml-rpc value is a struct, the elements are merged with the existing ones (overwriting existing ones).
204
     * If the xml-rpc value is empty (uninitialized), this method makes it a struct value, and sets that value.
205 1
     * Fails otherwise.
206
     *
207 1
     * @param Value[] $values
208
     * @return int 1 or 0 on failure
209
     *
210
     * @todo add some checking for $values to be an array of xml-rpc values?
211
     * @todo rename to addToStruct?
212
     */
213
    public function addStruct($values)
214
    {
215
        if ($this->mytype == 0) {
216
            $this->mytype = static::$xmlrpcTypes['struct'];
217
            $this->me['struct'] = $values;
218
219
            return 1;
220
        } elseif ($this->mytype == 3) {
221
            // we're adding to a struct here
222
            $this->me['struct'] = array_merge($this->me['struct'], $values);
223
224
            return 1;
225
        } else {
226
            $this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': already initialized as a [' . $this->kindOf() . ']');
227 1
            return 0;
228
        }
229 1
    }
230
231
    /**
232
     * Returns a string describing the base type of the value.
233
     *
234 1
     * @return string either "struct", "array", "scalar" or "undef"
235
     */
236 1
    public function kindOf()
237
    {
238 1
        switch ($this->mytype) {
239
            case 3:
240
                return 'struct';
241
            case 2:
242
                return 'array';
243
            case 1:
244
                return 'scalar';
245
            default:
246
                return 'undef';
247
        }
248
    }
249
250 627
251
    /**
252 627
     * Returns the value of a scalar xml-rpc value (base 64 decoding is automatically handled here)
253 627
     *
254 150
     * @return mixed
255 606
     */
256 214
    public function scalarVal()
257 583
    {
258 583
        $b = reset($this->me);
259
260
        return $b;
261
    }
262
263
    /**
264
     * Returns the type of the xml-rpc value.
265
     *
266
     * @return string For integers, 'int' is always returned in place of 'i4'. 'i8' is considered a separate type and
267
     *                returned as such
268
     */
269
    public function scalarTyp()
270 705
    {
271
        reset($this->me);
272 705
        $a = key($this->me);
273
        if ($a == static::$xmlrpcI4) {
274 705
            $a = static::$xmlrpcInt;
275 2
        }
276
277
        return $a;
278 705
    }
279 705
280
    /**
281 684
     * Returns the xml representation of the value. XML prologue not included.
282 23
     *
283 23
     * @param string $charsetEncoding the charset to be used for serialization. If null, US-ASCII is assumed
284 684
     * @return string
285 46
     */
286 46
    public function serialize($charsetEncoding = '')
287 663
    {
288
        $val = reset($this->me);
289 573
        $typ = key($this->me);
290 573
291 474
        return '<value>' . $this->serializeData($typ, $val, $charsetEncoding) . "</value>\n";
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::serializeData() has been deprecated: this should be folded back into serialize() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

291
        return '<value>' . /** @scrutinizer ignore-deprecated */ $this->serializeData($typ, $val, $charsetEncoding) . "</value>\n";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
292 68
    }
293 68
294 430
    /**
295 430
     * @param string $typ
296 68
     * @param Value[]|mixed $val
297
     * @param string $charsetEncoding
298
     * @return string
299
     *
300
     * @deprecated this should be folded back into serialize()
301
     */
302 24
    protected function serializeData($typ, $val, $charsetEncoding = '')
303 24
    {
304 47
        $this->logDeprecationUnlessCalledBy('serialize');
305 25
306 24
        if (!isset(static::$xmlrpcTypes[$typ])) {
307 23
            return '';
308 22
        }
309 23
310 23
        switch (static::$xmlrpcTypes[$typ]) {
311
            case 1:
312
                switch ($typ) {
313
                    case static::$xmlrpcBase64:
314
                        $rs = "<{$typ}>" . base64_encode($val) . "</{$typ}>";
0 ignored issues
show
Bug introduced by
It seems like $val can also be of type PhpXmlRpc\Value[]; however, parameter $string of base64_encode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

314
                        $rs = "<{$typ}>" . base64_encode(/** @scrutinizer ignore-type */ $val) . "</{$typ}>";
Loading history...
315 25
                        break;
316 23
                    case static::$xmlrpcBoolean:
317 23
                        $rs = "<{$typ}>" . ($val ? '1' : '0') . "</{$typ}>";
318 23
                        break;
319
                    case static::$xmlrpcString:
320 1
                        // Do NOT use htmlentities, since it will produce named html entities, which are invalid xml
321
                        $rs = "<{$typ}>" . $this->getCharsetEncoder()->encodeEntities($val, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</{$typ}>";
322 23
                        break;
323
                    case static::$xmlrpcInt:
324
                    case static::$xmlrpcI4:
325
                    case static::$xmlrpcI8:
326
                        $rs = "<{$typ}>" . (int)$val . "</{$typ}>";
327
                        break;
328 684
                    case static::$xmlrpcDouble:
329 218
                        // avoid using standard conversion of float to string because it is locale-dependent,
330
                        // and also because the xml-rpc spec forbids exponential notation.
331 133
                        // sprintf('%F') could be most likely ok, but it fails e.g. on 2e-14.
332 1
                        // The code below tries its best at keeping max precision while avoiding exp notation,
333
                        // but there is of course no limit in the number of decimal places to be used...
334 133
                        $rs = "<{$typ}>" . preg_replace('/\\.?0+$/', '', number_format((double)$val, PhpXmlRpc::$xmlpc_double_precision, '.', '')) . "</{$typ}>";
335
                        break;
336 133
                    case static::$xmlrpcDateTime:
337
                        if (is_string($val)) {
338 133
                            $rs = "<{$typ}>{$val}</{$typ}>";
339 112
                        // DateTimeInterface is not present in php 5.4...
340
                        } elseif (is_a($val, 'DateTimeInterface') || is_a($val, 'DateTime')) {
341 112
                            $rs = "<{$typ}>" . $val->format('Ymd\TH:i:s') . "</{$typ}>";
342 112
                        } elseif (is_int($val)) {
343
                            $rs = "<{$typ}>" . date('Ymd\TH:i:s', $val) . "</{$typ}>";
344 133
                        } else {
345 133
                            // not really a good idea here: but what should we output anyway? left for backward compat...
346 154
                            $rs = "<{$typ}>{$val}</{$typ}>";
347
                        }
348 154
                        break;
349
                    case static::$xmlrpcNull:
350 154
                        if (PhpXmlRpc::$xmlrpc_null_apache_encoding) {
351
                            $rs = "<ex:nil/>";
352 154
                        } else {
353
                            $rs = "<nil/>";
354 154
                        }
355 154
                        break;
356
                    default:
357
                        // no standard type value should arrive here, but provide a possibility
358
                        // for xml-rpc values of unknown type...
359
                        $rs = "<{$typ}>{$val}</{$typ}>";
360 705
                }
361
                break;
362
            case 3:
363
                // struct
364
                if ($this->_php_class) {
365
                    $rs = '<struct php_class="' . $this->_php_class . "\">\n";
366
                } else {
367
                    $rs = "<struct>\n";
368
                }
369
                $charsetEncoder = $this->getCharsetEncoder();
370 705
                /** @var Value $val2 */
371
                foreach ($val as $key2 => $val2) {
372 705
                    $rs .= '<member><name>' . $charsetEncoder->encodeEntities($key2, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</name>\n";
373 705
                    $rs .= $val2->serialize($charsetEncoding);
374
                    $rs .= "</member>\n";
375 705
                }
376
                $rs .= '</struct>';
377
                break;
378
            case 2:
379
                // array
380
                $rs = "<array>\n<data>\n";
381
                /** @var Value $element */
382
                foreach ($val as $element) {
383
                    $rs .= $element->serialize($charsetEncoding);
384
                }
385
                $rs .= "</data>\n</array>";
386
                break;
387
            default:
388
                /// @todo log a warning?
389 2
                $rs = '';
390
                break;
391
        }
392
393 2
        return $rs;
394
    }
395
396
    /**
397
     * Returns the number of members in an xml-rpc value:
398
     * - 0 for uninitialized values
399
     * - 1 for scalar values
400
     * - the number of elements for struct and array values
401
     *
402
     * @return integer
403
     */
404
    #[\ReturnTypeWillChange]
405
    public function count()
406 29
    {
407
        switch ($this->mytype) {
408
            case 3:
409
                return count($this->me['struct']);
410 29
            case 2:
411
                return count($this->me['array']);
412
            case 1:
413
                return 1;
414
            default:
415
                return 0;
416
        }
417
    }
418
419
    /**
420
     * Implements the IteratorAggregate interface
421
     * @internal required to be public to implement an Interface
422
     *
423
     * @return \ArrayIterator
424
     */
425
    #[\ReturnTypeWillChange]
426
    public function getIterator()
427
    {
428
        switch ($this->mytype) {
429
            case 3:
430
                return new \ArrayIterator($this->me['struct']);
431
            case 2:
432
                return new \ArrayIterator($this->me['array']);
433
            case 1:
434
                return new \ArrayIterator($this->me);
435
            default:
436
                return new \ArrayIterator();
437
        }
438
    }
439
440
    /**
441
     * @internal required to be public to implement an Interface
442
     *
443
     * @param mixed $offset
444 660
     * @param mixed $value
445
     * @return void
446 660
     * @throws ValueErrorException|TypeErrorException
447
     */
448 660
    #[\ReturnTypeWillChange]
449
    public function offsetSet($offset, $value)
450
    {
451
        switch ($this->mytype) {
452
            case 3:
453
                if (!($value instanceof Value)) {
454
                    throw new TypeErrorException('It is only possible to add Value objects to an XML-RPC Struct');
455
                }
456
                if (is_null($offset)) {
457
                    // disallow struct members with empty names
458 454
                    throw new ValueErrorException('It is not possible to add anonymous members to an XML-RPC Struct');
459
                } else {
460 454
                    $this->me['struct'][$offset] = $value;
461 454
                }
462 454
                return;
463
            case 2:
464
                if (!($value instanceof Value)) {
465
                    throw new TypeErrorException('It is only possible to add Value objects to an XML-RPC Array');
466 454
                }
467
                if (is_null($offset)) {
468
                    $this->me['array'][] = $value;
469
                } else {
470
                    // nb: we are not checking that $offset is above the existing array range...
471
                    $this->me['array'][$offset] = $value;
472
                }
473
                return;
474
            case 1:
475
                /// @todo: should we handle usage of i4 to retrieve int (in both set/unset/isset)? After all we consider
476
                ///        'int' to be the preferred form, as evidenced in scalarTyp()
477
                reset($this->me);
478 43
                $type = key($this->me);
479
                if ($type != $offset && ($type != 'i4' || $offset != 'int')) {
480
                    throw new ValueErrorException('...');
481
                }
482 43
                $this->me[$type] = $value;
483
                return;
484
            default:
485
                // it would be nice to allow empty values to be turned into non-empty ones this way, but we miss info to do so
486
                throw new ValueErrorException("XML-RPC Value is of type 'undef' and its value can not be set using array index");
487
        }
488
    }
489
490
    /**
491
     * @internal required to be public to implement an Interface
492 44
     *
493
     * @param mixed $offset
494
     * @return bool
495
     */
496 44
    #[\ReturnTypeWillChange]
497
    public function offsetExists($offset)
498
    {
499
        switch ($this->mytype) {
500
            case 3:
501
                return isset($this->me['struct'][$offset]);
502
            case 2:
503
                return isset($this->me['array'][$offset]);
504
            case 1:
505
                // handle i4 vs int
506 23
                if ($offset == 'i4') {
507
                    // to be consistent with set and unset, we disallow usage of i4 to check for int
508
                    reset($this->me);
509
                    return $offset == key($this->me);
510 23
                } else {
511
                    return $offset == $this->scalarTyp();
512
                }
513
            default:
514
                return false;
515
        }
516
    }
517
518
    /**
519
     * @internal required to be public to implement an Interface
520
     *
521
     * @param mixed $offset
522 25
     * @return void
523
     * @throws ValueErrorException|StateErrorException
524 25
     */
525 25
    #[\ReturnTypeWillChange]
526
    public function offsetUnset($offset)
527 25
    {
528 25
        switch ($this->mytype) {
529
            case 3:
530
                unset($this->me['struct'][$offset]);
531
                return;
532
            case 2:
533
                unset($this->me['array'][$offset]);
534
                return;
535
            case 1:
536
                // can not remove value from a scalar
537
                /// @todo feature creep - allow this to move back the value to 'undef' state?
538
                throw new StateErrorException("XML-RPC Value is of type 'scalar' and its value can not be unset using array index");
539
            default:
540
                throw new StateErrorException("XML-RPC Value is of type 'undef' and its value can not be unset using array index");
541
        }
542
    }
543 258
544
    /**
545 258
     * @internal required to be public to implement an Interface
546 258
     *
547 65
     * @param mixed $offset
548 215
     * @return mixed|Value|null
549 215
     * @throws StateErrorException
550
     */
551
    #[\ReturnTypeWillChange]
552
    public function offsetGet($offset)
553
    {
554
        switch ($this->mytype) {
555
            case 3:
556
                return isset($this->me['struct'][$offset]) ? $this->me['struct'][$offset] : null;
557
            case 2:
558
                return isset($this->me['array'][$offset]) ? $this->me['array'][$offset] : null;
559
            case 1:
560
                /// @todo what to return on bad type: null or exception?
561
                $value = reset($this->me);
562
                $type = key($this->me);
563
                return $type == $offset ? $value : (($type == 'i4' && $offset == 'int') ? $value : null);
564 22
            default:
565
                // return null or exception?
566 22
                throw new StateErrorException("XML-RPC Value is of type 'undef' and can not be accessed using array index");
567 22
        }
568
    }
569
570
    // *** BC layer ***
571
572
    /**
573
     * Checks whether a struct member with a given name is present.
574
     *
575
     * Works only on xml-rpc values of type struct.
576
     *
577
     * @param string $key the name of the struct member to be looked up
578 22
     * @return boolean
579 22
     *
580
     * @deprecated use array access, e.g. isset($val[$key])
581
     */
582 22
    public function structMemExists($key)
583 22
    {
584
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
585
586
        return array_key_exists($key, $this->me['struct']);
587
    }
588 22
589
    /**
590
     * Returns the value of a given struct member (an xml-rpc value object in itself).
591
     * Will raise a php warning if struct member of given name does not exist.
592
     *
593
     * @param string $key the name of the struct member to be looked up
594
     * @return Value
595
     *
596
     * @deprecated use array access, e.g. $val[$key]
597
     */
598
    public function structMem($key)
599
    {
600
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
601
602
        return $this->me['struct'][$key];
603
    }
604
605
    /**
606
     * Reset internal pointer for xml-rpc values of type struct.
607
     * @return void
608
     *
609
     * @deprecated iterate directly over the object using foreach instead
610
     */
611
    public function structReset()
612
    {
613
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
614
615
        reset($this->me['struct']);
616
    }
617
618
    /**
619
     * Return next member element for xml-rpc values of type struct.
620
     *
621
     * @return array having the same format as PHP's `each` method
622
     *
623
     * @deprecated iterate directly over the object using foreach instead
624
     */
625
    public function structEach()
626
    {
627
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
628
629
        $key = key($this->me['struct']);
630
        $value = current($this->me['struct']);
631
        next($this->me['struct']);
632
        return array(1 => $value, 'value' => $value, 0 => $key, 'key' => $key);
633
    }
634
635
    /**
636
     * Returns the n-th member of an xml-rpc value of array type.
637
     *
638
     * @param integer $key the index of the value to be retrieved (zero based)
639
     *
640
     * @return Value
641
     *
642
     * @deprecated use array access, e.g. $val[$key]
643
     */
644
    public function arrayMem($key)
645
    {
646
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
647
648
        return $this->me['array'][$key];
649
    }
650
651
    /**
652
     * Returns the number of members in an xml-rpc value of array type.
653
     *
654
     * @return integer
655 175
     *
656
     * @deprecated use count() instead
657 175
     */
658 175
    public function arraySize()
659 173
    {
660 24
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
661 24
662
        return count($this->me['array']);
663
    }
664
665
    /**
666
     * Returns the number of members in an xml-rpc value of struct type.
667
     *
668
     * @return integer
669
     *
670
     * @deprecated use count() instead
671
     */
672
    public function structSize()
673
    {
674
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
675
676
        return count($this->me['struct']);
677
    }
678
679
    // we have to make this return by ref in order to allow calls such as `$resp->_cookies['name'] = ['value' => 'something'];`
680
    public function &__get($name)
681
    {
682
        switch ($name) {
683
            case 'me':
684
            case 'mytype':
685
            case '_php_class':
686
                $this->logDeprecation('Getting property Value::' . $name . ' is deprecated');
687
                return $this->$name;
688
            default:
689
                /// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout...
690
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
691
                trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING);
692
                $result = null;
693
                return $result;
694
        }
695
    }
696
697
    public function __set($name, $value)
698
    {
699
        switch ($name) {
700
            case 'me':
701
            case 'mytype':
702
            case '_php_class':
703
                $this->logDeprecation('Setting property Value::' . $name . ' is deprecated');
704
                $this->$name = $value;
705
                break;
706
            default:
707
                /// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout...
708
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
709
                trigger_error('Undefined property via __set(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING);
710
        }
711
    }
712
713
    public function __isset($name)
714
    {
715
        switch ($name) {
716
            case 'me':
717
            case 'mytype':
718
            case '_php_class':
719
                $this->logDeprecation('Checking property Value::' . $name . ' is deprecated');
720
                return isset($this->$name);
721
            default:
722
                return false;
723
        }
724
    }
725
726
    public function __unset($name)
727
    {
728
        switch ($name) {
729
            case 'me':
730
            case 'mytype':
731
            case '_php_class':
732
                $this->logDeprecation('Unsetting property Value::' . $name . ' is deprecated');
733
                unset($this->$name);
734
                break;
735
            default:
736
                /// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout...
737
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
738
                trigger_error('Undefined property via __unset(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING);
739
        }
740
    }
741
}
742