ModelUtil::setNewIdentifier()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 3
c 1
b 0
f 0
nc 2
nop 4
dl 0
loc 9
rs 10
1
<?php
2
3
namespace Xml\Impl\Util;
4
5
use Xml\ModelInterface;
6
use Xml\Exception\ModelException;
7
use Xml\Impl\ModelInstanceImpl;
8
use Xml\Impl\Type\ModelElementTypeImpl;
9
use Xml\Impl\Type\Attribute\StringAttribute;
10
use Xml\Instance\{
11
    DomElementInterface,
12
    ModelElementInstanceInterface
13
};
14
use Xml\Type\ModelElementTypeInterface;
15
16
class ModelUtil
17
{
18
    public const ID_ATTRIBUTE_NAME = "id";
19
20
    /**
21
     * @return mixed
22
     */
23
    public static function getModelElement(
24
        DomElementInterface $domElement,
25
        ModelInstanceImpl $modelInstance,
26
        ?ModelElementTypeImpl $modelType = null,
27
        ?string $namespaceUri = null
28
    ) {
29
        if ($modelType === null && $namespaceUri === null) {
30
            $modelElement = $domElement->getModelElementInstance();
31
32
            if ($modelElement === null) {
33
                $modelType = self::getModelElement($domElement, $modelInstance, null, $domElement->getNamespaceURI());
34
                $modelElement = $modelType->newInstance($modelInstance, $domElement);
35
                $domElement->setModelElementInstance($modelElement);
36
            }
37
            return $modelElement;
38
        } elseif ($modelType !== null) {
39
            $modelElement = $domElement->getModelElementInstance();
40
41
            if ($modelElement === null) {
42
                $modelElement = $modelType->newInstance($modelInstance, $domElement);
43
                $domElement->setModelElementInstance($modelElement);
44
            }
45
            return $modelElement;
46
        } elseif ($namespaceUri !== null) {
47
            $localName = $domElement->getLocalName();
48
            $modelType = $modelInstance->getModel()->getTypeForName($namespaceUri, $localName);
49
            if ($modelType === null) {
50
                $model = $modelInstance->getModel();
51
                $actualNamespaceUri = $model->getActualNamespace($namespaceUri);
52
                if ($actualNamespaceUri !== null) {
53
                    $modelType = self::getModelElement($domElement, $modelInstance, null, $actualNamespaceUri);
54
                } else {
55
                    $modelType = $modelInstance->registerGenericType($namespaceUri, $localName);
56
                }
57
            }
58
59
            return $modelType;
60
        }
61
62
        return null;
63
    }
64
65
    public static function getQName(?string $namespaceUri, string $localName): QName
66
    {
67
        return new QName($namespaceUri, $localName);
68
    }
69
70
    /**
71
     * @param mixed $instance
72
     * @param string $type
73
     */
74
    public static function ensureInstanceOf($instance, string $type): void
75
    {
76
        if (!($instance instanceof $type)) {
77
            throw new ModelException(sprintf("Object is not instance of type %s", $type));
78
        }
79
    }
80
81
    public static function valueAsBoolean(?string $rawValue): bool
82
    {
83
        return $rawValue === null ? false : json_decode($rawValue);
84
    }
85
86
    public static function valueAsInteger(string $rawValue): int
87
    {
88
        return intval($rawValue);
89
    }
90
91
    public static function valueAsFloat(string $rawValue): float
92
    {
93
        return floatval($rawValue);
94
    }
95
96
    public static function valueAsDouble(string $rawValue): float
97
    {
98
        return floatval($rawValue);
99
    }
100
101
    public static function valueAsShort(string $rawValue): int
102
    {
103
        return intval($rawValue);
104
    }
105
106
    /**
107
     * @param mixed $rawValue
108
     */
109
    public static function valueAsString($rawValue): string
110
    {
111
        return strval($rawValue);
112
    }
113
114
    public static function getModelElementCollection(array $view, ModelInstanceImpl $model): array
115
    {
116
        $resultList = [];
117
        foreach ($view as $element) {
118
            $resultList[] = self::getModelElement($element, $model);
119
        }
120
        return $resultList;
121
    }
122
123
    public static function getIndexOfElementType(
124
        ModelElementInstanceInterface $modelElement,
125
        array $childElementTypes
126
    ): int {
127
        $numOfChildren = count($childElementTypes);
128
        for ($index = 0; $index < $numOfChildren; $index += 1) {
129
            $childElementType = $childElementTypes[$index];
130
            $instanceType = $childElementType->getInstanceType();
131
            if (is_a($modelElement, $instanceType)) {
132
                return $index;
133
            }
134
        }
135
        $childElementTypeNames = [];
136
        foreach ($childElementTypes as $childElementType) {
137
            $childElementTypeNames[] = $childElementType->getTypeName();
138
        }
139
        throw new ModelException(
140
            sprintf(
141
                "New child is not a valid child element type: %s; valid types are: %s",
142
                $modelElement->getElementType()->getTypeName(),
143
                implode(', ', $childElementTypeNames)
144
            )
145
        );
146
    }
147
148
    public static function calculateAllExtendingTypes(
149
        ModelInterface $model,
150
        array $baseTypes
151
    ): array {
152
        $allExtendingTypes = [];
153
        foreach ($baseTypes as $baseType) {
154
            $modelElementTypeImpl = $model->getType($baseType->getInstanceType());
155
            $modelElementTypeImpl->resolveExtendingTypes($allExtendingTypes);
0 ignored issues
show
Bug introduced by
The method resolveExtendingTypes() does not exist on Xml\Type\ModelElementTypeInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Xml\Type\ModelElementTypeInterface. ( Ignorable by Annotation )

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

155
            $modelElementTypeImpl->/** @scrutinizer ignore-call */ 
156
                                   resolveExtendingTypes($allExtendingTypes);
Loading history...
156
        }
157
        return $allExtendingTypes;
158
    }
159
160
    public static function calculateAllBaseTypes(ModelElementTypeInterface $type): array
161
    {
162
        $baseTypes = [];
163
        $type->resolveBaseTypes($baseTypes);
0 ignored issues
show
Bug introduced by
The method resolveBaseTypes() does not exist on Xml\Type\ModelElementTypeInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Xml\Type\ModelElementTypeInterface. ( Ignorable by Annotation )

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

163
        $type->/** @scrutinizer ignore-call */ 
164
               resolveBaseTypes($baseTypes);
Loading history...
164
        return $baseTypes;
165
    }
166
167
    public static function setNewIdentifier(
168
        ModelElementTypeInterface $type,
169
        ModelElementInstanceInterface $modelElementInstance,
170
        string $newId,
171
        bool $withReferenceUpdate
172
    ): void {
173
        $id = $type->getAttribute(self::ID_ATTRIBUTE_NAME);
174
        if ($id !== null && $id instanceof StringAttribute && $id->isIdAttribute()) {
175
            $id->setValue($modelElementInstance, $newId, $withReferenceUpdate);
176
        }
177
    }
178
179
    public static function setGeneratedUniqueIdentifier(
180
        ModelElementTypeInterface $type,
181
        ModelElementInstanceInterface $modelElementInstance,
182
        bool $withReferenceUpdate = true
183
    ): void {
184
        self::setNewIdentifier($type, $modelElementInstance, self::getUniqueIdentifier($type), $withReferenceUpdate);
185
    }
186
187
    public static function getUniqueIdentifier(ModelElementTypeInterface $type): string
188
    {
189
        $data = openssl_random_pseudo_bytes(16);
190
        $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
191
        $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
192
        $uuid = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
0 ignored issues
show
Bug introduced by
It seems like str_split(bin2hex($data), 4) can also be of type true; however, parameter $values of vsprintf() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

192
        $uuid = vsprintf('%s%s-%s-%s-%s-%s%s%s', /** @scrutinizer ignore-type */ str_split(bin2hex($data), 4));
Loading history...
193
        return $type->getTypeName() . '_' . $uuid;
194
    }
195
}
196