Total Complexity | 85 |
Total Lines | 417 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like PatchListUtils 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.
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 PatchListUtils, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | class PatchListUtils |
||
11 | { |
||
12 | public function createSimplifiedList(array $patches) |
||
13 | { |
||
14 | $groups = $this->createTargetsList($patches); |
||
15 | |||
16 | $result = array_map(function ($group) { |
||
17 | $fingerprints = array_map(function ($item) { |
||
18 | return sprintf( |
||
19 | '%s, %s:%s', |
||
20 | isset($item[Patch::LABEL]) ? $item[Patch::LABEL] : '{no label}', |
||
21 | Patch::HASH, |
||
22 | isset($item[Patch::HASH]) && $item[Patch::HASH] ? $item[Patch::HASH] : '{no hash}' |
||
23 | ); |
||
24 | }, $group); |
||
25 | |||
26 | $keys = array_map(function ($key, $item) { |
||
27 | return sprintf('%s%s%s', $item[Patch::OWNER], Patch::SOURCE_INFO_SEPARATOR, $key); |
||
28 | }, array_keys($group), $group); |
||
29 | |||
30 | return array_combine($keys, $fingerprints); |
||
31 | |||
32 | }, $groups); |
||
33 | |||
34 | return $result; |
||
35 | } |
||
36 | |||
37 | public function createDetailedList(array $patches) |
||
38 | { |
||
39 | $result = array(); |
||
40 | |||
41 | $labelInfoMatcher = sprintf('/%s:(?P<hash>.*)/', Patch::HASH); |
||
42 | |||
43 | foreach ($patches as $target => $group) { |
||
44 | $result[$target] = array(); |
||
45 | |||
46 | if (!is_array($group)) { |
||
47 | continue; |
||
48 | } |
||
49 | |||
50 | foreach ($group as $sourceInfo => $label) { |
||
51 | $sourceConfig = explode(Patch::SOURCE_INFO_SEPARATOR, $sourceInfo); |
||
52 | |||
53 | $path = array_pop($sourceConfig); |
||
54 | $owner = array_pop($sourceConfig); |
||
55 | |||
56 | $labelConfig = explode(',', $label); |
||
57 | |||
58 | preg_match($labelInfoMatcher, trim(end($labelConfig)), $matches); |
||
59 | |||
60 | $result[$target][$path] = array( |
||
61 | 'path' => $path, |
||
62 | 'targets' => array($target), |
||
63 | 'source' => $path, |
||
64 | 'owner' => $owner ? $owner : Patch::OWNER_UNKNOWN, |
||
65 | 'label' => implode(',', array_slice($labelConfig, 0, -1)), |
||
66 | 'md5' => is_array($matches) && isset($matches['hash']) ? $matches['hash'] : null |
||
67 | ); |
||
68 | } |
||
69 | } |
||
70 | |||
71 | return $result; |
||
72 | } |
||
73 | |||
74 | public function createTargetsList(array $patches) |
||
75 | { |
||
76 | $result = array(); |
||
77 | |||
78 | foreach ($patches as $originName => $patchGroup) { |
||
79 | if (!is_array($patchGroup)) { |
||
80 | continue; |
||
81 | } |
||
82 | |||
83 | foreach ($patchGroup as $patchPath => $patchInfo) { |
||
84 | foreach ($patchInfo[Patch::TARGETS] as $target) { |
||
85 | if (!isset($result[$target])) { |
||
86 | $result[$target] = array(); |
||
87 | } |
||
88 | |||
89 | $path = (isset($patchInfo['url']) && $patchInfo['url']) ? $patchInfo['url'] : $patchPath; |
||
90 | |||
91 | $result[$target][$path] = array_replace( |
||
92 | $patchInfo, |
||
93 | array(Patch::ORIGIN => $originName) |
||
94 | ); |
||
95 | } |
||
96 | } |
||
97 | } |
||
98 | |||
99 | return $result; |
||
100 | } |
||
101 | |||
102 | public function groupItemsByTarget(array $patchesList) |
||
122 | } |
||
123 | |||
124 | public function createOriginList(array $patchesList) |
||
125 | { |
||
126 | $result = array(); |
||
127 | |||
128 | foreach ($patchesList as $group) { |
||
129 | foreach ($group as $path => $patch) { |
||
130 | $origin = $patch[Patch::ORIGIN]; |
||
131 | |||
132 | if (!isset($result[$origin])) { |
||
133 | $result[$origin] = array(); |
||
134 | } |
||
135 | |||
136 | if (isset($result[$origin][$path])) { |
||
137 | continue; |
||
138 | } |
||
139 | |||
140 | $result[$origin][$path] = array_diff_key($patch, array(Patch::ORIGIN => true)); |
||
141 | } |
||
142 | } |
||
143 | |||
144 | return array_filter($result); |
||
145 | } |
||
146 | |||
147 | public function sanitizeFileSystem(array $patches) |
||
156 | } |
||
157 | } |
||
158 | } |
||
159 | |||
160 | public function getAllTargets(array $patches) |
||
161 | { |
||
162 | $targetList = array(); |
||
163 | |||
164 | foreach ($patches as $patchGroup) { |
||
165 | foreach ($patchGroup as $patchInfo) { |
||
166 | $targetList = array_merge( |
||
167 | $targetList, |
||
168 | $patchInfo[Patch::TARGETS] |
||
169 | ); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | return array_values( |
||
174 | array_unique($targetList) |
||
175 | ); |
||
176 | } |
||
177 | |||
178 | public function applyDefinitionFilter(array $patches, $filter, $key) |
||
179 | { |
||
180 | foreach ($patches as &$packagePatches) { |
||
181 | foreach ($packagePatches as &$patchInfo) { |
||
182 | if (!isset($patchInfo[$key])) { |
||
183 | $patchInfo = false; |
||
184 | |||
185 | continue; |
||
186 | } |
||
187 | |||
188 | if ($this->shouldIncludePatch($patchInfo[$key], $filter)) { |
||
189 | continue; |
||
190 | } |
||
191 | |||
192 | $patchInfo = false; |
||
193 | } |
||
194 | } |
||
195 | |||
196 | return array_filter( |
||
197 | array_map('array_filter', $patches) |
||
198 | ); |
||
199 | } |
||
200 | |||
201 | private function shouldIncludePatch($value, $filter) |
||
202 | { |
||
203 | if (is_array($value) && preg_grep($filter, $value)) { |
||
204 | return true; |
||
205 | } |
||
206 | |||
207 | if (is_string($value) && preg_match($filter, $value)) { |
||
208 | return true; |
||
209 | } |
||
210 | |||
211 | if (is_bool($filter) && $value === $filter) { |
||
212 | return true; |
||
213 | } |
||
214 | |||
215 | return false; |
||
216 | } |
||
217 | |||
218 | public function getRelatedPatches(array $patchesList, array $targets) |
||
219 | { |
||
220 | $scanTargets = $targets; |
||
221 | |||
222 | $targetsStack = array(); |
||
223 | |||
224 | $result = array(); |
||
225 | |||
226 | do { |
||
227 | $targetsUpdates = array(); |
||
228 | |||
229 | foreach ($patchesList as $owner => $patches) { |
||
230 | foreach ($patches as $patchPath => $patchInfo) { |
||
231 | if (!array_intersect($patchInfo[Patch::TARGETS], $scanTargets)) { |
||
232 | continue; |
||
233 | } |
||
234 | |||
235 | if (!isset($result[$owner])) { |
||
236 | $result[$owner] = array(); |
||
237 | } |
||
238 | |||
239 | $result[$owner][$patchPath] = $patchInfo; |
||
240 | |||
241 | $targetsUpdates = array_merge($targetsUpdates, $patchInfo[Patch::TARGETS]); |
||
242 | } |
||
243 | } |
||
244 | |||
245 | $targetsStack = array_unique( |
||
246 | array_merge($targetsStack, $scanTargets) |
||
247 | ); |
||
248 | |||
249 | $scanTargets = array_diff($targetsUpdates, $targetsStack, $scanTargets); |
||
250 | } while ($scanTargets); |
||
|
|||
251 | |||
252 | return $result; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @SuppressWarnings(PHPMD.BooleanArgumentFlag) |
||
257 | * |
||
258 | * @param array $patches |
||
259 | * @param array|bool|string $update |
||
260 | * @param bool $onlyNew |
||
261 | * @return array |
||
262 | */ |
||
263 | public function embedInfoToItems(array $patches, $update, $onlyNew = false) |
||
264 | { |
||
265 | foreach ($patches as $target => $group) { |
||
266 | foreach (array_keys($group) as $path) { |
||
267 | $patches[$target][$path] = is_array($update) |
||
268 | ? array_replace( |
||
269 | $patches[$target][$path], |
||
270 | $onlyNew ? array_diff_key($update, array_filter($patches[$target][$path])) : $update |
||
271 | ) |
||
272 | : $update; |
||
273 | } |
||
274 | } |
||
275 | |||
276 | return $patches; |
||
277 | } |
||
278 | |||
279 | public function filterListByTargets(array $patches, array $targets) |
||
292 | } |
||
293 | |||
294 | public function mergeLists(array $listA, array $listB) |
||
295 | { |
||
296 | $result = array(); |
||
297 | |||
298 | $keys = array_unique( |
||
299 | array_merge(array_keys($listA), array_keys($listB)) |
||
300 | ); |
||
301 | |||
302 | foreach ($keys as $key) { |
||
303 | $result[$key] = array_replace( |
||
304 | isset($listA[$key]) ? $listA[$key] : array(), |
||
305 | isset($listB[$key]) ? $listB[$key] : array() |
||
306 | ); |
||
307 | } |
||
308 | |||
309 | return $result; |
||
310 | } |
||
311 | |||
312 | public function getAllPaths($patches) |
||
313 | { |
||
314 | return array_reduce( |
||
315 | $patches, |
||
316 | function ($result, array $group) { |
||
317 | return array_merge( |
||
318 | $result, |
||
319 | array_values( |
||
320 | array_map(function (array $item) { |
||
321 | return $item[Patch::PATH] ? $item[Patch::PATH] : $item[Patch::URL]; |
||
322 | }, $group) |
||
323 | ) |
||
324 | ); |
||
325 | }, |
||
326 | array() |
||
327 | ); |
||
328 | } |
||
329 | |||
330 | public function diffListsByPath(array $listA, array $listB) |
||
331 | { |
||
332 | $pathFlags = array_fill_keys($this->getAllPaths($listB), true); |
||
333 | |||
334 | return array_map(function (array $group) use ($pathFlags) { |
||
335 | return array_filter( |
||
336 | $group, |
||
337 | function (array $item) use ($pathFlags) { |
||
338 | $path = $item[Patch::PATH] ? $item[Patch::PATH] : $item[Patch::URL]; |
||
339 | |||
340 | return !isset($pathFlags[$path]); |
||
341 | } |
||
342 | ); |
||
343 | }, $listA); |
||
344 | } |
||
345 | |||
346 | public function intersectListsByPath(array $listA, array $listB) |
||
347 | { |
||
348 | $pathFlags = array_fill_keys($this->getAllPaths($listB), true); |
||
349 | |||
350 | return array_map(function (array $group) use ($pathFlags) { |
||
351 | return array_filter( |
||
352 | $group, |
||
353 | function (array $item) use ($pathFlags) { |
||
354 | $path = $item[Patch::PATH] ? $item[Patch::PATH] : $item[Patch::URL]; |
||
355 | |||
356 | return isset($pathFlags[$path]); |
||
357 | } |
||
358 | ); |
||
359 | }, $listA); |
||
360 | } |
||
361 | |||
362 | public function diffListsByName(array $listA, array $listB) |
||
373 | } |
||
374 | |||
375 | public function intersectListsByName(array $listA, array $listB) |
||
376 | { |
||
377 | $result = array(); |
||
378 | |||
379 | foreach ($listB as $target => $group) { |
||
380 | if (!isset($listA[$target])) { |
||
381 | continue; |
||
382 | } |
||
383 | |||
384 | $result[$target] = array_intersect_key($listA[$target], $group); |
||
385 | } |
||
386 | |||
387 | return $result; |
||
388 | } |
||
389 | |||
390 | public function updateStatuses(array $patches, $status) |
||
391 | { |
||
392 | return array_map(function (array $group) use ($status) { |
||
393 | return array_map(function (array $patch) use ($status) { |
||
394 | return array_replace($patch, array( |
||
395 | Patch::STATUS => $status |
||
396 | )); |
||
397 | }, $group); |
||
398 | }, $patches); |
||
399 | } |
||
400 | |||
401 | public function extractValue($patches, array $keys) |
||
427 | ); |
||
428 | } |
||
429 | } |
||
430 |
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.