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

I can't override form block when admin classes are registered in new way in Symfony 4 #5528

Closed mleko64 closed 4 years ago

mleko64 commented 5 years ago

Environment

Sonata packages

sonata-project/admin-bundle              3.x-dev af8723a dev-master 570a097 The missing Symfony Admin Generator
sonata-project/block-bundle              3.15.0          3.15.0             Symfony SonataBlockBundle
sonata-project/cache                     2.0.1           2.0.1              Cache library
sonata-project/core-bundle               3.16.2          3.16.2             Symfony SonataCoreBundle
sonata-project/datagrid-bundle           2.5.0           3.0.0              Symfony SonataDatagridBundle
sonata-project/doctrine-extensions       1.2.0           1.2.0              Doctrine2 behavioral extensions
sonata-project/doctrine-orm-admin-bundle 3.x-dev 80f4c54 dev-master e02a399 Symfony Sonata / Integrate Doctrine ORM into the SonataAdminBundle
sonata-project/exporter                  2.0.1           2.0.1              Lightweight Exporter library

Symfony packages

symfony/apache-pack          v1.0.1             v1.0.1             A pack for Apache support in Symfony
symfony/asset                v4.2.7             v4.2.7             Symfony Asset Component
symfony/browser-kit          v4.2.7             v4.2.7             Symfony BrowserKit Component
symfony/cache                v4.2.7             v4.2.7             Symfony Cache component with PSR-6, PSR-16, and tags
symfony/config               v4.2.7             v4.2.7             Symfony Config Component
symfony/console              v4.2.7             v4.2.7             Symfony Console Component
symfony/contracts            v1.0.2             v1.0.2             A set of abstractions extracted out of the Symfony components
symfony/css-selector         v4.2.7             v4.2.7             Symfony CssSelector Component
symfony/debug                v4.2.7             v4.2.7             Symfony Debug Component
symfony/debug-bundle         v4.2.7             v4.2.7             Symfony DebugBundle
symfony/debug-pack           v1.0.7             v1.0.7             A debug pack for Symfony projects
symfony/dependency-injection v4.2.7             v4.2.7             Symfony DependencyInjection Component
symfony/doctrine-bridge      v4.2.7             v4.2.7             Symfony Doctrine Bridge
symfony/dom-crawler          v4.2.7             v4.2.7             Symfony DomCrawler Component
symfony/dotenv               v4.2.7             v4.2.7             Registers environment variables from a .env file
symfony/event-dispatcher     v4.2.7             v4.2.7             Symfony EventDispatcher Component
symfony/expression-language  v4.2.7             v4.2.7             Symfony ExpressionLanguage Component
symfony/filesystem           v4.2.7             v4.2.7             Symfony Filesystem Component
symfony/finder               v4.2.7             v4.2.7             Symfony Finder Component
symfony/flex                 v1.2.3             v1.2.3             Composer plugin for Symfony
symfony/form                 v4.2.7             v4.2.7             Symfony Form Component
symfony/framework-bundle     v4.2.7             v4.2.7             Symfony FrameworkBundle
symfony/http-foundation      v4.2.7             v4.2.7             Symfony HttpFoundation Component
symfony/http-kernel          v4.2.7             v4.2.7             Symfony HttpKernel Component
symfony/inflector            v4.2.7             v4.2.7             Symfony Inflector Component
symfony/intl                 v4.2.7             v4.2.7             A PHP replacement layer for the C intl extension that includes additional data from the ICU library.
symfony/maker-bundle         v1.11.5            v1.11.5            Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you c...
symfony/monolog-bridge       v4.2.7             v4.2.7             Symfony Monolog Bridge
symfony/monolog-bundle       v3.3.1             v3.3.1             Symfony MonologBundle
symfony/options-resolver     v4.2.7             v4.2.7             Symfony OptionsResolver Component
symfony/orm-pack             v1.0.6             v1.0.6             A pack for the Doctrine ORM
symfony/phpunit-bridge       v4.2.7             v4.2.7             Symfony PHPUnit Bridge
symfony/polyfill-ctype       v1.11.0            v1.11.0            Symfony polyfill for ctype functions
symfony/polyfill-intl-icu    v1.11.0            v1.11.0            Symfony polyfill for intl's ICU-related data and classes
symfony/polyfill-intl-idn    v1.11.0            v1.11.0            Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions
symfony/polyfill-mbstring    v1.11.0            v1.11.0            Symfony polyfill for the Mbstring extension
symfony/polyfill-php72       v1.11.0            v1.11.0            Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
symfony/process              v4.2.7             v4.2.7             Symfony Process Component
symfony/profiler-pack        v1.0.4             v1.0.4             A pack for the Symfony web profiler
symfony/property-access      v4.2.7             v4.2.7             Symfony PropertyAccess Component
symfony/property-info        v4.2.7             v4.2.7             Symfony Property Info Component
symfony/routing              v4.2.7             v4.2.7             Symfony Routing Component
symfony/security-acl         v3.0.2             v3.0.2             Symfony Security Component - ACL (Access Control List)
symfony/security-bundle      v4.2.7             v4.2.7             Symfony SecurityBundle
symfony/security-core        v4.2.7             v4.2.7             Symfony Security Component - Core Library
symfony/security-csrf        v4.2.7             v4.2.7             Symfony Security Component - CSRF Library
symfony/security-guard       v4.2.7             v4.2.7             Symfony Security Component - Guard
symfony/security-http        v4.2.7             v4.2.7             Symfony Security Component - HTTP Integration
symfony/serializer           v4.2.7             v4.2.7             Symfony Serializer Component
symfony/serializer-pack      v1.0.2             v1.0.2             A pack for the Symfony serializer
symfony/stopwatch            v4.2.7             v4.2.7             Symfony Stopwatch Component
symfony/swiftmailer-bundle   v3.2.5             v3.2.5             Symfony SwiftmailerBundle
symfony/templating           v4.2.7             v4.2.7             Symfony Templating Component
symfony/translation          v4.2.7             v4.2.7             Symfony Translation Component
symfony/twig-bridge          v4.2.7             v4.2.7             Symfony Twig Bridge
symfony/twig-bundle          v4.2.7             v4.2.7             Symfony TwigBundle
symfony/validator            v4.2.7             v4.2.7             Symfony Validator Component
symfony/var-dumper           v4.2.7             v4.2.7             Symfony mechanism for exploring and dumping PHP variables
symfony/var-exporter         v4.2.7             v4.2.7             A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code
symfony/web-link             v4.2.7             v4.2.7             Symfony WebLink Component
symfony/web-profiler-bundle  v4.2.7             v4.2.7             Symfony WebProfilerBundle
symfony/webpack-encore-pack  v1.0.3             v1.0.3             A pack for Symfony Encore
symfony/yaml                 v4.2.7             v4.2.7             Symfony Yaml Component

PHP version

PHP 7.3.3 (cli) (built: Mar  6 2019 18:03:57) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.3, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.3, Copyright (c) 1999-2018, by Zend Technologies

Subject

Sometimes, I need override form block fields (I believe that not only me) generates by SonataAdmin (to handle some cases). When I'm using SonataAdmin with Symfony 4, all block prefixes looks like this (example):

[
  "form"
  "text"
  "App\Admin\User\User_text"
  "App\Admin\User\User_firstName_text"
  "App\Admin\User\User_firstName_text__s851c23b5dd_firstName"
]

I can't override for example App\Admin\User\User_firstName_text block because Twig not allow me to create in Twig template a block with name which contains backslash characters.

{# This block name is invalid - produce a Twig error :( #}
{% block App\Admin\User\User_firstName_text %}
{% endblock %}

I know, that this name (first part of block name) is coming from Admin code (in Symfony 4 all Admin classes are registered in new way):

services:
    App\Admin\User\User:
        arguments: [~, App\Entity\User\User, ~]
        tags:
            - { name: sonata.admin, manager_type: orm, group: Users, label: Users }
        calls:
            - [setTranslationDomain, ["User"]]

I found where names for form block prefixes are prepared: sonata-project/admin-bundle/src/Form/Extension/Field/Type/FormTypeFieldExtension.php

In line 90 and 123 is prepared $basename variable from Admin code (first part of block prefix name):

$baseName = str_replace('.', '_', $view->parent->vars['sonata_admin_code']);

Only dot characters are replaced to underscores. In my opinion, backslash characters should be replaced too.

Steps to reproduce

Create new Admin class and register is as service in new way:

services:
    App\Admin\User\User:
        arguments: [~, App\Entity\User\User, ~]
        tags:
            - { name: sonata.admin, manager_type: orm, group: Users, label: Users, label_catalogue: User, show_mosaic_button: false }
        calls:
            - [setTranslationDomain, ["User"]]

Expected results

All names for form block prefixes should by valid to override in Twig template (replace backslash characters to underscore characters):

[
  "form"
  "text"
  "App_Admin_User_User_text"
  "App_Admin_User_User_firstName_text"
  "App_Admin_User_User_firstName_text__s851c23b5dd_firstName"
]

Actual results

Cannot override form blocks, because block names contains backslash characters. These names are not valid for Twig.

[
  "form"
  "text"
  "App\Admin\User\User_text"
  "App\Admin\User\User_firstName_text"
  "App\Admin\User\User_firstName_text__s851c23b5dd_firstName"
]
ricky6982 commented 5 years ago

Something like this problem happens to me when I want to replace a template from the calls section within the service. I can only call the function if I put as an @required annotation.

stale[bot] commented 4 years ago

Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

mikemix commented 1 year ago

This thread has been stale & closed, but is relatively high in Google results for this issue. I'd like to post a workaround for people (like me) affected by this – don't rely on auto-loaded block names.

Example - my form field before:

            ->add('someFieldName', ModelAutocompleteType::class, [
                'class' => SomeObject::class,
                'multiple' => true,
                'by_reference' => false,
                'required' => false,
                'property' => 'name',
                'placeholder' => '',
                'btn_add' => false,
                'to_string_callback' => '…',
            ])

Twig html block to override the label that was working fine before:

{% block admin_someAdminName_someFieldName_sonata_type_model_autocomplete_label %}
    here I override the label
{% endblock %}

To work around the issue, give a unique block_prefix to the form field. The form field after:

            ->add('someFieldName', ModelAutocompleteType::class, [
                'class' => SomeObject::class,
                'multiple' => true,
                'by_reference' => false,
                'required' => false,
                'property' => 'name',
                'placeholder' => '',
                'btn_add' => false,
                'to_string_callback' => '…',
                'block_prefix' => 'some_admin_some_field_name',
            ])

Now you can reference this name directly in Twig. Twig after:

{% block some_admin_some_field_name_label %}
    here I override the label
{% endblock %}

Done! Hope it helps.


There are 4 overrides available in total (the block prefix + underscore + override name):