Completed
Push — master ( 7eb259...e42f4b )
by Dominik
08:43
created

DoctrineOrmManagerRegistry   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Test Coverage

Coverage 65.43%

Importance

Changes 0
Metric Value
wmc 29
lcom 2
cbo 4
dl 0
loc 256
ccs 53
cts 81
cp 0.6543
rs 10
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() 0 12 2
A getConnections() 0 11 2
A getConnectionNames() 0 6 1
A getDefaultManagerName() 0 6 1
A getManager() 0 16 3
A getManagers() 0 17 3
A getManagerNames() 0 6 1
A resetManager() 0 20 2
A getAliasNamespace() 0 11 3
A getRepository() 0 4 1
A getManagerForClass() 0 13 4
A loadConnections() 0 7 2
A loadManagers() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\ServiceProvider\Registry;
6
7
use Doctrine\Common\Persistence\ManagerRegistry;
8
use Doctrine\Common\Persistence\ObjectManager;
9
use Doctrine\Common\Persistence\ObjectRepository;
10
use Doctrine\DBAL\Connection;
11
use Doctrine\ORM\EntityManager;
12
use Doctrine\ORM\EntityRepository;
13
use Doctrine\ORM\ORMException;
14
use Doctrine\ORM\Proxy\Proxy;
15
use Pimple\Container;
16
17
final class DoctrineOrmManagerRegistry implements ManagerRegistry
18
{
19
    /**
20
     * @var Container
21
     */
22
    private $container;
23
24
    /**
25
     * @var Container|Connection[]
26
     */
27
    private $connections;
28
29
    /**
30
     * @var string
31
     */
32
    private $defaultConnectionName;
33
34
    /**
35
     * @var Container|EntityManager[]
36
     */
37
    private $originalManagers;
38
39
    /**
40
     * @var EntityManager[]
41
     */
42
    private $resetManagers = [];
43
44
    /**
45
     * @var string
46
     */
47
    private $defaultManagerName;
48
49
    /**
50
     * @var string
51
     */
52
    private $proxyInterfaceName;
53
54
    /**
55
     * @param Container $container
56
     * @param string    $proxyInterfaceName
57
     */
58 10
    public function __construct(Container $container, $proxyInterfaceName = Proxy::class)
59
    {
60 10
        $this->container = $container;
61 10
        $this->proxyInterfaceName = $proxyInterfaceName;
62 10
    }
63
64
    /**
65
     * @return string
66
     */
67 3
    public function getDefaultConnectionName(): string
68
    {
69 3
        $this->loadConnections();
70
71 3
        return $this->defaultConnectionName;
72
    }
73
74
    /**
75
     * @param string|null $name
76
     *
77
     * @return Connection
78
     *
79
     * @throws \InvalidArgumentException
80
     */
81 2
    public function getConnection($name = null): Connection
82
    {
83 2
        $this->loadConnections();
84
85 2
        $name = $name ?? $this->getDefaultConnectionName();
86
87 2
        if (!isset($this->connections[$name])) {
88 1
            throw new \InvalidArgumentException(sprintf('Missing connection with name "%s".', $name));
89
        }
90
91 1
        return $this->connections[$name];
92
    }
93
94
    /**
95
     * @return Connection[]
96
     */
97 1
    public function getConnections(): array
98
    {
99 1
        $this->loadConnections();
100
101 1
        $connections = array();
102 1
        foreach ($this->connections->keys() as $name) {
103 1
            $connections[$name] = $this->connections[$name];
104
        }
105
106 1
        return $connections;
107
    }
108
109
    /**
110
     * @return string[]
111
     */
112 1
    public function getConnectionNames(): array
113
    {
114 1
        $this->loadConnections();
115
116 1
        return $this->connections->keys();
117
    }
118
119
    /**
120
     * @return string
121
     */
122 3
    public function getDefaultManagerName(): string
123
    {
124 3
        $this->loadManagers();
125
126 3
        return $this->defaultManagerName;
127
    }
128
129
    /**
130
     * @param string|null $name
131
     *
132
     * @return EntityManager|ObjectManager
133
     */
134 2
    public function getManager($name = null): ObjectManager
135
    {
136 2
        $this->loadManagers();
137
138 2
        $name = $name ?? $this->getDefaultManagerName();
139
140 2
        if (!isset($this->originalManagers[$name])) {
141 1
            throw new \InvalidArgumentException(sprintf('Missing manager with name "%s".', $name));
142
        }
143
144 1
        if (isset($this->resetManagers[$name])) {
145
            return $this->resetManagers[$name];
146
        }
147
148 1
        return $this->originalManagers[$name];
149
    }
150
151
    /**
152
     * @return EntityManager[]|ObjectManager[]
153
     */
154 1
    public function getManagers(): array
155
    {
156 1
        $this->loadManagers();
157
158 1
        $managers = array();
159 1
        foreach ($this->originalManagers->keys() as $name) {
160 1
            if (isset($this->resetManagers[$name])) {
161
                $manager = $this->resetManagers[$name];
162
            } else {
163 1
                $manager = $this->originalManagers[$name];
164
            }
165
166 1
            $managers[$name] = $manager;
167
        }
168
169 1
        return $managers;
170
    }
171
172
    /**
173
     * @return array
174
     */
175 1
    public function getManagerNames(): array
176
    {
177 1
        $this->loadManagers();
178
179 1
        return $this->originalManagers->keys();
180
    }
181
182
    /**
183
     * @param string|null $name
184
     *
185
     * @return EntityManager|ObjectManager
186
     */
187
    public function resetManager($name = null)
188
    {
189
        $this->loadManagers();
190
191
        $name = $name ?? $this->getDefaultManagerName();
192
193
        if (!isset($this->originalManagers[$name])) {
194
            throw new \InvalidArgumentException(sprintf('Missing manager with name "%s".', $name));
195
        }
196
197
        $originalManager = $this->originalManagers[$name];
198
199
        $this->resetManagers[$name] = EntityManager::create(
200
            $originalManager->getConnection(),
201
            $originalManager->getConfiguration(),
202
            $originalManager->getEventManager()
203
        );
204
205
        return $this->resetManagers[$name];
206
    }
207
208
    /**
209
     * @param string $alias
210
     *
211
     * @return string
212
     *
213
     * @throws ORMException
214
     */
215
    public function getAliasNamespace($alias): string
216
    {
217
        foreach ($this->getManagerNames() as $name) {
218
            try {
219
                return $this->getManager($name)->getConfiguration()->getEntityNamespace($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\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

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...
220
            } catch (ORMException $e) {
221
                // throw the exception only if no manager can solve it
222
            }
223
        }
224
        throw ORMException::unknownEntityNamespace($alias);
225
    }
226
227
    /**
228
     * @param string $persistentObject
229
     * @param null   $persistentManagerName
230
     *
231
     * @return EntityRepository|ObjectRepository
232
     */
233
    public function getRepository($persistentObject, $persistentManagerName = null): ObjectRepository
234
    {
235
        return $this->getManager($persistentManagerName)->getRepository($persistentObject);
236
    }
237
238
    /**
239
     * @param string $class
240
     *
241
     * @return EntityManager|ObjectManager|null
242
     */
243
    public function getManagerForClass($class)
244
    {
245
        $proxyClass = new \ReflectionClass($class);
246
        if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
247
            $class = $proxyClass->getParentClass()->getName();
248
        }
249
250
        foreach ($this->getManagerNames() as $name) {
251
            if (!$this->getManager($name)->getMetadataFactory()->isTransient($class)) {
252
                return $this->getManager($name);
253
            }
254
        }
255
    }
256
257 5
    private function loadConnections()
258
    {
259 5
        if (null === $this->connections) {
260 5
            $this->connections = $this->container['doctrine.dbal.dbs'];
261 5
            $this->defaultConnectionName = $this->container['doctrine.dbal.dbs.default'];
262
        }
263 5
    }
264
265 5
    private function loadManagers()
266
    {
267 5
        if (null === $this->originalManagers) {
268 5
            $this->originalManagers = $this->container['doctrine.orm.ems'];
269 5
            $this->defaultManagerName = $this->container['doctrine.orm.ems.default'];
270
        }
271 5
    }
272
}
273