Passed
Push — dev_2x ( fedccd...fb9ebe )
by Adrian
02:16
created

Mapper::patch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm;
5
6
use Sirius\Orm\Behaviour\BehaviourInterface;
7
use Sirius\Orm\Collection\Collection;
8
use Sirius\Orm\Contract\EntityInterface;
9
use Sirius\Orm\Contract\HydratorInterface;
10
use Sirius\Orm\Entity\GenericHydrator;
11
use Sirius\Orm\Entity\Patcher;
12
use Sirius\Orm\Relation\Relation;
13
14
/**
15
 * @method Query where($column, $value, $condition)
16
 * @method Query orderBy(string $expr, string ...$exprs)
17
 */
18
class Mapper
19
{
20
    /**
21
     * @var Orm
22
     */
23
    protected $orm;
24
25
    /**
26
     * @var ConnectionLocator
27
     */
28
    protected $connectionLocator;
29
30
    /**
31
     * @var MapperConfig
32
     */
33
    protected $mapperConfig;
34
35
    /**
36
     * @var HydratorInterface
37
     */
38
    protected $hydrator;
39
40
    /**
41
     * @var Behaviours
42
     */
43
    protected $behaviours;
44
45
    /**
46
     * @var array
47
     */
48
    protected $relations = [];
49
50
    public function __construct(Orm $orm)
51
    {
52
        $this->orm               = $orm;
53
        $this->connectionLocator = $orm->getConnectionLocator();
54
        $this->behaviours        = new Behaviours();
55
        $this->hydrator          = new GenericHydrator($this->orm->getCastingManager());
56
        $this->init();
57
    }
58
59
    protected function init()
60
    {
61
    }
62
63
    public function __call(string $method, array $params)
64
    {
65
        switch ($method) {
66
            case 'where':
67
            case 'orderBy':
68
                $query = $this->newQuery();
69
70
                return $query->{$method}(...$params);
71
        }
72
73
        throw new \BadMethodCallException("Unknown method {$method} for class " . get_class($this));
74
    }
75
76
    /**
77
     * @return MapperConfig
78
     */
79
    public function getConfig(): MapperConfig
80
    {
81
        return $this->mapperConfig;
82
    }
83
84
    /**
85
     * @return HydratorInterface
86
     */
87
    public function getHydrator(): HydratorInterface
88
    {
89
        return $this->hydrator;
90
    }
91
92
    /**
93
     * Add behaviours to the mapper
94
     *
95
     * @param mixed ...$behaviours
96
     */
97
    public function use(...$behaviours)
98
    {
99
        /** @var BehaviourInterface $behaviour */
100
        foreach ($behaviours as $behaviour) {
101
            $this->behaviours->add($behaviour);
102
        }
103
    }
104
105
    /**
106
     * Create a clone of the mapper without the selected behaviour
107
     *
108
     * @param mixed ...$behaviours
109
     *
110
     * @return self
111
     */
112
    public function without(...$behaviours)
113
    {
114
        $mapper             = clone $this;
115
        $mapper->behaviours = $this->behaviours->without(...$behaviours);
116
117
        return $mapper;
118
    }
119
120
    public function addQueryScope($scope, callable $callback)
121
    {
122
        $this->mapperConfig->addQueryScope($scope, $callback);
0 ignored issues
show
Bug introduced by
The method addQueryScope() does not exist on Sirius\Orm\MapperConfig. ( Ignorable by Annotation )

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

122
        $this->mapperConfig->/** @scrutinizer ignore-call */ 
123
                             addQueryScope($scope, $callback);

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...
123
    }
124
125
    public function newEntity(array $data): EntityInterface
126
    {
127
        $entity = $this->getHydrator()
128
                       ->hydrate(array_merge(
129
                           $this->getConfig()->getAttributeDefaults(),
130
                           $data
131
                       ));
132
133
        return $this->behaviours->apply($this, __FUNCTION__, $entity);
134
    }
135
136
    public function newCollection(array $datas = []): Collection
137
    {
138
        $entities = [];
139
        foreach ($datas as $data) {
140
            // if $data is an entity or some other object, keep it as is
141
            $entities[] = (is_array($data)) ? $this->newEntity($data) : $data;
142
        }
143
144
        return new Collection($entities, $this->hydrator);
145
    }
146
147
    public function patch($entity, array $data)
148
    {
149
        return (new Patcher($this))($entity, $data);
150
    }
151
152
    /**
153
     * @param string $name
154
     * @param array|Relation $relation
155
     */
156
    public function addRelation(string $name, $relation)
157
    {
158
        if (is_array($relation) || $relation instanceof Relation) {
0 ignored issues
show
introduced by
$relation is always a sub-type of Sirius\Orm\Relation\Relation.
Loading history...
159
            $this->relations[$name] = $relation;
160
161
            return;
162
        }
163
        throw new \InvalidArgumentException(
164
            sprintf('The relation has to be a Relation instance or an array of configuration options')
165
        );
166
    }
167
168
    public function hasRelation(string $name): bool
169
    {
170
        return isset($this->relations[$name]);
171
    }
172
173
    public function getRelation(string $name): Relation
174
    {
175
        if (! $this->hasRelation($name)) {
176
            throw new \InvalidArgumentException("Relation named {$name} is not registered for this mapper");
177
        }
178
179
        if (is_array($this->relations[$name])) {
180
            $this->relations[$name] = $this->orm->createRelation($this, $name, $this->relations[$name]);
181
        }
182
183
        return $this->relations[$name];
184
    }
185
186
    public function getRelations(): array
187
    {
188
        return array_keys($this->relations);
189
    }
190
191
    /**
192
     * @return Query
193
     */
194
    public function newQuery()
195
    {
196
        $query = new Query($this->getReadConnection(), $this);
197
198
        return $this->behaviours->apply($this, __FUNCTION__, $query);
199
    }
200
201
    public function getReadConnection(): Connection
202
    {
203
        return $this->connectionLocator->getRead();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->connectionLocator->getRead() returns the type Atlas\Pdo\Connection which includes types incompatible with the type-hinted return Sirius\Orm\Connection.
Loading history...
204
    }
205
206
    public function getWriteConnection(): Connection
207
    {
208
        return $this->connectionLocator->getWrite();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->connectionLocator->getWrite() returns the type Atlas\Pdo\Connection which includes types incompatible with the type-hinted return Sirius\Orm\Connection.
Loading history...
209
    }
210
}
211