Completed
Pull Request — master (#294)
by
unknown
08:47
created

StepAggregator::process()   C

Complexity

Conditions 15
Paths 96

Size

Total Lines 58
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 36
CRAP Score 15.0044

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 58
ccs 36
cts 37
cp 0.973
rs 6.4661
cc 15
eloc 31
nc 96
nop 0
crap 15.0044

How to fix   Long Method    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
namespace Ddeboer\DataImport\Workflow;
4
5
use Ddeboer\DataImport\Exception;
6
use Ddeboer\DataImport\Exception\UnexpectedTypeException;
7
use Ddeboer\DataImport\Reader;
8
use Ddeboer\DataImport\Result;
9
use Ddeboer\DataImport\Step;
10
use Ddeboer\DataImport\Step\PriorityStep;
11
use Ddeboer\DataImport\Workflow;
12
use Ddeboer\DataImport\Writer;
13
use Psr\Log\LoggerInterface;
14
use Psr\Log\LoggerAwareInterface;
15
use Psr\Log\LoggerAwareTrait;
16
use Psr\Log\NullLogger;
17
18
/**
19
 * A mediator between a reader and one or more writers and converters
20
 *
21
 * @author David de Boer <[email protected]>
22
 */
23
class StepAggregator implements Workflow, LoggerAwareInterface
24
{
25
    use LoggerAwareTrait;
26
27
    /**
28
     * @var Reader
29
     */
30
    private $reader;
31
32
    /**
33
     * Identifier for the Import/Export
34
     *
35
     * @var string|null
36
     */
37
    private $name = null;
38
39
    /**
40
     * @var boolean
41
     */
42
    private $skipItemOnFailure = false;
43
44
    /**
45
     * @var \SplPriorityQueue
46
     */
47
    private $steps;
48
49
    /**
50
     * @var Writer[]
51
     */
52
    private $writers = [];
53
54
    /**
55
     * @var boolean
56
     */
57
    protected $shouldStop = false;
58
59
    /**
60
     * @param Reader $reader
61
     * @param string $name
62
     */
63 13
    public function __construct(Reader $reader, $name = null)
64
    {
65 13
        $this->name = $name;
66 13
        $this->reader = $reader;
67
68
        // Defaults
69 13
        $this->logger = new NullLogger();
70 13
        $this->steps = new \SplPriorityQueue();
71 13
    }
72
73
    /**
74
     * Add a step to the current workflow
75
     *
76
     * @param Step         $step
77
     * @param integer|null $priority
78
     *
79
     * @return $this
80
     */
81 6
    public function addStep(Step $step, $priority = null)
82
    {
83 6
        if (null === $priority) {
84 6
            $priority =  $step instanceof PriorityStep ? $step->getPriority() : null;
85 6
        }
86 6
        $priority = null === $priority ? 0 : $priority;
87
88 6
        $this->steps->insert($step, $priority);
89
90 6
        return $this;
91
    }
92
93
    /**
94
     * Add a new writer to the current workflow
95
     *
96
     * @param Writer $writer
97
     *
98
     * @return $this
99
     */
100 9
    public function addWriter(Writer $writer)
101
    {
102 9
        array_push($this->writers, $writer);
103
104 9
        return $this;
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110 11
    public function process()
111
    {
112 11
        $count      = 0;
113 11
        $exceptions = new \SplObjectStorage();
114 11
        $startTime  = new \DateTime;
115
116 11
        foreach ($this->writers as $writer) {
117 8
            $writer->prepare();
118 11
        }
119
120 11
        if (is_callable('pcntl_signal')) {
121 11
            pcntl_signal(SIGTERM, array($this, 'stop'));
122 11
            pcntl_signal(SIGINT, array($this, 'stop'));
123 11
        }
124
125
        // Read all items
126 11
        foreach ($this->reader as $index => $item) {
127
128 11
            if (is_callable('pcntl_signal_dispatch')) {
129 11
                pcntl_signal_dispatch();
130 11
            }
131
132 11
            if ($this->shouldStop) {
133
                break;
134
            }
135
136
            try {
137 11
                foreach (clone $this->steps as $step) {
138 5
                    if (false === $step->process($item)) {
139 2
                        continue 2;
140
                    }
141 9
                }
142
143 9
                if (!is_array($item) && !($item instanceof \ArrayAccess && $item instanceof \Traversable)) {
144 2
                    throw new UnexpectedTypeException($item, 'array');
145
                }
146
147 7
                foreach ($this->writers as $writer) {
148 6
                    $writer->writeItem($item);
149 6
                }
150 9
            } catch(Exception $e) {
151 3
                if (!$this->skipItemOnFailure) {
152 2
                    throw $e;
153
                }
154
155 1
                $exceptions->attach($e, $index);
156 1
                $this->logger->error($e->getMessage());
157
            }
158
159 7
            $count++;
160 9
        }
161
162 9
        foreach ($this->writers as $writer) {
163 6
            $writer->finish();
164 9
        }
165
166 9
        return new Result($this->name, $startTime, new \DateTime, $count, $exceptions);
167
    }
168
169
    /**
170
     * Stops processing and force return Result from process() function
171
     */
172
    public function stop()
173
    {
174
        $this->shouldStop = true;
175
    }
176
177
    /**
178
     * Sets the value which determines whether the item should be skipped when error occures
179
     *
180
     * @param boolean $skipItemOnFailure When true skip current item on process exception and log the error
181
     *
182
     * @return $this
183
     */
184 1
    public function setSkipItemOnFailure($skipItemOnFailure)
185
    {
186 1
        $this->skipItemOnFailure = $skipItemOnFailure;
187
188 1
        return $this;
189
    }
190
191
    /**
192
     * @return string
193
     */
194
    public function getName()
195
    {
196
        return $this->name;
197
    }
198
}
199