Completed
Pull Request — master (#1289)
by Johannes
13:58
created

DocBlockDriver::getReflection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
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\ExpressionPropertyMetadata;
9
use JMS\Serializer\Metadata\PropertyMetadata;
10
use JMS\Serializer\Metadata\StaticPropertyMetadata;
11
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
12
use JMS\Serializer\Type\Parser;
13
use JMS\Serializer\Type\ParserInterface;
14
use Metadata\ClassMetadata;
15
use Metadata\Driver\DriverInterface;
16
use ReflectionClass;
17
use ReflectionException;
18
use ReflectionProperty;
19
20
class DocBlockDriver implements DriverInterface
21
{
22
    /**
23
     * @var DriverInterface
24
     */
25
    protected $delegate;
26
27
    /**
28
     * @var ParserInterface
29
     */
30
    protected $typeParser;
31
    /**
32
     * @var DocBlockTypeResolver
33
     */
34
    private $docBlockTypeResolver;
35
36
    public function __construct(DriverInterface $delegate, ?ParserInterface $typeParser = null)
37
    {
38
        $this->delegate = $delegate;
39
        $this->typeParser = $typeParser ?: new Parser();
40
        $this->docBlockTypeResolver = new DocBlockTypeResolver();
41
    }
42
43
    public function loadMetadataForClass(ReflectionClass $class): ?ClassMetadata
44
    {
45
        $classMetadata = $this->delegate->loadMetadataForClass($class);
46
        \assert($classMetadata instanceof SerializerClassMetadata);
47
48
        if (null === $classMetadata) {
49
            return null;
50
        }
51
52
        // We base our scan on the internal driver's property list so that we
53
        // respect any internal white/blacklisting like in the AnnotationDriver
54
        foreach ($classMetadata->propertyMetadata as $key => $propertyMetadata) {
55
            // If the inner driver provides a type, don't guess anymore.
56
            if ($propertyMetadata->type || $this->isVirtualProperty($propertyMetadata)) {
57
                continue;
58
            }
59
60
            try {
61
                $propertyReflection = $this->getReflection($propertyMetadata);
62
63
                $type = $this->docBlockTypeResolver->getPropertyDocblockTypeHint($propertyReflection);
64
                if ($type) {
65
                    $propertyMetadata->setType($this->typeParser->parse($type));
0 ignored issues
show
introduced by
The method setType() does not exist on Metadata\PropertyMetadata. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

65
                    $propertyMetadata->/** @scrutinizer ignore-call */ 
66
                                       setType($this->typeParser->parse($type));
Loading history...
66
                }
67
            } catch (ReflectionException $e) {
68
                continue;
69
            }
70
        }
71
72
        return $classMetadata;
73
    }
74
75
    private function isVirtualProperty(PropertyMetadata $propertyMetadata): bool
76
    {
77
        return $propertyMetadata instanceof VirtualPropertyMetadata
78
            || $propertyMetadata instanceof StaticPropertyMetadata
79
            || $propertyMetadata instanceof ExpressionPropertyMetadata;
80
    }
81
82
    private function getReflection(PropertyMetadata $propertyMetadata): ReflectionProperty
83
    {
84
        return new ReflectionProperty($propertyMetadata->class, $propertyMetadata->name);
85
    }
86
}
87