Passed
Pull Request — master (#17)
by BENOIT
02:04
created

SubscriptionsController::__invoke()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 23
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 36
rs 9.552
1
<?php
2
3
namespace BenTools\MercurePHP\Controller;
4
5
use BenTools\MercurePHP\Hub\Hub;
6
use BenTools\MercurePHP\Security\Authenticator;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use React\Http\Message\Response;
11
use React\Stream\ThroughStream;
12
13
use function BenTools\MercurePHP\nullify;
14
15
final class SubscriptionsController extends AbstractController
16
{
17
    private const PATH = '/.well-known/mercure/subscriptions';
18
    private Hub $hub;
19
    private Authenticator $authenticator;
20
21
    public function __construct(Hub $hub, Authenticator $authenticator)
22
    {
23
        $this->hub = $hub;
24
        $this->authenticator = $authenticator;
25
    }
26
27
    public function __invoke(ServerRequestInterface $request): ResponseInterface
28
    {
29
        if (!\in_array($request->getMethod(), ['GET', 'HEAD', 'OPTIONS'])) {
30
            return new Response(405);
31
        }
32
33
        $path = $request->getUri()->getPath();
34
        $filters = \explode('/', \trim(\strtr($path, [self::PATH => '']), '/'), 2);
35
        $subscriber = nullify($filters[0]);
36
        $topic = nullify($filters[1] ?? null);
37
38
        $stream = new ThroughStream();
39
        $this->hub->hook(
40
            function () use ($stream, $path, $subscriber, $topic) {
41
                $this->hub->getActiveSubscriptions($subscriber, $topic)
42
                    ->then(
43
                        function (iterable $subscriptions) use ($stream, $path) {
44
                            $result = [
45
                                '@context' => 'https://mercure.rocks/',
46
                                'id' => $path,
47
                                'type' => 'Subscriptions',
48
                                'subscriptions' => \iterable_to_array($subscriptions),
49
                            ];
50
                            $stream->write(\json_encode($result, \JSON_THROW_ON_ERROR));
51
                            $stream->end();
52
                            $stream->close();
53
                        }
54
                    );
55
            }
56
        );
57
58
        $headers = [
59
            'Content-Type' => 'application/ld+json',
60
        ];
61
62
        return new Response(200, $headers, $stream);
63
    }
64
65
    public function matchRequest(RequestInterface $request): bool
66
    {
67
        return 0 === \strpos($request->getUri()->getPath(), self::PATH);
68
    }
69
}
70