Passed
Pull Request — master (#61)
by Viktor
10:41
created

EventConfigurator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 5
Bugs 0 Features 2
Metric Value
wmc 20
eloc 33
c 5
b 0
f 2
dl 0
loc 67
ccs 0
cts 38
cp 0
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B registerListeners() 0 24 9
A __construct() 0 4 1
B isCallable() 0 23 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Console\Config;
6
7
use Psr\Container\ContainerInterface;
8
use Yiisoft\EventDispatcher\Provider\AbstractProviderConfigurator;
9
use Yiisoft\EventDispatcher\Provider\Provider;
10
use Yiisoft\Injector\Injector;
11
12
class EventConfigurator extends AbstractProviderConfigurator
13
{
14
    private Provider $listenerProvider;
15
16
    private ContainerInterface $container;
17
18
    public function __construct(Provider $listenerProvider, ContainerInterface $container)
19
    {
20
        $this->listenerProvider = $listenerProvider;
21
        $this->container = $container;
22
    }
23
24
    /**
25
     * @suppress PhanAccessMethodProtected
26
     */
27
    public function registerListeners(array $eventsListeners): void
28
    {
29
        foreach ($eventsListeners as $eventName => $listeners) {
30
            if (!is_string($eventName)) {
31
                throw new \RuntimeException('Incorrect event listener format. Format with event name must be used.');
32
            }
33
34
            if (!is_array($listeners)) {
35
                $type = $this->isCallable($listeners) ? 'callable' : gettype($listeners);
36
                throw new \RuntimeException("Event listeners for $eventName must be an array, $type given.");
37
            }
38
            foreach ($listeners as $callable) {
39
                if (!$this->isCallable($callable)) {
40
                    $type = gettype($listeners);
41
                    throw new \RuntimeException("Listener must be a callable. $type given.");
42
                }
43
                if (is_array($callable) && !is_object($callable[0])) {
44
                    $callable = [$this->container->get($callable[0]), $callable[1]];
45
                }
46
47
                $this->listenerProvider
48
                    ->attach(
49
                        fn ($event) => (new Injector($this->container))->invoke($callable, [$event]),
50
                        $eventName
51
                    );
52
            }
53
        }
54
    }
55
56
    private function isCallable($definition): bool
57
    {
58
        if (is_callable($definition)) {
59
            return true;
60
        }
61
62
        if (is_array($definition) && array_keys($definition) === [0, 1]) {
63
            if (
64
                is_string($definition[0])
65
                && class_exists($definition[0])
66
                && in_array($definition[1], get_class_methods($definition[0]) ?? [], true)
67
            ) {
68
                return true;
69
            }
70
71
            if ((is_string($definition[0]) || is_object($definition[0])) && $this->container->has($definition[0])) {
72
                $object = $this->container->get($definition[0]);
73
74
                return method_exists($object, $definition[1]);
75
            }
76
        }
77
78
        return false;
79
    }
80
}
81