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

api-platform / core / 3711198772

pending completion
3711198772

push

github

GitHub
fix(jsonschema): remove @id @type @context from input schema  (#5267)

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

7447 of 12203 relevant lines covered (61.03%)

82.13 hits per line

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

68.18
/src/Metadata/Extractor/XmlResourceExtractor.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\Extractor;
15

16
use ApiPlatform\Exception\InvalidArgumentException;
17
use ApiPlatform\Metadata\GetCollection;
18
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
19
use ApiPlatform\Metadata\GraphQl\Mutation;
20
use ApiPlatform\Metadata\GraphQl\Query;
21
use ApiPlatform\Metadata\GraphQl\QueryCollection;
22
use ApiPlatform\Metadata\GraphQl\Subscription;
23
use ApiPlatform\Metadata\Post;
24
use Symfony\Component\Config\Util\XmlUtils;
25

26
/**
27
 * Extracts an array of metadata from a list of XML files.
28
 *
29
 * @author Vincent Chalamon <vincentchalamon@gmail.com>
30
 */
31
final class XmlResourceExtractor extends AbstractResourceExtractor
32
{
33
    use ResourceExtractorTrait;
34

35
    public const SCHEMA = __DIR__.'/schema/resources.xsd';
36

37
    /**
38
     * {@inheritdoc}
39
     */
40
    protected function extractPath(string $path): void
41
    {
42
        try {
43
            /** @var \SimpleXMLElement $xml */
44
            $xml = simplexml_import_dom(XmlUtils::loadFile($path, self::SCHEMA));
22✔
45
        } catch (\InvalidArgumentException $e) {
22✔
46
            // Ensure it's not a resource
47
            try {
48
                simplexml_import_dom(XmlUtils::loadFile($path, XmlPropertyExtractor::SCHEMA));
22✔
49
            } catch (\InvalidArgumentException) {
×
50
                throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
×
51
            }
52

53
            // It's a property: ignore error
54
            return;
22✔
55
        }
56

57
        foreach ($xml->resource as $resource) {
22✔
58
            $base = $this->buildExtendedBase($resource);
22✔
59
            $this->resources[$this->resolve((string) $resource['class'])][] = array_merge($base, [
22✔
60
                'class' => $this->phpize($resource, 'class', 'string'),
22✔
61
                'operations' => $this->buildOperations($resource, $base),
22✔
62
                'graphQlOperations' => $this->buildGraphQlOperations($resource, $base),
22✔
63
            ]);
22✔
64
        }
65
    }
66

67
    private function buildExtendedBase(\SimpleXMLElement $resource): array
68
    {
69
        return array_merge($this->buildBase($resource), [
22✔
70
            'uriTemplate' => $this->phpize($resource, 'uriTemplate', 'string'),
22✔
71
            'routePrefix' => $this->phpize($resource, 'routePrefix', 'string'),
22✔
72
            'stateless' => $this->phpize($resource, 'stateless', 'bool'),
22✔
73
            'sunset' => $this->phpize($resource, 'sunset', 'string'),
22✔
74
            'acceptPatch' => $this->phpize($resource, 'acceptPatch', 'string'),
22✔
75
            'status' => $this->phpize($resource, 'status', 'integer'),
22✔
76
            'host' => $this->phpize($resource, 'host', 'string'),
22✔
77
            'condition' => $this->phpize($resource, 'condition', 'string'),
22✔
78
            'controller' => $this->phpize($resource, 'controller', 'string'),
22✔
79
            'types' => $this->buildArrayValue($resource, 'type'),
22✔
80
            'formats' => $this->buildFormats($resource, 'formats'),
22✔
81
            'inputFormats' => $this->buildFormats($resource, 'inputFormats'),
22✔
82
            'outputFormats' => $this->buildFormats($resource, 'outputFormats'),
22✔
83
            'uriVariables' => $this->buildUriVariables($resource),
22✔
84
            'defaults' => isset($resource->defaults->values) ? $this->buildValues($resource->defaults->values) : null,
22✔
85
            'requirements' => $this->buildRequirements($resource),
22✔
86
            'options' => isset($resource->options->values) ? $this->buildValues($resource->options->values) : null,
22✔
87
            'schemes' => $this->buildArrayValue($resource, 'scheme'),
22✔
88
            'cacheHeaders' => $this->buildCacheHeaders($resource),
22✔
89
            'hydraContext' => isset($resource->hydraContext->values) ? $this->buildValues($resource->hydraContext->values) : null,
22✔
90
            'openapiContext' => isset($resource->openapiContext->values) ? $this->buildValues($resource->openapiContext->values) : null,
22✔
91
            'paginationViaCursor' => $this->buildPaginationViaCursor($resource),
22✔
92
            'exceptionToStatus' => $this->buildExceptionToStatus($resource),
22✔
93
            'queryParameterValidationEnabled' => $this->phpize($resource, 'queryParameterValidationEnabled', 'bool'),
22✔
94
        ]);
22✔
95
    }
96

97
    private function buildBase(\SimpleXMLElement $resource): array
98
    {
99
        return [
22✔
100
            'shortName' => $this->phpize($resource, 'shortName', 'string'),
22✔
101
            'description' => $this->phpize($resource, 'description', 'string'),
22✔
102
            'urlGenerationStrategy' => $this->phpize($resource, 'urlGenerationStrategy', 'integer'),
22✔
103
            'deprecationReason' => $this->phpize($resource, 'deprecationReason', 'string'),
22✔
104
            'elasticsearch' => $this->phpize($resource, 'elasticsearch', 'bool'),
22✔
105
            'messenger' => $this->phpize($resource, 'messenger', 'bool|string'),
22✔
106
            'mercure' => $this->buildMercure($resource),
22✔
107
            'input' => $this->phpize($resource, 'input', 'bool|string'),
22✔
108
            'output' => $this->phpize($resource, 'output', 'bool|string'),
22✔
109
            'fetchPartial' => $this->phpize($resource, 'fetchPartial', 'bool'),
22✔
110
            'forceEager' => $this->phpize($resource, 'forceEager', 'bool'),
22✔
111
            'paginationClientEnabled' => $this->phpize($resource, 'paginationClientEnabled', 'bool'),
22✔
112
            'paginationClientItemsPerPage' => $this->phpize($resource, 'paginationClientItemsPerPage', 'bool'),
22✔
113
            'paginationClientPartial' => $this->phpize($resource, 'paginationClientPartial', 'bool'),
22✔
114
            'paginationEnabled' => $this->phpize($resource, 'paginationEnabled', 'bool'),
22✔
115
            'paginationFetchJoinCollection' => $this->phpize($resource, 'paginationFetchJoinCollection', 'bool'),
22✔
116
            'paginationUseOutputWalkers' => $this->phpize($resource, 'paginationUseOutputWalkers', 'bool'),
22✔
117
            'paginationItemsPerPage' => $this->phpize($resource, 'paginationItemsPerPage', 'integer'),
22✔
118
            'paginationMaximumItemsPerPage' => $this->phpize($resource, 'paginationMaximumItemsPerPage', 'integer'),
22✔
119
            'paginationPartial' => $this->phpize($resource, 'paginationPartial', 'bool'),
22✔
120
            'paginationType' => $this->phpize($resource, 'paginationType', 'string'),
22✔
121
            'processor' => $this->phpize($resource, 'processor', 'string'),
22✔
122
            'provider' => $this->phpize($resource, 'provider', 'string'),
22✔
123
            'security' => $this->phpize($resource, 'security', 'string'),
22✔
124
            'securityMessage' => $this->phpize($resource, 'securityMessage', 'string'),
22✔
125
            'securityPostDenormalize' => $this->phpize($resource, 'securityPostDenormalize', 'string'),
22✔
126
            'securityPostDenormalizeMessage' => $this->phpize($resource, 'securityPostDenormalizeMessage', 'string'),
22✔
127
            'securityPostValidation' => $this->phpize($resource, 'securityPostValidation', 'string'),
22✔
128
            'securityPostValidationMessage' => $this->phpize($resource, 'securityPostValidationMessage', 'string'),
22✔
129
            'normalizationContext' => isset($resource->normalizationContext->values) ? $this->buildValues($resource->normalizationContext->values) : null,
22✔
130
            'denormalizationContext' => isset($resource->denormalizationContext->values) ? $this->buildValues($resource->denormalizationContext->values) : null,
22✔
131
            'validationContext' => isset($resource->validationContext->values) ? $this->buildValues($resource->validationContext->values) : null,
22✔
132
            'filters' => $this->buildArrayValue($resource, 'filter'),
22✔
133
            'order' => isset($resource->order->values) ? $this->buildValues($resource->order->values) : null,
22✔
134
            'extraProperties' => $this->buildExtraProperties($resource, 'extraProperties'),
22✔
135
            'read' => $this->phpize($resource, 'read', 'bool'),
22✔
136
            'write' => $this->phpize($resource, 'write', 'bool'),
22✔
137
        ];
22✔
138
    }
139

140
    private function buildFormats(\SimpleXMLElement $resource, string $key): ?array
141
    {
142
        if (!isset($resource->{$key}->format)) {
22✔
143
            return null;
22✔
144
        }
145

146
        $data = [];
×
147
        foreach ($resource->{$key}->format as $format) {
×
148
            if (isset($format['name'])) {
×
149
                $data[(string) $format['name']] = (string) $format;
×
150
                continue;
×
151
            }
152

153
            $data[] = (string) $format;
×
154
        }
155

156
        return $data;
×
157
    }
158

159
    private function buildUriVariables(\SimpleXMLElement $resource): ?array
160
    {
161
        if (!isset($resource->uriVariables->uriVariable)) {
22✔
162
            return null;
22✔
163
        }
164

165
        $uriVariables = [];
22✔
166
        foreach ($resource->uriVariables->uriVariable as $data) {
22✔
167
            $parameterName = (string) $data['parameterName'];
22✔
168
            if (1 === (null === $data->attributes() ? 0 : \count($data->attributes()))) {
22✔
169
                $uriVariables[$parameterName] = $parameterName;
22✔
170
                continue;
22✔
171
            }
172

173
            if ($fromProperty = $this->phpize($data, 'fromProperty', 'string')) {
22✔
174
                $uriVariables[$parameterName]['from_property'] = $fromProperty;
×
175
            }
176
            if ($toProperty = $this->phpize($data, 'toProperty', 'string')) {
22✔
177
                $uriVariables[$parameterName]['to_property'] = $toProperty;
22✔
178
            }
179
            if ($fromClass = $this->phpize($data, 'fromClass', 'string')) {
22✔
180
                $uriVariables[$parameterName]['from_class'] = $fromClass;
22✔
181
            }
182
            if ($toClass = $this->phpize($data, 'toClass', 'string')) {
22✔
183
                $uriVariables[$parameterName]['to_class'] = $toClass;
×
184
            }
185
            if (isset($data->identifiers->values)) {
22✔
186
                $uriVariables[$parameterName]['identifiers'] = $this->buildValues($data->identifiers->values);
×
187
            }
188
            if (null !== ($compositeIdentifier = $this->phpize($data, 'compositeIdentifier', 'bool'))) {
22✔
189
                $uriVariables[$parameterName]['composite_identifier'] = $compositeIdentifier;
×
190
            }
191
        }
192

193
        return $uriVariables;
22✔
194
    }
195

196
    private function buildCacheHeaders(\SimpleXMLElement $resource): ?array
197
    {
198
        if (!isset($resource->cacheHeaders->cacheHeader)) {
22✔
199
            return null;
22✔
200
        }
201

202
        $data = [];
×
203
        foreach ($resource->cacheHeaders->cacheHeader as $cacheHeader) {
×
204
            if (isset($cacheHeader->values->value)) {
×
205
                $data[(string) $cacheHeader['name']] = $this->buildValues($cacheHeader->values);
×
206
                continue;
×
207
            }
208

209
            $data[(string) $cacheHeader['name']] = (string) $cacheHeader;
×
210
        }
211

212
        return $data;
×
213
    }
214

215
    private function buildRequirements(\SimpleXMLElement $resource): ?array
216
    {
217
        if (!isset($resource->requirements->requirement)) {
22✔
218
            return null;
22✔
219
        }
220

221
        $data = [];
×
222
        foreach ($resource->requirements->requirement as $requirement) {
×
223
            $data[(string) $requirement->attributes()->property] = (string) $requirement;
×
224
        }
225

226
        return $data;
×
227
    }
228

229
    private function buildMercure(\SimpleXMLElement $resource): array|bool|null
230
    {
231
        if (!isset($resource->mercure)) {
22✔
232
            return null;
22✔
233
        }
234

235
        if (null !== $resource->mercure->attributes()->private) {
×
236
            return ['private' => $this->phpize($resource->mercure->attributes(), 'private', 'bool')];
×
237
        }
238

239
        return true;
×
240
    }
241

242
    private function buildPaginationViaCursor(\SimpleXMLElement $resource): ?array
243
    {
244
        if (!isset($resource->paginationViaCursor->paginationField)) {
22✔
245
            return null;
22✔
246
        }
247

248
        $data = [];
×
249
        foreach ($resource->paginationViaCursor->paginationField as $paginationField) {
×
250
            $data[(string) $paginationField['field']] = (string) $paginationField['direction'];
×
251
        }
252

253
        return $data;
×
254
    }
255

256
    private function buildExceptionToStatus(\SimpleXMLElement $resource): ?array
257
    {
258
        if (!isset($resource->exceptionToStatus->exception)) {
22✔
259
            return null;
22✔
260
        }
261

262
        $data = [];
×
263
        foreach ($resource->exceptionToStatus->exception as $exception) {
×
264
            $data[(string) $exception['class']] = (int) $exception['statusCode'];
×
265
        }
266

267
        return $data;
×
268
    }
269

270
    private function buildExtraProperties(\SimpleXMLElement $resource, string $key = null): ?array
271
    {
272
        if (null !== $key) {
22✔
273
            if (!isset($resource->{$key})) {
22✔
274
                return null;
22✔
275
            }
276

277
            $resource = $resource->{$key};
×
278
        }
279

280
        return $this->buildValues($resource->values);
×
281
    }
282

283
    private function buildOperations(\SimpleXMLElement $resource, array $root): ?array
284
    {
285
        if (!isset($resource->operations->operation)) {
22✔
286
            return null;
22✔
287
        }
288

289
        $data = [];
22✔
290
        foreach ($resource->operations->operation as $operation) {
22✔
291
            $datum = $this->buildExtendedBase($operation);
22✔
292
            foreach ($datum as $key => $value) {
22✔
293
                if (null === $value) {
22✔
294
                    $datum[$key] = $root[$key];
22✔
295
                }
296
            }
297

298
            if (\in_array((string) $operation['class'], [GetCollection::class, Post::class], true)) {
22✔
299
                $datum['itemUriTemplate'] = $this->phpize($operation, 'itemUriTemplate', 'string');
22✔
300
            }
301

302
            $data[] = array_merge($datum, [
22✔
303
                'openapi' => $this->phpize($operation, 'openapi', 'bool'),
22✔
304
                'collection' => $this->phpize($operation, 'collection', 'bool'),
22✔
305
                'class' => (string) $operation['class'],
22✔
306
                'method' => $this->phpize($operation, 'method', 'string'),
22✔
307
                'read' => $this->phpize($operation, 'read', 'bool'),
22✔
308
                'deserialize' => $this->phpize($operation, 'deserialize', 'bool'),
22✔
309
                'validate' => $this->phpize($operation, 'validate', 'bool'),
22✔
310
                'write' => $this->phpize($operation, 'write', 'bool'),
22✔
311
                'serialize' => $this->phpize($operation, 'serialize', 'bool'),
22✔
312
                'queryParameterValidate' => $this->phpize($operation, 'queryParameterValidate', 'bool'),
22✔
313
                'priority' => $this->phpize($operation, 'priority', 'integer'),
22✔
314
                'name' => $this->phpize($operation, 'name', 'string'),
22✔
315
            ]);
22✔
316
        }
317

318
        return $data;
22✔
319
    }
320

321
    private function buildGraphQlOperations(\SimpleXMLElement $resource, array $root): ?array
322
    {
323
        if (!isset($resource->graphQlOperations->mutation) && !isset($resource->graphQlOperations->query) && !isset($resource->graphQlOperations->subscription)) {
22✔
324
            return null;
22✔
325
        }
326

327
        $data = [];
×
328
        foreach (['mutation' => Mutation::class, 'query' => Query::class, 'subscription' => Subscription::class] as $type => $class) {
×
329
            foreach ($resource->graphQlOperations->{$type} as $operation) {
×
330
                $datum = $this->buildBase($operation);
×
331
                foreach ($datum as $key => $value) {
×
332
                    if (null === $value) {
×
333
                        $datum[$key] = $root[$key];
×
334
                    }
335
                }
336

337
                $collection = $this->phpize($operation, 'collection', 'bool', false);
×
338
                if (Query::class === $class && $collection) {
×
339
                    $class = QueryCollection::class;
×
340
                }
341

342
                $delete = $this->phpize($operation, 'delete', 'bool', false);
×
343
                if (Mutation::class === $class && $delete) {
×
344
                    $class = DeleteMutation::class;
×
345
                }
346

347
                $data[] = array_merge($datum, [
×
348
                    'graphql_operation_class' => $class,
×
349
                    'resolver' => $this->phpize($operation, 'resolver', 'string'),
×
350
                    'args' => $this->buildArgs($operation),
×
351
                    'class' => $this->phpize($operation, 'class', 'string'),
×
352
                    'read' => $this->phpize($operation, 'read', 'bool'),
×
353
                    'deserialize' => $this->phpize($operation, 'deserialize', 'bool'),
×
354
                    'validate' => $this->phpize($operation, 'validate', 'bool'),
×
355
                    'write' => $this->phpize($operation, 'write', 'bool'),
×
356
                    'serialize' => $this->phpize($operation, 'serialize', 'bool'),
×
357
                    'priority' => $this->phpize($operation, 'priority', 'integer'),
×
358
                ]);
×
359
            }
360
        }
361

362
        return $data;
×
363
    }
364
}
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