Conditions | 61 |
Paths | 943 |
Total Lines | 162 |
Code Lines | 110 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
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:
If many parameters/temporary variables are present:
1 | <?php |
||
38 | public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic) |
||
39 | { |
||
40 | $refs = $values; |
||
41 | foreach ($values as $k => $value) { |
||
42 | if (\is_resource($value)) { |
||
43 | throw new NotInstantiableTypeException(get_resource_type($value).' resource'); |
||
44 | } |
||
45 | $refs[$k] = $objectsPool; |
||
46 | |||
47 | if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) { |
||
48 | $values[$k] = &$value; // Break hard references to make $values completely |
||
49 | unset($value); // independent from the original structure |
||
50 | $refs[$k] = $value = $values[$k]; |
||
51 | if ($value instanceof Reference && 0 > $value->id) { |
||
52 | $valuesAreStatic = false; |
||
53 | ++$value->count; |
||
54 | continue; |
||
55 | } |
||
56 | $refsPool[] = [&$refs[$k], $value, &$value]; |
||
57 | $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value); |
||
58 | } |
||
59 | |||
60 | if (\is_array($value)) { |
||
61 | if ($value) { |
||
|
|||
62 | $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); |
||
63 | } |
||
64 | goto handle_value; |
||
65 | } elseif (!\is_object($value) || $value instanceof \UnitEnum) { |
||
66 | goto handle_value; |
||
67 | } |
||
68 | |||
69 | $valueIsStatic = false; |
||
70 | if (isset($objectsPool[$value])) { |
||
71 | ++$objectsCount; |
||
72 | $value = new Reference($objectsPool[$value][0]); |
||
73 | goto handle_value; |
||
74 | } |
||
75 | |||
76 | $class = $value::class; |
||
77 | $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); |
||
78 | $properties = []; |
||
79 | |||
80 | if ($reflector->hasMethod('__serialize')) { |
||
81 | if (!$reflector->getMethod('__serialize')->isPublic()) { |
||
82 | throw new \Error(\sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); |
||
83 | } |
||
84 | |||
85 | if (!\is_array($serializeProperties = $value->__serialize())) { |
||
86 | throw new \TypeError($class.'::__serialize() must return an array'); |
||
87 | } |
||
88 | |||
89 | if ($reflector->hasMethod('__unserialize')) { |
||
90 | $properties = $serializeProperties; |
||
91 | } else { |
||
92 | foreach ($serializeProperties as $n => $v) { |
||
93 | $p = $reflector->hasProperty($n) ? $reflector->getProperty($n) : null; |
||
94 | $c = $p && (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly()) ? $p->class : 'stdClass'; |
||
95 | $properties[$c][$n] = $v; |
||
96 | } |
||
97 | } |
||
98 | |||
99 | goto prepare_value; |
||
100 | } |
||
101 | |||
102 | $sleep = null; |
||
103 | $proto = Registry::$prototypes[$class]; |
||
104 | |||
105 | if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { |
||
106 | // ArrayIterator and ArrayObject need special care because their "flags" |
||
107 | // option changes the behavior of the (array) casting operator. |
||
108 | [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto); |
||
109 | |||
110 | // populates Registry::$prototypes[$class] with a new instance |
||
111 | Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]); |
||
112 | } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) { |
||
113 | // By implementing Serializable, SplObjectStorage breaks |
||
114 | // internal references; let's deal with it on our own. |
||
115 | foreach (clone $value as $v) { |
||
116 | $properties[] = $v; |
||
117 | $properties[] = $value[$v]; |
||
118 | } |
||
119 | $properties = ['SplObjectStorage' => ["\0" => $properties]]; |
||
120 | $arrayValue = (array) $value; |
||
121 | } elseif ($value instanceof \Serializable |
||
122 | || $value instanceof \__PHP_Incomplete_Class |
||
123 | ) { |
||
124 | ++$objectsCount; |
||
125 | $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; |
||
126 | $value = new Reference($id); |
||
127 | goto handle_value; |
||
128 | } else { |
||
129 | if (method_exists($class, '__sleep')) { |
||
130 | if (!\is_array($sleep = $value->__sleep())) { |
||
131 | trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE); |
||
132 | $value = null; |
||
133 | goto handle_value; |
||
134 | } |
||
135 | $sleep = array_flip($sleep); |
||
136 | } |
||
137 | |||
138 | $arrayValue = (array) $value; |
||
139 | } |
||
140 | |||
141 | $proto = (array) $proto; |
||
142 | |||
143 | foreach ($arrayValue as $name => $v) { |
||
144 | $i = 0; |
||
145 | $n = (string) $name; |
||
146 | if ('' === $n || "\0" !== $n[0]) { |
||
147 | $p = $reflector->hasProperty($n) ? $reflector->getProperty($n) : null; |
||
148 | $c = $p && (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly()) ? $p->class : 'stdClass'; |
||
149 | } elseif ('*' === $n[1]) { |
||
150 | $n = substr($n, 3); |
||
151 | $c = $reflector->getProperty($n)->class; |
||
152 | if ('Error' === $c) { |
||
153 | $c = 'TypeError'; |
||
154 | } elseif ('Exception' === $c) { |
||
155 | $c = 'ErrorException'; |
||
156 | } |
||
157 | } else { |
||
158 | $i = strpos($n, "\0", 2); |
||
159 | $c = substr($n, 1, $i - 1); |
||
160 | $n = substr($n, 1 + $i); |
||
161 | } |
||
162 | if (null !== $sleep) { |
||
163 | if (!isset($sleep[$name]) && (!isset($sleep[$n]) || ($i && $c !== $class))) { |
||
164 | unset($arrayValue[$name]); |
||
165 | continue; |
||
166 | } |
||
167 | unset($sleep[$name], $sleep[$n]); |
||
168 | } |
||
169 | if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { |
||
170 | $properties[$c][$n] = $v; |
||
171 | } |
||
172 | } |
||
173 | if ($sleep) { |
||
174 | foreach ($sleep as $n => $v) { |
||
175 | trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); |
||
176 | } |
||
177 | } |
||
178 | if (method_exists($class, '__unserialize')) { |
||
179 | $properties = $arrayValue; |
||
180 | } |
||
181 | |||
182 | prepare_value: |
||
183 | $objectsPool[$value] = [$id = \count($objectsPool)]; |
||
184 | $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); |
||
185 | ++$objectsCount; |
||
186 | $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)]; |
||
187 | |||
188 | $value = new Reference($id); |
||
189 | |||
190 | handle_value: |
||
191 | if ($isRef) { |
||
192 | unset($value); // Break the hard reference created above |
||
193 | } elseif (!$valueIsStatic) { |
||
194 | $values[$k] = $value; |
||
195 | } |
||
196 | $valuesAreStatic = $valueIsStatic && $valuesAreStatic; |
||
197 | } |
||
198 | |||
199 | return $values; |
||
200 | } |
||
421 |
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.