Completed
Push — master ( 7e3ae5...a3185b )
by Nazar
04:30
created

Event::off()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.0067

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 3
nop 2
dl 0
loc 16
ccs 10
cts 11
cp 0.9091
crap 3.0067
rs 9.4285
c 0
b 0
f 0
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
 * @method static $this instance($check = false)
11
 */
12
class Event {
13
	use
14
		Singleton;
15
	const INIT_STATE_METHOD = 'init';
16
	/**
17
	 * @var callable[][]
18
	 */
19
	protected $callbacks = [];
20
	/**
21
	 * @var callable[][]
22
	 */
23
	protected $callbacks_cache;
24 90
	protected function construct () {
25 90
		foreach ($this->events_files_paths() as $path) {
26 84
			include $path;
27
		}
28 90
	}
29 90
	protected function init () {
30
		/**
31
		 * All events handlers registered before first request processing was started should be cached for further requests
32
		 */
33
		/** @noinspection PhpUndefinedFieldInspection */
34 90
		if ($this->__request_id === 1) {
35 44
			$this->callbacks_cache = $this->callbacks;
36
		}
37
		/**
38
		 * Starting from seconds request we'll take cache and use it as reference set of events handlers
39
		 */
40
		/** @noinspection PhpUndefinedFieldInspection */
41 90
		if ($this->__request_id > 1) {
42 16
			$this->callbacks = $this->callbacks_cache;
43
		}
44 90
	}
45
	/**
46
	 * Add event handler
47
	 *
48
	 * @param string   $event    For example `admin/System/modules/disable`
49
	 * @param callable $callback Callable, that will be called at event dispatching
50
	 *
51
	 * @return Event
52
	 */
53 90
	public function on ($event, callable $callback) {
54 90
		if (!$event) {
55
			return $this;
56
		}
57 90
		$this->callbacks[$event][] = $callback;
58 90
		return $this;
59
	}
60
	/**
61
	 * Remove event handler
62
	 *
63
	 * @param string        $event
64
	 * @param callable|null $callback If not specified - all callbacks for this event will be removed
65
	 *
66
	 * @return Event
67
	 */
68 8
	public function off ($event, $callback = null) {
69 8
		if (!isset($this->callbacks[$event])) {
70
			return $this;
71
		}
72 8
		if (!$callback) {
73 2
			unset($this->callbacks[$event]);
74 2
			return $this;
75
		}
76 8
		$this->callbacks[$event] = array_filter(
77 8
			$this->callbacks[$event],
78
			function ($c) use ($callback) {
79 8
				return $c !== $callback;
80 8
			}
81
		);
82 8
		return $this;
83
	}
84
	/**
85
	 * Similar to `::on()`, but but removes handler after handling of first event
86
	 *
87
	 * @param string   $event
88
	 * @param callable $callback
89
	 *
90
	 * @return Event
91
	 */
92 10
	public function once ($event, callable $callback) {
93 10
		if (!$event) {
94 2
			return $this;
95
		}
96 8
		$wrapped_callback = function (...$arguments) use (&$wrapped_callback, $event, $callback) {
97 6
			$this->off($event, $wrapped_callback);
98 6
			return $callback(...$arguments);
99 8
		};
100 8
		return $this->on($event, $wrapped_callback);
101
	}
102
	/**
103
	 * Fire event
104
	 *
105
	 * After event name it is possible to specify as many arguments as needed
106
	 *
107
	 * @param string  $event For example `admin/System/modules/disable`
108
	 * @param mixed[] $arguments
109
	 *
110
	 * @return bool
111
	 */
112 88
	public function fire ($event, ...$arguments) {
113
		if (
114 88
			!$event ||
115 88
			!isset($this->callbacks[$event])
116
		) {
117 84
			return true;
118
		}
119 72
		foreach ($this->callbacks[$event] as $callback) {
120 72
			if ($callback(...$arguments) === false) {
121 70
				return false;
122
			}
123
		}
124 70
		return true;
125
	}
126
	/**
127
	 * @return string[]
128
	 */
129 90
	protected function events_files_paths () {
130 90
		$paths = [];
131 90
		foreach (get_files_list(MODULES, false, 'd', true) as $path) {
132 84
			if (file_exists("$path/events.php")) {
133 84
				$paths[] = "$path/events.php";
134
			}
135
		}
136 90
		return $paths;
137
	}
138
}
139