1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @link https://github.com/nnx-framework/form-comparator |
4
|
|
|
* @author Malofeykin Andrey <[email protected]> |
5
|
|
|
*/ |
6
|
|
|
namespace Nnx\FormComparator\Comparator; |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
use Nnx\FormComparator\Comparator\CollectionDiffService\HashElementBuilder; |
10
|
|
|
use Nnx\FormComparator\Comparator\Diff\DeletedCollectionElement; |
11
|
|
|
use Nnx\FormComparator\Comparator\Diff\InsertCollectionElement; |
12
|
|
|
use Webmozart\Assert\Assert; |
13
|
|
|
use Zend\Form\Element\Collection; |
14
|
|
|
use Zend\Form\ElementInterface; |
15
|
|
|
|
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class CollectionDiffService |
19
|
|
|
* |
20
|
|
|
* @package Nnx\FormComparator\Comparator |
21
|
|
|
*/ |
22
|
|
|
class CollectionDiffService |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* Компоент отвечающий за подготовку хеша элемента |
26
|
|
|
* |
27
|
|
|
* @var HashElementBuilder |
28
|
|
|
*/ |
29
|
|
|
private $hashElementBuilder; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Возвращает компоент отвечающий за подготовку хеша элемента |
33
|
|
|
* |
34
|
|
|
* @return HashElementBuilder |
35
|
|
|
*/ |
36
|
|
|
public function getHashElementBuilder() |
37
|
|
|
{ |
38
|
|
|
if (null === $this->hashElementBuilder) { |
39
|
|
|
$this->hashElementBuilder = new HashElementBuilder(); |
40
|
|
|
} |
41
|
|
|
return $this->hashElementBuilder; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Устанавливает компоент отвечающий за подготовку хеша элемента |
46
|
|
|
* |
47
|
|
|
* @param HashElementBuilder $hashElementBuilder |
48
|
|
|
* |
49
|
|
|
* @return $this |
50
|
|
|
*/ |
51
|
|
|
public function setHashElementBuilder(HashElementBuilder $hashElementBuilder) |
52
|
|
|
{ |
53
|
|
|
$this->hashElementBuilder = $hashElementBuilder; |
54
|
|
|
|
55
|
|
|
return $this; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Подготавливает объекты описывающие элементы добавленной коллекции |
60
|
|
|
* |
61
|
|
|
* @param Collection $insertedCollection |
62
|
|
|
* @param $prefixPath |
63
|
|
|
* |
64
|
|
|
* @return InsertCollectionElement[] |
65
|
|
|
* @throws \Nnx\FormComparator\Comparator\Exception\DomainException |
66
|
|
|
* @throws \Nnx\FormComparator\Comparator\CollectionDiffService\Exception\RuntimeException |
67
|
|
|
*/ |
68
|
|
View Code Duplication |
public function buildDiffInsertedCollection(Collection $insertedCollection, $prefixPath) |
|
|
|
|
69
|
|
|
{ |
70
|
|
|
Assert::string($prefixPath); |
71
|
|
|
Assert::notEmpty($prefixPath); |
72
|
|
|
|
73
|
|
|
$collectionElementsInfo = $this->buildInfoForCollectionElements($insertedCollection, $prefixPath); |
74
|
|
|
|
75
|
|
|
$diff = []; |
76
|
|
|
|
77
|
|
|
foreach ($collectionElementsInfo as $rowUniqueId => $info) { |
78
|
|
|
$builder = $this->diffCollectionElementBuilderFactory(DiffCollectionElementBuilder::INSERT_ELEMENT_MODE); |
79
|
|
|
$builder->setSourceHash($info['hash']) |
80
|
|
|
->setRowIndex($info['rowIndex']) |
81
|
|
|
->setSourceCollectionElement($info['element']) |
82
|
|
|
->setUniqueRowId($info['rowUniqueId']) |
83
|
|
|
->setPathToElement($info['pathToElement']); |
84
|
|
|
$diff[] = $builder->build(); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
return $diff; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Подготавливает объекты описывающие элементы удаленной коллекции |
92
|
|
|
* |
93
|
|
|
* @param Collection $deletedCollection |
94
|
|
|
* @param $prefixPath |
95
|
|
|
* |
96
|
|
|
* @return DeletedCollectionElement[] |
97
|
|
|
* @throws \Nnx\FormComparator\Comparator\Exception\DomainException |
98
|
|
|
* @throws \Nnx\FormComparator\Comparator\CollectionDiffService\Exception\RuntimeException |
99
|
|
|
*/ |
100
|
|
View Code Duplication |
public function buildDiffDeletedCollection(Collection $deletedCollection, $prefixPath) |
|
|
|
|
101
|
|
|
{ |
102
|
|
|
Assert::string($prefixPath); |
103
|
|
|
Assert::notEmpty($prefixPath); |
104
|
|
|
|
105
|
|
|
$collectionElementsInfo = $this->buildInfoForCollectionElements($deletedCollection, $prefixPath); |
106
|
|
|
|
107
|
|
|
$diff = []; |
108
|
|
|
|
109
|
|
|
foreach ($collectionElementsInfo as $rowUniqueId => $info) { |
110
|
|
|
$builder = $this->diffCollectionElementBuilderFactory(DiffCollectionElementBuilder::DELETE_ELEMENT_MODE); |
111
|
|
|
$builder->setSourceHash($info['hash']) |
112
|
|
|
->setRowIndex($info['rowIndex']) |
113
|
|
|
->setSourceCollectionElement($info['element']) |
114
|
|
|
->setUniqueRowId($info['rowUniqueId']) |
115
|
|
|
->setPathToElement($info['pathToElement']); |
116
|
|
|
$diff[] = $builder->build(); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return $diff; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Получение расхождения элементов меджу двумя коллекциями |
125
|
|
|
* |
126
|
|
|
* @param Collection $sourceCollection |
127
|
|
|
* @param Collection $targetCollection |
128
|
|
|
* |
129
|
|
|
* @param $prefixPath |
130
|
|
|
* |
131
|
|
|
* @return mixed |
132
|
|
|
* @throws \Nnx\FormComparator\Comparator\Exception\DomainException |
133
|
|
|
* @throws \Nnx\FormComparator\Comparator\CollectionDiffService\Exception\RuntimeException |
134
|
|
|
*/ |
135
|
|
|
public function buildDiffUpdatedCollection(Collection $sourceCollection, Collection $targetCollection, $prefixPath) |
136
|
|
|
{ |
137
|
|
|
Assert::string($prefixPath); |
138
|
|
|
Assert::notEmpty($prefixPath); |
139
|
|
|
|
140
|
|
|
$sourceCollectionElementsInfo = $this->buildInfoForCollectionElements($sourceCollection, $prefixPath); |
141
|
|
|
$targetCollectionElementsInfo = $this->buildInfoForCollectionElements($targetCollection, $prefixPath); |
142
|
|
|
|
143
|
|
|
|
144
|
|
|
$diff = []; |
145
|
|
|
foreach ($sourceCollectionElementsInfo as $rowUniqueId => $sourceInfo) { |
146
|
|
|
if (array_key_exists($rowUniqueId, $targetCollectionElementsInfo)) { |
147
|
|
|
$targetInfo = $targetCollectionElementsInfo[$rowUniqueId]; |
148
|
|
|
if ($sourceInfo['hash'] !== $targetInfo['hash']) { |
149
|
|
|
$builder = $this->diffCollectionElementBuilderFactory(DiffCollectionElementBuilder::UPDATE_ELEMENT_MODE); |
150
|
|
|
$builder->setSourceHash($sourceInfo['hash']) |
151
|
|
|
->setTargetHash($targetInfo['hash']) |
152
|
|
|
->setRowIndex($sourceInfo['rowIndex']) |
153
|
|
|
->setSourceCollectionElement($sourceInfo['element']) |
154
|
|
|
->setTargetCollectionElement($targetInfo['element']) |
155
|
|
|
->setUniqueRowId($targetInfo['rowUniqueId']) |
156
|
|
|
->setPathToElement($targetInfo['pathToElement']); |
157
|
|
|
$diff[] = $builder->build(); |
158
|
|
|
} |
159
|
|
|
} else { |
160
|
|
|
$builder = $this->diffCollectionElementBuilderFactory(DiffCollectionElementBuilder::DELETE_ELEMENT_MODE); |
161
|
|
|
$builder->setSourceHash($sourceInfo['hash']) |
162
|
|
|
->setRowIndex($sourceInfo['rowIndex']) |
163
|
|
|
->setSourceCollectionElement($sourceInfo['element']) |
164
|
|
|
->setUniqueRowId($sourceInfo['rowUniqueId']) |
165
|
|
|
->setPathToElement($sourceInfo['pathToElement']); |
166
|
|
|
$diff[] = $builder->build(); |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
foreach ($targetCollectionElementsInfo as $rowUniqueId => $targetInfo) { |
171
|
|
|
if (!array_key_exists($rowUniqueId, $sourceCollectionElementsInfo)) { |
172
|
|
|
$builder = $this->diffCollectionElementBuilderFactory(DiffCollectionElementBuilder::INSERT_ELEMENT_MODE); |
173
|
|
|
$builder->setSourceHash($targetInfo['hash']) |
174
|
|
|
->setRowIndex($targetInfo['rowIndex']) |
175
|
|
|
->setSourceCollectionElement($targetInfo['element']) |
176
|
|
|
->setUniqueRowId($targetInfo['rowUniqueId']) |
177
|
|
|
->setPathToElement($targetInfo['pathToElement']); |
178
|
|
|
$diff[] = $builder->build(); |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
|
183
|
|
|
return $diff; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @param Collection $collection |
188
|
|
|
* |
189
|
|
|
* |
190
|
|
|
* @param $prefixPath |
191
|
|
|
* |
192
|
|
|
* @return array |
193
|
|
|
* @throws \Nnx\FormComparator\Comparator\CollectionDiffService\Exception\RuntimeException |
194
|
|
|
*/ |
195
|
|
|
protected function buildInfoForCollectionElements(Collection $collection, $prefixPath) |
196
|
|
|
{ |
197
|
|
|
$rowUniqueId = 0; |
198
|
|
|
$hashForCollectionElements = []; |
199
|
|
|
$hashElementBuilder = $this->getHashElementBuilder(); |
200
|
|
|
|
201
|
|
|
foreach ($collection->getIterator() as $elementOrFieldset) { |
202
|
|
|
/** @var ElementInterface $elementOrFieldset */ |
203
|
|
|
Assert::isInstanceOf($elementOrFieldset, ElementInterface::class); |
204
|
|
|
$hashForCollectionElements[$rowUniqueId] = [ |
205
|
|
|
'hash' => $hashElementBuilder->hash($elementOrFieldset), |
206
|
|
|
'element' => $elementOrFieldset, |
207
|
|
|
'rowUniqueId' => $rowUniqueId, |
208
|
|
|
'rowIndex' => $rowUniqueId, |
209
|
|
|
'pathToElement' => $prefixPath . '.' . $elementOrFieldset->getName() |
210
|
|
|
]; |
211
|
|
|
$rowUniqueId++; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
return $hashForCollectionElements; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Билдер для получения объекта описывающего разницу в коллекции |
220
|
|
|
* |
221
|
|
|
* @param $mode |
222
|
|
|
* |
223
|
|
|
* @return DiffCollectionElementBuilder |
224
|
|
|
*/ |
225
|
|
|
protected function diffCollectionElementBuilderFactory($mode) |
226
|
|
|
{ |
227
|
|
|
return new DiffCollectionElementBuilder($mode); |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
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.