<?php
/**
* Part of the Joomla Framework Event Package
*
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\Event;
/**
* A class containing an inner listeners priority queue that can be iterated multiple times.
*
* @since 1.0
* @internal
*/
final class ListenersPriorityQueue implements \IteratorAggregate, \Countable
{
/**
* The listeners for an event.
*
* @var array
* @since 2.0.0
*/
private $listeners = [];
/**
* Add a listener with the given priority only if not already present.
*
* @param callable $callback A callable function acting as an event listener.
* @param integer $priority The listener priority.
*
* @return $this
*
* @since 1.0
*/
public function add(callable $callback, int $priority): self
{
$this->listeners[$priority][] = $callback;
return $this;
}
/**
* Remove a listener from the queue.
*
* @param callable $callback A callable function acting as an event listener.
*
* @return $this
*
* @since 1.0
*/
public function remove(callable $callback): self
{
foreach ($this->listeners as $priority => $listeners)
{
if (($key = array_search($callback, $listeners, true)) !== false)
{
unset($this->listeners[$priority][$key]);
}
}
return $this;
}
/**
* Tell if the listener exists in the queue.
*
* @param callable $callback A callable function acting as an event listener.
*
* @return boolean True if it exists, false otherwise.
*
* @since 1.0
*/
public function has(callable $callback): bool
{
foreach ($this->listeners as $priority => $listeners)
{
if (($key = array_search($callback, $listeners, true)) !== false)
{
return true;
}
}
return false;
}
/**
* Get the priority of the given listener.
*
* @param callable $callback A callable function acting as an event listener.
* @param mixed $default The default value to return if the listener doesn't exist.
*
* @return mixed The listener priority if it exists or the specified default value
*
* @since 1.0
*/
public function getPriority(callable $callback, $default = null)
{
foreach ($this->listeners as $priority => $listeners)
{
if (($key = array_search($callback, $listeners, true)) !== false)
{
return $priority;
}
}
return $default;
}
/**
* Get all listeners contained in this queue, sorted according to their priority.
*
* @return callable[] An array of listeners.
*
* @since 1.0
*/
public function getAll(): array
{
if (empty($this->listeners))
{
return [];
}
krsort($this->listeners);
return \call_user_func_array('array_merge', $this->listeners);
}
/**
* Get the priority queue.
*
* @return \ArrayIterator
*
* @since 1.0
*/
public function getIterator()
{
return new \ArrayIterator($this->getAll());
}
/**
* Count the number of listeners in the queue.
*
* @return integer The number of listeners in the queue.
*
* @since 1.0
*/
public function count()
{
$count = 0;
foreach ($this->listeners as $priority)
{
$count += \count($priority);
}
return $count;
}
}