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

api-platform / core / 15775135891

20 Jun 2025 08:42AM UTC coverage: 22.065% (+0.2%) from 21.876%
15775135891

push

github

soyuka
Merge 4.1

13 of 103 new or added lines in 10 files covered. (12.62%)

868 existing lines in 35 files now uncovered.

11487 of 52060 relevant lines covered (22.06%)

21.72 hits per line

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

0.0
/src/Metadata/Tests/Extractor/Adapter/XmlResourceAdapter.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\Tests\Extractor\Adapter;
15

16
use ApiPlatform\Metadata\Tests\Extractor\ResourceMetadataCompatibilityTest;
17

18
/**
19
 * XML adapter for ResourceMetadataCompatibilityTest.
20
 *
21
 * @author Vincent Chalamon <vincentchalamon@gmail.com>
22
 */
23
final class XmlResourceAdapter implements ResourceAdapterInterface
24
{
25
    private const ATTRIBUTES = [
26
        'uriTemplate',
27
        'shortName',
28
        'description',
29
        'routePrefix',
30
        'stateless',
31
        'sunset',
32
        'class',
33
        'acceptPatch',
34
        'status',
35
        'host',
36
        'condition',
37
        'controller',
38
        'urlGenerationStrategy',
39
        'deprecationReason',
40
        'messenger',
41
        'input',
42
        'output',
43
        'fetchPartial',
44
        'forceEager',
45
        'paginationClientEnabled',
46
        'paginationClientItemsPerPage',
47
        'paginationClientPartial',
48
        'paginationEnabled',
49
        'paginationFetchJoinCollection',
50
        'paginationUseOutputWalkers',
51
        'paginationItemsPerPage',
52
        'paginationMaximumItemsPerPage',
53
        'paginationPartial',
54
        'paginationType',
55
        'processor',
56
        'provider',
57
        'security',
58
        'securityMessage',
59
        'securityPostDenormalize',
60
        'securityPostDenormalizeMessage',
61
        'securityPostValidation',
62
        'securityPostValidationMessage',
63
        'queryParameterValidationEnabled',
64
        'strictQueryParameterValidation',
65
        'hideHydraOperation',
66
        'stateOptions',
67
        'collectDenormalizationErrors',
68
        'links',
69
        'parameters',
70
    ];
71

72
    private const EXCLUDE = ['policy', 'middleware', 'rule'];
73

74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function __invoke(string $resourceClass, array $parameters, array $fixtures): array
78
    {
UNCOV
79
        $xml = new \SimpleXMLElement(<<<XML_WRAP
×
80
<?xml version="1.0" encoding="UTF-8" ?>
81
<resources xmlns="https://api-platform.com/schema/metadata/resources-3.0"
82
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
83
           xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
84
           https://api-platform.com/schema/metadata/resources-3.0.xsd">
85
</resources>
UNCOV
86
XML_WRAP
×
87
        );
×
88

UNCOV
89
        foreach ($fixtures as $fixture) {
×
90
            $resource = $xml->addChild('resource');
×
91

UNCOV
92
            if (null === $fixture) {
×
93
                $resource->addAttribute('class', $resourceClass);
×
94
                continue;
×
95
            }
96

UNCOV
97
            $fixture['class'] = $resourceClass;
×
98
            foreach ($parameters as $parameter) {
×
99
                $parameterName = $parameter->getName();
×
100
                if (\in_array($parameterName, self::EXCLUDE, true)) {
×
101
                    continue;
×
102
                }
103

UNCOV
104
                $value = \array_key_exists($parameterName, $fixture) ? $fixture[$parameterName] : null;
×
105

UNCOV
106
                if ('compositeIdentifier' === $parameterName || 'provider' === $parameterName || 'processor' === $parameterName) {
×
107
                    continue;
×
108
                }
109

UNCOV
110
                if (method_exists($this, 'build'.ucfirst($parameterName))) {
×
111
                    $this->{'build'.ucfirst($parameterName)}($resource, $value);
×
112
                    continue;
×
113
                }
114

UNCOV
115
                if (\in_array($parameterName, self::ATTRIBUTES, true) && \is_scalar($value)) {
×
116
                    $resource->addAttribute($parameterName, $this->parse($value));
×
117
                    continue;
×
118
                }
119

UNCOV
120
                throw new \LogicException(\sprintf('Cannot adapt attribute or child "%s". Please add fixtures in '.ResourceMetadataCompatibilityTest::class.' and create a "%s" method in %s.', $parameterName, 'build'.ucfirst($parameterName), self::class));
×
121
            }
122
        }
123

UNCOV
124
        $filename = __DIR__.'/resources.xml';
×
125
        $xml->asXML($filename);
×
126

UNCOV
127
        return [$filename];
×
128
    }
129

130
    private function buildTypes(\SimpleXMLElement $resource, array $values): void
131
    {
UNCOV
132
        $node = $resource->addChild('types');
×
133
        foreach ($values as $value) {
×
134
            $node->addChild('type', $value);
×
135
        }
136
    }
137

138
    private function buildInputFormats(\SimpleXMLElement $resource, array $values): void
139
    {
UNCOV
140
        $this->buildFormats($resource, $values, 'inputFormats');
×
141
    }
142

143
    private function buildOutputFormats(\SimpleXMLElement $resource, array $values): void
144
    {
UNCOV
145
        $this->buildFormats($resource, $values, 'outputFormats');
×
146
    }
147

148
    private function buildUriVariables(\SimpleXMLElement $resource, array $values): void
149
    {
UNCOV
150
        $child = $resource->addChild('uriVariables');
×
151
        foreach ($values as $parameterName => $value) {
×
152
            $grandChild = $child->addChild('uriVariable');
×
153
            $grandChild->addAttribute('parameterName', $parameterName);
×
154
            if (!isset($value['fromClass'])) {
×
155
                $value['fromClass'] = $value[0];
×
156
                $value['fromProperty'] = $value[1];
×
157
                unset($value[0], $value[1]);
×
158
            }
UNCOV
159
            foreach ($value as $key => $data) {
×
160
                $grandChild->addAttribute($key, $this->parse($data));
×
161
            }
162
        }
163
    }
164

165
    private function buildDefaults(\SimpleXMLElement $resource, array $values): void
166
    {
UNCOV
167
        $this->buildValues($resource->addChild('defaults'), $values);
×
168
    }
169

170
    private function buildMercure(\SimpleXMLElement $resource, $values): void
171
    {
UNCOV
172
        $child = $resource->addChild('mercure');
×
173
        if (\is_array($values)) {
×
174
            foreach ($values as $key => $value) {
×
175
                if (\is_string($key)) {
×
176
                    $child->addAttribute($key, $this->parse($value));
×
177
                }
178
            }
179
        }
180
    }
181

182
    private function buildRequirements(\SimpleXMLElement $resource, array $values): void
183
    {
UNCOV
184
        $node = $resource->addChild('requirements');
×
185
        foreach ($values as $key => $value) {
×
186
            $node->addChild('requirement', $value)->addAttribute('property', $key);
×
187
        }
188
    }
189

190
    private function buildOptions(\SimpleXMLElement $resource, array $values): void
191
    {
UNCOV
192
        $this->buildValues($resource->addChild('options'), $values);
×
193
    }
194

195
    private function buildSchemes(\SimpleXMLElement $resource, array $values): void
196
    {
UNCOV
197
        $node = $resource->addChild('schemes');
×
198
        foreach ($values as $value) {
×
199
            $node->addChild('scheme', $value);
×
200
        }
201
    }
202

203
    private function buildCacheHeaders(\SimpleXMLElement $resource, array $values): void
204
    {
UNCOV
205
        $node = $resource->addChild('cacheHeaders');
×
206
        foreach ($values as $key => $value) {
×
207
            if (\is_array($value)) {
×
208
                $child = $node->addChild('cacheHeader');
×
209
                $this->buildValues($child, $value);
×
210
            } else {
UNCOV
211
                $child = $node->addChild('cacheHeader', $this->parse($value));
×
212
            }
UNCOV
213
            $child->addAttribute('name', $key);
×
214
        }
215
    }
216

217
    private function buildNormalizationContext(\SimpleXMLElement $resource, array $values): void
218
    {
UNCOV
219
        $this->buildValues($resource->addChild('normalizationContext'), $values);
×
220
    }
221

222
    private function buildDenormalizationContext(\SimpleXMLElement $resource, array $values): void
223
    {
UNCOV
224
        $this->buildValues($resource->addChild('denormalizationContext'), $values);
×
225
    }
226

227
    private function buildHydraContext(\SimpleXMLElement $resource, array $values): void
228
    {
UNCOV
229
        $this->buildValues($resource->addChild('hydraContext'), $values);
×
230
    }
231

232
    private function buildOpenapi(\SimpleXMLElement $resource, array $values): void
233
    {
UNCOV
234
        $node = $resource->openapi ?? $resource->addChild('openapi');
×
235

UNCOV
236
        if (isset($values['tags'])) {
×
237
            $tagsNode = $node->tags ?? $node->addChild('tags');
×
238
            foreach ($values['tags'] as $tag) {
×
239
                $tagsNode->addChild('tag', $tag);
×
240
            }
241
        }
242

UNCOV
243
        if (isset($values['responses'])) {
×
244
            $responsesNode = $node->responses ?? $node->addChild('responses');
×
245
            foreach ($values['responses'] as $status => $response) {
×
246
                $responseNode = $responsesNode->addChild('response');
×
247
                $responseNode->addAttribute('status', $status);
×
248
                if (isset($response['description'])) {
×
249
                    $responseNode->addAttribute('description', $response['description']);
×
250
                }
UNCOV
251
                if (isset($response['content'])) {
×
252
                    $this->buildValues($responseNode->addChild('content'), $response['content']);
×
253
                }
UNCOV
254
                if (isset($response['headers'])) {
×
255
                    $this->buildValues($responseNode->addChild('headers'), $response['headers']);
×
256
                }
UNCOV
257
                if (isset($response['links'])) {
×
258
                    $this->buildValues($responseNode->addChild('links'), $response['links']);
×
259
                }
260
            }
261
        }
262

UNCOV
263
        if (isset($values['externalDocs'])) {
×
264
            $externalDocsNode = $node->externalDocs ?? $node->addChild('externalDocs');
×
265
            if (isset($values['externalDocs']['description'])) {
×
266
                $externalDocsNode->addAttribute('description', $values['externalDocs']['description']);
×
267
            }
UNCOV
268
            if (isset($values['url']['description'])) {
×
269
                $externalDocsNode->addAttribute('url', $values['externalDocs']['url']);
×
270
            }
271
        }
272

UNCOV
273
        if (isset($values['parameters'])) {
×
274
            $parametersNode = $node->parameters ?? $node->addChild('parameters');
×
275
            foreach ($values['parameters'] as $name => $parameter) {
×
276
                $parameterNode = $parametersNode->addChild('parameter');
×
277
                $parameterNode->addAttribute('name', $name);
×
278
                if (isset($parameter['in'])) {
×
279
                    $parameterNode->addAttribute('in', $parameter['in']);
×
280
                }
UNCOV
281
                if (isset($parameter['description'])) {
×
282
                    $parameterNode->addAttribute('description', $parameter['description']);
×
283
                }
UNCOV
284
                if (isset($parameter['required'])) {
×
285
                    $parameterNode->addAttribute('required', $parameter['required']);
×
286
                }
UNCOV
287
                if (isset($parameter['deprecated'])) {
×
288
                    $parameterNode->addAttribute('deprecated', $parameter['deprecated']);
×
289
                }
UNCOV
290
                if (isset($parameter['allowEmptyValue'])) {
×
291
                    $parameterNode->addAttribute('allowEmptyValue', $parameter['allowEmptyValue']);
×
292
                }
UNCOV
293
                if (isset($parameter['style'])) {
×
294
                    $parameterNode->addAttribute('style', $parameter['style']);
×
295
                }
UNCOV
296
                if (isset($parameter['explode'])) {
×
297
                    $parameterNode->addAttribute('explode', $parameter['explode']);
×
298
                }
UNCOV
299
                if (isset($parameter['allowReserved'])) {
×
300
                    $parameterNode->addAttribute('allowReserved', $parameter['allowReserved']);
×
301
                }
UNCOV
302
                if (isset($parameter['example'])) {
×
303
                    $parameterNode->addAttribute('example', $parameter['example']);
×
304
                }
UNCOV
305
                if (isset($parameter['schema'])) {
×
306
                    $this->buildValues($parameterNode->addChild('schema'), $parameter['schema']);
×
307
                }
UNCOV
308
                if (isset($parameter['examples'])) {
×
309
                    $this->buildValues($parameterNode->addChild('examples'), $parameter['examples']);
×
310
                }
UNCOV
311
                if (isset($parameter['content'])) {
×
312
                    $this->buildValues($parameterNode->addChild('content'), $parameter['content']);
×
313
                }
314
            }
315
        }
316

UNCOV
317
        if (isset($values['requestBody'])) {
×
318
            $requestBodyNode = $node->requestBody ?? $node->addChild('requestBody');
×
319
            if (isset($values['requestBody']['content'])) {
×
320
                $this->buildValues($requestBodyNode->addChild('content'), $values['requestBody']['content']);
×
321
            }
UNCOV
322
            if (isset($values['requestBody']['description'])) {
×
323
                $requestBodyNode->addAttribute('description', $values['requestBody']['description']);
×
324
            }
UNCOV
325
            if (isset($values['requestBody']['required'])) {
×
326
                $requestBodyNode->addAttribute('required', $values['requestBody']['required']);
×
327
            }
328
        }
329

UNCOV
330
        if (isset($values['callbacks'])) {
×
331
            $this->buildValues($node->callbacks ?? $node->addChild('callbacks'), $values['callbacks']);
×
332
        }
333

UNCOV
334
        if (isset($values['security'])) {
×
335
            $this->buildValues($node->security ?? $node->addChild('security'), $values['security']);
×
336
        }
337

UNCOV
338
        if (isset($values['servers'])) {
×
339
            $serversNode = $node->servers ?? $node->addChild('servers');
×
340
            foreach ($values['servers'] as $server) {
×
341
                $serverNode = $serversNode->addChild('serverNode');
×
342
                if (isset($server['url'])) {
×
343
                    $serverNode->addAttribute('url', $server['url']);
×
344
                }
UNCOV
345
                if (isset($server['description'])) {
×
346
                    $serverNode->addAttribute('description', $server['description']);
×
347
                }
UNCOV
348
                if (isset($server['variables'])) {
×
349
                    $this->buildValues($serverNode->addChild('variables'), $server['variables']);
×
350
                }
351
            }
352
        }
353

UNCOV
354
        if (isset($values['extensionProperties'])) {
×
355
            $this->buildValues($node->extensionProperties ?? $node->addChild('extensionProperties'), $values['extensionProperties']);
×
356
        }
357
    }
358

359
    private function buildValidationContext(\SimpleXMLElement $resource, array $values): void
360
    {
UNCOV
361
        $this->buildValues($resource->addChild('validationContext'), $values);
×
362
    }
363

364
    private function buildFilters(\SimpleXMLElement $resource, array $values): void
365
    {
UNCOV
366
        $node = $resource->addChild('filters');
×
367
        foreach ($values as $value) {
×
368
            $node->addChild('filter', $value);
×
369
        }
370
    }
371

372
    private function buildOrder(\SimpleXMLElement $resource, array $values): void
373
    {
UNCOV
374
        $this->buildValues($resource->addChild('order'), $values);
×
375
    }
376

377
    private function buildPaginationViaCursor(\SimpleXMLElement $resource, array $values): void
378
    {
UNCOV
379
        $node = $resource->addChild('paginationViaCursor');
×
380
        foreach ($values as $key => $value) {
×
381
            $child = $node->addChild('paginationField');
×
382
            $child->addAttribute('field', $key);
×
383
            $child->addAttribute('direction', $value);
×
384
        }
385
    }
386

387
    private function buildExceptionToStatus(\SimpleXMLElement $resource, array $values): void
388
    {
UNCOV
389
        $node = $resource->addChild('exceptionToStatus');
×
390
        foreach ($values as $key => $value) {
×
391
            $child = $node->addChild('exception');
×
392
            $child->addAttribute('class', $key);
×
393
            $child->addAttribute('statusCode', $this->parse($value));
×
394
        }
395
    }
396

397
    private function buildExtraProperties(\SimpleXMLElement $resource, array $values): void
398
    {
UNCOV
399
        $this->buildValues($resource->addChild('extraProperties'), $values);
×
400
    }
401

402
    private function buildArgs(\SimpleXMLElement $resource, array $args): void
403
    {
UNCOV
404
        $child = $resource->addChild('args');
×
405
        foreach ($args as $id => $values) {
×
406
            $grandChild = $child->addChild('arg');
×
407
            $grandChild->addAttribute('id', $id);
×
408
            $this->buildValues($grandChild, $values);
×
409
        }
410
    }
411

412
    private function buildExtraArgs(\SimpleXMLElement $resource, array $args): void
413
    {
UNCOV
414
        $child = $resource->addChild('extraArgs');
×
415
        foreach ($args as $id => $values) {
×
416
            $grandChild = $child->addChild('arg');
×
417
            $grandChild->addAttribute('id', $id);
×
418
            $this->buildValues($grandChild, $values);
×
419
        }
420
    }
421

422
    private function buildGraphQlOperations(\SimpleXMLElement $resource, array $values): void
423
    {
UNCOV
424
        $node = $resource->addChild('graphQlOperations');
×
425
        foreach ($values as $value) {
×
426
            $child = $node->addChild('graphQlOperation');
×
427
            foreach ($value as $index => $data) {
×
428
                if (method_exists($this, 'build'.ucfirst($index))) {
×
429
                    $this->{'build'.ucfirst($index)}($child, $data);
×
430
                    continue;
×
431
                }
432

UNCOV
433
                if (\is_string($data) || null === $data || is_numeric($data) || \is_bool($data)) {
×
434
                    $child->addAttribute($index, $this->parse($data));
×
435
                    continue;
×
436
                }
437

UNCOV
438
                throw new \LogicException(\sprintf('Cannot adapt graphQlOperation attribute or child "%s". Please create a "%s" method in %s.', $index, 'build'.ucfirst($index), self::class));
×
439
            }
440
        }
441
    }
442

443
    private function buildOperations(\SimpleXMLElement $resource, array $values): void
444
    {
UNCOV
445
        $node = $resource->addChild('operations');
×
446
        foreach ($values as $value) {
×
447
            $child = $node->addChild('operation');
×
448
            foreach ($value as $index => $data) {
×
449
                if (method_exists($this, 'build'.ucfirst($index))) {
×
450
                    $this->{'build'.ucfirst($index)}($child, $data);
×
451
                    continue;
×
452
                }
453

UNCOV
454
                if (\is_string($data) || null === $data || is_numeric($data) || \is_bool($data)) {
×
455
                    $child->addAttribute($index, $this->parse($data));
×
456
                    continue;
×
457
                }
458

UNCOV
459
                throw new \LogicException(\sprintf('Cannot adapt operation attribute or child "%s". Please create a "%s" method in %s.', $index, 'build'.ucfirst($index), self::class));
×
460
            }
461
        }
462
    }
463

464
    private function buildFormats(\SimpleXMLElement $resource, array $values, string $name = 'formats'): void
465
    {
UNCOV
466
        $node = $resource->addChild($name);
×
467
        foreach ($values as $key => $value) {
×
468
            $node->addChild('format', $value)->addAttribute('name', $key);
×
469
        }
470
    }
471

472
    private function buildStateOptions(\SimpleXMLElement $resource, array $values): void
473
    {
UNCOV
474
        $node = $resource->addChild('stateOptions');
×
475
        $childNode = $node->addChild(array_key_first($values));
×
476
        $childNode->addAttribute('index', $values[array_key_first($values)]['index']);
×
477
    }
478

479
    private function buildValues(\SimpleXMLElement $resource, array $values): void
480
    {
UNCOV
481
        $node = $resource->addChild('values');
×
UNCOV
482
        foreach ($values as $key => $value) {
×
483
            if (\is_array($value)) {
×
484
                $child = $node->addChild('value');
×
485
                $this->buildValues($child, $value);
×
486
            } else {
487
                $child = $node->addChild('value', $value);
×
488
            }
489
            if (\is_string($key)) {
×
UNCOV
490
                $child->addAttribute('name', $key);
×
491
            }
492
        }
493
    }
494

495
    private function buildLinks(\SimpleXMLElement $resource, ?array $values = null): void
496
    {
UNCOV
497
        if (!$values) {
×
UNCOV
498
            return;
×
499
        }
500

UNCOV
501
        $node = $resource->addChild('links');
×
UNCOV
502
        $childNode = $node->addChild('link');
×
503
        $childNode->addAttribute('rel', $values[0]['rel']);
×
504
        $childNode->addAttribute('href', $values[0]['href']);
×
505
    }
506

507
    private function buildRules(\SimpleXMLElement $resource, ?array $values = null): void
508
    {
UNCOV
509
    }
×
510

511
    private function buildHeaders(\SimpleXMLElement $resource, ?array $values = null): void
512
    {
UNCOV
513
        if (!$values) {
×
UNCOV
514
            return;
×
515
        }
516

UNCOV
517
        $node = $resource->addChild('headers');
×
UNCOV
518
        foreach ($values as $key => $value) {
×
519
            $childNode = $node->addChild('header');
×
520
            $childNode->addAttribute('key', $key);
×
521
            $childNode->addAttribute('value', $value);
×
522
        }
523
    }
524

525
    private function buildParameters(\SimpleXMLElement $resource, ?array $values = null): void
526
    {
UNCOV
527
        if (!$values) {
×
UNCOV
528
            return;
×
529
        }
530

UNCOV
531
        $node = $resource->addChild('parameters');
×
UNCOV
532
        foreach ($values as $key => $value) {
×
533
            $childNode = $node->addChild('parameter');
×
534
            $childNode->addAttribute('in', 'query');
×
535
            $childNode->addAttribute('key', $key);
×
536

537
            if (\array_key_exists('required', $value)) {
×
UNCOV
538
                $childNode->addAttribute('required', $this->parse($value['required']));
×
539
            }
540

UNCOV
541
            if (\array_key_exists('schema', $value)) {
×
UNCOV
542
                $this->buildValues($childNode->addChild('schema'), $value['schema']);
×
543
            }
544
        }
545
    }
546

547
    private function parse($value): ?string
548
    {
UNCOV
549
        if (null === $value) {
×
UNCOV
550
            return null;
×
551
        }
552

UNCOV
553
        return \is_bool($value) ? (true === $value ? 'true' : 'false') : (string) $value;
×
554
    }
555
}
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