Skip to content

Refactor Event Manager #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
tests export-ignore
bin export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
phpcs.xml export-ignore
README.md export-ignore
LICENSE export-ignore
136 changes: 136 additions & 0 deletions EventManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php
/**
* Event Manager for events and listeners.
* Based on https://carlalexander.ca/designing-system-wordpress-event-management/
*
* @package WPMedia\EventManager
*/

namespace WPMedia\EventManager;

/**
* The event manager manages events using the WordPress plugin API.
*/
class EventManager
{
/**
* WordPress plugin API manager
*
* @var PluginApiManager
*/
private $plugin_api_manager;

/**
* Constructor
*
* @param PluginApiManager $plugin_api_manager WordPress plugin API manager.
*/
public function __construct(PluginApiManager $plugin_api_manager)
{
$this->plugin_api_manager = $plugin_api_manager;
}

/**
* Adds the given event listener to the list of event listeners
*
* @param string $event_name Name of the event.
* @param callable $listener Listener Callback function.
* @param int $priority Priority.
* @param int $accepted_args Number of arguments.
*/
public function addListener($event_name, $listener, $priority = 10, $accepted_args = 1)
{
$this->plugin_api_manager->addCallback($event_name, $listener, $priority, $accepted_args);
}

/**
* Adds an event subscriber.
*
* The event manager adds the given subscriber to the list of event listeners
* for all the events that it wants to listen to.
*
* @param SubscriberInterface $subscriber SubscriberInterface implementation.
*/
public function addSubscriber(SubscriberInterface $subscriber)
{
if ($subscriber instanceof EventManagerAwareSubscriberInterface) {
$subscriber->setEventManager($this);
}

foreach ($subscriber->getSubscribedEvents() as $event_name => $parameters) {
$this->addSubscriberListener($subscriber, $event_name, $parameters);
}
}

/**
* Removes the given event listener from the list of event listeners
* that listen to the given event.
*
* @param string $event_name Event name.
* @param callable $callback Callback.
* @param int $priority Priority.
*
* @return bool
*/
public function removeListener($event_name, $callback, $priority = 10)
{
return $this->plugin_api_manager->removeCallback($event_name, $callback, $priority);
}

/**
* Removes an event subscriber.
*
* The event manager removes the given subscriber from the list of event listeners
* for all the events that it wants to listen to.
*
* @param SubscriberInterface $subscriber SubscriberInterface implementation.
*/
public function removeSubscriber(SubscriberInterface $subscriber)
{
foreach ($subscriber->getSubscribedEvents() as $event_name => $parameters) {
$this->removeSubscriberListener($subscriber, $event_name, $parameters);
}
}

/**
* Adds the given subscriber listener to the list of event listeners
* that listen to the given event.
*
* @param SubscriberInterface $subscriber SubscriberInterface implementation.
* @param string $event_name Event name.
* @param mixed $parameters Parameters, can be a string, an array or a multidimensional array.
*/
private function addSubscriberListener(SubscriberInterface $subscriber, $event_name, $parameters)
{
if (is_string($parameters)) {
$this->addListener($event_name, [ $subscriber, $parameters ]);
} elseif (is_array($parameters) && count($parameters) !== count($parameters, COUNT_RECURSIVE)) {
foreach ($parameters as $parameter) {
$this->addSubscriberListener($subscriber, $event_name, $parameter);
}
} elseif (is_array($parameters) && isset($parameters[0])) {
$this->addListener($event_name, [ $subscriber, $parameters[0] ], isset($parameters[1]) ? $parameters[1] : 10, isset($parameters[2]) ? $parameters[2] : 1);
}
}

/**
* Removes the given subscriber listener to the list of event listeners
* that listen to the given event.
*
* @param SubscriberInterface $subscriber SubscriberInterface implementation.
* @param string $event_name Event name.
* @param mixed $parameters Parameters, can be a string, an array or a multidimensional array.
*/
private function removeSubscriberListener(SubscriberInterface $subscriber, $event_name, $parameters)
{
if (is_string($parameters)) {
$this->removeListener($event_name, [ $subscriber, $parameters ]);
} elseif (is_array($parameters) && count($parameters) !== count($parameters, COUNT_RECURSIVE)) {
foreach ($parameters as $parameter) {
$this->removeSubscriberListener($subscriber, $event_name, $parameter);
}
} elseif (is_array($parameters) && isset($parameters[0])) {
$this->removeListener($event_name, [ $subscriber, $parameters[0] ], isset($parameters[1]) ? $parameters[1] : 10);
}
}
}
18 changes: 18 additions & 0 deletions EventManagerAwareSubscriberInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
/**
* Interface for subscribers who need access to the event manager object
*
* @package WPMedia\EventManager
*/

namespace WPMedia\EventManager;

interface EventManagerAwareSubscriberInterface extends SubscriberInterface
{
/**
* Set the WordPress event manager for the subscriber.
*
* @param EventManager $event_manager EventManager instance.
*/
public function setEventManager(EventManager $event_manager);
}
102 changes: 102 additions & 0 deletions PluginApiManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/**
* Based on https://carlalexander.ca/designing-system-wordpress-event-management/
*
* @package WPMedia\EventManager
*/

namespace WPMedia\EventManager;

/**
* Wrapper class around the WordPress plugin API
*/
class PluginApiManager
{
/**
* Adds a callback to a specific hook of the WordPress plugin API.
*
* @uses add_filter()
*
* @param string $hook_name Name of the hook.
* @param callable $callback Callback function.
* @param int $priority Priority.
* @param int $accepted_args Number of arguments.
*/
public function addCallback($hook_name, $callback, $priority = 10, $accepted_args = 1)
{
add_filter($hook_name, $callback, $priority, $accepted_args);
}

/**
* Removes the given callback from the given hook. The WordPress plugin API only
* removes the hook if the callback and priority match a registered hook.
*
* @uses remove_filter()
*
* @param string $hook_name Hook name.
* @param callable $callback Callback.
* @param int $priority Priority.
*
* @return bool
*/
public function removeCallback($hook_name, $callback, $priority = 10)
{
return remove_filter($hook_name, $callback, $priority);
}

/**
* Checks the WordPress plugin API to see if the given hook has
* the given callback. The priority of the callback will be returned
* or false. If no callback is given will return true or false if
* there's any callbacks registered to the hook.
*
* @uses has_filter()
*
* @param string $hook_name Hook name.
* @param mixed $callback Callback.
*
* @return bool|int
*/
public function hasCallback($hook_name, $callback = false)
{
return has_filter($hook_name, $callback);
}

/**
* Get the name of the hook that WordPress plugin API is executing. Returns
* false if it isn't executing a hook.
*
* @uses current_filter()
*
* @return string|bool
*/
public function getCurrentHook()
{
return current_filter();
}

/**
* Executes all the callbacks registered with the given hook.
*
* @uses do_action()
*/
public function execute()
{
$args = func_get_args();
return call_user_func_array('do_action', $args);
}

/**
* Filters the given value by applying all the changes from the callbacks
* registered with the given hook. Returns the filtered value.
*
* @uses apply_filters()
*
* @return mixed
*/
public function filter()
{
$args = func_get_args();
return call_user_func_array('apply_filters', $args);
}
}
38 changes: 38 additions & 0 deletions SubscriberInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/**
* Interface for subscribers
*
* @package WPMedia\EventManager
*/

namespace WPMedia\EventManager;

/**
* A Subscriber knows what specific WordPress events it wants to listen to.
*
* When an EventManager adds a Subscriber, it gets all the WordPress events that
* it wants to listen to. It then adds the subscriber as a listener for each of them.
*/
interface SubscriberInterface
{
/**
* Returns an array of events that this subscriber wants to listen to.
*
* The array key is the event name. The value can be:
*
* * The method name
* * An array with the method name and priority
* * An array with the method name, priority and number of accepted arguments
* * An array containing arrays following the above patterns
*
* For instance:
*
* * array('event_name' => 'method_name')
* * array('event_name' => array('method_name', $priority))
* * array('event_name' => array('method_name', $priority, $accepted_args))
* * array('event_name' => array(array('method_name_1', $priority_1, $accepted_args_1)), array('method_name_2', $priority_2, $accepted_args_2)))
*
* @return array
*/
public static function getSubscribedEvents();
}
Loading