Issues (126)

src/Internal/RegistrationHelper.php (1 issue)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlgoWeb\ODataMetadata\Internal;
6
7
use AlgoWeb\ODataMetadata\EdmUtil;
8
use AlgoWeb\ODataMetadata\Enums\SchemaElementKind;
9
use AlgoWeb\ODataMetadata\Exception\InvalidOperationException;
10
use AlgoWeb\ODataMetadata\Interfaces\IEdmElement;
11
use AlgoWeb\ODataMetadata\Interfaces\IEntityContainer;
12
use AlgoWeb\ODataMetadata\Interfaces\IEntitySet;
13
use AlgoWeb\ODataMetadata\Interfaces\IFunction;
14
use AlgoWeb\ODataMetadata\Interfaces\IFunctionBase;
15
use AlgoWeb\ODataMetadata\Interfaces\IProperty;
16
use AlgoWeb\ODataMetadata\Interfaces\ISchemaElement;
17
use AlgoWeb\ODataMetadata\Interfaces\ISchemaType;
18
use AlgoWeb\ODataMetadata\Interfaces\IValueTerm;
19
use AlgoWeb\ODataMetadata\Library\Internal\Ambiguous\AmbiguousEntityContainerBinding;
20
use AlgoWeb\ODataMetadata\Library\Internal\Ambiguous\AmbiguousEntitySetBinding;
21
use AlgoWeb\ODataMetadata\Library\Internal\Ambiguous\AmbiguousPropertyBinding;
22
use AlgoWeb\ODataMetadata\Library\Internal\Ambiguous\AmbiguousTypeBinding;
23
use AlgoWeb\ODataMetadata\Library\Internal\Ambiguous\AmbiguousValueTermBinding;
24
use AlgoWeb\ODataMetadata\StringConst;
25
use ArrayAccess;
26
27
/**
28
 * Class RegistrationHelper.
29
 * @package AlgoWeb\ODataMetadata
30
 * @internal
31
 */
32
abstract class RegistrationHelper
33
{
34
    /**
35
     * @param ISchemaElement                  $element
36
     * @param array<string, ISchemaType>      $schemaTypeDictionary
37
     * @param array<string, IValueTerm>       $valueTermDictionary
38
     * @param array<string, object>           $functionGroupDictionary
39
     * @param array<string, IEntityContainer> $containerDictionary
40
     */
41
    public static function registerSchemaElement(
42
        ISchemaElement $element,
43
        array $schemaTypeDictionary,
44
        array $valueTermDictionary,
45
        array $functionGroupDictionary,
46
        array $containerDictionary
47
    ) {
48
        $qualifiedName = $element->fullName();
49
        switch ($element->getSchemaElementKind()) {
50
            case SchemaElementKind::Function():
51
                assert($element instanceof IFunction);
52
                self::addFunction($element, $qualifiedName, $functionGroupDictionary);
53
                break;
54
            case SchemaElementKind::TypeDefinition():
55
                assert($element instanceof ISchemaType);
56
                self::addElement(
57
                    $element,
58
                    $qualifiedName,
59
                    $schemaTypeDictionary,
60
                    [self::class, 'createAmbiguousTypeBinding']
61
                );
62
                break;
63
            case SchemaElementKind::ValueTerm():
64
                assert($element instanceof IValueTerm);
65
                self::addElement(
66
                    $element,
67
                    $qualifiedName,
68
                    $valueTermDictionary,
69
                    [self::class, 'CreateAmbiguousValueTermBinding()']
70
                );
71
                break;
72
            case SchemaElementKind::EntityContainer():
73
                assert($element instanceof IEntityContainer);
74
                EdmUtil::checkArgumentNull($element->getName(), 'element->getName');
75
                // Add EntityContainers to the dictionary twice to maintain backwards compat with Edms that did not
76
                // consider EntityContainers to be schema elements.
77
                self::addElement(
78
                    $element,
79
                    $qualifiedName,
80
                    $containerDictionary,
81
                    [self::class, 'createAmbiguousEntityContainerBinding']
82
                );
83
                self::addElement(
84
                    $element,
85
                    $element->getName(),
86
                    $containerDictionary,
87
                    [self::class, 'createAmbiguousEntityContainerBinding']
88
                );
89
                break;
90
            case SchemaElementKind::None():
91
                throw new InvalidOperationException(StringConst::EdmModel_CannotUseElementWithTypeNone());
92
            default:
93
                throw new InvalidOperationException(
94
                    StringConst::UnknownEnumVal_SchemaElementKind($element->getSchemaElementKind()->getKey())
95
                );
96
        }
97
    }
98
99
    /**
100
     * @param IProperty                $element
101
     * @param string                   $name
102
     * @param array<string, IProperty> $dictionary
103
     */
104
    public static function registerProperty(IProperty $element, string $name, array $dictionary)
105
    {
106
        self::addElement($element, $name, $dictionary, [self::class, 'createAmbiguousPropertyBinding']);
107
    }
108
    //Dictionary
109
    // Func<T, T, T>
110
    /**
111
     * @param IEdmElement                                   $element
112
     * @param string                                        $name
113
     * @param array<string, IEdmElement>                    $elementDictionary
114
     * @param callable(IEdmElement,IEdmElement):IEdmElement $ambiguityCreator
115
     */
116
    public static function addElement($element, string $name, array &$elementDictionary, callable $ambiguityCreator)
117
    {
118
        if (array_key_exists($name, $elementDictionary)) {
119
            $preexisting              = $elementDictionary[$name];
120
            $elementDictionary[$name] = $ambiguityCreator($preexisting, $element);
121
        } else {
122
            $elementDictionary[$name] = $element;
123
        }
124
    }
125
126
    /**
127
     * @param IFunctionBase         $function
128
     * @param string                $name
129
     * @param array<string, object> $functionListDictionary
130
     */
131
    public static function addFunction(IFunctionBase $function, string $name, array &$functionListDictionary)
132
    {
133
        if (array_key_exists($name, $functionListDictionary)) {
134
            $functionList = $functionListDictionary[$name];
135
            if (!is_array($functionList) && !($functionList instanceof ArrayAccess)) {
0 ignored issues
show
The condition is_array($functionList) is always false.
Loading history...
136
                $functionListDictionary[$name] = [$functionList];
137
            }
138
            $functionListDictionary[$name][] = $function;
139
        } else {
140
            $functionListDictionary[$name] = $function;
141
        }
142
    }
143
144
    public static function createAmbiguousTypeBinding(ISchemaType $first, ISchemaType $second): ISchemaType
145
    {
146
        if ($first instanceof AmbiguousTypeBinding) {
147
            $first->addBinding($second);
148
            return $first;
149
        }
150
        return new AmbiguousTypeBinding($first, $second);
151
    }
152
153
    public static function createAmbiguousValueTermBinding(IValueTerm $first, IValueTerm $second): IValueTerm
154
    {
155
        if ($first instanceof AmbiguousValueTermBinding) {
156
            $first->addBinding($second);
157
            return $first;
158
        }
159
160
        return new AmbiguousValueTermBinding($first, $second);
161
    }
162
163
    public static function createAmbiguousEntitySetBinding(IEntitySet $first, IEntitySet $second): IEntitySet
164
    {
165
        if ($first instanceof AmbiguousEntitySetBinding) {
166
            $first->addBinding($second);
167
            return $first;
168
        }
169
170
        return new AmbiguousEntitySetBinding($first, $second);
171
    }
172
173
    public static function createAmbiguousEntityContainerBinding(
174
        IEntityContainer $first,
175
        IEntityContainer $second
176
    ): IEntityContainer {
177
        if ($first instanceof AmbiguousEntityContainerBinding) {
178
            $first->addBinding($second);
179
            return $first;
180
        }
181
182
        return new AmbiguousEntityContainerBinding($first, $second);
183
    }
184
185
    public static function createAmbiguousPropertyBinding(IProperty $first, IProperty $second): IProperty
186
    {
187
        if ($first instanceof AmbiguousPropertyBinding) {
188
            $first->addBinding($second);
189
            return $first;
190
        }
191
192
        return new AmbiguousPropertyBinding($first->getDeclaringType(), $first, $second);
193
    }
194
}
195