Completed
Push — master ( e40538...145af3 )
by Julien
05:11
created

UnitOfWork::getDirtyEntity()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.1481

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 2
cts 3
cp 0.6667
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2.1481
1
<?php
2
3
namespace Mapado\RestClientSdk;
4
5
use Mapado\RestClientSdk\Helper\ArrayHelper;
6
use Mapado\RestClientSdk\Mapping;
7
use Mapado\RestClientSdk\Mapping\ClassMetadata;
8
use Mapado\RestClientSdk\Mapping\Relation;
9
10
/**
11
 * UnitOfWork
12
 */
13
class UnitOfWork
14
{
15
    /**
16
     * mapping
17
     *
18
     * @var Mapping
19
     * @access private
20
     */
21
    private $mapping;
22
23
    /**
24
     * storage for every entity retrieved
25
     *
26
     * @var array
27
     */
28
    private $storage;
29
30
    /**
31
     * Constructor.
32
     */
33
    public function __construct(Mapping $mapping)
34
    {
35 1
        $this->mapping = $mapping;
36 1
        $this->storage = [];
37 1
    }
38
39
    /**
40
     * getDirtyData
41
     *
42
     * return the new serialized model with only needed fields to update
43
     *
44
     * @param array $newSerializedModel
45
     * @param array $oldSerializedModel
46
     * @param ClassMetadata $classMetadata
47
     * @access public
48
     * @return array
49
     */
50
    public function getDirtyData(array $newSerializedModel, array $oldSerializedModel, ClassMetadata $classMetadata)
51
    {
52 1
        return $this->getDirtyFields($newSerializedModel, $oldSerializedModel, $classMetadata);
53
    }
54
55
    /**
56
     * registerClean
57
     *
58
     * @param string $id
59
     * @param object $entity
60
     * @access public
61
     * @return UnitOfWork
62
     */
63
    public function registerClean($id, $entity)
64
    {
65 1
        if (is_object($entity)) {
66 1
            $entityStored = clone $entity;
67 1
            $this->storage[$id] = $entityStored;
68
        }
69
70 1
        return $this;
71
    }
72
73
    /**
74
     * getDirtyEntity
75
     *
76
     * @param string $id
77
     * @access public
78
     * @return mixed
79
     */
80
    public function getDirtyEntity($id)
81
    {
82 1
        if (isset($this->storage[$id])) {
83 1
            return $this->storage[$id];
84
        }
85
        return null;
86
    }
87
88
    /**
89
     * clear
90
     *
91
     * @param string $id
92
     * @access public
93
     * @return UnitOfWork
94
     */
95
    public function clear($id)
96
    {
97
        unset($this->storage[$id]);
98
        return $this;
99
    }
100
101
    /**
102
     * getDirtyFields
103
     *
104
     * compares serialize object and returns only modified fields
105
     *
106
     * @param array $newSerializedModel
107
     * @param array $oldSerializedModel
108
     * @param ClassMetadata $classMetadata
109
     * @access private
110
     * @return array
111
     */
112
    private function getDirtyFields(array $newSerializedModel, array $oldSerializedModel, ClassMetadata $classMetadata = null)
113
    {
114 1
        $dirtyFields = [];
115
116 1
        foreach ($newSerializedModel as $key => $value) {
117 1
            if (!array_key_exists($key, $oldSerializedModel)) {
118
                // a new key has been found, add it to the dirtyFields
119 1
                $dirtyFields[$key] = $value;
120 1
                continue;
121
            }
122
123 1
            $oldValue = $oldSerializedModel[$key];
124
125 1
            $currentRelation = $classMetadata ? $classMetadata->getRelation($key) : null;
126
127 1
            if (!$currentRelation) {
128 1
                if (is_array($value) && !ArrayHelper::arraySame($value, $oldValue)
129 1
                    || $value != $oldValue
130
                ) {
131 1
                    $dirtyFields[$key] = $value;
132
                }
133 1
                continue;
134
            }
135
136 1
            $currentClassMetadata = $this->mapping->getClassMetadata($currentRelation->getTargetEntity());
137
138 1
            $idSerializedKey = $currentClassMetadata ? $currentClassMetadata->getIdSerializeKey() : null;
139
140 1
            if ($currentRelation->getType() === Relation::MANY_TO_ONE) {
141 1
                if ($value !== $oldValue) {
142 1
                    if (is_string($value) || is_string($oldValue)) {
143 1
                        $dirtyFields[$key] = $value;
144 View Code Duplication
                    } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145 1
                        $recursiveDiff = $this->getDirtyFields($value, $oldValue, $currentClassMetadata);
146
147 1
                        if (!empty($recursiveDiff)) {
148 1
                            $recursiveDiff[$idSerializedKey] = self::getEntityId($value, $idSerializedKey);
149 1
                            $dirtyFields[$key] = $recursiveDiff;
150
                        }
151
                    }
152
                }
153
154 1
                continue;
155
            }
156
157
            // ONE_TO_MANY relation
158
159 1
            if (count($value) != count($oldValue)) {
160
                // get all objects ids of new array
161 1
                $dirtyFields[$key] = $this->addIdentifiers($value, [], $idSerializedKey);
162
            }
163
164 1
            if (!empty($value)) {
165 1
                foreach ($value as $relationKey => $relationValue) {
166 1
                    $oldRelationValue = $this->findOldRelation($relationValue, $oldValue, $currentClassMetadata);
167
168
169 1
                    if ($relationValue !== $oldRelationValue) {
170 1
                        if (is_string($relationValue) || is_string($oldRelationValue)) {
171 1
                            $dirtyFields[$key][$relationKey] = $relationValue;
172
                        } else {
173 1
                            $recursiveDiff = $this->getDirtyFields($relationValue, $oldRelationValue, $currentClassMetadata);
174
175 1 View Code Duplication
                            if (!empty($recursiveDiff)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176 1
                                $idSerializedKey = $currentClassMetadata->getIdSerializeKey();
177
178 1
                                $recursiveDiff[$idSerializedKey] = self::getEntityId($relationValue, $idSerializedKey);
179 1
                                $dirtyFields[$key][$relationKey] = $recursiveDiff;
180
                            }
181
                        }
182
                    }
183
                }
184
            }
185
        }
186
187
188 1
        return $dirtyFields;
189
    }
190
191
    /**
192
     * addIdentifiers
193
     *
194
     * add defined identifiers to given model
195
     *
196
     * @param array $newSerializedModel
197
     * @param array $dirtyFields
198
     * @access private
199
     * @return array
200
     */
201
    private function addIdentifiers($newSerializedModel, $dirtyFields, $idSerializedKey = null)
202
    {
203 1
        foreach ($newSerializedModel as $key => $value) {
204 1
            if ($idSerializedKey && isset($value[$idSerializedKey])) {
205 1
                $dirtyFields[$key][$idSerializedKey] = $value[$idSerializedKey];
206 1
            } elseif (is_string($value) && is_int($key)) {
207 1
                $dirtyFields[$key] = $value;
208
            }
209
        }
210
211 1
        return $dirtyFields;
212
    }
213
214
    private function findOldRelation($relationValue, array $oldValue, ClassMetadata $classMetadata)
215
    {
216 1
        $idSerializedKey = $classMetadata->getIdSerializeKey();
217
218 1
        $relationValueId = self::getEntityId($relationValue, $idSerializedKey);
219
220 1
        foreach ($oldValue as $oldRelationValue) {
221 1
            $oldRelationValueId = self::getEntityId($oldRelationValue, $idSerializedKey);
222
223 1
            if ($relationValueId === $oldRelationValueId) {
224 1
                return $oldRelationValue;
225
            }
226
        }
227
228 1
        return [];
229
    }
230
231
    /**
232
     * get entity id from string or array
233
     * @param mixed $stringOrEntity
234
     * @param string $idSerializedKey
235
     */
236
    private static function getEntityId($stringOrEntity, $idSerializedKey)
237
    {
238 1
        if (!is_array($stringOrEntity)) {
239 1
            return $stringOrEntity;
240
        }
241
242 1
        return $stringOrEntity[$idSerializedKey];
243
    }
244
}
245