Skip to content

Commit

Permalink
feat: subscription events (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpolaszek committed May 3, 2022
1 parent f81eb50 commit adc40a6
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/Hub/Controller/SubscribeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ public function __invoke(
): ResponseInterface {
$subscribedTopics = $this->extractSubscribedTopics($request);
$allowedTopics = $this->extractAllowedTopics($request);
$payload = $this->extractPayload($request);
$lastEventId = extract_last_event_id($request);

$subscriber = new Subscriber($subscribedTopics);
$subscriber = new Subscriber($subscribedTopics, $payload);

if (null !== $lastEventId) {
async(
Expand Down Expand Up @@ -138,4 +139,15 @@ private function extractAllowedTopics(ServerRequestInterface $request): ?array

return $jwt->claims()->get('mercure')['subscribe'] ?? null;
}

private function extractPayload(ServerRequestInterface $request): mixed
{
/** @var UnencryptedToken|null $jwt */
$jwt = $request->getAttribute('token');
if (null === $jwt) {
return null;
}

return $jwt->claims()->get('mercure')['payload'] ?? null;
}
}
23 changes: 23 additions & 0 deletions src/Hub/Hub.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Freddie\Hub\Middleware\HttpExceptionConverterMiddleware;
use Freddie\Hub\Transport\PHP\PHPTransport;
use Freddie\Hub\Transport\TransportInterface;
use Freddie\Message\Message;
use Freddie\Message\Update;
use Freddie\Subscription\Subscriber;
use Generator;
Expand All @@ -17,12 +18,14 @@
use Symfony\Component\OptionsResolver\OptionsResolver;

use function array_key_exists;
use function json_encode;
use function sprintf;

final class Hub implements HubInterface
{
public const DEFAULT_OPTIONS = [
'allow_anonymous' => true,
'enable_subscription_events' => true,
];

/**
Expand All @@ -46,6 +49,7 @@ public function __construct(
$resolver = new OptionsResolver();
$resolver->setDefaults(self::DEFAULT_OPTIONS);
$resolver->setAllowedTypes('allow_anonymous', 'bool');
$resolver->setAllowedTypes('enable_subscription_events', 'bool');
$this->options = $resolver->resolve($options);
foreach ($controllers as $controller) {
$controller->setHub($this);
Expand Down Expand Up @@ -79,11 +83,30 @@ public function publish(Update $update): PromiseInterface
public function subscribe(Subscriber $subscriber): void
{
$this->transport->subscribe($subscriber);
if (true === $this->getOption('enable_subscription_events')) {
foreach ($subscriber->subscriptions as $subscription) {
$update = new Update(
$subscription->id,
new Message(data: (string) json_encode($subscription), private: true)
);
Loop::futureTick(fn () => $this->publish($update));
}
}
}

public function unsubscribe(Subscriber $subscriber): void
{
$this->transport->unsubscribe($subscriber);
if (true === $this->getOption('enable_subscription_events')) {
$subscriber->active = false;
foreach ($subscriber->subscriptions as $subscription) {
$update = new Update(
$subscription->id,
new Message(data: (string) json_encode($subscription), private: true)
);
Loop::futureTick(fn () => $this->publish($update));
}
}
}

public function reconciliate(string $lastEventID): Generator
Expand Down
34 changes: 33 additions & 1 deletion src/Subscription/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,43 @@

namespace Freddie\Subscription;

final class Subscription
use JsonSerializable;

use function sprintf;
use function urlencode;

final class Subscription implements JsonSerializable
{
public readonly string $id;

public function __construct(
public Subscriber $subscriber,
public string $topic,
) {
$this->id = sprintf(
'/.well-known/mercure/subscriptions/%s/%s',
urlencode($this->topic),
urlencode((string) $subscriber->id)
);
}

/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$output = [
'id' => $this->id,
'type' => 'Subscription',
'subscriber' => (string) $this->subscriber->id,
'topic' => $this->topic,
'active' => $this->subscriber->active,
];

if (null !== $this->subscriber->payload) {
$output['payload'] = $this->subscriber->payload;
}

return $output;
}
}

0 comments on commit adc40a6

Please sign in to comment.