Completed
Push — master ( 622037...4b3bd1 )
by Asmir
06:56 queued 03:40
created

DefaultAccessorStrategy::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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\Exception\ExpressionLanguageRequiredException;
8
use JMS\Serializer\Exception\LogicException;
9
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
10
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
11
use JMS\Serializer\Metadata\PropertyMetadata;
12
use JMS\Serializer\Metadata\StaticPropertyMetadata;
13
14
/**
15
 * @author Asmir Mustafic <[email protected]>
16
 */
17
final class DefaultAccessorStrategy implements AccessorStrategyInterface
18
{
19
    private $readAccessors = [];
20
    private $writeAccessors = [];
21
    private $propertyReflectionCache = [];
22
23
    /**
24
     * @var ExpressionEvaluatorInterface
25
     */
26
    private $evaluator;
27
28 331
    public function __construct(ExpressionEvaluatorInterface $evaluator = null)
29
    {
30 331
        $this->evaluator = $evaluator;
31 331
    }
32
33 170
    public function getValue(object $object, PropertyMetadata $metadata)
34
    {
35 170
        if ($metadata instanceof StaticPropertyMetadata) {
36 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

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