Completed
Push — master ( ccb78a...e0e64f )
by Nazar
04:41
created

Event   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 91.67%

Importance

Changes 0
Metric Value
dl 0
loc 137
ccs 55
cts 60
cp 0.9167
rs 10
c 0
b 0
f 0
wmc 26
lcom 1
cbo 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
B fire() 0 15 5
A register_events() 0 5 2
A init() 0 6 2
A on() 0 7 3
A off() 0 16 3
A once() 0 10 3
A ensure_events_registered() 0 8 3
B events_files_paths() 0 14 5
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2015-2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs;
9
/**
10
 * Event class
11
 *
12
 * Provides events subscribing and dispatching
13
 *
14
 * @method static $this instance($check = false)
15
 */
16
class Event {
17
	use
18
		Singleton;
19
	const INIT_STATE_METHOD = 'init';
20
	/**
21
	 * @var callable[][]
22
	 */
23
	protected $callbacks = [];
24
	/**
25
	 * @var callable[][]
26
	 */
27
	protected $callbacks_cache;
28 26
	protected function init () {
29
		/** @noinspection PhpUndefinedFieldInspection */
30 26
		if ($this->__request_id > 1) {
31 2
			$this->callbacks = [];
32
		}
33 26
	}
34
	/**
35
	 * Add event handler
36
	 *
37
	 * @param string   $event    For example `admin/System/components/plugins/disable`
38
	 * @param callable $callback Callable, that will be called at event dispatching
39
	 *
40
	 * @return Event
41
	 */
42 26
	function on ($event, $callback) {
43 26
		if (!$event || !is_callable($callback)) {
44 2
			return $this;
45
		}
46 26
		$this->callbacks[$event][] = $callback;
47 26
		return $this;
48
	}
49
	/**
50
	 * Remove event handler
51
	 *
52
	 * @param string        $event
53
	 * @param callable|null $callback If not specified - all callbacks for this event will be removed
54
	 *
55
	 * @return Event
56
	 */
57 2
	function off ($event, $callback = null) {
58 2
		if (!isset($this->callbacks[$event])) {
59 2
			return $this;
60
		}
61 2
		if (!$callback) {
62 2
			unset($this->callbacks[$event]);
63 2
			return $this;
64
		}
65 2
		$this->callbacks[$event] = array_filter(
66 2
			$this->callbacks[$event],
67
			function ($c) use ($callback) {
68 2
				return $c !== $callback;
69 2
			}
70
		);
71 2
		return $this;
72
	}
73
	/**
74
	 * Similar to `::on()`, but but removes handler after handling of first event
75
	 *
76
	 * @param string   $event
77
	 * @param callable $callback
78
	 *
79
	 * @return Event
80
	 */
81 4
	function once ($event, $callback) {
82 4
		if (!$event || !is_callable($callback)) {
83 2
			return $this;
84
		}
85 2
		$wrapped_callback = function (...$arguments) use (&$wrapped_callback, $event, $callback) {
86
			$this->off($event, $wrapped_callback);
87
			$callback(...$arguments);
88 2
		};
89 2
		return $this->on($event, $wrapped_callback);
90
	}
91
	/**
92
	 * Fire event
93
	 *
94
	 * After event name it is possible to specify as many arguments as needed
95
	 *
96
	 * @param string  $event For example `admin/System/components/plugins/disable`
97
	 * @param mixed[] $arguments
98
	 *
99
	 * @return bool
100
	 */
101 16
	function fire ($event, ...$arguments) {
102 16
		$this->ensure_events_registered();
103
		if (
104 16
			!$event ||
105 16
			!isset($this->callbacks[$event])
106
		) {
107 16
			return true;
108
		}
109 10
		foreach ($this->callbacks[$event] as $callback) {
110 10
			if ($callback(...$arguments) === false) {
111 10
				return false;
112
			}
113
		}
114 10
		return true;
115
	}
116
	/**
117
	 * Before firing events we need to ensure that events callbacks were registered
118
	 */
119 16
	protected function ensure_events_registered () {
120 16
		if (!$this->callbacks_cache) {
121 16
			$this->register_events();
122 16
			$this->callbacks_cache = $this->callbacks;
123 16
		} elseif (!$this->callbacks) {
124 2
			$this->callbacks = $this->callbacks_cache;
125
		}
126 16
	}
127
	/**
128
	 * Initialize all events handlers
129
	 */
130 16
	protected function register_events () {
131 16
		foreach ($this->events_files_paths() as $path) {
132 16
			include $path;
133
		}
134 16
	}
135
	/**
136
	 * @return string[]
137
	 */
138 16
	protected function events_files_paths () {
139 16
		$paths = [];
140 16
		foreach (get_files_list(MODULES, false, 'd', true) as $path) {
141 16
			if (file_exists("$path/events.php")) {
142 16
				$paths[] = "$path/events.php";
143
			}
144
		}
145 16
		foreach (get_files_list(PLUGINS, false, 'd', true) as $path) {
146 2
			if (file_exists("$path/events.php")) {
147 2
				$paths[] = "$path/events.php";
148
			}
149
		}
150 16
		return $paths;
151
	}
152
}
153