Completed
Pull Request — develop (#683)
by Tom
01:23
created

DriverFactory::createService()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DoctrineModule\Service;
6
7
use Doctrine\Common\Annotations;
8
use Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator;
9
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
10
use Doctrine\Common\Persistence\Mapping\Driver\FileLocator;
11
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
12
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
13
use DoctrineModule\Options\Driver as DriverOptions;
14
use Interop\Container\ContainerInterface;
15
use InvalidArgumentException;
16
use Laminas\ServiceManager\ServiceLocatorInterface;
17
use function assert;
18
use function class_exists;
19
use function get_class;
20
use function is_array;
21
use function is_subclass_of;
22
use function sprintf;
23
24
/**
25
 * MappingDriver ServiceManager factory
26
 *
27
 * @link    http://www.doctrine-project.org/
28
 */
29
class DriverFactory extends AbstractFactory
30
{
31
    /**
32
     * {@inheritDoc}
33
     *
34
     * @return MappingDriver
35
     */
36 2
    public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
37
    {
38 2
        $options = $this->getOptions($container, 'driver');
39 2
        assert($options instanceof DriverOptions);
40
41 2
        return $this->createDriver($container, $options);
42
    }
43
44
    /**
45
     * {@inheritDoc}
46
     *
47
     * @return MappingDriver
48
     */
49 2
    public function createService(ServiceLocatorInterface $container)
50
    {
51 2
        return $this($container, MappingDriver::class);
52
    }
53
54 2
    public function getOptionsClass() : string
55
    {
56 2
        return 'DoctrineModule\Options\Driver';
57
    }
58
59
    /**
60
     * @throws InvalidArgumentException
61
     */
62 2
    protected function createDriver(ContainerInterface $container, DriverOptions $options) : MappingDriver
63
    {
64 2
        $class = $options->getClass();
65
66 2
        if (! $class) {
67
            throw new InvalidArgumentException('Drivers must specify a class');
68
        }
69
70 2
        if (! class_exists($class)) {
71
            throw new InvalidArgumentException(sprintf('Driver with type "%s" could not be found', $class));
72
        }
73
74
        // Not all drivers (DriverChain) require paths.
75 2
        $paths = $options->getPaths();
76
77
        // Special options for AnnotationDrivers.
78 2
        if ($class === 'Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver'
79 2
            || is_subclass_of($class, 'Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver')
80
        ) {
81
            $reader = new Annotations\AnnotationReader();
82
            $reader = new Annotations\CachedReader(
83
                new Annotations\IndexedReader($reader),
84
                $container->get($options->getCache())
85
            );
86
            $driver = new $class($reader, $paths);
87
            assert($driver instanceof MappingDriver);
88
        } else {
89 2
            $driver = new $class($paths);
90 2
            assert($driver instanceof MappingDriver);
91
        }
92
93 2
        if ($options->getExtension() && $driver instanceof FileDriver) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $options->getExtension() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
94
            $locator = $driver->getLocator();
95
            assert($locator instanceof FileLocator);
96
97
            if (get_class($locator) !== 'Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator') {
98
                throw new InvalidArgumentException(
99
                    sprintf(
100
                        'Discovered file locator for driver of type "%s" is an instance of "%s". This factory '
101
                        . 'supports only the DefaultFileLocator when an extension is set for the file locator',
102
                        get_class($driver),
103
                        get_class($locator)
104
                    )
105
                );
106
            }
107
108
            $driver->setLocator(new DefaultFileLocator($locator->getPaths(), $options->getExtension()));
109
        }
110
111
        // Extra post-create options for DriverChain.
112 2
        if ($driver instanceof MappingDriverChain && $options->getDrivers()) {
113 1
            $drivers = $options->getDrivers();
114
115 1
            if (! is_array($drivers)) {
116
                $drivers = [$drivers];
117
            }
118
119 1
            foreach ($drivers as $namespace => $driverName) {
120 1
                if ($driverName === null) {
121 1
                    continue;
122
                }
123
124 1
                $options = $this->getOptions($container, 'driver', $driverName);
125 1
                $driver->addDriver($this->createDriver($container, $options), $namespace);
0 ignored issues
show
Compatibility introduced by
$options of type object<Laminas\Stdlib\AbstractOptions> is not a sub-type of object<DoctrineModule\Options\Driver>. It seems like you assume a child class of the class Laminas\Stdlib\AbstractOptions to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
126
            }
127
        }
128
129 2
        return $driver;
130
    }
131
}
132