getReferenceIdentifier()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Xml\Impl\Type\Reference;
4
5
use Xml\Exception\{
6
    ModelException,
7
    ModelReferenceException,
8
    UnsupportedModelOperationException
9
};
10
use Xml\Impl\Instance\ModelElementInstanceImpl;
11
use Xml\Impl\Type\ModelElementTypeImpl;
12
use Xml\Impl\Util\ModelUtil;
13
use Xml\Instance\ModelElementInstanceInterface;
14
use Xml\Type\ModelElementTypeInterface;
15
use Xml\Type\Child\ChildElementCollectionInterface;
16
use Xml\Type\Reference\ElementReferenceCollectionInterface;
17
18
class ElementReferenceCollectionImpl extends ReferenceImpl implements ElementReferenceCollectionInterface
19
{
20
    private $referenceSourceCollection;
21
    private $referenceSourceType;
22
23
    public function __construct(ChildElementCollectionInterface $referenceSourceCollection)
24
    {
25
        $this->referenceSourceCollection = $referenceSourceCollection;
26
    }
27
28
    public function getReferenceSourceCollection(): ChildElementCollectionInterface
29
    {
30
        return $this->referenceSourceCollection;
31
    }
32
33
    protected function setReferenceIdentifier(
34
        ModelElementInstanceInterface $referenceSourceElement,
35
        string $referenceIdentifier
36
    ): void {
37
        $referenceSourceElement->setTextContent($referenceIdentifier);
38
    }
39
40
    protected function performAddOperation(
41
        ModelElementInstanceImpl $referenceSourceParentElement,
42
        ModelElementInstanceInterface $referenceTargetElement
43
    ): void {
44
        $modelInstance = $referenceSourceParentElement->getModelInstance();
45
        $referenceTargetIdentifier = $this->referenceTargetAttribute->getValue($referenceTargetElement);
46
        $existingElement = $modelInstance->getModelElementById($referenceTargetIdentifier);
47
        if ($existingElement === null || !$referenceTargetElement->equals($existingElement)) {
48
            throw new ModelReferenceException("Cannot create reference to model element");
49
        } else {
50
            $referenceSourceElement = $modelInstance->newInstance($this->referenceSourceType);
51
            $this->referenceSourceCollection->add($referenceSourceParentElement, $referenceSourceElement);
0 ignored issues
show
Bug introduced by
The method add() does not exist on Xml\Type\Child\ChildElementCollectionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Xml\Type\Child\ChildElementInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

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

51
            $this->referenceSourceCollection->/** @scrutinizer ignore-call */ 
52
                                              add($referenceSourceParentElement, $referenceSourceElement);
Loading history...
52
            $this->setReferenceIdentifier($referenceSourceElement, $referenceTargetIdentifier);
53
        }
54
    }
55
56
    protected function performRemoveOperation(
57
        ModelElementInstanceImpl $referenceSourceParentElement,
58
        ModelElementInstanceInterface $referenceTargetElement
59
    ): void {
60
        $referenceSourceChildElements = $referenceSourceParentElement->getChildElementsByType(
61
            $this->referenceSourceType
62
        );
63
        foreach ($referenceSourceChildElements as $referenceSourceChildElement) {
64
            if ($referenceTargetElement->equals($this->getReferenceTargetElement($referenceSourceChildElement))) {
65
                $referenceSourceParentElement->removeChildElement($referenceSourceChildElement);
66
            }
67
        }
68
    }
69
70
    protected function performClearOperation(
71
        ModelElementInstanceImpl $referenceSourceParentElement,
72
        array $elementsToRemove
73
    ): void {
74
        foreach ($elementsToRemove as $element) {
75
            $referenceSourceParentElement->getDomElement()->removeChild($element);
76
        }
77
    }
78
79
    /**
80
     * @return mixed
81
     */
82
    public function getReferenceIdentifier(ModelElementInstanceInterface $referenceSourceElement)
83
    {
84
        return $referenceSourceElement->getTextContent();
85
    }
86
87
    protected function updateReference(
88
        ModelElementInstanceInterface $referenceSourceElement,
89
        ?string $oldIdentifier,
90
        string $newIdentifier
91
    ): void {
92
        $referencingTextContent = $this->getReferenceIdentifier($referenceSourceElement);
93
        if ($oldIdentifier !== null && $oldIdentifier == $referencingTextContent) {
94
            $this->setReferenceIdentifier($referenceSourceElement, $newIdentifier);
95
        }
96
    }
97
98
    //@attention. $referenceTargetElement is mentioned, but not used
99
    protected function removeReference(
100
        ModelElementInstanceInterface $referenceSourceElement,
101
        ModelElementInstanceInterface $referenceTargetElement
102
    ): void {
103
        $parentElement = $referenceSourceElement->getParentElement();
104
        $this->referenceSourceCollection->remove($parentElement, $referenceSourceElement);
0 ignored issues
show
Bug introduced by
The method remove() does not exist on Xml\Type\Child\ChildElementCollectionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Xml\Type\Child\ChildElementInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

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

104
        $this->referenceSourceCollection->/** @scrutinizer ignore-call */ 
105
                                          remove($parentElement, $referenceSourceElement);
Loading history...
105
    }
106
107
    public function setReferenceSourceElementType(ModelElementTypeImpl $referenceSourceType): void
108
    {
109
        $this->referenceSourceType = $referenceSourceType;
110
    }
111
112
    public function getReferenceSourceElementType(): ModelElementTypeInterface
113
    {
114
        return $this->referenceSourceType;
115
    }
116
117
    protected function getView(ModelElementInstanceImpl $referenceSourceParentElement): array
118
    {
119
        $document = $referenceSourceParentElement->getModelInstance()->getDocument();
120
        $referenceSourceElements = $this->referenceSourceCollection->get($referenceSourceParentElement);
121
        $referenceTargetElements = [];
122
        foreach ($referenceSourceElements as $referenceSourceElement) {
123
            $identifier = $this->getReferenceIdentifier($referenceSourceElement);
124
            $referenceTargetElement = $document->getElementById($identifier);
125
            if ($referenceTargetElement !== null) {
126
                $referenceTargetElements[] = $referenceTargetElement;
127
            } else {
128
                throw new ModelException(spintf("Unable to find a model element instance for id %s", $identifier));
0 ignored issues
show
Bug introduced by
The function spintf was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

128
                throw new ModelException(/** @scrutinizer ignore-call */ spintf("Unable to find a model element instance for id %s", $identifier));
Loading history...
129
            }
130
        }
131
        return $referenceTargetElements;
132
    }
133
134
    public function size(ModelElementInstanceImpl $referenceSourceParentElement): int
135
    {
136
        return count($this->getView($referenceSourceParentElement));
137
    }
138
139
    public function isEmpty(ModelElementInstanceImpl $referenceSourceParentElement): bool
140
    {
141
        return count($this->getView($referenceSourceParentElement)) == 0;
142
    }
143
144
    public function contains(
145
        ModelElementInstanceImpl $referenceSourceParentElement,
146
        ?ModelElementInstanceInterface $elementToAdd
147
    ): bool {
148
        if ($elementToAdd === null) {
149
            return false;
150
        } else {
151
            foreach ($this->getView($referenceSourceParentElement) as $el) {
152
                if ($elementToAdd->getDomElement()->equals($el)) {
153
                    return true;
154
                }
155
            }
156
            return false;
157
        }
158
    }
159
160
    public function containsAll(
161
        ModelElementInstanceImpl $referenceSourceParentElement,
162
        array $c
163
    ): bool {
164
        $modelElementCollection = ModelUtil::getModelElementCollection(
165
            $this->getView($referenceSourceParentElement),
166
            $referenceSourceParentElement->getModelInstance()
167
        );
168
        foreach ($modelElementCollection as $el) {
169
            $flag = false;
170
            foreach ($c as $elementToCheck) {
171
                if ($elementToCheck->equals($el)) {
172
                    $flag = true;
173
                    break;
174
                }
175
            }
176
            if (!$flag) {
177
                return false;
178
            }
179
        }
180
        return true;
181
    }
182
183
    public function add(ModelElementInstanceImpl $referenceSourceParentElement, ModelElementInstanceInterface $e): bool
184
    {
185
        if ($this->referenceSourceCollection->isImmutable()) {
186
            throw new UnsupportedModelOperationException("collection is immutable");
187
        } else {
188
            if (!$this->contains($referenceSourceParentElement, $e)) {
189
                $this->performAddOperation($referenceSourceParentElement, $e);
190
            }
191
            return true;
192
        }
193
    }
194
195
    public function remove(
196
        ModelElementInstanceImpl $referenceSourceParentElement,
197
        ModelElementInstanceInterface $e
198
    ): bool {
199
        if ($this->referenceSourceCollection->isImmutable()) {
200
            throw new UnsupportedModelOperationException("collection is immutable");
201
        }
202
        $this->performRemoveOperation($referenceSourceParentElement, $e);
203
        return true;
204
    }
205
206
    public function addAll(ModelElementInstanceImpl $referenceSourceParentElement, array $c): bool
207
    {
208
        if ($this->referenceSourceCollection->isImmutable()) {
209
            throw new UnsupportedModelOperationException("collection is immutable");
210
        }
211
        $result = false;
212
        foreach ($c as $elementToAdd) {
213
            $result |= $this->add($referenceSourceParentElement, $elementToAdd);
214
        }
215
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
216
    }
217
218
    public function removeAll(ModelElementInstanceImpl $referenceSourceParentElement, array $c): bool
219
    {
220
        if ($this->referenceSourceCollection->isImmutable()) {
221
            throw new UnsupportedModelOperationException("collection is immutable");
222
        }
223
        $result = false;
224
        foreach ($c as $elementToRemove) {
225
            $result |= $this->remove($referenceSourceParentElement, $elementToRemove);
226
        }
227
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
228
    }
229
230
    public function retainAll(ModelElementInstanceImpl $referenceSourceParentElement, array $c): bool
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed. ( Ignorable by Annotation )

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

230
    public function retainAll(ModelElementInstanceImpl $referenceSourceParentElement, /** @scrutinizer ignore-unused */ array $c): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $referenceSourceParentElement is not used and could be removed. ( Ignorable by Annotation )

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

230
    public function retainAll(/** @scrutinizer ignore-unused */ ModelElementInstanceImpl $referenceSourceParentElement, array $c): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
231
    {
232
        throw new UnsupportedModelOperationException("retainAll not implemented");
233
    }
234
235
    public function clear(ModelElementInstanceImpl $referenceSourceParentElement): void
236
    {
237
        if ($this->referenceSourceCollection->isImmutable()) {
238
            throw new UnsupportedModelOperationException("collection is immutable");
239
        }
240
        $view = [];
241
        $referenceSourceElements = $this->referenceSourceCollection->get($referenceSourceParentElement);
242
        foreach ($referenceSourceElements as $referenceSourceElement) {
243
            $view[] = $referenceSourceElement->getDomElement();
244
        }
245
        $this->performClearOperation($referenceSourceParentElement, $view);
246
    }
247
248
    public function getReferenceTargetElements(ModelElementInstanceImpl $referenceSourceParentElement): array
249
    {
250
        return ModelUtil::getModelElementCollection(
251
            $this->getView($referenceSourceParentElement),
252
            $referenceSourceParentElement->getModelInstance()
253
        );
254
    }
255
}
256