Completed
Push — master ( b48dc5...46c1ee )
by Marcin
22s queued 19s
created

SerializerBuilder::setMetadataDirs()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
crap 3.0416
rs 10
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\Naming\CamelCaseNamingStrategy;
42
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
43
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
44
use JMS\Serializer\Type\Parser;
45
use JMS\Serializer\Type\ParserInterface;
46
use JMS\Serializer\Visitor\Factory\DeserializationVisitorFactory;
47
use JMS\Serializer\Visitor\Factory\JsonDeserializationVisitorFactory;
48
use JMS\Serializer\Visitor\Factory\JsonSerializationVisitorFactory;
49
use JMS\Serializer\Visitor\Factory\SerializationVisitorFactory;
50
use JMS\Serializer\Visitor\Factory\XmlDeserializationVisitorFactory;
51
use JMS\Serializer\Visitor\Factory\XmlSerializationVisitorFactory;
52
use Metadata\Cache\CacheInterface;
53
use Metadata\Cache\FileCache;
54
use Metadata\MetadataFactory;
55
use Metadata\MetadataFactoryInterface;
56
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
57
58
/**
59
 * Builder for serializer instances.
60
 *
61
 * This object makes serializer construction a breeze for projects that do not use
62
 * any special dependency injection container.
63
 *
64
 * @author Johannes M. Schmitt <[email protected]>
65
 */
66
final class SerializerBuilder
67
{
68
    /**
69
     * @var string[]
70
     */
71
    private $metadataDirs = [];
72
73
    /**
74
     * @var HandlerRegistryInterface
75
     */
76
    private $handlerRegistry;
77
78
    /**
79
     * @var bool
80
     */
81
    private $handlersConfigured = false;
82
83
    /**
84
     * @var EventDispatcherInterface
85
     */
86
    private $eventDispatcher;
87
88
    /**
89
     * @var bool
90
     */
91
    private $enableEnumSupport = false;
92
93
    /**
94
     * @var bool
95
     */
96 330
    private $listenersConfigured = false;
97
98 330
    /**
99
     * @var ObjectConstructorInterface
100
     */
101 330
    private $objectConstructor;
102
103 330
    /**
104 330
     * @var SerializationVisitorFactory[]
105 330
     */
106 330
    private $serializationVisitors;
107 330
108
    /**
109 330
     * @var DeserializationVisitorFactory[]
110 284
     */
111
    private $deserializationVisitors;
112 330
113 284
    /**
114
     * @var bool
115 330
     */
116
    private $deserializationVisitorsAdded = false;
117
118
    /**
119
     * @var bool
120
     */
121
    private $serializationVisitorsAdded = false;
122
123 330
    /**
124
     * @var PropertyNamingStrategyInterface
125 330
     */
126 330
    private $propertyNamingStrategy;
127
128 330
    /**
129
     * @var bool
130
     */
131 25
    private $debug = false;
132
133 25
    /**
134
     * @var string
135 25
     */
136
    private $cacheDir;
137
138 1
    /**
139
     * @var Reader
140 1
     */
141
    private $annotationReader;
142 1
143
    /**
144
     * @var bool
145
     */
146
    private $includeInterfaceMetadata = false;
147
148
    /**
149
     * @var DriverFactoryInterface
150
     */
151
    private $driverFactory;
152
153
    /**
154
     * @var SerializationContextFactoryInterface
155
     */
156
    private $serializationContextFactory;
157
158
    /**
159 1
     * @var DeserializationContextFactoryInterface
160
     */
161 1
    private $deserializationContextFactory;
162 1
163
    /**
164 1
     * @var ParserInterface
165
     */
166
    private $typeParser;
167
168 1
    /**
169
     * @var ExpressionEvaluatorInterface
170 1
     */
171
    private $expressionEvaluator;
172
173 71
    /**
174
     * @var AccessorStrategyInterface
175 71
     */
176 71
    private $accessorStrategy;
177 71
178 71
    /**
179
     * @var CacheInterface
180 71
     */
181
    private $metadataCache;
182
183 3
    /**
184
     * @var bool
185 3
     */
186 3
    private $docBlockTyperResolver;
187
188 3
    /**
189
     * @param mixed ...$args
190
     *
191 73
     * @return SerializerBuilder
192
     */
193 73
    public static function create(...$args): self
194 73
    {
195
        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

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