Passed
Push — master ( ac7767...ce6fb4 )
by PHPinnacle
06:06 queued 03:22
created

SignalDispatcher::__construct()   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 1
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
use Amp\Promise;
18
19
final class SignalDispatcher implements Dispatcher
20
{
21
    /**
22
     * @var HandlerRegistry
23
     */
24
    private $handlers;
25
26
    /**
27
     * @param HandlerRegistry $handlers
28
     */
29 5
    public function __construct(HandlerRegistry $handlers)
30
    {
31 5
        $this->handlers = $handlers;
32 5
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37 4
    public function dispatch($signal, ...$arguments): Promise
38
    {
39 4
        if (!$signal instanceof Signal) {
40 4
            $signal = Signal::create($signal, $arguments);
41
        }
42
43 4
        return new LazyPromise(function () use ($signal) {
44 4
            $handler = $this->handler($signal);
45 4
            $result  = $handler(...$signal->arguments());
46
47 3
            return $result instanceof \Generator ? new Coroutine($this->recoil($result)) : $result;
48 4
        });
49
    }
50
51
    /**
52
     * @param Signal $signal
53
     *
54
     * @return Handler
55
     */
56 4
    private function handler(Signal $signal): Handler
57
    {
58 4
        $name = $signal->name();
59
60 4
        return $this->handlers->get($name) ?: Handler::unknown($name);
61
    }
62
63
    /**
64
     * @param \Generator $generator
65
     *
66
     * @return mixed
67
     */
68 2
    private function recoil(\Generator $generator)
69
    {
70 2
        while ($generator->valid()) {
71
            try {
72 2
                $key     = $generator->key();
73 2
                $current = $generator->current();
74
75 2
                $generator->send(yield $this->adapt($key, $current));
76 2
            } catch (\Exception $error) {
77
                /** @scrutinizer ignore-call */
78 1
                $generator->throw($error);
79
            }
80
        }
81
82 1
        return $generator->getReturn();
83
    }
84
85
    /**
86
     * @param int|string $key
87
     * @param mixed      $value
88
     *
89
     * @return mixed
90
     */
91 2
    private function adapt($key, $value)
92
    {
93 2
        if ($value instanceof Signal) {
94 1
            return $this->dispatch($value);
95
        }
96
97 2
        if (\is_string($key)) {
98 1
            $current = \is_array($value) ? \array_values($value) : [$value];
99
100 1
            return $this->dispatch($key, ...$current);
101
        }
102
103 1
        return $value;
104
    }
105
}
106