DoctrineOrmFactory::create()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 7
dl 0
loc 28
ccs 12
cts 12
cp 1
crap 1
rs 8.8571
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace Simplex\Quickstart\Shared\Factory;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Cache\ArrayCache;
7
use Doctrine\Common\Cache\FilesystemCache;
8
use Doctrine\Common\EventManager;
9
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
10
use Doctrine\DBAL\Types\Type;
11
use Doctrine\ORM\Configuration;
12
use Doctrine\ORM\EntityManager;
13
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
14
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
15
use Gedmo\DoctrineExtensions as GedmoExtensions;
16
use Gedmo\Timestampable\TimestampableListener;
17
use Ramsey\Uuid\Doctrine\UuidType;
18
use Simplex\Quickstart\Shared\Doctrine\Type\DateTimeMicroType;
19
use Symfony\Component\Finder\Finder;
20
21
/**
22
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
23
 */
24
final class DoctrineOrmFactory
25
{
26
    private const DOCTRINE_CACHE_DIRECTORY = 'doctrine';
27
28
    private const PROXY_DIRECTORY = self::DOCTRINE_CACHE_DIRECTORY . DIRECTORY_SEPARATOR . 'proxy';
29
30
    private const PROXY_NAMESPACE = 'DoctrineProxies';
31
32
    private const MODULES_DIRECTORY_PATH = __DIR__ . '/../../Module';
33
34
    private const ENTITY_DIRECTORY_NAME = 'Model';
35
36
    /**
37
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
38
     */
39 1
    public function create(
40
        string $host,
41
        string $port,
42
        string $name,
43
        string $user,
44
        string $pass,
45
        \SplFileInfo $cacheDir,
46
        bool $enableCache
47
    ): EntityManager {
48
49
        $connectionOptions = [
50 1
            'driver' => 'pdo_mysql',
51 1
            'host' => $host,
52 1
            'port' => $port,
53 1
            'dbname' => $name,
54 1
            'user' => $user,
55 1
            'password' => $pass,
56
        ];
57
58 1
        $annotationReader = new AnnotationReader();
59
60 1
        $config = $this->buildConfig($cacheDir, $enableCache, $annotationReader);
61
62 1
        $this->addCustomTypes();
63
64 1
        $entityManager = $this->buildEntityManager($annotationReader, $connectionOptions, $config);
65
66 1
        return $entityManager;
67
    }
68
69 1
    private function buildConfig(
70
        \SplFileInfo $cacheDir,
71
        bool $enableCache,
72
        AnnotationReader $annotationReader
73
    ): Configuration {
74
75 1
        $config = new Configuration;
76
77 1
        $this->configureMetadataDrivers($annotationReader, $config);
78
79 1
        $this->configureCache($cacheDir, $enableCache, $config);
80
81 1
        $this->configureNamingStrategy($config);
82
83 1
        return $config;
84
    }
85
86 1
    private function configureMetadataDrivers(AnnotationReader $annotationReader, Configuration $config): void
87
    {
88 1
        $driverChain = new MappingDriverChain();
89
90 1
        $defaultDriver = new AnnotationDriver($annotationReader, $this->getEntityDirPaths());
91
92 1
        $driverChain->setDefaultDriver($defaultDriver);
93 1
        $config->setMetadataDriverImpl($driverChain);
94
95 1
        GedmoExtensions::registerAbstractMappingIntoDriverChainORM(
96 1
            $driverChain,
97 1
            $annotationReader
98
        );
99 1
    }
100
101 1
    private function getEntityDirPaths(): array
102
    {
103 1
        $finder = new Finder();
104 1
        $finder->directories()->depth(0)->in(self::MODULES_DIRECTORY_PATH);
105
106 1
        $paths = [];
107 1
        foreach ($finder as $dir) {
108 1
            $modelDir = $dir->getPathname() . DIRECTORY_SEPARATOR . self::ENTITY_DIRECTORY_NAME;
109 1
            if (is_readable($modelDir)) {
110 1
                $paths[] = $modelDir;
111
            }
112
        }
113
114 1
        return $paths;
115
    }
116
117
    /**
118
     * @SuppressWarnings(PHPMD.ElseExpression)
119
     */
120 1
    private function configureCache(\SplFileInfo $cacheDir, bool $enableCache, Configuration $config): void
121
    {
122 1
        if (!$enableCache) {
123 1
            $cache = new ArrayCache();
124
        } else {
125
            $cache = new FilesystemCache(
126
                $cacheDir->getPathname() . DIRECTORY_SEPARATOR . self::DOCTRINE_CACHE_DIRECTORY
127
            );
128
        }
129
130 1
        $config->setMetadataCacheImpl($cache);
131 1
        $config->setQueryCacheImpl($cache);
132 1
        $config->setProxyDir($cacheDir->getPathname() . DIRECTORY_SEPARATOR . self::PROXY_DIRECTORY);
133 1
        $config->setProxyNamespace(self::PROXY_NAMESPACE);
134
135 1
        if ($enableCache) {
136
            $config->setAutoGenerateProxyClasses(true);
137
        } else {
138 1
            $config->setAutoGenerateProxyClasses(false);
139
        }
140 1
    }
141
142 1
    private function configureNamingStrategy(Configuration $config): void
143
    {
144 1
        $namingStrategy = new UnderscoreNamingStrategy(CASE_LOWER);
145 1
        $config->setNamingStrategy($namingStrategy);
146 1
    }
147
148 1
    private function addCustomTypes(): void
149
    {
150 1
        Type::addType(UuidType::NAME, UuidType::class);
151 1
        Type::addType(DateTimeMicroType::NAME, DateTimeMicroType::class);
152 1
    }
153
154 1
    private function buildEntityManager(
155
        AnnotationReader $annotationReader,
156
        array $connectionOptions,
157
        Configuration$config
158
    ): EntityManager {
159
160 1
        $eventManager = $this->buildEventManager($annotationReader);
161
162 1
        $entityManager = EntityManager::create($connectionOptions, $config, $eventManager);
163
164 1
        return $entityManager;
165
    }
166
167 1
    private function buildEventManager(AnnotationReader $annotationReader): EventManager
168
    {
169 1
        $eventManager = new EventManager();
170
171 1
        $this->addEventListeners($annotationReader, $eventManager);
172
173 1
        return $eventManager;
174
    }
175
176 1
    private function addEventListeners(AnnotationReader $annotationReader, EventManager $eventManager): void
177
    {
178 1
        $timestampableListener = new TimestampableListener();
179 1
        $timestampableListener->setAnnotationReader($annotationReader);
180
181 1
        $eventManager->addEventSubscriber($timestampableListener);
182 1
    }
183
}
184