Completed
Push — 1.4 ( eba84d...d3bf7f )
by Rafał
08:33
created

WebhookEventsSubscriber::getWebhooks()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.9297
c 0
b 0
f 0
cc 6
nc 4
nop 3

1 Method

Rating   Name   Duplication   Size   Complexity  
A WebhookEventsSubscriber::getSubject() 0 13 4
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Web Publisher Core Bundle.
7
 *
8
 * Copyright 2016 Sourcefabric z.ú. and contributors.
9
 *
10
 * For the full copyright and license information, please see the
11
 * AUTHORS and LICENSE files distributed with this source code.
12
 *
13
 * @copyright 2016 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\CoreBundle\EventSubscriber;
18
19
use JMS\Serializer\SerializerInterface;
20
use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface;
21
use SWP\Bundle\ContentBundle\Event\ArticleEvent;
22
use SWP\Bundle\ContentBundle\Event\RouteEvent;
23
use SWP\Bundle\CoreBundle\Model\WebhookInterface;
24
use SWP\Bundle\CoreBundle\Repository\WebhookRepositoryInterface;
25
use SWP\Bundle\CoreBundle\Webhook\WebhookEvents;
26
use SWP\Bundle\MultiTenancyBundle\Context\TenantContext;
27
use SWP\Component\MultiTenancy\Repository\TenantRepositoryInterface;
28
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
29
use Symfony\Component\EventDispatcher\Event;
30
use Symfony\Component\EventDispatcher\GenericEvent;
31
32
final class WebhookEventsSubscriber extends AbstractWebhookEventSubscriber
33
{
34
    private $producer;
35
36
    private $serializer;
37
38
    public function __construct(
39
        ProducerInterface $producer,
40
        SerializerInterface $serializer,
41
        WebhookRepositoryInterface $webhooksRepository,
42
        TenantContext $tenantContext,
43
        TenantRepositoryInterface $tenantRepository
44
    ) {
45
        $this->producer = $producer;
46
        $this->serializer = $serializer;
47
48
        parent::__construct($webhooksRepository, $tenantContext, $tenantRepository);
49
    }
50
51
    public static function getSubscribedEvents(): array
52
    {
53
        $subscribedEvents = [];
54
        foreach (WebhookEvents::EVENTS as $webhookEvent) {
55
            $subscribedEvents[$webhookEvent] = 'handleEvent';
56
        }
57
58
        return $subscribedEvents;
59
    }
60
61
    public function handleEvent(Event $event, string $dispatcherEventName, EventDispatcherInterface $dispatcher): void
0 ignored issues
show
Unused Code introduced by
The parameter $dispatcherEventName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
62
    {
63
        $webhookEventName = $this->getEventName($event);
64
        if (!is_string($webhookEventName)) {
65
            return;
66
        }
67
68
        $subject = $this->getSubject($event);
69
        $webhooks = $this->getWebhooks($subject, $webhookEventName, $dispatcher);
70
71
        /** @var WebhookInterface $webhook */
72
        foreach ($webhooks as $webhook) {
73
            $this->producer->publish($this->serializer->serialize([
74
                'url' => $webhook->getUrl(),
75
                'metadata' => [
76
                    'event' => $webhookEventName,
77
                    'tenant' => $webhook->getTenantCode(),
78
                ],
79
                'subject' => $subject,
80
            ], 'json'));
81
        }
82
    }
83
84
    private function getEventName(Event $event): ?string
85
    {
86
        if ($event instanceof GenericEvent) {
87
            $arguments = $event->getArguments();
88
            if (array_key_exists('eventName', $arguments)) {
89
                return array_search($arguments['eventName'], WebhookEvents::EVENTS);
90
            }
91
        } elseif (method_exists($event, 'getEventName')) {
92
            return array_search($event->getEventName(), WebhookEvents::EVENTS);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\EventDispatcher\Event as the method getEventName() does only exist in the following sub-classes of Symfony\Component\EventDispatcher\Event: SWP\Bundle\ContentBundle\Event\ArticleEvent, SWP\Bundle\ContentBundle\Event\RouteEvent. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
93
        }
94
95
        return null;
96
    }
97
98
    private function getSubject(Event $event)
99
    {
100
        switch ($event) {
101
            case $event instanceof GenericEvent:
102
                return $event->getSubject();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\EventDispatcher\Event as the method getSubject() does only exist in the following sub-classes of Symfony\Component\EventDispatcher\Event: SWP\Component\Common\Event\HttpCacheEvent, Symfony\Component\EventDispatcher\GenericEvent, Symfony\Component\Workflow\Event\Event, Symfony\Component\Workflow\Event\GuardEvent. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
103
            case $event instanceof ArticleEvent:
104
                return $event->getArticle();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\EventDispatcher\Event as the method getArticle() does only exist in the following sub-classes of Symfony\Component\EventDispatcher\Event: SWP\Bundle\ContentBundle\Event\ArticleEvent. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
105
            case $event instanceof RouteEvent:
106
                return $event->getRoute();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\EventDispatcher\Event as the method getRoute() does only exist in the following sub-classes of Symfony\Component\EventDispatcher\Event: SWP\Bundle\ContentBundle\Event\RouteEvent. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
107
            default:
108
                return null;
109
        }
110
    }
111
}
112