Completed
Pull Request — master (#50)
by Jonathan
04:13 queued 01:53
created

AbstractManagerRegistry::getManagerForClass()   A

Complexity

Conditions 6
Paths 14

Size

Total Lines 31
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6.6829

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 31
ccs 11
cts 15
cp 0.7332
rs 9.2222
c 0
b 0
f 0
cc 6
nc 14
nop 1
crap 6.6829
1
<?php
2
3
namespace Doctrine\Persistence;
4
5
use InvalidArgumentException;
6
use ReflectionClass;
7
use RuntimeException;
8
use function explode;
9
use function sprintf;
10
use function strpos;
11
12
/**
13
 * Abstract implementation of the ManagerRegistry contract.
14
 */
15
abstract class AbstractManagerRegistry implements ManagerRegistry
16
{
17
    /** @var string */
18
    private $name;
19
20
    /** @var string[] */
21
    private $connections;
22
23
    /** @var string[] */
24
    private $managers;
25
26
    /** @var string */
27
    private $defaultConnection;
28
29
    /** @var string */
30
    private $defaultManager;
31
32
    /** @var string */
33
    private $proxyInterfaceName;
34
35
    /**
36
     * @param string[] $connections
37
     * @param string[] $managers
38
     */
39 9
    public function __construct(
40
        string $name,
41
        array $connections,
42
        array $managers,
43
        string $defaultConnection,
44
        string $defaultManager,
45
        string $proxyInterfaceName
46
    ) {
47 9
        $this->name               = $name;
48 9
        $this->connections        = $connections;
49 9
        $this->managers           = $managers;
50 9
        $this->defaultConnection  = $defaultConnection;
51 9
        $this->defaultManager     = $defaultManager;
52 9
        $this->proxyInterfaceName = $proxyInterfaceName;
53 9
    }
54
55
    /**
56
     * Fetches/creates the given services.
57
     *
58
     * A service in this context is connection or a manager instance.
59
     *
60
     * @param string $name The name of the service.
61
     *
62
     * @return object The instance of the given service.
63
     */
64
    abstract protected function getService(string $name) : object;
65
66
    /**
67
     * Resets the given services.
68
     *
69
     * A service in this context is connection or a manager instance.
70
     *
71
     * @param string $name The name of the service.
72
     */
73
    abstract protected function resetService(string $name) : void;
74
75
    /**
76
     * Gets the name of the registry.
77
     */
78
    public function getName() : string
79
    {
80
        return $this->name;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function getConnection(?string $name = null) : object
87
    {
88
        if ($name === null) {
89
            $name = $this->defaultConnection;
90
        }
91
92
        if (! isset($this->connections[$name])) {
93
            throw new InvalidArgumentException(
94
                sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name)
95
            );
96
        }
97
98
        return $this->getService($this->connections[$name]);
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function getConnectionNames() : array
105
    {
106
        return $this->connections;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function getConnections() : array
113
    {
114
        $connections = [];
115
        foreach ($this->connections as $name => $id) {
116
            $connections[$name] = $this->getService($id);
117
        }
118
119
        return $connections;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function getDefaultConnectionName() : string
126
    {
127
        return $this->defaultConnection;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function getDefaultManagerName() : string
134
    {
135
        return $this->defaultManager;
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     *
141
     * @throws InvalidArgumentException
142
     */
143 4
    public function getManager(?string $name = null) : ObjectManager
144
    {
145 4
        if ($name === null) {
146 4
            $name = $this->defaultManager;
147
        }
148
149 4
        if (! isset($this->managers[$name])) {
150
            throw new InvalidArgumentException(
151
                sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)
152
            );
153
        }
154
155
        /** @var ObjectManager $objectManager */
156 4
        $objectManager = $this->getService($this->managers[$name]);
157
158 4
        return $objectManager;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164 7
    public function getManagerForClass(string $class) : ?ObjectManager
165
    {
166
        // Check for namespace alias
167 7
        if (strpos($class, ':') !== false) {
168 3
            [$namespaceAlias, $simpleClassName] = explode(':', $class, 2);
169
170 3
            $class = $this->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName;
171
        }
172
173 7
        $proxyClass = new ReflectionClass($class);
174
175 5
        if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
176
            $parentClass = $proxyClass->getParentClass();
177
178
            if (! $parentClass) {
179
                return null;
180
            }
181
182
            $class = $parentClass->getName();
183
        }
184
185 5
        foreach ($this->managers as $id) {
186
            /** @var ObjectManager $manager */
187 5
            $manager = $this->getService($id);
188
189 5
            if (! $manager->getMetadataFactory()->isTransient($class)) {
190 4
                return $manager;
191
            }
192
        }
193
194 1
        return null;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function getManagerNames() : array
201
    {
202
        return $this->managers;
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208
    public function getManagers() : array
209
    {
210
        $dms = [];
211
        foreach ($this->managers as $name => $id) {
212
            /** @var ObjectManager $manager */
213
            $manager = $this->getService($id);
214
215
            $dms[$name] = $manager;
216
        }
217
218
        return $dms;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224 3
    public function getRepository(
225
        string $persistentObjectName,
226
        ?string $persistentManagerName = null
227
    ) : ObjectRepository {
228 3
        $manager = $this->selectManager($persistentObjectName, $persistentManagerName);
229
230 3
        if ($manager === null) {
231
            throw new RuntimeException(
232
                sprintf('Could not find object manager for class %s', $persistentObjectName)
233
            );
234
        }
235
236 3
        return $manager->getRepository($persistentObjectName);
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     */
242 1
    public function resetManager(?string $name = null) : ObjectManager
243
    {
244 1
        if ($name === null) {
245 1
            $name = $this->defaultManager;
246
        }
247
248 1
        if (! isset($this->managers[$name])) {
249
            throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name));
250
        }
251
252
        // force the creation of a new document manager
253
        // if the current one is closed
254 1
        $this->resetService($this->managers[$name]);
255
256 1
        return $this->getManager($name);
257
    }
258
259 3
    private function selectManager(
260
        string $persistentObjectName,
261
        ?string $persistentManagerName = null
262
    ) : ?ObjectManager {
263 3
        if ($persistentManagerName !== null) {
264 1
            return $this->getManager($persistentManagerName);
265
        }
266
267 2
        return $this->getManagerForClass($persistentObjectName) ?? $this->getManager();
268
    }
269
}
270