Processor::handleTarget()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.8666
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
/*
4
 * This file is part of Transfer.
5
 *
6
 * For the full copyright and license information, please view the LICENSE file located
7
 * in the root directory.
8
 */
9
10
namespace Transfer\Processor;
11
12
use Psr\Log\LoggerAwareInterface;
13
use Psr\Log\LoggerInterface;
14
use Transfer\Adapter\SourceAdapterInterface;
15
use Transfer\Adapter\TargetAdapterInterface;
16
use Transfer\Adapter\Transaction\Request;
17
use Transfer\Adapter\Transaction\Response;
18
use Transfer\Exception\MissingResponseException;
19
use Transfer\Procedure\Procedure;
20
use Transfer\Storage\InMemoryStorage;
21
use Transfer\Storage\StorageInterface;
22
use Transfer\Storage\StorageStack;
23
use Transfer\Storage\StorageStackAwareInterface;
24
use Transfer\Worker\WorkerInterface;
25
26
/**
27
 * Partial processor implementation.
28
 */
29
abstract class Processor implements ProcessorInterface, LoggerAwareInterface, StorageStackAwareInterface
30
{
31
    /**
32
     * @var array Procedures
33
     */
34
    protected $procedures = array();
35
36
    /**
37
     * @var StorageStack Storage stack
38
     */
39
    protected $stack;
40
41
    /**
42
     * @var LoggerInterface Logger
43
     */
44
    protected $logger;
45
46 15
    public function __construct()
47
    {
48 15
        $this->stack = new StorageStack(array(
49 15
            'global' => new InMemoryStorage(),
50 15
        ));
51 15
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 10
    public function addProcedure(Procedure $procedure)
57
    {
58 10
        $this->procedures[] = $procedure;
59
60 10
        return $this;
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 1
    public function setStorageStack(StorageStack $stack)
67
    {
68 1
        $this->stack = $stack;
69
70 1
        return $this;
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76 2
    public function setLogger(LoggerInterface $logger)
77
    {
78 2
        $this->logger = $logger;
79
80 2
        return $this;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 10
    public function process()
87
    {
88 10
        $this->handleProcedures($this->procedures);
89 8
    }
90
91
    /**
92
     * Handles procedure.
93
     *
94
     * @param Procedure $procedure Procedure to handle
95
     */
96
    abstract protected function handleProcedure(Procedure $procedure);
97
98
    /**
99
     * Calls procedure handle.
100
     *
101
     * @param Procedure $procedure Procedure to handle
102
     */
103 10
    protected function handleProcedureOuter(Procedure $procedure)
104
    {
105 10
        $this->handleProcedure($procedure);
106 8
    }
107
108
    /**
109
     * Handles procedures.
110
     *
111
     * @param array $procedures Procedures to handle
112
     */
113 10
    protected function handleProcedures(array $procedures)
114
    {
115
        /** @var Procedure $procedure */
116 10
        foreach ($procedures as $procedure) {
117 10
            $this->handleProcedureOuter($procedure);
118
119 8
            if ($procedure->hasChildren()) {
120 2
                $this->handleProcedures($procedure->getChildren());
121 2
            }
122 8
        }
123 8
    }
124
125
    /**
126
     * Handles source.
127
     *
128
     * @param SourceAdapterInterface $adapter Source adapter
129
     * @param Request                $request Request to handle
130
     *
131
     * @throws MissingResponseException
132
     *
133
     * @return Response Source adapter response
134
     */
135 8
    protected function handleSource(SourceAdapterInterface $adapter, Request $request)
136
    {
137 8
        $this->injectDependencies($adapter);
138
139 8
        $response = $adapter->receive($request);
140
141 8
        if ($response === null) {
142 1
            throw new MissingResponseException($adapter);
143
        }
144
145 7
        return $response;
146
    }
147
148
    /**
149
     * Handles sources.
150
     *
151
     * @param array $sources Sources
152
     *
153
     * @return \Iterator Iterator for all source response objects
154
     */
155 1
    protected function handleSources(array $sources)
156
    {
157 1
        $responses = array();
158
159 1
        foreach ($sources as $source) {
160 1
            list($adapter, $request) = $source;
161 1
            $responses[] = $this->handleSource($adapter, $request);
162 1
        }
163
164 1
        $iterator = new \AppendIterator();
165
166
        /** @var Response $response */
167 1
        foreach ($responses as $response) {
168 1
            $iterator->append($response->getIterator());
169 1
        }
170
171 1
        return $iterator;
172
    }
173
174
    /**
175
     * Handles worker.
176
     *
177
     * @param WorkerInterface  $worker  Worker
178
     * @param mixed            $object  Object to handle
179
     * @param StorageInterface $storage Associated storage
180
     */
181 6
    protected function handleWorker(WorkerInterface $worker, $object, StorageInterface $storage)
182
    {
183 6
        $this->injectDependencies($worker);
184
185 6
        $modifiedObject = $worker->handle($object);
186
187 6
        if ($modifiedObject === null && $object !== null) {
188 2
            $storage->remove($object);
189 6
        } elseif ($modifiedObject !== $object) {
190 2
            $storage->remove($object);
191 2
            $storage->add($modifiedObject);
192 2
        }
193
194 6
        return $modifiedObject;
195
    }
196
197
    /**
198
     * Handles workers.
199
     *
200
     * @param array            $workers Workers
201
     * @param StorageInterface $storage Associated storage
202
     */
203 7
    protected function handleWorkers(array $workers, StorageInterface $storage)
204
    {
205 7
        foreach ($workers as $worker) {
206 6
            foreach ($storage->all() as $element) {
207 6
                $this->handleWorker($worker, $element, $storage);
208 6
            }
209 7
        }
210 7
    }
211
212
    /**
213
     * Handles target.
214
     *
215
     * @param TargetAdapterInterface $adapter Target adapter
216
     * @param Request                $request Request to handle
217
     *
218
     * @throws MissingResponseException
219
     *
220
     * @return Response Target adapter response
221
     */
222 6
    protected function handleTarget(TargetAdapterInterface $adapter, Request $request)
223
    {
224 6
        $this->injectDependencies($adapter);
225
226 6
        $response = $adapter->send($request);
227
228 6
        if ($response === null) {
229 1
            throw new MissingResponseException($adapter);
230
        }
231
232 5
        return $response;
233
    }
234
235
    /**
236
     * Handles targets.
237
     *
238
     * @param array   $targets Targets
239
     * @param Request $request Request to handle
240
     *
241
     * @return array Target responses
242
     */
243 7
    protected function handleTargets(array $targets, Request $request)
244
    {
245 7
        $responses = array();
246
247 7
        foreach ($targets as $target) {
248 6
            $responses[] = $this->handleTarget($target, $request);
249 6
        }
250
251 6
        return $responses;
252
    }
253
254
    /**
255
     * Returns next object for an iterator.
256
     *
257
     * @param \Iterator $iterator Iterator to return the next object for
258
     *
259
     * @return mixed|false Object or false, if no object can be returned
260
     */
261 7
    protected function nextObject(\Iterator $iterator)
262
    {
263 7
        if ($iterator->valid()) {
264 7
            $object = $iterator->current();
265
266 7
            $iterator->next();
267
268 7
            return $object;
269
        }
270
271 6
        return false;
272
    }
273
274
    /**
275
     * Creates scoped storage.
276
     *
277
     * @param string $scope Scope name
278
     *
279
     * @return InMemoryStorage Local storage
280
     */
281 7
    protected function createStorage($scope)
282
    {
283 7
        $storage = new InMemoryStorage();
284
285 7
        $this->stack->setScope($scope, $storage);
286
287 7
        return $storage;
288
    }
289
290
    /**
291
     * Injects dependencies.
292
     *
293
     * @param object $component Component
294
     */
295 8
    protected function injectDependencies($component)
296
    {
297 8
        if ($component instanceof StorageStackAwareInterface) {
298 2
            $component->setStorageStack($this->stack);
299 2
        }
300
301 8
        if ($component instanceof LoggerAwareInterface && $this->logger instanceof LoggerInterface) {
302 1
            $component->setLogger($this->logger);
303 1
        }
304 8
    }
305
306
    /**
307
     * Prepares local storage.
308
     *
309
     * @param mixed $object Initial object
310
     *
311
     * @return InMemoryStorage Local storage
312
     */
313 7
    protected function prepareLocalStorage($object)
314
    {
315 7
        $storage = $this->createStorage('local');
316 7
        $storage->add($object);
317
318 7
        return $storage;
319
    }
320
321
    /**
322
     * Merges local storage with global storage.
323
     *
324
     * @param StorageInterface $storage Local storage
325
     */
326 6
    protected function mergeStorage(StorageInterface $storage)
327
    {
328 6
        foreach ($storage->all() as $id => $object) {
329 5
            $this->stack->getScope('global')->add($object);
330 6
        }
331 6
    }
332
}
333