Completed
Push — master ( 69a790...3f79ab )
by Nazar
04:58
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 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 3
c 1
b 1
f 0
nc 2
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
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 72
	protected function construct () {
25 72
		foreach ($this->events_files_paths() as $path) {
26 66
			include $path;
27
		}
28 72
	}
29 72
	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 72
		if ($this->__request_id === 1) {
35 28
			$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 72
		if ($this->__request_id > 1) {
42 2
			$this->callbacks = $this->callbacks_cache;
43
		}
44 72
	}
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 72
	public function on ($event, $callback) {
54 72
		if (!$event || !is_callable($callback)) {
55 2
			return $this;
56
		}
57 72
		$this->callbacks[$event][] = $callback;
58 72
		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 10
	public function once ($event, $callback) {
93 10
		if (!$event || !is_callable($callback)) {
94 2
			return $this;
95
		}
96 10
		$wrapped_callback = function (...$arguments) use (&$wrapped_callback, $event, $callback) {
97 8
			$this->off($event, $wrapped_callback);
98 8
			return $callback(...$arguments);
99 10
		};
100 10
		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 70
	public function fire ($event, ...$arguments) {
113
		if (
114 70
			!$event ||
115 70
			!isset($this->callbacks[$event])
116
		) {
117 66
			return true;
118
		}
119 56
		foreach ($this->callbacks[$event] as $callback) {
120 56
			if ($callback(...$arguments) === false) {
121 54
				return false;
122
			}
123
		}
124 54
		return true;
125
	}
126
	/**
127
	 * @return string[]
128
	 */
129 72
	protected function events_files_paths () {
130 72
		$paths = [];
131 72
		foreach (get_files_list(MODULES, false, 'd', true) as $path) {
132 66
			if (file_exists("$path/events.php")) {
133 66
				$paths[] = "$path/events.php";
134
			}
135
		}
136 72
		return $paths;
137
	}
138
}
139