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

api-platform / core / 14246153067

03 Apr 2025 02:56PM UTC coverage: 7.286% (-0.002%) from 7.288%
14246153067

push

github

web-flow
Merge commit from fork

12 of 160 new or added lines in 7 files covered. (7.5%)

2343 existing lines in 152 files now uncovered.

12450 of 170870 relevant lines covered (7.29%)

12.06 hits per line

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

89.83
/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
use Symfony\Component\Serializer\Attribute\Context;
18
use Symfony\Component\Serializer\Attribute\Groups;
19
use Symfony\Component\Serializer\Attribute\Ignore;
20
use Symfony\Component\Serializer\Attribute\MaxDepth;
21
use Symfony\Component\Serializer\Attribute\SerializedName;
22
use Symfony\Component\Serializer\Attribute\SerializedPath;
23

24
/**
25
 * ApiProperty annotation.
26
 *
27
 * @author Kévin Dunglas <dunglas@gmail.com>
28
 */
29
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_PARAMETER | \Attribute::TARGET_CLASS_CONSTANT | \Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
30
final class ApiProperty
31
{
32
    private ?array $types;
33
    private ?array $serialize;
34

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

225
    public function getProperty(): ?string
226
    {
227
        return $this->property;
96✔
228
    }
229

230
    public function withProperty(string $property): self
231
    {
232
        $self = clone $this;
×
233
        $self->property = $property;
×
234

235
        return $self;
×
236
    }
237

238
    public function getDescription(): ?string
239
    {
240
        return $this->description;
459✔
241
    }
242

243
    public function withDescription(string $description): self
244
    {
245
        $self = clone $this;
165✔
246
        $self->description = $description;
165✔
247

248
        return $self;
165✔
249
    }
250

251
    public function isReadable(): ?bool
252
    {
253
        return $this->readable;
1,060✔
254
    }
255

256
    public function withReadable(bool $readable): self
257
    {
258
        $self = clone $this;
406✔
259
        $self->readable = $readable;
406✔
260

261
        return $self;
406✔
262
    }
263

264
    public function isWritable(): ?bool
265
    {
266
        return $this->writable;
542✔
267
    }
268

269
    public function withWritable(bool $writable): self
270
    {
271
        $self = clone $this;
397✔
272
        $self->writable = $writable;
397✔
273

274
        return $self;
397✔
275
    }
276

277
    public function isReadableLink(): ?bool
278
    {
279
        return $this->readableLink;
464✔
280
    }
281

282
    public function withReadableLink(bool $readableLink): self
283
    {
284
        $self = clone $this;
153✔
285
        $self->readableLink = $readableLink;
153✔
286

287
        return $self;
153✔
288
    }
289

290
    public function isWritableLink(): ?bool
291
    {
292
        return $this->writableLink;
186✔
293
    }
294

295
    public function withWritableLink(bool $writableLink): self
296
    {
297
        $self = clone $this;
150✔
298
        $self->writableLink = $writableLink;
150✔
299

300
        return $self;
150✔
301
    }
302

303
    public function isRequired(): ?bool
304
    {
305
        return $this->required;
626✔
306
    }
307

308
    public function withRequired(bool $required): self
309
    {
310
        $self = clone $this;
478✔
311
        $self->required = $required;
478✔
312

313
        return $self;
478✔
314
    }
315

316
    public function isIdentifier(): ?bool
317
    {
318
        return $this->identifier;
388✔
319
    }
320

321
    public function withIdentifier(bool $identifier): self
322
    {
323
        $self = clone $this;
278✔
324
        $self->identifier = $identifier;
278✔
325

326
        return $self;
278✔
327
    }
328

329
    public function getDefault()
330
    {
331
        return $this->default;
338✔
332
    }
333

334
    public function withDefault($default): self
335
    {
336
        $self = clone $this;
157✔
337
        $self->default = $default;
157✔
338

339
        return $self;
157✔
340
    }
341

342
    public function getExample(): mixed
343
    {
344
        return $this->example;
337✔
345
    }
346

347
    public function withExample(mixed $example): self
348
    {
349
        $self = clone $this;
6✔
350
        $self->example = $example;
6✔
351

352
        return $self;
6✔
353
    }
354

355
    public function getDeprecationReason(): ?string
356
    {
357
        return $this->deprecationReason;
459✔
358
    }
359

360
    public function withDeprecationReason($deprecationReason): self
361
    {
362
        $self = clone $this;
19✔
363
        $self->deprecationReason = $deprecationReason;
19✔
364

365
        return $self;
19✔
366
    }
367

368
    public function isFetchable(): ?bool
369
    {
370
        return $this->fetchable;
96✔
371
    }
372

373
    public function withFetchable($fetchable): self
374
    {
375
        $self = clone $this;
×
376
        $self->fetchable = $fetchable;
×
377

378
        return $self;
×
379
    }
380

381
    public function getFetchEager(): ?bool
382
    {
383
        return $this->fetchEager;
111✔
384
    }
385

386
    public function withFetchEager($fetchEager): self
387
    {
388
        $self = clone $this;
×
389
        $self->fetchEager = $fetchEager;
×
390

391
        return $self;
×
392
    }
393

394
    public function getJsonldContext(): ?array
395
    {
396
        return $this->jsonldContext;
174✔
397
    }
398

399
    public function withJsonldContext($jsonldContext): self
400
    {
401
        $self = clone $this;
15✔
402
        $self->jsonldContext = $jsonldContext;
15✔
403

404
        return $self;
15✔
405
    }
406

407
    public function getOpenapiContext(): ?array
408
    {
409
        return $this->openapiContext;
345✔
410
    }
411

412
    public function withOpenapiContext($openapiContext): self
413
    {
414
        $self = clone $this;
9✔
415
        $self->openapiContext = $openapiContext;
9✔
416

417
        return $self;
9✔
418
    }
419

420
    public function getJsonSchemaContext(): ?array
421
    {
422
        return $this->jsonSchemaContext;
180✔
423
    }
424

425
    public function withJsonSchemaContext($jsonSchemaContext): self
426
    {
427
        $self = clone $this;
18✔
428
        $self->jsonSchemaContext = $jsonSchemaContext;
18✔
429

430
        return $self;
18✔
431
    }
432

433
    public function getPush(): ?bool
434
    {
435
        return $this->push;
163✔
436
    }
437

438
    public function withPush($push): self
439
    {
440
        $self = clone $this;
10✔
441
        $self->push = $push;
10✔
442

443
        return $self;
10✔
444
    }
445

446
    public function getSecurity(): ?string
447
    {
448
        return $this->security instanceof \Stringable ? (string) $this->security : $this->security;
973✔
449
    }
450

451
    public function withSecurity($security): self
452
    {
453
        $self = clone $this;
8✔
454
        $self->security = $security;
8✔
455

456
        return $self;
8✔
457
    }
458

459
    public function getSecurityPostDenormalize(): ?string
460
    {
461
        return $this->securityPostDenormalize instanceof \Stringable ? (string) $this->securityPostDenormalize : $this->securityPostDenormalize;
265✔
462
    }
463

464
    public function withSecurityPostDenormalize($securityPostDenormalize): self
465
    {
466
        $self = clone $this;
8✔
467
        $self->securityPostDenormalize = $securityPostDenormalize;
8✔
468

469
        return $self;
8✔
470
    }
471

472
    public function getTypes(): ?array
473
    {
474
        return $this->types;
478✔
475
    }
476

477
    /**
478
     * @param string[]|string $types
479
     */
480
    public function withTypes(array|string $types = []): self
481
    {
482
        $self = clone $this;
59✔
483
        $self->types = (array) $types;
59✔
484

485
        return $self;
59✔
486
    }
487

488
    /**
489
     * @return Type[]
490
     */
491
    public function getBuiltinTypes(): ?array
492
    {
493
        return $this->builtinTypes;
1,277✔
494
    }
495

496
    /**
497
     * @param Type[] $builtinTypes
498
     */
499
    public function withBuiltinTypes(array $builtinTypes = []): self
500
    {
501
        $self = clone $this;
424✔
502
        $self->builtinTypes = $builtinTypes;
424✔
503

504
        return $self;
424✔
505
    }
506

507
    public function getSchema(): ?array
508
    {
509
        return $this->schema;
576✔
510
    }
511

512
    public function withSchema(array $schema = []): self
513
    {
514
        $self = clone $this;
451✔
515
        $self->schema = $schema;
451✔
516

517
        return $self;
451✔
518
    }
519

520
    public function withInitializable(?bool $initializable): self
521
    {
522
        $self = clone $this;
337✔
523
        $self->initializable = $initializable;
337✔
524

525
        return $self;
337✔
526
    }
527

528
    public function isInitializable(): ?bool
529
    {
530
        return $this->initializable;
477✔
531
    }
532

533
    public function getExtraProperties(): ?array
534
    {
535
        return $this->extraProperties;
666✔
536
    }
537

538
    public function withExtraProperties(array $extraProperties = []): self
539
    {
540
        $self = clone $this;
111✔
541
        $self->extraProperties = $extraProperties;
111✔
542

543
        return $self;
111✔
544
    }
545

546
    /**
547
     * Gets IRI of this property.
548
     */
549
    public function getIris()
550
    {
551
        return $this->iris;
174✔
552
    }
553

554
    /**
555
     * Returns a new instance with the given IRI.
556
     *
557
     * @param string|string[] $iris
558
     */
559
    public function withIris(string|array $iris): self
560
    {
561
        $metadata = clone $this;
27✔
562
        $metadata->iris = (array) $iris;
27✔
563

564
        return $metadata;
27✔
565
    }
566

567
    /**
568
     * Whether to generate a skolem iri on anonymous resources.
569
     */
570
    public function getGenId()
571
    {
572
        return $this->genId;
490✔
573
    }
574

575
    public function withGenId(bool $genId): self
576
    {
577
        $metadata = clone $this;
10✔
578
        $metadata->genId = $genId;
10✔
579

580
        return $metadata;
10✔
581
    }
582

583
    /**
584
     * Whether to return the subRessource collection IRI instead of an iterable of IRI.
585
     *
586
     * @experimental
587
     */
588
    public function getUriTemplate(): ?string
589
    {
590
        return $this->uriTemplate;
557✔
591
    }
592

593
    public function withUriTemplate(?string $uriTemplate): self
594
    {
UNCOV
595
        $metadata = clone $this;
5✔
UNCOV
596
        $metadata->uriTemplate = $uriTemplate;
5✔
597

UNCOV
598
        return $metadata;
5✔
599
    }
600

601
    public function getPolicy(): ?string
602
    {
603
        return $this->policy;
934✔
604
    }
605

606
    public function withPolicy(?string $policy): static
607
    {
608
        $self = clone $this;
×
609
        $self->policy = $policy;
×
610

611
        return $self;
×
612
    }
613

614
    public function getSerialize(): ?array
615
    {
616
        return $this->serialize;
96✔
617
    }
618

619
    /**
620
     * @param Context|Groups|Ignore|SerializedName|SerializedPath|MaxDepth|array<array-key, Context|Groups|Ignore|SerializedName|SerializedPath|MaxDepth> $serialize
621
     */
622
    public function withSerialize(array|Context|Groups|Ignore|SerializedName|SerializedPath|MaxDepth $serialize): static
623
    {
624
        $self = clone $this;
96✔
625
        $self->serialize = (array) $serialize;
96✔
626

627
        return $self;
96✔
628
    }
629
}
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