ManagerRegistry   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 246
Duplicated Lines 17.07 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 0
Metric Value
wmc 34
lcom 2
cbo 3
dl 42
loc 246
rs 9.2
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getDefaultConnectionName() 0 6 1
A getConnection() 14 14 3
A getConnections() 0 14 3
A getConnectionNames() 0 10 2
A loadConnections() 0 7 2
A getDefaultManagerName() 0 6 1
A getManager() 14 14 3
A getManagers() 0 14 3
A getManagerNames() 0 10 2
A resetManager() 14 14 3
A loadManagers() 0 7 2
A getAliasNamespace() 0 10 3
A getRepository() 0 4 1
A getManagerForClass() 0 13 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Saxulum\DoctrineMongodbOdmManagerRegistry\Doctrine;
4
5
use Doctrine\Common\Persistence\ManagerRegistry as ManagerRegistryInterface;
6
use Doctrine\Common\Persistence\ObjectManager;
7
use Doctrine\Common\Persistence\ObjectRepository;
8
use Doctrine\MongoDB\Connection;
9
use Doctrine\ODM\MongoDB\MongoDBException;
10
use Pimple\Container;
11
12
class ManagerRegistry implements ManagerRegistryInterface
13
{
14
    /**
15
     * @var Container
16
     */
17
    protected $container;
18
19
    /**
20
     * @var Connection[]
21
     */
22
    protected $connections;
23
24
    /**
25
     * @var string
26
     */
27
    protected $defaultConnectionName;
28
29
    /**
30
     * @var ObjectManager[]
31
     */
32
    protected $managers;
33
34
    /**
35
     * @var string
36
     */
37
    protected $defaultManagerName;
38
39
    /**
40
     * @var string
41
     */
42
    protected $proxyInterfaceName;
43
44
    /**
45
     * @param Container $container
46
     * @param string  $proxyInterfaceName
47
     */
48
    public function __construct(Container $container, $proxyInterfaceName = 'Doctrine\ODM\MongoDB\Proxy\Proxy')
49
    {
50
        $this->container = $container;
51
        $this->proxyInterfaceName = $proxyInterfaceName;
52
    }
53
54
    /**
55
     * @return string
56
     */
57
    public function getDefaultConnectionName()
58
    {
59
        $this->loadConnections();
60
61
        return $this->defaultConnectionName;
62
    }
63
64
    /**
65
     * @param  string|null               $name
66
     * @return Connection
67
     * @throws \InvalidArgumentException
68
     */
69 View Code Duplication
    public function getConnection($name = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
    {
71
        $this->loadConnections();
72
73
        if ($name === null) {
74
            $name = $this->getDefaultConnectionName();
75
        }
76
77
        if (!isset($this->connections[$name])) {
78
            throw new \InvalidArgumentException(sprintf('Doctrine Connection named "%s" does not exist.', $name));
79
        }
80
81
        return $this->connections[$name];
82
    }
83
84
    /**
85
     * @return array
86
     */
87
    public function getConnections()
88
    {
89
        $this->loadConnections();
90
91
        if ($this->connections instanceof Container) {
92
            $connections = array();
93
            foreach ($this->getConnectionNames() as $name) {
94
                $connections[$name] = $this->connections[$name];
95
            }
96
            $this->connections = $connections;
97
        }
98
99
        return $this->connections;
100
    }
101
102
    /**
103
     * @return array
104
     */
105
    public function getConnectionNames()
106
    {
107
        $this->loadConnections();
108
109
        if ($this->connections instanceof Container) {
110
            return $this->connections->keys();
111
        } else {
112
            return array_keys($this->connections);
113
        }
114
    }
115
116
    protected function loadConnections()
117
    {
118
        if (is_null($this->connections)) {
119
            $this->connections = $this->container['mongodbs'];
120
            $this->defaultConnectionName = $this->container['mongodbs.default'];
121
        }
122
    }
123
124
    /**
125
     * @return string
126
     */
127
    public function getDefaultManagerName()
128
    {
129
        $this->loadManagers();
130
131
        return $this->defaultManagerName;
132
    }
133
134
    /**
135
     * @param  null                      $name
136
     * @return ObjectManager
137
     * @throws \InvalidArgumentException
138
     */
139 View Code Duplication
    public function getManager($name = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
    {
141
        $this->loadManagers();
142
143
        if ($name === null) {
144
            $name = $this->getDefaultManagerName();
145
        }
146
147
        if (!isset($this->managers[$name])) {
148
            throw new \InvalidArgumentException(sprintf('Doctrine Manager named "%s" does not exist.', $name));
149
        }
150
151
        return $this->managers[$name];
152
    }
153
154
    /**
155
     * @return array
156
     */
157
    public function getManagers()
158
    {
159
        $this->loadManagers();
160
161
        if ($this->managers instanceof Container) {
162
            $managers = array();
163
            foreach ($this->getManagerNames() as $name) {
164
                $managers[$name] = $this->managers[$name];
165
            }
166
            $this->managers = $managers;
167
        }
168
169
        return $this->managers;
170
    }
171
172
    /**
173
     * @return array
174
     */
175
    public function getManagerNames()
176
    {
177
        $this->loadManagers();
178
179
        if ($this->managers instanceof Container) {
180
            return $this->managers->keys();
181
        } else {
182
            return array_keys($this->managers);
183
        }
184
    }
185
186
    /**
187
     * @param  null                      $name
188
     * @return void
189
     * @throws \InvalidArgumentException
190
     */
191 View Code Duplication
    public function resetManager($name = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
    {
193
        $this->loadManagers();
194
195
        if (null === $name) {
196
            $name = $this->getDefaultManagerName();
197
        }
198
199
        if (!isset($this->managers[$name])) {
200
            throw new \InvalidArgumentException(sprintf('Doctrine Manager named "%s" does not exist.', $name));
201
        }
202
203
        $this->managers[$name] = null;
204
    }
205
206
    protected function loadManagers()
207
    {
208
        if (is_null($this->managers)) {
209
            $this->managers = $this->container['mongodbodm.dms'];
210
            $this->defaultManagerName = $this->container['mongodbodm.dms.default'];
211
        }
212
    }
213
214
    /**
215
     * @param  string       $alias
216
     * @return string
217
     * @throws MongoDBException
218
     */
219
    public function getAliasNamespace($alias)
220
    {
221
        foreach ($this->getManagerNames() as $name) {
222
            try {
223
                return $this->getManager($name)->getConfiguration()->getDocumentNamespace($alias);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method getConfiguration() does only exist in the following implementations of said interface: Doctrine\ODM\MongoDB\DocumentManager.

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...
224
            } catch (MongoDBException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
225
            }
226
        }
227
        throw MongoDBException::unknownDocumentNamespace($alias);
228
    }
229
230
    /**
231
     * @param  string           $persistentObject
232
     * @param  null             $persistentManagerName
233
     * @return ObjectRepository
234
     */
235
    public function getRepository($persistentObject, $persistentManagerName = null)
236
    {
237
        return $this->getManager($persistentManagerName)->getRepository($persistentObject);
238
    }
239
240
    /**
241
     * @param  string             $class
242
     * @return ObjectManager|null
243
     */
244
    public function getManagerForClass($class)
245
    {
246
        $proxyClass = new \ReflectionClass($class);
247
        if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
248
            $class = $proxyClass->getParentClass()->getName();
249
        }
250
251
        foreach ($this->getManagerNames() as $managerName) {
252
            if (!$this->getManager($managerName)->getMetadataFactory()->isTransient($class)) {
253
                return $this->getManager($managerName);
254
            }
255
        }
256
    }
257
}
258