Passed
Push — master ( 0756fe...706dc7 )
by Arthur
14:47
created

PropertyFactory::getFreshProperties()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
4
namespace Larapie\DataTransferObject\Factories;
5
6
7
use Larapie\DataTransferObject\Contracts\AdditionalProperties;
8
use Larapie\DataTransferObject\Contracts\DtoContract;
9
use Larapie\DataTransferObject\Contracts\WithAdditionalProperties;
10
use Larapie\DataTransferObject\Exceptions\UnknownPropertiesDtoException;
11
use Larapie\DataTransferObject\Property;
12
use ReflectionClass;
13
use ReflectionProperty;
14
15
class PropertyFactory
16
{
17
    /**
18
     * @var DtoContract
19
     */
20
    protected $dto;
21
22
    /**
23
     * @var Property[] $cache
24
     */
25
    private static $cache = [];
26
27
    /**
28
     * PropertyValueFactory constructor.
29
     * @param DtoContract $dto
30
     */
31
    public function __construct(DtoContract &$dto)
32
    {
33
        $this->dto = $dto;
34
    }
35
36
    public function build(array $parameters)
37
    {
38
        $properties = [];
39
        foreach ($this->buildPublicProperties() as $property) {
40
41
            if (array_key_exists($property->getName(), $parameters)) {
42
                $property->set($parameters[$property->getName()]);
43
            }
44
45
            /* add the property to an associative array with the name as key */
46
            $properties[$property->getName()] = $property;
47
48
            /* remove the property from the value object and parameters array  */
49
            unset($parameters[$property->getName()], $this->dto->{$property->getName()});
50
        }
51
52
        $this->checkRemainingProperties($parameters);
53
54
        return $properties;
55
    }
56
57
    protected function getDtoClass(): string
58
    {
59
        return get_class($this->dto);
60
    }
61
62
    protected function buildPublicProperties(): array
63
    {
64
        if (!isset(self::$cache[$this->getDtoClass()])) {
65
            $class = new ReflectionClass($this->dto);
66
67
            $properties = [];
68
            foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $reflectionProperty) {
69
                $property = new Property($reflectionProperty);
70
71
                //Set default value
72
                if (($default = $reflectionProperty->getValue($this->dto)) !== null)
0 ignored issues
show
Unused Code introduced by
The assignment to $default is dead and can be removed.
Loading history...
73
                    $property->set($reflectionProperty->getValue($this->dto));
74
75
                $properties[$reflectionProperty->getName()] = $property;
76
            }
77
            self::$cache[$this->getDtoClass()] = $properties;
78
            return $properties;
79
        }
80
        return $this->getFreshProperties();
81
    }
82
83
    protected function getFreshProperties()
84
    {
85
        $properties = [];
86
        foreach (self::$cache[$this->getDtoClass()] as $key => $property) {
87
            $property = clone $property;
88
            $property->reset();
89
            $properties[$key] = $property;
90
        }
91
        return $properties;
92
    }
93
94
    protected function checkRemainingProperties(array $parameters)
95
    {
96
        if (empty($parameters))
97
            return;
98
        elseif ($this instanceof WithAdditionalProperties) {
99
            foreach ($parameters as $name => $parameter) {
100
                $this->dto->with($name, $parameter);
101
            }
102
        } elseif ($this instanceof AdditionalProperties)
103
            return;
104
        throw new UnknownPropertiesDtoException($parameters, $this->getDtoClass());
105
    }
106
107
108
}