110 lines
2.9 KiB
PHP
110 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Blax\ReactPhpKernel\Support;
|
|
|
|
/**
|
|
* A generic, in-memory registry of active connections/peers keyed by string id.
|
|
*
|
|
* Shared plumbing for presence + broadcast in protocol servers — WS channel
|
|
* members, WebRTC peers in a room, etc. It is transport-agnostic: values are
|
|
* arbitrary objects (a socket connection, a peer wrapper, ...), so the same
|
|
* registry serves every protocol on the kernel.
|
|
*/
|
|
final class ConnectionRegistry implements \Countable
|
|
{
|
|
/** @var array<string,object> */
|
|
private array $items = [];
|
|
|
|
/** @var array<callable> */
|
|
private array $onAdd = [];
|
|
|
|
/** @var array<callable> */
|
|
private array $onRemove = [];
|
|
|
|
/** Register (or replace) a connection under $id. Fires onAdd listeners. */
|
|
public function add(string $id, object $connection): void
|
|
{
|
|
$this->items[$id] = $connection;
|
|
|
|
foreach ($this->onAdd as $listener) {
|
|
$listener($id, $connection);
|
|
}
|
|
}
|
|
|
|
/** Remove a connection by id (no-op if absent). Fires onRemove listeners. */
|
|
public function remove(string $id): void
|
|
{
|
|
if (! isset($this->items[$id])) {
|
|
return;
|
|
}
|
|
|
|
$connection = $this->items[$id];
|
|
unset($this->items[$id]);
|
|
|
|
foreach ($this->onRemove as $listener) {
|
|
$listener($id, $connection);
|
|
}
|
|
}
|
|
|
|
public function has(string $id): bool
|
|
{
|
|
return isset($this->items[$id]);
|
|
}
|
|
|
|
public function get(string $id): ?object
|
|
{
|
|
return $this->items[$id] ?? null;
|
|
}
|
|
|
|
/** @return array<string,object> */
|
|
public function all(): array
|
|
{
|
|
return $this->items;
|
|
}
|
|
|
|
/** @return array<int,string> */
|
|
public function ids(): array
|
|
{
|
|
// Cast: PHP coerces numeric-string keys (e.g. "1") to int keys internally.
|
|
return array_map(strval(...), array_keys($this->items));
|
|
}
|
|
|
|
public function count(): int
|
|
{
|
|
return count($this->items);
|
|
}
|
|
|
|
/**
|
|
* Apply a callback to every connection — the broadcast primitive.
|
|
* The callback receives (object $connection, string $id).
|
|
*/
|
|
public function each(callable $callback): void
|
|
{
|
|
foreach ($this->items as $id => $connection) {
|
|
$callback($connection, (string) $id);
|
|
}
|
|
}
|
|
|
|
/** Listen for additions: function(string $id, object $connection): void. */
|
|
public function onAdd(callable $listener): void
|
|
{
|
|
$this->onAdd[] = $listener;
|
|
}
|
|
|
|
/** Listen for removals: function(string $id, object $connection): void. */
|
|
public function onRemove(callable $listener): void
|
|
{
|
|
$this->onRemove[] = $listener;
|
|
}
|
|
|
|
/** Remove every connection (firing onRemove for each). */
|
|
public function clear(): void
|
|
{
|
|
foreach (array_keys($this->items) as $id) {
|
|
$this->remove((string) $id); // keys may be int (PHP numeric-string coercion)
|
|
}
|
|
}
|
|
}
|