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

EventConfigurator::isCallable()   B

Complexity

Conditions 10
Paths 5

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 12
c 3
b 0
f 1
dl 0
loc 23
ccs 0
cts 7
cp 0
rs 7.6666
cc 10
nc 5
nop 1
crap 110

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\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