Completed
Push — master ( f29a75...c4e6f7 )
by Julián
02:15
created

EntityManagerBuilder::setupMetadataDriver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
/**
3
 * Slim3 Doctrine integration (https://github.com/juliangut/slim-doctrine)
4
 *
5
 * @link https://github.com/juliangut/slim-doctrine for the canonical source repository
6
 *
7
 * @license https://raw.githubusercontent.com/juliangut/slim-doctrine/master/LICENSE
8
 */
9
10
namespace Jgut\Slim\Doctrine;
11
12
use Doctrine\Common\Annotations\AnnotationReader;
13
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
14
use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver;
15
use Doctrine\Common\Proxy\AbstractProxyFactory;
16
use Doctrine\DBAL\Connection;
17
use Doctrine\DBAL\Types\Type;
18
use Doctrine\ORM\Configuration;
19
use Doctrine\ORM\EntityManager;
20
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
21
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
22
use Doctrine\ORM\Mapping\NamingStrategy;
23
use Doctrine\ORM\Mapping\QuoteStrategy;
24
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
25
use Doctrine\ORM\Mapping\Driver\XmlDriver;
26
use Doctrine\ORM\Mapping\Driver\YamlDriver;
27
28
/**
29
 * Doctrine Entity Manager service builder
30
 */
31
class EntityManagerBuilder
32
{
33
    use ObjectManagerTrait;
34
35
    /**
36
     * Default configuration options.
37
     *
38
     * @var array
39
     */
40
    protected static $defaultOptions = [
41
        'connection' => null,
42
        'cache_driver' => null,
43
        'cache_namespace' => null,
44
        'annotation_files' => [],
45
        'annotation_namespaces' => [],
46
        'annotation_autoloaders' => [],
47
        'annotation_paths' => null,
48
        'xml_paths' => null,
49
        'yaml_paths' => null,
50
        'php_paths' => null,
51
        'naming_strategy' => null,
52
        'quote_strategy' => null,
53
        'proxy_path' => null,
54
        'proxies_namespace' => 'DoctrineORMProxy',
55
        'auto_generate_proxies' => AbstractProxyFactory::AUTOGENERATE_NEVER,
56
        'sql_logger' => null,
57
        'event_manager' => null,
58
        'custom_types' => [],
59
        'string_functions' => [],
60
        'numeric_functions' => [],
61
        'datetime_functions' => [],
62
    ];
63
64
    /**
65
     * Create a Doctrine entity manager.
66
     *
67
     * @param array $options
68
     *
69
     * @throws \Doctrine\DBAL\DBALException
70
     * @throws \Doctrine\ORM\ORMException
71
     * @throws \InvalidArgumentException
72
     * @throws \RuntimeException
73
     *
74
     * @return \Doctrine\ORM\EntityManager
75
     */
76
    public static function build(array $options)
77
    {
78
        $options = array_merge(static::$defaultOptions, $options);
79
80
        static::setupAnnotationMetadata($options);
81
82
        $config = static::getConfiguration($options);
83
        static::setupMetadataDriver($config, $options);
84
        static::setupNamingStrategy($config, $options);
85
        static::setupQuoteStrategy($config, $options);
86
        static::setupProxy($config, $options);
87
        static::setupSQLLogger($config, $options);
88
        static::setupCustomDQLFunctions($config, $options);
89
90
        $entityManager = EntityManager::create(
91
            $options['connection'],
92
            $config,
93
            $options['event_manager']
94
        );
95
96
        $connection = $entityManager->getConnection();
97
        static::setupCustomDBALTypes($connection, $options);
98
99
        return $entityManager;
100
    }
101
102
    /**
103
     * Create Doctrine ORM bare configuration.
104
     *
105
     * @param array $options
106
     *
107
     * @throws \InvalidArgumentException
108
     *
109
     * @return \Doctrine\ORM\Configuration
110
     */
111
    protected static function getConfiguration(array $options)
112
    {
113
        $cacheDriver = static::getCacheDriver(
114
            $options['cache_driver'],
115
            $options['cache_namespace'] ?: 'orm_dc2_' . sha1($options['proxy_path'] ?: sys_get_temp_dir()) . '_'
116
        );
117
118
        $config = new Configuration();
119
        $config->setMetadataCacheImpl($cacheDriver);
120
        $config->setQueryCacheImpl($cacheDriver);
121
        $config->setResultCacheImpl($cacheDriver);
122
123
        return $config;
124
    }
125
126
    /**
127
     * Create Doctrine ODM configuration.
128
     *
129
     * @param \Doctrine\ORM\Configuration $config
130
     * @param array                       $options
131
     *
132
     * @throws \RuntimeException
133
     */
134
    protected static function setupMetadataDriver(Configuration $config, array $options)
135
    {
136
        $metadataDriver = new MappingDriverChain;
137
        $metadataDriver->setDefaultDriver(self::getMetadataDriver($config, $options));
138
139
        $config->setMetadataDriverImpl($metadataDriver);
140
    }
141
142
    /**
143
     * @param \Doctrine\ORM\Configuration $config
144
     * @param array                       $options
145
     *
146
     * @throws \RuntimeException
147
     *
148
     * @return \Doctrine\Common\Persistence\Mapping\Driver\MappingDriver
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use AnnotationDriver|XmlDriv...lDriver|StaticPHPDriver.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
149
     */
150
    protected static function getMetadataDriver(Configuration $config, array $options)
151
    {
152
        if ($options['annotation_paths']) {
153
            // Only to register ORM annotations mapping
154
            $config->newDefaultAnnotationDriver();
155
156
            return new AnnotationDriver(new AnnotationReader, (array) $options['annotation_paths']);
157
        }
158
159
        if ($options['xml_paths']) {
160
            return new XmlDriver((array) $options['xml_paths'], '.xml');
161
        }
162
163
        if ($options['yaml_paths']) {
164
            return new YamlDriver((array) $options['yaml_paths'], '.yml');
165
        }
166
167
        if ($options['php_paths']) {
168
            return new StaticPHPDriver((array) $options['php_paths']);
169
        }
170
171
        throw new \RuntimeException('No Metadata paths defined');
172
    }
173
174
    /**
175
     * Setup naming strategy.
176
     *
177
     * @param \Doctrine\ORM\Configuration $config
178
     * @param array                       $options
179
     *
180
     * @throws \InvalidArgumentException
181
     */
182
    protected static function setupNamingStrategy(Configuration $config, array $options)
183
    {
184
        $namingStrategy = $options['naming_strategy'] ?: new UnderscoreNamingStrategy(CASE_LOWER);
185
        if (!$namingStrategy instanceof NamingStrategy) {
186
            throw new \InvalidArgumentException('Naming strategy provided is not valid');
187
        }
188
189
        $config->setNamingStrategy($namingStrategy);
190
    }
191
192
    /**
193
     * Setup quote strategy.
194
     *
195
     * @param \Doctrine\ORM\Configuration $config
196
     * @param array                       $options
197
     *
198
     * @throws \InvalidArgumentException
199
     */
200
    protected static function setupQuoteStrategy(Configuration $config, array $options)
201
    {
202
        $quoteStrategy = $options['quote_strategy'] ?: new DefaultQuoteStrategy();
203
        if (!$quoteStrategy instanceof QuoteStrategy) {
204
            throw new \InvalidArgumentException('Quote strategy provided is not valid');
205
        }
206
207
        $config->setQuoteStrategy($quoteStrategy);
208
    }
209
210
    /**
211
     * Setup SQL logger.
212
     *
213
     * @param \Doctrine\ORM\Configuration $config
214
     * @param array                       $options
215
     */
216
    protected static function setupSQLLogger(Configuration $config, array $options)
217
    {
218
        if ($options['sql_logger']) {
219
            $config->setSQLLogger($options['sql_logger']);
220
        }
221
    }
222
223
    /**
224
     * Setup custom DQL functions.
225
     *
226
     * @param \Doctrine\ORM\Configuration $config
227
     * @param array                       $options
228
     */
229
    protected static function setupCustomDQLFunctions(Configuration $config, array $options)
230
    {
231
        $config->setCustomStringFunctions($options['string_functions']);
232
233
        $config->setCustomNumericFunctions($options['numeric_functions']);
234
235
        $config->setCustomDatetimeFunctions($options['datetime_functions']);
236
    }
237
238
    /**
239
     * Setup Custom DBAL types.
240
     *
241
     * @param \Doctrine\DBAL\Connection $connection
242
     * @param array                     $options
243
     *
244
     * @throws \Doctrine\DBAL\DBALException
245
     * @throws \RuntimeException
246
     */
247
    protected static function setupCustomDBALTypes(Connection $connection, array $options)
248
    {
249
        $platform = $connection->getDatabasePlatform();
250
251
        foreach ($options['custom_types'] as $type => $class) {
252
            if (Type::hasType($type)) {
253
                throw new \RuntimeException(sprintf('Type "%s" is already registered', $type));
254
            }
255
256
            Type::addType($type, $class);
257
            $platform->registerDoctrineTypeMapping($type, $type);
258
        }
259
    }
260
}
261