Passed
Push — master ( cef8d3...1f0b7e )
by Allan
02:45
created

PatchListUtils::createFlatList()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 11
rs 10
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 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);
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...
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)
280
    {
281
        foreach ($patches as $target => $group) {
282
            foreach ($group as $path => $patch) {
283
                if (array_intersect($patch[Patch::TARGETS], $targets)) {
284
                    continue;
285
                }
286
287
                unset($patches[$target][$path]);
288
            }
289
        }
290
        
291
        return array_filter($patches);
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)
363
    {
364
        foreach ($listB as $target => $group) {
365
            if (!isset($listA[$target])) {
366
                $listA[$target] = array();
367
            }
368
369
            $listA[$target] = array_diff_key($listA[$target], $group);
370
        }
371
372
        return $listA;
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)
402
    {
403
        return array_reduce(
404
            $patches,
405
            function (array $result, array $items) use ($keys) {
406
                $values = array_values(
407
                    array_map(function ($item) use ($keys) {
408
                        foreach ($keys as $key) {
409
                            if (!isset($item[$key])) {
410
                                continue;
411
                            }
412
                            
413
                            if (!$item[$key]) {
414
                                continue;
415
                            }
416
                            
417
                            return $item[$key];
418
                        }
419
                        
420
                        return null;
421
                    }, $items)
422
                );
423
424
                return array_merge($result, $values);
425
            },
426
            array()
427
        );
428
    }
429
}
430