Completed
Push — master ( 7e6b75...39b5c8 )
by Julián
02:19
created

getDefaultRepositoryClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
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
    use OptionsTrait;
33
34
    /**
35
     * Manager builder's common default options.
36
     *
37
     * @var array
38
     */
39
    private $defaultOptions = [
40
        'proxies_auto_generation' => AbstractProxyFactory::AUTOGENERATE_NEVER,
41
    ];
42
43
    /**
44
     * Builder name.
45
     *
46
     * @var
47
     */
48
    protected $name;
49
50
    /**
51
     * Metadata mapping driver.
52
     *
53
     * @var MappingDriverChain
54
     */
55
    protected $mappingDriver;
56
57
    /**
58
     * General cache driver.
59
     *
60
     * @var CacheProvider
61
     */
62
    protected $cacheDriver;
63
64
    /**
65
     * Metadata cache driver.
66
     *
67
     * @var CacheProvider
68
     */
69
    protected $metadataCacheDriver;
70
71
    /**
72
     * Event manager.
73
     *
74
     * @var EventManager
75
     */
76
    protected $eventManager;
77
78
    /**
79
     * ManagerBuilder constructor.
80
     *
81
     * @param array       $options
82
     * @param string|null $name
83
     */
84
    public function __construct(array $options = [], $name = null)
85
    {
86
        $this->setOptions(array_merge($this->defaultOptions, $this->getDefaultOptions(), $options));
87
        $this->setName($name);
88
    }
89
90
    /**
91
     * Get manager builder's default options.
92
     *
93
     * @return array
94
     */
95
    abstract protected function getDefaultOptions();
96
97
    /**
98
     * Unset created objects for rebuild.
99
     */
100
    protected function wipe()
101
    {
102
        $this->mappingDriver = null;
103
        $this->cacheDriver = null;
104
        $this->metadataCacheDriver = null;
105
        $this->eventManager = null;
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     *
111
     * @return string|null
112
     */
113
    public function getName()
114
    {
115
        return $this->name;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     *
121
     * @return $this
122
     */
123
    public function setName($name = null)
124
    {
125
        $this->name = $name;
126
127
        return $this;
128
    }
129
130
    /**
131
     * Set up annotation metadata.
132
     *
133
     * @throws \InvalidArgumentException
134
     * @throws \RuntimeException
135
     */
136
    protected function setupAnnotationMetadata()
137
    {
138
        $annotationFiles = (array) $this->getOption('annotation_files');
139
        array_walk(
140
            $annotationFiles,
141
            function ($file) {
142
                if (!file_exists($file)) {
143
                    throw new \RuntimeException(sprintf('"%s" file does not exist', $file));
144
                }
145
146
                AnnotationRegistry::registerFile($file);
147
            }
148
        );
149
150
        AnnotationRegistry::registerAutoloadNamespaces($this->getAnnotationNamespaces());
151
152
        $annotationLoaders = (array) $this->getOption('annotation_autoloaders');
153
        array_walk(
154
            $annotationLoaders,
155
            function ($autoLoader) {
156
                AnnotationRegistry::registerLoader($autoLoader);
157
            }
158
        );
159
    }
160
161
    /**
162
     * Retrieve annotation namespaces.
163
     *
164
     * @return array
165
     */
166
    protected function getAnnotationNamespaces()
167
    {
168
        $namespaces = (array) $this->getOption('annotation_namespaces');
169
170
        return array_filter(
171
            $namespaces,
172
            function ($namespace) {
173
                return is_string($namespace);
174
            },
175
            ARRAY_FILTER_USE_KEY
176
        );
177
    }
178
179
    /**
180
     * {@inheritdoc}
181
     *
182
     * @throws \RuntimeException
183
     * @throws \UnexpectedValueException
184
     */
185
    public function getMetadataMappingDriver()
186
    {
187
        if (!$this->mappingDriver instanceof MappingDriverChain) {
188
            $metadataDriverChain = new MappingDriverChain;
189
190
            $this->parseMetadataMapping($metadataDriverChain);
191
192
            if ($metadataDriverChain->getDefaultDriver() === null && count($metadataDriverChain->getDrivers()) === 0) {
193
                throw new \RuntimeException('No metadata mapping defined');
194
            }
195
196
            $this->mappingDriver = $metadataDriverChain;
197
        }
198
199
        return $this->mappingDriver;
200
    }
201
202
    /**
203
     * Parse metadata mapping configuration.
204
     *
205
     * @param MappingDriverChain $metadataDriverChain
206
     *
207
     * @throws \RuntimeException
208
     */
209
    protected function parseMetadataMapping(MappingDriverChain $metadataDriverChain)
210
    {
211
        foreach ((array) $this->getOption('metadata_mapping') as $metadataMapping) {
212
            if (!is_array($metadataMapping)) {
213
                $metadataMapping = ['driver' => $metadataMapping];
214
            }
215
216
            if (!array_key_exists('namespace', $metadataMapping) && $metadataDriverChain->getDefaultDriver() !== null) {
217
                throw new \RuntimeException(
218
                    'Only one default metadata mapping driver allowed, a namespace must be defined'
219
                );
220
            }
221
222
            $mappingDriver = $this->getMappingDriver($metadataMapping);
223
224
            if (array_key_exists('namespace', $metadataMapping)) {
225
                $metadataDriverChain->addDriver($mappingDriver, $metadataMapping['namespace']);
226
            } else {
227
                $metadataDriverChain->setDefaultDriver($mappingDriver);
228
            }
229
        }
230
    }
231
232
    /**
233
     * Retrieve mapping driver.
234
     *
235
     * @param array $metadataMapping
236
     *
237
     * @throws \UnexpectedValueException
238
     *
239
     * @return MappingDriver
240
     */
241
    protected function getMappingDriver(array $metadataMapping)
242
    {
243
        if (array_key_exists('driver', $metadataMapping)) {
244
            $mappingDriver = $metadataMapping['driver'];
245
246
            if (!$mappingDriver instanceof MappingDriver) {
247
                throw new \UnexpectedValueException(
248
                    sprintf('Provided driver should be of the type MappingDriver, "%s" given', gettype($mappingDriver))
249
                );
250
            }
251
252
            return $mappingDriver;
253
        }
254
255
        if (count(array_intersect(['type', 'path'], array_keys($metadataMapping))) === 2) {
256
            $metadataMapping = array_merge(['extension' => null], $metadataMapping);
257
258
            return $this->getMappingDriverImplementation(
259
                $metadataMapping['type'],
260
                (array) $metadataMapping['path'],
0 ignored issues
show
Documentation introduced by
(array) $metadataMapping['path'] is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
261
                $metadataMapping['extension']
262
            );
263
        }
264
265
        throw new \UnexpectedValueException(
266
            'metadata_mapping must be array with "driver" key or "type" and "path" keys'
267
        );
268
    }
269
270
    /**
271
     * Get metadata mapping driver implementation.
272
     *
273
     * @param string $type
274
     * @param string $paths
275
     * @param string $extension
276
     *
277
     * @throws \UnexpectedValueException
278
     *
279
     * @return MappingDriver|PHPDriver
280
     */
281
    protected function getMappingDriverImplementation($type, $paths, $extension)
282
    {
283
        switch ($type) {
284
            case ManagerBuilder::METADATA_MAPPING_ANNOTATION:
285
                return $this->getAnnotationMappingDriver($paths);
0 ignored issues
show
Documentation introduced by
$paths is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
286
287
            case ManagerBuilder::METADATA_MAPPING_XML:
288
                return $this->getXmlMappingDriver($paths, $extension);
0 ignored issues
show
Documentation introduced by
$paths is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
289
290
            case ManagerBuilder::METADATA_MAPPING_YAML:
291
                return $this->getYamlMappingDriver($paths, $extension);
0 ignored issues
show
Documentation introduced by
$paths is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
292
293
            case ManagerBuilder::METADATA_MAPPING_PHP:
294
                return $this->getPhpMappingDriver($paths);
0 ignored issues
show
Documentation introduced by
$paths is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
295
        }
296
297
        throw new \UnexpectedValueException(
298
            sprintf('"%s" is not a valid metadata mapping type', $type)
299
        );
300
    }
301
302
    /**
303
     * Get annotation metadata driver.
304
     *
305
     * @param array $paths
306
     *
307
     * @return MappingDriver
308
     */
309
    abstract protected function getAnnotationMappingDriver(array $paths);
310
311
    /**
312
     * Get XML metadata driver.
313
     *
314
     * @param array       $paths
315
     * @param string|null $extension
316
     *
317
     * @return MappingDriver
318
     */
319
    abstract protected function getXmlMappingDriver(array $paths, $extension = null);
320
321
    /**
322
     * Get YAML metadata driver.
323
     *
324
     * @param array       $paths
325
     * @param string|null $extension
326
     *
327
     * @return MappingDriver
328
     */
329
    abstract protected function getYamlMappingDriver(array $paths, $extension = null);
330
331
    /**
332
     * {@inheritdoc}
333
     *
334
     * @return $this
335
     */
336
    public function setMetadataMappingDriver(MappingDriverChain $mappingDriver)
337
    {
338
        $this->mappingDriver = $mappingDriver;
339
340
        return $this;
341
    }
342
343
    /**
344
     * Get PHP metadata driver.
345
     *
346
     * @param array $paths
347
     *
348
     * @return PHPDriver
349
     */
350
    protected function getPhpMappingDriver(array $paths)
351
    {
352
        return new PHPDriver($paths);
353
    }
354
355
    /**
356
     * Get custom repository factory.
357
     */
358
    abstract protected function getRepositoryFactory();
359
360
    /**
361
     * Get default repository class name.
362
     *
363
     * @return string|null
364
     */
365
    protected function getDefaultRepositoryClass()
366
    {
367
        return array_key_exists('default_repository_class', $this->options)
368
            ? (string) $this->options['default_repository_class']
369
            : null;
370
    }
371
372
    /**
373
     * Retrieve proxies path.
374
     *
375
     * @return string
376
     */
377
    protected function getProxiesPath()
378
    {
379
        return (string) $this->getOption('proxies_path', sys_get_temp_dir());
380
    }
381
382
    /**
383
     * Retrieve proxies namespace.
384
     *
385
     * @return null|string
386
     */
387
    protected function getProxiesNamespace()
388
    {
389
        $proxyNamespace = $this->getOption('proxies_namespace');
390
391
        return is_string($proxyNamespace) ? $proxyNamespace : null;
392
    }
393
394
    /**
395
     * Retrieve proxy generation strategy.
396
     *
397
     * @return int
398
     */
399
    protected function getProxiesAutoGeneration()
400
    {
401
        return (int) $this->getOption('proxies_auto_generation');
402
    }
403
404
    /**
405
     * {@inheritdoc}
406
     *
407
     * @throws \InvalidArgumentException
408
     */
409
    public function getMetadataCacheDriver()
410
    {
411
        if (!$this->metadataCacheDriver instanceof CacheProvider) {
412
            $metadataCacheDriver = $this->getOption('metadata_cache_driver');
413
414
            if (!$metadataCacheDriver instanceof CacheProvider) {
415
                $metadataCacheDriver = $this->createNewCacheDriver();
416
            }
417
418
            if ($metadataCacheDriver->getNamespace() === '') {
419
                $metadataCacheDriver->setNamespace((string) $this->getOption('metadata_cache_namespace'));
420
            }
421
422
            $this->metadataCacheDriver = $metadataCacheDriver;
423
        }
424
425
        return $this->metadataCacheDriver;
426
    }
427
428
    /**
429
     * Retrieve a newly created cache driver.
430
     *
431
     * @return ApcuCache|ArrayCache|MemcacheCache|RedisCache|XcacheCache
432
     */
433
    private function createNewCacheDriver()
434
    {
435
        switch (true) {
436
            // @codeCoverageIgnoreStart
437
            case extension_loaded('apc'):
438
                $cacheDriver = new ApcuCache;
439
                break;
440
441
            case extension_loaded('xcache'):
442
                $cacheDriver = new XcacheCache;
443
                break;
444
445
            case extension_loaded('memcache'):
446
                $memcache = new \Memcache;
447
                $memcache->connect('127.0.0.1');
448
449
                $cacheDriver = new MemcacheCache;
450
                $cacheDriver->setMemcache($memcache);
451
                break;
452
453
            case extension_loaded('redis'):
454
                $redis = new \Redis();
455
                $redis->connect('127.0.0.1');
456
457
                $cacheDriver = new RedisCache;
458
                $cacheDriver->setRedis($redis);
459
                break;
460
            // @codeCoverageIgnoreEnd
461
462
            default:
463
                $cacheDriver = new ArrayCache;
464
        }
465
466
        return $cacheDriver;
467
    }
468
469
    /**
470
     * {@inheritdoc}
471
     *
472
     * @return $this
473
     */
474
    public function setMetadataCacheDriver(CacheProvider $metadataCacheDriver)
475
    {
476
        $this->metadataCacheDriver = $metadataCacheDriver;
477
478
        return $this;
479
    }
480
481
    /**
482
     * {@inheritdoc}
483
     */
484
    public function getEventManager()
485
    {
486
        if (!$this->eventManager instanceof EventManager) {
487
            $eventManager = $this->getOption('event_manager');
488
489
            if (!$eventManager instanceof EventManager) {
490
                $eventManager = new EventManager;
491
            }
492
493
            $this->eventManager = $eventManager;
494
        }
495
496
        return $this->eventManager;
497
    }
498
499
    /**
500
     * {@inheritdoc}
501
     *
502
     * @return $this
503
     */
504
    public function setEventManager(EventManager $eventManager)
505
    {
506
        $this->eventManager = $eventManager;
507
508
        return $this;
509
    }
510
511
    /**
512
     * Get event subscribers.
513
     *
514
     * @return array|null
515
     */
516
    protected function getEventSubscribers()
517
    {
518
        $eventSubscribers = $this->getOption('event_subscribers');
519
520
        if (is_null($eventSubscribers) || !is_array($eventSubscribers)) {
521
            return;
522
        }
523
524
        return array_filter(
525
            $eventSubscribers,
526
            function ($name) {
527
                return is_string($name);
528
            },
529
            ARRAY_FILTER_USE_KEY
530
        );
531
    }
532
}
533