Completed
Push — master ( 2d575f...4695ab )
by Julián
02:36
created

AbstractManagerBuilder::getAnnotationNamespaces()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
/**
3
 * doctrine-manager-builder (https://github.com/juliangut/doctrine-manager-builder)
4
 * Doctrine2 managers builder
5
 *
6
 * @license BSD-3-Clause
7
 * @author Julián Gutiérrez <[email protected]>
8
 */
9
10
namespace Jgut\Doctrine\ManagerBuilder;
11
12
use Doctrine\Common\Annotations\AnnotationRegistry;
13
use Doctrine\Common\Cache\ApcuCache;
14
use Doctrine\Common\Cache\ArrayCache;
15
use Doctrine\Common\Cache\Cache;
16
use Doctrine\Common\Cache\CacheProvider;
17
use Doctrine\Common\Cache\MemcacheCache;
18
use Doctrine\Common\Cache\RedisCache;
19
use Doctrine\Common\Cache\XcacheCache;
20
use Doctrine\Common\EventManager;
21
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
22
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
23
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver;
24
25
/**
26
 * Abstract Doctrine Manager builder.
27
 */
28
abstract class AbstractManagerBuilder implements ManagerBuilder
29
{
30
    /**
31
     * Builder name.
32
     *
33
     * @var
34
     */
35
    protected $name;
36
37
    /**
38
     * Builder options.
39
     *
40
     * @var array
41
     */
42
    protected $options = [];
43
44
    /**
45
     * Metadata mapping driver.
46
     *
47
     * @var MappingDriverChain
48
     */
49
    protected $mappingDriver;
50
51
    /**
52
     * General cache driver.
53
     *
54
     * @var Cache
55
     */
56
    protected $cacheDriver;
57
58
    /**
59
     * Metadata cache driver.
60
     *
61
     * @var Cache
62
     */
63
    protected $metadataCacheDriver;
64
65
    /**
66
     * Mapping driver chain.
67
     *
68
     * @var MappingDriverChain
69
     */
70
    protected $mappingDriverChain;
71
72
    /**
73
     * Event manager.
74
     *
75
     * @var EventManager
76
     */
77
    protected $eventManager;
78
79
    /**
80
     * ManagerBuilder constructor.
81
     *
82
     * @param array       $options
83
     * @param string|null $name
84
     */
85
    public function __construct(array $options = [], $name = null)
86
    {
87
        $this->setOptions(array_merge($this->getDefaultOptions(), $options));
88
        $this->setName($name);
89
    }
90
91
    /**
92
     * Unset created objects for rebuild.
93
     */
94
    protected function wipe()
95
    {
96
        $this->mappingDriver = null;
97
        $this->cacheDriver = null;
98
        $this->metadataCacheDriver = null;
99
        $this->mappingDriverChain = null;
100
        $this->eventManager = null;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     *
106
     * @return string|null
107
     */
108
    public function getName()
109
    {
110
        return $this->name;
111
    }
112
113
    /**
114
     * Set builder's name.
115
     *
116
     * @param string|null $name
117
     *
118
     * @return $this
119
     */
120
    public function setName($name = null)
121
    {
122
        $this->name = $name;
123
124
        return $this;
125
    }
126
127
    /**
128
     * Get default options.
129
     *
130
     * @return array
131
     */
132
    abstract protected function getDefaultOptions();
133
134
    /**
135
     * Retrieve builder options.
136
     *
137
     * @return array
138
     */
139
    public function getOptions()
140
    {
141
        return $this->options;
142
    }
143
144
    /**
145
     * Retrieve builder option.
146
     *
147
     * @param string     $option
148
     * @param mixed|null $default
149
     *
150
     * @return mixed
151
     */
152
    public function getOption($option, $default = null)
153
    {
154
        return array_key_exists($option, $this->options) ? $this->options[$option] : $default;
155
    }
156
157
    /**
158
     * Verifies option existence.
159
     *
160
     * @param string $option
161
     *
162
     * @return bool
163
     */
164
    public function hasOption($option)
165
    {
166
        return array_key_exists($option, $this->options);
167
    }
168
169
    /**
170
     * Set builder options.
171
     *
172
     * @param array $options
173
     *
174
     * @return $this
175
     */
176
    public function setOptions(array $options)
177
    {
178
        foreach ($options as $option => $value) {
179
            $this->setOption($option, $value);
180
        }
181
182
        return $this;
183
    }
184
185
    /**
186
     * Set builder option.
187
     *
188
     * @param string $option
189
     * @param mixed  $value
190
     *
191
     * @return $this
192
     */
193
    public function setOption($option, $value)
194
    {
195
        $this->options[$option] = $value;
196
197
        return $this;
198
    }
199
200
    /**
201
     * Set up annotation metadata.
202
     *
203
     * @param bool $registerDefault
204
     *
205
     * @throws \InvalidArgumentException
206
     * @throws \RuntimeException
207
     */
208
    protected function setupAnnotationMetadata($registerDefault = false)
209
    {
210
        $annotationFiles = (array) $this->getOption('annotation_files');
211
        array_walk(
212
            $annotationFiles,
213
            function ($file) {
214
                if (!file_exists($file)) {
215
                    throw new \RuntimeException(sprintf('"%s" file does not exist', $file));
216
                }
217
218
                AnnotationRegistry::registerFile($file);
219
            }
220
        );
221
222
        AnnotationRegistry::registerAutoloadNamespaces($this->getAnnotationNamespaces());
223
224
        $annotationLoaders = (array) $this->getOption('annotation_autoloaders');
225
        array_walk(
226
            $annotationLoaders,
227
            function ($autoLoader) {
228
                AnnotationRegistry::registerLoader($autoLoader);
229
            }
230
        );
231
232
        if ($registerDefault === true) {
233
            AnnotationRegistry::registerLoader('class_exists');
234
        }
235
    }
236
237
    /**
238
     * Retrieve annotation namespaces.
239
     *
240
     * @return array
241
     */
242
    protected function getAnnotationNamespaces()
243
    {
244
        $namespaces = (array) $this->getOption('annotation_namespaces');
245
246
        return array_filter(
247
            $namespaces,
248
            function ($namespace) {
249
                return is_string($namespace);
250
            },
251
            ARRAY_FILTER_USE_KEY
252
        );
253
    }
254
255
    /**
256
     * Create metadata mapping driver.
257
     *
258
     * @throws \RuntimeException
259
     * @throws \UnexpectedValueException
260
     *
261
     * @return MappingDriverChain
262
     */
263
    public function getMetadataMappingDriver()
264
    {
265
        if (!$this->mappingDriver instanceof MappingDriverChain) {
266
            $metadataDriver = new MappingDriverChain;
267
268
            foreach ((array) $this->getOption('metadata_mapping') as $metadataMapping) {
269
                if (!is_array($metadataMapping)) {
270
                    $metadataMapping = ['driver' => $metadataMapping];
271
                }
272
273
                if (!array_key_exists('namespace', $metadataMapping) && $metadataDriver->getDefaultDriver() !== null) {
274
                    throw new \RuntimeException(
275
                        'Only one default metadata mapping driver allowed, a namespace must be defined'
276
                    );
277
                }
278
279
                $mappingDriver = $this->getMappingDriver($metadataMapping);
280
281
                if (array_key_exists('namespace', $metadataMapping)) {
282
                    $metadataDriver->addDriver($mappingDriver, $metadataMapping['namespace']);
283
                } else {
284
                    $metadataDriver->setDefaultDriver($mappingDriver);
285
                }
286
            }
287
288
            if ($metadataDriver->getDefaultDriver() === null && count($metadataDriver->getDrivers()) === 0) {
289
                throw new \RuntimeException('No metadata mapping defined');
290
            }
291
292
            $this->mappingDriver = $metadataDriver;
293
        }
294
295
        return $this->mappingDriver;
296
    }
297
298
    /**
299
     * Retrieve mapping driver.
300
     *
301
     * @param array $metadataMapping
302
     *
303
     * @throws \UnexpectedValueException
304
     *
305
     * @return MappingDriver
306
     */
307
    protected function getMappingDriver(array $metadataMapping)
308
    {
309
        if (array_key_exists('driver', $metadataMapping)) {
310
            $mappingDriver = $metadataMapping['driver'];
311
312
            if (!$mappingDriver instanceof MappingDriver) {
313
                throw new \UnexpectedValueException(
314
                    sprintf('Provided driver should be of the type MappingDriver, "%s" given', gettype($mappingDriver))
315
                );
316
            }
317
318
            return $mappingDriver;
319
        } elseif (array_key_exists('type', $metadataMapping) && array_key_exists('path', $metadataMapping)) {
320
            $metadataMapping = array_merge(['extension' => null], $metadataMapping);
321
322
            switch ($metadataMapping['type']) {
323
                case ManagerBuilder::METADATA_MAPPING_ANNOTATION:
324
                    return $this->getAnnotationMetadataDriver((array) $metadataMapping['path']);
325
326
                case ManagerBuilder::METADATA_MAPPING_XML:
327
                    return $this->getXmlMetadataDriver((array) $metadataMapping['path'], $metadataMapping['extension']);
328
329
                case ManagerBuilder::METADATA_MAPPING_YAML:
330
                    return $this->getYamlMetadataDriver((array) $metadataMapping['path'], $metadataMapping['extension']);
331
332
                case ManagerBuilder::METADATA_MAPPING_PHP:
333
                    return new PHPDriver((array) $metadataMapping['path']);
334
            }
335
336
            throw new \UnexpectedValueException(
337
                sprintf('"%s" is not a valid metadata mapping type', $metadataMapping['type'])
338
            );
339
        }
340
341
        throw new \UnexpectedValueException(
342
            'metadata_mapping must be array with "driver" key or "type" and "path" keys'
343
        );
344
    }
345
346
    /**
347
     * Get annotation metadata driver.
348
     *
349
     * @param array $paths
350
     *
351
     * @return MappingDriver
352
     */
353
    abstract protected function getAnnotationMetadataDriver(array $paths);
354
355
    /**
356
     * Get XML metadata driver.
357
     *
358
     * @param array       $paths
359
     * @param string|null $extension
360
     *
361
     * @return MappingDriver
362
     */
363
    abstract protected function getXmlMetadataDriver(array $paths, $extension = null);
364
365
    /**
366
     * Get YAML metadata driver.
367
     *
368
     * @param array       $paths
369
     * @param string|null $extension
370
     *
371
     * @return MappingDriver
372
     */
373
    abstract protected function getYamlMetadataDriver(array $paths, $extension = null);
374
375
    /**
376
     * Retrieve proxies path.
377
     *
378
     * @return string
379
     */
380
    protected function getProxiesPath()
381
    {
382
        return (string) $this->getOption('proxies_path', sys_get_temp_dir());
383
    }
384
385
    /**
386
     * Retrieve proxies namespace.
387
     *
388
     * @return null|string
389
     */
390
    protected function getProxiesNamespace()
391
    {
392
        $proxyNamespace = $this->getOption('proxies_namespace');
393
394
        return is_string($proxyNamespace) ? $proxyNamespace : null;
395
    }
396
397
    /**
398
     * Retrieve proxy generation strategy.
399
     *
400
     * @return int
401
     */
402
    protected function getProxiesAutoGeneration()
403
    {
404
        return (int) $this->getOption('proxies_auto_generation');
405
    }
406
407
    /**
408
     * Retrieve metadata cache driver.
409
     *
410
     * @throws \InvalidArgumentException
411
     *
412
     * @return Cache
413
     */
414
    public function getMetadataCacheDriver()
415
    {
416
        if (!$this->metadataCacheDriver instanceof Cache) {
417
            $metadataCacheDriver = $this->getOption('metadata_cache_driver');
418
419
            if (!$metadataCacheDriver instanceof Cache) {
420
                $metadataCacheDriver = $this->getCacheDriver();
421
                $metadataCacheDriver->setNamespace($this->getMetadataCacheNamespace());
422
            }
423
424
            if ($metadataCacheDriver->getNamespace() === '') {
425
                $metadataCacheDriver->setNamespace($this->getMetadataCacheNamespace());
426
            }
427
428
            $this->metadataCacheDriver = $metadataCacheDriver;
429
        }
430
431
        return $this->metadataCacheDriver;
432
    }
433
434
    /**
435
     * Set metadata cache driver.
436
     *
437
     * @param Cache $metadataCacheDriver
438
     */
439
    public function setMetadataCacheDriver(Cache $metadataCacheDriver)
440
    {
441
        $this->metadataCacheDriver = $metadataCacheDriver;
442
    }
443
444
    /**
445
     * Retrieve metadata cache namespace.
446
     *
447
     * @return string
448
     */
449
    protected function getMetadataCacheNamespace()
450
    {
451
        return (string) $this->getOption('metadata_cache_namespace', $this->getCacheDriverNamespace());
452
    }
453
454
    /**
455
     * Retrieve general cache driver.
456
     *
457
     * @throws \InvalidArgumentException
458
     *
459
     * @return CacheProvider
460
     */
461
    public function getCacheDriver()
462
    {
463
        if (!$this->cacheDriver instanceof Cache) {
464
            $cacheNamespace = $this->getCacheDriverNamespace();
465
            $cacheDriver = $this->getOption('cache_driver');
466
467
            if ($cacheDriver === null) {
468
                $cacheDriver = $this->createNewCacheDriver($cacheNamespace);
469
            }
470
471
            if (!$cacheDriver instanceof Cache) {
472
                throw new \InvalidArgumentException('Cache Driver provided is not valid');
473
            }
474
475
            if ($cacheDriver->getNamespace() === '') {
476
                $cacheDriver->setNamespace($cacheNamespace);
477
            }
478
479
            $this->cacheDriver = $cacheDriver;
480
        }
481
482
        return $this->cacheDriver;
483
    }
484
485
    /**
486
     * Retrieve a newly created cache driver.
487
     *
488
     * @param string $namespace
489
     *
490
     * @return ApcuCache|ArrayCache|MemcacheCache|RedisCache|XcacheCache
491
     */
492
    private function createNewCacheDriver($namespace)
493
    {
494
        // @codeCoverageIgnoreStart
495
        switch (true) {
496
            case extension_loaded('apc'):
497
                $cacheDriver = new ApcuCache;
498
                break;
499
500
            case extension_loaded('xcache'):
501
                $cacheDriver = new XcacheCache;
502
                break;
503
504
            case extension_loaded('memcache'):
505
                $memcache = new \Memcache;
506
                $memcache->connect('127.0.0.1');
507
508
                $cacheDriver = new MemcacheCache;
509
                $cacheDriver->setMemcache($memcache);
510
                break;
511
512
            case extension_loaded('redis'):
513
                $redis = new \Redis();
514
                $redis->connect('127.0.0.1');
515
516
                $cacheDriver = new RedisCache;
517
                $cacheDriver->setRedis($redis);
518
                break;
519
520
            default:
521
                $cacheDriver = new ArrayCache;
522
        }
523
        // @codeCoverageIgnoreEnd
524
525
        $cacheDriver->setNamespace($namespace);
526
527
        return $cacheDriver;
528
    }
529
530
    /**
531
     * Set general cache driver.
532
     *
533
     * @param Cache $cacheDriver
534
     */
535
    public function setCacheDriver(Cache $cacheDriver)
536
    {
537
        $this->cacheDriver = $cacheDriver;
538
    }
539
540
    /**
541
     * Retrieve general cache driver namespace.
542
     *
543
     * @return string
544
     */
545
    protected function getCacheDriverNamespace()
546
    {
547
        return (string) $this->getOption('cache_driver_namespace', 'dc2_' . sha1(sys_get_temp_dir()) . '_');
548
    }
549
550
    /**
551
     * Retrieve event manager.
552
     *
553
     * @return EventManager
554
     */
555
    public function getEventManager()
556
    {
557
        if (!$this->eventManager instanceof EventManager) {
558
            $eventManager = $this->getOption('event_manager');
559
560
            if (!$eventManager instanceof EventManager) {
561
                $eventManager = new EventManager;
562
            }
563
564
            $this->eventManager = $eventManager;
565
        }
566
567
        return $this->eventManager;
568
    }
569
570
    /**
571
     * Set event manager.
572
     *
573
     * @param EventManager $eventManager
574
     */
575
    public function setEventManager(EventManager $eventManager)
576
    {
577
        $this->eventManager = $eventManager;
578
    }
579
}
580