Completed
Push — master ( b7b84b...78616b )
by Nazar
04:19
created

Event::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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