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

api-platform / core / 15133993414

20 May 2025 09:30AM UTC coverage: 26.313% (-1.2%) from 27.493%
15133993414

Pull #7161

github

web-flow
Merge e2c03d45f into 5459ba375
Pull Request #7161: fix(metadata): infer parameter string type from schema

0 of 2 new or added lines in 1 file covered. (0.0%)

11019 existing lines in 363 files now uncovered.

12898 of 49018 relevant lines covered (26.31%)

34.33 hits per line

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

100.0
/src/Metadata/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\Metadata\Util;
15

16
use ApiPlatform\Metadata\ApiFilter;
17
use Symfony\Component\String\UnicodeString;
18

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

UNCOV
37
        foreach ($attributes as $attribute) {
71✔
UNCOV
38
            yield $attribute->newInstance();
18✔
39
        }
40
    }
41

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

UNCOV
49
        if ($filterAttribute->properties) {
18✔
UNCOV
50
            foreach ($filterAttribute->properties as $property => $strategy) {
14✔
UNCOV
51
                if (\is_int($property)) {
14✔
UNCOV
52
                    $properties[$strategy] = $properties[$strategy] = null !== $reflectionProperty ? $filterAttribute->strategy : null;
12✔
53
                } else {
UNCOV
54
                    $properties[$property] = $strategy;
7✔
55
                }
56
            }
57

UNCOV
58
            return $properties;
14✔
59
        }
60

UNCOV
61
        if (null !== $reflectionProperty) {
11✔
UNCOV
62
            $properties[$reflectionProperty->getName()] = $filterAttribute->strategy ?: null;
8✔
63

UNCOV
64
            return $properties;
8✔
65
        }
66

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

UNCOV
73
        return $properties;
7✔
74
    }
75

76
    /**
77
     * Reads filter attribute from a ReflectionClass.
78
     *
79
     * @return array<string, array{array<string, mixed>, class-string, ApiFilter}> indexed by the filter id, the filter tuple has the filter arguments, the filter class and the ApiFilter attribute instance
80
     */
81
    private function readFilterAttributes(\ReflectionClass $reflectionClass): array
82
    {
UNCOV
83
        $filters = [];
71✔
84

UNCOV
85
        foreach ($this->getFilterAttributes($reflectionClass) as $filterAttribute) {
71✔
UNCOV
86
            $filterClass = $filterAttribute->filterClass;
17✔
UNCOV
87
            $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAttribute->id ?? $filterAttribute->alias);
17✔
88

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

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

UNCOV
98
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
71✔
UNCOV
99
            foreach ($this->getFilterAttributes($reflectionProperty) as $filterAttribute) {
65✔
UNCOV
100
                $filterClass = $filterAttribute->filterClass;
8✔
UNCOV
101
                $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAttribute->id ?? $filterAttribute->alias);
8✔
102

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

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

UNCOV
117
        $parent = $reflectionClass->getParentClass();
71✔
118

UNCOV
119
        if (false !== $parent) {
71✔
UNCOV
120
            return array_merge($filters, $this->readFilterAttributes($parent));
10✔
121
        }
122

UNCOV
123
        return $filters;
71✔
124
    }
125

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

UNCOV
137
        return 'annotated_'.(new UnicodeString(str_replace('\\', '', $reflectionClass->getName().(new \ReflectionClass($filterClass))->getName().$suffix)))->snake()->toString();
18✔
138
    }
139
}
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