Completed
Push — master ( 63cb48...b7ca1d )
by Julián
02:17
created

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