Workflow::processItem()   C
last analyzed

Complexity

Conditions 14
Paths 19

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 14

Importance

Changes 7
Bugs 1 Features 2
Metric Value
dl 0
loc 32
ccs 26
cts 26
cp 1
rs 5.0864
c 7
b 1
f 2
cc 14
eloc 21
nc 19
nop 2
crap 14

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of plumphp/plum.
5
 *
6
 * (c) Florian Eckerstorfer <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace Plum\Plum;
12
13
use Cocur\Vale\Vale;
14
use InvalidArgumentException;
15
use Plum\Plum\Converter\ConverterInterface;
16
use Plum\Plum\Filter\FilterInterface;
17
use Plum\Plum\Pipe\ConverterPipe;
18
use Plum\Plum\Pipe\FilterPipe;
19
use Plum\Plum\Pipe\AbstractPipe;
20
use Plum\Plum\Pipe\WriterPipe;
21
use Plum\Plum\Reader\ReaderInterface;
22
use Plum\Plum\Writer\WriterInterface;
23
24
/**
25
 * Workflow.
26
 *
27
 * @author    Florian Eckerstorfer <[email protected]>
28
 * @copyright 2014-2016 Florian Eckerstorfer
29
 */
30
class Workflow
31
{
32
    const APPEND  = 1;
33
    const PREPEND = 2;
34
35
    /**
36
     * @var AbstractPipe[]
37
     */
38
    private $pipeline = [];
39
40
    /**
41
     * @var array
42
     */
43
    private $options = [
44
        'resumeOnError' => false,
45
    ];
46
47
    /**
48
     * @param array $options
49
     *
50
     * @codeCoverageIgnore
51
     */
52
    public function __construct(array $options = [])
53
    {
54
        $this->options = array_merge($this->options, $options);
55
    }
56
57
    /**
58
     * @param string|null $type
59
     *
60
     * @return AbstractPipe[]
61
     */
62 2
    public function getPipeline($type = null)
63
    {
64 2
        $pipeline = [];
65
66 2
        foreach ($this->pipeline as $element) {
67 2
            if ($type === null || get_class($element) === $type) {
68 2
                $pipeline[] = $element;
69 2
            }
70 2
        }
71
72 2
        return $pipeline;
73
    }
74
75
    /**
76
     * Inserts an element into the pipeline at the given position.
77
     *
78
     * @param AbstractPipe $pipe
79
     *
80
     * @return Workflow
81
     */
82 13
    protected function addPipe(AbstractPipe $pipe)
83
    {
84 13
        if ($pipe->getPosition() === self::PREPEND) {
85 5
            array_unshift($this->pipeline, $pipe);
86 5
        } else {
87 13
            $this->pipeline[] = $pipe;
88
        }
89
90 13
        return $this;
91
    }
92
93
    /**
94
     * @param array|callable|FilterInterface $element
95
     *
96
     * @return Workflow
97
     *
98
     * @throws InvalidArgumentException
99
     */
100 11
    public function addFilter($element)
101
    {
102 11
        $pipe = FilterPipe::createFilter($element);
103
104 8
        return $this->addPipe($pipe);
105
    }
106
107
    /**
108
     * @return FilterPipe[]
109
     */
110 5
    public function getFilters()
111
    {
112 5
        return $this->getPipeline('Plum\Plum\Pipe\FilterPipe');
113
    }
114
115
    /**
116
     * @param ConverterInterface|callable|array $element
117
     *
118
     * @return Workflow $this
119
     */
120 13
    public function addConverter($element)
121
    {
122 13
        $pipe = ConverterPipe::createConverter($element);
123
124 10
        return $this->addPipe($pipe);
125
    }
126
127
    /**
128
     * @return ConverterPipe[]
129
     */
130 5
    public function getConverters()
131
    {
132 5
        return $this->getPipeline('Plum\Plum\Pipe\ConverterPipe');
133
    }
134
135
    /**
136
     * @param WriterInterface|array $element
137
     *
138
     * @return Workflow
139
     */
140 7
    public function addWriter($element)
141
    {
142 7
        $pipe = WriterPipe::createWriter($element);
143
144 4
        return $this->addPipe($pipe);
145
    }
146
147
    /**
148
     * @return WriterPipe[]
149
     */
150 3
    public function getWriters()
151
    {
152 3
        return $this->getPipeline('Plum\Plum\Pipe\WriterPipe');
153
    }
154
155
    /**
156
     * @param ReaderInterface[]|ReaderInterface $readers
157
     *
158
     * @return Result
159
     */
160 19
    public function process($readers)
161
    {
162 19
        if (!is_array($readers)) {
163 18
            $readers = [$readers];
164 18
        }
165
166 19
        $result = new Result();
167
168 19
        $this->prepareWriters($this->getWriters());
169
170 19
        foreach ($readers as $reader) {
171 19
            $this->processReader($reader, $result);
172 18
        }
173
174 18
        $this->finishWriters($this->getWriters());
175
176 18
        return $result;
177
    }
178
179
    /**
180
     * @param ReaderInterface $reader
181
     * @param Result          $result
182
     */
183 16
    protected function processReader(ReaderInterface $reader, Result $result)
184
    {
185 16
        foreach ($reader as $item) {
186 15
            $result->incReadCount();
187
            try {
188 15
                $this->processItem($item, $result);
189 15
            } catch (\Exception $e) {
190 2
                $result->addException($e);
191 2
                if (!$this->options['resumeOnError']) {
192 1
                    throw $e;
193
                }
194
            }
195 15
        }
196 15
    }
197
198
    /**
199
     * @param WriterPipe[] $writers
200
     */
201 5
    protected function prepareWriters($writers)
202
    {
203 5
        foreach ($writers as $element) {
204 5
            $element->getWriter()->prepare();
205 5
        }
206 5
    }
207
208
    /**
209
     * @param WriterPipe[] $writers
210
     */
211 5
    protected function finishWriters($writers)
212
    {
213 5
        foreach ($writers as $element) {
214 5
            $element->getWriter()->finish();
215 5
        }
216 5
    }
217
218
    /**
219
     * @param mixed  $item
220
     * @param Result $result
221
     */
222 18
    protected function processItem($item, Result $result)
223
    {
224 18
        $written = false;
225
226 18
        foreach ($this->pipeline as $element) {
227 18
            if ($element instanceof FilterPipe && $element->getField()) {
228 1
                if ($element->getFilter()->filter(Vale::get($item, $element->getField())) === false) {
229 1
                    return;
230
                }
231 18
            } elseif ($element instanceof FilterPipe) {
232 1
                if ($element->getFilter()->filter($item) === false) {
233 1
                    return;
234
                }
235 18
            } elseif ($element instanceof ConverterPipe && $element->getField()) {
236 4
                $item = $this->convertItemValue($item, $element);
237 18
            } elseif ($element instanceof ConverterPipe) {
238 7
                $item = $this->convertItem($item, $element);
239 5
                if ($item === null) {
240 1
                    return;
241
                }
242 15
            } elseif ($element instanceof WriterPipe) {
243 11
                if ($this->writeItem($item, $element) === true) {
244 10
                    $result->incWriteCount();
245 10
                    $written = true;
246 10
                }
247 11
            }
248 16
        }
249
250 16
        if ($written === true) {
251 10
            $result->incItemWriteCount();
252 10
        }
253 16
    }
254
255
    /**
256
     * Applies the given converter to the given item either if no filter is given or if the filter returns `true`.
257
     *
258
     * @param mixed         $item
259
     * @param ConverterPipe $pipe
260
     *
261
     * @return mixed
262
     */
263 5
    protected function convertItem($item, ConverterPipe $pipe)
264
    {
265 5
        $filterValue = $pipe->getFilterField() ? Vale::get($item, $pipe->getFilterField()) : $item;
266 5
        if ($pipe->getFilter() === null || $pipe->getFilter()->filter($filterValue) === true) {
267 4
            return $pipe->getConverter()->convert($item);
268
        }
269
270 2
        return $item;
271
    }
272
273
    /**
274
     * Applies the given converter to the given field in the given item if no filter is given or if the filters returns
275
     * `true` for the field.
276
     *
277
     * @param mixed         $item
278
     * @param ConverterPipe $pipe
279
     *
280
     * @return mixed
281
     */
282 4
    protected function convertItemValue($item, ConverterPipe $pipe)
283
    {
284 4
        $value       = Vale::get($item, $pipe->getField());
285 4
        $filterValue = $pipe->getFilterField() ? Vale::get($item, $pipe->getFilterField()) : $item;
286
287 4
        if ($pipe->getFilter() === null || $pipe->getFilter()->filter($filterValue) === true) {
288 3
            $item = Vale::set($item, $pipe->getField(), $pipe->getConverter()->convert($value));
289 3
        }
290
291 4
        return $item;
292
    }
293
294
    /**
295
     * Writes the given item to the given writer if the no filter is given or the filter returns `true`.
296
     *
297
     * @param mixed      $item
298
     * @param WriterPipe $pipe
299
     *
300
     * @return bool `true` if the item has been written, `false` if not.
301
     */
302 4
    protected function writeItem($item, WriterPipe $pipe)
303
    {
304 4
        if ($pipe->getFilter() === null || $pipe->getFilter()->filter($item) === true) {
305 3
            $pipe->getWriter()->writeItem($item);
306
307 3
            return true;
308
        }
309
310 1
        return false;
311
    }
312
}
313