MessageManagerBackendDispatcher   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 2
dl 0
loc 112
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 18 5
A getBackend() 0 16 4
A getIterator() 0 4 1
A handle() 0 4 1
A getStatus() 0 4 1
A cleanup() 0 4 1
A initialize() 0 3 1
A getDefaultBackend() 0 14 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\NotificationBundle\Backend;
15
16
use Laminas\Diagnostics\Result\Success;
17
use Sonata\NotificationBundle\Model\MessageInterface;
18
use Sonata\NotificationBundle\Model\MessageManagerInterface;
19
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
20
21
/**
22
 * Producer side of the doctrine backend.
23
 */
24
class MessageManagerBackendDispatcher extends QueueBackendDispatcher
25
{
26
    /**
27
     * @var array
28
     */
29
    protected $dedicatedTypes = [];
30
31
    /**
32
     * @var BackendInterface
33
     */
34
    protected $default;
35
36
    /**
37
     * @param MessageManagerInterface $messageManager Only used in compiler pass
38
     * @param string                  $defaultQueue
39
     */
40
    public function __construct(MessageManagerInterface $messageManager, array $queues, $defaultQueue, array $backends)
41
    {
42
        parent::__construct($queues, $defaultQueue, $backends);
43
44
        foreach ($this->queues as $queue) {
45
            if (true === $queue['default']) {
46
                continue;
47
            }
48
49
            $this->dedicatedTypes = array_merge($this->dedicatedTypes, $queue['types']);
50
        }
51
52
        foreach ($this->backends as $backend) {
53
            if (empty($backend['types'])) {
54
                $this->default = $backend['backend'];
55
            }
56
        }
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    public function getBackend($type)
63
    {
64
        $default = null;
0 ignored issues
show
Unused Code introduced by
$default is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
65
66
        if (!$type) {
67
            return $this->getDefaultBackend();
68
        }
69
70
        foreach ($this->backends as $backend) {
71
            if (\in_array($type, $backend['types'], true)) {
72
                return $backend['backend'];
73
            }
74
        }
75
76
        return $this->getDefaultBackend();
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function getIterator(): void
83
    {
84
        throw new \RuntimeException('You need to use a specific doctrine backend supporting the selected queue to run a consumer.');
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function handle(MessageInterface $message, EventDispatcherInterface $dispatcher): void
91
    {
92
        throw new \RuntimeException('You need to use a specific doctrine backend supporting the selected queue to run a consumer.');
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function getStatus()
99
    {
100
        return new Success('Channel is running (Database) and consumers for all queues available.');
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function cleanup(): void
107
    {
108
        throw new \RuntimeException('You need to use a specific doctrine backend supporting the selected queue to run a consumer.');
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function initialize(): void
115
    {
116
    }
117
118
    /**
119
     * @return BackendInterface
120
     */
121
    protected function getDefaultBackend()
122
    {
123
        $types = [];
124
125
        if (!empty($this->dedicatedTypes)) {
126
            $types = [
127
                'exclude' => $this->dedicatedTypes,
128
            ];
129
        }
130
131
        $this->default->setTypes($types);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sonata\NotificationBundle\Backend\BackendInterface as the method setTypes() does only exist in the following implementations of said interface: Sonata\NotificationBundl...d\MessageManagerBackend.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
132
133
        return $this->default;
134
    }
135
}
136