QueueGenerator   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 85
dl 0
loc 189
rs 10
c 2
b 0
f 0
wmc 19

9 Methods

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