Supply validation group context with Symfony / API Platform

Viewed 520

As I said in the title I try to supply the validation context of Sf / Api platform.

More precisely I would like to have different validation groups depending on an entity value.

If i'm a User with ROLE_PRO : then i want validate:pro and default as validation groups.

If i'm a User with ROLE_USER : then i want default as validation group.

I tried to create an event based on the following api-platform event but I can't find a way to supply the ExecutionContextInterface with my validation groups

public static function getSubscribedEvents()
{
     return [
          KernelEvents::VIEW => ['addGroups', EventPriorities::PRE_VALIDATE],
     ];
}
1 Answers

As you can see in api-platform documentation (https://api-platform.com/docs/core/serialization/#changing-the-serialization-context-dynamically) you can manipulate validation groups dynamically with a service.

First of all, in your api-platform configuration, you have to define default validation group:

App\Class\MyClass:
  properties:
    id:
      identifier: true
  attributes:
    input: false
    normalization_context:
      groups: ['default']

You need to define a new service which implements SerializerContextBuilderInterface

class ContextBuilder implements SerializerContextBuilderInterface
{
    private SerializerContextBuilderInterface $decorated;
    private AuthorizationCheckerInterface $authorizationChecker;

    public function __construct(SerializerContextBuilderInterface $decorated, AuthorizationCheckerInterface $authorizationChecker)
    {
        $this->decorated = $decorated;
        $this->authorizationChecker = $authorizationChecker;
    }

    public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array
    {
        $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);

        if (isset($context['groups']) && $this->authorizationChecker->isGranted('ROLE_PRO') && true === $normalization) {
            $context['groups'][] = 'validate:pro';
        }
        return $context;
    }
}

Also, you need to configure your new service with a decorator

App\Builder\ContextBuilder:
        decorates: 'api_platform.serializer.context_builder'
        arguments: [ '@App\Builder\ContextBuilder.inner' ]

What it's happening here is:

You're overriding the ContextBuilder. First of all you create the context from request and from configuration (first line of createFromRequest method) and after this, you modify the context depeding of which user is logged.

Thanks!

Related