1
votes

I try to override layout template in Sonata Admin but depends of logged user. If logged user belong to group customers has some ROLE - show other layout.

I want change -

layout" => "@SonataAdmin/standard_layout.html.twig" 

Where is best place to do it ?

I found that i can do this in admin class - override getTemplate.

But is possible to do this is some listener and switch globaly without edit admin classes ?

UPDATE 1

i create class

class SonataTemplateRegistry implements MutableTemplateRegistryInterface
{

    /**
     * @var string[]
     */
    private $templates = [];

    /**
     * @param string[] $templates
     * @param ContactService $contactService
     */
    public function __construct(array $templates = [], ContactService $contactService)
    {

        $templates['layout']= '@SonataAdmin/layout1.html.twig';
//        $templates['layout']= '@SonataAdmin/standard_layout.html.twig';

//        echo '<pre>'; var_dump($templates); die();

        $this->templates = $templates;

    }

register it

 sonata.admin.global_template_registry:
        class: App\Service\SonataTemplateRegistry
        public: true
        arguments: ['%sonata.admin.configuration.templates%', '@mea.contact']

class is fired - die() show templates but main template is not changed when i change here.

Update 2

in admin class when i get layout template i get correct @SonataAdmin/layout1.html.twig

protected function configureListFields(ListMapper $listMapper)
    {

        var_dump($this->configurationPool->getTemplate('layout'));

but it is not loaded, still see @SonataAdmin/standard_layout.html.twig

UPDATE 3

I found a strange behavior - main page sonata admin - switching template works but already under the pages use the default template

UPDATE 4 I found something interesting , each admin panel has sub service like here :

php bin/console debug:container |grep app.admin.social
  app.admin.social.accounts                                                                     App\SocialManager\Admin\SocialAccountAdmin                                                      
  app.admin.social.accounts.template_registry                                                   Sonata\AdminBundle\Templating\TemplateRegistry                                                  
  app.admin.social.order                                                                        App\SocialManager\Admin\SocialManagementOrderAdmin                                              
  app.admin.social.order.template_registry                                                      Sonata\AdminBundle\Templating\TemplateRegistry    

i override parameters :

parameters:
    sonata.admin.global_template_registry: App\Service\SonataTemplateRegistry

and service

sonata.admin.global_template_registry:
    class: App\Service\SonataTemplateRegistry
    public: true
    arguments: ['%sonata.admin.configuration.templates%', '@mea.contact']

so why sonata still use Sonata\AdminBundle\Templating\TemplateRegistry

protected function configureListFields(ListMapper $listMapper)
    {


$this->getTemplateRegistry()

give Sonata\AdminBundle\Templating\TemplateRegistry

2
What do you mean with “but depends of logged user”? Can you give an example of what you’re trying to do?Lumen
If logged user belong to group customers has some ROLE - show other layoutDeveloper

2 Answers

0
votes

You can use workaround by service tags. First create your own Template registry and implement MutableTemplateRegistryInterface. Then create compiler pass.

<?php

namespace App\DependencyInjection\Compiler;

use App\Registry\TemplateRegistry;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Class SonataAdminTemplateRegistryPass
 * @package App\DependencyInjection\Compiler
 */
class SonataAdminTemplateRegistryPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        foreach ($container->findTaggedServiceIds('sonata.admin.template_registry') as $id => $tags)
        {
            //because @see src/vendor/sonata-project/admin-bundle/src/DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php:405
            $adminServiceId = str_replace(".template_registry", "", $id);
            $def            = $container->getDefinition($adminServiceId);
            $def->removeMethodCall('setTemplateRegistry');
            $def->addMethodCall('setTemplateRegistry', [new Reference(TemplateRegistry::class)]);
        }
    }

}

then add compiler pass to src/Kernel.php like this

protected function build(ContainerBuilder $container)
{
    $container->addCompilerPass(new SonataAdminTemplateRegistryPass());
}

And you will get always override TemplateRegistry in any admin class. So you can implement your own logic in your own TemplateRegistry :)

0
votes

You can do this using single Twig template:

{# layout.html.twig #}
{# mutatis mutandis #}

{% extends app.user ?
    ('ROLE_ADMIN' in app.user.role ?
        'admin_layout.html.twig' :
        'customer_layout.html.twig'
    ) :
    'fallback.html.twig'
%}