Passed
Push — master ( d68e66...3a2ed0 )
by PHPinnacle
03:05
created

AmpProcessor::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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