Skip to content
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

fix: better generics support for State\ProcessorInterface #6103

Merged
merged 4 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/HttpCache/State/AddHeadersProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
use ApiPlatform\State\ProcessorInterface;
use Symfony\Component\HttpFoundation\Response;

/**
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*/
final class AddHeadersProcessor implements ProcessorInterface
{
/**
* @param ProcessorInterface<Response>|ProcessorInterface<mixed> $decorated
* @param ProcessorInterface<T1, T2> $decorated
*/
public function __construct(private readonly ProcessorInterface $decorated, private readonly bool $etag = false, private readonly ?int $maxAge = null, private readonly ?int $sharedMaxAge = null, private readonly ?array $vary = null, private readonly ?bool $public = null, private readonly ?int $staleWhileRevalidate = null, private readonly ?int $staleIfError = null)
{
Expand Down
8 changes: 7 additions & 1 deletion src/Hydra/State/HydraLinkProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@
use Symfony\Component\WebLink\GenericLinkProvider;
use Symfony\Component\WebLink\Link;

/**
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*/
final class HydraLinkProcessor implements ProcessorInterface
{
use CorsTrait;

/**
* @param ProcessorInterface<mixed> $decorated
* @param ProcessorInterface<T1, T2> $decorated
*/
public function __construct(private readonly ProcessorInterface $decorated, private readonly UrlGeneratorInterface $urlGenerator)
{
Expand Down
8 changes: 7 additions & 1 deletion src/State/CallableProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
use ApiPlatform\Metadata\Operation;
use Psr\Container\ContainerInterface;

/**
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*/
final class CallableProcessor implements ProcessorInterface
{
public function __construct(private readonly ?ContainerInterface $locator = null)
Expand All @@ -40,7 +46,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
throw new RuntimeException(sprintf('Processor "%s" not found on operation "%s"', $processor, $operation->getName()));
}

/** @var ProcessorInterface $processorInstance */
/** @var ProcessorInterface<T1, T2> $processorInstance */
$processorInstance = $this->locator->get($processor);

return $processorInstance->process($data, $operation, $uriVariables, $context);
Expand Down
9 changes: 9 additions & 0 deletions src/State/Processor/AddLinkHeaderProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\WebLink\HttpHeaderSerializer;

/**
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*/
final class AddLinkHeaderProcessor implements ProcessorInterface
{
/**
* @param ProcessorInterface<T1, T2> $decorated
*/
public function __construct(private readonly ProcessorInterface $decorated, private readonly ?HttpHeaderSerializer $serializer = new HttpHeaderSerializer())
{
}
Expand Down
2 changes: 1 addition & 1 deletion src/State/Processor/RespondProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
$status = $operation->getStatus();

if ($sunset = $operation->getSunset()) {
$headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTime::RFC1123);
$headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTimeInterface::RFC1123);
}

if ($acceptPatch = $operation->getAcceptPatch()) {
Expand Down
8 changes: 8 additions & 0 deletions src/State/Processor/SerializeProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,18 @@
/**
* Serializes data.
*
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*
* @author Kévin Dunglas <[email protected]>
*/
final class SerializeProcessor implements ProcessorInterface
{
/**
* @param ProcessorInterface<T1, T2> $processor
*/
public function __construct(private readonly ProcessorInterface $processor, private readonly SerializerInterface $serializer, private readonly SerializerContextBuilderInterface $serializerContextBuilder)
{
}
Expand Down
9 changes: 9 additions & 0 deletions src/State/Processor/WriteProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@
/**
* Bridges persistence and the API system.
*
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*
* @author Kévin Dunglas <[email protected]>
* @author Baptiste Meyer <[email protected]>
*/
final class WriteProcessor implements ProcessorInterface
{
use ClassInfoTrait;

/**
* @param ProcessorInterface<T1, T2> $processor
* @param ProcessorInterface<T1, T2> $callableProcessor
*/
public function __construct(private readonly ProcessorInterface $processor, private readonly ProcessorInterface $callableProcessor)
{
}
Expand Down
15 changes: 9 additions & 6 deletions src/State/ProcessorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,26 @@
namespace ApiPlatform\State;

use ApiPlatform\Metadata\Operation;
use Symfony\Component\HttpFoundation\Request;

/**
* Process data: send an email, persist to storage, add to queue etc.
* Processes data: sends an email, persists to storage, adds to queue etc.
*
* @template T
* @template T1
* @template T2
*
* @author Antoine Bluchet <[email protected]>
*/
interface ProcessorInterface
{
/**
* Handle the state.
* Handles the state.
*
* @param array<string, mixed> $uriVariables
* @param array<string, mixed>&array{request?: \Symfony\Component\HttpFoundation\Request, previous_data?: mixed, resource_class?: string, original_data?: mixed} $context
* @param T1 $data
* @param array<string, mixed> $uriVariables
* @param array<string, mixed>&array{request?: Request, previous_data?: mixed, resource_class?: string, original_data?: mixed} $context
*
* @return T
* @return T2
*/
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []);
}
8 changes: 5 additions & 3 deletions src/State/ProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace ApiPlatform\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
use Symfony\Component\HttpFoundation\Request;

/**
* Retrieves data from a persistence layer.
Expand All @@ -27,10 +29,10 @@ interface ProviderInterface
/**
* Provides data.
*
* @param array<string, mixed> $uriVariables
* @param array<string, mixed>|array{request?: \Symfony\Component\HttpFoundation\Request, resource_class?: string} $context
* @param array<string, mixed> $uriVariables
* @param array<string, mixed>|array{request?: Request, resource_class?: string} $context
*
* @return T|Pagination\PartialPaginatorInterface<T>|iterable<T>|null
* @return T|PartialPaginatorInterface<T>|iterable<T>|null
*/
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null;
}
8 changes: 7 additions & 1 deletion src/Symfony/State/MercureLinkProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@
use ApiPlatform\State\ProcessorInterface;
use Symfony\Component\Mercure\Discovery;

/**
* @template T1
* @template T2
*
* @implements ProcessorInterface<T1, T2>
*/
final class MercureLinkProcessor implements ProcessorInterface
{
/**
* @param ProcessorInterface<mixed> $decorated
* @param ProcessorInterface<T1, T2> $decorated
*/
public function __construct(private readonly ProcessorInterface $decorated, private readonly Discovery $discovery)
{
Expand Down
4 changes: 2 additions & 2 deletions tests/State/RespondProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function testRedirectToOperation(): void
return ($args[2] ?? null)?->getUriTemplate() ?? '/default';
});

/** @var ProcessorInterface<Response> $respondProcessor */
/** @var ProcessorInterface<string, Response> $respondProcessor */
$respondProcessor = new RespondProcessor($iriConverter->reveal(), $resourceClassResolver->reveal(), $operationMetadataFactory->reveal());

$response = $respondProcessor->process('content', $canonicalUriTemplateRedirectingOperation, context: [
Expand Down Expand Up @@ -103,7 +103,7 @@ public function testAddsExceptionHeaders(): void
{
$operation = new Get();

/** @var ProcessorInterface<Response> $respondProcessor */
/** @var ProcessorInterface<string, Response> $respondProcessor */
$respondProcessor = new RespondProcessor();
$req = new Request();
$req->attributes->set('exception', new TooManyRequestsHttpException(32));
Expand Down
Loading