Completed
Pull Request — master (#1)
by Arnaud
58:13 queued 48:12
created

TaskRunner::filterSources()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 23
ccs 0
cts 10
cp 0
rs 8.5906
cc 6
eloc 13
nc 4
nop 2
crap 42
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
     * TaskRunner constructor.
29
     *
30
     * @param FilterInterface[] $filters
31
     * @param Locator $locator
32
     * @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
41
    /**
42
     * Run a task, load its sources before and call the clean method on the filter.
43
     *
44
     * @param Task $task
45
     * @throws Exception
46
     */
47
    public function run(Task $task)
48
    {
49
        // get configured filters for this task
50
        $filters = $task
51
            ->getConfiguration()
52
            ->getParameter('filters');
53
54
        // get sources files
55
        $sources = $this->fetchSources($task);
56
        $destinations = $this->fetchDestinations($task);
57
58
        foreach ($filters as $filterName) {
59
            // get current configured filter
60
            $filter = $this->getFilter($filterName);
61
62
            // filter the files supported by this filter
63
            $filteredSources = $this->filterSources($sources, $filter);
64
65
            // apply the filter
66
            $updatedSources = $filter->run($filteredSources, $destinations);
67
68
            // update new sources if exists
69
            if ($updatedSources === null) {
70
                $updatedSources = [];
71
            }
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
                // clean the files generated by the filter
81
                $filter->clean();
82
            }
83
        }
84
    }
85
86
    /**
87
     * 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
        if (!array_key_exists($name, $this->filters)) {
97
            throw new Exception('Invalid filter '.$name.'. Check your mapping configuration');
98
        }
99
100
        return $this->filters[$name];
101
    }
102
103
    /**
104
     * Fetch the source files from the task and return and array of SplInfo.
105
     *
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
            // locate new resource and merge them to the existing sources
115
            $sources = array_merge($sources, $this->locator->locate($source));
116
        }
117
118
        return $sources;
119
    }
120
121
    /**
122
     * Fetch the destination files from the task and return and array of SplInfo.
123
     *
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
        }
135
136
        return $sources;
137
    }
138
139
    /**
140
     * Filter only the sources supported by the current filter.
141
     *
142
     * @param SplFileInfo[] $sources
143
     * @param FilterInterface $filter
144
     * @return array
145
     * @throws Exception
146
     */
147
    protected function filterSources(array $sources, FilterInterface $filter)
148
    {
149
        $filteredSources = [];
150
151
        // if the filter supports no extension, there is an error
152
        if (!is_array($filter->getSupportedExtensions()) || !count($filter->getSupportedExtensions())) {
153
            throw new Exception('No supported extensions found for the filter '.$filter->getName());
154
        }
155
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
168
        return $filteredSources;
169
    }
170
171
    /**
172
     * Remove the filtered files from the sources, and merge with the new ones.
173
     *
174
     * @param SplFileInfo[] $originalSources
175
     * @param SplFileInfo[] $filteredSources
176
     * @param SplFileInfo[] $updatedSources
177
     * @return SplFileInfo[]
178
     * @throws Exception
179
     */
180
    protected function updateSources(array $originalSources, array $filteredSources, array $updatedSources)
181
    {
182
        $sources = [];
183
184
        // keep only the not filtered files
185
        foreach ($originalSources as $source) {
186
187
            if (!in_array($source, $filteredSources)) {
188
                $sources[] = $source;
189
            }
190
        }
191
        // check updated files
192
        foreach ($updatedSources as $index => $source) {
193
            if (is_string($source)) {
194
                $updatedSources[$index] = new SplFileInfo($source);
195
            } else if (!($source instanceof SplFileInfo)) {
196
                throw new Exception('Invalid source file type '.gettype($source));
197
            }
198
        }
199
        // merge with the new sources
200
        $sources = array_merge($sources, $updatedSources);
201
202
        return $sources;
203
    }
204
}
205