Completed
Push — 6.0 ( dbdaa9...b9ee63 )
by liu
05:09
created

Event::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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