mercureact/src/Broker/Topic.php

103 lines
2.2 KiB
PHP

<?php
namespace NoccyLabs\Mercureact\Broker;
use NoccyLabs\Mercureact\Broker\Subscriber\SubscriberInterface;
use SplObjectStorage;
class Topic
{
const MAX_HISTORY_AGE = 180;
/** @var string Topic name */
private string $topic;
/** @var array<string,Message> */
private array $messages = [];
private ?string $lastEventId = null;
/** @var int Creation unixtime */
private int $created;
private SplObjectStorage $subscribers;
public function __construct(string $topic)
{
$this->topic = $topic;
$this->subscribers = new SplObjectStorage();
$this->created = time();
}
public function publish(Message $message)
{
// check if message id has already been published
if (isset($this->messages[$message->id])) return;
$this->messages[$message->id] = $message;
foreach ($this->subscribers as $subscriber) {
// Skip sending private messages to unauthorized subscribers
if ($message->private && !$subscriber->isAuthorized()) {
continue;
}
// Deliver to the subscriber
$subscriber->deliver($message);
}
}
public function getAge(): int
{
return time() - $this->created;
}
public function getHistorySize(): int
{
return count($this->messages);
}
public function getSubscriberCount(): int
{
return count($this->subscribers);
}
public function addSubscriber(SubscriberInterface $subscriber)
{
$this->subscribers->attach($subscriber);
}
public function removeSubscriber(SubscriberInterface $subscriber)
{
$this->subscribers->detach($subscriber);
}
public function getSubscribers(): array
{
return iterator_to_array($this->subscribers);
}
public function getTopic(): string
{
return $this->topic;
}
public function getLastEventId(): ?string
{
return $this->lastEventId;
}
/**
* Garbage collect histry
*
*/
public function garbageCollect(): void
{
$this->messages = array_filter(
$this->messages,
fn($message) => $message->getAge() < self::MAX_HISTORY_AGE
);
}
}