Completed
Push — master ( 932cc5...b796f0 )
by Andrii
12:16
created

ConfigurableEmitter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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