sonata-project / SonataAdminBundle

The missing Symfony Admin Generator
https://docs.sonata-project.org/projects/SonataAdminBundle
MIT License
2.11k stars 1.26k forks source link

Submitting a form with ->render instead of ->renderWithExtraParams does not work #8120

Closed AntoineRoue closed 11 months ago

AntoineRoue commented 1 year ago

Environment

Sonata packages

show

``` $ composer show --latest 'sonata-project/*' Direct dependencies required in composer.json: sonata-project/admin-bundle 4.28.0 4.28.0 The missing Symfony Admin Generator sonata-project/doctrine-orm-admin-bundle 4.13.0 4.14.0 Integrate Doctrine ORM into the SonataAdminBundle sonata-project/intl-bundle 3.1.0 3.1.0 Symfony SonataIntlBundle sonata-project/media-bundle 4.10.4 4.10.4 Symfony SonataMediaBundle sonata-project/twig-extensions 2.3.0 2.3.0 Sonata twig extensions sonata-project/user-bundle 5.10.0 5.10.0 Symfony SonataUserBundle Transitive dependencies not required in composer.json: sonata-project/block-bundle 5.0.1 5.0.1 Symfony SonataBlockBundle sonata-project/doctrine-extensions 2.3.0 2.3.0 Doctrine2 behavioral extensions sonata-project/exporter 3.2.0 3.3.0 Lightweight Exporter library sonata-project/form-extensions 2.1.0 2.1.0 Symfony form extensions ```

Symfony packages

show

``` $ composer show --latest 'symfony/*' Direct dependencies required in composer.json: symfony/console v6.3.4 v6.3.4 Eases the creation of beautiful and testable command line interfaces symfony/debug-bundle v6.3.2 v6.3.2 Provides a tight integration of the Symfony VarDumper component a... symfony/doctrine-messenger v6.3.6 v6.3.6 Symfony Doctrine Messenger Bridge symfony/dotenv v6.3.0 v6.3.0 Registers environment variables from a .env file symfony/filesystem v6.3.1 v6.3.1 Provides basic utilities for the filesystem symfony/flex v2.4.0 v2.4.0 Composer plugin for Symfony symfony/framework-bundle v6.3.6 v6.3.6 Provides a tight integration between Symfony components and the S... symfony/mailer v6.3.5 v6.3.5 Helps sending emails symfony/messenger v6.3.6 v6.3.6 Helps applications send and receive messages to/from other applic... symfony/monolog-bundle v3.8.0 v3.8.0 Symfony MonologBundle symfony/rate-limiter v6.3.6 v6.3.6 Provides a Token Bucket implementation to rate limit input and ou... symfony/runtime v6.3.2 v6.3.2 Enables decoupling PHP applications from global state symfony/serializer v6.3.6 v6.3.6 Handles serializing and deserializing data structures, including ... symfony/stopwatch v6.3.0 v6.3.0 Provides a way to profile code symfony/twig-bundle v6.3.0 v6.3.0 Provides a tight integration of Twig into the Symfony full-stack ... symfony/web-profiler-bundle v6.3.6 v6.3.6 Provides a development tool that gives detailed information about... symfony/webpack-encore-bundle v1.17.2 v2.1.1 Integration with your Symfony app & Webpack Encore! symfony/yaml v6.3.3 v6.3.3 Loads and dumps YAML files Transitive dependencies not required in composer.json: symfony/asset v6.3.0 v6.3.0 Manages URL generation and versioning of web assets such as CSS s... symfony/cache v6.3.6 v6.3.6 Provides extended PSR-6, PSR-16 (and tags) implementations symfony/cache-contracts v3.3.0 v3.3.0 Generic abstractions related to caching symfony/clock v6.3.4 v6.3.4 Decouples applications from the system clock symfony/config v6.3.2 v6.3.2 Helps you find, load, combine, autofill and validate configuratio... symfony/dependency-injection v6.3.5 v6.3.5 Allows you to standardize and centralize the way objects are cons... symfony/deprecation-contracts v3.3.0 v3.3.0 A generic function and convention to trigger deprecation notices symfony/doctrine-bridge v6.3.6 v6.3.6 Provides integration for Doctrine with various Symfony components symfony/error-handler v6.3.5 v6.3.5 Provides tools to manage errors and ease debugging PHP code symfony/event-dispatcher v6.3.2 v6.3.2 Provides tools that allow your application components to communic... symfony/event-dispatcher-contracts v3.3.0 v3.3.0 Generic abstractions related to dispatching event symfony/expression-language v6.3.0 v6.3.0 Provides an engine that can compile and evaluate expressions symfony/finder v6.3.5 v6.3.5 Finds files and directories via an intuitive fluent interface symfony/form v6.3.6 v6.3.6 Allows to easily create, process and reuse HTML forms symfony/http-client v6.3.6 v6.3.6 Provides powerful methods to fetch HTTP resources synchronously o... symfony/http-client-contracts v3.3.0 v3.3.0 Generic abstractions related to HTTP clients symfony/http-foundation v6.3.6 v6.3.6 Defines an object-oriented layer for the HTTP specification symfony/http-kernel v6.3.6 v6.3.6 Provides a structured process for converting a Request into a Res... symfony/intl v6.3.2 v6.3.2 Provides access to the localization data of the ICU library symfony/mime v6.3.5 v6.3.5 Allows manipulating MIME messages symfony/monolog-bridge v6.3.1 v6.3.1 Provides integration for Monolog with various Symfony components symfony/options-resolver v6.3.0 v6.3.0 Provides an improved replacement for the array_replace PHP function symfony/password-hasher v6.3.5 v6.3.5 Provides password hashing utilities symfony/polyfill-intl-grapheme v1.28.0 v1.28.0 Symfony polyfill for intl's grapheme_* functions symfony/polyfill-intl-icu v1.28.0 v1.28.0 Symfony polyfill for intl's ICU-related data and classes symfony/polyfill-intl-idn v1.28.0 v1.28.0 Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions symfony/polyfill-intl-normalizer v1.28.0 v1.28.0 Symfony polyfill for intl's Normalizer class and related functions symfony/polyfill-mbstring v1.28.0 v1.28.0 Symfony polyfill for the Mbstring extension symfony/polyfill-php72 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 7.2+ features to lower PHP ... symfony/polyfill-php73 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 7.3+ features to lower PHP ... symfony/polyfill-php80 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 8.0+ features to lower PHP ... symfony/polyfill-php83 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 8.3+ features to lower PHP ... symfony/process v6.3.4 v6.3.4 Executes commands in sub-processes symfony/property-access v6.3.2 v6.3.2 Provides functions to read and write from/to an object or array u... symfony/property-info v6.3.0 v6.3.0 Extracts information about PHP class' properties using metadata o... symfony/routing v6.3.5 v6.3.5 Maps an HTTP request to a set of configuration variables symfony/security-acl v3.3.2 v3.3.2 Symfony Security Component - ACL (Access Control List) symfony/security-bundle v6.3.6 v6.3.6 Provides a tight integration of the Security component into the S... symfony/security-core v6.3.5 v6.3.5 Symfony Security Component - Core Library symfony/security-csrf v6.3.2 v6.3.2 Symfony Security Component - CSRF Library symfony/security-http v6.3.6 v6.3.6 Symfony Security Component - HTTP Integration symfony/service-contracts v3.3.0 v3.3.0 Generic abstractions related to writing services symfony/string v6.3.5 v6.3.5 Provides an object-oriented API to strings and deals with bytes, ... symfony/translation v6.3.6 v6.3.6 Provides tools to internationalize your application symfony/translation-contracts v3.3.0 v3.3.0 Generic abstractions related to translation symfony/twig-bridge v6.3.5 v6.3.5 Provides integration for Twig with various Symfony components symfony/validator v6.3.6 v6.3.6 Provides tools to validate values symfony/var-dumper v6.3.6 v6.3.6 Provides mechanisms for walking through any arbitrary PHP variable symfony/var-exporter v6.3.6 v6.3.6 Allows exporting any serializable PHP data structure to plain PHP... ```

PHP version

$ php -v
PHP 8.2.8 (cli) (built: Jul  8 2023 07:09:59) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.8, Copyright (c), by Zend Technologies
    with blackfire v1.86.4~linux-x64-non_zts82, https://blackfire.io, by Blackfire

Subject

The pull request #8116 auto-injects admin in twig so that CRUDController::renderWithExtraParams can be replaced by ::render instead. However, in a form edition or creation, the injected admin uniqId parameter and other parameters linked to the form are null. Thus, when we submit the form without uniqid, the form is not recognized as submitted.

Steps to reproduce

Create a basic admin form, replace renderWithExtraParams by render in CRUDController::editAction and CRUDController::createAction, then try to create or edit an object.

Expected results

Submitting the form once works.

Actual results

Submitting the form once does not work, we have to submit it another time. In fact, one submit out of two does not work because when we are redirected to a form, the uniqId parameter is null. Result of {{ dump(admin) }} in the form template, with render : https://i.imgur.com/ZbeVvcv.png Result of {{ dump(admin) }} in the form template, with renderWithExtraParams : https://i.imgur.com/aNXxHXG.png

VincentLanglet commented 1 year ago

cc @core23

core23 commented 1 year ago

I can reproduce the issue, but I have no idea why this happens, as both methods do exactly the same stuff and do not provide some unique id

https://github.com/sonata-project/SonataAdminBundle/blob/4.x/src/EventListener/AdminEventListener.php#L40-L59 https://github.com/sonata-project/SonataAdminBundle/blob/4.x/src/Controller/CRUDController.php#L1019-L1028

VincentLanglet commented 1 year ago

I can reproduce the issue, but I have no idea why this happens, as both methods do exactly the same stuff and do not provide some unique id

In the listener there is

try {
    $admin = $this->adminFetcher->get($request);
} catch (\InvalidArgumentException) {
    return;
}

Maybe you're in the catch (?)

AntoineRoue commented 1 year ago

No, I tested, the addVariable below this code is called.

AntoineRoue commented 11 months ago

I found what causes the problem. 1- AdminEventListener.php listens to kernel.request event, fetches the admin with AdminFetcher::get() and registers this admin as a twig global. 2- ConfigureCRUDControllerListener.php listens to kernel.controller event and calls CRUDController::configureAdmin(). configureAdmin also calls AdminFetcher::get which retrieves another instance of the admin. The second admin is set as CRUDController::admin property and is used to handle the request.

If the code setting twig globals is moved inside or after CRUDController::configureAdmin(), and uses CRUDController::admin property instead of a new instance of the admin, it works.

VincentLanglet commented 11 months ago

If the code setting twig globals is moved inside or after CRUDController::configureAdmin(), and uses CRUDController::admin property instead of a new instance of the admin, it works.

Do you want to try the PR @AntoineRoue ? (or @core23 ?)

AntoineRoue commented 11 months ago

Should we set these twig globals in CRUDController::configureAdmin() ?

VincentLanglet commented 11 months ago

Should we set these twig globals in CRUDController::configureAdmin() ?

It seems fine to me if it does the job. (Is it to you @core23 ?)

Do you know if

return $this->render($template, [
    'base_template' => 'foo',
]);

will allows to override the twig global ? (which would be great to allow the user to easily override our default value)

AntoineRoue commented 11 months ago

Yes, your example would override the twig global.