Passed
Push — master ( cbecdb...34e2d9 )
by Arthur
07:30
created

Property::chainImmutable()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 9
c 0
b 0
f 0
rs 9.6111
cc 5
nc 5
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Larapie\DataTransferObject\Property;
6
7
use Larapie\DataTransferObject\Casters\TypeCaster;
8
use Larapie\DataTransferObject\DataTransferObject;
9
use Larapie\DataTransferObject\Violations\InvalidPropertyTypeViolation;
10
use Larapie\DataTransferObject\Violations\PropertyRequiredViolation;
11
use ReflectionProperty;
12
use Symfony\Component\Validator\ConstraintViolationList;
13
use Symfony\Component\Validator\ConstraintViolationListInterface;
14
use Symfony\Component\Validator\ValidatorBuilder;
15
16
class Property
17
{
18
    /** @var PropertyData */
19
    protected $data;
20
21
    /** @var mixed */
22
    public $value;
23
24
    /** @var bool */
25
    protected $initialized = false;
26
27
    /** @var bool */
28
    protected $visible = true;
29
30
    /** @var ConstraintViolationListInterface|null */
31
    protected $violations;
32
33
    /**
34
     * PropertyValue constructor.
35
     * @param ReflectionProperty $reflection
36
     */
37
    public function __construct(ReflectionProperty $reflection)
38
    {
39
        $this->boot($reflection);
40
    }
41
42
    public function boot(ReflectionProperty $property)
43
    {
44
        $this->data = new PropertyData($property);
45
        $this->initViolations();
46
    }
47
48
    protected function initViolations()
49
    {
50
        $this->setViolations(new ConstraintViolationList());
51
        if (! $this->data->isOptional()) {
52
            $this->violations->add(new PropertyRequiredViolation());
0 ignored issues
show
Bug introduced by
The method add() does not exist on null. ( Ignorable by Annotation )

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

52
            $this->violations->/** @scrutinizer ignore-call */ 
53
                               add(new PropertyRequiredViolation());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
53
        }
54
    }
55
56
    public function set($value): void
57
    {
58
        $value = (new TypeCaster($this->data->getType()))->cast($value);
59
        $this->value = $this->disableAutoValidation($value);
60
        $this->initialized = true;
61
        $this->setViolations($this->validate($value));
62
    }
63
64
    protected function disableAutoValidation($value)
65
    {
66
        if (is_iterable($value)) {
67
            $values = [];
68
            foreach ($value as $potentialDto) {
69
                if ($potentialDto instanceof DataTransferObject) {
70
                    $potentialDto->disableValidation();
71
                    $values[] = $potentialDto;
72
                }
73
            }
74
75
            return $values;
76
        } elseif ($value instanceof DataTransferObject) {
77
            $value->disableValidation();
78
        }
79
80
        return $value;
81
    }
82
83
    public function reset()
84
    {
85
        $this->value = null;
86
        $this->initialized = false;
87
        $this->initViolations();
88
    }
89
90
    public function isInitialized()
91
    {
92
        return $this->initialized;
93
    }
94
95
    public function validate($value): ?ConstraintViolationListInterface
96
    {
97
        $constraints = $this->data->getConstraints();
98
99
        $violations = (new ValidatorBuilder())->getValidator()->validate($value, $constraints);
100
101
        if (! $this->isInitialized() && ! $this->data->isOptional()) {
102
            $violations->add(new PropertyRequiredViolation());
103
        }
104
105
106
        if (! $this->data->getType()->isValid($value)) {
107
            $violations->add(new InvalidPropertyTypeViolation($this->data->getType()->getTypes()));
108
        }
109
110
        return $violations;
111
    }
112
113
    public function isValid()
114
    {
115
        return $this->violations === null || $this->violations->count() <= 0;
116
    }
117
118
    /**
119
     * @return ConstraintViolationListInterface|null
120
     */
121
    public function getViolations(): ?ConstraintViolationListInterface
122
    {
123
        return $this->violations;
124
    }
125
126
    public function setViolations(?ConstraintViolationListInterface $violationList): ?ConstraintViolationListInterface
127
    {
128
        return $this->violations = $violationList;
129
    }
130
131
    public function isImmutable()
132
    {
133
        return $this->data->isImmutable();
134
    }
135
136
    public function getValue()
137
    {
138
        return $this->value;
139
    }
140
141
    public function getName()
142
    {
143
        return $this->data->getName();
144
    }
145
146
    /**
147
     * @return bool
148
     */
149
    public function isVisible(): bool
150
    {
151
        return $this->visible;
152
    }
153
154
    /**
155
     * @param bool $visible
156
     */
157
    public function setVisible(bool $visible): void
158
    {
159
        $this->visible = $visible;
160
    }
161
162
    public function chainImmutable($immutable)
163
    {
164
        $dto = $this->getValue();
165
        if ($dto instanceof DataTransferObject) {
166
            $dto->setImmutable($immutable);
167
        } elseif (is_iterable($dto)) {
168
            foreach ($dto as $aPotentialDto) {
169
                if ($aPotentialDto instanceof DataTransferObject) {
170
                    $aPotentialDto->setImmutable($immutable);
171
                }
172
            }
173
        }
174
    }
175
}
176