Passed
Push — master ( f2e35b...cd03c9 )
by Allan
04:05 queued 15s
created

QueueGenerator::resolveStatusCode()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 8
nc 8
nop 1
dl 0
loc 15
rs 9.2222
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\Repository\PatchesApplier;
7
8
use Vaimo\ComposerPatches\Patch\Definition as Patch;
9
10
class QueueGenerator
11
{
12
    /**
13
     * @var \Vaimo\ComposerPatches\Interfaces\ListResolverInterface
14
     */
15
    private $listResolver;
16
17
    /**
18
     * @var \Vaimo\ComposerPatches\Repository\State\Analyser
19
     */
20
    private $repoStateAnalyser;
21
    
22
    /**
23
     * @var \Vaimo\ComposerPatches\Utils\PatchListUtils
24
     */
25
    private $patchListUtils;
26
    
27
    /**
28
     * @param \Vaimo\ComposerPatches\Interfaces\ListResolverInterface $listResolver,
29
     * @param \Vaimo\ComposerPatches\Repository\State\Analyser $repoStateAnalyser
30
     */
31
    public function __construct(
32
        \Vaimo\ComposerPatches\Interfaces\ListResolverInterface $listResolver,
33
        \Vaimo\ComposerPatches\Repository\State\Analyser $repoStateAnalyser
34
    ) {
35
        $this->listResolver = $listResolver;
36
        $this->repoStateAnalyser = $repoStateAnalyser;
37
        
38
        $this->patchListUtils = new \Vaimo\ComposerPatches\Utils\PatchListUtils();
39
    }
40
41
    public function generateApplyQueue(array $patches, array $repositoryState)
42
    {
43
        $patchesQueue = $this->listResolver->resolvePatchesQueue($patches);
44
45
        $initialState = $this->listResolver->resolveInitialState($patchesQueue, $repositoryState);
46
47
        list($includes, $removals) = $this->resolveChangesInState($patches, $patchesQueue, $initialState);
48
        
49
        list($includesQueue, $removalsQueue) = $this->buildChangeQueues($includes, $removals, $patchesQueue);
50
        
51
        $affectedPatches = $this->resolveAffectedPatches($includes, $removals, $patches);
52
53
        $queue = array_reduce(
54
            array($affectedPatches, $includesQueue, $removalsQueue),
55
            array($this->patchListUtils, 'mergeLists'),
56
            array()
57
        );
58
        
59
        return $this->updateStatusMarkers($queue, $repositoryState);
60
    }
61
    
62
    private function updateStatusMarkers($patches, $repositoryState)
63
    {
64
        $patchesByTarget = $this->patchListUtils->createTargetsList(array_map('array_filter', $patches));
65
        $patchFootprints = $this->patchListUtils->createSimplifiedList($patchesByTarget);
66
67
        $staticItems = array();
68
        $changedItems = array();
69
        
70
        foreach ($patchFootprints as $target => $footprints) {
71
            if (!isset($repositoryState[$target])) {
72
                continue;
73
            }
74
            
75
            $staticItems[$target] = array_intersect_assoc($footprints, $repositoryState[$target]);
76
            $changedItems[$target] = array_diff_key(
77
                array_intersect_key($footprints, $repositoryState[$target]),
78
                $staticItems[$target]
79
            );
80
        }
81
82
        $changedItems = $this->patchListUtils->createDetailedList($changedItems);
83
        $staticItems = $this->patchListUtils->createDetailedList($staticItems);
84
        
85
        foreach ($patchesByTarget as $target => $items) {
86
            foreach ($items as $path => $item) {
87
                $item = array_replace($item, array(
88
                    Patch::STATUS_NEW => !isset($staticItems[$target][$path]) && !isset($changedItems[$target][$path]),
89
                    Patch::STATUS_CHANGED => isset($changedItems[$target][$path])
90
                ));
91
                
92
                $patchesByTarget[$target][$path] = array_replace($item, array(
93
                    Patch::STATUS => $this->resolveStatusCode($item)
94
                ));
95
            }
96
        }
97
        
98
        return $this->patchListUtils->mergeLists(
99
            $patches,
100
            $this->patchListUtils->createOriginList($patchesByTarget)
101
        );
102
    }
103
    
104
    private function resolveStatusCode(array $item)
105
    {
106
        $status = isset($item[Patch::STATUS])
107
            ? $item[Patch::STATUS]
108
            : '';
109
110
        if ($item[Patch::STATUS_NEW] && !$status) {
111
            $status = 'new';
112
        }
113
114
        if ($item[Patch::STATUS_CHANGED] && !$status) {
115
            $status = 'changed';
116
        }
117
        
118
        return $status;
119
    }
120
    
121
    private function resolveAffectedPatches($includes, $removals, $patches)
122
    {
123
        $queueTargets = $this->patchListUtils->getAllTargets(
124
            $this->patchListUtils->mergeLists($includes, $removals)
125
        );
126
127
        $affectedPatches = $this->patchListUtils->getRelatedPatches($patches, $queueTargets);
128
129
        $patchesByTarget = $this->patchListUtils->createTargetsList($affectedPatches);
130
        
131
        return $this->patchListUtils->createOriginList(
132
            $this->patchListUtils->diffListsByName($patchesByTarget, $removals)
133
        );
134
    }
135
    
136
    private function resolveChangesInState($patches, $patchesQueue, $repositoryState)
137
    {
138
        $relevantPatches = $this->listResolver->resolveRelevantPatches($patches, $patchesQueue);
139
140
        $removals = $this->repoStateAnalyser->collectPatchRemovals($repositoryState, $relevantPatches);
141
        $includes = $this->repoStateAnalyser->collectPatchIncludes($repositoryState, $relevantPatches);
142
        
143
        return array(array_filter($includes), array_filter($removals));
144
    }
145
    
146
    private function buildChangeQueues($includes, $removals, $patchesQueue)
147
    {
148
        $patchesQueueByTarget = $this->patchListUtils->createTargetsList($patchesQueue);
149
        
150
        $includesQueue = $this->patchListUtils->createOriginList(
151
            $this->patchListUtils->intersectListsByName($patchesQueueByTarget, $includes)
152
        );
153
154
        $removalsQueue = $this->patchListUtils->embedInfoToItems($removals, false);
155
        
156
        return array($includesQueue, $removalsQueue);
157
    }
158
    
159
    public function generateRemovalQueue(array $patches, array $repositoryState)
160
    {
161
        $state = $this->patchListUtils->createDetailedList($repositoryState);
162
163
        $stateMatches = $this->patchListUtils->intersectListsByName($state, $patches);
164
165
        $state = $this->patchListUtils->createSimplifiedList($stateMatches);
166
        
167
        $removals = $this->repoStateAnalyser->collectPatchRemovals(
168
            $state,
169
            array_map('array_filter', $patches)
170
        );
171
        
172
        return $this->patchListUtils->embedInfoToItems(
173
            array_filter($removals),
174
            array(
175
                Patch::STATUS => 'removed',
176
                Patch::STATUS_MATCH => true
177
            )
178
        );
179
    }
180
    
181
    public function generateResetQueue(array $patches)
182
    {
183
        $directTargets = array_keys($patches);
184
        
185
        $declaredTargets = $this->patchListUtils->getAllTargets(
186
            array_map('array_filter', $patches)
187
        );
188
        
189
        return array_unique(
190
            array_merge($directTargets, $declaredTargets)
191
        );
192
    }
193
}
194