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

api-platform / core / 13203378522

07 Feb 2025 03:56PM UTC coverage: 8.501% (+0.7%) from 7.837%
13203378522

push

github

soyuka
Merge 4.1

111 of 490 new or added lines in 51 files covered. (22.65%)

5590 existing lines in 163 files now uncovered.

13345 of 156987 relevant lines covered (8.5%)

22.88 hits per line

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

96.67
/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\Metadata\ApiProperty;
17
use ApiPlatform\Metadata\Error as ErrorOperation;
18
use ApiPlatform\Metadata\ErrorResource;
19
use ApiPlatform\Metadata\Exception\HttpExceptionInterface;
20
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
21
use ApiPlatform\Metadata\Exception\RuntimeException;
22
use ApiPlatform\Metadata\Util\CompositeIdentifierParser;
23
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface as SymfonyHttpExceptionInterface;
24
use Symfony\Component\Serializer\Annotation\Groups;
25
use Symfony\Component\Serializer\Annotation\SerializedName;
26
use Symfony\Component\Validator\ConstraintViolationList;
27
use Symfony\Component\Validator\ConstraintViolationListInterface;
28
use Symfony\Component\WebLink\Link;
29

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

85
    public function __construct(ConstraintViolationListInterface $message = new ConstraintViolationList(), string|int|null $code = null, int|\Throwable|null $previous = null, \Throwable|string|null $errorTitle = null)
86
    {
87
        $this->errorTitle = $errorTitle;
116✔
88
        $this->constraintViolationList = $message;
116✔
89
        parent::__construct($this->__toString(), $code ?? 0, $previous);
116✔
90
    }
91

92
    /**
93
     * @deprecated
94
     */
95
    public function getErrorTitle(): ?string
96
    {
97
        return $this->errorTitle;
×
98
    }
99

100
    public function getId(): string
101
    {
102
        $ids = [];
64✔
103
        foreach ($this->getConstraintViolationList() as $violation) {
64✔
104
            $ids[] = $violation->getCode();
61✔
105
        }
106

107
        $id = 1 < \count($ids) ? CompositeIdentifierParser::stringify(identifiers: $ids) : ($ids[0] ?? null);
64✔
108

109
        if (!$id) {
64✔
UNCOV
110
            return spl_object_hash($this);
3✔
111
        }
112

113
        return $id;
61✔
114
    }
115

116
    #[Groups(['jsonld'])]
117
    #[ApiProperty(writable: false, initializable: false)]
118
    public function getDescription(): string
119
    {
120
        return $this->detail;
38✔
121
    }
122

123
    #[Groups(['jsonld', 'json', 'jsonapi'])]
124
    #[ApiProperty(writable: false, initializable: false)]
125
    public function getType(): string
126
    {
127
        return '/validation_errors/'.$this->getId();
64✔
128
    }
129

130
    #[Groups(['jsonld', 'json', 'jsonapi'])]
131
    #[ApiProperty(writable: false, initializable: false)]
132
    public function getTitle(): ?string
133
    {
134
        return $this->errorTitle ?? 'An error occurred';
111✔
135
    }
136

137
    #[Groups(['jsonld', 'json', 'jsonapi'])]
138
    #[ApiProperty(writable: false, initializable: false)]
139
    private string $detail;
140

141
    public function getDetail(): ?string
142
    {
143
        return $this->detail;
64✔
144
    }
145

146
    public function setDetail(string $detail): void
147
    {
148
        $this->detail = $detail;
64✔
149
    }
150

151
    #[Groups(['jsonld', 'json', 'jsonapi'])]
152
    public function getStatus(): ?int
153
    {
154
        return $this->status;
111✔
155
    }
156

157
    public function setStatus(int $status): void
158
    {
159
        $this->status = $status;
65✔
160
    }
161

162
    #[Groups(['jsonld', 'json', 'jsonapi'])]
163
    #[ApiProperty(writable: false, initializable: false)]
164
    public function getInstance(): ?string
165
    {
166
        return null;
64✔
167
    }
168

169
    #[SerializedName('violations')]
170
    #[Groups(['json', 'jsonld'])]
171
    #[ApiProperty(
172
        jsonldContext: ['@type' => 'ConstraintViolationList'],
173
        schema: [
174
            'type' => 'array',
175
            'items' => [
176
                'type' => 'object',
177
                'properties' => [
178
                    'propertyPath' => ['type' => 'string', 'description' => 'The property path of the violation'],
179
                    'message' => ['type' => 'string', 'description' => 'The message associated with the violation'],
180
                ],
181
            ],
182
        ]
183
    )]
184
    public function getConstraintViolationList(): ConstraintViolationListInterface
185
    {
186
        return $this->constraintViolationList;
116✔
187
    }
188

189
    public function __toString(): string
190
    {
191
        $message = '';
116✔
192
        foreach ($this->getConstraintViolationList() as $violation) {
116✔
193
            if ('' !== $message) {
66✔
194
                $message .= "\n";
11✔
195
            }
196
            if ($propertyPath = $violation->getPropertyPath()) {
66✔
197
                $message .= "$propertyPath: ";
66✔
198
            }
199

200
            $message .= $violation->getMessage();
66✔
201
        }
202

203
        return $message;
116✔
204
    }
205

206
    public function getStatusCode(): int
207
    {
208
        return $this->status;
65✔
209
    }
210

211
    public function getHeaders(): array
212
    {
213
        return [];
65✔
214
    }
215
}
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