commit vendor
This commit is contained in:
342
vendor/laminas/laminas-eventmanager/src/EventManager.php
vendored
Normal file
342
vendor/laminas/laminas-eventmanager/src/EventManager.php
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-eventmanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-eventmanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-eventmanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\EventManager;
|
||||
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* Event manager: notification system
|
||||
*
|
||||
* Use the EventManager when you want to create a per-instance notification
|
||||
* system for your objects.
|
||||
*/
|
||||
class EventManager implements EventManagerInterface
|
||||
{
|
||||
/**
|
||||
* Subscribed events and their listeners
|
||||
*
|
||||
* STRUCTURE:
|
||||
* [
|
||||
* <string name> => [
|
||||
* <int priority> => [
|
||||
* 0 => [<callable listener>, ...]
|
||||
* ],
|
||||
* ...
|
||||
* ],
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* NOTE:
|
||||
* This structure helps us to reuse the list of listeners
|
||||
* instead of first iterating over it and generating a new one
|
||||
* -> In result it improves performance by up to 25% even if it looks a bit strange
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $events = [];
|
||||
|
||||
/**
|
||||
* @var EventInterface Prototype to use when creating an event at trigger().
|
||||
*/
|
||||
protected $eventPrototype;
|
||||
|
||||
/**
|
||||
* Identifiers, used to pull shared signals from SharedEventManagerInterface instance
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $identifiers = [];
|
||||
|
||||
/**
|
||||
* Shared event manager
|
||||
*
|
||||
* @var null|SharedEventManagerInterface
|
||||
*/
|
||||
protected $sharedManager = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Allows optionally specifying identifier(s) to use to pull signals from a
|
||||
* SharedEventManagerInterface.
|
||||
*
|
||||
* @param SharedEventManagerInterface $sharedEventManager
|
||||
* @param array $identifiers
|
||||
*/
|
||||
public function __construct(SharedEventManagerInterface $sharedEventManager = null, array $identifiers = [])
|
||||
{
|
||||
if ($sharedEventManager) {
|
||||
$this->sharedManager = $sharedEventManager;
|
||||
$this->setIdentifiers($identifiers);
|
||||
}
|
||||
|
||||
$this->eventPrototype = new Event();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setEventPrototype(EventInterface $prototype)
|
||||
{
|
||||
$this->eventPrototype = $prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the shared event manager, if composed.
|
||||
*
|
||||
* @return null|SharedEventManagerInterface $sharedEventManager
|
||||
*/
|
||||
public function getSharedManager()
|
||||
{
|
||||
return $this->sharedManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIdentifiers()
|
||||
{
|
||||
return $this->identifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setIdentifiers(array $identifiers)
|
||||
{
|
||||
$this->identifiers = array_unique($identifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function addIdentifiers(array $identifiers)
|
||||
{
|
||||
$this->identifiers = array_unique(array_merge(
|
||||
$this->identifiers,
|
||||
$identifiers
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function trigger($eventName, $target = null, $argv = [])
|
||||
{
|
||||
$event = clone $this->eventPrototype;
|
||||
$event->setName($eventName);
|
||||
|
||||
if ($target !== null) {
|
||||
$event->setTarget($target);
|
||||
}
|
||||
|
||||
if ($argv) {
|
||||
$event->setParams($argv);
|
||||
}
|
||||
|
||||
return $this->triggerListeners($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function triggerUntil(callable $callback, $eventName, $target = null, $argv = [])
|
||||
{
|
||||
$event = clone $this->eventPrototype;
|
||||
$event->setName($eventName);
|
||||
|
||||
if ($target !== null) {
|
||||
$event->setTarget($target);
|
||||
}
|
||||
|
||||
if ($argv) {
|
||||
$event->setParams($argv);
|
||||
}
|
||||
|
||||
return $this->triggerListeners($event, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function triggerEvent(EventInterface $event)
|
||||
{
|
||||
return $this->triggerListeners($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function triggerEventUntil(callable $callback, EventInterface $event)
|
||||
{
|
||||
return $this->triggerListeners($event, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function attach($eventName, callable $listener, $priority = 1)
|
||||
{
|
||||
if (! is_string($eventName)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string for the event; received %s',
|
||||
__METHOD__,
|
||||
(is_object($eventName) ? get_class($eventName) : gettype($eventName))
|
||||
));
|
||||
}
|
||||
|
||||
$this->events[$eventName][(int) $priority][0][] = $listener;
|
||||
return $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception\InvalidArgumentException for invalid event types.
|
||||
*/
|
||||
public function detach(callable $listener, $eventName = null, $force = false)
|
||||
{
|
||||
|
||||
// If event is wildcard, we need to iterate through each listeners
|
||||
if (null === $eventName || ('*' === $eventName && ! $force)) {
|
||||
foreach (array_keys($this->events) as $eventName) {
|
||||
$this->detach($listener, $eventName, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (! is_string($eventName)) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a string for the event; received %s',
|
||||
__METHOD__,
|
||||
(is_object($eventName) ? get_class($eventName) : gettype($eventName))
|
||||
));
|
||||
}
|
||||
|
||||
if (! isset($this->events[$eventName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->events[$eventName] as $priority => $listeners) {
|
||||
foreach ($listeners[0] as $index => $evaluatedListener) {
|
||||
if ($evaluatedListener !== $listener) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found the listener; remove it.
|
||||
unset($this->events[$eventName][$priority][0][$index]);
|
||||
|
||||
// If the queue for the given priority is empty, remove it.
|
||||
if (empty($this->events[$eventName][$priority][0])) {
|
||||
unset($this->events[$eventName][$priority]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the queue for the given event is empty, remove it.
|
||||
if (empty($this->events[$eventName])) {
|
||||
unset($this->events[$eventName]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function clearListeners($eventName)
|
||||
{
|
||||
if (isset($this->events[$eventName])) {
|
||||
unset($this->events[$eventName]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare arguments
|
||||
*
|
||||
* Use this method if you want to be able to modify arguments from within a
|
||||
* listener. It returns an ArrayObject of the arguments, which may then be
|
||||
* passed to trigger().
|
||||
*
|
||||
* @param array $args
|
||||
* @return ArrayObject
|
||||
*/
|
||||
public function prepareArgs(array $args)
|
||||
{
|
||||
return new ArrayObject($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger listeners
|
||||
*
|
||||
* Actual functionality for triggering listeners, to which trigger() delegate.
|
||||
*
|
||||
* @param EventInterface $event
|
||||
* @param null|callable $callback
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
protected function triggerListeners(EventInterface $event, callable $callback = null)
|
||||
{
|
||||
$name = $event->getName();
|
||||
|
||||
if (empty($name)) {
|
||||
throw new Exception\RuntimeException('Event is missing a name; cannot trigger!');
|
||||
}
|
||||
|
||||
if (isset($this->events[$name])) {
|
||||
$listOfListenersByPriority = $this->events[$name];
|
||||
|
||||
if (isset($this->events['*'])) {
|
||||
foreach ($this->events['*'] as $priority => $listOfListeners) {
|
||||
$listOfListenersByPriority[$priority][] = $listOfListeners[0];
|
||||
}
|
||||
}
|
||||
} elseif (isset($this->events['*'])) {
|
||||
$listOfListenersByPriority = $this->events['*'];
|
||||
} else {
|
||||
$listOfListenersByPriority = [];
|
||||
}
|
||||
|
||||
if ($this->sharedManager) {
|
||||
foreach ($this->sharedManager->getListeners($this->identifiers, $name) as $priority => $listeners) {
|
||||
$listOfListenersByPriority[$priority][] = $listeners;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by priority in reverse order
|
||||
krsort($listOfListenersByPriority);
|
||||
|
||||
// Initial value of stop propagation flag should be false
|
||||
$event->stopPropagation(false);
|
||||
|
||||
// Execute listeners
|
||||
$responses = new ResponseCollection();
|
||||
foreach ($listOfListenersByPriority as $listOfListeners) {
|
||||
foreach ($listOfListeners as $listeners) {
|
||||
foreach ($listeners as $listener) {
|
||||
$response = $listener($event);
|
||||
$responses->push($response);
|
||||
|
||||
// If the event was asked to stop propagating, do so
|
||||
if ($event->propagationIsStopped()) {
|
||||
$responses->setStopped(true);
|
||||
return $responses;
|
||||
}
|
||||
|
||||
// If the result causes our validation callback to return true,
|
||||
// stop propagation
|
||||
if ($callback && $callback($response)) {
|
||||
$responses->setStopped(true);
|
||||
return $responses;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $responses;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user