Passed
Push — master ( c66900...e3cbf5 )
by Rafael
06:44
created

Subscriber   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 8
eloc 28
c 1
b 0
f 0
dl 0
loc 112
ccs 0
cts 45
cp 0
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A onSymfonyAuthSuccess() 0 3 1
A setMercureHubUrl() 0 3 1
A getSubscribedEvents() 0 5 1
A __construct() 0 4 1
A __invoke() 0 29 3
A operationStart() 0 3 1
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Subscription;
12
13
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
14
use Symfony\Component\HttpFoundation\RequestStack;
15
use Symfony\Component\HttpFoundation\Session\Session;
16
use Symfony\Component\Security\Core\AuthenticationEvents;
17
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
18
use Ynlo\GraphQLBundle\Definition\Registry\Endpoint;
19
use Ynlo\GraphQLBundle\Events\GraphQLEvents;
20
use Ynlo\GraphQLBundle\Events\GraphQLOperationEvent;
21
use Ynlo\GraphQLBundle\Resolver\ResolverContext;
22
use Ynlo\GraphQLBundle\Util\Uuid;
23
24
/**
25
 * The subscriber is a resolver that resolve subscriptions and return a subscription link
26
 * act as a middleware before the real subscription resolver is executed
27
 */
28
class Subscriber implements EventSubscriberInterface
29
{
30
    /**
31
     * @var string
32
     */
33
    protected $mercureHubUrl;
34
35
    /**
36
     * @var SubscriptionManager
37
     */
38
    protected $subscriptionManager;
39
40
    /**
41
     * @var RequestStack
42
     */
43
    protected $requestStack;
44
45
    /**
46
     * @var string
47
     */
48
    protected $username;
49
50
    /**
51
     * @var Endpoint
52
     */
53
    protected $endpoint;
54
55
    /**
56
     * Subscriber constructor.
57
     *
58
     * @param RequestStack        $requestStack
59
     * @param SubscriptionManager $subscriptionManager
60
     */
61
    public function __construct(RequestStack $requestStack, ?SubscriptionManager $subscriptionManager = null)
62
    {
63
        $this->requestStack = $requestStack;
64
        $this->subscriptionManager = $subscriptionManager;
65
    }
66
67
    /**
68
     * @param array  $mercureHubsUrls
69
     * @param string $hub
70
     */
71
    public function setMercureHubUrl(array $mercureHubsUrls, $hub)
72
    {
73
        $this->mercureHubUrl = $mercureHubsUrls[$hub];
74
    }
75
76
    /**
77
     * @inheritDoc
78
     */
79
    public static function getSubscribedEvents(): array
80
    {
81
        return [
82
            GraphQLEvents::OPERATION_START => 'operationStart',
83
            AuthenticationEvents::AUTHENTICATION_SUCCESS => 'onSymfonyAuthSuccess',
84
        ];
85
    }
86
87
    /**
88
     * @param AuthenticationEvent $event
89
     */
90
    public function onSymfonyAuthSuccess(AuthenticationEvent $event): void
91
    {
92
        $this->username = $event->getAuthenticationToken()->getUsername();
93
    }
94
95
    /**
96
     * @param GraphQLOperationEvent $event
97
     */
98
    public function operationStart(GraphQLOperationEvent $event): void
99
    {
100
        $this->endpoint = $event->getEndpoint();
101
    }
102
103
    /**
104
     * @param ResolverContext $context
105
     * @param array           $args
106
     *
107
     * @return SubscriptionLink
108
     *
109
     * @throws \Exception
110
     */
111
    public function __invoke(ResolverContext $context, $args = [])
112
    {
113
        $request = $this->requestStack->getCurrentRequest();
114
        if (!$request) {
115
            throw new \RuntimeException('Missing required request');
116
        }
117
118
        if ($request->getSession()) {
119
            //clear session
120
            $request->setSession(new Session());
121
        }
122
123
        // subscriptions are created with a very lowest expiration date
124
        // if the client does not connect to given subscription in x seconds the subscription is automatically deleted
125
        $expireAt = new \DateTime('+10seconds');
126
127
        $id = Uuid::createFromData(
128
            [
129
                $this->username,
130
                $this->endpoint,
131
                $request->getUri(),
132
                $request->getContent(),
133
            ]
134
        );
135
136
        $subscriptionName = $this->endpoint->getSubscriptionNameForResolver($context->getDefinition()->getResolver());
137
        $this->subscriptionManager->subscribe($id, $subscriptionName, $args, $request, $expireAt);
138
139
        return new SubscriptionLink(sprintf('%s?topic=%s', $this->mercureHubUrl, $id));
140
    }
141
}
142