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

api-platform / core / 18089958695

29 Sep 2025 07:57AM UTC coverage: 21.569% (-0.2%) from 21.797%
18089958695

push

github

web-flow
fix(openapi): define items type for HydraCollectionBaseSchema hydra:member (#7419)

Co-authored-by: Thibaut Cholley <thibaut.cholley@elsie-sante.fr>

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

12063 existing lines in 401 files now uncovered.

11765 of 54545 relevant lines covered (21.57%)

12.57 hits per line

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

93.94
/src/Validator/Exception/ValidationException.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\Validator\Exception;
15

16
use ApiPlatform\JsonSchema\SchemaFactory;
17
use ApiPlatform\Metadata\ApiProperty;
18
use ApiPlatform\Metadata\Error as ErrorOperation;
19
use ApiPlatform\Metadata\ErrorResource;
20
use ApiPlatform\Metadata\Exception\HttpExceptionInterface;
21
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
22
use ApiPlatform\Metadata\Exception\RuntimeException;
23
use ApiPlatform\Metadata\Util\CompositeIdentifierParser;
24
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface as SymfonyHttpExceptionInterface;
25
use Symfony\Component\Serializer\Annotation\Groups;
26
use Symfony\Component\Serializer\Annotation\SerializedName;
27
use Symfony\Component\Validator\ConstraintViolationList;
28
use Symfony\Component\Validator\ConstraintViolationListInterface;
29
use Symfony\Component\WebLink\Link;
30

31
/**
32
 * Thrown when a validation error occurs.
33
 *
34
 * @author Kévin Dunglas <dunglas@gmail.com>
35
 */
36
#[ErrorResource(
UNCOV
37
    uriTemplate: '/validation_errors/{id}',
UNCOV
38
    status: 422,
UNCOV
39
    uriVariables: ['id'],
UNCOV
40
    openapi: false,
UNCOV
41
    outputFormats: [
UNCOV
42
        'jsonapi' => ['application/vnd.api+json'],
UNCOV
43
        'jsonld' => ['application/ld+json'],
UNCOV
44
        'json' => ['application/problem+json', 'application/json'],
UNCOV
45
        'xml' => ['application/xml', 'text/xml'],
UNCOV
46
    ],
UNCOV
47
    provider: 'api_platform.validator.state.error_provider',
UNCOV
48
    shortName: 'ConstraintViolation',
UNCOV
49
    description: 'Unprocessable entity',
UNCOV
50
    operations: [
UNCOV
51
        new ErrorOperation(
UNCOV
52
            name: '_api_validation_errors_problem',
UNCOV
53
            outputFormats: [
UNCOV
54
                'json' => ['application/problem+json'],
UNCOV
55
            ],
UNCOV
56
            normalizationContext: [
UNCOV
57
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
UNCOV
58
                'groups' => ['json'],
UNCOV
59
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
UNCOV
60
                'skip_null_values' => true,
UNCOV
61
            ]
UNCOV
62
        ),
UNCOV
63
        new ErrorOperation(
UNCOV
64
            name: '_api_validation_errors_hydra',
UNCOV
65
            outputFormats: ['jsonld' => ['application/problem+json', 'application/ld+json']],
UNCOV
66
            links: [new Link(rel: 'http://www.w3.org/ns/json-ld#error', href: 'http://www.w3.org/ns/hydra/error')],
UNCOV
67
            normalizationContext: [
UNCOV
68
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
UNCOV
69
                'groups' => ['jsonld'],
UNCOV
70
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
UNCOV
71
                'skip_null_values' => true,
UNCOV
72
            ]
UNCOV
73
        ),
UNCOV
74
        new ErrorOperation(
UNCOV
75
            name: '_api_validation_errors_jsonapi',
UNCOV
76
            outputFormats: ['jsonapi' => ['application/vnd.api+json']],
UNCOV
77
            normalizationContext: [
UNCOV
78
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
UNCOV
79
                'disable_json_schema_serializer_groups' => false,
UNCOV
80
                'groups' => ['jsonapi'],
UNCOV
81
                'skip_null_values' => true,
UNCOV
82
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
UNCOV
83
            ]
UNCOV
84
        ),
UNCOV
85
        new ErrorOperation(
UNCOV
86
            name: '_api_validation_errors_xml',
UNCOV
87
            outputFormats: [
UNCOV
88
                'xml' => ['application/xml', 'text/xml'],
UNCOV
89
            ],
UNCOV
90
            normalizationContext: [
UNCOV
91
                'groups' => ['json'],
UNCOV
92
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
UNCOV
93
                'skip_null_values' => true,
UNCOV
94
            ]
UNCOV
95
        ),
UNCOV
96
    ],
UNCOV
97
    graphQlOperations: []
UNCOV
98
)]
99
#[ApiProperty(property: 'traceAsString', hydra: false)]
100
#[ApiProperty(property: 'string', hydra: false)]
101
class ValidationException extends RuntimeException implements ConstraintViolationListAwareExceptionInterface, \Stringable, ProblemExceptionInterface, HttpExceptionInterface, SymfonyHttpExceptionInterface
102
{
103
    private int $status = 422;
104
    protected ?string $errorTitle = null;
105
    private array|ConstraintViolationListInterface $constraintViolationList = [];
106

107
    public function __construct(string|ConstraintViolationListInterface $message = new ConstraintViolationList(), string|int|null $code = null, int|\Throwable|null $previous = null, \Throwable|string|null $errorTitle = null)
108
    {
UNCOV
109
        $this->errorTitle = $errorTitle;
45✔
110

UNCOV
111
        if ($message instanceof ConstraintViolationListInterface) {
45✔
UNCOV
112
            $this->constraintViolationList = $message;
45✔
UNCOV
113
            parent::__construct($this->__toString(), $code ?? 0, $previous);
45✔
114

UNCOV
115
            return;
45✔
116
        }
117

118
        trigger_deprecation('api_platform/core', '5.0', \sprintf('The "%s" exception will have a "%s" first argument in 5.x.', self::class, ConstraintViolationListInterface::class));
×
119
        parent::__construct($message ?: $this->__toString(), $code ?? 0, $previous);
×
120
    }
121

122
    public function getId(): string
123
    {
UNCOV
124
        $ids = [];
33✔
UNCOV
125
        foreach ($this->getConstraintViolationList() as $violation) {
33✔
UNCOV
126
            $ids[] = $violation->getCode();
33✔
127
        }
128

UNCOV
129
        $id = 1 < \count($ids) ? CompositeIdentifierParser::stringify(identifiers: $ids) : ($ids[0] ?? null);
33✔
130

UNCOV
131
        if (!$id) {
33✔
UNCOV
132
            return spl_object_hash($this);
1✔
133
        }
134

UNCOV
135
        return $id;
32✔
136
    }
137

138
    #[Groups(['jsonld'])]
139
    #[ApiProperty(writable: false, initializable: false)]
140
    public function getDescription(): string
141
    {
UNCOV
142
        return $this->detail;
33✔
143
    }
144

145
    #[Groups(['jsonld', 'json', 'jsonapi'])]
146
    #[ApiProperty(writable: false, initializable: false)]
147
    public function getType(): string
148
    {
UNCOV
149
        return '/validation_errors/'.$this->getId();
33✔
150
    }
151

152
    #[Groups(['jsonld', 'json', 'jsonapi'])]
153
    #[ApiProperty(writable: false, initializable: false)]
154
    public function getTitle(): ?string
155
    {
UNCOV
156
        return $this->errorTitle ?? 'An error occurred';
44✔
157
    }
158

159
    #[Groups(['jsonld', 'json', 'jsonapi'])]
160
    #[ApiProperty(writable: false, initializable: false)]
161
    private string $detail;
162

163
    public function getDetail(): ?string
164
    {
UNCOV
165
        return $this->detail;
33✔
166
    }
167

168
    public function setDetail(string $detail): void
169
    {
UNCOV
170
        $this->detail = $detail;
33✔
171
    }
172

173
    #[Groups(['jsonld', 'json', 'jsonapi'])]
174
    public function getStatus(): ?int
175
    {
UNCOV
176
        return $this->status;
44✔
177
    }
178

179
    public function setStatus(int $status): void
180
    {
UNCOV
181
        $this->status = $status;
33✔
182
    }
183

184
    #[Groups(['jsonld', 'json', 'jsonapi'])]
185
    #[ApiProperty(writable: false, initializable: false)]
186
    public function getInstance(): ?string
187
    {
UNCOV
188
        return null;
33✔
189
    }
190

191
    #[SerializedName('violations')]
192
    #[Groups(['json', 'jsonld'])]
193
    #[ApiProperty(
UNCOV
194
        jsonldContext: ['@type' => 'ConstraintViolationList'],
UNCOV
195
        schema: [
UNCOV
196
            'type' => 'array',
UNCOV
197
            'items' => [
UNCOV
198
                'type' => 'object',
UNCOV
199
                'properties' => [
UNCOV
200
                    'propertyPath' => ['type' => 'string', 'description' => 'The property path of the violation'],
UNCOV
201
                    'message' => ['type' => 'string', 'description' => 'The message associated with the violation'],
UNCOV
202
                ],
UNCOV
203
            ],
UNCOV
204
        ]
UNCOV
205
    )]
206
    public function getConstraintViolationList(): ConstraintViolationListInterface
207
    {
UNCOV
208
        return $this->constraintViolationList;
45✔
209
    }
210

211
    public function __toString(): string
212
    {
UNCOV
213
        $message = '';
45✔
UNCOV
214
        foreach ($this->getConstraintViolationList() as $violation) {
45✔
UNCOV
215
            if ('' !== $message) {
34✔
UNCOV
216
                $message .= "\n";
9✔
217
            }
UNCOV
218
            if ($propertyPath = $violation->getPropertyPath()) {
34✔
UNCOV
219
                $message .= "$propertyPath: ";
34✔
220
            }
221

UNCOV
222
            $message .= $violation->getMessage();
34✔
223
        }
224

UNCOV
225
        return $message;
45✔
226
    }
227

228
    public function getStatusCode(): int
229
    {
UNCOV
230
        return $this->status;
33✔
231
    }
232

233
    public function getHeaders(): array
234
    {
UNCOV
235
        return [];
33✔
236
    }
237
}
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