Skip to content

[FrameworkBundle] Add BC layer and FormView handling after #46854 #47600

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

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ CHANGELOG
* Add `resolve-env` option to `debug:config` command to display actual values of environment variables in dumped configuration
* Add `NotificationAssertionsTrait`
* Add option `framework.catch_all_throwables` to allow `Symfony\Component\HttpKernel\HttpKernel` to catch all kinds of `Throwable`
* Make `AbstractController::render()` able to deal with forms and deprecate `renderForm()`
* Make `AbstractController::render()` able to deal with forms and deprecate `renderForm()` when `framework.form.controllers_render_form_views` is `true`
* Deprecate the `Symfony\Component\Serializer\Normalizer\ObjectNormalizer` and
`Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against
`Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand Down Expand Up @@ -58,6 +59,9 @@ abstract class AbstractController implements ServiceSubscriberInterface
*/
protected $container;

// To be removed in 7.0
private bool $renderFormViews = false;

/**
* @required
*/
Expand All @@ -70,6 +74,14 @@ public function setContainer(ContainerInterface $container): ?ContainerInterface
return $previous;
}

/**
* @internal To be removed in 7.0
*/
public function setRenderFormViews(bool $renderFormViews): void
{
$this->renderFormViews = $renderFormViews;
}

/**
* Gets a container parameter by its name.
*/
Expand Down Expand Up @@ -233,9 +245,11 @@ protected function renderView(string $view, array $parameters = []): string
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
}

foreach ($parameters as $k => $v) {
if ($v instanceof FormInterface) {
$parameters[$k] = $v->createView();
if ($this->renderFormViews) {
foreach ($parameters as $k => $v) {
if ($v instanceof FormInterface) {
$parameters[$k] = $v->createView();
}
}
}

Expand All @@ -256,9 +270,12 @@ protected function render(string $view, array $parameters = [], Response $respon
$response = new Response();
}

if (200 === $response->getStatusCode()) {
if ($this->renderFormViews && 200 === $response->getStatusCode()) {
foreach ($parameters as $v) {
if ($v instanceof FormInterface && $v->isSubmitted() && !$v->isValid()) {
if (
$v instanceof FormInterface && $v->isSubmitted() && !$v->isValid()
|| $v instanceof FormView && !($v->vars['valid'] ?? true)
) {
$response->setStatusCode(422);
break;
}
Expand All @@ -281,7 +298,16 @@ protected function renderForm(string $view, array $parameters = [], Response $re
{
trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s::renderForm()" method is deprecated, use "render()" instead.', get_debug_type($this));

return $this->render($view, $parameters, $response);
$oldValue = $this->renderFormViews;
$this->renderFormViews = true;

try {
$response = $this->render($view, $parameters, $response);
} finally {
$this->renderFormViews = $oldValue;
}

return $response;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,21 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI
->booleanNode('legacy_error_messages')
->setDeprecated('symfony/framework-bundle', '6.2')
->end()
// to be deprecated in Symfony 7.1
->booleanNode('controllers_render_form_views')
->info('Enables "AbstractController::render()" method to convert FormInterface to FormView and setting 422 status code when invalid.')
->defaultFalse()
->validate()
->always()
->then(function ($v) {
if (false === $v) {
trigger_deprecation('symfony/framework-bundle', '6.2', 'Not setting the "framework.form.controllers_render_form_views" option to "true" is deprecated. It will have no effect as of Symfony 7.0.');
}

return $v;
})
->end()
->end()
->end()
->end()
->end()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ class FrameworkExtension extends Extension
private bool $notifierConfigEnabled = false;
private bool $serializerConfigEnabled = false;
private bool $propertyAccessConfigEnabled = false;
// To be removed in 7.0
private bool $controllersRenderFormViews = false;
private static bool $lockConfigEnabled = false;

/**
Expand Down Expand Up @@ -596,6 +598,7 @@ public function load(array $configs, ContainerBuilder $container)
$container->registerForAutoconfiguration(ValueResolverInterface::class)
->addTag('controller.argument_value_resolver');
$container->registerForAutoconfiguration(AbstractController::class)
->addMethodCall('setRenderFormViews', [$this->controllersRenderFormViews])
->addTag('controller.service_arguments');
$container->registerForAutoconfiguration(DataCollectorInterface::class)
->addTag('data_collector');
Expand Down Expand Up @@ -746,6 +749,8 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont
->clearTag('kernel.reset')
;
}

$this->controllersRenderFormViews = $config['form']['controllers_render_form_views'];
}

private function registerHttpCacheConfiguration(array $config, ContainerBuilder $container, bool $httpMethodOverride)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,29 @@ public function testRenderTwig()
$this->assertEquals('bar', $controller->render('foo')->getContent());
}

/**
* @group legacy
*/
public function testRenderViewWithForm()
{
$form = $this->getMockBuilder(FormInterface::class)->getMock();
$form->expects($this->never())->method('createView');

$twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->with('foo', ['bar' => $form])->willReturn('bar');

$container = new Container();
$container->set('twig', $twig);

$controller = $this->createController();
$controller->setContainer($container);

$content = $controller->renderView('foo', ['bar' => $form]);

$this->assertSame('bar', $content);
}

public function testRenderViewWithFormHandlesFormView()
{
$formView = new FormView();

Expand All @@ -407,13 +429,39 @@ public function testRenderViewWithForm()

$controller = $this->createController();
$controller->setContainer($container);
$controller->setRenderFormViews(true);

$content = $controller->renderView('foo', ['bar' => $form]);

$this->assertSame('bar', $content);
}

/**
* @group legacy
*/
public function testRenderWithFormSubmittedAndInvalid()
{
$form = $this->getMockBuilder(FormInterface::class)->getMock();
$form->expects($this->never())->method('createView');
$form->expects($this->never())->method('isSubmitted');
$form->expects($this->never())->method('isValid');

$twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->with('foo', ['bar' => $form])->willReturn('bar');

$container = new Container();
$container->set('twig', $twig);

$controller = $this->createController();
$controller->setContainer($container);

$response = $controller->render('foo', ['bar' => $form]);

$this->assertSame(200, $response->getStatusCode());
$this->assertSame('bar', $response->getContent());
}

public function testRenderWithFormSubmittedAndInvalidHandlesStatusCode()
{
$formView = new FormView();

Expand All @@ -430,13 +478,35 @@ public function testRenderWithFormSubmittedAndInvalid()

$controller = $this->createController();
$controller->setContainer($container);
$controller->setRenderFormViews(true);

$response = $controller->render('foo', ['bar' => $form]);

$this->assertSame(422, $response->getStatusCode());
$this->assertSame('bar', $response->getContent());
}

public function testRenderWithInvalidFormViewHandlesStatusCode()
{
$formView = new FormView();
$formView->vars['valid'] = false;

$twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->with('foo', ['bar' => $formView])->willReturn('bar');

$container = new Container();
$container->set('twig', $twig);

$controller = $this->createController();
$controller->setContainer($container);
$controller->setRenderFormViews(true);

$response = $controller->render('foo', ['bar' => $formView]);

$this->assertSame(422, $response->getStatusCode());
$this->assertSame('bar', $response->getContent());
}

/**
* @group legacy
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ protected static function getBundleDefaultConfig()
'enabled' => null, // defaults to csrf_protection.enabled
'field_name' => '_token',
],
'controllers_render_form_views' => false,
],
'esi' => ['enabled' => false],
'ssi' => ['enabled' => false],
Expand Down