Completed
Push — master ( ddccce...70f96e )
by Andrey
02:38
created

CollectionDiffService   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 208
Duplicated Lines 20.19 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
c 1
b 0
f 0
lcom 1
cbo 5
dl 42
loc 208
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getHashElementBuilder() 0 7 2
A setHashElementBuilder() 0 6 1
A buildDiffInsertedCollection() 21 21 2
A buildDiffDeletedCollection() 21 21 2
B buildDiffUpdatedCollection() 0 50 6
A buildInfoForCollectionElements() 0 21 2
A diffCollectionElementBuilderFactory() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
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