• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 7358252084

29 Dec 2023 04:32PM UTC coverage: 37.248% (-0.1%) from 37.395%
7358252084

push

github

soyuka
Merge 3.2

6 of 8 new or added lines in 6 files covered. (75.0%)

44 existing lines in 2 files now uncovered.

10347 of 27779 relevant lines covered (37.25%)

28.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Util/AttributeFilterExtractorTrait.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Util;
15

16
use ApiPlatform\Metadata\ApiFilter;
17

18
/**
19
 * Generates a service id for a generic filter.
20
 *
21
 * @internal
22
 *
23
 * @author Antoine Bluchet <soyuka@gmail.com>
24
 */
25
trait AttributeFilterExtractorTrait
26
{
27
    /**
28
     * Filters annotations to get back only ApiFilter annotations.
29
     *
30
     * @return \Iterator only ApiFilter annotations
31
     */
32
    private function getFilterAttributes(\ReflectionClass|\ReflectionProperty $reflector): \Iterator
33
    {
UNCOV
34
        $attributes = $reflector->getAttributes(ApiFilter::class);
×
35

UNCOV
36
        foreach ($attributes as $attribute) {
×
UNCOV
37
            yield $attribute->newInstance();
×
38
        }
39
    }
40

41
    /**
42
     * Given a filter attribute and reflection elements, find out the properties where the filter is applied.
43
     */
44
    private function getFilterProperties(ApiFilter $filterAttribute, \ReflectionClass $reflectionClass, \ReflectionProperty $reflectionProperty = null): array
45
    {
UNCOV
46
        $properties = [];
×
47

UNCOV
48
        if ($filterAttribute->properties) {
×
UNCOV
49
            foreach ($filterAttribute->properties as $property => $strategy) {
×
UNCOV
50
                if (\is_int($property)) {
×
UNCOV
51
                    $properties[$strategy] = null;
×
52
                } else {
UNCOV
53
                    $properties[$property] = $strategy;
×
54
                }
55
            }
56

UNCOV
57
            return $properties;
×
58
        }
59

UNCOV
60
        if (null !== $reflectionProperty) {
×
UNCOV
61
            $properties[$reflectionProperty->getName()] = $filterAttribute->strategy ?: null;
×
62

UNCOV
63
            return $properties;
×
64
        }
65

UNCOV
66
        if ($filterAttribute->strategy) {
×
UNCOV
67
            foreach ($reflectionClass->getProperties() as $reflectionProperty) {
×
UNCOV
68
                $properties[$reflectionProperty->getName()] = $filterAttribute->strategy;
×
69
            }
70
        }
71

UNCOV
72
        return $properties;
×
73
    }
74

75
    /**
76
     * Reads filter attribute from a ReflectionClass.
77
     *
78
     * @return array Key is the filter id. It has two values, properties and the ApiFilter instance
79
     */
80
    private function readFilterAttributes(\ReflectionClass $reflectionClass): array
81
    {
UNCOV
82
        $filters = [];
×
83

UNCOV
84
        foreach ($this->getFilterAttributes($reflectionClass) as $filterAttribute) {
×
UNCOV
85
            $filterClass = $filterAttribute->filterClass;
×
UNCOV
86
            $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAttribute->id);
×
87

UNCOV
88
            if (!isset($filters[$id])) {
×
UNCOV
89
                $filters[$id] = [$filterAttribute->arguments, $filterClass];
×
90
            }
91

UNCOV
92
            if ($properties = $this->getFilterProperties($filterAttribute, $reflectionClass)) {
×
UNCOV
93
                $filters[$id][0]['properties'] = $properties;
×
94
            }
95
        }
96

UNCOV
97
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
×
UNCOV
98
            foreach ($this->getFilterAttributes($reflectionProperty) as $filterAttribute) {
×
UNCOV
99
                $filterClass = $filterAttribute->filterClass;
×
UNCOV
100
                $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAttribute->id);
×
101

UNCOV
102
                if (!isset($filters[$id])) {
×
UNCOV
103
                    $filters[$id] = [$filterAttribute->arguments, $filterClass];
×
104
                }
105

UNCOV
106
                if ($properties = $this->getFilterProperties($filterAttribute, $reflectionClass, $reflectionProperty)) {
×
UNCOV
107
                    if (isset($filters[$id][0]['properties'])) {
×
UNCOV
108
                        $filters[$id][0]['properties'] = array_merge($filters[$id][0]['properties'], $properties);
×
109
                    } else {
UNCOV
110
                        $filters[$id][0]['properties'] = $properties;
×
111
                    }
112
                }
113
            }
114
        }
115

UNCOV
116
        $parent = $reflectionClass->getParentClass();
×
117

UNCOV
118
        if (false !== $parent) {
×
UNCOV
119
            return array_merge($filters, $this->readFilterAttributes($parent));
×
120
        }
121

UNCOV
122
        return $filters;
×
123
    }
124

125
    /**
126
     * Generates a unique, per-class and per-filter identifier prefixed by `annotated_`.
127
     *
128
     * @param \ReflectionClass $reflectionClass the reflection class of a Resource
129
     * @param string           $filterClass     the filter class
130
     * @param string|null      $filterId        the filter id
131
     */
132
    private function generateFilterId(\ReflectionClass $reflectionClass, string $filterClass, string $filterId = null): string
133
    {
UNCOV
134
        $suffix = null !== $filterId ? '_'.$filterId : $filterId;
×
135

UNCOV
136
        return 'annotated_'.Inflector::tableize(str_replace('\\', '', $reflectionClass->getName().(new \ReflectionClass($filterClass))->getName().$suffix));
×
137
    }
138
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc