Completed
Push — master ( 5fc0c8...b5d242 )
by Gaetano
06:30
created

Value::addScalar()   C

Complexity

Conditions 11
Paths 26

Size

Total Lines 43
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 1
Metric Value
c 4
b 1
f 1
dl 0
loc 43
rs 5.2653
cc 11
eloc 26
nc 26
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
    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
        if ($val !== -1 || $type != '') {
60
            switch ($type) {
61
                case '':
62
                    $this->mytype = 1;
63
                    $this->me['string'] = $val;
64
                    break;
65
                case 'i4':
66
                case 'i8':
67
                case 'int':
68
                case 'double':
69
                case 'string':
70
                case 'boolean':
71
                case 'dateTime.iso8601':
72
                case 'base64':
73
                case 'null':
74
                    $this->mytype = 1;
75
                    $this->me[$type] = $val;
76
                    break;
77
                case 'array':
78
                    $this->mytype = 2;
79
                    $this->me['array'] = $val;
80
                    break;
81
                case 'struct':
82
                    $this->mytype = 3;
83
                    $this->me['struct'] = $val;
84
                    break;
85
                default:
86
                    error_log("XML-RPC: " . __METHOD__ . ": not a known type ($type)");
87
            }
88
        }
89
    }
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
    public function addScalar($val, $type = 'string')
104
    {
105
        $typeOf = null;
106
        if (isset(static::$xmlrpcTypes[$type])) {
107
            $typeOf = static::$xmlrpcTypes[$type];
108
        }
109
110
        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
        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
        switch ($this->mytype) {
127
            case 1:
128
                error_log('XML-RPC: ' . __METHOD__ . ': scalar xmlrpc value can have only one value');
129
                return 0;
130
            case 3:
131
                error_log('XML-RPC: ' . __METHOD__ . ': cannot add anonymous scalar to struct xmlrpc value');
132
                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 View Code Duplication
    public function addArray($values)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
161
    {
162
        if ($this->mytype == 0) {
163
            $this->mytype = static::$xmlrpcTypes['array'];
164
            $this->me['array'] = $values;
165
166
            return 1;
167
        } elseif ($this->mytype == 2) {
168
            // we're adding to an array here
169
            $this->me['array'] = array_merge($this->me['array'], $values);
170
171
            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 View Code Duplication
    public function addStruct($values)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
192
    {
193
        if ($this->mytype == 0) {
194
            $this->mytype = static::$xmlrpcTypes['struct'];
195
            $this->me['struct'] = $values;
196
197
            return 1;
198
        } elseif ($this->mytype == 3) {
199
            // we're adding to a struct here
200
            $this->me['struct'] = array_merge($this->me['struct'], $values);
201
202
            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
    public function kindOf()
215
    {
216
        switch ($this->mytype) {
217
            case 3:
218
                return 'struct';
219
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
220
            case 2:
221
                return 'array';
222
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
223
            case 1:
224
                return 'scalar';
225
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
226
            default:
227
                return 'undef';
228
        }
229
    }
230
231
    protected function serializedata($typ, $val, $charsetEncoding = '')
232
    {
233
        $rs = '';
234
235
        if (!isset(static::$xmlrpcTypes[$typ])) {
236
            return $rs;
237
        }
238
239
        switch (static::$xmlrpcTypes[$typ]) {
240
            case 1:
241
                switch ($typ) {
242
                    case static::$xmlrpcBase64:
243
                        $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
244
                        break;
245
                    case static::$xmlrpcBoolean:
246
                        $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
247
                        break;
248
                    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
                        $rs .= "<${typ}>" . Charset::instance()->encodeEntities($val, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</${typ}>";
252
                        break;
253
                    case static::$xmlrpcInt:
254
                    case static::$xmlrpcI4:
255
                    case static::$xmlrpcI8:
256
                        $rs .= "<${typ}>" . (int)$val . "</${typ}>";
257
                        break;
258
                    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
                        $rs .= "<${typ}>" . preg_replace('/\\.?0+$/', '', number_format((double)$val, 128, '.', '')) . "</${typ}>";
265
                        break;
266
                    case static::$xmlrpcDateTime:
267
                        if (is_string($val)) {
268
                            $rs .= "<${typ}>${val}</${typ}>";
269
                        } elseif (is_a($val, 'DateTime')) {
270
                            $rs .= "<${typ}>" . $val->format('Ymd\TH:i:s') . "</${typ}>";
271
                        } elseif (is_int($val)) {
272
                            $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
                        break;
278
                    case static::$xmlrpcNull:
279
                        if (PhpXmlRpc::$xmlrpc_null_apache_encoding) {
280
                            $rs .= "<ex:nil/>";
281
                        } else {
282
                            $rs .= "<nil/>";
283
                        }
284
                        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
                break;
291
            case 3:
292
                // struct
293
                if ($this->_php_class) {
294
                    $rs .= '<struct php_class="' . $this->_php_class . "\">\n";
295
                } else {
296
                    $rs .= "<struct>\n";
297
                }
298
                $charsetEncoder = Charset::instance();
299
                foreach ($val as $key2 => $val2) {
300
                    $rs .= '<member><name>' . $charsetEncoder->encodeEntities($key2, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</name>\n";
301
                    //$rs.=$this->serializeval($val2);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
302
                    $rs .= $val2->serialize($charsetEncoding);
303
                    $rs .= "</member>\n";
304
                }
305
                $rs .= '</struct>';
306
                break;
307
            case 2:
308
                // array
309
                $rs .= "<array>\n<data>\n";
310
                foreach ($val as $element) {
311
                    //$rs.=$this->serializeval($val[$i]);
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
312
                    $rs .= $element->serialize($charsetEncoding);
313
                }
314
                $rs .= "</data>\n</array>";
315
                break;
316
            default:
317
                break;
318
        }
319
320
        return $rs;
321
    }
322
323
    /**
324
     * Returns the xml representation of the value. XML prologue not included.
325
     *
326
     * @param string $charsetEncoding the charset to be used for serialization. if null, US-ASCII is assumed
327
     *
328
     * @return string
329
     */
330
    public function serialize($charsetEncoding = '')
331
    {
332
        reset($this->me);
333
        list($typ, $val) = each($this->me);
334
335
        return '<value>' . $this->serializedata($typ, $val, $charsetEncoding) . "</value>\n";
336
    }
337
338
    /**
339
     * Checks whether a struct member with a given name is present.
340
     *
341
     * Works only on xmlrpc values of type struct.
342
     *
343
     * @param string $key the name of the struct member to be looked up
344
     *
345
     * @return boolean
346
     *
347
     * @deprecated use array access, e.g. isset($val[$key])
348
     */
349
    public function structmemexists($key)
350
    {
351
        return array_key_exists($key, $this->me['struct']);
352
    }
353
354
    /**
355
     * Returns the value of a given struct member (an xmlrpc value object in itself).
356
     * Will raise a php warning if struct member of given name does not exist.
357
     *
358
     * @param string $key the name of the struct member to be looked up
359
     *
360
     * @return Value
361
     *
362
     * @deprecated use array access, e.g. $val[$key]
363
     */
364
    public function structmem($key)
365
    {
366
        return $this->me['struct'][$key];
367
    }
368
369
    /**
370
     * Reset internal pointer for xmlrpc values of type struct.
371
     * @deprecated iterate directly over the object using foreach instead
372
     */
373
    public function structreset()
374
    {
375
        reset($this->me['struct']);
376
    }
377
378
    /**
379
     * Return next member element for xmlrpc values of type struct.
380
     *
381
     * @return Value
382
     *
383
     * @deprecated iterate directly over the object using foreach instead
384
     */
385
    public function structeach()
386
    {
387
        return each($this->me['struct']);
388
    }
389
390
    /**
391
     * Returns the value of a scalar xmlrpc value (base 64 decoding is automatically handled here)
392
     *
393
     * @return mixed
394
     */
395
    public function scalarval()
396
    {
397
        reset($this->me);
398
        list(, $b) = each($this->me);
399
400
        return $b;
401
    }
402
403
    /**
404
     * Returns the type of the xmlrpc value.
405
     *
406
     * For integers, 'int' is always returned in place of 'i4'. 'i8' is considered a separate type and returned as such
407
     *
408
     * @return string
409
     */
410
    public function scalartyp()
411
    {
412
        reset($this->me);
413
        list($a,) = each($this->me);
414
        if ($a == static::$xmlrpcI4) {
415
            $a = static::$xmlrpcInt;
416
        }
417
418
        return $a;
419
    }
420
421
    /**
422
     * Returns the m-th member of an xmlrpc value of array type.
423
     *
424
     * @param integer $key the index of the value to be retrieved (zero based)
425
     *
426
     * @return Value
427
     *
428
     * @deprecated use array access, e.g. $val[$key]
429
     */
430
    public function arraymem($key)
431
    {
432
        return $this->me['array'][$key];
433
    }
434
435
    /**
436
     * Returns the number of members in an xmlrpc value of array type.
437
     *
438
     * @return integer
439
     *
440
     * @deprecated use count() instead
441
     */
442
    public function arraysize()
443
    {
444
        return count($this->me['array']);
445
    }
446
447
    /**
448
     * Returns the number of members in an xmlrpc value of struct type.
449
     *
450
     * @return integer
451
     *
452
     * @deprecated use count() instead
453
     */
454
    public function structsize()
455
    {
456
        return count($this->me['struct']);
457
    }
458
459
    /**
460
     * Returns the number of members in an xmlrpc value:
461
     * - 0 for uninitialized values
462
     * - 1 for scalar values
463
     * - the number of elements for struct and array values
464
     *
465
     * @return integer
466
     */
467
    public function count()
468
    {
469
        switch ($this->mytype) {
470
            case 3:
471
                return count($this->me['struct']);
472
            case 2:
473
                return count($this->me['array']);
474
            case 1:
475
                return 1;
476
            default:
477
                return 0;
478
        }
479
    }
480
481
    /**
482
     * Implements the IteratorAggregate interface
483
     *
484
     * @return ArrayIterator
485
     */
486
    public function getIterator() {
487
        switch ($this->mytype) {
488
            case 3:
489
                return new \ArrayIterator($this->me['struct']);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \ArrayIterator($this->me['struct']); (ArrayIterator) is incompatible with the return type documented by PhpXmlRpc\Value::getIterator of type PhpXmlRpc\ArrayIterator.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
490
            case 2:
491
                return new \ArrayIterator($this->me['array']);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \ArrayIterator($this->me['array']); (ArrayIterator) is incompatible with the return type documented by PhpXmlRpc\Value::getIterator of type PhpXmlRpc\ArrayIterator.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
492
            case 1:
493
                return new \ArrayIterator($this->me);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \ArrayIterator($this->me); (ArrayIterator) is incompatible with the return type documented by PhpXmlRpc\Value::getIterator of type PhpXmlRpc\ArrayIterator.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
494
            default:
495
                return new \ArrayIterator();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \ArrayIterator(); (ArrayIterator) is incompatible with the return type documented by PhpXmlRpc\Value::getIterator of type PhpXmlRpc\ArrayIterator.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
496
        }
497
        return new \ArrayIterator();
0 ignored issues
show
Unused Code introduced by
return new \ArrayIterator(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
498
    }
499
500
    public function offsetSet($offset, $value) {
501
502
        switch ($this->mytype) {
503
            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
            case 2:
515
                if (!($value instanceof \PhpXmlRpc\Value)) {
516
                    throw new \Exception('It is only possible to add Value objects to an XML-RPC Array');
517
                }
518
                if (is_null($offset)) {
519
                    $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
                return;
525
            case 1:
526
// todo: handle i4 vs int
527
                reset($this->me);
528
                list($type,) = each($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
        switch ($this->mytype) {
572
            case 3:
573
                return isset($this->me['struct'][$offset]) ? $this->me['struct'][$offset] : null;
574
            case 2:
575
                return isset($this->me['array'][$offset]) ? $this->me['array'][$offset] : null;
576
            case 1:
577
// on bad type: null or exception?
578
                reset($this->me);
579
                list($type, $value) = each($this->me);
580
                return $type == $offset ? $value : null;
581
            default:
582
// return null or exception?
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
583
                throw new \Exception("XML-RPC Value is of type 'undef' and can not be accessed using array index");
584
        }
585
    }
586
}
587