Completed
Push — master ( fb0873...0bfc19 )
by Julián
02:05
created

MongoDBBuilder::buildManager()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 39
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.439
c 0
b 0
f 0
nc 16
cc 5
eloc 23
nop 0
1
<?php
2
3
/*
4
 * doctrine-manager-builder (https://github.com/juliangut/doctrine-manager-builder).
5
 * Doctrine2 managers builder.
6
 *
7
 * @license BSD-3-Clause
8
 * @link https://github.com/juliangut/doctrine-manager-builder
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
namespace Jgut\Doctrine\ManagerBuilder;
13
14
use Doctrine\Common\Annotations\AnnotationReader;
15
use Doctrine\Common\Proxy\AbstractProxyFactory;
16
use Doctrine\MongoDB\Connection;
17
use Doctrine\ODM\MongoDB\Configuration;
18
use Doctrine\ODM\MongoDB\DocumentManager;
19
use Doctrine\ODM\MongoDB\DocumentRepository;
20
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
21
use Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver;
22
use Doctrine\ODM\MongoDB\Mapping\Driver\YamlDriver;
23
use Doctrine\ODM\MongoDB\Repository\RepositoryFactory;
24
use Doctrine\ODM\MongoDB\Tools\Console\Helper\DocumentManagerHelper;
25
use Symfony\Component\Console\Command\Command;
26
use Symfony\Component\Console\Helper\HelperSet;
27
28
/**
29
 * Doctrine MongoDB Document Manager builder.
30
 */
31
class MongoDBBuilder extends AbstractManagerBuilder
32
{
33
    /**
34
     * Document Manager.
35
     *
36
     * @var DocumentManager
37
     */
38
    protected $manager;
39
40
    /**
41
     * Logger callable.
42
     *
43
     * @var callable
44
     */
45
    protected $loggerCallable;
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    protected function getDefaultOptions()
51
    {
52
        return [
53
            'connection' => [], // Array or \Doctrine\MongoDB\Connection
54
            'proxies_namespace' => 'DoctrineMongoDBODMProxy',
55
            'metadata_cache_namespace' => 'DoctrineMongoDBODMMetadataCache',
56
            'default_repository_class' => DocumentRepository::class,
57
            'hydrators_namespace' => 'DoctrineMongoDBODMHydrator',
58
            'hydrators_auto_generation' => AbstractProxyFactory::AUTOGENERATE_NEVER,
59
            'persistent_collections_namespace' => 'DoctrineMongoDBODMPersistentCollection',
60
            'persistent_collections_auto_generation' => AbstractProxyFactory::AUTOGENERATE_NEVER,
61
        ];
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     *
67
     * @throws \Doctrine\ODM\MongoDB\MongoDBException
68
     * @throws \InvalidArgumentException
69
     * @throws \RuntimeException
70
     * @throws \UnexpectedValueException
71
     *
72
     * @return DocumentManager
73
     */
74
    public function getManager($force = false)
75
    {
76
        if ($force === true) {
77
            $this->wipe();
78
        }
79
80
        if (!$this->manager instanceof DocumentManager) {
81
            $this->manager = $this->buildManager();
82
        }
83
84
        return $this->manager;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    protected function wipe()
91
    {
92
        parent::wipe();
93
94
        $this->manager = null;
95
        $this->loggerCallable = null;
96
    }
97
98
    /**
99
     * Build Doctrine MongoDB Document Manager.
100
     *
101
     * @throws \Doctrine\ODM\MongoDB\MongoDBException
102
     * @throws \InvalidArgumentException
103
     * @throws \RuntimeException
104
     * @throws \UnexpectedValueException
105
     *
106
     * @return DocumentManager
107
     */
108
    protected function buildManager()
109
    {
110
        $config = new Configuration;
111
112
        $this->setupAnnotationMetadata();
113
        $config->setMetadataDriverImpl($this->getMetadataMappingDriver());
114
115
        $config->setProxyDir($this->getProxiesPath());
116
        $config->setProxyNamespace($this->getProxiesNamespace());
117
        $config->setAutoGenerateProxyClasses($this->getProxiesAutoGeneration());
118
119
        $config->setHydratorDir($this->getHydratorsPath());
120
        $config->setHydratorNamespace($this->getHydratorsNamespace());
121
        $config->setAutoGenerateHydratorClasses($this->getHydratorsAutoGeneration());
122
123
        $config->setPersistentCollectionDir($this->getPersistentCollectionPath());
124
        $config->setPersistentCollectionNamespace($this->getPersistentCollectionNamespace());
125
        $config->setAutoGeneratePersistentCollectionClasses($this->getAutoGeneratePersistentCollection());
126
127
        $config->setMetadataCacheImpl($this->getMetadataCacheDriver());
128
129
        if ($this->getRepositoryFactory() !== null) {
130
            $config->setRepositoryFactory($this->getRepositoryFactory());
131
        }
132
133
        if ($this->getDefaultRepositoryClass() !== null) {
134
            $config->setDefaultRepositoryClassName($this->getDefaultRepositoryClass());
135
        }
136
137
        if ($this->getDefaultDatabase() !== null) {
138
            $config->setDefaultDB($this->getDefaultDatabase());
139
        }
140
141
        if ($this->getLoggerCallable() !== null) {
142
            $config->setLoggerCallable($this->getLoggerCallable());
143
        }
144
145
        return DocumentManager::create($this->getConnection($config), $config, $this->getEventManager());
146
    }
147
148
    /**
149
     * Create MongoDB Connection.
150
     *
151
     * @param Configuration $config
152
     *
153
     * @throws \InvalidArgumentException
154
     * @throws \RuntimeException
155
     *
156
     * @return Connection
157
     */
158
    protected function getConnection(Configuration $config)
159
    {
160
        $connection = $this->getOption('connection');
161
162
        switch (true) {
163
            case is_array($connection):
164
                $connection = new Connection(
165
                    array_key_exists('server', $connection) ? $connection['server'] : null,
166
                    array_key_exists('options', $connection) ? $connection['options'] : [],
167
                    $config,
168
                    $this->getEventManager()
169
                );
170
                break;
171
172
            case $connection instanceof Connection:
173
                if ($connection->getEventManager() !== $this->getEventManager()) {
174
                    throw new \RuntimeException(
175
                        'Cannot use different EventManager instances for DocumentManager and Connection.'
176
                    );
177
                }
178
                break;
179
180
            default:
181
                throw new \InvalidArgumentException('Invalid argument: ' . $connection);
182
        }
183
184
        return $connection;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    protected function getAnnotationMetadataDriver(array $paths)
191
    {
192
        return new AnnotationDriver(new AnnotationReader, $paths);
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    protected function getXmlMetadataDriver(array $paths, $extension = null)
199
    {
200
        return new XmlDriver($paths, $extension ?: XmlDriver::DEFAULT_FILE_EXTENSION);
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206
    protected function getYamlMetadataDriver(array $paths, $extension = null)
207
    {
208
        return new YamlDriver($paths, $extension ?: YamlDriver::DEFAULT_FILE_EXTENSION);
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     *
214
     * @throws \InvalidArgumentException
215
     *
216
     * @return RepositoryFactory|null
217
     */
218
    protected function getRepositoryFactory()
219
    {
220
        if (!array_key_exists('repository_factory', $this->options)) {
221
            return;
222
        }
223
224
        $repositoryFactory = $this->options['repository_factory'];
225
226
        if (!$repositoryFactory instanceof RepositoryFactory) {
227
            throw new \InvalidArgumentException(sprintf(
228
                'Invalid factory class "%s". It must be a Doctrine\ODM\MongoDB\Repository\RepositoryFactory.',
229
                get_class($repositoryFactory)
230
            ));
231
        }
232
233
        return $repositoryFactory;
234
    }
235
236
    /**
237
     * Retrieve hydrators path.
238
     *
239
     * @return string
240
     */
241
    protected function getHydratorsPath()
242
    {
243
        return (string) $this->getOption('hydrators_path', sys_get_temp_dir());
244
    }
245
246
    /**
247
     * Retrieve hydrators namespace.
248
     *
249
     * @return null|string
250
     */
251
    protected function getHydratorsNamespace()
252
    {
253
        $proxyNamespace = $this->getOption('hydrators_namespace');
254
255
        return is_string($proxyNamespace) ? $proxyNamespace : null;
256
    }
257
258
    /**
259
     * Retrieve hydrators generation strategy.
260
     *
261
     * @return int
262
     */
263
    protected function getHydratorsAutoGeneration()
264
    {
265
        return (int) $this->getOption('hydrators_auto_generation');
266
    }
267
268
    /**
269
     * Retrieve persistent collections path.
270
     *
271
     * @return string
272
     */
273
    protected function getPersistentCollectionPath()
274
    {
275
        return (string) $this->getOption('persistent_collections_path', sys_get_temp_dir());
276
    }
277
278
    /**
279
     * Retrieve persistent collections namespace.
280
     *
281
     * @return null|string
282
     */
283
    protected function getPersistentCollectionNamespace()
284
    {
285
        $collectionNamespace = $this->getOption('persistent_collections_namespace');
286
287
        return is_string($collectionNamespace) ? $collectionNamespace : null;
288
    }
289
290
    /**
291
     * Retrieve persistent collections generation strategy.
292
     *
293
     * @return int
294
     */
295
    protected function getAutoGeneratePersistentCollection()
296
    {
297
        return (int) $this->getOption('persistent_collections_auto_generation');
298
    }
299
300
    /**
301
     * Get default database.
302
     *
303
     * @return string|null
304
     */
305
    protected function getDefaultDatabase()
306
    {
307
        return $this->hasOption('default_database') ? (string) $this->getOption('default_database') : null;
308
    }
309
310
    /**
311
     * Retrieve logger callable.
312
     *
313
     * @return callable|null
314
     */
315
    protected function getLoggerCallable()
316
    {
317
        if (!is_callable($this->loggerCallable)) {
318
            $loggerCallable = $this->getOption('logger_callable');
319
320
            if (is_callable($loggerCallable)) {
321
                $this->loggerCallable = $loggerCallable;
322
            }
323
        }
324
325
        return $this->loggerCallable;
326
    }
327
328
    /**
329
     * {@inheritdoc}
330
     *
331
     * @throws \Doctrine\ODM\MongoDB\MongoDBException
332
     * @throws \InvalidArgumentException
333
     * @throws \RuntimeException
334
     * @throws \Symfony\Component\Console\Exception\InvalidArgumentException
335
     * @throws \Symfony\Component\Console\Exception\LogicException
336
     * @throws \UnexpectedValueException
337
     *
338
     * @return Command[]
339
     */
340
    public function getConsoleCommands()
341
    {
342
        $commands = [
343
            // ODM
344
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\GenerateDocumentsCommand,
345
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\GenerateHydratorsCommand,
346
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\GenerateProxiesCommand,
347
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\GenerateRepositoriesCommand,
348
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\QueryCommand,
349
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\ClearCache\MetadataCommand,
350
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\Schema\CreateCommand,
351
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\Schema\DropCommand,
352
            new \Doctrine\ODM\MongoDB\Tools\Console\Command\Schema\UpdateCommand,
353
        ];
354
        $commandPrefix = (string) $this->getName();
355
356
        if ($commandPrefix !== '') {
357
            $commands = array_map(
358
                function (Command $command) use ($commandPrefix) {
359
                    $commandNames = array_map(
360
                        function ($commandName) use ($commandPrefix) {
361
                            return preg_replace('/^odm:/', $commandPrefix . ':odm:', $commandName);
362
                        },
363
                        array_merge([$command->getName()], $command->getAliases())
364
                    );
365
366
                    $command->setName(array_shift($commandNames));
367
                    $command->setAliases($commandNames);
368
369
                    return $command;
370
                },
371
                $commands
372
            );
373
        }
374
375
        return $commands;
376
    }
377
378
    /**
379
     * {@inheritdoc}
380
     *
381
     * @throws \Doctrine\ODM\MongoDB\MongoDBException
382
     * @throws \InvalidArgumentException
383
     * @throws \RuntimeException
384
     * @throws \UnexpectedValueException
385
     */
386
    public function getConsoleHelperSet()
387
    {
388
        return new HelperSet([
389
            'dm' => new DocumentManagerHelper($this->getManager()),
390
        ]);
391
    }
392
}
393