Passed
Pull Request — master (#1487)
by Martin Poirier
03:02
created

DocBlockDriver::isNotSupportedVirtualProperty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JMS\Serializer\Metadata\Driver;
6
7
use JMS\Serializer\Metadata\ClassMetadata as SerializerClassMetadata;
8
use JMS\Serializer\Metadata\Driver\DocBlockDriver\DocBlockTypeResolver;
9
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
10
use JMS\Serializer\Metadata\PropertyMetadata;
11
use JMS\Serializer\Metadata\StaticPropertyMetadata;
12
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
13
use JMS\Serializer\Type\Parser;
14
use JMS\Serializer\Type\ParserInterface;
15
use Metadata\ClassMetadata;
16
use Metadata\Driver\DriverInterface;
17
use ReflectionClass;
18
use ReflectionException;
19
use ReflectionMethod;
20
use ReflectionProperty;
21
22
class DocBlockDriver implements DriverInterface
23
{
24
    /**
25
     * @var DriverInterface
26
     */
27
    protected $delegate;
28
29
    /**
30
     * @var ParserInterface
31
     */
32
    protected $typeParser;
33
    /**
34
     * @var DocBlockTypeResolver
35
     */
36
    private $docBlockTypeResolver;
37
38
    public function __construct(DriverInterface $delegate, ?ParserInterface $typeParser = null)
39
    {
40
        $this->delegate = $delegate;
41
        $this->typeParser = $typeParser ?: new Parser();
42
        $this->docBlockTypeResolver = new DocBlockTypeResolver();
43
    }
44
45
    public function loadMetadataForClass(ReflectionClass $class): ?ClassMetadata
46
    {
47
        $classMetadata = $this->delegate->loadMetadataForClass($class);
48
        \assert($classMetadata instanceof SerializerClassMetadata);
49
50
        if (null === $classMetadata) {
51
            return null;
52
        }
53
54
        // We base our scan on the internal driver's property list so that we
55
        // respect any internal allow/blocklist like in the AnnotationDriver
56
        foreach ($classMetadata->propertyMetadata as $key => $propertyMetadata) {
57
            // If the inner driver provides a type, don't guess anymore.
58
            if ($propertyMetadata->type) {
59
                continue;
60
            }
61
62
            if ($this->isNotSupportedVirtualProperty($propertyMetadata)) {
63
                continue;
64
            }
65
66
            try {
67
                if ($propertyMetadata instanceof VirtualPropertyMetadata) {
68
                    $type = $this->docBlockTypeResolver->getMethodDocblockTypeHint(
69
                        new ReflectionMethod($propertyMetadata->class, $propertyMetadata->getter)
70
                    );
71
                } else {
72
                    $type = $this->docBlockTypeResolver->getPropertyDocblockTypeHint(
73
                        new ReflectionProperty($propertyMetadata->class, $propertyMetadata->name)
74
                    );
75
                }
76
77
                if ($type) {
78
                    $propertyMetadata->setType($this->typeParser->parse($type));
79
                }
80
            } catch (ReflectionException $e) {
81
                continue;
82
            }
83
        }
84
85
        return $classMetadata;
86
    }
87
88
    private function isNotSupportedVirtualProperty(PropertyMetadata $propertyMetadata): bool
89
    {
90
        return $propertyMetadata instanceof StaticPropertyMetadata
91
            || $propertyMetadata instanceof ExpressionPropertyMetadata;
92
    }
93
}
94