Passed
Push — master ( 2d6ed9...31b4e9 )
by PHPinnacle
05:04
created

Processor::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
nc 1
nop 2
dl 0
loc 7
c 0
b 0
f 0
cc 1
ccs 5
cts 5
cp 1
crap 1
rs 10
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
use Amp\Promise;
18
19
final class Processor
20
{
21
    /**
22
     * @var callable[]
23
     */
24
    private $interruptions = [];
25
26
    /**
27
     * @var int
28
     */
29
    private $tasks = 0;
30
31
    /**
32
     * @param string   $interrupt
33
     * @param callable $interrupter
34
     */
35 6
    public function interrupt(string $interrupt, callable $interrupter): void
36
    {
37 6
        $this->interruptions[$interrupt] = $interrupter;
38 6
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43 8
    public function execute(callable $callable, ...$arguments): Task
44
    {
45 8
        $token = new Token();
46
47 8
        return new Task(++$this->tasks, new LazyPromise(function () use ($callable, $arguments, $token) {
48 8
            return $this->adapt($callable(...$arguments), $token);
49 8
        }), $token);
50
    }
51
52
    /**
53
     * @param mixed $value
54
     * @param Token $token
55
     *
56
     * @return mixed
57
     */
58 7
    private function adapt($value, Token $token)
59
    {
60 7
        return $value instanceof \Generator ? new Coroutine($this->recoil($value, $token)) : $value;
61
    }
62
63
    /**
64
     * @param \Generator $generator
65
     * @param Token      $token
66
     *
67
     * @return mixed
68
     */
69 2
    private function recoil(\Generator $generator, Token $token)
70
    {
71 2
        while ($generator->valid()) {
72 2
            $token->guard();
73
74
            try {
75 2
                $value = $this->intercept($generator->key(), $generator->current());
76
77 2
                $generator->send(yield $this->adapt($value, $token));
78 2
            } catch (\Exception $error) {
79
                /** @scrutinizer ignore-call */
80 1
                $generator->throw($error);
81
            }
82
        }
83
84 1
        return $this->adapt($generator->getReturn(), $token);
85
    }
86
87
    /**
88
     * @param int|string $key
89
     * @param mixed      $value
90
     *
91
     * @return mixed
92
     */
93 2
    private function intercept($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
            return $value;
101
        }
102
103 1
        $interceptor = $this->interruptions[$key];
104
105 1
        $value = \is_array($value) ? $value : [$value];
106
107 1
        return $interceptor(...$value);
108
    }
109
}
110