Passed
Pull Request — master (#3)
by PHPinnacle
03:21
created

TaskProcessor::intercept()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
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;
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 (isset($this->interruptions[$key])) {
96 1
            $interceptor = $this->interruptions[$key];
97
98 1
            $value = \is_array($value) ? $value : [$value];
99 1
            $value = $interceptor(...$value);
100
        }
101
102 2
        return $value;
103
    }
104
}
105