Completed
Push — master ( b5054b...5e1fc6 )
by Julián
02:29
created

AbstractManagerBuilder::getMappingDriver()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 15
nc 4
nop 1
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\AnnotationRegistry;
15
use Doctrine\Common\Cache\CacheProvider;
16
use Doctrine\Common\EventManager;
17
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
18
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
19
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver;
20
use Doctrine\Common\Persistence\ObjectManager;
21
use Doctrine\Common\Proxy\AbstractProxyFactory;
22
use Jgut\Doctrine\ManagerBuilder\Util\CacheBuilder;
23
use Jgut\Doctrine\ManagerBuilder\Util\OptionsTrait;
24
25
/**
26
 * Abstract Doctrine Manager builder.
27
 */
28
abstract class AbstractManagerBuilder implements ManagerBuilder
29
{
30
    use OptionsTrait;
31
32
    /**
33
     * Manager builder's common default options.
34
     *
35
     * @var array
36
     */
37
    private $defaultOptions = [
38
        'proxies_auto_generation' => AbstractProxyFactory::AUTOGENERATE_NEVER,
39
    ];
40
41
    /**
42
     * Builder name.
43
     *
44
     * @var
45
     */
46
    protected $name;
47
48
    /**
49
     * Object Manager.
50
     *
51
     * @var ObjectManager
52
     */
53
    protected $manager;
54
55
    /**
56
     * Metadata mapping driver.
57
     *
58
     * @var MappingDriverChain
59
     */
60
    protected $mappingDriver;
61
62
    /**
63
     * Metadata cache driver.
64
     *
65
     * @var CacheProvider
66
     */
67
    protected $metadataCacheDriver;
68
69
    /**
70
     * Event manager.
71
     *
72
     * @var EventManager
73
     */
74
    protected $eventManager;
75
76
    /**
77
     * ManagerBuilder constructor.
78
     *
79
     * @param array       $options
80
     * @param string|null $name
81
     */
82
    public function __construct(array $options = [], $name = null)
83
    {
84
        $this->setOptions(array_merge($this->defaultOptions, $this->getDefaultOptions(), $options));
85
        $this->setName($name);
86
    }
87
88
    /**
89
     * Get manager builder's default options.
90
     *
91
     * @return array
92
     */
93
    abstract protected function getDefaultOptions();
94
95
    /**
96
     * {@inheritdoc}
97
     *
98
     * @return ObjectManager
99
     */
100
    public function getManager($force = false)
101
    {
102
        if ($force === true) {
103
            $this->wipe();
104
        }
105
106
        if (!$this->manager instanceof ObjectManager) {
107
            $this->manager = $this->buildManager();
108
        }
109
110
        return $this->manager;
111
    }
112
113
    /**
114
     * Unset created objects for rebuild.
115
     */
116
    abstract protected function wipe();
117
118
    /**
119
     * Build new Doctrine object manager.
120
     *
121
     * @return ObjectManager
122
     */
123
    abstract protected function buildManager();
124
125
    /**
126
     * {@inheritdoc}
127
     *
128
     * @return string|null
129
     */
130
    public function getName()
131
    {
132
        return $this->name;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     *
138
     * @return $this
139
     */
140
    public function setName($name = null)
141
    {
142
        $this->name = $name;
143
144
        return $this;
145
    }
146
147
    /**
148
     * Set up annotation metadata.
149
     *
150
     * @throws \InvalidArgumentException
151
     * @throws \RuntimeException
152
     */
153
    protected function setupAnnotationMetadata()
154
    {
155
        $annotationFiles = (array) $this->getOption('annotation_files');
156
        array_walk(
157
            $annotationFiles,
158
            function ($file) {
159
                if (!file_exists($file)) {
160
                    throw new \RuntimeException(sprintf('"%s" file does not exist', $file));
161
                }
162
163
                AnnotationRegistry::registerFile($file);
164
            }
165
        );
166
167
        AnnotationRegistry::registerAutoloadNamespaces($this->getAnnotationNamespaces());
168
169
        $annotationLoaders = (array) $this->getOption('annotation_autoloaders');
170
        array_walk(
171
            $annotationLoaders,
172
            function ($autoLoader) {
173
                AnnotationRegistry::registerLoader($autoLoader);
174
            }
175
        );
176
    }
177
178
    /**
179
     * Retrieve annotation namespaces.
180
     *
181
     * @return array
182
     */
183
    protected function getAnnotationNamespaces()
184
    {
185
        $namespaces = (array) $this->getOption('annotation_namespaces');
186
187
        return array_filter(
188
            $namespaces,
189
            function ($namespace) {
190
                return is_string($namespace);
191
            },
192
            ARRAY_FILTER_USE_KEY
193
        );
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     *
199
     * @throws \RuntimeException
200
     * @throws \UnexpectedValueException
201
     */
202
    public function getMetadataMappingDriver()
203
    {
204
        if (!$this->mappingDriver instanceof MappingDriverChain) {
205
            $metadataDriverChain = new MappingDriverChain;
206
207
            $this->parseMetadataMapping($metadataDriverChain);
208
209
            if ($metadataDriverChain->getDefaultDriver() === null && count($metadataDriverChain->getDrivers()) === 0) {
210
                throw new \RuntimeException('No metadata mapping defined');
211
            }
212
213
            $this->mappingDriver = $metadataDriverChain;
214
        }
215
216
        return $this->mappingDriver;
217
    }
218
219
    /**
220
     * Parse metadata mapping configuration.
221
     *
222
     * @param MappingDriverChain $metadataDriverChain
223
     *
224
     * @throws \RuntimeException
225
     */
226
    protected function parseMetadataMapping(MappingDriverChain $metadataDriverChain)
227
    {
228
        foreach ((array) $this->getOption('metadata_mapping') as $metadataMapping) {
229
            if (!is_array($metadataMapping)) {
230
                $metadataMapping = ['driver' => $metadataMapping];
231
            }
232
233
            if (!array_key_exists('namespace', $metadataMapping) && $metadataDriverChain->getDefaultDriver() !== null) {
234
                throw new \RuntimeException(
235
                    'Only one default metadata mapping driver allowed, a namespace must be defined'
236
                );
237
            }
238
239
            $mappingDriver = $this->getMappingDriver($metadataMapping);
240
241
            if (array_key_exists('namespace', $metadataMapping)) {
242
                $metadataDriverChain->addDriver($mappingDriver, $metadataMapping['namespace']);
243
            } else {
244
                $metadataDriverChain->setDefaultDriver($mappingDriver);
245
            }
246
        }
247
    }
248
249
    /**
250
     * Retrieve mapping driver.
251
     *
252
     * @param array $metadataMapping
253
     *
254
     * @throws \UnexpectedValueException
255
     *
256
     * @return MappingDriver
257
     */
258
    protected function getMappingDriver(array $metadataMapping)
259
    {
260
        if (array_key_exists('driver', $metadataMapping)) {
261
            $mappingDriver = $metadataMapping['driver'];
262
263
            if (!$mappingDriver instanceof MappingDriver) {
264
                throw new \UnexpectedValueException(
265
                    sprintf('Provided driver should be of the type MappingDriver, "%s" given', gettype($mappingDriver))
266
                );
267
            }
268
269
            return $mappingDriver;
270
        }
271
272
        if (count(array_intersect(['type', 'path'], array_keys($metadataMapping))) === 2) {
273
            $metadataMapping = array_merge(['extension' => null], $metadataMapping);
274
275
            return $this->getMappingDriverImplementation(
276
                $metadataMapping['type'],
277
                (array) $metadataMapping['path'],
278
                $metadataMapping['extension']
279
            );
280
        }
281
282
        throw new \UnexpectedValueException(
283
            'metadata_mapping must be array with "driver" key or "type" and "path" keys'
284
        );
285
    }
286
287
    /**
288
     * Get metadata mapping driver implementation.
289
     *
290
     * @param string $type
291
     * @param array  $paths
292
     * @param string $extension
293
     *
294
     * @throws \UnexpectedValueException
295
     *
296
     * @return MappingDriver|PHPDriver
297
     */
298
    protected function getMappingDriverImplementation($type, $paths, $extension)
299
    {
300
        switch ($type) {
301
            case ManagerBuilder::METADATA_MAPPING_ANNOTATION:
302
                return $this->getAnnotationMappingDriver($paths);
303
304
            case ManagerBuilder::METADATA_MAPPING_XML:
305
                return $this->getXmlMappingDriver($paths, $extension);
306
307
            case ManagerBuilder::METADATA_MAPPING_YAML:
308
                return $this->getYamlMappingDriver($paths, $extension);
309
310
            case ManagerBuilder::METADATA_MAPPING_PHP:
311
                return $this->getPhpMappingDriver($paths);
312
        }
313
314
        throw new \UnexpectedValueException(
315
            sprintf('"%s" is not a valid metadata mapping type', $type)
316
        );
317
    }
318
319
    /**
320
     * Get annotation metadata driver.
321
     *
322
     * @param array $paths
323
     *
324
     * @return MappingDriver
325
     */
326
    abstract protected function getAnnotationMappingDriver(array $paths);
327
328
    /**
329
     * Get XML metadata driver.
330
     *
331
     * @param array       $paths
332
     * @param string|null $extension
333
     *
334
     * @return MappingDriver
335
     */
336
    abstract protected function getXmlMappingDriver(array $paths, $extension = null);
337
338
    /**
339
     * Get YAML metadata driver.
340
     *
341
     * @param array       $paths
342
     * @param string|null $extension
343
     *
344
     * @return MappingDriver
345
     */
346
    abstract protected function getYamlMappingDriver(array $paths, $extension = null);
347
348
    /**
349
     * Get PHP metadata driver.
350
     *
351
     * @param array $paths
352
     *
353
     * @return PHPDriver
354
     */
355
    protected function getPhpMappingDriver(array $paths)
356
    {
357
        return new PHPDriver($paths);
358
    }
359
360
    /**
361
     * {@inheritdoc}
362
     *
363
     * @return $this
364
     */
365
    public function setMetadataMappingDriver(MappingDriverChain $mappingDriver)
366
    {
367
        $this->mappingDriver = $mappingDriver;
368
369
        return $this;
370
    }
371
372
    /**
373
     * Get custom repository factory.
374
     */
375
    abstract protected function getRepositoryFactory();
376
377
    /**
378
     * Get default repository class name.
379
     *
380
     * @return string|null
381
     */
382
    protected function getDefaultRepositoryClass()
383
    {
384
        return array_key_exists('default_repository_class', $this->options)
385
            ? (string) $this->options['default_repository_class']
386
            : null;
387
    }
388
389
    /**
390
     * Retrieve proxies path.
391
     *
392
     * @return string
393
     */
394
    protected function getProxiesPath()
395
    {
396
        return (string) $this->getOption('proxies_path', sys_get_temp_dir());
397
    }
398
399
    /**
400
     * Retrieve proxies namespace.
401
     *
402
     * @return null|string
403
     */
404
    protected function getProxiesNamespace()
405
    {
406
        $proxyNamespace = $this->getOption('proxies_namespace');
407
408
        return is_string($proxyNamespace) ? $proxyNamespace : null;
409
    }
410
411
    /**
412
     * Retrieve proxy generation strategy.
413
     *
414
     * @return int
415
     */
416
    protected function getProxiesAutoGeneration()
417
    {
418
        return (int) $this->getOption('proxies_auto_generation');
419
    }
420
421
    /**
422
     * {@inheritdoc}
423
     *
424
     * @throws \InvalidArgumentException
425
     */
426
    public function getMetadataCacheDriver()
427
    {
428
        if (!$this->metadataCacheDriver instanceof CacheProvider) {
429
            $metadataCacheDriver = $this->getOption('metadata_cache_driver');
430
431
            if (!$metadataCacheDriver instanceof CacheProvider) {
432
                $metadataCacheDriver = CacheBuilder::build();
433
            }
434
435
            if ($metadataCacheDriver->getNamespace() === '') {
436
                $metadataCacheDriver->setNamespace((string) $this->getOption('metadata_cache_namespace'));
437
            }
438
439
            $this->metadataCacheDriver = $metadataCacheDriver;
440
        }
441
442
        return $this->metadataCacheDriver;
443
    }
444
445
    /**
446
     * {@inheritdoc}
447
     *
448
     * @return $this
449
     */
450
    public function setMetadataCacheDriver(CacheProvider $metadataCacheDriver)
451
    {
452
        $this->metadataCacheDriver = $metadataCacheDriver;
453
454
        return $this;
455
    }
456
457
    /**
458
     * {@inheritdoc}
459
     */
460
    public function getEventManager()
461
    {
462
        if (!$this->eventManager instanceof EventManager) {
463
            $eventManager = $this->getOption('event_manager');
464
465
            if (!$eventManager instanceof EventManager) {
466
                $eventManager = new EventManager;
467
            }
468
469
            $this->eventManager = $eventManager;
470
        }
471
472
        return $this->eventManager;
473
    }
474
475
    /**
476
     * {@inheritdoc}
477
     *
478
     * @return $this
479
     */
480
    public function setEventManager(EventManager $eventManager)
481
    {
482
        $this->eventManager = $eventManager;
483
484
        return $this;
485
    }
486
487
    /**
488
     * Get event subscribers.
489
     *
490
     * @return array|null
491
     */
492
    protected function getEventSubscribers()
493
    {
494
        $eventSubscribers = $this->getOption('event_subscribers');
495
496
        if (is_null($eventSubscribers) || !is_array($eventSubscribers)) {
497
            return;
498
        }
499
500
        return array_filter(
501
            $eventSubscribers,
502
            function ($name) {
503
                return is_string($name);
504
            },
505
            ARRAY_FILTER_USE_KEY
506
        );
507
    }
508
}
509