Passed
Push — master ( 826a3d...cef8d3 )
by Allan
02:36 queued 10s
created

PatchListUtils::shouldIncludePatch()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 7
nc 4
nop 2
dl 0
loc 15
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright © Vaimo Group. All rights reserved.
4
 * See LICENSE_VAIMO.txt for license details.
5
 */
6
namespace Vaimo\ComposerPatches\Utils;
7
8
use Vaimo\ComposerPatches\Patch\Definition as Patch;
9
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)
103
    {
104
        $result = array();
105
106
        foreach ($patchesList as $origin => $group) {
107
            if (!isset($result[$origin])) {
108
                $result[$origin] = array();
109
            }
110
111
            foreach ($group as $path => $patch) {
112
                foreach ($patch[Patch::TARGETS] as $target) {
113
                    $result[$target][$path] = array_replace(
114
                        $patch,
115
                        array(Patch::ORIGIN => $origin)
116
                    );
117
                }
118
            }
119
        }
120
121
        return array_filter($result);
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)
148
    {
149
        foreach ($patches as $patchGroup) {
150
            foreach ($patchGroup as $patchInfo) {
151
                if (!isset($patchInfo[Patch::TMP]) || !$patchInfo[Patch::TMP]) {
152
                    continue;
153
                }
154
155
                unlink($patchInfo[Patch::PATH]);
156
            }
157
        }
158
    }
159
160
    public function createFlatList(array $patches)
161
    {
162
        $result = array();
163
164
        foreach ($patches as $patchGroup) {
165
            foreach ($patchGroup as $patchInfo) {
166
                $result[] = $patchInfo;
167
            }
168
        }
169
170
        return $result;
171
    }
172
    
173
    public function getAllTargets(array $patches)
174
    {
175
        $targetList = array();
176
177
        foreach ($patches as $patchGroup) {
178
            foreach ($patchGroup as $patchInfo) {
179
                $targetList = array_merge(
180
                    $targetList,
181
                    $patchInfo[Patch::TARGETS]
182
                );
183
            }
184
        }
185
186
        return array_values(
187
            array_unique($targetList)
188
        );
189
    }
190
191
    public function applyDefinitionFilter(array $patches, $filter, $key)
192
    {
193
        foreach ($patches as &$packagePatches) {
194
            foreach ($packagePatches as &$patchInfo) {
195
                if (!isset($patchInfo[$key])) {
196
                    $patchInfo = false;
197
                    
198
                    continue;
199
                }
200
                
201
                if ($this->shouldIncludePatch($patchInfo[$key], $filter)) {
202
                    continue;
203
                }
204
205
                $patchInfo = false;
206
            }
207
        }
208
209
        return array_filter(
210
            array_map('array_filter', $patches)
211
        );
212
    }
213
    
214
    private function shouldIncludePatch($value, $filter)
215
    {
216
        if (is_array($value) && preg_grep($filter, $value)) {
217
            return true;
218
        }
219
220
        if (is_string($value) && preg_match($filter, $value)) {
221
            return true;
222
        }
223
224
        if (is_bool($filter) && $value === $filter) {
225
            return true;
226
        }
227
        
228
        return false;
229
    }
230
231
    public function getRelatedPatches(array $patchesList, array $targets)
232
    {
233
        $scanTargets = $targets;
234
235
        $targetsStack = array();
236
237
        $result = array();
238
239
        do {
240
            $targetsUpdates = array();
241
242
            foreach ($patchesList as $owner => $patches) {
243
                foreach ($patches as $patchPath => $patchInfo) {
244
                    if (!array_intersect($patchInfo[Patch::TARGETS], $scanTargets)) {
245
                        continue;
246
                    }
247
248
                    if (!isset($result[$owner])) {
249
                        $result[$owner] = array();
250
                    }
251
252
                    $result[$owner][$patchPath] = $patchInfo;
253
254
                    $targetsUpdates = array_merge($targetsUpdates, $patchInfo[Patch::TARGETS]);
255
                }
256
            }
257
258
            $targetsStack = array_unique(
259
                array_merge($targetsStack, $scanTargets)
260
            );
261
262
            $scanTargets = array_diff($targetsUpdates, $targetsStack, $scanTargets);
263
        } while ($scanTargets);
0 ignored issues
show
Bug Best Practice introduced by
The expression $scanTargets 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 empty(..) or ! empty(...) instead.

Loading history...
264
265
        return $result;
266
    }
267
268
    /**
269
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
270
     *
271
     * @param array $patches
272
     * @param array|bool|string $update
273
     * @param bool $onlyNew
274
     * @return array
275
     */
276
    public function embedInfoToItems(array $patches, $update, $onlyNew = false)
277
    {
278
        foreach ($patches as $target => $group) {
279
            foreach (array_keys($group) as $path) {
280
                $patches[$target][$path] = is_array($update)
281
                    ? array_replace(
282
                        $patches[$target][$path],
283
                        $onlyNew ? array_diff_key($update, array_filter($patches[$target][$path])) : $update
284
                    )
285
                    : $update;
286
            }
287
        }
288
289
        return $patches;
290
    }
291
    
292
    public function filterListByTargets(array $patches, array $targets)
293
    {
294
        foreach ($patches as $target => $group) {
295
            foreach ($group as $path => $patch) {
296
                if (array_intersect($patch[Patch::TARGETS], $targets)) {
297
                    continue;
298
                }
299
300
                unset($patches[$target][$path]);
301
            }
302
        }
303
        
304
        return array_filter($patches);
305
    }
306
    
307
    public function mergeLists(array $listA, array $listB)
308
    {
309
        $result = array();
310
311
        $keys = array_unique(
312
            array_merge(array_keys($listA), array_keys($listB))
313
        );
314
        
315
        foreach ($keys as $key) {
316
            $result[$key] = array_replace(
317
                isset($listA[$key]) ? $listA[$key] : array(),
318
                isset($listB[$key]) ? $listB[$key] : array()
319
            );
320
        }
321
322
        return $result;
323
    }
324
    
325
    public function getAllPaths($patches)
326
    {
327
        return array_reduce(
328
            $patches,
329
            function ($result, array $group) {
330
                return array_merge(
331
                    $result,
332
                    array_values(
333
                        array_map(function (array $item) {
334
                            return $item[Patch::PATH] ? $item[Patch::PATH] : $item[Patch::URL];
335
                        }, $group)
336
                    )
337
                );
338
            },
339
            array()
340
        );
341
    }
342
    
343
    public function diffListsByPath(array $listA, array $listB)
344
    {
345
        $pathFlags = array_fill_keys($this->getAllPaths($listB), true);
346
347
        return array_map(function (array $group) use ($pathFlags) {
348
            return array_filter(
349
                $group,
350
                function (array $item) use ($pathFlags) {
351
                    $path = $item[Patch::PATH] ? $item[Patch::PATH] : $item[Patch::URL];
352
                    
353
                    return !isset($pathFlags[$path]);
354
                }
355
            );
356
        }, $listA);
357
    }
358
    
359
    public function intersectListsByPath(array $listA, array $listB)
360
    {
361
        $pathFlags = array_fill_keys($this->getAllPaths($listB), true);
362
363
        return array_map(function (array $group) use ($pathFlags) {
364
            return array_filter(
365
                $group,
366
                function (array $item) use ($pathFlags) {
367
                    $path = $item[Patch::PATH] ? $item[Patch::PATH] : $item[Patch::URL];
368
369
                    return isset($pathFlags[$path]);
370
                }
371
            );
372
        }, $listA);
373
    }
374
375
    public function diffListsByName(array $listA, array $listB)
376
    {
377
        foreach ($listB as $target => $group) {
378
            if (!isset($listA[$target])) {
379
                $listA[$target] = array();
380
            }
381
382
            $listA[$target] = array_diff_key($listA[$target], $group);
383
        }
384
385
        return $listA;
386
    }
387
388
    public function intersectListsByName(array $listA, array $listB)
389
    {
390
        $result = array();
391
        
392
        foreach ($listB as $target => $group) {
393
            if (!isset($listA[$target])) {
394
                continue;
395
            }
396
            
397
            $result[$target] = array_intersect_key($listA[$target], $group);
398
        }
399
400
        return $result;
401
    }
402
    
403
    public function updateStatuses(array $patches, $status)
404
    {
405
        return array_map(function (array $group) use ($status) {
406
            return array_map(function (array $patch) use ($status) {
407
                return array_replace($patch, array(
408
                    Patch::STATUS => $status
409
                ));
410
            }, $group);
411
        }, $patches);
412
    }
413
    
414
    public function extractValue($patches, array $keys)
415
    {
416
        return array_reduce(
417
            $patches,
418
            function (array $result, array $items) use ($keys) {
419
                $values = array_values(
420
                    array_map(function ($item) use ($keys) {
421
                        foreach ($keys as $key) {
422
                            if (!isset($item[$key])) {
423
                                continue;
424
                            }
425
                            
426
                            if (!$item[$key]) {
427
                                continue;
428
                            }
429
                            
430
                            return $item[$key];
431
                        }
432
                        
433
                        return null;
434
                    }, $items)
435
                );
436
437
                return array_merge($result, $values);
438
            },
439
            array()
440
        );
441
    }
442
}
443