getHook($event); // check whether someone is using a deprecated hook if (has_filter($bc)) { // trigger warning to inform the user that a manual adjustment is needed trigger_error( sprintf('expected %s hook, %s given', $event, $bc), E_USER_WARNING ); /** * Trigger the event for backward compatibility. * Assign the returned value to the first argument, * so that other plugins assigned to the correct * hook will be able to manipulate it. * * @since 10.1.32 * * @deprecated 10.2 Use the correct hook instead. */ $args[0] = apply_filters_ref_array($bc, $args); } } /** * Trigger the event. * Use `apply_filters_ref_array` instead of `do_action_ref_array` * to start supporting return values. * * @since 10.1.23 */ $return = apply_filters_ref_array($event, $args); if (is_null($return)) { // return an empty list as none manipulated the return value return array(); } // push the returned value within a list for Joomla standards return array($return); } /** * Registers an event handler to the event dispatcher * * @param string $event Name of the event to register handler for. * @param string $handler Name of the event handler. * * @return void * * @since 10.1.30 * @throws InvalidArgumentException */ public function register($event, $handler) { // are we dealing with a class or callback type handler? if (is_callable($handler)) { // function type event handler, let's attach it $method = array('event' => $event, 'handler' => $handler); $this->attach($method); } else if (class_exists($handler)) { // class type event handler, let's instantiate and attach it $this->attach(new $handler($this)); } else { throw new InvalidArgumentException('Invalid event handler.'); } } /** * Attach an observer object. * * @param mixed $observer An observer object to attach. * * @return void * * @since 10.1.29 */ public function attach($observer) { if (is_array($observer)) { if (!isset($observer['handler']) || !isset($observer['event']) || !is_callable($observer['handler'])) { return; } // make sure we haven't already attached this array as an observer foreach ($this->observers as $check) { if (is_array($check) && $check['event'] === $observer['event'] && $check['handler'] === $observer['handler']) { // callback already registered return; } } // obtain callback reflection and retrieve arguments $reflection = new ReflectionFunction($observer['handler']); $params = $reflection->getParameters(); // Register filter. // Always increase parameters counter by one in order to // accept the return value, which is never passed on Joomla. add_filter($observer['event'], $observer['handler'], 10, count($params) + 1); } else { // make sure we haven't already attached this object as an observer $class = get_class($observer); foreach ($this->observers as $check) { if ($check instanceof $class) { // class already observed return; } } // obtain class reflection $reflection = new ReflectionClass($observer); // retrieve all methods $methods = $reflection->getMethods(); // retrieve all JEvent methods $default = get_class_methods('JEvent'); foreach ($methods as $method) { // make sure the method is not already used by the parent class, // it is public and it is not static if (!in_array($method->name, $default) && $method->isPublic() && !$method->isStatic()) { // get method parameters $params = $method->getParameters(); /** * Refactor event name at runtime to support the * WordPress hooks notation. * * @since 10.1.32 */ $hook = $this->getHook($method->name); // Register filter. // Always increase parameters counter by one in order to // accept the return value, which is never passed on Joomla. add_filter($hook, array($observer, $method->name), 10, count($params) + 1); } } } // cache observer to avoid registering the same events more than once $this->observers[] = $observer; } /** * Checks whether the specified event uses the Joomla notation. * In that case, rebuild the event to look more similar to * WordPress hooks. * * @param string $event The event to check. * * @return string The modified event, if needed. * * @since 10.1.32 */ protected function getHook($event) { // make sure it starts with "on" if (preg_match("/^on[A-Z]/", $event)) { // remove initial "on" $event = preg_replace("/^on/", '', $event); // recover option from request $option = JFactory::getApplication()->input->get('option'); if ($option) { // clean "com_" from option $option = preg_replace("/^com_/", '', $option); // remove plugin name from event $event = preg_replace("/{$option}/i", '', $event); // always prepend plugin name at the beginning $event = strtolower($option) . $event; } // place an underscore between each camelCase $event = strtolower(preg_replace("/([a-z])([A-Z])/", '$1_$2', $event)); } return $event; } }