8000 Add support for the @Ignore annotation · Issue #1566 · api-platform/api-platform · GitHub
[go: up one dir, main page]

Skip to content

Add support for the @Ignore annotation #1566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
TNAJanssen opened this issue Jun 20, 2020 · 15 comments
Open

Add support for the @Ignore annotation #1566

TNAJanssen opened this issue Jun 20, 2020 · 15 comments

Comments

@TNAJanssen
Copy link

Description
Symfony 5.1 brought us the @ignore annotation but it's not supported yet here.

Example
It allows to create a method for example that you don't want to expose in the API without using the Groups annotation

@mpiot
Copy link
mpiot commented Jul 16, 2020

+1, as mentioned in https://symfony.com/blog/new-in-symfony-5-1-serializer-improvements#added-ignore-annotation a PR symfony/symfony#28744 done by @dunglas add an @Ignore annotation.

Is there a specific way to use it in api-platform ? (because this PR was done by the api-platform creator on the Symfony edge, it seems strange that doesn't work on api-platform side)

@dunglas
Copy link
Member
dunglas commented Jul 16, 2020

It was indeed my intent to support it in API Platform too, but I didn’t have the time to do the PR yet. Any help on this will be very appreciated!

@mpiot
Copy link
mpiot commented Jul 16, 2020

@dunglas I can take a look at this, but I don't really know where to start. I thought that api-platform use the symfony serializer then take care of it automaticaly.

@vasilvestre
Copy link
Contributor

I would love to see this in API-P, I will try to work on it !

I have (as mpiot) no clue about where to start except I will modify test so it fit the needs here, then I will fix the test by modifying the code.

@lucasgranberg
Copy link

Quick n' dirty this is what I did to add support. I guess this should live in \ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory. There is no ignore field in the metadata but doing $propertyMetadata->withWritable(false)->withReadable(false); remove the field in the schemafactory.

    App\Api\OpenapiSchema\SerializationIgnoreExtractor:
        decorates: api_platform.metadata.property.metadata_factory
        decoration_priority: 22
        arguments: [ '@serializer.mapping.class_metadata_factory','@.inner' ]
        autowire: false
<?php

namespace App\Api\OpenapiSchema;

use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;

final class SerializationIgnoreExtractor implements PropertyMetadataFactoryInterface
{
    private PropertyMetadataFactoryInterface $decorated;
    private ClassMetadataFactoryInterface $serializerClassMetadataFactory;

    public function __construct(ClassMetadataFactoryInterface $serializerClassMetadataFactory, PropertyMetadataFactoryInterface $decorated)
    {
        $this->serializerClassMetadataFactory = $serializerClassMetadataFactory;
        $this->decorated = $decorated;
    }

    /**
     * {@inheritdoc}
     */
    public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata
    {
        $propertyMetadata = $this->decorated->create($resourceClass, $property, $options);

        $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($resourceClass);
        if(
            isset($serializerClassMetadata->getAttributesMetadata()[$property]) &&
            $serializerClassMetadata->getAttributesMetadata()[$property]->isIgnored()
        ){
            $propertyMetadata = $propertyMetadata->withWritable(false)->withReadable(false);
        }
        return $propertyMetadata;
    }
}

@dunglas
Copy link
Member
dunglas commented Dec 14, 2020

It's supported in API Platform 2.6!

@dunglas dunglas closed this as completed Dec 14, 2020
@lucasgranberg
Copy link

@dunglas as this is implemented in AbstractItemNormalizer it is supported when retrieving stuff from the API but the schema still exposes the ignored properties.

@dunglas dunglas reopened this Dec 15, 2020
@dunglas
Copy link
Member
dunglas commented Dec 15, 2020

@lucasgranberg got it. Would you mind to open a PR? It's indeed better to strip these properties at the schema level. The other patch should be reverted.

@lucasgranberg
Copy link

I could give it a shot but I need some pointers. Is $propertyMetadata->withWritable(false)->withReadable(false); the right way to go?

Looking at AbstractItemNormalizer it looks like I should do withInitializable(false) too:
https://github.com/api-platform/core/blob/f3c544a329f02454ae96cdefee7d7b0443bad136/src/Serializer/AbstractItemNormalizer.php#L373-L381

            if (
                $this->isAllowedAttribute($classOrObject, $propertyName, null, $context) &&
                (
                    isset($context['api_normalize']) && $propertyMetadata->isReadable() ||
                    isset($context['api_denormalize']) && ($propertyMetadata->isWritable() || !\is_object($classOrObject) && $propertyMetadata->isInitializable())
                )
            ) {
                $allowedAttributes[] = $propertyName;
            }

Also, is this code supposed to go in symfony bridge as it has to do with symfony/serializer?

@dunglas
Copy link
Member
dunglas commented Dec 15, 2020

I think the ignored properties should be totally removed from the collection PropertyNameCollection. This should be done in a factory implementing PropertyNameCollectionFactoryInterface.

@lucasgranberg
Copy link

The best thing would probably be if it was handled in symfony propertyinfo directly. There is code for it in symfony 5.2 but int only triggers if there is serialization groups:
https://github.com/symfony/symfony/blob/a4033bb58065fea0f7238e29b6735ed994554721/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php#L36

@lucasgranberg
Copy link

Ignore that, it already works with symfony 5.2!

@vasilvestre
Copy link
Contributor

Ignore that, it already works with symfony 5.2!

it does ? Adding test would be useful or that's like duplicating Symfony/Validator tests ?

@lucasgranberg
Copy link
lucasgranberg commented Dec 15, 2020

Oh no... I still had my "hack" implemented so thats why I thought it worked. I do not fully understand how api-platform uses propertyinfo but it should work since symfony 5.2 allows null as serialization group.

@lucasgranberg
Copy link

I did this PR:
api-platform/core#3907

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
0