Issues (126)

src/Helpers/FunctionImportHelpers.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlgoWeb\ODataMetadata\Helpers;
6
7
use AlgoWeb\ODataMetadata\EdmUtil;
8
use AlgoWeb\ODataMetadata\Interfaces\Expressions\IExpression;
9
use AlgoWeb\ODataMetadata\Interfaces\Expressions\IPathExpression;
10
use AlgoWeb\ODataMetadata\Interfaces\IEntitySet;
11
use AlgoWeb\ODataMetadata\Interfaces\IEntityType;
12
use AlgoWeb\ODataMetadata\Interfaces\IFunctionImport;
13
use AlgoWeb\ODataMetadata\Interfaces\IFunctionParameter;
14
use AlgoWeb\ODataMetadata\Interfaces\IModel;
15
use AlgoWeb\ODataMetadata\Interfaces\INavigationProperty;
16
17
/**
18
 * Trait FunctionImportHelpers.
19
 * @package AlgoWeb\ODataMetadata\Helpers
20
 */
21
trait FunctionImportHelpers
22
{
23
    /**
24
     * Analyzes IFunctionImport::EntitySet expression and returns a static IEdmEntitySet reference if available.
25
     *
26
     * @param  IEntitySet $entitySet the static entity set of the function import
27
     * @return bool       true if the entity set expression of the functionImport contains a static reference to an IEntitySet, otherwise false
28
     */
29
    public function tryGetStaticEntitySet(IEntitySet &$entitySet = null): bool
30
    {
31
        /** @var IFunctionImport $this */
32
        $entitySetReference = $this->getEntitySet();
33
        $entitySet          = ($entitySetReference instanceof IEntitySet) ? $entitySetReference : null;
34
        return $entitySet !== null;
35
    }
36
37
    /**
38
     * Analyzes IFunctionImport::EntitySet expression and returns a relative path to an IEntitySet if available.
39
     * The path starts with the parameter and may have optional sequence of NavigationProperty and type casts segments.
40
     *
41
     * @param  IModel                     $model     the model containing the function import
42
     * @param  IFunctionParameter|null    $parameter the function import parameter from which the relative entity set
43
     *                                               path starts
44
     * @param  INavigationProperty[]|null $path      the optional sequence of navigation properties
45
     * @return bool                       true if the entity set expression of the functionImport contains a relative
46
     *                                              path an IEntitySet, otherwise false
47
     */
48
    public function tryGetRelativeEntitySetPath(
49
        IModel $model,
50
        IFunctionParameter &$parameter = null,
51
        array &$path = null
52
    ): bool {
53
        /**
54
         * @var IFunctionImport $this
55
         */
56
        $parameter = null;
57
        $path      = null;
58
59
        $entitySetPath = $this->getEntitySet();
60
        $entitySetPath = $entitySetPath instanceof IPathExpression ? $entitySetPath : null;
61
        if ($entitySetPath === null) {
62
            return false;
63
        }
64
65
        $pathToResolve = $entitySetPath->getPath();
66
        $numSegments   = count($pathToResolve);
67
        if (0 === $numSegments) {
68
            return false;
69
        }
70
71
        // Resolve the first segment as a parameter.
72
        $parameter = $this->findParameter($pathToResolve[0]);
73
        if ($parameter === null) {
74
            return false;
75
        }
76
77
        if (1 === $numSegments) {
78
            $path = [];
79
            return true;
80
        } else {
81
            // Get the entity type of the parameter, treat the rest of the path as a sequence of navprops.
82
            assert($parameter instanceof IFunctionParameter);
83
            /**
84
             * @var IEntityType $entityType
85
             */
86
            $entityType = Helpers::getPathSegmentEntityType($parameter->getType());
87
            /**
88
             * @var INavigationProperty[] $pathList
89
             */
90
            $pathList = [];
91
            for ($i = 1; $i < $numSegments; ++$i) {
92
                $segment = $pathToResolve[$i];
93
                if (EdmUtil::isQualifiedName($segment)) {
94
                    if ($i == count($pathToResolve) - 1) {
95
                        // The last segment must not be type cast.
96
                        return false;
97
                    }
98
                    /**
99
                     * @var IEntityType|null $subType ;
100
                     */
101
                    $subType = $model->findDeclaredType($segment);
102
                    $subType = $subType instanceof IEntityType ? $subType : null;
103
                    if ($subType == null || !$subType->isOrInheritsFrom($entityType)) {
104
                        return false;
105
                    }
106
107
                    $entityType = $subType;
108
                } else {
109
                    $navProp = $entityType->findProperty($segment);
110
                    $navProp = $navProp instanceof INavigationProperty ? $navProp : null;
111
                    if ($navProp == null) {
112
                        return false;
113
                    }
114
115
                    $pathList[] = $navProp;
116
                    $entityType = Helpers::getPathSegmentEntityType($navProp->getType());
0 ignored issues
show
It seems like $navProp->getType() can also be of type null; however, parameter $segmentType of AlgoWeb\ODataMetadata\He...PathSegmentEntityType() does only seem to accept AlgoWeb\ODataMetadata\Interfaces\ITypeReference, 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

116
                    $entityType = Helpers::getPathSegmentEntityType(/** @scrutinizer ignore-type */ $navProp->getType());
Loading history...
117
                }
118
            }
119
120
            $path = $pathList;
121
            return true;
122
        }
123
    }
124
125
    /**
126
     * @return IExpression|null gets the entity set containing entities returned by this function import
127
     */
128
    abstract public function getEntitySet(): ?IExpression;
129
}
130