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

api-platform / core / 18223414080

03 Oct 2025 01:18PM UTC coverage: 0.0% (-22.0%) from 21.956%
18223414080

Pull #7397

github

web-flow
Merge 69d085182 into 0b8237918
Pull Request #7397: fix(jsonschema/jsonld): make `@id` and `@type` properties required only in the JSON-LD schema for output

0 of 18 new or added lines in 2 files covered. (0.0%)

12304 existing lines in 405 files now uncovered.

0 of 53965 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/src/State/ApiResource/Error.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\State\ApiResource;
15

16
use ApiPlatform\JsonSchema\SchemaFactory;
17
use ApiPlatform\Metadata\ApiProperty;
18
use ApiPlatform\Metadata\Error as Operation;
19
use ApiPlatform\Metadata\ErrorResource;
20
use ApiPlatform\Metadata\ErrorResourceInterface;
21
use ApiPlatform\Metadata\Exception\HttpExceptionInterface;
22
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
23
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface as SymfonyHttpExceptionInterface;
24
use Symfony\Component\Serializer\Annotation\Groups;
25
use Symfony\Component\Serializer\Annotation\Ignore;
26
use Symfony\Component\Serializer\Annotation\SerializedName;
27
use Symfony\Component\WebLink\Link;
28

29
#[ErrorResource(
UNCOV
30
    uriVariables: ['status'],
×
UNCOV
31
    requirements: ['status' => '\d+'],
×
UNCOV
32
    uriTemplate: '/errors/{status}{._format}',
×
UNCOV
33
    openapi: false,
×
UNCOV
34
    operations: [
×
UNCOV
35
        new Operation(
×
UNCOV
36
            errors: [],
×
UNCOV
37
            name: '_api_errors_problem',
×
UNCOV
38
            routeName: '_api_errors',
×
UNCOV
39
            outputFormats: [
×
UNCOV
40
                'json' => ['application/problem+json', 'application/json'],
×
UNCOV
41
            ],
×
UNCOV
42
            hideHydraOperation: true,
×
UNCOV
43
            normalizationContext: [
×
UNCOV
44
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
×
UNCOV
45
                'groups' => ['jsonproblem'],
×
UNCOV
46
                'skip_null_values' => true,
×
UNCOV
47
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
×
UNCOV
48
            ],
×
UNCOV
49
        ),
×
UNCOV
50
        new Operation(
×
UNCOV
51
            errors: [],
×
UNCOV
52
            name: '_api_errors_hydra',
×
UNCOV
53
            routeName: '_api_errors',
×
UNCOV
54
            outputFormats: ['jsonld' => ['application/problem+json', 'application/ld+json']],
×
UNCOV
55
            normalizationContext: [
×
UNCOV
56
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
×
UNCOV
57
                'groups' => ['jsonld'],
×
UNCOV
58
                'skip_null_values' => true,
×
UNCOV
59
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
×
UNCOV
60
            ],
×
UNCOV
61
            links: [new Link(rel: 'http://www.w3.org/ns/json-ld#error', href: 'http://www.w3.org/ns/hydra/error')],
×
UNCOV
62
        ),
×
UNCOV
63
        new Operation(
×
UNCOV
64
            errors: [],
×
UNCOV
65
            name: '_api_errors_jsonapi',
×
UNCOV
66
            routeName: '_api_errors',
×
UNCOV
67
            hideHydraOperation: true,
×
UNCOV
68
            outputFormats: ['jsonapi' => ['application/vnd.api+json']],
×
UNCOV
69
            normalizationContext: [
×
UNCOV
70
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
×
UNCOV
71
                'disable_json_schema_serializer_groups' => false,
×
UNCOV
72
                'groups' => ['jsonapi'],
×
UNCOV
73
                'skip_null_values' => true,
×
UNCOV
74
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
×
UNCOV
75
            ],
×
UNCOV
76
        ),
×
UNCOV
77
        new Operation(
×
UNCOV
78
            errors: [],
×
UNCOV
79
            name: '_api_errors_xml',
×
UNCOV
80
            routeName: '_api_errors',
×
UNCOV
81
            outputFormats: [
×
UNCOV
82
                'xml' => ['application/xml', 'text/xml'],
×
UNCOV
83
            ],
×
UNCOV
84
            hideHydraOperation: true,
×
UNCOV
85
            normalizationContext: [
×
UNCOV
86
                SchemaFactory::OPENAPI_DEFINITION_NAME => '',
×
UNCOV
87
                'groups' => ['jsonproblem'],
×
UNCOV
88
                'skip_null_values' => true,
×
UNCOV
89
                'ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString', 'previous'],
×
UNCOV
90
            ],
×
UNCOV
91
        ),
×
UNCOV
92
        new Operation(
×
UNCOV
93
            name: '_api_errors',
×
UNCOV
94
            hideHydraOperation: true,
×
UNCOV
95
            extraProperties: ['_api_disable_swagger_provider' => true],
×
UNCOV
96
            outputFormats: [
×
UNCOV
97
                'html' => ['text/html'],
×
UNCOV
98
                'jsonapi' => ['application/vnd.api+json'],
×
UNCOV
99
                'jsonld' => ['application/ld+json'],
×
UNCOV
100
                'json' => ['application/problem+json', 'application/json'],
×
UNCOV
101
                'xml' => ['application/xml', 'text/xml'],
×
UNCOV
102
            ],
×
UNCOV
103
        ),
×
UNCOV
104
    ],
×
UNCOV
105
    outputFormats: [
×
UNCOV
106
        'jsonapi' => ['application/vnd.api+json'],
×
UNCOV
107
        'jsonld' => ['application/ld+json'],
×
UNCOV
108
        'json' => ['application/problem+json', 'application/json'],
×
UNCOV
109
        'xml' => ['application/xml', 'text/xml'],
×
UNCOV
110
    ],
×
UNCOV
111
    provider: 'api_platform.state.error_provider',
×
UNCOV
112
    graphQlOperations: [],
×
UNCOV
113
    description: 'A representation of common errors.',
×
UNCOV
114
)]
×
115
#[ApiProperty(property: 'previous', hydra: false, readable: false)]
116
#[ApiProperty(property: 'traceAsString', hydra: false, readable: false)]
117
#[ApiProperty(property: 'string', hydra: false, readable: false)]
118
class Error extends \Exception implements ProblemExceptionInterface, HttpExceptionInterface, ErrorResourceInterface
119
{
120
    private ?string $id = null;
121

122
    public function __construct(
123
        private string $title,
124
        private string $detail,
125
        #[ApiProperty(
126
            description: 'The HTTP status code applicable to this problem.',
127
            identifier: true,
128
            writable: false,
129
            initializable: false,
130
            schema: ['type' => 'number', 'examples' => [404], 'default' => 400]
131
        )] private int $status,
132
        ?array $originalTrace = null,
133
        private ?string $instance = null,
134
        private string $type = 'about:blank',
135
        private array $headers = [],
136
        ?\Throwable $previous = null,
137
        private ?array $meta = null,
138
        private ?array $source = null,
139
        private ?string $description = null,
140
    ) {
UNCOV
141
        parent::__construct($title, $status, $previous);
×
142

UNCOV
143
        if (!$originalTrace) {
×
UNCOV
144
            return;
×
145
        }
146

UNCOV
147
        $this->originalTrace = [];
×
UNCOV
148
        foreach ($originalTrace as $i => $t) {
×
UNCOV
149
            unset($t['args']); // we don't want arguments in our JSON traces, especially with xdebug
×
UNCOV
150
            $this->originalTrace[$i] = $t;
×
151
        }
152
    }
153

154
    #[Groups(['jsonapi'])]
155
    public function getId(): string
156
    {
UNCOV
157
        return $this->id ?? ((string) $this->status);
×
158
    }
159

160
    #[Groups(['jsonapi'])]
161
    #[ApiProperty(schema: ['type' => 'object'])]
162
    public function getMeta(): ?array
163
    {
UNCOV
164
        return $this->meta;
×
165
    }
166

167
    #[Groups(['jsonapi'])]
168
    #[ApiProperty(schema: [
UNCOV
169
        'type' => 'object',
×
UNCOV
170
        'properties' => [
×
UNCOV
171
            'pointer' => ['type' => 'string'],
×
UNCOV
172
            'parameter' => ['type' => 'string'],
×
UNCOV
173
            'header' => ['type' => 'string'],
×
UNCOV
174
        ],
×
UNCOV
175
    ])]
×
176
    public function getSource(): ?array
177
    {
UNCOV
178
        return $this->source;
×
179
    }
180

181
    #[SerializedName('trace')]
182
    #[Groups(['trace'])]
183
    #[ApiProperty(writable: false, initializable: false)]
184
    public ?array $originalTrace = null;
185

186
    #[Groups(['jsonld'])]
187
    #[ApiProperty(writable: false, initializable: false)]
188
    public function getDescription(): ?string
189
    {
UNCOV
190
        return $this->description ?? $this->detail;
×
191
    }
192

193
    public function setDescription(?string $description = null): void
194
    {
195
        $this->description = $description;
×
196
    }
197

198
    public static function createFromException(\Exception|\Throwable $exception, int $status): self
199
    {
UNCOV
200
        $headers = ($exception instanceof SymfonyHttpExceptionInterface || $exception instanceof HttpExceptionInterface) ? $exception->getHeaders() : [];
×
201

UNCOV
202
        return new self('An error occurred', $exception->getMessage(), $status, $exception->getTrace(), type: "/errors/$status", headers: $headers, previous: $exception->getPrevious());
×
203
    }
204

205
    #[Ignore]
206
    #[ApiProperty(readable: false)]
207
    public function getHeaders(): array
208
    {
209
        return $this->headers;
×
210
    }
211

212
    #[Ignore]
213
    public function getStatusCode(): int
214
    {
215
        return $this->status;
×
216
    }
217

218
    /**
219
     * @param array<string, string> $headers
220
     */
221
    public function setHeaders(array $headers): void
222
    {
223
        $this->headers = $headers;
×
224
    }
225

226
    #[Groups(['jsonld', 'jsonproblem', 'jsonapi'])]
227
    #[ApiProperty(writable: false, initializable: false, description: 'A URI reference that identifies the problem type')]
228
    public function getType(): string
229
    {
UNCOV
230
        return $this->type;
×
231
    }
232

233
    public function setType(string $type): void
234
    {
235
        $this->type = $type;
×
236
    }
237

238
    #[Groups(['jsonld', 'jsonproblem', 'jsonapi'])]
239
    #[ApiProperty(writable: false, initializable: false, description: 'A short, human-readable summary of the problem.')]
240
    public function getTitle(): ?string
241
    {
UNCOV
242
        return $this->title;
×
243
    }
244

245
    public function setTitle(?string $title = null): void
246
    {
247
        $this->title = $title;
×
248
    }
249

250
    #[Groups(['jsonld', 'jsonproblem', 'jsonapi'])]
251
    public function getStatus(): ?int
252
    {
UNCOV
253
        return $this->status;
×
254
    }
255

256
    public function setStatus(int $status): void
257
    {
258
        $this->status = $status;
×
259
    }
260

261
    #[Groups(['jsonld', 'jsonproblem', 'jsonapi'])]
262
    #[ApiProperty(writable: false, initializable: false, description: 'A human-readable explanation specific to this occurrence of the problem.')]
263
    public function getDetail(): ?string
264
    {
UNCOV
265
        return $this->detail;
×
266
    }
267

268
    public function setDetail(?string $detail = null): void
269
    {
270
        $this->detail = $detail;
×
271
    }
272

273
    #[Groups(['jsonld', 'jsonproblem', 'jsonapi'])]
274
    #[ApiProperty(writable: false, initializable: false, description: 'A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.')]
275
    public function getInstance(): ?string
276
    {
UNCOV
277
        return $this->instance;
×
278
    }
279

280
    public function setInstance(?string $instance = null): void
281
    {
282
        $this->instance = $instance;
×
283
    }
284

285
    public function setId(?string $id = null): void
286
    {
287
        $this->id = $id;
×
288
    }
289

290
    public function setMeta(?array $meta = null): void
291
    {
292
        $this->meta = $meta;
×
293
    }
294

295
    public function setSource(?array $source = null): void
296
    {
297
        $this->source = $source;
×
298
    }
299
}
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