Completed
Push — master ( a3185b...20774e )
by Nazar
04:43
created

Event::construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
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 2
			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 2
			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
	public function once ($event, callable $callback) {
93 10
		$wrapped_callback = function (...$arguments) use (&$wrapped_callback, $event, $callback) {
94 8
			$this->off($event, $wrapped_callback);
95 8
			return $callback(...$arguments);
96 10
		};
97 10
		return $this->on($event, $wrapped_callback);
98
	}
99
	/**
100
	 * Fire event
101
	 *
102
	 * After event name it is possible to specify as many arguments as needed
103
	 *
104
	 * @param string  $event For example `admin/System/modules/disable`
105
	 * @param mixed[] $arguments
106
	 *
107
	 * @return bool
108
	 */
109 88
	public function fire ($event, ...$arguments) {
110
		if (
111 88
			!$event ||
112 88
			!isset($this->callbacks[$event])
113
		) {
114 84
			return true;
115
		}
116 72
		foreach ($this->callbacks[$event] as $callback) {
117 72
			if ($callback(...$arguments) === false) {
118 70
				return false;
119
			}
120
		}
121 70
		return true;
122
	}
123
	/**
124
	 * @return string[]
125
	 */
126 90
	protected function events_files_paths () {
127 90
		$paths = [];
128 90
		foreach (get_files_list(MODULES, false, 'd', true) as $path) {
129 84
			if (file_exists("$path/events.php")) {
130 84
				$paths[] = "$path/events.php";
131
			}
132
		}
133 90
		return $paths;
134
	}
135
}
136