Completed
Push — dev ( 8ef4f2...ca2ae3 )
by Arnaud
07:16
created

TaskRunner::updateSources()   C

Complexity

Conditions 7
Paths 24

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 7

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 29
ccs 7
cts 7
cp 1
rs 6.7272
cc 7
eloc 15
nc 24
nop 3
crap 7
1
<?php
2
3
namespace JK\Sam\Task;
4
5
use Exception;
6
use JK\Sam\File\Locator;
7
use JK\Sam\Filter\FilterInterface;
8
use SplFileInfo;
9
10
class TaskRunner
11
{
12
    /**
13
     * @var FilterInterface[]
14
     */
15
    protected $filters;
16
17
    /**
18
     * @var Locator
19
     */
20
    protected $locator;
21
22
    /**
23
     * @var bool
24
     */
25
    protected $isDebug;
26
27
    /**
28 1
     * TaskRunner constructor.
29
     *
30 1
     * @param FilterInterface[] $filters
31 1
     * @param Locator $locator
32 1
     * @param bool $isDebug
33
     */
34
    public function __construct(array $filters, Locator $locator, $isDebug = false)
35
    {
36
        $this->filters = $filters;
37
        $this->locator = $locator;
38
        $this->isDebug = $isDebug;
39
    }
40 1
41
    /**
42
     * Run a task, load its sources before and call the clean method on the filter.
43
     *
44 1
     * @param Task $task
45 1
     * @throws Exception
46
     */
47
    public function run(Task $task)
48 1
    {
49 1
        // get configured filters for this task
50
        $filters = $task
51 1
            ->getConfiguration()
52
            ->getParameter('filters');
53 1
54
        // get sources files
55
        $sources = $this->fetchSources($task);
56 1
        $destinations = $this->fetchDestinations($task);
57
58
        foreach ($filters as $filterName) {
59 1
            // get current configured filter
60
            $filter = $this->getFilter($filterName);
61 1
62 1
            // filter the files supported by this filter
63 1
            $filteredSources = $this->filterSources($sources, $filter);
64
65
            // apply the filter
66 1
            $updatedSources = $filter->run($filteredSources, $destinations);
67
68
            // update new sources if exists
69 1
            if ($updatedSources === null) {
70 1
                $updatedSources = [];
71 1
            }
72
            $sources = $this->updateSources($sources, $filteredSources, $updatedSources);
73
        }
74
75
        if (!$this->isDebug) {
76
            foreach ($filters as $filterName) {
77
                // get current configured filter
78
                $filter = $this->getFilter($filterName);
79
80 1
                // clean the files generated by the filter
81
                $filter->clean();
82
            }
83 1
        }
84 1
    }
85
86
    /**
87 1
     * Return a filter by its name. Throw an exception if it is not exists.
88
     *
89
     * @param string $name
90
     * @return FilterInterface
91
     * @throws Exception
92
     */
93
    protected function getFilter($name)
94
    {
95
        // filters must exists in configured filters
96 1
        if (!array_key_exists($name, $this->filters)) {
97
            throw new Exception('Invalid filter '.$name.'. Check your mapping configuration');
98 1
        }
99
100 1
        return $this->filters[$name];
101
    }
102 1
103 1
    /**
104
     * Fetch the source files from the task and return and array of SplInfo.
105 1
     *
106
     * @param Task $task
107
     * @return array
108
     */
109
    protected function fetchSources(Task $task)
110
    {
111
        $sources = [];
112
113
        foreach ($task->getSources() as $source) {
114 1
            // locate new resource and merge them to the existing sources
115
            $sources = array_merge($sources, $this->locator->locate($source));
116 1
        }
117
118 1
        return $sources;
119
    }
120 1
121 1
    /**
122
     * Fetch the destination files from the task and return and array of SplInfo.
123 1
     *
124
     * @param Task $task
125
     * @return SplFileInfo[]
126
     */
127
    protected function fetchDestinations(Task $task)
128
    {
129
        $sources = [];
130
131
        foreach ($task->getDestinations() as $source) {
132
            // locate new resource and merge them to the existing sources
133
            $sources[] = new SplFileInfo($source);
134 1
        }
135
136 1
        return $sources;
137
    }
138
139 1
    /**
140 1
     * Filter only the sources supported by the current filter.
141
     *
142
     * @param SplFileInfo[] $sources
143
     * @param FilterInterface $filter
144 1
     * @return array
145 1
     * @throws Exception
146
     */
147
    protected function filterSources(array $sources, FilterInterface $filter)
148 1
    {
149
        $filteredSources = [];
150 1
151 1
        // if the filter supports no extension, there is an error
152 1
        if (!is_array($filter->getSupportedExtensions()) || !count($filter->getSupportedExtensions())) {
153 1
            throw new Exception('No supported extensions found for the filter '.$filter->getName());
154
        }
155 1
156
        foreach ($sources as $source) {
157
            $isExtensionSupported = in_array($source->getExtension(), $filter->getSupportedExtensions());
158
            $supportAllExtensions = in_array('*', $filter->getSupportedExtensions());
159
160
            if ($isExtensionSupported  || $supportAllExtensions) {
161
                $filteredSources[] = $this
162
                    ->locator
163
                    ->getNormalizer()
164
                    ->normalize($source);
165
            }
166
        }
167 1
168
        return $filteredSources;
169 1
    }
170
171
    /**
172 1
     * Remove the filtered files from the sources, and merge with the new ones.
173
     *
174 1
     * @param SplFileInfo[] $originalSources
175
     * @param SplFileInfo[] $filteredSources
176
     * @param SplFileInfo[] $updatedSources
177 1
     * @return SplFileInfo[]
178
     * @throws Exception
179 1
     */
180 1
    protected function updateSources(array $originalSources, array $filteredSources, array $updatedSources)
181 1
    {
182 1
        $sources = [];
183 1
        $filteredPath = [];
184
185 1
        foreach ($filteredSources as $filteredSource) {
186
            $filteredPath[] = $filteredSource->getPath();
187 1
        }
188
        // keep only the not filtered files
189 1
        foreach ($originalSources as $originalSource) {
190
191
            // if an original source is not used by the current filter, we keep it in the source list
192
            if (!in_array($originalSource->getPath(), $filteredPath)) {
193
                $sources[] = $originalSource;
194
            }
195
        }
196
        // check updated files
197
        foreach ($updatedSources as $index => $source) {
198
            if (is_string($source)) {
199
                $updatedSources[$index] = new SplFileInfo($source);
200
            } else if (!($source instanceof SplFileInfo)) {
201
                throw new Exception('Invalid source file type '.gettype($source));
202
            }
203
        }
204
        // merge with the new sources
205
        $sources = array_merge($sources, $updatedSources);
206
207
        return $sources;
208
    }
209
}
210