Passed
Push — master ( 1ff9eb...d68e66 )
by PHPinnacle
02:16
created

TaskProcessor   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
dl 0
loc 98
ccs 31
cts 31
cp 1
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 2
A intercept() 0 3 1
A coroutine() 0 3 2
A recoil() 0 17 3
B interrupt() 0 14 5
A execute() 0 8 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
            return $this->coroutine($callable(...$arguments), $token);
57 6
        }), $token);
58
    }
59
60
    /**
61
     * @param mixed     $value
62
     * @param TaskToken $token
63
     *
64
     * @return mixed
65
     */
66 5
    private function coroutine($value, TaskToken $token)
67
    {
68 5
        return $value instanceof \Generator ? new Coroutine($this->recoil($value, $token)) : $value;
69
    }
70
71
    /**
72
     * @param \Generator $generator
73
     * @param TaskToken  $token
74
     *
75
     * @return mixed
76
     */
77 2
    private function recoil(\Generator $generator, TaskToken $token)
78
    {
79 2
        while ($generator->valid()) {
80 2
            $token->guard();
81
82
            try {
83 2
                $key   = $generator->key();
84 2
                $value = $this->interrupt($key, $generator->current());
85
86 2
                $generator->send(yield $this->coroutine($value, $token));
87 2
            } catch (\Exception $error) {
88
                /** @scrutinizer ignore-call */
89 1
                $generator->throw($error);
90
            }
91
        }
92
93 1
        return $this->coroutine($generator->getReturn(), $token);
94
    }
95
96
    /**
97
     * @param int|string $key
98
     * @param mixed      $value
99
     *
100
     * @return mixed
101
     */
102 2
    private function interrupt($key, $value)
103
    {
104 2
        if (!\is_string($key) && \is_object($value)) {
105 1
            $key = \get_class($value);
106
        }
107
108 2
        if (isset($this->interruptions[$key])) {
109 1
            $interceptor = $this->interruptions[$key];
110
111 1
            $value = \is_array($value) ? $value : [$value];
112 1
            $value = $interceptor(...$value);
113
        }
114
115 2
        return $value;
116
    }
117
}
118