We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
Complex classes like ValidationException 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 ValidationException, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class ValidationException extends InvalidArgumentException implements ExceptionInterface |
||
20 | { |
||
21 | const MODE_DEFAULT = 1; |
||
22 | const MODE_NEGATIVE = 2; |
||
23 | const STANDARD = 0; |
||
24 | public static $defaultTemplates = [ |
||
25 | self::MODE_DEFAULT => [ |
||
26 | self::STANDARD => 'Data validation failed for %s', |
||
27 | ], |
||
28 | self::MODE_NEGATIVE => [ |
||
29 | self::STANDARD => 'Data validation failed for %s', |
||
30 | ], |
||
31 | ]; |
||
32 | |||
33 | /** |
||
34 | * @var int |
||
35 | */ |
||
36 | private static $maxDepthStringify = 5; |
||
37 | |||
38 | /** |
||
39 | * @var int |
||
40 | */ |
||
41 | private static $maxCountStringify = 10; |
||
42 | |||
43 | /** |
||
44 | * @var string |
||
45 | */ |
||
46 | private static $maxReplacementStringify = '...'; |
||
47 | |||
48 | protected $id = 'validation'; |
||
49 | protected $mode = self::MODE_DEFAULT; |
||
50 | protected $name = ''; |
||
51 | protected $template = ''; |
||
52 | protected $params = []; |
||
53 | private $customTemplate = false; |
||
54 | |||
55 | 8 | public static function format($template, array $vars = []) |
|
56 | { |
||
57 | 8 | return preg_replace_callback( |
|
58 | 8 | '/{{(\w+)}}/', |
|
59 | 8 | function ($match) use ($vars) { |
|
60 | 7 | if (!isset($vars[$match[1]])) { |
|
61 | 2 | return $match[0]; |
|
62 | } |
||
63 | |||
64 | 7 | $value = $vars[$match[1]]; |
|
65 | 7 | if ('name' == $match[1] && is_string($value)) { |
|
66 | 4 | return $value; |
|
67 | } |
||
68 | |||
69 | 4 | return ValidationException::stringify($value); |
|
70 | 8 | }, |
|
71 | 8 | $template |
|
72 | ); |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * @param mixed $value |
||
77 | * @param int $depth |
||
78 | * |
||
79 | * @return string |
||
80 | */ |
||
81 | 36 | public static function stringify($value, $depth = 1) |
|
82 | { |
||
83 | 36 | if ($depth >= self::$maxDepthStringify) { |
|
84 | return self::$maxReplacementStringify; |
||
85 | } |
||
86 | |||
87 | 36 | if (is_array($value)) { |
|
88 | 20 | return static::stringifyArray($value, $depth); |
|
89 | } |
||
90 | |||
91 | 35 | if (is_object($value)) { |
|
92 | 9 | return static::stringifyObject($value, $depth); |
|
93 | } |
||
94 | |||
95 | 33 | if (is_resource($value)) { |
|
96 | 4 | return sprintf('`[resource] (%s)`', get_resource_type($value)); |
|
97 | } |
||
98 | |||
99 | 30 | if (is_float($value)) { |
|
100 | 4 | if (is_infinite($value)) { |
|
101 | 2 | return ($value > 0 ? '' : '-').'INF'; |
|
102 | } |
||
103 | |||
104 | 2 | if (is_nan($value)) { |
|
105 | 1 | return 'NaN'; |
|
106 | } |
||
107 | } |
||
108 | |||
109 | 27 | return @json_encode($value, (JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)) ?: $value; |
|
110 | } |
||
111 | |||
112 | /** |
||
113 | * @param array $value |
||
114 | * @param int $depth |
||
115 | * |
||
116 | * @return string |
||
117 | */ |
||
118 | 20 | public static function stringifyArray(array $value, $depth = 1) |
|
119 | { |
||
120 | 20 | $nextDepth = ($depth + 1); |
|
121 | 20 | if ($nextDepth >= self::$maxDepthStringify) { |
|
122 | 4 | return self::$maxReplacementStringify; |
|
123 | } |
||
124 | |||
125 | 20 | if (empty($value)) { |
|
126 | 3 | return '{ }'; |
|
127 | } |
||
128 | |||
129 | 18 | $total = count($value); |
|
130 | 18 | $string = ''; |
|
131 | 18 | $current = 0; |
|
132 | 18 | foreach ($value as $childKey => $childValue) { |
|
133 | 18 | if ($current++ >= self::$maxCountStringify) { |
|
134 | 1 | $string .= self::$maxReplacementStringify; |
|
135 | 1 | break; |
|
136 | } |
||
137 | |||
138 | 18 | if (!is_int($childKey)) { |
|
139 | 7 | $string .= sprintf('%s: ', static::stringify($childKey, $nextDepth)); |
|
140 | } |
||
141 | |||
142 | 18 | $string .= static::stringify($childValue, $nextDepth); |
|
143 | |||
144 | 18 | if ($current !== $total) { |
|
145 | 18 | $string .= ', '; |
|
146 | } |
||
147 | } |
||
148 | |||
149 | 18 | return sprintf('{ %s }', $string); |
|
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param mixed $value |
||
154 | * @param int $depth |
||
155 | * |
||
156 | * @return string |
||
157 | */ |
||
158 | 9 | public static function stringifyObject($value, $depth = 2) |
|
159 | { |
||
160 | 9 | $nextDepth = $depth + 1; |
|
161 | |||
162 | 9 | if ($value instanceof DateTime) { |
|
163 | 1 | return sprintf('"%s"', $value->format('Y-m-d H:i:s')); |
|
164 | } |
||
165 | |||
166 | 8 | $class = get_class($value); |
|
167 | |||
168 | 8 | if ($value instanceof Traversable) { |
|
169 | 2 | return sprintf('`[traversable] (%s: %s)`', $class, static::stringify(iterator_to_array($value), $nextDepth)); |
|
170 | } |
||
171 | |||
172 | 6 | if ($value instanceof Exception) { |
|
173 | $properties = [ |
||
174 | 1 | 'message' => $value->getMessage(), |
|
175 | 1 | 'code' => $value->getCode(), |
|
176 | 1 | 'file' => $value->getFile().':'.$value->getLine(), |
|
177 | ]; |
||
178 | |||
179 | 1 | return sprintf('`[exception] (%s: %s)`', $class, static::stringify($properties, $nextDepth)); |
|
180 | } |
||
181 | |||
182 | 5 | if (method_exists($value, '__toString')) { |
|
183 | 1 | return static::stringify($value->__toString(), $nextDepth); |
|
184 | } |
||
185 | |||
186 | 4 | $properties = static::stringify(get_object_vars($value), $nextDepth); |
|
187 | |||
188 | 4 | return sprintf('`[object] (%s: %s)`', $class, str_replace('`', '', $properties)); |
|
189 | } |
||
190 | |||
191 | 2 | public function __toString() |
|
195 | |||
196 | 4 | public function chooseTemplate() |
|
200 | |||
201 | 3 | public function configure($name, array $params = []) |
|
202 | { |
||
203 | 3 | $this->setName($name); |
|
204 | 3 | $this->setId($this->guessId()); |
|
205 | 3 | $this->setParams($params); |
|
206 | |||
207 | 3 | return $this; |
|
208 | } |
||
209 | |||
210 | 5 | public function getName() |
|
214 | |||
215 | 1 | public function getId() |
|
219 | |||
220 | 5 | public function getMainMessage() |
|
221 | { |
||
222 | 5 | $vars = $this->getParams(); |
|
223 | 5 | $vars['name'] = $this->getName(); |
|
224 | 5 | $template = $this->getTemplate(); |
|
225 | 5 | if (isset($vars['translator']) && is_callable($vars['translator'])) { |
|
226 | $template = call_user_func($vars['translator'], $template); |
||
227 | } |
||
228 | |||
229 | 5 | return static::format($template, $vars); |
|
230 | } |
||
231 | |||
232 | 1 | public function getParam($name) |
|
236 | |||
237 | 5 | public function getParams() |
|
241 | |||
242 | 5 | public function getTemplate() |
|
243 | { |
||
244 | 5 | if (!empty($this->template)) { |
|
245 | 4 | return $this->template; |
|
246 | } |
||
247 | |||
248 | 5 | return $this->template = $this->buildTemplate(); |
|
249 | } |
||
250 | |||
251 | 1 | public function hasParam($name) |
|
255 | |||
256 | 3 | public function setId($id) |
|
262 | |||
263 | 3 | public function setName($name) |
|
269 | |||
270 | public function setMode($mode) |
||
271 | { |
||
272 | $this->mode = $mode; |
||
273 | $this->template = $this->buildTemplate(); |
||
274 | |||
275 | $this->buildMessage(); |
||
276 | |||
277 | return $this; |
||
278 | } |
||
279 | |||
280 | public function setParam($key, $value) |
||
281 | { |
||
282 | $this->params[$key] = $value; |
||
283 | |||
284 | $this->buildMessage(); |
||
285 | |||
286 | return $this; |
||
287 | } |
||
288 | |||
289 | 3 | public function setParams(array $params) |
|
290 | { |
||
291 | 3 | foreach ($params as $key => $value) { |
|
292 | 1 | $this->params[$key] = $value; |
|
293 | } |
||
294 | |||
295 | 3 | $this->buildMessage(); |
|
296 | |||
297 | 3 | return $this; |
|
298 | } |
||
299 | |||
300 | public function hasCustomTemplate() |
||
304 | |||
305 | 2 | public function setTemplate($template) |
|
306 | { |
||
307 | 2 | $this->customTemplate = true; |
|
308 | 2 | $this->template = $template; |
|
309 | |||
310 | 2 | $this->buildMessage(); |
|
311 | |||
312 | 2 | return $this; |
|
313 | } |
||
314 | |||
315 | 3 | private function buildMessage() |
|
316 | { |
||
317 | 3 | $this->message = $this->getMainMessage(); |
|
318 | 3 | } |
|
319 | |||
320 | 5 | protected function buildTemplate() |
|
326 | |||
327 | 3 | public function guessId() |
|
340 | } |
||
341 |