Completed
Push — master ( b9f89d...74ba61 )
by Alex
29s queued 14s
created

findTarget()   C

Complexity

Conditions 14
Paths 13

Size

Total Lines 89
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 14
eloc 65
c 2
b 0
f 0
nc 13
nop 2
dl 0
loc 89
rs 6.2666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
6
namespace AlgoWeb\ODataMetadata\Edm\Validation\ValidationRules\IVocabularyAnnotation;
7
8
use AlgoWeb\ODataMetadata\Edm\Validation\EdmErrorCode;
9
use AlgoWeb\ODataMetadata\Edm\Validation\ValidationContext;
10
use AlgoWeb\ODataMetadata\EdmUtil;
11
use AlgoWeb\ODataMetadata\Interfaces\Annotations\IVocabularyAnnotation;
12
use AlgoWeb\ODataMetadata\Interfaces\IEdmElement;
13
use AlgoWeb\ODataMetadata\Interfaces\IEntityContainer;
14
use AlgoWeb\ODataMetadata\Interfaces\IEntitySet;
15
use AlgoWeb\ODataMetadata\Interfaces\IFunction;
16
use AlgoWeb\ODataMetadata\Interfaces\IFunctionBase;
17
use AlgoWeb\ODataMetadata\Interfaces\IFunctionImport;
18
use AlgoWeb\ODataMetadata\Interfaces\IFunctionParameter;
19
use AlgoWeb\ODataMetadata\Interfaces\IProperty;
20
use AlgoWeb\ODataMetadata\Interfaces\ISchemaType;
21
use AlgoWeb\ODataMetadata\Interfaces\IStructuredType;
22
use AlgoWeb\ODataMetadata\Interfaces\ITerm;
23
use AlgoWeb\ODataMetadata\StringConst;
24
25
/**
26
 * Validates that a vocabulary annotations target can be found through the model containing the annotation.
27
 *
28
 * @package AlgoWeb\ODataMetadata\Edm\Validation\ValidationRules\IVocabularyAnnotation
29
 */
30
class VocabularyAnnotationInaccessibleTarget extends VocabularyAnnotationRule
31
{
32
    public function __invoke(ValidationContext $context, ?IEdmElement $annotation)
33
    {
34
        assert($annotation instanceof IVocabularyAnnotation);
35
        $target      = $annotation->getTarget();
36
        $foundTarget = $this->findTarget($context, $target);
37
38
        if (!$foundTarget) {
39
            EdmUtil::checkArgumentNull($annotation->Location(), 'annotation->Location');
40
            $context->AddError(
41
                $annotation->Location(),
42
                EdmErrorCode::BadUnresolvedTarget(),
43
                StringConst::EdmModel_Validator_Semantic_InaccessibleTarget(EdmUtil::FullyQualifiedName($target))
44
            );
45
        }
46
    }
47
48
    /**
49
     * @param  ValidationContext                                        $context
50
     * @param  \AlgoWeb\ODataMetadata\Interfaces\IVocabularyAnnotatable $target
51
     * @return bool
52
     */
53
    protected function findTarget(
54
        ValidationContext $context,
55
        \AlgoWeb\ODataMetadata\Interfaces\IVocabularyAnnotatable $target
56
    ): bool {
57
        $foundTarget     = false;
58
        $entityContainer = $target;
59
        if ($entityContainer instanceof IEntityContainer) {
60
            $foundTarget = ($context->getModel()->findEntityContainer($entityContainer->FullName()) != null);
61
            return $foundTarget;
62
        }
63
        $entitySet = $target;
64
        if ($entitySet instanceof IEntitySet) {
65
            EdmUtil::checkArgumentNull($entitySet->getName(), 'entitySet->getName');
66
            $container = $entitySet->getContainer();
67
            if ($container instanceof IEntityContainer) {
68
                $foundTarget = ($container->findEntitySet($entitySet->getName()) != null);
69
                return $foundTarget;
70
            }
71
            return false;
72
        }
73
        $schemaType = $target;
74
        if ($schemaType instanceof ISchemaType) {
75
            $foundTarget = ($context->getModel()->FindType($schemaType->FullName()) != null);
76
            return $foundTarget;
77
        }
78
        $term = $target;
79
        if ($term instanceof ITerm) {
80
            $foundTarget = ($context->getModel()->FindValueTerm($term->FullName()) != null);
81
            return $foundTarget;
82
        }
83
        $function = $target;
84
        if ($function instanceof IFunction) {
85
            $foundTarget = count($context->getModel()->FindFunctions($function->FullName())) > 0;
86
            return $foundTarget;
87
        }
88
        $functionImport = $target;
89
        if ($functionImport instanceof IFunctionImport) {
90
            EdmUtil::checkArgumentNull($functionImport->getName(), 'functionImport->getName');
91
            $funcName    = $functionImport->getName();
92
            $foundTarget = count($functionImport->getContainer()->findFunctionImports($funcName)) > 0;
93
            return $foundTarget;
94
        }
95
        $typeProperty = $target;
96
        if ($typeProperty instanceof IProperty) {
97
            $declaringType = $typeProperty->getDeclaringType();
98
            assert($declaringType instanceof ISchemaType);
99
            $declaringTypeFullName = EdmUtil::FullyQualifiedName($declaringType);
100
            EdmUtil::checkArgumentNull($declaringTypeFullName, 'declaringTypeFullName');
101
            EdmUtil::checkArgumentNull($typeProperty->getName(), 'typeProperty->getName');
102
            $modelType = $context->getModel()->FindType($declaringTypeFullName);
103
            if ($modelType !== null && $modelType instanceof IStructuredType) {
104
                // If we can find a structured type with this name in the model check if it
105
                // has a property with this name
106
                $foundTarget = ($modelType->findProperty($typeProperty->getName()) != null);
107
                return $foundTarget;
108
            }
109
            return false;
110
        }
111
        $functionParameter = $target;
112
        if ($functionParameter instanceof IFunctionParameter) {
113
            $paramName = $functionParameter->getName();
114
            EdmUtil::checkArgumentNull($paramName, 'functionParameter->getName');
115
            $declaringFunction = $functionParameter->getDeclaringFunction();
116
            switch (true) {
117
                case $declaringFunction instanceof IFunction:
118
                    $functions = $context->getModel()->FindFunctions($declaringFunction->FullName());
119
                    break;
120
                case $declaringFunction instanceof IFunctionImport:
121
                    $container = $declaringFunction->getContainer();
122
                    assert($container instanceof IEntityContainer);
123
                    EdmUtil::checkArgumentNull($declaringFunction->getName(), 'declaringFunction->getName');
124
                    $functions = $container->findFunctionImports($declaringFunction->getName());
125
                    break;
126
                default:
127
                    return false;
128
            }
129
130
            // For all functions with this name declared in the model check if it has
131
            // a parameter with this name
132
            return 0 < count(array_filter($functions, function (IFunctionBase $func) use ($paramName) {
133
                return null !== $func->findParameter($paramName);
134
            }));
135
        } else {
136
            // Only validate annotations targeting elements that can be found via the
137
            // model API.
138
            // E.g. annotations targeting annotations will not be valid without this branch.
139
            $foundTarget = true;
140
        }
141
        return $foundTarget;
142
    }
143
}
144