PageRenderTime 34ms CodeModel.GetById 9ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

/libraries/joomla/event/dispatcher.php

https://gitlab.com/vitaliylukin91/alex-lavka
PHP | 278 lines | 134 code | 33 blank | 111 comment | 21 complexity | 25a1351f58781b353f52c0bf88c19a67 MD5 | raw file
  1<?php
  2/**
  3 * @package     Joomla.Platform
  4 * @subpackage  Event
  5 *
  6 * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
  7 * @license     GNU General Public License version 2 or later; see LICENSE
  8 */
  9
 10defined('JPATH_PLATFORM') or die;
 11
 12/**
 13 * Class to handle dispatching of events.
 14 *
 15 * This is the Observable part of the Observer design pattern
 16 * for the event architecture.
 17 *
 18 * @link   https://docs.joomla.org/Tutorial:Plugins Plugin tutorials
 19 * @see    JPlugin
 20 * @since  12.1
 21 */
 22class JEventDispatcher extends JObject
 23{
 24	/**
 25	 * An array of Observer objects to notify
 26	 *
 27	 * @var    array
 28	 * @since  11.3
 29	 */
 30	protected $_observers = array();
 31
 32	/**
 33	 * The state of the observable object
 34	 *
 35	 * @var    mixed
 36	 * @since  11.3
 37	 */
 38	protected $_state = null;
 39
 40	/**
 41	 * A multi dimensional array of [function][] = key for observers
 42	 *
 43	 * @var    array
 44	 * @since  11.3
 45	 */
 46	protected $_methods = array();
 47
 48	/**
 49	 * Stores the singleton instance of the dispatcher.
 50	 *
 51	 * @var    JEventDispatcher
 52	 * @since  11.3
 53	 */
 54	protected static $instance = null;
 55
 56	/**
 57	 * Returns the global Event Dispatcher object, only creating it
 58	 * if it doesn't already exist.
 59	 *
 60	 * @return  JEventDispatcher  The EventDispatcher object.
 61	 *
 62	 * @since   11.1
 63	 */
 64	public static function getInstance()
 65	{
 66		if (self::$instance === null)
 67		{
 68			self::$instance = new static;
 69		}
 70
 71		return self::$instance;
 72	}
 73
 74	/**
 75	 * Get the state of the JEventDispatcher object
 76	 *
 77	 * @return  mixed    The state of the object.
 78	 *
 79	 * @since   11.3
 80	 */
 81	public function getState()
 82	{
 83		return $this->_state;
 84	}
 85
 86	/**
 87	 * Registers an event handler to the event dispatcher
 88	 *
 89	 * @param   string  $event    Name of the event to register handler for
 90	 * @param   string  $handler  Name of the event handler
 91	 *
 92	 * @return  void
 93	 *
 94	 * @since   11.1
 95	 * @throws  InvalidArgumentException
 96	 */
 97	public function register($event, $handler)
 98	{
 99		// Are we dealing with a class or callback type handler?
100		if (is_callable($handler))
101		{
102			// Ok, function type event handler... let's attach it.
103			$method = array('event' => $event, 'handler' => $handler);
104			$this->attach($method);
105		}
106		elseif (class_exists($handler))
107		{
108			// Ok, class type event handler... let's instantiate and attach it.
109			$this->attach(new $handler($this));
110		}
111		else
112		{
113			throw new InvalidArgumentException('Invalid event handler.');
114		}
115	}
116
117	/**
118	 * Triggers an event by dispatching arguments to all observers that handle
119	 * the event and returning their return values.
120	 *
121	 * @param   string  $event  The event to trigger.
122	 * @param   array   $args   An array of arguments.
123	 *
124	 * @return  array  An array of results from each function call.
125	 *
126	 * @since   11.1
127	 */
128	public function trigger($event, $args = array())
129	{
130		$result = array();
131
132		/*
133		 * If no arguments were passed, we still need to pass an empty array to
134		 * the call_user_func_array function.
135		 */
136		$args = (array) $args;
137
138		$event = strtolower($event);
139
140		// Check if any plugins are attached to the event.
141		if (!isset($this->_methods[$event]) || empty($this->_methods[$event]))
142		{
143			// No Plugins Associated To Event!
144			return $result;
145		}
146
147		// Loop through all plugins having a method matching our event
148		foreach ($this->_methods[$event] as $key)
149		{
150			// Check if the plugin is present.
151			if (!isset($this->_observers[$key]))
152			{
153				continue;
154			}
155
156			// Fire the event for an object based observer.
157			if (is_object($this->_observers[$key]))
158			{
159				$args['event'] = $event;
160				$value = $this->_observers[$key]->update($args);
161			}
162			// Fire the event for a function based observer.
163			elseif (is_array($this->_observers[$key]))
164			{
165				$value = call_user_func_array($this->_observers[$key]['handler'], $args);
166			}
167
168			if (isset($value))
169			{
170				$result[] = $value;
171			}
172		}
173
174		return $result;
175	}
176
177	/**
178	 * Attach an observer object
179	 *
180	 * @param   object  $observer  An observer object to attach
181	 *
182	 * @return  void
183	 *
184	 * @since   11.3
185	 */
186	public function attach($observer)
187	{
188		if (is_array($observer))
189		{
190			if (!isset($observer['handler']) || !isset($observer['event']) || !is_callable($observer['handler']))
191			{
192				return;
193			}
194
195			// Make sure we haven't already attached this array as an observer
196			foreach ($this->_observers as $check)
197			{
198				if (is_array($check) && $check['event'] == $observer['event'] && $check['handler'] == $observer['handler'])
199				{
200					return;
201				}
202			}
203
204			$this->_observers[] = $observer;
205			$methods = array($observer['event']);
206		}
207		else
208		{
209			if (!($observer instanceof JEvent))
210			{
211				return;
212			}
213
214			// Make sure we haven't already attached this object as an observer
215			$class = get_class($observer);
216
217			foreach ($this->_observers as $check)
218			{
219				if ($check instanceof $class)
220				{
221					return;
222				}
223			}
224
225			$this->_observers[] = $observer;
226			$methods = array_diff(get_class_methods($observer), get_class_methods('JPlugin'));
227		}
228
229		end($this->_observers);
230		$key = key($this->_observers);
231
232		foreach ($methods as $method)
233		{
234			$method = strtolower($method);
235
236			if (!isset($this->_methods[$method]))
237			{
238				$this->_methods[$method] = array();
239			}
240
241			$this->_methods[$method][] = $key;
242		}
243	}
244
245	/**
246	 * Detach an observer object
247	 *
248	 * @param   object  $observer  An observer object to detach.
249	 *
250	 * @return  boolean  True if the observer object was detached.
251	 *
252	 * @since   11.3
253	 */
254	public function detach($observer)
255	{
256		$retval = false;
257
258		$key = array_search($observer, $this->_observers);
259
260		if ($key !== false)
261		{
262			unset($this->_observers[$key]);
263			$retval = true;
264
265			foreach ($this->_methods as &$method)
266			{
267				$k = array_search($key, $method);
268
269				if ($k !== false)
270				{
271					unset($method[$k]);
272				}
273			}
274		}
275
276		return $retval;
277	}
278}