These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Peridot\Leo\ObjectPath; |
||
3 | |||
4 | /** |
||
5 | * ObjectPath is a utility for parsing object and array strings into |
||
6 | * ObjectPathValues. |
||
7 | * |
||
8 | * @package Peridot\Leo\Utility |
||
9 | */ |
||
10 | class ObjectPath |
||
11 | { |
||
12 | /** |
||
13 | * The subject to match path expressions against. |
||
14 | * |
||
15 | * @var array|object |
||
16 | */ |
||
17 | protected $subject; |
||
18 | |||
19 | /** |
||
20 | * A pattern for matching array keys |
||
21 | * |
||
22 | * @var string |
||
23 | */ |
||
24 | private static $arrayKey = '/\[([^\]]+)\]/'; |
||
25 | |||
26 | /** |
||
27 | * @param array|object $subject |
||
28 | */ |
||
29 | public function __construct($subject) |
||
30 | { |
||
31 | $this->subject = $subject; |
||
32 | } |
||
33 | |||
34 | /** |
||
35 | * Returns an ObjectPathValue if the property described by $path |
||
36 | * can be located in the subject. |
||
37 | * |
||
38 | * A path expression uses object and array syntax. |
||
39 | * |
||
40 | * @code |
||
41 | * |
||
42 | * $person = new stdClass(); |
||
43 | * $person->name = new stdClass(); |
||
44 | * $person->name->first = 'brian'; |
||
45 | * $person->name->last = 'scaturro'; |
||
46 | * $person->hobbies = ['programming', 'reading', 'board games']; |
||
47 | * |
||
48 | * $path = new ObjectPath($person); |
||
49 | * $first = $path->get('name->first'); |
||
50 | * $reading = $path->get('hobbies[0]'); |
||
51 | * |
||
52 | * @endcode |
||
53 | * |
||
54 | * @param string $path |
||
55 | * @return ObjectPathValue |
||
56 | */ |
||
57 | public function get($path) |
||
58 | { |
||
59 | $parts = $this->getPathParts($path); |
||
60 | $properties = $this->getPropertyCollection($this->subject); |
||
61 | $pathValue = null; |
||
62 | while ($properties && $parts) { |
||
0 ignored issues
–
show
The expression
$parts of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
63 | $key = array_shift($parts); |
||
64 | $key = $this->normalizeKey($key); |
||
65 | $pathValue = array_key_exists($key, $properties) ? new ObjectPathValue($key, $properties[$key]) : null; |
||
66 | |||
67 | if (! array_key_exists($key, $properties)) { |
||
68 | break; |
||
69 | } |
||
70 | |||
71 | $properties = $this->getPropertyCollection($properties[$key]); |
||
72 | } |
||
73 | return $pathValue; |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Breaks a path expression into an array used |
||
78 | * for navigating a path. |
||
79 | * |
||
80 | * @param $path |
||
81 | * @return array |
||
82 | */ |
||
83 | public function getPathParts($path) |
||
84 | { |
||
85 | $path = preg_replace('/\[/', '->[', $path); |
||
86 | if (preg_match('/^->/', $path)) { |
||
87 | $path = substr($path, 2); |
||
88 | } |
||
89 | |||
90 | return explode('->', $path); |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Returns a property as an array. |
||
95 | * |
||
96 | * @param $subject |
||
97 | * @return array |
||
98 | */ |
||
99 | protected function getPropertyCollection($subject) |
||
100 | { |
||
101 | if (is_object($subject)) { |
||
102 | return get_object_vars($subject); |
||
103 | } |
||
104 | |||
105 | return $subject; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Return a key that can be used on the current subject. |
||
110 | * |
||
111 | * @param $key |
||
112 | * @param $matches |
||
113 | * @return mixed |
||
114 | */ |
||
115 | protected function normalizeKey($key) |
||
116 | { |
||
117 | if (preg_match(static::$arrayKey, $key, $matches)) { |
||
0 ignored issues
–
show
Since
$arrayKey is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $arrayKey to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
Loading history...
|
|||
118 | $key = $matches[1]; |
||
119 | return $key; |
||
120 | } |
||
121 | return $key; |
||
122 | } |
||
123 | } |
||
124 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.