Skip to content

Commit

Permalink
feat: Allow ignoring properties from schema
Browse files Browse the repository at this point in the history
  • Loading branch information
DominicLuidold committed Jan 9, 2025
1 parent 13408ab commit 8586a1e
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/Attribute/Ignore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Nelmio\ApiDocBundle\Attribute;

#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
final class Ignore
{
}
19 changes: 19 additions & 0 deletions src/ModelDescriber/Annotations/AnnotationsReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Nelmio\ApiDocBundle\ModelDescriber\Annotations;

use Doctrine\Common\Annotations\Reader;
use Nelmio\ApiDocBundle\Attribute\Ignore;
use Nelmio\ApiDocBundle\Model\ModelRegistry;
use OpenApi\Annotations as OA;
use OpenApi\Generator;
Expand Down Expand Up @@ -73,6 +74,24 @@ public function updateProperty($reflection, OA\Property $property, ?array $seria
$this->symfonyConstraintAnnotationReader->updateProperty($reflection, $property, $serializationGroups);
}

/**
* @param \ReflectionProperty[]|\ReflectionMethod[] $reflections
*/
public function shouldDescribeProperty(array $reflections): bool
{
if (\PHP_VERSION_ID < 80100) {
return true;
}

foreach ($reflections as $reflection) {
if ([] !== $reflection->getAttributes(Ignore::class)) {
return false;
}
}

return true;
}

/**
* Whether the model describer should continue reading class properties
* after updating the open api schema from an `OA\Schema` definition.
Expand Down
6 changes: 6 additions & 0 deletions src/ModelDescriber/JMSModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ public function describe(Model $model, OA\Schema $schema)
}
}

if (!$annotationsReader->shouldDescribeProperty($reflections)) {
$context->popPropertyMetadata();

continue;
}

$groups = $this->computeGroups($context, $item->type);

if (true === $item->inline && isset($item->type['name'])) {
Expand Down
4 changes: 4 additions & 0 deletions src/ModelDescriber/ObjectModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ public function describe(Model $model, OA\Schema $schema)

$reflections = $this->getReflections($reflClass, $propertyName);

if (!$annotationsReader->shouldDescribeProperty($reflections)) {
continue;
}

// Check if a custom name is set
foreach ($reflections as $reflection) {
$serializedName = $annotationsReader->getPropertyName($reflection, $serializedName);
Expand Down
13 changes: 13 additions & 0 deletions tests/Functional/Controller/ApiController81.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityThroughNameConverter;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType81;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithFalsyDefaults;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithIgnoredProperty;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithNullableSchemaSet;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithObjectType;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef;
Expand Down Expand Up @@ -350,6 +351,18 @@ public function entityWithUuid()
{
}

#[Route('/entity-with-ignored-property', methods: ['GET', 'POST'])]
#[OA\Response(
response: 200,
description: 'success',
content: new OA\JsonContent(
ref: new Model(type: EntityWithIgnoredProperty::class),
),
)]
public function entityWithIgnoredProperty()
{
}

#[Route('/form-with-alternate-type', methods: ['POST'])]
#[OA\Response(
response: 204,
Expand Down
12 changes: 12 additions & 0 deletions tests/Functional/Controller/JMSController81.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSDualComplex;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSEnum81;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSIgnoredProperty;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNamingStrategyConstraints;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChat;
Expand Down Expand Up @@ -157,4 +158,15 @@ public function discriminatorMapAction()
public function enumArrayAction()
{
}

#[Route('/api/jms_ignored_property', methods: ['GET'])]
#[OA\Response(
response: 200,
description: 'Success',
content: new Model(type: JMSIgnoredProperty::class)
)
]
public function ignoredProperty()
{
}
}
26 changes: 26 additions & 0 deletions tests/Functional/Entity/EntityWithIgnoredProperty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Nelmio\ApiDocBundle\Tests\Functional\Entity;

use Nelmio\ApiDocBundle\Attribute\Ignore;

class EntityWithIgnoredProperty
{
public function __construct(
public string $regularProperty,
#[Ignore]
public string $ignoredProperty,
) {
}
}
33 changes: 33 additions & 0 deletions tests/Functional/Entity/JMSIgnoredProperty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Nelmio\ApiDocBundle\Tests\Functional\Entity;

use JMS\Serializer\Annotation as Serializer;
use Nelmio\ApiDocBundle\Attribute\Ignore;

/**
* JMSIgnoredProperty.
*/
#[Serializer\ExclusionPolicy('all')]
class JMSIgnoredProperty
{
#[Serializer\Type('string')]
#[Serializer\Expose]
private $regularProperty;

#[Ignore]
#[Serializer\Type('string')]
#[Serializer\Expose]
private $ignoredProperty;
}
14 changes: 14 additions & 0 deletions tests/Functional/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,20 @@ public function testEntityWithUuid(): void
], json_decode($this->getModel('EntityWithUuid')->toJson(), true));
}

public function testEntityWithIgnoredProperty(): void
{
self::assertEquals([
'schema' => 'EntityWithIgnoredProperty',
'type' => 'object',
'required' => ['regularProperty'],
'properties' => [
'regularProperty' => [
'type' => 'string',
],
],
], json_decode($this->getModel('EntityWithIgnoredProperty')->toJson(), true));
}

public function testEntitiesWithRefInSchemaDoNoReadOtherProperties(): void
{
$model = $this->getModel('EntityWithRef');
Expand Down
13 changes: 13 additions & 0 deletions tests/Functional/JMSFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,19 @@ public function testModeDiscriminatorMap(): void
], json_decode($this->getModel('JMSAbstractUser')->toJson(), true));
}

public function testIgnoredProperty(): void
{
self::assertEquals([
'schema' => 'JMSIgnoredProperty',
'type' => 'object',
'properties' => [
'regular_property' => [
'type' => 'string',
],
],
], json_decode($this->getModel('JMSIgnoredProperty')->toJson(), true));
}

/**
* @param array<mixed> $options
*/
Expand Down

0 comments on commit 8586a1e

Please sign in to comment.