Passed
Push — master ( 315034...3914e6 )
by Alexander
06:41
created

EventConfigurator::registerListeners()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 45
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 19.8291

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 10
eloc 25
c 4
b 1
f 0
nc 9
nop 1
dl 0
loc 45
ccs 14
cts 26
cp 0.5385
crap 19.8291
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Event;
6
7
use Psr\Container\ContainerExceptionInterface;
8
use Psr\Container\ContainerInterface;
9
use Yiisoft\EventDispatcher\Provider\AbstractProviderConfigurator;
10
use Yiisoft\EventDispatcher\Provider\Provider;
11
use Yiisoft\Injector\Injector;
12
13
final class EventConfigurator extends AbstractProviderConfigurator
14
{
15
    private Provider $listenerProvider;
16
17
    private ContainerInterface $container;
18
19 2
    public function __construct(Provider $listenerProvider, ContainerInterface $container)
20
    {
21 2
        $this->listenerProvider = $listenerProvider;
22 2
        $this->container = $container;
23 2
    }
24
25
    /**
26
     * @suppress PhanAccessMethodProtected
27
     *
28
     * @param array $eventListeners Event listener list in format ['eventName1' => [$listener1, $listener2, ...]]
29
     *
30
     * @throws InvalidEventConfigurationFormatException
31
     * @throws InvalidListenerConfigurationException
32
     */
33 2
    public function registerListeners(array $eventListeners): void
34
    {
35 2
        $container = $this->container;
36 2
        $injector = new Injector($container);
37
38 2
        foreach ($eventListeners as $eventName => $listeners) {
39 2
            if (!is_string($eventName)) {
40
                throw new InvalidEventConfigurationFormatException(
41
                    'Incorrect event listener format. Format with event name must be used.'
42
                );
43
            }
44
45 2
            if (!is_array($listeners)) {
46
                $type = $this->isCallable($listeners) ? 'callable' : gettype($listeners);
47
48
                throw new InvalidEventConfigurationFormatException(
49
                    "Event listeners for $eventName must be an array, $type given."
50
                );
51
            }
52
53 2
            foreach ($listeners as $callable) {
54
                try {
55 2
                    if (!$this->isCallable($callable)) {
56
                        $type = gettype($listeners);
57
58
                        throw new InvalidListenerConfigurationException(
59 2
                            "Listener must be a callable. $type given."
60
                        );
61
                    }
62
                } catch (ContainerExceptionInterface $exception) {
63
                    throw new InvalidListenerConfigurationException(
64
                        "Could not instantiate event listener or listener class has invalid configuration.",
65
                        0,
66
                        $exception
67
                    );
68
                }
69
70 2
                $listener = static function (object $event) use ($injector, $callable, $container) {
71 1
                    if (is_array($callable) && !is_object($callable[0])) {
72
                        $callable = [$container->get($callable[0]), $callable[1]];
73
                    }
74
75 1
                    return $injector->invoke($callable, [$event]);
76 2
                };
77 2
                $this->listenerProvider->attach($listener, $eventName);
78
            }
79
        }
80 2
    }
81
82 2
    private function isCallable($definition): bool
83
    {
84 2
        if (is_callable($definition)) {
85 2
            return true;
86
        }
87
88
        if (
89 1
            is_array($definition)
90 1
            && array_keys($definition) === [0, 1]
91 1
            && is_string($definition[0])
92 1
            && $this->container->has($definition[0])
93
        ) {
94 1
            $object = $this->container->get($definition[0]);
95
96 1
            return method_exists($object, $definition[1]);
97
        }
98
99
        return false;
100
    }
101
}
102