Passed
Push — master ( 9e2269...1ff9eb )
by PHPinnacle
04:22
created

TaskProcessor::interrupt()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 7
nc 6
nop 2
crap 5
1
<?php
2
/**
3
 * This file is part of PHPinnacle/Ensign.
4
 *
5
 * (c) PHPinnacle Team <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types = 1);
12
13
namespace PHPinnacle\Ensign;
14
15
use Amp\LazyPromise;
16
use Amp\Coroutine;
17
18
final class TaskProcessor implements Processor
19
{
20
    /**
21
     * @var ArgumentsResolver
22
     */
23
    private $resolver;
24
25
    /**
26
     * @var callable[]
27
     */
28
    private $interruptions = [];
29
30
    /**
31
     * @param ArgumentsResolver $resolver
32
     */
33 7
    public function __construct(ArgumentsResolver $resolver = null)
34
    {
35 7
        $this->resolver = $resolver ?: new Resolver\EmptyResolver();
36 7
    }
37
38
    /**
39
     * @param string   $interrupt
40
     * @param callable $interrupter
41
     */
42 4
    public function intercept(string $interrupt, callable $interrupter): void
43
    {
44 4
        $this->interruptions[$interrupt] = $interrupter;
45 4
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 6
    public function execute(callable $callable, ...$arguments): Task
51
    {
52 6
        $token     = new TaskToken();
53 6
        $arguments = (new Arguments($arguments))->inject($this->resolver->resolve($callable));
54
55 6
        return new Task(new LazyPromise(function () use ($callable, $arguments, $token) {
56 6
            $result = $callable(...$arguments);
57
58 5
            return $result instanceof \Generator ? new Coroutine($this->recoil($result, $token)) : $result;
59 6
        }), $token);
60
    }
61
62
    /**
63
     * @param \Generator $generator
64
     * @param TaskToken  $token
65
     *
66
     * @return mixed
67
     */
68 2
    private function recoil(\Generator $generator, TaskToken $token)
69
    {
70 2
        while ($generator->valid()) {
71 2
            $token->guard();
72
73
            try {
74 2
                $key     = $generator->key();
75 2
                $current = $generator->current();
76
77 2
                $generator->send(yield $this->interrupt($key, $current));
78 2
            } catch (\Exception $error) {
79
                /** @scrutinizer ignore-call */
80 1
                $generator->throw($error);
81
            }
82
        }
83
84 1
        return $generator->getReturn();
85
    }
86
87
    /**
88
     * @param int|string $key
89
     * @param mixed      $value
90
     *
91
     * @return mixed
92
     */
93 2
    private function interrupt($key, $value)
94
    {
95 2
        if (!\is_string($key) && \is_object($value)) {
96 1
            $key = \get_class($value);
97
        }
98
99 2
        if (isset($this->interruptions[$key])) {
100 1
            $interceptor = $this->interruptions[$key];
101
102 1
            $value = \is_array($value) ? $value : [$value];
103 1
            $value = $interceptor(...$value);
104
        }
105
106 2
        return $value;
107
    }
108
}
109