Completed
Pull Request — master (#7709)
by
unknown
09:31
created

Configuration   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 549
Duplicated Lines 0 %

Test Coverage

Coverage 96.73%

Importance

Changes 0
Metric Value
eloc 104
dl 0
loc 549
rs 3.36
c 0
b 0
f 0
ccs 148
cts 153
cp 0.9673
wmc 63

47 Methods

Rating   Name   Duplication   Size   Complexity  
A setDefaultRepositoryClassName() 0 9 2
A getFilterClassName() 0 3 1
A setMetadataDriverImpl() 0 3 1
A setCustomStringFunctions() 0 4 2
A setDefaultQueryHints() 0 3 1
A addCustomDatetimeFunction() 0 3 1
A getHydrationCacheImpl() 0 3 1
A getCustomHydrationMode() 0 3 1
A buildGhostObjectFactory() 0 3 1
A getCustomStringFunction() 0 3 1
A getMetadataCacheImpl() 0 3 1
A setSecondLevelCacheConfiguration() 0 3 1
A addCustomHydrationMode() 0 3 1
A setMetadataCacheImpl() 0 3 1
A setCustomHydrationModes() 0 6 2
A getProxyManagerConfiguration() 0 4 1
A setAutoGenerateProxyClasses() 0 18 5
A setHydrationCacheImpl() 0 3 1
A setQueryCacheImpl() 0 3 1
A getDefaultQueryHint() 0 3 1
A setNamingStrategy() 0 3 1
A setProxyDir() 0 4 1
A getClassMetadataFactoryName() 0 3 1
A setSecondLevelCacheEnabled() 0 3 1
A isSecondLevelCacheEnabled() 0 3 1
A setCustomNumericFunctions() 0 4 2
A getCustomNumericFunction() 0 3 1
A getMetadataDriverImpl() 0 3 1
A addCustomStringFunction() 0 3 1
A setCustomDatetimeFunctions() 0 4 2
A setProxyNamespace() 0 3 1
A getNamingStrategy() 0 4 1
A getDefaultQueryHints() 0 3 1
A getEntityListenerResolver() 0 4 1
A newDefaultAnnotationDriver() 0 7 1
A setClassMetadataFactoryName() 0 3 1
A setEntityListenerResolver() 0 3 1
A getQueryCacheImpl() 0 3 1
A getRepositoryFactory() 0 4 1
A addFilter() 0 3 1
A setDefaultQueryHint() 0 3 1
A getCustomDatetimeFunction() 0 3 1
A addCustomNumericFunction() 0 3 1
A ensureProductionSettings() 0 24 6
A getDefaultRepositoryClassName() 0 3 1
A setRepositoryFactory() 0 3 1
A getSecondLevelCacheConfiguration() 0 7 3

How to fix   Complexity   

Complex Class

Complex classes like Configuration often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Configuration, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\Common\Annotations\AnnotationRegistry;
9
use Doctrine\Common\Annotations\CachedReader;
10
use Doctrine\Common\Cache\ArrayCache;
11
use Doctrine\Common\Cache\Cache as CacheDriver;
12
use Doctrine\Common\Persistence\ObjectRepository;
13
use Doctrine\DBAL\Configuration as DBALConfiguration;
14
use Doctrine\ORM\Cache\CacheConfiguration;
15
use Doctrine\ORM\Cache\Exception\MetadataCacheNotConfigured;
16
use Doctrine\ORM\Cache\Exception\MetadataCacheUsesNonPersistentCache;
17
use Doctrine\ORM\Cache\Exception\QueryCacheNotConfigured;
18
use Doctrine\ORM\Cache\Exception\QueryCacheUsesNonPersistentCache;
19
use Doctrine\ORM\Exception\InvalidEntityRepository;
20
use Doctrine\ORM\Exception\ProxyClassesAlwaysRegenerating;
21
use Doctrine\ORM\Mapping\ClassMetadataFactory;
22
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
23
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
24
use Doctrine\ORM\Mapping\Driver\MappingDriver;
25
use Doctrine\ORM\Mapping\EntityListenerResolver;
26
use Doctrine\ORM\Mapping\Factory\DefaultNamingStrategy;
27
use Doctrine\ORM\Mapping\Factory\NamingStrategy;
28
use Doctrine\ORM\Proxy\Factory\ProxyFactory;
29
use Doctrine\ORM\Query\ResultSetMapping;
30
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
31
use Doctrine\ORM\Repository\RepositoryFactory;
32
use ProxyManager\Configuration as ProxyManagerConfiguration;
33
use ProxyManager\Factory\LazyLoadingGhostFactory;
34
use ProxyManager\FileLocator\FileLocator;
35
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
36
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
37
use ReflectionClass;
38
use function strtolower;
39
40
/**
41
 * Configuration container for all configuration options of Doctrine.
42
 * It combines all configuration options from DBAL & ORM.
43
 *
44
 * {@internal When adding a new configuration option just write a getter/setter pair. }}
45
 */
46
class Configuration extends DBALConfiguration
47
{
48
    /** @var ProxyManagerConfiguration|null */
49
    private $proxyManagerConfiguration;
50
51
    /** @var MappingDriver|null */
52
    private $metadataDriver;
53
54
    /** @var CacheDriver|null */
55
    private $queryCache;
56
57
    /** @var CacheDriver|null */
58
    private $hydrationCache;
59
60
    /** @var CacheDriver|null */
61
    private $metadataCache;
62
63
    /** @var string[][]|ResultSetMapping[][] tuples of [$sqlString, $resultSetMapping] indexed by query name */
64
    private $customStringFunctions = [];
65
66
    /** @var string[][]|ResultSetMapping[][] tuples of [$sqlString, $resultSetMapping] indexed by query name */
67
    private $customNumericFunctions = [];
68
69
    /** @var string[][]|ResultSetMapping[][] tuples of [$sqlString, $resultSetMapping] indexed by query name */
70
    private $customDatetimeFunctions = [];
71
72
    /** @var string[] of hydrator class names, indexed by mode name */
73
    private $customHydrationModes = [];
74
75
    /** @var string */
76
    private $classMetadataFactoryClassName = ClassMetadataFactory::class;
77
78
    /** @var string[] of filter class names, indexed by filter name */
79
    private $filters;
80
81
    /** @var string */
82
    private $defaultRepositoryClassName = EntityRepository::class;
83
84
    /** @var NamingStrategy|null */
85
    private $namingStrategy;
86
87
    /** @var EntityListenerResolver|null */
88
    private $entityListenerResolver;
89
90
    /** @var RepositoryFactory|null */
91
    private $repositoryFactory;
92
93
    /** @var bool */
94
    private $isSecondLevelCacheEnabled = false;
95
96
    /** @var CacheConfiguration|null */
97
    private $secondLevelCacheConfiguration;
98
99
    /** @var mixed[] indexed by hint name */
100
    private $defaultQueryHints = [];
101
102
    /**
103
     * Sets the directory where Doctrine generates any necessary proxy class files.
104
     */
105 92
    public function setProxyDir(string $directory) : void
106
    {
107 92
        $this->getProxyManagerConfiguration()->setProxiesTargetDir($directory);
108 92
        $this->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS);
109 92
    }
110
111
    /**
112
     * Sets the strategy for automatically generating proxy classes.
113
     *
114
     * @param bool|int $autoGenerate Possible values are constants of Doctrine\ORM\Proxy\Factory\ProxyFactory.
115
     *                               True is converted to AUTOGENERATE_ALWAYS, false to AUTOGENERATE_NEVER.
116
     */
117 2297
    public function setAutoGenerateProxyClasses($autoGenerate) : void
118
    {
119 2297
        $proxyManagerConfig = $this->getProxyManagerConfiguration();
120
121 2297
        switch ((int) $autoGenerate) {
122
            case ProxyFactory::AUTOGENERATE_ALWAYS:
123
            case ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS:
124 101
                $proxyManagerConfig->setGeneratorStrategy(new FileWriterGeneratorStrategy(
125 101
                    new FileLocator($proxyManagerConfig->getProxiesTargetDir())
126
                ));
127
128 101
                return;
129
            case ProxyFactory::AUTOGENERATE_NEVER:
130
            case ProxyFactory::AUTOGENERATE_EVAL:
131
            default:
132 2212
                $proxyManagerConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
133
134 2212
                return;
135
        }
136
    }
137
138
    /**
139
     * Sets the namespace where proxy classes reside.
140
     */
141 2284
    public function setProxyNamespace(string $namespace) : void
142
    {
143 2284
        $this->getProxyManagerConfiguration()->setProxiesNamespace($namespace);
144 2284
    }
145
146
    /**
147
     * Sets the cache driver implementation that is used for metadata caching.
148
     *
149
     * @todo Force parameter to be a Closure to ensure lazy evaluation
150
     *       (as soon as a metadata cache is in effect, the driver never needs to initialize).
151
     */
152 2280
    public function setMetadataDriverImpl(MappingDriver $metadataDriver) : void
153
    {
154 2280
        $this->metadataDriver = $metadataDriver;
155 2280
    }
156
157
    /**
158
     * Adds a new default annotation driver with a correctly configured annotation reader.
159
     *
160
     * @param string[] $paths
161
     */
162 2268
    public function newDefaultAnnotationDriver(array $paths = []) : AnnotationDriver
163
    {
164 2268
        AnnotationRegistry::registerFile(__DIR__ . '/Annotation/DoctrineAnnotations.php');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...egistry::registerFile() has been deprecated: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists') ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

164
        /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerFile(__DIR__ . '/Annotation/DoctrineAnnotations.php');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
165
166 2268
        $reader = new CachedReader(new AnnotationReader(), new ArrayCache());
167
168 2268
        return new AnnotationDriver($reader, $paths);
169
    }
170
171
    /**
172
     * Gets the cache driver implementation that is used for the mapping metadata.
173
     */
174 2278
    public function getMetadataDriverImpl() : ?MappingDriver
175
    {
176 2278
        return $this->metadataDriver;
177
    }
178
179
    /**
180
     * Gets the cache driver implementation that is used for the query cache (SQL cache).
181
     */
182 778
    public function getQueryCacheImpl() : ?CacheDriver
183
    {
184 778
        return $this->queryCache;
185
    }
186
187
    /**
188
     * Sets the cache driver implementation that is used for the query cache (SQL cache).
189
     */
190 2219
    public function setQueryCacheImpl(CacheDriver $queryCache) : void
191
    {
192 2219
        $this->queryCache = $queryCache;
193 2219
    }
194
195
    /**
196
     * Gets the cache driver implementation that is used for the hydration cache (SQL cache).
197
     */
198 1
    public function getHydrationCacheImpl() : ?CacheDriver
199
    {
200 1
        return $this->hydrationCache;
201
    }
202
203
    /**
204
     * Sets the cache driver implementation that is used for the hydration cache (SQL cache).
205
     */
206 2
    public function setHydrationCacheImpl(CacheDriver $hydrationCache) : void
207
    {
208 2
        $this->hydrationCache = $hydrationCache;
209 2
    }
210
211
    /**
212
     * Gets the cache driver implementation that is used for metadata caching.
213
     */
214 2285
    public function getMetadataCacheImpl() : ?CacheDriver
215
    {
216 2285
        return $this->metadataCache;
217
    }
218
219
    /**
220
     * Sets the cache driver implementation that is used for metadata caching.
221
     */
222 2219
    public function setMetadataCacheImpl(CacheDriver $metadataCache) : void
223
    {
224 2219
        $this->metadataCache = $metadataCache;
225 2219
    }
226
227
    /**
228
     * Ensures that this Configuration instance contains settings that are
229
     * suitable for a production environment.
230
     *
231
     * @throws ORMException If a configuration setting has a value that is not
232
     *                      suitable for a production environment.
233
     */
234 6
    public function ensureProductionSettings() : void
235
    {
236 6
        $queryCacheImpl = $this->getQueryCacheImpl();
237
238 6
        if (! $queryCacheImpl) {
239 1
            throw QueryCacheNotConfigured::create();
240
        }
241
242 5
        if ($queryCacheImpl instanceof ArrayCache) {
243 1
            throw QueryCacheUsesNonPersistentCache::fromDriver($queryCacheImpl);
244
        }
245
246 4
        $metadataCacheImpl = $this->getMetadataCacheImpl();
247
248 4
        if (! $metadataCacheImpl) {
249 1
            throw MetadataCacheNotConfigured::create();
250
        }
251
252 3
        if ($metadataCacheImpl instanceof ArrayCache) {
253 1
            throw MetadataCacheUsesNonPersistentCache::fromDriver($metadataCacheImpl);
254
        }
255
256 2
        if ($this->getProxyManagerConfiguration()->getGeneratorStrategy() instanceof EvaluatingGeneratorStrategy) {
257 1
            throw ProxyClassesAlwaysRegenerating::create();
258
        }
259 1
    }
260
261
    /**
262
     * Registers a custom DQL function that produces a string value.
263
     * Such a function can then be used in any DQL statement in any place where string
264
     * functions are allowed.
265
     *
266
     * DQL function names are case-insensitive.
267
     *
268
     * @param string|callable $classNameOrFactory Class name or a callable that returns the function.
269
     */
270 5
    public function addCustomStringFunction(string $functionName, $classNameOrFactory) : void
271
    {
272 5
        $this->customStringFunctions[strtolower($functionName)] = $classNameOrFactory;
273 5
    }
274
275
    /**
276
     * Gets the implementation class name of a registered custom string DQL function.
277
     *
278
     * @return string|callable|null
279
     */
280 163
    public function getCustomStringFunction(string $functionName)
281
    {
282 163
        return $this->customStringFunctions[strtolower($functionName)] ?? null;
283
    }
284
285
    /**
286
     * Sets a map of custom DQL string functions.
287
     *
288
     * Keys must be function names and values the FQCN of the implementing class.
289
     * The function names will be case-insensitive in DQL.
290
     *
291
     * Any previously added string functions are discarded.
292
     *
293
     * @param string[]|callable[] $functions The map of custom DQL string functions.
294
     */
295 1
    public function setCustomStringFunctions(array $functions) : void
296
    {
297 1
        foreach ($functions as $name => $className) {
298 1
            $this->addCustomStringFunction($name, $className);
299
        }
300 1
    }
301
302
    /**
303
     * Registers a custom DQL function that produces a numeric value.
304
     * Such a function can then be used in any DQL statement in any place where numeric
305
     * functions are allowed.
306
     *
307
     * DQL function names are case-insensitive.
308
     *
309
     * @param string|callable $classNameOrFactory Class name or a callable that returns the function.
310
     */
311 3
    public function addCustomNumericFunction(string $functionName, $classNameOrFactory) : void
312
    {
313 3
        $this->customNumericFunctions[strtolower($functionName)] = $classNameOrFactory;
314 3
    }
315
316
    /**
317
     * Gets the implementation class name of a registered custom numeric DQL function.
318
     *
319
     * @return string|callable|null
320
     */
321 160
    public function getCustomNumericFunction(string $functionName)
322
    {
323 160
        return $this->customNumericFunctions[strtolower($functionName)] ?? null;
324
    }
325
326
    /**
327
     * Sets a map of custom DQL numeric functions.
328
     *
329
     * Keys must be function names and values the FQCN of the implementing class.
330
     * The function names will be case-insensitive in DQL.
331
     *
332
     * Any previously added numeric functions are discarded.
333
     *
334
     * @param string[]|callable[] $functions The map of custom DQL numeric functions.
335
     */
336 2
    public function setCustomNumericFunctions(array $functions) : void
337
    {
338 2
        foreach ($functions as $name => $className) {
339 1
            $this->addCustomNumericFunction($name, $className);
340
        }
341 2
    }
342
343
    /**
344
     * Registers a custom DQL function that produces a date/time value.
345
     * Such a function can then be used in any DQL statement in any place where date/time
346
     * functions are allowed.
347
     *
348
     * DQL function names are case-insensitive.
349
     *
350
     * @param string|callable $classNameOrFactory Class name or a callable that returns the function.
351
     */
352 1
    public function addCustomDatetimeFunction(string $functionName, $classNameOrFactory)
353
    {
354 1
        $this->customDatetimeFunctions[strtolower($functionName)] = $classNameOrFactory;
355 1
    }
356
357
    /**
358
     * Gets the implementation class name of a registered custom date/time DQL function.
359
     *
360
     * @return string|callable|null
361
     */
362 158
    public function getCustomDatetimeFunction(string $functionName)
363
    {
364 158
        return $this->customDatetimeFunctions[strtolower($functionName)] ?? null;
365
    }
366
367
    /**
368
     * Sets a map of custom DQL date/time functions.
369
     *
370
     * Keys must be function names and values the FQCN of the implementing class.
371
     * The function names will be case-insensitive in DQL.
372
     *
373
     * Any previously added date/time functions are discarded.
374
     *
375
     * @param iterable|string[] $functions The map of custom DQL date/time functions.
376
     */
377 1
    public function setCustomDatetimeFunctions(array $functions) : void
378
    {
379 1
        foreach ($functions as $name => $className) {
380 1
            $this->addCustomDatetimeFunction($name, $className);
381
        }
382 1
    }
383
384
    /**
385
     * Sets the custom hydrator modes in one pass.
386
     *
387
     * @param iterable|string[] $modes An iterable of string $modeName => string $hydratorClassName
388
     */
389 1
    public function setCustomHydrationModes(iterable $modes) : void
390
    {
391 1
        $this->customHydrationModes = [];
392
393 1
        foreach ($modes as $modeName => $hydrator) {
394 1
            $this->addCustomHydrationMode($modeName, $hydrator);
395
        }
396 1
    }
397
398
    /**
399
     * Gets the hydrator class for the given hydration mode name.
400
     *
401
     * @return string|null The hydrator class name.
402
     */
403 3
    public function getCustomHydrationMode(string $modeName) : ?string
404
    {
405 3
        return $this->customHydrationModes[$modeName] ?? null;
406
    }
407
408
    /**
409
     * Adds a custom hydration mode.
410
     */
411 3
    public function addCustomHydrationMode(string $modeName, string $hydratorClassName) : void
412
    {
413 3
        $this->customHydrationModes[$modeName] = $hydratorClassName;
414 3
    }
415
416
    /**
417
     * Sets a class metadata factory.
418
     */
419 1
    public function setClassMetadataFactoryName(string $classMetadataFactoryClassName) : void
420
    {
421 1
        $this->classMetadataFactoryClassName = $classMetadataFactoryClassName;
422 1
    }
423
424 2276
    public function getClassMetadataFactoryName() : string
425
    {
426 2276
        return $this->classMetadataFactoryClassName;
427
    }
428
429
    /**
430
     * Adds a filter to the list of possible filters.
431
     */
432 47
    public function addFilter(string $filterName, string $filterClassName) : void
433
    {
434 47
        $this->filters[$filterName] = $filterClassName;
435 47
    }
436
437
    /**
438
     * Gets the class name for a given filter name.
439
     *
440
     * @return string|null The class name of the filter
441
     */
442 46
    public function getFilterClassName(string $filterName) : ?string
443
    {
444 46
        return $this->filters[$filterName] ?? null;
445
    }
446
447
    /**
448
     * Sets default repository class.
449
     *
450
     * @throws ORMException If not is a \Doctrine\Common\Persistence\ObjectRepository implementation.
451
     */
452 2
    public function setDefaultRepositoryClassName(string $repositoryClassName) : void
453
    {
454 2
        $reflectionClass = new ReflectionClass($repositoryClassName);
455
456 2
        if (! $reflectionClass->implementsInterface(ObjectRepository::class)) {
457 1
            throw InvalidEntityRepository::fromClassName($repositoryClassName);
458
        }
459
460 1
        $this->defaultRepositoryClassName = $repositoryClassName;
461 1
    }
462
463
    /**
464
     * Get default repository class.
465
     */
466 137
    public function getDefaultRepositoryClassName() : string
467
    {
468 137
        return $this->defaultRepositoryClassName;
469
    }
470
471
    /**
472
     * Sets naming strategy.
473
     */
474 3
    public function setNamingStrategy(NamingStrategy $namingStrategy) : void
475
    {
476 3
        $this->namingStrategy = $namingStrategy;
477 3
    }
478
479
    /**
480
     * Gets naming strategy..
481
     */
482 1967
    public function getNamingStrategy() : ?NamingStrategy
483
    {
484 1967
        return $this->namingStrategy
485 1967
            ?? $this->namingStrategy = new DefaultNamingStrategy();
486
    }
487
488
    /**
489
     * Set the entity listener resolver.
490
     */
491 1
    public function setEntityListenerResolver(EntityListenerResolver $resolver) : void
492
    {
493 1
        $this->entityListenerResolver = $resolver;
494 1
    }
495
496
    /**
497
     * Get the entity listener resolver.
498
     */
499 2276
    public function getEntityListenerResolver() : EntityListenerResolver
500
    {
501 2276
        return $this->entityListenerResolver
502 2276
            ?? $this->entityListenerResolver = new DefaultEntityListenerResolver();
503
    }
504
505
    /**
506
     * Set the entity repository factory.
507
     */
508
    public function setRepositoryFactory(RepositoryFactory $repositoryFactory) : void
509
    {
510
        $this->repositoryFactory = $repositoryFactory;
511
    }
512
513
    /**
514
     * Get the entity repository factory.
515
     */
516 2275
    public function getRepositoryFactory() : RepositoryFactory
517
    {
518 2275
        return $this->repositoryFactory
519 2275
            ?? $this->repositoryFactory = new DefaultRepositoryFactory();
520
    }
521
522 2275
    public function isSecondLevelCacheEnabled() : bool
523
    {
524 2275
        return $this->isSecondLevelCacheEnabled;
525
    }
526
527 281
    public function setSecondLevelCacheEnabled(bool $flag = true) : void
528
    {
529 281
        $this->isSecondLevelCacheEnabled = $flag;
530 281
    }
531
532 281
    public function setSecondLevelCacheConfiguration(CacheConfiguration $cacheConfig) : void
533
    {
534 281
        $this->secondLevelCacheConfiguration = $cacheConfig;
535 281
    }
536
537 282
    public function getSecondLevelCacheConfiguration() : ?CacheConfiguration
538
    {
539 282
        if ($this->isSecondLevelCacheEnabled && ! $this->secondLevelCacheConfiguration) {
540 1
            $this->secondLevelCacheConfiguration = new CacheConfiguration();
541
        }
542
543 282
        return $this->secondLevelCacheConfiguration;
544
    }
545
546
    /**
547
     * Returns query hints, which will be applied to every query in application
548
     *
549
     * @return mixed[]
550
     */
551 974
    public function getDefaultQueryHints() : array
552
    {
553 974
        return $this->defaultQueryHints;
554
    }
555
556
    /**
557
     * Sets array of query hints, which will be applied to every query in application
558
     *
559
     * @param mixed[] $defaultQueryHints
560
     */
561 1
    public function setDefaultQueryHints(array $defaultQueryHints) : void
562
    {
563 1
        $this->defaultQueryHints = $defaultQueryHints;
564 1
    }
565
566
    /**
567
     * Gets the value of a default query hint. If the hint name is not recognized, FALSE is returned.
568
     *
569
     * @return mixed The value of the hint or FALSE, if the hint name is not recognized.
570
     */
571
    public function getDefaultQueryHint(string $hintName)
572
    {
573
        return $this->defaultQueryHints[$hintName] ?? false;
574
    }
575
576
    /**
577
     * Sets a default query hint. If the hint name is not recognized, it is silently ignored.
578
     *
579
     * @param mixed $value The value of the hint.
580
     */
581 1
    public function setDefaultQueryHint(string $hintName, $value) : void
582
    {
583 1
        $this->defaultQueryHints[$hintName] = $value;
584 1
    }
585
586 2276
    public function buildGhostObjectFactory() : LazyLoadingGhostFactory
587
    {
588 2276
        return new LazyLoadingGhostFactory(clone $this->getProxyManagerConfiguration());
589
    }
590
591 2299
    public function getProxyManagerConfiguration() : ProxyManagerConfiguration
592
    {
593 2299
        return $this->proxyManagerConfiguration
594 2299
            ?? $this->proxyManagerConfiguration = new ProxyManagerConfiguration();
595
    }
596
}
597