AnnotationDriverFactory   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 41
dl 0
loc 100
rs 10
c 1
b 0
f 0
wmc 14

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getReader() 0 18 4
A getCache() 0 28 5
A __invoke() 0 30 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\LaminasDoctrine\Factory\Mapping\Driver;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\Common\Annotations\IndexedReader;
9
use Doctrine\Common\Annotations\PsrCachedReader;
10
use Doctrine\Common\Annotations\Reader;
11
use Doctrine\Common\Cache\Cache;
12
use Doctrine\Common\Cache\Psr6\DoctrineProvider;
13
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
14
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
15
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
16
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
17
use Laminas\ServiceManager\ServiceLocatorInterface;
18
use Psr\Cache\CacheItemPoolInterface;
19
use Psr\Container\ContainerExceptionInterface;
20
use Psr\Container\ContainerInterface;
21
use Psr\Container\NotFoundExceptionInterface;
22
23
final class AnnotationDriverFactory extends AbstractDriverFactory
24
{
25
    /**
26
     * @param array<string, mixed>|null $options
27
     *
28
     * @throws ServiceNotCreatedException
29
     * @throws ServiceNotFoundException
30
     * @throws ContainerExceptionInterface
31
     * @throws NotFoundExceptionInterface
32
     */
33
    public function __invoke(ContainerInterface $container, string $requestedName, array $options = null): MappingDriver
34
    {
35
        $options = $options ?? $this->getOptions($container, $requestedName, $options);
36
37
        $className = $options['class'] ?? null;
38
        if (empty($className)) {
39
            throw new ServiceNotCreatedException(
40
                sprintf('The required \'class\' configuration option is missing for service \'%s\'', $requestedName)
41
            );
42
        }
43
44
        if (!is_a($className, MappingDriver::class, true)) {
45
            throw new ServiceNotCreatedException(
46
                sprintf(
47
                    'The driver configuration option must resolve to a class of type \'%s\'',
48
                    MappingDriver::class
49
                )
50
            );
51
        }
52
53
        $options['reader'] ??= AnnotationReader::class;
54
55
        $reader = $this->getReader($container, $options['reader'], $requestedName);
56
57
        if (!empty($options['cache']) && $container instanceof ServiceLocatorInterface) {
58
            $cache = $this->getCache($container, $options['cache'], $requestedName);
59
            $reader = new PsrCachedReader(new IndexedReader($reader), $cache);
60
        }
61
62
        return new AnnotationDriver($reader, $options['paths'] ?? []);
63
    }
64
65
    /**
66
     * @throws ServiceNotCreatedException
67
     * @throws ServiceNotFoundException
68
     * @throws ContainerExceptionInterface
69
     */
70
    private function getReader(ContainerInterface $container, string|Reader $reader, string $serviceName): Reader
71
    {
72
        if (is_string($reader)) {
73
            $reader = $this->getService($container, $reader, $serviceName);
74
        }
75
76
        if (!$reader instanceof Reader) {
77
            throw new ServiceNotCreatedException(
78
                sprintf(
79
                    'The reader must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
80
                    Reader::class,
81
                    is_object($reader) ? get_class($reader) : gettype($reader),
82
                    $serviceName
83
                )
84
            );
85
        }
86
87
        return $reader;
88
    }
89
90
    /**
91
     * @throws ContainerExceptionInterface
92
     * @throws ServiceNotFoundException
93
     * @throws ServiceNotCreatedException
94
     */
95
    private function getCache(
96
        ServiceLocatorInterface $container,
97
        string|CacheItemPoolInterface $cache,
98
        string $serviceName
99
    ): CacheItemPoolInterface {
100
        if (is_string($cache)) {
101
            if ($container->has($cache)) {
102
                $cache = $container->get($cache);
103
            } else {
104
                /** @var DoctrineProvider $provider */
105
                $provider = $this->buildService($container, Cache::class, ['name' => $cache], $serviceName);
106
107
                $cache = $provider->getPool();
108
            }
109
        }
110
111
        if (!$cache instanceof CacheItemPoolInterface) {
112
            throw new ServiceNotCreatedException(
113
                sprintf(
114
                    'The cache must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
115
                    CacheItemPoolInterface::class,
116
                    is_object($cache) ? get_class($cache) : gettype($cache),
117
                    $serviceName,
118
                )
119
            );
120
        }
121
122
        return $cache;
123
    }
124
}
125