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

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