Completed
Push — master ( 80acb7...286b6e )
by Nazar
04:18
created

Event::off()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 16
rs 9.4285
cc 3
eloc 11
nc 3
nop 2
1
<?php
2
/**
3
 * @package   CleverStyle CMS
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 Event instance($check = false)
15
 */
16
class Event {
17
	use Singleton;
18
	/**
19
	 * @var callable[][]
20
	 */
21
	protected $callbacks = [];
22
	/**
23
	 * @var bool
24
	 */
25
	protected $initialized = false;
26
	/**
27
	 * Add event handler
28
	 *
29
	 * @param string   $event    For example `admin/System/components/plugins/disable`
30
	 * @param callable $callback Callable, that will be called at event dispatching
31
	 *
32
	 * @return Event
33
	 */
34
	function on ($event, $callback) {
35
		if (!$event || !is_callable($callback)) {
36
			return $this;
37
		}
38
		$this->callbacks[$event][] = $callback;
39
		return $this;
40
	}
41
	/**
42
	 * Remove event handler
43
	 *
44
	 * @param string        $event
45
	 * @param callable|null $callback If not specified - all callbacks for this event will be removed
46
	 *
47
	 * @return Event
48
	 */
49
	function off ($event, $callback = null) {
50
		if (!isset($this->callbacks[$event])) {
51
			return $this;
52
		}
53
		if (!$callback) {
54
			unset($this->callbacks[$event]);
55
			return $this;
56
		}
57
		$this->callbacks[$event] = array_filter(
58
			$this->callbacks[$event],
59
			function ($c) use ($callback) {
60
				return $c !== $callback;
61
			}
62
		);
63
		return $this;
64
	}
65
	/**
66
	 * Similar to `::on()`, but but removes handler after handling of first event
67
	 *
68
	 * @param string   $event
69
	 * @param callable $callback
70
	 *
71
	 * @return Event
72
	 */
73
	function once ($event, $callback) {
74
		if (!$event || !is_callable($callback)) {
75
			return $this;
76
		}
77
		$wrapped_callback = function () use (&$wrapped_callback, $event, $callback) {
78
			$this->off($event, $wrapped_callback);
79
			call_user_func_array($callback, func_get_args());
80
		};
81
		return $this->on($event, $wrapped_callback);
82
	}
83
	/**
84
	 * Fire event
85
	 *
86
	 * After event name it is possible to specify as many arguments as needed
87
	 *
88
	 * @param string $event For example `admin/System/components/plugins/disable`
89
	 * @param mixed  $param1
90
	 * @param mixed  $_
91
	 *
92
	 * @return bool
93
	 */
94
	function fire ($event, $param1 = null, $_ = null) {
95
		if (!$this->initialized) {
96
			$this->initialize();
97
		}
98
		if (
99
			!$event ||
100
			!isset($this->callbacks[$event])
101
		) {
102
			return true;
103
		}
104
		$arguments = array_slice(func_get_args(), 1);
105
		foreach ($this->callbacks[$event] as $callback) {
106
			if (call_user_func_array($callback, $arguments) === false) {
107
				return false;
108
			}
109
		}
110
		return true;
111
	}
112
	/**
113
	 * Initialize all events handlers
114
	 */
115
	protected function initialize () {
116
		foreach ($this->events_files_paths() as $path) {
117
			include DIR."/$path";
118
		}
119
		$this->initialized = true;
120
	}
121
	/**
122
	 * @return string[]
123
	 */
124
	protected function events_files_paths () {
125
		return Cache::instance()->get(
126
			'events_files_paths',
127
			function () {
128
				$paths = [];
129
				foreach (get_files_list(MODULES, false, 'd', 'components/modules') as $path) {
130
					if (file_exists(DIR."/$path/events.php")) {
131
						$paths[] = "$path/events.php";
132
					}
133
				}
134
				foreach (get_files_list(PLUGINS, false, 'd', 'components/plugins') as $path) {
135
					if (file_exists(DIR."/$path/events.php")) {
136
						$paths[] = "$path/events.php";
137
					}
138
				}
139
				return $paths;
140
			}
141
		);
142
	}
143
}
144