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

api-platform / core / 10330093240

10 Aug 2024 07:59AM UTC coverage: 7.84% (-0.001%) from 7.841%
10330093240

push

github

web-flow
chore: remove deprecation (#6508)

1 of 1 new or added line in 1 file covered. (100.0%)

210 existing lines in 19 files now uncovered.

12686 of 161815 relevant lines covered (7.84%)

26.86 hits per line

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

91.49
/src/Metadata/Resource/Factory/OperationDefaultsTrait.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\Resource\Factory;
15

16
use ApiPlatform\Metadata\ApiResource;
17
use ApiPlatform\Metadata\CollectionOperationInterface;
18
use ApiPlatform\Metadata\Delete;
19
use ApiPlatform\Metadata\Exception\RuntimeException;
20
use ApiPlatform\Metadata\Get;
21
use ApiPlatform\Metadata\GetCollection;
22
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
23
use ApiPlatform\Metadata\GraphQl\Mutation;
24
use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation;
25
use ApiPlatform\Metadata\GraphQl\Query;
26
use ApiPlatform\Metadata\GraphQl\QueryCollection;
27
use ApiPlatform\Metadata\GraphQl\Subscription;
28
use ApiPlatform\Metadata\HttpOperation;
29
use ApiPlatform\Metadata\Operation;
30
use ApiPlatform\Metadata\Operations;
31
use ApiPlatform\Metadata\Patch;
32
use ApiPlatform\Metadata\Post;
33
use ApiPlatform\Metadata\Put;
34
use ApiPlatform\Metadata\Util\CamelCaseToSnakeCaseNameConverter;
35
use ApiPlatform\State\CreateProvider;
36
use Psr\Log\LoggerInterface;
37

38
trait OperationDefaultsTrait
39
{
40
    private CamelCaseToSnakeCaseNameConverter $camelCaseToSnakeCaseNameConverter;
41
    private array $defaults = [];
42
    private LoggerInterface $logger;
43

44
    private function addGlobalDefaults(ApiResource|Operation $operation): ApiResource|Operation
45
    {
46
        $extraProperties = $this->defaults['extra_properties'] ?? [];
109✔
47

48
        foreach ($this->defaults as $key => $value) {
109✔
49
            if ('operations' === $key) {
100✔
50
                continue;
×
51
            }
52

53
            $upperKey = ucfirst($this->camelCaseToSnakeCaseNameConverter->denormalize($key));
100✔
54
            $getter = 'get'.$upperKey;
100✔
55

56
            if (!method_exists($operation, $getter)) {
100✔
57
                if (!isset($extraProperties[$key])) {
82✔
58
                    $extraProperties[$key] = $value;
82✔
59
                }
60

61
                continue;
82✔
62
            }
63

64
            $currentValue = $operation->{$getter}();
100✔
65

66
            if (\is_array($currentValue) && $currentValue) {
100✔
67
                $operation = $operation->{'with'.$upperKey}(array_merge($value, $currentValue));
100✔
68
            }
69

70
            if (null !== $currentValue) {
100✔
71
                continue;
100✔
72
            }
73

74
            $operation = $operation->{'with'.$upperKey}($value);
100✔
75
        }
76

77
        return $operation->withExtraProperties(array_merge($extraProperties, $operation->getExtraProperties()));
109✔
78
    }
79

80
    private function getResourceWithDefaults(string $resourceClass, string $shortName, ApiResource $resource): ApiResource
81
    {
82
        $resource = $resource
109✔
83
            ->withShortName($resource->getShortName() ?? $shortName)
109✔
84
            ->withClass($resourceClass);
109✔
85

86
        return $this->addGlobalDefaults($resource);
109✔
87
    }
88

89
    private function getDefaultHttpOperations($resource): iterable
90
    {
91
        if (enum_exists($resource->getClass())) {
50✔
92
            return new Operations([new GetCollection(paginationEnabled: false), new Get()]);
10✔
93
        }
94

95
        if (($defaultOperations = $this->defaults['operations'] ?? null) && null === $resource->getOperations()) {
44✔
96
            $operations = [];
×
97

98
            foreach ($defaultOperations as $defaultOperation) {
×
99
                $operations[] = new $defaultOperation();
×
100
            }
101

102
            return new Operations($operations);
×
103
        }
104

105
        $post = new Post();
44✔
106
        if ($resource->getUriTemplate() && !$resource->getProvider()) {
44✔
UNCOV
107
            $post = $post->withProvider(CreateProvider::class);
3✔
108
        }
109

110
        return [new Get(), new GetCollection(), $post, new Put(), new Patch(), new Delete()];
44✔
111
    }
112

113
    private function addDefaultGraphQlOperations(ApiResource $resource): ApiResource
114
    {
115
        $operations = enum_exists($resource->getClass()) ? [new QueryCollection(paginationEnabled: false), new Query()] : [new QueryCollection(), new Query(), (new Mutation())->withName('update'), (new DeleteMutation())->withName('delete'), (new Mutation())->withName('create')];
63✔
116
        $graphQlOperations = [];
63✔
117
        foreach ($operations as $operation) {
63✔
118
            [$key, $operation] = $this->getOperationWithDefaults($resource, $operation);
63✔
119
            $graphQlOperations[$key] = $operation;
63✔
120
        }
121

122
        if ($resource->getMercure()) {
63✔
123
            [$key, $operation] = $this->getOperationWithDefaults($resource, (new Subscription())->withDescription("Subscribes to the update event of a {$operation->getShortName()}."));
6✔
124
            $graphQlOperations[$key] = $operation;
6✔
125
        }
126

127
        return $resource->withGraphQlOperations($graphQlOperations);
63✔
128
    }
129

130
    /**
131
     * Adds nested query operations if there are no existing query ones on the resource.
132
     * They are needed when the resource is queried inside a root query, using a relation.
133
     * Since the nested argument is used, root queries will not be generated for these operations.
134
     */
135
    private function completeGraphQlOperations(ApiResource $resource): ApiResource
136
    {
137
        $graphQlOperations = $resource->getGraphQlOperations();
26✔
138

139
        $hasQueryOperation = false;
26✔
140
        $hasQueryCollectionOperation = false;
26✔
141
        foreach ($graphQlOperations as $operation) {
26✔
142
            if ($operation instanceof Query && !$operation instanceof QueryCollection) {
20✔
143
                $hasQueryOperation = true;
17✔
144
            }
145
            if ($operation instanceof QueryCollection) {
20✔
146
                $hasQueryCollectionOperation = true;
11✔
147
            }
148
        }
149

150
        if (!$hasQueryOperation) {
26✔
151
            $queryOperation = (new Query())->withNested(true);
12✔
152
            $graphQlOperations[$queryOperation->getName()] = $queryOperation;
12✔
153
        }
154
        if (!$hasQueryCollectionOperation) {
26✔
155
            $queryCollectionOperation = (new QueryCollection())->withNested(true);
19✔
156
            $graphQlOperations[$queryCollectionOperation->getName()] = $queryCollectionOperation;
19✔
157
        }
158

159
        return $resource->withGraphQlOperations($graphQlOperations);
26✔
160
    }
161

162
    private function getOperationWithDefaults(ApiResource $resource, Operation $operation, bool $generated = false, array $ignoredOptions = []): array
163
    {
164
        // Inherit from resource defaults
165
        foreach (get_class_methods($resource) as $methodName) {
109✔
166
            if (!str_starts_with($methodName, 'get')) {
109✔
167
                continue;
109✔
168
            }
169

170
            if (\in_array(lcfirst(substr($methodName, 3)), $ignoredOptions, true)) {
109✔
171
                continue;
20✔
172
            }
173

174
            if (!method_exists($operation, $methodName) || null !== $operation->{$methodName}()) {
109✔
175
                continue;
109✔
176
            }
177

178
            if (null === ($value = $resource->{$methodName}())) {
109✔
179
                continue;
109✔
180
            }
181

182
            $operation = $operation->{'with'.substr($methodName, 3)}($value);
109✔
183
        }
184

185
        $operation = $operation->withExtraProperties(array_merge(
109✔
186
            $resource->getExtraProperties(),
109✔
187
            $operation->getExtraProperties(),
109✔
188
            $generated ? ['generated_operation' => true] : []
109✔
189
        ));
109✔
190

191
        // Add global defaults attributes to the operation
192
        $operation = $this->addGlobalDefaults($operation);
109✔
193

194
        if ($operation instanceof GraphQlOperation) {
109✔
195
            if (!$operation->getName()) {
82✔
196
                throw new RuntimeException('No GraphQL operation name.');
×
197
            }
198

199
            if ($operation instanceof Mutation) {
82✔
200
                $operation = $operation->withDescription(ucfirst("{$operation->getName()}s a {$resource->getShortName()}."));
68✔
201
            }
202

203
            return [$operation->getName(), $operation];
82✔
204
        }
205

206
        if (!$operation instanceof HttpOperation) {
109✔
207
            throw new RuntimeException(\sprintf('Operation should be an instance of "%s"', HttpOperation::class));
×
208
        }
209

210
        if (!$operation->getName() && $operation->getRouteName()) {
109✔
211
            /** @var HttpOperation $operation */
UNCOV
212
            $operation = $operation->withName($operation->getRouteName());
3✔
213
        }
214

215
        $operationName = $operation->getName() ?? $this->getDefaultOperationName($operation, $resource->getClass());
109✔
216

217
        return [
109✔
218
            $operationName,
109✔
219
            $operation,
109✔
220
        ];
109✔
221
    }
222

223
    private function getDefaultShortname(string $resourceClass): string
224
    {
225
        return (false !== $pos = strrpos($resourceClass, '\\')) ? substr($resourceClass, $pos + 1) : $resourceClass;
×
226
    }
227

228
    private function getDefaultOperationName(HttpOperation $operation, string $resourceClass): string
229
    {
230
        $path = ($operation->getRoutePrefix() ?? '').($operation->getUriTemplate() ?? '');
108✔
231

232
        return \sprintf(
108✔
233
            '_api_%s_%s%s',
108✔
234
            $path ?: ($operation->getShortName() ?? $this->getDefaultShortname($resourceClass)),
108✔
235
            strtolower($operation->getMethod()),
108✔
236
            $operation instanceof CollectionOperationInterface ? '_collection' : '');
108✔
237
    }
238
}
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