Skip to content

Instantly share code, notes, and snippets.

@ArrayIterator
Last active February 24, 2022 03:38
Show Gist options
  • Save ArrayIterator/81a04b9e039f61508e3ead7f05fc455d to your computer and use it in GitHub Desktop.
Save ArrayIterator/81a04b9e039f61508e3ead7f05fc455d to your computer and use it in GitHub Desktop.

Revisions

  1. ArrayIterator revised this gist Feb 24, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -161,6 +161,7 @@ public function dispatch(string $name, ...$arguments)
    $key = 0;
    if (count($arguments) === 0) {
    $value = null;
    array_push($arguments, $value);
    } else {
    $value = reset($arguments);
    $key = key($arguments);
  2. ArrayIterator revised this gist Feb 24, 2022. 1 changed file with 0 additions and 7 deletions.
    7 changes: 0 additions & 7 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -38,13 +38,6 @@ class Events implements Countable
    */
    protected $currentEvents = [];

    /**
    * @param Services $services
    */
    public function __construct()
    {
    }

    /**
    * @param callable $callable
    *
  3. ArrayIterator revised this gist Feb 24, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Events.php
    Original file line number Diff line number Diff line change
    @@ -16,7 +16,7 @@
    * $events->trigger(); // call dispatch with void result
    * $isDispatched = $events->dispatcher($name) > 0;
    */
    class Events implements Countable, ServiceInterface
    class Events implements Countable
    {
    /**
    * @var array<string, array<int, array<int, array<string, string|callable>>>>
  4. ArrayIterator revised this gist Feb 24, 2022. 1 changed file with 1 addition and 15 deletions.
    16 changes: 1 addition & 15 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -38,25 +38,11 @@ class Events implements Countable, ServiceInterface
    */
    protected $currentEvents = [];

    /**
    * @var Services
    */
    private $services;

    /**
    * @param Services $services
    */
    public function __construct(Services $services)
    {
    $this->services = $services;
    }

    /**
    * @return Services
    */
    public function getServices(): Services
    public function __construct()
    {
    return $this->services;
    }

    /**
  5. ArrayIterator revised this gist Feb 11, 2022. 1 changed file with 36 additions and 15 deletions.
    51 changes: 36 additions & 15 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -16,10 +16,10 @@
    * $events->trigger(); // call dispatch with void result
    * $isDispatched = $events->dispatcher($name) > 0;
    */
    class Events implements Countable
    class Events implements Countable, ServiceInterface
    {
    /**
    * @var array[]
    * @var array<string, array<int, array<int, array<string, string|callable>>>>
    */
    protected $events = [];

    @@ -29,7 +29,7 @@ class Events implements Countable
    protected $currentDispatches = [];

    /**
    * @var array<array<array<int>>>
    * @var array<string, array<string, array<int, int>>>
    */
    protected $dispatched = [];

    @@ -38,22 +38,43 @@ class Events implements Countable
    */
    protected $currentEvents = [];

    /**
    * @var Services
    */
    private $services;

    /**
    * @param Services $services
    */
    public function __construct(Services $services)
    {
    $this->services = $services;
    }

    /**
    * @return Services
    */
    public function getServices(): Services
    {
    return $this->services;
    }

    /**
    * @param callable $callable
    *
    * @return string|null
    */
    protected function createHash(callable $callable) : ?string
    protected function createHash(callable $callable)
    {
    if (is_string($callable)) {
    $hash = $callable;
    } elseif (is_array($callable)) {
    if (is_object(reset($callable[1]))) {
    $hash = spl_object_hash(reset($callable[1])).'::'.next($callable);
    if (is_object(reset($callable))) {
    $hash = spl_object_hash(reset($callable)).'::'.next($callable);
    } elseif (is_string(reset($callable))) {
    $hash = implode('::', $callable);
    }
    } elseif (is_object($callable)) {
    } else {
    /**
    * @var object $callable
    */
    @@ -97,7 +118,7 @@ public function add(
    * @return int
    * @noinspection PhpUnused
    */
    public function dispatched(string $name, ?callable $callable = null, ?int $priority = null) : int
    public function dispatched(string $name, callable $callable = null, int $priority = null) : int
    {
    $called = 0;
    if (!isset($this->dispatched[$name])) {
    @@ -137,7 +158,7 @@ public function dispatched(string $name, ?callable $callable = null, ?int $prior
    * @return bool
    * @noinspection PhpUnused
    */
    public function inDispatch(string $name, ?callable $callable = null, ?int $priority = null) : bool
    public function inDispatch(string $name, callable $callable = null, int $priority = null) : bool
    {
    if ($callable) {
    $hash = $this->createHash($callable);
    @@ -214,8 +235,8 @@ public function dispatch(string $name, ...$arguments)

    $this->dispatched[$name][$hash][$prior]++;
    $this->currentEvents[$prior][$hash] = true;
    $value = call_user_func($callback['function'], ...$arguments);
    $arguments[$key] = $value;
    // not using call_user_func[array] to allow call pass by reference
    $arguments[$key] = $callback['function'](...$arguments);
    unset($this->currentEvents[$prior][$hash]);
    unset($this->currentDispatches[$name][$hash][$prior]);
    if (empty($this->currentDispatches[$name][$hash])) {
    @@ -243,7 +264,7 @@ public function dispatch(string $name, ...$arguments)
    * @see Events::dispatch()
    *
    */
    public function trigger(string $name, ...$arguments) : void
    public function trigger(string $name, ...$arguments)
    {
    $this->dispatch($name, ...$arguments);
    }
    @@ -257,7 +278,7 @@ public function trigger(string $name, ...$arguments) : void
    *
    * @return int
    */
    public function countEvent(string $name, ?callable $callable = null, ?int $priority = null) : int
    public function countEvent(string $name, callable $callable = null, int $priority = null) : int
    {
    if (!isset($this->events[$name])) {
    return 0;
    @@ -298,7 +319,7 @@ public function countEvent(string $name, ?callable $callable = null, ?int $prior
    *
    * @return bool
    */
    public function exist(string $name, ?callable $callable = null, ?int $priority = null) : bool
    public function exist(string $name, callable $callable = null, int $priority = null) : bool
    {
    return $this->countEvent($name, $callable, $priority) > 0;
    }
    @@ -312,7 +333,7 @@ public function exist(string $name, ?callable $callable = null, ?int $priority =
    *
    * @return int
    */
    public function remove(string $name, ?callable $functionToRemove = null, ?int $priority = null) : int
    public function remove(string $name, callable $functionToRemove = null, int $priority = null) : int
    {
    if (!isset($this->events[$name])) {
    return 0;
  6. ArrayIterator revised this gist Feb 11, 2022. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion Events.php
    Original file line number Diff line number Diff line change
    @@ -158,11 +158,14 @@ public function inDispatch(string $name, ?callable $callable = null, ?int $prior
    */
    public function dispatch(string $name, ...$arguments)
    {
    $key = 0;
    if (count($arguments) === 0) {
    $value = null;
    } else {
    $value = reset($arguments);
    $key = key($arguments);
    }

    if (!isset($this->events[$name])) {
    return $value;
    }
    @@ -211,7 +214,8 @@ public function dispatch(string $name, ...$arguments)

    $this->dispatched[$name][$hash][$prior]++;
    $this->currentEvents[$prior][$hash] = true;
    $value = call_user_func($callback['function'], ...$arguments);
    $value = call_user_func($callback['function'], ...$arguments);
    $arguments[$key] = $value;
    unset($this->currentEvents[$prior][$hash]);
    unset($this->currentDispatches[$name][$hash][$prior]);
    if (empty($this->currentDispatches[$name][$hash])) {
  7. ArrayIterator revised this gist Jun 9, 2021. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -11,8 +11,8 @@
    * @package ArrayIterator\SimpleEvent
    *
    * $events = new Events();
    * $events->add($name, function($arg) {return $newValue;// do code}, 10);
    * $result = $events->dispatch($value); // will be return $newValue
    * $events->add($name, function($value) {return $newValue;// do code}, 10);
    * $result = $events->dispatch($name, $value); // will be return $newValue
    * $events->trigger(); // call dispatch with void result
    * $isDispatched = $events->dispatcher($name) > 0;
    */
  8. ArrayIterator revised this gist Jun 9, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Events.php
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,7 @@

    namespace ArrayIterator\SimpleEvent;

    use Countable;
    use RuntimeException;

    /**
    @@ -119,7 +120,6 @@ public function dispatched(string $name, ?callable $callable = null, ?int $prior
    return $called;
    }

    //$this->fired[$name][$hash][$prior]
    foreach ($this->dispatched[$name] as $item) {
    foreach ($item as $subItem) {
    $called+= $subItem;
  9. ArrayIterator revised this gist Jun 9, 2021. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -35,7 +35,7 @@ class Events implements Countable
    /**
    * @var array
    */
    protected $currentsEvents = [];
    protected $currentEvents = [];

    /**
    * @param callable $callable
    @@ -210,15 +210,15 @@ public function dispatch(string $name, ...$arguments)
    }

    $this->dispatched[$name][$hash][$prior]++;
    $this->currentsEvents[$prior][$hash] = true;
    $value = call_user_func($callback['function'], ...$arguments);
    unset($this->currentsEvents[$prior][$hash]);
    $this->currentEvents[$prior][$hash] = true;
    $value = call_user_func($callback['function'], ...$arguments);
    unset($this->currentEvents[$prior][$hash]);
    unset($this->currentDispatches[$name][$hash][$prior]);
    if (empty($this->currentDispatches[$name][$hash])) {
    unset($this->currentDispatches[$name][$hash]);
    }
    if (empty($this->currentsEvents[$prior])) {
    unset($this->currentsEvents[$prior]);
    if (empty($this->currentEvents[$prior])) {
    unset($this->currentEvents[$prior]);
    }
    } while (!empty($this->events[$name])
    && !empty($this->events[$name][$prior])
  10. ArrayIterator revised this gist Jun 9, 2021. 1 changed file with 85 additions and 2 deletions.
    87 changes: 85 additions & 2 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@
    * $events->trigger(); // call dispatch with void result
    * $isDispatched = $events->dispatcher($name) > 0;
    */
    class Events
    class Events implements Countable
    {
    /**
    * @var array[]
    @@ -94,6 +94,7 @@ public function add(
    * @param int|null $priority
    *
    * @return int
    * @noinspection PhpUnused
    */
    public function dispatched(string $name, ?callable $callable = null, ?int $priority = null) : int
    {
    @@ -134,6 +135,7 @@ public function dispatched(string $name, ?callable $callable = null, ?int $prior
    * @param int|null $priority
    *
    * @return bool
    * @noinspection PhpUnused
    */
    public function inDispatch(string $name, ?callable $callable = null, ?int $priority = null) : bool
    {
    @@ -243,6 +245,63 @@ public function trigger(string $name, ...$arguments) : void
    }

    /**
    * Count event by name
    *
    * @param string $name
    * @param callable|null $callable
    * @param int|null $priority
    *
    * @return int
    */
    public function countEvent(string $name, ?callable $callable = null, ?int $priority = null) : int
    {
    if (!isset($this->events[$name])) {
    return 0;
    }

    $counted = 0;
    $hash = $callable ? $this->createHash($callable) : false;
    foreach ($this->events[$name] as $prior => $item) {
    if ($hash === false) {
    $counted += count($item);
    continue;
    }
    if ($hash === null) {
    continue;
    }
    if ($priority !== null && $priority !== $prior) {
    continue;
    }
    foreach ($item as $callableArray) {
    if ($hash === $callableArray['hash']) {
    $counted++;
    }
    }
    if (empty($this->events[$name][$prior])) {
    unset($this->events[$name][$prior]);
    }
    }

    return $counted;
    }

    /**
    * Check event(s) if exists
    *
    * @param string $name
    * @param callable|null $callable
    * @param int|null $priority
    *
    * @return bool
    */
    public function exist(string $name, ?callable $callable = null, ?int $priority = null) : bool
    {
    return $this->countEvent($name, $callable, $priority) > 0;
    }

    /**
    * Remove Event(s)
    *
    * @param string $name
    * @param callable|null $functionToRemove
    * @param int|null $priority
    @@ -254,6 +313,7 @@ public function remove(string $name, ?callable $functionToRemove = null, ?int $p
    if (!isset($this->events[$name])) {
    return 0;
    }

    $removed = 0;
    $hash = $functionToRemove ? $this->createHash($functionToRemove) : false;
    foreach ($this->events[$name] as $prior => $item) {
    @@ -275,9 +335,32 @@ public function remove(string $name, ?callable $functionToRemove = null, ?int $p
    }
    }

    $this->events[$name][$prior] = array_values($item);
    if (empty($this->events[$name][$prior])) {
    unset($this->events[$name][$prior]);
    } else {
    $this->events[$name][$prior] = array_values($this->events[$name][$prior]);
    }
    }
    if (empty($this->events[$name])) {
    unset($this->events[$name]);
    }

    return $removed;
    }

    /**
    * @see Countable
    * @return int
    */
    public function count() : int
    {
    $total = 0;
    foreach ($this->events as $item) {
    foreach ($item as $subItem) {
    $total += count($subItem);
    }
    }

    return $total;
    }
    }
  11. ArrayIterator created this gist Jun 9, 2021.
    283 changes: 283 additions & 0 deletions Events.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,283 @@
    <?php
    declare(strict_types=1);

    namespace ArrayIterator\SimpleEvent;

    use RuntimeException;

    /**
    * Class Events
    * @package ArrayIterator\SimpleEvent
    *
    * $events = new Events();
    * $events->add($name, function($arg) {return $newValue;// do code}, 10);
    * $result = $events->dispatch($value); // will be return $newValue
    * $events->trigger(); // call dispatch with void result
    * $isDispatched = $events->dispatcher($name) > 0;
    */
    class Events
    {
    /**
    * @var array[]
    */
    protected $events = [];

    /**
    * @var array<array<string>>
    */
    protected $currentDispatches = [];

    /**
    * @var array<array<array<int>>>
    */
    protected $dispatched = [];

    /**
    * @var array
    */
    protected $currentsEvents = [];

    /**
    * @param callable $callable
    *
    * @return string|null
    */
    protected function createHash(callable $callable) : ?string
    {
    if (is_string($callable)) {
    $hash = $callable;
    } elseif (is_array($callable)) {
    if (is_object(reset($callable[1]))) {
    $hash = spl_object_hash(reset($callable[1])).'::'.next($callable);
    } elseif (is_string(reset($callable))) {
    $hash = implode('::', $callable);
    }
    } elseif (is_object($callable)) {
    /**
    * @var object $callable
    */
    $hash = spl_object_hash($callable);
    }
    return $hash??null;
    }

    /**
    * @param string $name
    * @param callable $callable
    * @param int $priority
    *
    * @return string
    */
    public function add(
    string $name,
    callable $callable,
    int $priority = 10
    ) : string {
    if (!isset($this->events[$name])) {
    $this->events[$name] = [];
    }

    $hash = $this->createHash($callable);
    $this->events[$name][$priority][] = [
    'hash' => $hash,
    'function' => $callable,
    ];
    ksort($this->events[$name]);
    return $hash;
    }

    /**
    * Get count callable called
    *
    * @param string $name
    * @param callable|null $callable
    * @param int|null $priority
    *
    * @return int
    */
    public function dispatched(string $name, ?callable $callable = null, ?int $priority = null) : int
    {
    $called = 0;
    if (!isset($this->dispatched[$name])) {
    return $called;
    }
    if ($callable) {
    $hash = $this->createHash($callable);
    if (!isset($this->dispatched[$name][$hash])) {
    return $called;
    }
    if ($priority !== null) {
    if (!isset($this->dispatched[$name][$hash][$priority])) {
    return $called;
    }
    return $this->dispatched[$name][$hash][$priority];
    }
    foreach ($this->dispatched[$name][$hash] as $item) {
    $called += $item;
    }
    return $called;
    }

    //$this->fired[$name][$hash][$prior]
    foreach ($this->dispatched[$name] as $item) {
    foreach ($item as $subItem) {
    $called+= $subItem;
    }
    }

    return $called;
    }

    /**
    * @param string $name
    * @param callable|null $callable
    * @param int|null $priority
    *
    * @return bool
    */
    public function inDispatch(string $name, ?callable $callable = null, ?int $priority = null) : bool
    {
    if ($callable) {
    $hash = $this->createHash($callable);
    if ($priority !== null) {
    return isset($this->currentDispatches[$name][$hash][$priority]);
    }
    return isset($this->currentDispatches[$name][$hash]);
    }

    return isset($this->currentDispatches[$name]);
    }

    /**
    * @param string $name
    * @param ...$arguments
    *
    * @return mixed
    */
    public function dispatch(string $name, ...$arguments)
    {
    if (count($arguments) === 0) {
    $value = null;
    } else {
    $value = reset($arguments);
    }
    if (!isset($this->events[$name])) {
    return $value;
    }

    reset($this->events[$name]);
    do {
    $current = current($this->events[$name]);
    $prior = key($this->events[$name]);
    reset($this->events[$name][$prior]);
    if (!$current) {
    break;
    }
    do {
    $callback = current($this->events[$name][$prior]);
    if (!$callback) {
    break;
    }
    $hash = $callback['hash'];
    if (!isset($this->currentDispatches[$name])) {
    $this->currentDispatches[$name] = [];
    }
    if (!isset($this->currentDispatches[$name][$hash])) {
    $this->currentDispatches[$name][$hash] = [];
    }
    if (!empty($this->currentDispatches[$name][$hash][$prior])) {
    throw new RuntimeException(
    sprintf(
    'Event %s(%s)(%d) still in progress',
    $name,
    $hash,
    $prior
    )
    );
    }

    $this->currentDispatches[$name][$hash][$prior] = true;
    if (!isset($this->dispatched[$name])) {
    $this->dispatched[$name] = [];
    }
    if (!isset($this->dispatched[$name][$hash])) {
    $this->dispatched[$name][$hash] = [];
    }
    if (!isset($this->dispatched[$name][$hash][$prior])) {
    $this->dispatched[$name][$hash][$prior] = 0;
    }

    $this->dispatched[$name][$hash][$prior]++;
    $this->currentsEvents[$prior][$hash] = true;
    $value = call_user_func($callback['function'], ...$arguments);
    unset($this->currentsEvents[$prior][$hash]);
    unset($this->currentDispatches[$name][$hash][$prior]);
    if (empty($this->currentDispatches[$name][$hash])) {
    unset($this->currentDispatches[$name][$hash]);
    }
    if (empty($this->currentsEvents[$prior])) {
    unset($this->currentsEvents[$prior]);
    }
    } while (!empty($this->events[$name])
    && !empty($this->events[$name][$prior])
    && next($this->events[$name][$prior]) !== false
    );
    } while (!empty($this->events[$name]) && next($this->events[$name]) !== false);
    if (empty($this->currentDispatches[$name])) {
    unset($this->currentDispatches[$name]);
    }

    return $value;
    }

    /**
    * @param string $name
    * @param ...$arguments
    *
    * @see Events::dispatch()
    *
    */
    public function trigger(string $name, ...$arguments) : void
    {
    $this->dispatch($name, ...$arguments);
    }

    /**
    * @param string $name
    * @param callable|null $functionToRemove
    * @param int|null $priority
    *
    * @return int
    */
    public function remove(string $name, ?callable $functionToRemove = null, ?int $priority = null) : int
    {
    if (!isset($this->events[$name])) {
    return 0;
    }
    $removed = 0;
    $hash = $functionToRemove ? $this->createHash($functionToRemove) : false;
    foreach ($this->events[$name] as $prior => $item) {
    if ($hash === false) {
    $removed += count($item);
    unset($this->events[$name][$prior]);
    continue;
    }
    if ($hash === null) {
    continue;
    }
    if ($priority !== null && $priority !== $prior) {
    continue;
    }
    foreach ($item as $key => $callableArray) {
    if ($hash === $callableArray['hash']) {
    $removed++;
    unset($this->events[$name][$prior][$key]);
    }
    }

    $this->events[$name][$prior] = array_values($item);
    }

    return $removed;
    }
    }