Completed
Push — master ( 852076...2b713c )
by Alex
23s queued 14s
created

FindVocabularyAnnotations()   C

Complexity

Conditions 13
Paths 7

Size

Total Lines 41
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 21
c 1
b 0
f 0
nc 7
nop 4
dl 0
loc 41
rs 6.6166

How to fix   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
 * Created by PhpStorm.
6
 * User: alex
7
 * Date: 22/07/20
8
 * Time: 10:26 PM.
9
 */
10
namespace AlgoWeb\ODataMetadata\Helpers;
11
12
use AlgoWeb\ODataMetadata\EdmUtil;
13
use AlgoWeb\ODataMetadata\Interfaces\Annotations\IVocabularyAnnotation;
14
use AlgoWeb\ODataMetadata\Interfaces\IModel;
15
use AlgoWeb\ODataMetadata\Interfaces\IStructuredType;
16
use AlgoWeb\ODataMetadata\Interfaces\ITerm;
17
use AlgoWeb\ODataMetadata\Interfaces\IVocabularyAnnotatable;
18
19
trait ModelHelpersVocabularyAnnotation
20
{
21
    /**
22
     * Gets an annotatable element's vocabulary annotations that bind a particular term.
23
     *
24
     * @param  IVocabularyAnnotatable           $element   element to check for annotations
25
     * @param  ITerm|string|null                $term      Term to search for. OR Name of the term to search for.
26
     * @param  string|null                      $qualifier qualifier to apply
27
     * @param  string|null                      $type      type of the annotation being returned
28
     * @return iterable|IVocabularyAnnotation[] annotations attached to the element by this model or by models
29
     *                                                    referenced by this model that bind the term with the given qualifier
30
     */
31
    public function FindVocabularyAnnotations(
32
        IVocabularyAnnotatable $element,
33
        $term = null,
34
        string $qualifier = null,
35
        string $type = null
36
    ): iterable {
37
        assert(
38
            null === $term || $term instanceof ITerm || is_string($term),
39
            '$term should be a string or instanceof iTerm'
40
        );
41
        if (null === $term) {
42
            return $this->processNullVocabularyAnnotationTerm($element);
43
        }
44
        if (is_string($term)) {
45
            $termName = $term;
46
            // Look up annotations on the element by name. There's no particular advantage in searching for a term first.
47
            $name          = null;
48
            $namespaceName = null;
49
50
            if (EdmUtil::TryGetNamespaceNameFromQualifiedName($termName, $namespaceName, $name)) {
51
                /**
52
                 * @var IVocabularyAnnotation $annotation
53
                 */
54
                foreach ($this->FindVocabularyAnnotations($element) as $annotation) {
55
                    if (null !== $type && !is_a($annotation, $type)) {
56
                        continue;
57
                    }
58
                    $annotationTerm = $annotation->getTerm();
59
                    if ($annotationTerm->getNamespace() === $namespaceName &&
60
                        $annotationTerm->getName() === $name &&
61
                        (
62
                            null === $qualifier ||
63
                            $qualifier == $annotation->getQualifier()
64
                        )
65
                    ) {
66
                        yield $annotation;
0 ignored issues
show
Bug Best Practice introduced by
The expression yield $annotation returns the type Generator which is incompatible with the documented return type AlgoWeb\ODataMetadata\In...ryAnnotation[]|iterable.
Loading history...
67
                    }
68
                }
69
            }
70
        } else {
71
            return $this->processTermVocabularyAnnotationTerm($element, $term, $qualifier, $type);
72
        }
73
    }
74
75
    /**
76
     * Gets an annotatable element's vocabulary annotations defined in a specific model and models referenced by
77
     * that model.
78
     * @param  IVocabularyAnnotatable  $element element to check for annotations
79
     * @return IVocabularyAnnotation[] annotations attached to the element (or, if the element is a type, to its base
80
     *                                         types) by this model or by models referenced by this model
81
     */
82
    public function FindVocabularyAnnotationsIncludingInheritedAnnotations(IVocabularyAnnotatable $element): array
83
    {
84
        /**
85
         * @var IVocabularyAnnotation[] $result
86
         */
87
        $result = $this->FindDeclaredVocabularyAnnotations($element);
0 ignored issues
show
Bug introduced by
It seems like FindDeclaredVocabularyAnnotations() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

87
        /** @scrutinizer ignore-call */ 
88
        $result = $this->FindDeclaredVocabularyAnnotations($element);
Loading history...
88
89
        if ($element instanceof IStructuredType) {
90
            $typeElement = $element;
91
            assert($typeElement instanceof IStructuredType);
92
            $typeElement = $typeElement->getBaseType();
93
            while (null !== $typeElement) {
94
                if ($typeElement instanceof IVocabularyAnnotatable) {
95
                    $result = array_merge($result, $this->FindDeclaredVocabularyAnnotations($typeElement));
96
                }
97
98
                $typeElement = $typeElement->getBaseType();
99
            }
100
        }
101
102
        return $result;
103
    }
104
105
    /**
106
     * @param  IVocabularyAnnotatable        $element
107
     * @return IVocabularyAnnotation[]|array
108
     */
109
    protected function processNullVocabularyAnnotationTerm(
110
        IVocabularyAnnotatable $element
111
    ): array {
112
        $result = $this->FindVocabularyAnnotationsIncludingInheritedAnnotations($element);
113
        foreach ($this->getReferencedModels() as $referencedModel) {
114
            $result = array_merge(
115
                $result,
116
                $referencedModel->FindVocabularyAnnotationsIncludingInheritedAnnotations($element)
117
            );
118
        }
119
        return $result;
120
    }
121
122
    /**
123
     * @param  IVocabularyAnnotatable $element
124
     * @param  ITerm                  $term
125
     * @param  string                 $qualifier
126
     * @param  string                 $type
127
     * @return array
128
     */
129
    protected function processTermVocabularyAnnotationTerm(
130
        IVocabularyAnnotatable $element,
131
        ITerm $term,
132
        string $qualifier = null,
133
        string $type = null
134
    ): array {
135
        $result = [];
136
        /**
137
         * @var IVocabularyAnnotation $annotation
138
         */
139
        foreach ($this->FindVocabularyAnnotations($element) as $annotation) {
140
            if (null !== $type && !is_a($annotation, $type)) {
141
                continue;
142
            }
143
144
            if ($annotation->getTerm() == $term && (null === $qualifier || $qualifier == $annotation->getQualifier())) {
145
                $result[] = $annotation;
146
            }
147
        }
148
149
        return $result;
150
    }
151
152
    /**
153
     * @return IModel[] gets the collection of models referred to by this model
154
     */
155
    abstract public function getReferencedModels(): array;
156
}
157