Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
     */
55
    protected $mytype = 0;
56
    /** @var string|null */
57
    protected $_php_class = null;
58
 
59
    /**
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
     *                     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
     */
70
    public function __construct($val = -1, $type = '')
71
    {
72
        // 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
                    break;
92
                case 'array':
93
                    $this->mytype = 2;
94
                    $this->me['array'] = $val;
95
                    break;
96
                case 'struct':
97
                    $this->mytype = 3;
98
                    $this->me['struct'] = $val;
99
                    break;
100
                default:
101
                    $this->getLogger()->error("XML-RPC: " . __METHOD__ . ": not a known type ($type)");
102
            }
103
        }
104
    }
105
 
106
    /**
107
     * Add a single php value to an xml-rpc value.
108
     *
109
     * If the xml-rpc value is an array, the php value is added as its last element.
110
     * If the xml-rpc value is empty (uninitialized), this method makes it a scalar value, and sets that value.
111
     * Fails if the xml-rpc value is not an array (i.e. a struct or a scalar) and already initialized.
112
     *
113
     * @param mixed $val
114
     * @param string $type allowed values: i4, i8, int, boolean, string, double, dateTime.iso8601, base64, null.
115
     * @return int 1 or 0 on failure
116
     *
117
     * @todo arguably, as we have addArray to add elements to an Array value, and addStruct to add elements to a Struct
118
     *       value, we should not allow this method to add values to an Array. The 'scalar' in the method name refers to
119
     *       the expected state of the target object, not to the type of $val. Also, this works differently from
120
     *       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
        $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
            if (strcasecmp($val, 'true') == 0 || $val == 1 || ($val == true && strcasecmp($val, 'false'))) {
140
                $val = true;
141
            } else {
142
                $val = false;
143
            }
144
        }
145
 
146
        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
                // 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
                $this->me[$type] = $val;
163
                $this->mytype = $typeOf;
164
 
165
                return 1;
166
        }
167
    }
168
 
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
            return 0;
197
        }
198
    }
199
 
200
    /**
201
     * Merges an array of named xml-rpc value objects into an xml-rpc value.
202
     *
203
     * 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
     * Fails otherwise.
206
     *
207
     * @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
            return 0;
228
        }
229
    }
230
 
231
    /**
232
     * Returns a string describing the base type of the value.
233
     *
234
     * @return string either "struct", "array", "scalar" or "undef"
235
     */
236
    public function kindOf()
237
    {
238
        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
 
251
    /**
252
     * Returns the value of a scalar xml-rpc value (base 64 decoding is automatically handled here)
253
     *
254
     * @return mixed
255
     */
256
    public function scalarVal()
257
    {
258
        $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
    {
271
        reset($this->me);
272
        $a = key($this->me);
273
        if ($a == static::$xmlrpcI4) {
274
            $a = static::$xmlrpcInt;
275
        }
276
 
277
        return $a;
278
    }
279
 
280
    /**
281
     * Returns the xml representation of the value. XML prologue not included.
282
     *
283
     * @param string $charsetEncoding the charset to be used for serialization. If null, US-ASCII is assumed
284
     * @return string
285
     */
286
    public function serialize($charsetEncoding = '')
287
    {
288
        $val = reset($this->me);
289
        $typ = key($this->me);
290
 
291
        return '<value>' . $this->serializeData($typ, $val, $charsetEncoding) . "</value>\n";
292
    }
293
 
294
    /**
295
     * @param string $typ
296
     * @param Value[]|mixed $val
297
     * @param string $charsetEncoding
298
     * @return string
299
     *
300
     * @deprecated this should be folded back into serialize()
301
     */
302
    protected function serializeData($typ, $val, $charsetEncoding = '')
303
    {
304
        $this->logDeprecationUnlessCalledBy('serialize');
305
 
306
        if (!isset(static::$xmlrpcTypes[$typ])) {
307
            return '';
308
        }
309
 
310
        switch (static::$xmlrpcTypes[$typ]) {
311
            case 1:
312
                switch ($typ) {
313
                    case static::$xmlrpcBase64:
314
                        $rs = "<{$typ}>" . base64_encode($val) . "</{$typ}>";
315
                        break;
316
                    case static::$xmlrpcBoolean:
317
                        $rs = "<{$typ}>" . ($val ? '1' : '0') . "</{$typ}>";
318
                        break;
319
                    case static::$xmlrpcString:
320
                        // 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
                        break;
323
                    case static::$xmlrpcInt:
324
                    case static::$xmlrpcI4:
325
                    case static::$xmlrpcI8:
326
                        $rs = "<{$typ}>" . (int)$val . "</{$typ}>";
327
                        break;
328
                    case static::$xmlrpcDouble:
329
                        // 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
                        // sprintf('%F') could be most likely ok, but it fails e.g. on 2e-14.
332
                        // 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
                        $rs = "<{$typ}>" . preg_replace('/\\.?0+$/', '', number_format((double)$val, PhpXmlRpc::$xmlpc_double_precision, '.', '')) . "</{$typ}>";
335
                        break;
336
                    case static::$xmlrpcDateTime:
337
                        if (is_string($val)) {
338
                            $rs = "<{$typ}>{$val}</{$typ}>";
339
                        // DateTimeInterface is not present in php 5.4...
340
                        } elseif (is_a($val, 'DateTimeInterface') || is_a($val, 'DateTime')) {
341
                            $rs = "<{$typ}>" . $val->format('Ymd\TH:i:s') . "</{$typ}>";
342
                        } elseif (is_int($val)) {
343
                            $rs = "<{$typ}>" . date('Ymd\TH:i:s', $val) . "</{$typ}>";
344
                        } else {
345
                            // not really a good idea here: but what should we output anyway? left for backward compat...
346
                            $rs = "<{$typ}>{$val}</{$typ}>";
347
                        }
348
                        break;
349
                    case static::$xmlrpcNull:
350
                        if (PhpXmlRpc::$xmlrpc_null_apache_encoding) {
351
                            $rs = "<ex:nil/>";
352
                        } else {
353
                            $rs = "<nil/>";
354
                        }
355
                        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
                }
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
                /** @var Value $val2 */
371
                foreach ($val as $key2 => $val2) {
372
                    $rs .= '<member><name>' . $charsetEncoder->encodeEntities($key2, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</name>\n";
373
                    $rs .= $val2->serialize($charsetEncoding);
374
                    $rs .= "</member>\n";
375
                }
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
                $rs = '';
390
                break;
391
        }
392
 
393
        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
    {
407
        switch ($this->mytype) {
408
            case 3:
409
                return count($this->me['struct']);
410
            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
     * @param mixed $value
445
     * @return void
446
     *
447
     * @throws ValueErrorException|TypeErrorException
448
     */
449
    #[\ReturnTypeWillChange]
450
    public function offsetSet($offset, $value)
451
    {
452
        switch ($this->mytype) {
453
            case 3:
454
                if (!($value instanceof Value)) {
455
                    throw new TypeErrorException('It is only possible to add Value objects to an XML-RPC Struct');
456
                }
457
                if (is_null($offset)) {
458
                    // disallow struct members with empty names
459
                    throw new ValueErrorException('It is not possible to add anonymous members to an XML-RPC Struct');
460
                } else {
461
                    $this->me['struct'][$offset] = $value;
462
                }
463
                return;
464
            case 2:
465
                if (!($value instanceof Value)) {
466
                    throw new TypeErrorException('It is only possible to add Value objects to an XML-RPC Array');
467
                }
468
                if (is_null($offset)) {
469
                    $this->me['array'][] = $value;
470
                } else {
471
                    // nb: we are not checking that $offset is above the existing array range...
472
                    $this->me['array'][$offset] = $value;
473
                }
474
                return;
475
            case 1:
476
                /// @todo: should we handle usage of i4 to retrieve int (in both set/unset/isset)? After all we consider
477
                ///        'int' to be the preferred form, as evidenced in scalarTyp()
478
                reset($this->me);
479
                $type = key($this->me);
480
                if ($type != $offset && ($type != 'i4' || $offset != 'int')) {
481
                    throw new ValueErrorException('...');
482
                }
483
                $this->me[$type] = $value;
484
                return;
485
            default:
486
                // it would be nice to allow empty values to be turned into non-empty ones this way, but we miss info to do so
487
                throw new ValueErrorException("XML-RPC Value is of type 'undef' and its value can not be set using array index");
488
        }
489
    }
490
 
491
    /**
492
     * @internal required to be public to implement an Interface
493
     *
494
     * @param mixed $offset
495
     * @return bool
496
     */
497
    #[\ReturnTypeWillChange]
498
    public function offsetExists($offset)
499
    {
500
        switch ($this->mytype) {
501
            case 3:
502
                return isset($this->me['struct'][$offset]);
503
            case 2:
504
                return isset($this->me['array'][$offset]);
505
            case 1:
506
                // handle i4 vs int
507
                if ($offset == 'i4') {
508
                    // to be consistent with set and unset, we disallow usage of i4 to check for int
509
                    reset($this->me);
510
                    return $offset == key($this->me);
511
                } else {
512
                    return $offset == $this->scalarTyp();
513
                }
514
            default:
515
                return false;
516
        }
517
    }
518
 
519
    /**
520
     * @internal required to be public to implement an Interface
521
     *
522
     * @param mixed $offset
523
     * @return void
524
     *
525
     * @throws ValueErrorException|StateErrorException
526
     */
527
    #[\ReturnTypeWillChange]
528
    public function offsetUnset($offset)
529
    {
530
        switch ($this->mytype) {
531
            case 3:
532
                unset($this->me['struct'][$offset]);
533
                return;
534
            case 2:
535
                unset($this->me['array'][$offset]);
536
                return;
537
            case 1:
538
                // can not remove value from a scalar
539
                /// @todo feature creep - allow this to move back the value to 'undef' state?
540
                throw new StateErrorException("XML-RPC Value is of type 'scalar' and its value can not be unset using array index");
541
            default:
542
                throw new StateErrorException("XML-RPC Value is of type 'undef' and its value can not be unset using array index");
543
        }
544
    }
545
 
546
    /**
547
     * @internal required to be public to implement an Interface
548
     *
549
     * @param mixed $offset
550
     * @return mixed|Value|null
551
     * @throws StateErrorException
552
     */
553
    #[\ReturnTypeWillChange]
554
    public function offsetGet($offset)
555
    {
556
        switch ($this->mytype) {
557
            case 3:
558
                return isset($this->me['struct'][$offset]) ? $this->me['struct'][$offset] : null;
559
            case 2:
560
                return isset($this->me['array'][$offset]) ? $this->me['array'][$offset] : null;
561
            case 1:
562
                /// @todo what to return on bad type: null or exception?
563
                $value = reset($this->me);
564
                $type = key($this->me);
565
                return $type == $offset ? $value : (($type == 'i4' && $offset == 'int') ? $value : null);
566
            default:
567
                // return null or exception?
568
                throw new StateErrorException("XML-RPC Value is of type 'undef' and can not be accessed using array index");
569
        }
570
    }
571
 
572
    // *** BC layer ***
573
 
574
    /**
575
     * Checks whether a struct member with a given name is present.
576
     *
577
     * Works only on xml-rpc values of type struct.
578
     *
579
     * @param string $key the name of the struct member to be looked up
580
     * @return boolean
581
     *
582
     * @deprecated use array access, e.g. isset($val[$key])
583
     */
584
    public function structMemExists($key)
585
    {
586
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
587
 
588
        return array_key_exists($key, $this->me['struct']);
589
    }
590
 
591
    /**
592
     * Returns the value of a given struct member (an xml-rpc value object in itself).
593
     * Will raise a php warning if struct member of given name does not exist.
594
     *
595
     * @param string $key the name of the struct member to be looked up
596
     * @return Value
597
     *
598
     * @deprecated use array access, e.g. $val[$key]
599
     */
600
    public function structMem($key)
601
    {
602
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
603
 
604
        return $this->me['struct'][$key];
605
    }
606
 
607
    /**
608
     * Reset internal pointer for xml-rpc values of type struct.
609
     * @return void
610
     *
611
     * @deprecated iterate directly over the object using foreach instead
612
     */
613
    public function structReset()
614
    {
615
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
616
 
617
        reset($this->me['struct']);
618
    }
619
 
620
    /**
621
     * Return next member element for xml-rpc values of type struct.
622
     *
623
     * @return array having the same format as PHP's `each` method
624
     *
625
     * @deprecated iterate directly over the object using foreach instead
626
     */
627
    public function structEach()
628
    {
629
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
630
 
631
        $key = key($this->me['struct']);
632
        $value = current($this->me['struct']);
633
        next($this->me['struct']);
634
        return array(1 => $value, 'value' => $value, 0 => $key, 'key' => $key);
635
    }
636
 
637
    /**
638
     * Returns the n-th member of an xml-rpc value of array type.
639
     *
640
     * @param integer $key the index of the value to be retrieved (zero based)
641
     *
642
     * @return Value
643
     *
644
     * @deprecated use array access, e.g. $val[$key]
645
     */
646
    public function arrayMem($key)
647
    {
648
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
649
 
650
        return $this->me['array'][$key];
651
    }
652
 
653
    /**
654
     * Returns the number of members in an xml-rpc value of array type.
655
     *
656
     * @return integer
657
     *
658
     * @deprecated use count() instead
659
     */
660
    public function arraySize()
661
    {
662
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
663
 
664
        return count($this->me['array']);
665
    }
666
 
667
    /**
668
     * Returns the number of members in an xml-rpc value of struct type.
669
     *
670
     * @return integer
671
     *
672
     * @deprecated use count() instead
673
     */
674
    public function structSize()
675
    {
676
        $this->logDeprecation('Method ' . __METHOD__ . ' is deprecated');
677
 
678
        return count($this->me['struct']);
679
    }
680
 
681
    // we have to make this return by ref in order to allow calls such as `$resp->_cookies['name'] = ['value' => 'something'];`
682
    public function &__get($name)
683
    {
684
        switch ($name) {
685
            case 'me':
686
            case 'mytype':
687
            case '_php_class':
688
                $this->logDeprecation('Getting property Value::' . $name . ' is deprecated');
689
                return $this->$name;
690
            default:
691
                /// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout...
692
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
693
                trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING);
694
                $result = null;
695
                return $result;
696
        }
697
    }
698
 
699
    public function __set($name, $value)
700
    {
701
        switch ($name) {
702
            case 'me':
703
            case 'mytype':
704
            case '_php_class':
705
                $this->logDeprecation('Setting property Value::' . $name . ' is deprecated');
706
                $this->$name = $value;
707
                break;
708
            default:
709
                /// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout...
710
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
711
                trigger_error('Undefined property via __set(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING);
712
        }
713
    }
714
 
715
    public function __isset($name)
716
    {
717
        switch ($name) {
718
            case 'me':
719
            case 'mytype':
720
            case '_php_class':
721
                $this->logDeprecation('Checking property Value::' . $name . ' is deprecated');
722
                return isset($this->$name);
723
            default:
724
                return false;
725
        }
726
    }
727
 
728
    public function __unset($name)
729
    {
730
        switch ($name) {
731
            case 'me':
732
            case 'mytype':
733
            case '_php_class':
734
                $this->logDeprecation('Unsetting property Value::' . $name . ' is deprecated');
735
                unset($this->$name);
736
                break;
737
            default:
738
                /// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout...
739
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
740
                trigger_error('Undefined property via __unset(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING);
741
        }
742
    }
743
}