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

Init form provider #793

Merged
merged 1 commit into from
Nov 23, 2023
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
40 changes: 5 additions & 35 deletions src/Component/Tests/Symfony/EventListener/FormListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
namespace Sylius\Component\Resource\Tests\Symfony\EventListener;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Sylius\Resource\Context\Context;
use Sylius\Resource\Context\Initiator\RequestContextInitiatorInterface;
use Sylius\Resource\Metadata\BulkUpdate;
use Sylius\Resource\Metadata\Create;
use Sylius\Resource\Metadata\Operation\HttpOperationInitiatorInterface;
use Sylius\Resource\Metadata\Operations;
use Sylius\Resource\Metadata\Show;
use Sylius\Resource\Symfony\EventListener\FormListener;
use Sylius\Resource\Symfony\Form\Factory\FormFactoryInterface;
Expand Down Expand Up @@ -75,16 +75,10 @@ public function it_handles_forms(): void
$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$attributes->get('_route')->willReturn('app_dummy_show');
Copy link
Member Author

@loic425 loic425 Nov 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed a lot of non-necessary code in this test class, but in the end, this form listener and its PHPUnit test class will be removed.

$attributes->all('_sylius')->willReturn(['resource' => 'app.dummy']);

$operation = new Create(formType: 'App\Type\DummyType');

$this->operationInitiator->initializeOperation($request)->willReturn($operation);

$operations = new Operations();
$operations->add('app_dummy_show', $operation);

$context = new Context();
$this->contextInitiator->initializeContext($request)->willReturn($context);

Expand Down Expand Up @@ -119,20 +113,14 @@ public function it_does_nothing_when_controller_result_is_a_response(): void
$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$attributes->get('_route')->willReturn('app_dummy_show');
$attributes->all('_sylius')->willReturn(['resource' => 'app.dummy']);

$operation = new Create(formType: 'App\Type\DummyType');

$this->operationInitiator->initializeOperation($request)->willReturn($operation);

$operations = new Operations();
$operations->add('app_dummy_show', $operation);

$context = new Context();
$this->contextInitiator->initializeContext($request)->willReturn($context);

$this->formFactory->create($operation, $context, ['foo' => 'fighters'])
$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;
Expand Down Expand Up @@ -162,20 +150,14 @@ public function it_does_nothing_when_operation_has_no_form_type(): void
$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$attributes->get('_route')->willReturn('app_dummy_show');
$attributes->all('_sylius')->willReturn(['resource' => 'app.dummy']);

$operation = new Create(formType: null);

$this->operationInitiator->initializeOperation($request)->willReturn($operation);

$operations = new Operations();
$operations->add('app_dummy_show', $operation);

$context = new Context();
$this->contextInitiator->initializeContext($request)->willReturn($context);

$this->formFactory->create($operation, $context, ['foo' => 'fighters'])
$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;
Expand Down Expand Up @@ -205,20 +187,14 @@ public function it_does_nothing_when_operation_is_not_a_create_or_update(): void
$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$attributes->get('_route')->willReturn('app_dummy_show');
$attributes->all('_sylius')->willReturn(['resource' => 'app.dummy']);

$operation = new Show(formType: 'App\Type\DummyType');

$this->operationInitiator->initializeOperation($request)->willReturn($operation);

$operations = new Operations();
$operations->add('app_dummy_show', $operation);

$context = new Context();
$this->contextInitiator->initializeContext($request)->willReturn($context);

$this->formFactory->create($operation, $context, ['foo' => 'fighters'])
$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;
Expand Down Expand Up @@ -248,20 +224,14 @@ public function it_does_nothing_when_operation_is_a_bulk_update(): void
$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$attributes->get('_route')->willReturn('app_dummy_show');
$attributes->all('_sylius')->willReturn(['resource' => 'app.dummy']);

$operation = new BulkUpdate(formType: 'App\Type\DummyType');

$this->operationInitiator->initializeOperation($request)->willReturn($operation);

$operations = new Operations();
$operations->add('app_dummy_show', $operation);

$context = new Context();
$this->contextInitiator->initializeContext($request)->willReturn($context);

$this->formFactory->create($operation, $context, ['foo' => 'fighters'])
$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;
Expand Down
191 changes: 191 additions & 0 deletions src/Component/Tests/Symfony/Form/State/FormProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<?php

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

declare(strict_types=1);

namespace Sylius\Component\Resource\Tests\Symfony\Form\State;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Sylius\Resource\Context\Context;
use Sylius\Resource\Context\Option\RequestOption;
use Sylius\Resource\Metadata\BulkUpdate;
use Sylius\Resource\Metadata\Create;
use Sylius\Resource\Metadata\Operations;
use Sylius\Resource\Metadata\Show;
use Sylius\Resource\State\ProviderInterface;
use Sylius\Resource\Symfony\Form\Factory\FormFactoryInterface;
use Sylius\Resource\Symfony\Form\State\FormProvider;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

final class FormProviderTest extends TestCase
{
use ProphecyTrait;

private ProviderInterface|ObjectProphecy $decorated;

private FormFactoryInterface|ObjectProphecy $formFactory;

private FormProvider $formProvider;

protected function setUp(): void
{
$this->decorated = $this->prophesize(ProviderInterface::class);
$this->formFactory = $this->prophesize(FormFactoryInterface::class);

$this->formProvider = new FormProvider(
$this->decorated->reveal(),
$this->formFactory->reveal(),
);
}

/** @test */
public function it_handles_forms(): void
{
$request = $this->prophesize(Request::class);
$attributes = $this->prophesize(ParameterBag::class);
$form = $this->prophesize(FormInterface::class);

$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html')->shouldBeCalled();

$operation = new Create(formType: 'App\Type\DummyType');

$context = new Context(new RequestOption($request->reveal()));

$this->decorated->provide($operation, $context)->willReturn(['foo' => 'fighters'])->shouldBeCalled();

$this->formFactory->create($operation, $context, ['foo' => 'fighters'])
->willReturn($form)
->shouldBeCalled()
;

$form->handleRequest($request)->willReturn($form)->shouldBeCalled();

$attributes->set('form', $form)->shouldBeCalled();

$this->formProvider->provide($operation, $context);
}

/** @test */
public function it_does_nothing_when_data_is_a_response(): void
{
$request = $this->prophesize(Request::class);
$attributes = $this->prophesize(ParameterBag::class);
$form = $this->prophesize(FormInterface::class);
$response = $this->prophesize(Response::class);

$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$operation = new Create(formType: 'App\Type\DummyType');

$context = new Context(new RequestOption($request->reveal()));
$this->decorated->provide($operation, $context)->willReturn($response)->shouldBeCalled();

$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;

$form->handleRequest($request)->willReturn($form)->shouldNotBeCalled();

$attributes->set('form', $form)->shouldNotBeCalled();

$this->formProvider->provide($operation, $context);
}

/** @test */
public function it_does_nothing_when_operation_has_no_form_type(): void
{
$request = $this->prophesize(Request::class);
$attributes = $this->prophesize(ParameterBag::class);
$form = $this->prophesize(FormInterface::class);

$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html')->shouldBeCalled();

$operation = new Create(formType: null);

$context = new Context(new RequestOption($request->reveal()));

$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;

$form->handleRequest($request)->willReturn($form)->shouldNotBeCalled();

$attributes->set('form', $form)->shouldNotBeCalled();

$this->formProvider->provide($operation, $context);
}

/** @test */
public function it_does_nothing_when_operation_is_not_a_create_or_update(): void
{
$request = $this->prophesize(Request::class);
$attributes = $this->prophesize(ParameterBag::class);
$form = $this->prophesize(FormInterface::class);

$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$operation = new Show(formType: 'App\Type\DummyType');

$context = new Context(new RequestOption($request->reveal()));

$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;

$form->handleRequest($request)->willReturn($form)->shouldNotBeCalled();

$attributes->set('form', $form)->shouldNotBeCalled();

$this->formProvider->provide($operation, $context);
}

/** @test */
public function it_does_nothing_when_operation_is_a_bulk_update(): void
{
$request = $this->prophesize(Request::class);
$attributes = $this->prophesize(ParameterBag::class);
$form = $this->prophesize(FormInterface::class);

$request->attributes = $attributes;
$request->getRequestFormat()->willReturn('html');

$operation = new BulkUpdate(formType: 'App\Type\DummyType');

$operations = new Operations();
$operations->add('app_dummy_show', $operation);

$context = new Context(new RequestOption($request->reveal()));

$this->formFactory->create(Argument::cetera())
->willReturn($form)
->shouldNotBeCalled()
;

$form->handleRequest($request)->willReturn($form)->shouldNotBeCalled();

$attributes->set('form', $form)->shouldNotBeCalled();

$this->formProvider->provide($operation, $context);
}
}
64 changes: 64 additions & 0 deletions src/Component/src/Symfony/Form/State/FormProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

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

declare(strict_types=1);

namespace Sylius\Resource\Symfony\Form\State;

use Sylius\Resource\Context\Context;
use Sylius\Resource\Context\Option\RequestOption;
use Sylius\Resource\Metadata\BulkOperationInterface;
use Sylius\Resource\Metadata\CreateOperationInterface;
use Sylius\Resource\Metadata\Operation;
use Sylius\Resource\Metadata\UpdateOperationInterface;
use Sylius\Resource\State\ProviderInterface;
use Sylius\Resource\Symfony\Form\Factory\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Response;

final class FormProvider implements ProviderInterface
{
public function __construct(
private ProviderInterface $decorated,
private FormFactoryInterface $formFactory,
) {
}

public function provide(Operation $operation, Context $context): object|array|null
{
$data = $this->decorated->provide($operation, $context);

$request = $context->get(RequestOption::class)?->request();

if (null === $request) {
return $data;
}

/** @var string $format */
$format = $request->getRequestFormat();

if (
$data instanceof Response ||
$operation instanceof BulkOperationInterface ||
!($operation instanceof CreateOperationInterface || $operation instanceof UpdateOperationInterface) ||
'html' !== $format ||
null === $operation->getFormType()
) {
return $data;
}

$form = $this->formFactory->create($operation, $context, $data);
$form->handleRequest($request);

$request->attributes->set('form', $form);

return $data;
}
}