SerializerBuilder::decorateAnnotationReader()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 4
nop 1
dl 0
loc 14
ccs 0
cts 0
cp 0
crap 30
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JMS\Serializer;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\Common\Annotations\CachedReader;
0 ignored issues
show
Bug introduced by
The type Doctrine\Common\Annotations\CachedReader was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Doctrine\Common\Annotations\PsrCachedReader;
10
use Doctrine\Common\Annotations\Reader;
11
use Doctrine\Common\Cache\FilesystemCache;
0 ignored issues
show
Bug introduced by
The type Doctrine\Common\Cache\FilesystemCache was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use JMS\Serializer\Accessor\AccessorStrategyInterface;
13
use JMS\Serializer\Accessor\DefaultAccessorStrategy;
14
use JMS\Serializer\Builder\DefaultDriverFactory;
15
use JMS\Serializer\Builder\DocBlockDriverFactory;
16
use JMS\Serializer\Builder\DriverFactoryInterface;
17
use JMS\Serializer\Construction\ObjectConstructorInterface;
18
use JMS\Serializer\Construction\UnserializeObjectConstructor;
19
use JMS\Serializer\ContextFactory\CallableDeserializationContextFactory;
20
use JMS\Serializer\ContextFactory\CallableSerializationContextFactory;
21
use JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface;
22
use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface;
23
use JMS\Serializer\EventDispatcher\EventDispatcher;
24
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
25
use JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber;
26
use JMS\Serializer\EventDispatcher\Subscriber\EnumSubscriber;
27
use JMS\Serializer\Exception\InvalidArgumentException;
28
use JMS\Serializer\Exception\RuntimeException;
29
use JMS\Serializer\Expression\CompilableExpressionEvaluatorInterface;
30
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
31
use JMS\Serializer\GraphNavigator\Factory\DeserializationGraphNavigatorFactory;
32
use JMS\Serializer\GraphNavigator\Factory\GraphNavigatorFactoryInterface;
33
use JMS\Serializer\GraphNavigator\Factory\SerializationGraphNavigatorFactory;
34
use JMS\Serializer\Handler\ArrayCollectionHandler;
35
use JMS\Serializer\Handler\DateHandler;
36
use JMS\Serializer\Handler\EnumHandler;
37
use JMS\Serializer\Handler\HandlerRegistry;
38
use JMS\Serializer\Handler\HandlerRegistryInterface;
39
use JMS\Serializer\Handler\IteratorHandler;
40
use JMS\Serializer\Handler\StdClassHandler;
41
use JMS\Serializer\Handler\UnionHandler;
42
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
43
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
44
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
45
use JMS\Serializer\Type\Parser;
46
use JMS\Serializer\Type\ParserInterface;
47
use JMS\Serializer\Visitor\Factory\DeserializationVisitorFactory;
48
use JMS\Serializer\Visitor\Factory\JsonDeserializationVisitorFactory;
49
use JMS\Serializer\Visitor\Factory\JsonSerializationVisitorFactory;
50
use JMS\Serializer\Visitor\Factory\SerializationVisitorFactory;
51
use JMS\Serializer\Visitor\Factory\XmlDeserializationVisitorFactory;
52
use JMS\Serializer\Visitor\Factory\XmlSerializationVisitorFactory;
53
use Metadata\Cache\CacheInterface;
54
use Metadata\Cache\FileCache;
55
use Metadata\MetadataFactory;
56
use Metadata\MetadataFactoryInterface;
57
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
58
59
/**
60
 * Builder for serializer instances.
61
 *
62
 * This object makes serializer construction a breeze for projects that do not use
63
 * any special dependency injection container.
64
 *
65
 * @author Johannes M. Schmitt <[email protected]>
66
 */
67
final class SerializerBuilder
68
{
69
    /**
70
     * @var string[]
71
     */
72
    private $metadataDirs = [];
73
74
    /**
75
     * @var HandlerRegistryInterface
76
     */
77
    private $handlerRegistry;
78
79
    /**
80
     * @var bool
81
     */
82
    private $handlersConfigured = false;
83
84
    /**
85
     * @var EventDispatcherInterface
86
     */
87
    private $eventDispatcher;
88
89
    /**
90
     * @var bool
91
     */
92
    private $enableEnumSupport = false;
93
94
    /**
95
     * @var bool
96 330
     */
97
    private $listenersConfigured = false;
98 330
99
    /**
100
     * @var ObjectConstructorInterface
101 330
     */
102
    private $objectConstructor;
103 330
104 330
    /**
105 330
     * @var SerializationVisitorFactory[]
106 330
     */
107 330
    private $serializationVisitors;
108
109 330
    /**
110 284
     * @var DeserializationVisitorFactory[]
111
     */
112 330
    private $deserializationVisitors;
113 284
114
    /**
115 330
     * @var bool
116
     */
117
    private $deserializationVisitorsAdded = false;
118
119
    /**
120
     * @var bool
121
     */
122
    private $serializationVisitorsAdded = false;
123 330
124
    /**
125 330
     * @var PropertyNamingStrategyInterface
126 330
     */
127
    private $propertyNamingStrategy;
128 330
129
    /**
130
     * @var bool
131 25
     */
132
    private $debug = false;
133 25
134
    /**
135 25
     * @var string
136
     */
137
    private $cacheDir;
138 1
139
    /**
140 1
     * @var Reader
141
     */
142 1
    private $annotationReader;
143
144
    /**
145
     * @var bool
146
     */
147
    private $includeInterfaceMetadata = false;
148
149
    /**
150
     * @var DriverFactoryInterface
151
     */
152
    private $driverFactory;
153
154
    /**
155
     * @var SerializationContextFactoryInterface
156
     */
157
    private $serializationContextFactory;
158
159 1
    /**
160
     * @var DeserializationContextFactoryInterface
161 1
     */
162 1
    private $deserializationContextFactory;
163
164 1
    /**
165
     * @var ParserInterface
166
     */
167
    private $typeParser;
168 1
169
    /**
170 1
     * @var ExpressionEvaluatorInterface
171
     */
172
    private $expressionEvaluator;
173 71
174
    /**
175 71
     * @var AccessorStrategyInterface
176 71
     */
177 71
    private $accessorStrategy;
178 71
179
    /**
180 71
     * @var CacheInterface
181
     */
182
    private $metadataCache;
183 3
184
    /**
185 3
     * @var bool
186 3
     */
187
    private $docBlockTyperResolver;
188 3
189
    /**
190
     * @param mixed ...$args
191 73
     *
192
     * @return SerializerBuilder
193 73
     */
194 73
    public static function create(...$args): self
195
    {
196 73
        return new static(...$args);
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $handlerRegistry of JMS\Serializer\SerializerBuilder::__construct() does not expect variable arguments. ( Ignorable by Annotation )

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

196
        return new static(/** @scrutinizer ignore-type */ ...$args);
Loading history...
197
    }
198
199 1
    public function __construct(?HandlerRegistryInterface $handlerRegistry = null, ?EventDispatcherInterface $eventDispatcher = null)
200
    {
201 1
        $this->typeParser = new Parser();
202 1
        $this->handlerRegistry = $handlerRegistry ?: new HandlerRegistry();
203
        $this->eventDispatcher = $eventDispatcher ?: new EventDispatcher();
204 1
        $this->serializationVisitors = [];
205
        $this->deserializationVisitors = [];
206
207 4
        if ($handlerRegistry) {
208
            $this->handlersConfigured = true;
209 4
        }
210
211 4
        if ($eventDispatcher) {
212
            $this->listenersConfigured = true;
213
        }
214
    }
215
216
    public function setAccessorStrategy(AccessorStrategyInterface $accessorStrategy): self
217
    {
218
        $this->accessorStrategy = $accessorStrategy;
219
220
        return $this;
221 2
    }
222
223 2
    private function getAccessorStrategy(): AccessorStrategyInterface
224 2
    {
225
        if (!$this->accessorStrategy) {
226 2
            $this->accessorStrategy = new DefaultAccessorStrategy($this->expressionEvaluator);
227
        }
228
229
        return $this->accessorStrategy;
230
    }
231
232
    public function setExpressionEvaluator(ExpressionEvaluatorInterface $expressionEvaluator): self
233
    {
234
        $this->expressionEvaluator = $expressionEvaluator;
235
236
        return $this;
237 329
    }
238
239 329
    public function setTypeParser(ParserInterface $parser): self
240 329
    {
241 329
        $this->typeParser = $parser;
242 329
243
        return $this;
244
    }
245 329
246
    public function setAnnotationReader(Reader $reader): self
247
    {
248 329
        $this->annotationReader = $reader;
249
250 329
        return $this;
251 329
    }
252 329
253 329
    public function setDebug(bool $bool): self
254
    {
255
        $this->debug = $bool;
256 329
257
        return $this;
258
    }
259
260
    public function setCacheDir(string $dir): self
261
    {
262
        if (!is_dir($dir)) {
263
            $this->createDir($dir);
264 1
        }
265
266 1
        if (!is_writable($dir)) {
267
            throw new InvalidArgumentException(sprintf('The cache directory "%s" is not writable.', $dir));
268 1
        }
269
270
        $this->cacheDir = $dir;
271
272
        return $this;
273
    }
274
275
    public function addDefaultHandlers(): self
276
    {
277
        $this->handlersConfigured = true;
278
        $this->handlerRegistry->registerSubscribingHandler(new DateHandler());
279
        $this->handlerRegistry->registerSubscribingHandler(new StdClassHandler());
280
        $this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler());
281
        $this->handlerRegistry->registerSubscribingHandler(new IteratorHandler());
282 2
283
        if ($this->enableEnumSupport) {
284 2
            $this->handlerRegistry->registerSubscribingHandler(new EnumHandler());
285 2
        }
286 2
287
        if (PHP_VERSION_ID >= 80000) {
288
            $this->handlerRegistry->registerSubscribingHandler(new UnionHandler());
289
        }
290 2
291
        return $this;
292 2
    }
293
294
    public function configureHandlers(\Closure $closure): self
295
    {
296
        $this->handlersConfigured = true;
297
        $closure($this->handlerRegistry);
298
299
        return $this;
300
    }
301
302
    public function addDefaultListeners(): self
303
    {
304
        $this->listenersConfigured = true;
305
        $this->eventDispatcher->addSubscriber(new DoctrineProxySubscriber());
306
        if ($this->enableEnumSupport) {
307
            $this->eventDispatcher->addSubscriber(new EnumSubscriber());
308
        }
309
310
        return $this;
311
    }
312
313
    public function configureListeners(\Closure $closure): self
314
    {
315
        $this->listenersConfigured = true;
316
        $closure($this->eventDispatcher);
317
318
        return $this;
319
    }
320
321
    public function setObjectConstructor(ObjectConstructorInterface $constructor): self
322
    {
323
        $this->objectConstructor = $constructor;
324
325
        return $this;
326
    }
327
328
    public function setPropertyNamingStrategy(PropertyNamingStrategyInterface $propertyNamingStrategy): self
329
    {
330
        $this->propertyNamingStrategy = $propertyNamingStrategy;
331
332
        return $this;
333
    }
334
335
    public function setSerializationVisitor(string $format, SerializationVisitorFactory $visitor): self
336
    {
337
        $this->serializationVisitorsAdded = true;
338
        $this->serializationVisitors[$format] = $visitor;
339
340
        return $this;
341
    }
342
343
    public function setDeserializationVisitor(string $format, DeserializationVisitorFactory $visitor): self
344
    {
345
        $this->deserializationVisitorsAdded = true;
346
        $this->deserializationVisitors[$format] = $visitor;
347
348
        return $this;
349
    }
350
351
    public function addDefaultSerializationVisitors(): self
352
    {
353
        $this->serializationVisitorsAdded = true;
354
        $this->serializationVisitors = [
355
            'xml' => new XmlSerializationVisitorFactory(),
356
            'json' => new JsonSerializationVisitorFactory(),
357
        ];
358
359
        return $this;
360
    }
361
362
    public function addDefaultDeserializationVisitors(): self
363
    {
364
        $this->deserializationVisitorsAdded = true;
365
        $this->deserializationVisitors = [
366
            'xml' => new XmlDeserializationVisitorFactory(),
367
            'json' => new JsonDeserializationVisitorFactory(),
368
        ];
369
370
        return $this;
371
    }
372
373
    /**
374
     * @param bool $include Whether to include the metadata from the interfaces
375
     *
376
     * @return SerializerBuilder
377
     */
378 13
    public function includeInterfaceMetadata(bool $include): self
379
    {
380 13
        $this->includeInterfaceMetadata = $include;
381
382 13
        return $this;
383
    }
384
385
    /**
386
     * Sets a map of namespace prefixes to directories.
387
     *
388
     * This method overrides any previously defined directories.
389
     *
390 5
     * @param array <string,string> $namespacePrefixToDirMap
0 ignored issues
show
Documentation Bug introduced by
The doc comment <string,string> at position 0 could not be parsed: Unknown type name '<' at position 0 in <string,string>.
Loading history...
391
     *
392 5
     * @return SerializerBuilder
393 3
     *
394 2
     * @throws InvalidArgumentException When a directory does not exist.
395 2
     */
396 2
    public function setMetadataDirs(array $namespacePrefixToDirMap): self
397
    {
398
        foreach ($namespacePrefixToDirMap as $dir) {
399
            if (!is_dir($dir)) {
400
                throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
401
            }
402 5
        }
403
404
        $this->metadataDirs = $namespacePrefixToDirMap;
405
406
        return $this;
407
    }
408
409
    /**
410 3
     * Adds a directory where the serializer will look for class metadata.
411
     *
412 3
     * The namespace prefix will make the names of the actual metadata files a bit shorter. For example, let's assume
413 3
     * that you have a directory where you only store metadata files for the ``MyApplication\Entity`` namespace.
414
     *
415
     * If you use an empty prefix, your metadata files would need to look like:
416
     *
417
     * ``my-dir/MyApplication.Entity.SomeObject.yml``
418
     * ``my-dir/MyApplication.Entity.OtherObject.xml``
419
     *
420
     * If you use ``MyApplication\Entity`` as prefix, your metadata files would need to look like:
421
     *
422 3
     * ``my-dir/SomeObject.yml``
423
     * ``my-dir/OtherObject.yml``
424
     *
425
     * Please keep in mind that you currently may only have one directory per namespace prefix.
426
     *
427
     * @param string $dir             The directory where metadata files are located.
428
     * @param string $namespacePrefix An optional prefix if you only store metadata for specific namespaces in this directory.
429
     *
430
     * @return SerializerBuilder
431 330
     *
432
     * @throws InvalidArgumentException When a directory does not exist.
433 330
     * @throws InvalidArgumentException When a directory has already been registered.
434 330
     */
435 330
    public function addMetadataDir(string $dir, string $namespacePrefix = ''): self
436
    {
437 330
        if (!is_dir($dir)) {
438 1
            throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
439 1
        }
440 1
441
        if (isset($this->metadataDirs[$namespacePrefix])) {
442
            throw new InvalidArgumentException(sprintf('There is already a directory configured for the namespace prefix "%s". Please use replaceMetadataDir() to override directories.', $namespacePrefix));
443
        }
444 330
445 318
        $this->metadataDirs[$namespacePrefix] = $dir;
446 318
447
        return $this;
448
    }
449 330
450 330
    /**
451
     * Adds a map of namespace prefixes to directories.
452 330
     *
453
     * @param array <string,string> $namespacePrefixToDirMap
0 ignored issues
show
Documentation Bug introduced by
The doc comment <string,string> at position 0 could not be parsed: Unknown type name '<' at position 0 in <string,string>.
Loading history...
454 330
     *
455
     * @return SerializerBuilder
456 330
     */
457 1
    public function addMetadataDirs(array $namespacePrefixToDirMap): self
458 1
    {
459
        foreach ($namespacePrefixToDirMap as $prefix => $dir) {
460
            $this->addMetadataDir($dir, $prefix);
461 330
        }
462 71
463
        return $this;
464
    }
465 330
466 73
    /**
467
     * Similar to addMetadataDir(), but overrides an existing entry.
468
     *
469 330
     * @return SerializerBuilder
470 329
     *
471 329
     * @throws InvalidArgumentException When a directory does not exist.
472
     * @throws InvalidArgumentException When no directory is configured for the ns prefix.
473
     */
474 330
    public function replaceMetadataDir(string $dir, string $namespacePrefix = ''): self
475 330
    {
476
        if (!is_dir($dir)) {
477
            throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
478 330
        }
479 330
480 330
        if (!isset($this->metadataDirs[$namespacePrefix])) {
481 330
            throw new InvalidArgumentException(sprintf('There is no directory configured for namespace prefix "%s". Please use addMetadataDir() for adding new directories.', $namespacePrefix));
482 330
        }
483 330
484 330
        $this->metadataDirs[$namespacePrefix] = $dir;
485 330
486
        return $this;
487
    }
488 330
489
    public function setMetadataDriverFactory(DriverFactoryInterface $driverFactory): self
490
    {
491 330
        $this->driverFactory = $driverFactory;
492
493 330
        return $this;
494 330
    }
495 330
496 330
    /**
497 330
     * @param SerializationContextFactoryInterface|callable $serializationContextFactory
498 330
     */
499
    public function setSerializationContextFactory($serializationContextFactory): self
500
    {
501
        if ($serializationContextFactory instanceof SerializationContextFactoryInterface) {
502 330
            $this->serializationContextFactory = $serializationContextFactory;
503
        } elseif (is_callable($serializationContextFactory)) {
504 330
            $this->serializationContextFactory = new CallableSerializationContextFactory(
505 330
                $serializationContextFactory,
506 330
            );
507 330
        } else {
508 330
            throw new InvalidArgumentException('expected SerializationContextFactoryInterface or callable.');
509 330
        }
510 330
511
        return $this;
512
    }
513
514 318
    /**
515
     * @param DeserializationContextFactoryInterface|callable $deserializationContextFactory
516 318
     */
517
    public function setDeserializationContextFactory($deserializationContextFactory): self
518
    {
519
        if ($deserializationContextFactory instanceof DeserializationContextFactoryInterface) {
520 318
            $this->deserializationContextFactory = $deserializationContextFactory;
521 318
        } elseif (is_callable($deserializationContextFactory)) {
522
            $this->deserializationContextFactory = new CallableDeserializationContextFactory(
523 1
                $deserializationContextFactory,
524
            );
525 1
        } else {
526
            throw new InvalidArgumentException('expected DeserializationContextFactoryInterface or callable.');
527
        }
528
529 1
        return $this;
530
    }
531
532 1
    public function enableEnumSupport(bool $enableEnumSupport = true): self
533
    {
534
        if ($enableEnumSupport && PHP_VERSION_ID < 80100) {
535
            throw new InvalidArgumentException('Enum support can be enabled only on PHP 8.1 or higher.');
536
        }
537
538
        $this->enableEnumSupport = $enableEnumSupport;
539
540
        return $this;
541
    }
542
543
    public function setMetadataCache(CacheInterface $cache): self
544
    {
545
        $this->metadataCache = $cache;
546
547
        return $this;
548
    }
549
550
    public function setDocBlockTypeResolver(bool $docBlockTypeResolver): self
551
    {
552
        $this->docBlockTyperResolver = $docBlockTypeResolver;
553
554
        return $this;
555
    }
556
557
    public function build(): Serializer
558
    {
559
        $annotationReader = $this->annotationReader;
560
        if (null === $annotationReader && class_exists(AnnotationReader::class)) {
561
            $annotationReader = $this->decorateAnnotationReader(new AnnotationReader());
562
        }
563
564
        if (null === $this->driverFactory) {
565
            $this->initializePropertyNamingStrategy();
566
            $this->driverFactory = new DefaultDriverFactory(
567
                $this->propertyNamingStrategy,
568
                $this->typeParser,
569
                $this->expressionEvaluator instanceof CompilableExpressionEvaluatorInterface ? $this->expressionEvaluator : null,
570
            );
571
            $this->driverFactory->enableEnumSupport($this->enableEnumSupport);
572
        }
573
574
        if ($this->docBlockTyperResolver) {
575
            $this->driverFactory = new DocBlockDriverFactory($this->driverFactory, $this->typeParser);
576
        }
577
578
        $metadataDriver = $this->driverFactory->createDriver($this->metadataDirs, $annotationReader);
579
        $metadataFactory = new MetadataFactory($metadataDriver, null, $this->debug);
580
581
        $metadataFactory->setIncludeInterfaces($this->includeInterfaceMetadata);
582
583
        if (null !== $this->metadataCache) {
584
            $metadataFactory->setCache($this->metadataCache);
585
        } elseif (null !== $this->cacheDir) {
586
            $this->createDir($this->cacheDir . '/metadata');
587
            $metadataFactory->setCache(new FileCache($this->cacheDir . '/metadata'));
588
        }
589
590
        if (!$this->handlersConfigured) {
591
            $this->addDefaultHandlers();
592
        }
593
594
        if (!$this->listenersConfigured) {
595
            $this->addDefaultListeners();
596
        }
597
598
        if (!$this->serializationVisitorsAdded) {
599
            $this->addDefaultSerializationVisitors();
600
        }
601
602
        if (!$this->deserializationVisitorsAdded) {
603
            $this->addDefaultDeserializationVisitors();
604
        }
605
606
        $navigatorFactories = [
607
            GraphNavigatorInterface::DIRECTION_SERIALIZATION => $this->getSerializationNavigatorFactory($metadataFactory),
608
            GraphNavigatorInterface::DIRECTION_DESERIALIZATION => $this->getDeserializationNavigatorFactory($metadataFactory),
609
        ];
610
611
        return new Serializer(
612
            $metadataFactory,
613
            $navigatorFactories,
614
            $this->serializationVisitors,
615
            $this->deserializationVisitors,
616
            $this->serializationContextFactory,
617
            $this->deserializationContextFactory,
618
            $this->typeParser,
619
        );
620
    }
621
622
    private function getSerializationNavigatorFactory(MetadataFactoryInterface $metadataFactory): GraphNavigatorFactoryInterface
623
    {
624
        return new SerializationGraphNavigatorFactory(
625
            $metadataFactory,
626
            $this->handlerRegistry,
627
            $this->getAccessorStrategy(),
628
            $this->eventDispatcher,
629
            $this->expressionEvaluator,
630
        );
631
    }
632
633
    private function getDeserializationNavigatorFactory(MetadataFactoryInterface $metadataFactory): GraphNavigatorFactoryInterface
634
    {
635
        return new DeserializationGraphNavigatorFactory(
636
            $metadataFactory,
637
            $this->handlerRegistry,
638
            $this->objectConstructor ?: new UnserializeObjectConstructor(),
639
            $this->getAccessorStrategy(),
640
            $this->eventDispatcher,
641
            $this->expressionEvaluator,
642
        );
643
    }
644
645
    private function initializePropertyNamingStrategy(): void
646
    {
647
        if (null !== $this->propertyNamingStrategy) {
648
            return;
649
        }
650
651
        $this->propertyNamingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy());
652
    }
653
654
    private function createDir(string $dir): void
655
    {
656
        if (is_dir($dir)) {
657
            return;
658
        }
659
660
        if (false === @mkdir($dir, 0777, true) && false === is_dir($dir)) {
661
            throw new RuntimeException(sprintf('Could not create directory "%s".', $dir));
662
        }
663
    }
664
665
    private function decorateAnnotationReader(Reader $annotationReader): Reader
666
    {
667
        if (null !== $this->cacheDir) {
668
            $this->createDir($this->cacheDir . '/annotations');
669
            if (class_exists(FilesystemAdapter::class)) {
670
                $annotationsCache = new FilesystemAdapter('', 0, $this->cacheDir . '/annotations');
671
                $annotationReader = new PsrCachedReader($annotationReader, $annotationsCache, $this->debug);
672
            } elseif (class_exists(FilesystemCache::class) && class_exists(CachedReader::class)) {
673
                $annotationsCache = new FilesystemCache($this->cacheDir . '/annotations');
674
                $annotationReader = new CachedReader($annotationReader, $annotationsCache, $this->debug);
675
            }
676
        }
677
678
        return $annotationReader;
679
    }
680
}
681