Completed
Push — master ( 224f38...7a3326 )
by Asmir
38:41 queued 23:44
created

DefaultAccessorStrategy::getValue()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 44
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 10.4632

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 10
eloc 25
c 1
b 0
f 1
nc 9
nop 3
dl 0
loc 44
ccs 20
cts 24
cp 0.8333
crap 10.4632
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\CompilableExpressionEvaluatorInterface;
11
use JMS\Serializer\Expression\Expression;
12
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
13
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
14
use JMS\Serializer\Metadata\PropertyMetadata;
15
use JMS\Serializer\Metadata\StaticPropertyMetadata;
16
use JMS\Serializer\SerializationContext;
17
18
/**
19
 * @author Asmir Mustafic <[email protected]>
20
 */
21
final class DefaultAccessorStrategy implements AccessorStrategyInterface
22
{
23
    /**
24
     * @var callable[]
25
     */
26
    private $readAccessors = [];
27
28
    /**
29
     * @var callable[]
30 333
     */
31
    private $writeAccessors = [];
32 333
33 333
    /**
34
     * @var \ReflectionProperty[]
35 172
     */
36
    private $propertyReflectionCache = [];
37 172
38 15
    /**
39
     * @var ExpressionEvaluatorInterface
40
     */
41 168
    private $evaluator;
42 6
43 2
    public function __construct(?ExpressionEvaluatorInterface $evaluator = null)
44
    {
45 4
        $this->evaluator = $evaluator;
46
    }
47
48 164
49 158
    /**
50 158
     * {@inheritdoc}
51
     */
52
    public function getValue(object $object, PropertyMetadata $metadata, SerializationContext $context)
53 4
    {
54 4
        if ($metadata instanceof StaticPropertyMetadata) {
55 4
            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

55
            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...
56 4
        }
57 4
58
        if ($metadata instanceof ExpressionPropertyMetadata) {
59
            if (null === $this->evaluator) {
60 4
                throw new ExpressionLanguageRequiredException(sprintf('The property %s on %s requires the expression accessor strategy to be enabled.', $metadata->name, $metadata->class));
61 4
            }
62
63
            $variables = ['object' => $object, 'context' => $context, 'property_metadata' => $metadata];
64 156
65 156
            if (($metadata->expression instanceof Expression) && ($this->evaluator instanceof CompilableExpressionEvaluatorInterface)) {
66
                return $this->evaluator->evaluateParsed($metadata->expression, $variables);
67
            }
68
69 158
            return $this->evaluator->evaluate($metadata->expression, $variables);
70
        }
71
72 24
        if (null !== $metadata->getter) {
73
            return $object->{$metadata->getter}();
74
        }
75 64
76
        if ($metadata->forceReflectionAccess) {
77 64
            $ref = $this->propertyReflectionCache[$metadata->class][$metadata->name] ?? null;
78
            if (null === $ref) {
79
                $ref = new \ReflectionProperty($metadata->class, $metadata->name);
80
                $ref->setAccessible(true);
81 64
                $this->propertyReflectionCache[$metadata->class][$metadata->name] = $ref;
82 63
            }
83 63
84
            return $ref->getValue($object);
85 4
        }
86 4
87
        $accessor = $this->readAccessors[$metadata->class] ?? null;
88
        if (null === $accessor) {
89
            $accessor =\Closure::bind(static function ($o, $name) {
90
                return $o->$name;
91
            }, null, $metadata->class);
92 4
            $this->readAccessors[$metadata->class] = $accessor;
93 4
        }
94
95
        return $accessor($object, $metadata->name);
96 61
    }
97 61
98
    /**
99
     * {@inheritdoc}
100
     */
101 63
    public function setValue(object $object, $value, PropertyMetadata $metadata, DeserializationContext $context): void
102 63
    {
103
        if (true === $metadata->readOnly) {
104
            throw new LogicException(sprintf('%s on %s is read only.', $metadata->name, $metadata->class));
105 3
        }
106 3
107
        if (null !== $metadata->setter) {
108
            $object->{$metadata->setter}($value);
109
            return;
110
        }
111
112
        if ($metadata->forceReflectionAccess) {
113
            $ref = $this->propertyReflectionCache[$metadata->class][$metadata->name] ?? null;
114
            if (null === $ref) {
115
                $ref = new \ReflectionProperty($metadata->class, $metadata->name);
116
                $ref->setAccessible(true);
117
                $this->propertyReflectionCache[$metadata->class][$metadata->name] = $ref;
118
            }
119
120
            $ref->setValue($object, $value);
121
            return;
122
        }
123
124
        $accessor = $this->writeAccessors[$metadata->class] ?? null;
125
        if (null === $accessor) {
126
            $accessor = \Closure::bind(static function ($o, $name, $value): void {
127
                $o->$name = $value;
128
            }, null, $metadata->class);
129
            $this->writeAccessors[$metadata->class] = $accessor;
130
        }
131
        $accessor($object, $metadata->name, $value);
132
    }
133
}
134