Completed
Push — 6.0 ( b19574...b50b1c )
by liu
02:56
created

Event::subscribe()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 9.0581

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 6
nop 1
dl 0
loc 23
ccs 5
cts 11
cp 0.4545
crap 9.0581
rs 9.6111
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
class Event
1 ignored issue
show
Coding Style introduced by
Missing doc comment for class Event
Loading history...
16
{
17
    /**
18
     * 监听者
19
     * @var array
20
     */
21
    protected $listener = [];
22
23
    /**
24
     * 观察者
25
     * @var array
26
     */
27
    protected $observer = [];
28
29
    /**
30
     * 事件别名
31
     * @var array
32
     */
33
    protected $bind = [
34
        'AppInit'  => event\AppInit::class,
35
        'HttpRun'  => event\HttpRun::class,
36
        'HttpEnd'  => event\HttpEnd::class,
37
        'LogLevel' => event\LogLevel::class,
38
        'LogWrite' => event\LogWrite::class,
39
    ];
40
41
    /**
42
     * 是否需要事件响应
43
     * @var bool
44
     */
45
    protected $withEvent = true;
46
47
    /**
48
     * 应用对象
49
     * @var App
50
     */
51
    protected $app;
52
53 6
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
54
    {
55 6
        $this->app = $app;
56 6
    }
57
58
    /**
59
     * 设置是否开启事件响应
60
     * @access protected
61
     * @param  bool $event 是否需要事件响应
62
     * @return $this
63
     */
64 6
    public function withEvent(bool $event)
65
    {
66 6
        $this->withEvent = $event;
67 6
        return $this;
68
    }
69
70
    /**
71
     * 批量注册事件监听
72
     * @access public
73
     * @param  array $events 事件定义
74
     * @return $this
75
     */
76 1
    public function listenEvents(array $events)
77
    {
78 1
        if (!$this->withEvent) {
79
            return $this;
80
        }
81
82 1
        foreach ($events as $event => $listeners) {
83
            if (isset($this->bind[$event])) {
84
                $event = $this->bind[$event];
85
            }
86
87
            $this->listener[$event] = array_merge($this->listener[$event] ?? [], $listeners);
88
        }
89
90 1
        return $this;
91
    }
92
93
    /**
94
     * 注册事件监听
95
     * @access public
96
     * @param  string $event    事件名称
97
     * @param  mixed  $listener 监听操作(或者类名)
98
     * @param  bool   $first    是否优先执行
99
     * @return $this
100
     */
101
    public function listen(string $event, $listener, bool $first = false)
102
    {
103
        if (!$this->withEvent) {
104
            return $this;
105
        }
106
107
        if (isset($this->bind[$event])) {
108
            $event = $this->bind[$event];
109
        }
110
111
        if ($first && isset($this->listener[$event])) {
112
            array_unshift($this->listener[$event], $listener);
113
        } else {
114
            $this->listener[$event][] = $listener;
115
        }
116
117
        return $this;
118
    }
119
120
    /**
121
     * 是否存在事件监听
122
     * @access public
123
     * @param  string $event 事件名称
124
     * @return bool
125
     */
126
    public function hasListen(string $event): bool
127
    {
128
        if (isset($this->bind[$event])) {
129
            $event = $this->bind[$event];
130
        }
131
132
        return isset($this->listener[$event]);
133
    }
134
135
    /**
136
     * 移除事件监听
137
     * @access public
138
     * @param  string $event 事件名称
139
     * @return $this
140
     */
141
    public function remove(string $event): void
142
    {
143
        if (isset($this->bind[$event])) {
144
            $event = $this->bind[$event];
145
        }
146
147
        unset($this->listener[$event]);
148
    }
149
150
    /**
151
     * 指定事件别名标识 便于调用
152
     * @access public
153
     * @param  array $events 事件别名
154
     * @return $this
155
     */
156 1
    public function bind(array $events)
157
    {
158 1
        $this->bind = array_merge($this->bind, $events);
159
160 1
        return $this;
161
    }
162
163
    /**
164
     * 注册事件订阅者
165
     * @access public
166
     * @param  mixed $subscriber 订阅者
167
     * @return $this
168
     */
169 1
    public function subscribe($subscriber)
170
    {
171 1
        if (!$this->withEvent) {
172
            return $this;
173
        }
174
175 1
        $subscribers = (array) $subscriber;
176
177 1
        foreach ($subscribers as $subscriber) {
0 ignored issues
show
introduced by
$subscriber is overwriting one of the parameters of this function.
Loading history...
178
            if (is_string($subscriber)) {
179
                $subscriber = $this->app->make($subscriber);
180
            }
181
182
            if (method_exists($subscriber, 'subscribe')) {
183
                // 手动订阅
184
                $subscriber->subscribe($this);
185
            } else {
186
                // 智能订阅
187
                $this->observe($subscriber);
188
            }
189
        }
190
191 1
        return $this;
192
    }
193
194
    /**
195
     * 自动注册事件观察者
196
     * @access public
197
     * @param  string|object $observer 观察者
198
     * @return $this
199
     */
200
    public function observe($observer)
201
    {
202
        if (!$this->withEvent) {
203
            return $this;
204
        }
205
206
        if (is_string($observer)) {
207
            $observer = $this->app->make($observer);
208
        }
209
210
        $events = array_keys($this->listener);
211
212
        foreach ($events as $event) {
213
            $method = 'on' . substr(strrchr($event, '\\'), 1);
214
215
            if (method_exists($observer, $method)) {
216
                $this->listen($event, [$observer, $method]);
217
            }
218
        }
219
220
        return $this;
221
    }
222
223
    /**
224
     * 触发事件
225
     * @access public
226
     * @param  string|object $event  事件名称
227
     * @param  mixed         $params 传入参数
228
     * @param  bool          $once   只获取一个有效返回值
229
     * @return mixed
230
     */
231 6
    public function trigger($event, $params = null, bool $once = false)
232
    {
233 6
        if (!$this->withEvent) {
234
            return;
235
        }
236
237 6
        if (is_object($event)) {
238
            $class = get_class($event);
239
            $this->app->instance($class, $event);
240
            $event = $class;
241
        }
242
243 6
        if (isset($this->bind[$event])) {
244 6
            $event = $this->bind[$event];
245
        }
246
247 6
        $listeners = $this->listener[$event] ?? [];
248
249 6
        $result = [];
250 6
        foreach ($listeners as $key => $listener) {
251
            $result[$key] = $this->dispatch($listener, $params);
252
253
            if (false === $result[$key] || (!is_null($result[$key]) && $once)) {
254
                break;
255
            }
256
        }
257
258 6
        return $once ? end($result) : $result;
259
    }
260
261
    /**
262
     * 执行事件调度
263
     * @access protected
264
     * @param  mixed $event  事件方法
265
     * @param  mixed $params 参数
266
     * @return mixed
267
     */
268
    protected function dispatch($event, $params = null)
269
    {
270
        if (!is_string($event)) {
271
            $call = $event;
272
        } elseif (strpos($event, '::')) {
273
            $call = $event;
274
        } else {
275
            $obj  = $this->app->make($event);
276
            $call = [$obj, 'handle'];
277
        }
278
279
        return $this->app->invoke($call, [$params]);
280
    }
281
282
}
283