Completed
Push — master ( 4695ab...73566d )
by Julián
02:31
created

AbstractManagerBuilder::getPhpMetadataDriver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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