Completed
Push — master ( a348db...6805c3 )
by Asmir
06:28
created

DefaultAccessorStrategy::getValue()   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 22
nc 7
nop 3
dl 0
loc 38
ccs 23
cts 23
cp 1
crap 8
rs 5.3846
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JMS\Serializer\Accessor;
6
7
use JMS\Serializer\DeserializationContext;
8
use JMS\Serializer\Exception\ExpressionLanguageRequiredException;
9
use JMS\Serializer\Exception\LogicException;
10
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
11
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
12
use JMS\Serializer\Metadata\PropertyMetadata;
13
use JMS\Serializer\Metadata\StaticPropertyMetadata;
14
use JMS\Serializer\SerializationContext;
15
16
/**
17
 * @author Asmir Mustafic <[email protected]>
18
 */
19
final class DefaultAccessorStrategy implements AccessorStrategyInterface
20
{
21
    private $readAccessors = [];
22
    private $writeAccessors = [];
23
    private $propertyReflectionCache = [];
24
25
    /**
26
     * @var ExpressionEvaluatorInterface
27
     */
28
    private $evaluator;
29
30 333
    public function __construct(ExpressionEvaluatorInterface $evaluator = null)
31
    {
32 333
        $this->evaluator = $evaluator;
33 333
    }
34
35 172
    public function getValue(object $object, PropertyMetadata $metadata, SerializationContext $context)
36
    {
37 172
        if ($metadata instanceof StaticPropertyMetadata) {
38 15
            return $metadata->getValue(null);
0 ignored issues
show
Unused Code introduced by
The call to JMS\Serializer\Metadata\...rtyMetadata::getValue() has too many arguments starting with null. ( Ignorable by Annotation )

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

38
            return $metadata->/** @scrutinizer ignore-call */ getValue(null);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
39
        }
40
41 168
        if ($metadata instanceof ExpressionPropertyMetadata) {
42 6
            if ($this->evaluator === null) {
43 2
                throw new ExpressionLanguageRequiredException(sprintf('The property %s on %s requires the expression accessor strategy to be enabled.', $metadata->name, $metadata->class));
44
            }
45 4
            return $this->evaluator->evaluate($metadata->expression, ['object' => $object, 'context' => $context, 'property_metadata' => $metadata ]);
46
        }
47
48 164
        if (null === $metadata->getter) {
49 158
            if (!isset($this->readAccessors[$metadata->class])) {
50 158
                if ($metadata->forceReflectionAccess === true) {
51 4
                    $this->readAccessors[$metadata->class] = function ($o, $name) use ($metadata) {
52
53 4
                        $ref = $this->propertyReflectionCache[$metadata->class][$name] ?? null;
54 4
                        if ($ref === null) {
55 4
                            $ref = new \ReflectionProperty($metadata->class, $name);
56 4
                            $ref->setAccessible(true);
57 4
                            $this->propertyReflectionCache[$metadata->class][$name] = $ref;
58
                        }
59
60 4
                        return $ref->getValue($o);
61 4
                    };
62
                } else {
63 156
                    $this->readAccessors[$metadata->class] = \Closure::bind(function ($o, $name) {
64 156
                        return $o->$name;
65 156
                    }, null, $metadata->class);
66
                }
67
            }
68
69 158
            return $this->readAccessors[$metadata->class]($object, $metadata->name);
70
        }
71
72 24
        return $object->{$metadata->getter}();
73
    }
74
75 64
    public function setValue(object $object, $value, PropertyMetadata $metadata, DeserializationContext $context): void
76
    {
77 64
        if ($metadata->readOnly) {
78
            throw new LogicException(sprintf('%s on %s is read only.', $metadata->name, $metadata->class));
79
        }
80
81 64
        if (null === $metadata->setter) {
82 63
            if (!isset($this->writeAccessors[$metadata->class])) {
83 63
                if ($metadata->forceReflectionAccess === true) {
84 4
                    $this->writeAccessors[$metadata->class] = function ($o, $name, $value) use ($metadata) {
85 4
                        $ref = $this->propertyReflectionCache[$metadata->class][$name] ?? null;
86 4
                        if ($ref === null) {
87
                            $ref = new \ReflectionProperty($metadata->class, $name);
88
                            $ref->setAccessible(true);
89
                            $this->propertyReflectionCache[$metadata->class][$name] = $ref;
90
                        }
91
92 4
                        $ref->setValue($o, $value);
93 4
                    };
94
                } else {
95 61
                    $this->writeAccessors[$metadata->class] = \Closure::bind(function ($o, $name, $value) {
96 61
                        $o->$name = $value;
97 61
                    }, null, $metadata->class);
98
                }
99
            }
100
101 63
            $this->writeAccessors[$metadata->class]($object, $metadata->name, $value);
102 63
            return;
103
        }
104
105 3
        $object->{$metadata->setter}($value);
106 3
    }
107
}
108