Passed
Push — dev_2x ( 241dab...1e248d )
by Adrian
01:59
created

GenericHydrator   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 21
eloc 37
c 1
b 0
f 0
dl 0
loc 137
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getMapperConfig() 0 3 1
A hydrate() 0 13 2
A setMapper() 0 3 1
A __construct() 0 3 1
A setPk() 0 3 1
A set() 0 7 2
A getPk() 0 3 1
A extract() 0 12 2
B compileRelations() 0 21 9
A get() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm\Entity;
5
6
use Sirius\Orm\CastingManager;
7
use Sirius\Orm\Contract\EntityInterface;
8
use Sirius\Orm\Contract\HydratorInterface;
9
use Sirius\Orm\Contract\LazyLoader;
10
use Sirius\Orm\Contract\Relation\ToManyInterface;
11
use Sirius\Orm\Contract\Relation\ToOneInterface;
12
use Sirius\Orm\Helpers\Arr;
13
use Sirius\Orm\Mapper;
14
use Sirius\Orm\MapperConfig;
15
16
class GenericHydrator implements HydratorInterface
17
{
18
    /**
19
     * @var CastingManager
20
     */
21
    protected $castingManager;
22
23
    /**
24
     * @var Mapper
25
     */
26
    protected $mapper;
27
28
    public function __construct(CastingManager $castingManager)
29
    {
30
        $this->castingManager = $castingManager;
31
    }
32
33
    public function setMapper(Mapper $mapper)
34
    {
35
        $this->mapper = $mapper;
36
    }
37
38
    /**
39
     * @param array $attributes
40
     *
41
     * @return mixed|GenericEntity
42
     */
43
    public function hydrate(array $attributes = [])
44
    {
45
        $attributes = Arr::renameKeys($attributes, $this->getMapperConfig()->getColumnAttributeMap());
46
        if ($this->castingManager) {
47
            $attributes = $this->castingManager
48
                ->castArray($attributes, $this->getMapperConfig()->getCasts());
49
        }
50
51
        $attributes = $this->compileRelations($attributes);
52
53
        $class = $this->getMapperConfig()->getEntityClass() ?? GenericEntity::class;
54
55
        return new $class($attributes);
56
    }
57
58
    /**
59
     * @param EntityInterface $entity
60
     *
61
     * @return array
62
     */
63
    public function extract(EntityInterface $entity)
64
    {
65
        $data = Arr::renameKeys(
66
            $entity->toArray(),
67
            array_flip($this->getMapperConfig()->getColumnAttributeMap())
68
        );
69
        if ($this->castingManager) {
70
            $data = $this->castingManager
71
                ->castArrayForDb($data, $this->getMapperConfig()->getCasts());
72
        }
73
74
        return Arr::only($data, $this->getMapperConfig()->getColumns());
75
    }
76
77
    /**
78
     * @param $entity
79
     * @param $attribute
80
     *
81
     * @return mixed
82
     */
83
    public function get(EntityInterface $entity, $attribute)
84
    {
85
        return $entity->{$attribute};
86
    }
87
88
    /**
89
     * @param $entity
90
     * @param $attribute
91
     * @param $value
92
     *
93
     * @return mixed
94
     */
95
    public function set(EntityInterface $entity, $attribute, $value)
96
    {
97
        if ($value instanceof LazyLoader) {
98
            return $entity->setLazy($attribute, $value);
99
        }
100
101
        return $entity->{$attribute} = $value;
102
    }
103
104
    /**
105
     * @param $entity
106
     *
107
     * @return mixed
108
     */
109
    public function getPk($entity)
110
    {
111
        return $this->get($entity, $this->getMapperConfig()->getPrimaryKey());
112
    }
113
114
    /**
115
     * Set primary key on an entity
116
     *
117
     * @param $entity
118
     * @param $value
119
     *
120
     * @return mixed
121
     */
122
    public function setPk($entity, $value)
123
    {
124
        return $this->set($entity, $this->getMapperConfig()->getPrimaryKey(), $value);
125
    }
126
127
    protected function compileRelations(array $attributes)
128
    {
129
        foreach ($this->mapper->getRelations() as $name) {
130
            $relation = $this->mapper->getRelation($name);
131
            if ($relation instanceof ToOneInterface &&
132
                isset($attributes[$name]) &&
133
                ! is_object($attributes[$name])) {
134
                $attributes[$name] = $relation->getForeignMapper()->newEntity($attributes[$name]);
135
            } elseif ($relation instanceof ToManyInterface &&
136
                      ! $relation instanceof ToOneInterface
137
                      && ( ! isset($attributes[$name]) || is_array($attributes[$name]))) {
138
                /**
139
                 * we also need to check against ToOneInterface because OneToOne relation extends
140
                 * OneToMany which implements ToOneInterface
141
                 * @todo remove this quirk
142
                 */
143
                $attributes[$name] = $relation->getForeignMapper()->newCollection($attributes[$name] ?? []);
144
            }
145
        }
146
147
        return $attributes;
148
    }
149
150
    protected function getMapperConfig(): MapperConfig
151
    {
152
        return $this->mapper->getConfig();
153
    }
154
}
155