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

api-platform / core / 8156443696

05 Mar 2024 12:43PM UTC coverage: 57.081% (+0.2%) from 56.922%
8156443696

push

github

web-flow
Merge pull request #6201 from soyuka/merge-main

Merge 3.2

33 of 45 new or added lines in 9 files covered. (73.33%)

109 existing lines in 5 files now uncovered.

9553 of 16736 relevant lines covered (57.08%)

41.05 hits per line

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

90.57
/src/Metadata/ApiProperty.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;
15

16
use Symfony\Component\PropertyInfo\Type;
17

18
/**
19
 * ApiProperty annotation.
20
 *
21
 * @author Kévin Dunglas <dunglas@gmail.com>
22
 */
23
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_PARAMETER | \Attribute::TARGET_CLASS_CONSTANT)]
24
final class ApiProperty
25
{
26
    /**
27
     * @param bool|null   $readableLink            https://api-platform.com/docs/core/serialization/#force-iri-with-relations-of-the-same-type-parentchilds-relations
28
     * @param bool|null   $writableLink            https://api-platform.com/docs/core/serialization/#force-iri-with-relations-of-the-same-type-parentchilds-relations
29
     * @param bool|null   $required                https://api-platform.com/docs/admin/validation/#client-side-validation
30
     * @param bool|null   $identifier              https://api-platform.com/docs/core/identifiers/
31
     * @param string|null $default
32
     * @param mixed       $example                 https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts
33
     * @param string|null $deprecationReason       https://api-platform.com/docs/core/deprecations/#deprecating-resource-classes-operations-and-properties
34
     * @param bool|null   $fetchEager              https://api-platform.com/docs/core/performance/#eager-loading
35
     * @param array|null  $jsonldContext           https://api-platform.com/docs/core/extending-jsonld-context/#extending-json-ld-and-hydra-contexts
36
     * @param array|null  $openapiContext          https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts
37
     * @param bool|null   $push                    https://api-platform.com/docs/core/push-relations/
38
     * @param string|null $security                https://api-platform.com/docs/core/security
39
     * @param string|null $securityPostDenormalize https://api-platform.com/docs/core/security/#executing-access-control-rules-after-denormalization
40
     * @param string[]    $types                   the RDF types of this property
41
     * @param string[]    $iris
42
     * @param Type[]      $builtinTypes
43
     * @param string|null $uriTemplate             (experimental) whether to return the subRessource collection IRI instead of an iterable of IRI
44
     */
45
    public function __construct(
46
        private ?string $description = null,
47
        private ?bool $readable = null,
48
        private ?bool $writable = null,
49
        private ?bool $readableLink = null,
50
        private ?bool $writableLink = null,
51
        private ?bool $required = null,
52
        private ?bool $identifier = null,
53
        private $default = null,
54
        private mixed $example = null,
55
        /**
56
         * The `deprecationReason` option deprecates the current operation with a deprecation message.
57
         *
58
         * <div data-code-selector>
59
         *
60
         * ```php
61
         * <?php
62
         * // api/src/Entity/Review.php
63
         * use ApiPlatform\Metadata\ApiProperty;
64
         * use ApiPlatform\Metadata\ApiResource;
65
         *
66
         * #[ApiResource]
67
         * class Review
68
         * {
69
         *     #[ApiProperty(deprecationReason: "Use the rating property instead")]
70
         *     public string $letter;
71
         * }
72
         * ```
73
         *
74
         * ```yaml
75
         * # api/config/api_platform/properties.yaml
76
         * properties:
77
         *     App\Entity\Review:
78
         *         letter:
79
         *             deprecationReason: 'Create a Book instead'
80
         * ```
81
         *
82
         * ```xml
83
         * <?xml version="1.0" encoding="UTF-8" ?>
84
         * <!-- api/config/api_platform/properties.xml -->
85
         *
86
         * <properties
87
         *         xmlns="https://api-platform.com/schema/metadata/properties-3.0"
88
         *         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
89
         *         xsi:schemaLocation="https://api-platform.com/schema/metadata/properties-3.0
90
         *         https://api-platform.com/schema/metadata/properties-3.0.xsd">
91
         *     <property resource="App\Entity\Review" name="letter" deprecationReason="Create a Book instead" />
92
         * </properties>
93
         * ```
94
         *
95
         * </div>
96
         *
97
         * - With JSON-lD / Hydra, [an `owl:deprecated` annotation property](https://www.w3.org/TR/owl2-syntax/#Annotation_Properties) will be added to the appropriate data structure
98
         * - With Swagger / OpenAPI, [a `deprecated` property](https://swagger.io/docs/specification/2-0/paths-and-operations/) will be added
99
         * - With GraphQL, the [`isDeprecated` and `deprecationReason` properties](https://facebook.github.io/graphql/June2018/#sec-Deprecation) will be added to the schema
100
         */
101
        private ?string $deprecationReason = null,
102
        private ?bool $fetchable = null,
103
        private ?bool $fetchEager = null,
104
        private ?array $jsonldContext = null,
105
        private ?array $openapiContext = null,
106
        private ?array $jsonSchemaContext = null,
107
        private ?bool $push = null,
108
        /**
109
         * The `security` option defines the access to the current property, on normalization process, based on Symfony Security.
110
         * It receives an `object` variable related to the current object, and a `property` variable related to the current property.
111
         *
112
         * <div data-code-selector>
113
         *
114
         * ```php
115
         * <?php
116
         * // api/src/Entity/Review.php
117
         * use ApiPlatform\Metadata\ApiProperty;
118
         * use ApiPlatform\Metadata\ApiResource;
119
         *
120
         * #[ApiResource]
121
         * class Review
122
         * {
123
         *     #[ApiProperty(security: 'is_granted("ROLE_ADMIN")')]
124
         *     public string $letter;
125
         * }
126
         * ```
127
         *
128
         * ```yaml
129
         * # api/config/api_platform/properties.yaml
130
         * properties:
131
         *     App\Entity\Review:
132
         *         letter:
133
         *             security: 'is_granted("ROLE_ADMIN")'
134
         * ```
135
         *
136
         * ```xml
137
         * <?xml version="1.0" encoding="UTF-8" ?>
138
         * <!-- api/config/api_platform/properties.xml -->
139
         *
140
         * <properties
141
         *         xmlns="https://api-platform.com/schema/metadata/properties-3.0"
142
         *         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
143
         *         xsi:schemaLocation="https://api-platform.com/schema/metadata/properties-3.0
144
         *         https://api-platform.com/schema/metadata/properties-3.0.xsd">
145
         *     <property resource="App\Entity\Review" name="letter" security="is_granted('ROLE_ADMIN')" />
146
         * </properties>
147
         * ```
148
         *
149
         * </div>
150
         */
151
        private ?string $security = null,
152
        /**
153
         * The `securityPostDenormalize` option defines access to the current property after the denormalization process, based on Symfony Security.
154
         * It receives an `object` variable related to the current object, and a `property` variable related to the current property.
155
         *
156
         * <div data-code-selector>
157
         *
158
         * ```php
159
         * <?php
160
         * // api/src/Entity/Review.php
161
         * use ApiPlatform\Metadata\ApiProperty;
162
         * use ApiPlatform\Metadata\ApiResource;
163
         *
164
         * #[ApiResource]
165
         * class Review
166
         * {
167
         *     #[ApiProperty(securityPostDenormalize: 'is_granted("ROLE_ADMIN")')]
168
         *     public string $letter;
169
         * }
170
         * ```
171
         *
172
         * ```yaml
173
         * # api/config/api_platform/properties.yaml
174
         * properties:
175
         *     App\Entity\Review:
176
         *         letter:
177
         *             securityPostDenormalize: 'is_granted("ROLE_ADMIN")'
178
         * ```
179
         *
180
         * ```xml
181
         * <?xml version="1.0" encoding="UTF-8" ?>
182
         * <!-- api/config/api_platform/properties.xml -->
183
         *
184
         * <properties
185
         *         xmlns="https://api-platform.com/schema/metadata/properties-3.0"
186
         *         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
187
         *         xsi:schemaLocation="https://api-platform.com/schema/metadata/properties-3.0
188
         *         https://api-platform.com/schema/metadata/properties-3.0.xsd">
189
         *     <property resource="App\Entity\Review" name="letter" securityPostDenormalize="is_granted('ROLE_ADMIN')" />
190
         * </properties>
191
         * ```
192
         *
193
         * </div>
194
         */
195
        private ?string $securityPostDenormalize = null,
196
        private array|string|null $types = null,
197
        /*
198
         * The related php types.
199
         */
200
        private ?array $builtinTypes = null,
201
        private ?array $schema = null,
202
        private ?bool $initializable = null,
203
        private $iris = null,
204
        private ?bool $genId = null,
205
        private ?string $uriTemplate = null,
206
        private array $extraProperties = [],
207
    ) {
208
        if (\is_string($types)) {
312✔
UNCOV
209
            $this->types = (array) $types;
×
210
        }
211
    }
212

213
    public function getDescription(): ?string
214
    {
215
        return $this->description;
72✔
216
    }
217

218
    public function withDescription(string $description): self
219
    {
220
        $self = clone $this;
104✔
221
        $self->description = $description;
104✔
222

223
        return $self;
104✔
224
    }
225

226
    public function isReadable(): ?bool
227
    {
228
        return $this->readable;
144✔
229
    }
230

231
    public function withReadable(bool $readable): self
232
    {
233
        $self = clone $this;
180✔
234
        $self->readable = $readable;
180✔
235

236
        return $self;
180✔
237
    }
238

239
    public function isWritable(): ?bool
240
    {
241
        return $this->writable;
124✔
242
    }
243

244
    public function withWritable(bool $writable): self
245
    {
246
        $self = clone $this;
160✔
247
        $self->writable = $writable;
160✔
248

249
        return $self;
160✔
250
    }
251

252
    public function isReadableLink(): ?bool
253
    {
254
        return $this->readableLink;
148✔
255
    }
256

257
    public function withReadableLink(bool $readableLink): self
258
    {
259
        $self = clone $this;
104✔
260
        $self->readableLink = $readableLink;
104✔
261

262
        return $self;
104✔
263
    }
264

265
    public function isWritableLink(): ?bool
266
    {
267
        return $this->writableLink;
40✔
268
    }
269

270
    public function withWritableLink(bool $writableLink): self
271
    {
272
        $self = clone $this;
100✔
273
        $self->writableLink = $writableLink;
100✔
274

275
        return $self;
100✔
276
    }
277

278
    public function isRequired(): ?bool
279
    {
280
        return $this->required;
288✔
281
    }
282

283
    public function withRequired(bool $required): self
284
    {
285
        $self = clone $this;
248✔
286
        $self->required = $required;
248✔
287

288
        return $self;
248✔
289
    }
290

291
    public function isIdentifier(): ?bool
292
    {
293
        return $this->identifier;
108✔
294
    }
295

296
    public function withIdentifier(bool $identifier): self
297
    {
298
        $self = clone $this;
56✔
299
        $self->identifier = $identifier;
56✔
300

301
        return $self;
56✔
302
    }
303

304
    public function getDefault()
305
    {
306
        return $this->default;
64✔
307
    }
308

309
    public function withDefault($default): self
310
    {
311
        $self = clone $this;
44✔
312
        $self->default = $default;
44✔
313

314
        return $self;
44✔
315
    }
316

317
    public function getExample(): mixed
318
    {
319
        return $this->example;
64✔
320
    }
321

322
    public function withExample(mixed $example): self
323
    {
UNCOV
324
        $self = clone $this;
×
UNCOV
325
        $self->example = $example;
×
326

UNCOV
327
        return $self;
×
328
    }
329

330
    public function getDeprecationReason(): ?string
331
    {
332
        return $this->deprecationReason;
72✔
333
    }
334

335
    public function withDeprecationReason($deprecationReason): self
336
    {
337
        $self = clone $this;
8✔
338
        $self->deprecationReason = $deprecationReason;
8✔
339

340
        return $self;
8✔
341
    }
342

343
    public function isFetchable(): ?bool
344
    {
345
        return $this->fetchable;
28✔
346
    }
347

348
    public function withFetchable($fetchable): self
349
    {
UNCOV
350
        $self = clone $this;
×
UNCOV
351
        $self->fetchable = $fetchable;
×
352

UNCOV
353
        return $self;
×
354
    }
355

356
    public function getFetchEager(): ?bool
357
    {
358
        return $this->fetchEager;
32✔
359
    }
360

361
    public function withFetchEager($fetchEager): self
362
    {
363
        $self = clone $this;
4✔
364
        $self->fetchEager = $fetchEager;
4✔
365

366
        return $self;
4✔
367
    }
368

369
    public function getJsonldContext(): ?array
370
    {
371
        return $this->jsonldContext;
80✔
372
    }
373

374
    public function withJsonldContext($jsonldContext): self
375
    {
376
        $self = clone $this;
20✔
377
        $self->jsonldContext = $jsonldContext;
20✔
378

379
        return $self;
20✔
380
    }
381

382
    public function getOpenapiContext(): ?array
383
    {
384
        return $this->openapiContext;
44✔
385
    }
386

387
    public function withOpenapiContext($openapiContext): self
388
    {
UNCOV
389
        $self = clone $this;
×
UNCOV
390
        $self->openapiContext = $openapiContext;
×
391

UNCOV
392
        return $self;
×
393
    }
394

395
    public function getJsonSchemaContext(): ?array
396
    {
397
        return $this->jsonSchemaContext;
76✔
398
    }
399

400
    public function withJsonSchemaContext($jsonSchemaContext): self
401
    {
402
        $self = clone $this;
8✔
403
        $self->jsonSchemaContext = $jsonSchemaContext;
8✔
404

405
        return $self;
8✔
406
    }
407

408
    public function getPush(): ?bool
409
    {
410
        return $this->push;
36✔
411
    }
412

413
    public function withPush($push): self
414
    {
415
        $self = clone $this;
12✔
416
        $self->push = $push;
12✔
417

418
        return $self;
12✔
419
    }
420

421
    public function getSecurity(): ?string
422
    {
423
        return $this->security;
108✔
424
    }
425

426
    public function withSecurity($security): self
427
    {
428
        $self = clone $this;
4✔
429
        $self->security = $security;
4✔
430

431
        return $self;
4✔
432
    }
433

434
    public function getSecurityPostDenormalize(): ?string
435
    {
436
        return $this->securityPostDenormalize;
44✔
437
    }
438

439
    public function withSecurityPostDenormalize($securityPostDenormalize): self
440
    {
441
        $self = clone $this;
4✔
442
        $self->securityPostDenormalize = $securityPostDenormalize;
4✔
443

444
        return $self;
4✔
445
    }
446

447
    public function getTypes(): ?array
448
    {
449
        return $this->types;
248✔
450
    }
451

452
    /**
453
     * @param string[]|string $types
454
     */
455
    public function withTypes(array|string $types = []): self
456
    {
457
        $self = clone $this;
36✔
458
        $self->types = (array) $types;
36✔
459

460
        return $self;
36✔
461
    }
462

463
    /**
464
     * @return Type[]
465
     */
466
    public function getBuiltinTypes(): ?array
467
    {
468
        return $this->builtinTypes;
432✔
469
    }
470

471
    /**
472
     * @param Type[] $builtinTypes
473
     */
474
    public function withBuiltinTypes(array $builtinTypes = []): self
475
    {
476
        $self = clone $this;
204✔
477
        $self->builtinTypes = $builtinTypes;
204✔
478

479
        return $self;
204✔
480
    }
481

482
    public function getSchema(): ?array
483
    {
484
        return $this->schema;
324✔
485
    }
486

487
    public function withSchema(array $schema = []): self
488
    {
489
        $self = clone $this;
216✔
490
        $self->schema = $schema;
216✔
491

492
        return $self;
216✔
493
    }
494

495
    public function withInitializable(?bool $initializable): self
496
    {
497
        $self = clone $this;
64✔
498
        $self->initializable = $initializable;
64✔
499

500
        return $self;
64✔
501
    }
502

503
    public function isInitializable(): ?bool
504
    {
505
        return $this->initializable;
80✔
506
    }
507

508
    public function getExtraProperties(): ?array
509
    {
510
        return $this->extraProperties;
444✔
511
    }
512

513
    public function withExtraProperties(array $extraProperties = []): self
514
    {
515
        $self = clone $this;
48✔
516
        $self->extraProperties = $extraProperties;
48✔
517

518
        return $self;
48✔
519
    }
520

521
    /**
522
     * Gets IRI of this property.
523
     */
524
    public function getIris()
525
    {
526
        return $this->iris;
80✔
527
    }
528

529
    /**
530
     * Returns a new instance with the given IRI.
531
     *
532
     * @param string|string[] $iris
533
     */
534
    public function withIris(string|array $iris): self
535
    {
536
        $metadata = clone $this;
20✔
537
        $metadata->iris = (array) $iris;
20✔
538

539
        return $metadata;
20✔
540
    }
541

542
    /**
543
     * Whether to generate a skolem iri on anonymous resources.
544
     */
545
    public function getGenId()
546
    {
547
        return $this->genId;
48✔
548
    }
549

550
    public function withGenId(bool $genId): self
551
    {
552
        $metadata = clone $this;
8✔
553
        $metadata->genId = $genId;
8✔
554

555
        return $metadata;
8✔
556
    }
557

558
    /**
559
     * Whether to return the subRessource collection IRI instead of an iterable of IRI.
560
     *
561
     * @experimental
562
     */
563
    public function getUriTemplate(): ?string
564
    {
565
        return $this->uriTemplate;
76✔
566
    }
567

568
    public function withUriTemplate(?string $uriTemplate): self
569
    {
570
        $metadata = clone $this;
4✔
571
        $metadata->uriTemplate = $uriTemplate;
4✔
572

573
        return $metadata;
4✔
574
    }
575
}
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

© 2026 Coveralls, Inc