ConfigurableEmitter::__set()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
c 0
b 0
f 0
rs 9.9666
cc 2
nc 2
nop 2
1
<?php
2
3
namespace hiapi\event;
4
5
use League\Event\Emitter;
6
use League\Event\EmitterInterface;
7
use League\Event\ListenerInterface;
8
use Psr\Container\ContainerInterface;
9
use yii\base\InvalidConfigException;
10
use yii\base\UnknownPropertyException;
11
use yii\di\Container;
12
use yii\helpers\StringHelper;
13
14
/**
15
 * Class ConfigurableEmitter
16
 *
17
 * @author Dmytro Naumenko <[email protected]>
18
 */
19
class ConfigurableEmitter extends Emitter implements EmitterInterface
20
{
21
    /**
22
     * @var ContainerInterface
23
     */
24
    private $container;
25
26
    /**
27
     * ConfigurableEmitter constructor.
28
     *
29
     * @param ContainerInterface $container
30
     */
31
    public function __construct(ContainerInterface $container)
32
    {
33
        $this->container = $container;
34
    }
35
36
    public function __set($name, $value)
37
    {
38
        if ($name === 'listeners') {
39
            $this->setListeners($value);
40
            return;
41
        }
42
43
        throw new UnknownPropertyException('Property "' . $name . '" is not available.');
44
    }
45
46
    /**
47
     * Allows to set listeners with standard Yii configuration system
48
     *
49
     * @param array[] $listeners
50
     * @return $this
51
     * @throws InvalidConfigException
52
     */
53
    public function setListeners(array $listeners = [])
54
    {
55
        foreach ($listeners as $listener) {
56
            if (!isset($listener['event']) || !isset($listener['listener'])) {
57
                throw new InvalidConfigException('Both "event" and "listener" properties are required to attach a listener.');
58
            }
59
60
            if (is_string($listener['listener'])) {
61
                $listener['listener'] = $this->listenerFromClassName($listener['listener']);
62
            }
63
64
            $this->addListener($listener['event'], $listener['listener'], $listener['priority'] ?? self::P_NORMAL);
65
        }
66
67
        return $this;
68
    }
69
70
    /**
71
     * @param $className
72
     * @return \Closure
73
     */
74
    private function listenerFromClassName(string $className): \Closure
75
    {
76
        return function ($event) use ($className) {
77
            /** @var ListenerInterface $handler */
78
            $listener = $this->container->get($className);
79
80
            $listener->handle($event);
81
        };
82
    }
83
84
    public function hasListeners($event)
85
    {
86
        if (parent::hasListeners($event)) {
87
            return true;
88
        }
89
90
        $namesWithWildcard = array_filter(array_keys($this->listeners), function ($name) {
91
            return $name !== '*' && strpos($name, '*') !== false;
92
        });
93
        foreach ($namesWithWildcard as $name) {
94
            if (StringHelper::matchWildcard('*', $name)) {
95
                return true;
96
            }
97
        }
98
99
        return false;
100
    }
101
102
    /**
103
     * Get the listeners sorted by priority for a given event.
104
     *
105
     * @param string $event
106
     *
107
     * @return ListenerInterface[]
108
     */
109
    protected function getSortedListeners($event)
110
    {
111
        if (! $this->hasListeners($event)) {
112
            return [];
113
        }
114
115
        $listeners = $this->listeners[$event] ?? [];
116
117
        if ($event !== '*') {
118
            $namesWithWildcard = array_filter(array_keys($this->listeners), function ($name) {
119
                return $name !== '*' && strpos($name, '*') !== false;
120
            });
121
            foreach ($namesWithWildcard as $name) {
122
                if (StringHelper::matchWildcard('*', $name)) {
123
                    $listeners = array_merge($listeners, $this->listeners[$name]);
124
                }
125
            }
126
        }
127
128
        if (empty($listeners)) {
129
            return [];
130
        }
131
132
        krsort($listeners);
133
134
        return call_user_func_array('array_merge', $listeners);
135
    }
136
}
137