Skip to content

Commit

Permalink
Switching ArgumentValueResolverInterface into ValueResolverInterface
Browse files Browse the repository at this point in the history
  • Loading branch information
Witold Karaś committed Jul 17, 2024
1 parent ba9c72e commit 4705763
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
3 changes: 2 additions & 1 deletion config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use DualMedia\DtoRequestBundle\Service\Type\CoercerService;
use DualMedia\DtoRequestBundle\Service\Validation\GroupProviderService;
use DualMedia\DtoRequestBundle\Service\Validation\TypeValidationHelper;
use DualMedia\DtoBundle\ArgumentResolver\DtoValueResolver;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\DependencyInjection\Reference;
Expand Down Expand Up @@ -137,7 +138,7 @@
->arg(6, new Reference(ActionValidatorService::class))
->arg(7, new Reference('validator'));

$services->set(DtoArgumentResolver::class)
$services->set(interface_exists(\Symfony\Component\HttpKernel\Controller\ValueResolverInterface::class) ? DtoValueResolver::class : DtoArgumentResolver::class)
->arg(0, new Reference(DtoResolverInterface::class))
->arg(1, new Reference('event_dispatcher'))
->tag('controller.argument_value_resolver');
Expand Down
3 changes: 2 additions & 1 deletion config/services_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use DualMedia\DtoRequestBundle\Service\Type\CoercerService;
use DualMedia\DtoRequestBundle\Service\Validation\TypeValidationHelper;
use DualMedia\DtoRequestBundle\Tests\Service\Entity\DummyModelProvider;
use DualMedia\DtoBundle\ArgumentResolver\DtoValueResolver;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;

Expand Down Expand Up @@ -49,7 +50,7 @@

DtoOADescriber::class,

DtoArgumentResolver::class,
interface_exists(\Symfony\Component\HttpKernel\Controller\ValueResolverInterface::class) ? DtoValueResolver::class : DtoArgumentResolver::class,

OnNullActionValidator::class,
HttpDtoActionSubscriber::class,
Expand Down
56 changes: 56 additions & 0 deletions src/ArgumentResolver/DtoValueResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace DualMedia\DtoBundle\ArgumentResolver;

use DualMedia\DtoBundle\Event\DtoResolvedEvent;
use DualMedia\DtoBundle\Exception\Dynamic\ParameterNotSupportedException;
use DualMedia\DtoBundle\Exception\Type\InvalidTypeCountException;
use DualMedia\DtoBundle\Interfaces\DtoInterface;
use DualMedia\DtoBundle\Interfaces\Resolver\DtoResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;

/** @psalm-suppress UndefinedClass */
if (interface_exists(\Symfony\Component\HttpKernel\Controller\ValueResolverInterface::class)) {
class DtoValueResolver implements \Symfony\Component\HttpKernel\Controller\ValueResolverInterface
{
public function __construct(
private DtoResolverInterface $resolverService,
private EventDispatcherInterface $eventDispatcher
) {
$this->dtoResolver = $resolverService;
$this->eventDispatcher = $eventDispatcher;
}

/**
* @param Request $request
* @param ArgumentMetadata $argument
*
* @return iterable<DtoInterface>
*
* @throws InvalidTypeCountException
* @throws ParameterNotSupportedException
*/
public function resolve(
Request $request,
ArgumentMetadata $argument
): iterable {
$class = $argument->getType();

if (null === class || !is_subclass_of(class, DtoInterface::class)) {
return [];
}

$this->eventDispatcher->dispatch(
new DtoResolvedEvent(
$object = $this->dtoResolver->resolve($request, $class)
)
);

$object->setOptional($argument->isNullable());

yield $object;
}
}
}
74 changes: 74 additions & 0 deletions tests/Unit/ArgumentResolver/DtoValueResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace DualMedia\DtoBundle\Tests\Unit\ArgumentResolver;

use DualMedia\DtoBundle\ArgumentResolver\DtoValueResolver;
use DualMedia\DtoBundle\Event\DtoResolvedEvent;
use DualMedia\DtoBundle\Tests\Fixtures\Model\ResolveDto\SubDto;
use DualMedia\DtoBundle\Tests\PHPUnit\KernelTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;

class DtoValueResolverTest extends KernelTestCase
{
private ValueResolverInterface $service;
private MockObject $eventMock;

protected function setUp(): void
{
self::bootKernel();
$this->eventMock = $this->createMock(EventDispatcherInterface::class);
self::$container->set('event_dispatcher', $this->eventMock);

if (interface_exists(\Symfony\Component\HttpKernel\Controller\ValueResolverInterface::class)) {
$this->service = $this->getService(DtoValueResolver::class);
}
}

public function testResolve(): void
{
$this->assertTrue(true);

if (interface_exists(\Symfony\Component\HttpKernel\Controller\ValueResolverInterface::class)) {
$event = $this->deferCallable(function ($event): void {
$this->assertInstanceOf(DtoResolvedEvent::class, $event);
$this->assertInstanceOf(SubDto::class, $event->getDto());
});

$this->eventMock->expects($this->once())
->method('dispatch')
->willReturnCallback(function (...$args) use ($event) {
$event->set($args);

return $args[0];
});

$request = new Request([], [
'value' => 155,
'floaty_boy' => 22.5,
]);

$mock = $this->createMock(ArgumentMetadata::class);
$mock->method('getType')
->willReturn(SubDto::class);
$mock->method('isNullable')
->willReturn(false);

/**
* @var SubDto $dto
* @psalm-suppress InvalidArgument
*/
$dto = iterator_to_array($this->service->resolve($request, $mock))[0];

$this->assertInstanceOf(SubDto::class, $dto);
$this->assertTrue($dto->isValid());
$this->assertEquals(155, $dto->value);
$this->assertEquals(22.5, $dto->floatVal);
$this->assertTrue($dto->visited('value'));
$this->assertTrue($dto->visited('floatVal'));
}
}
}

0 comments on commit 4705763

Please sign in to comment.