瀏覽代碼

Support abstract admin service inheritance (#4253)

François-Xavier de Guillebon 8 年之前
父節點
當前提交
17ae021f48

+ 35 - 12
DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php

@@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
 use Symfony\Component\DependencyInjection\Reference;
 
 /**
@@ -50,21 +51,20 @@ class AddDependencyCallsCompilerPass implements CompilerPassInterface
         foreach ($container->findTaggedServiceIds('sonata.admin') as $id => $tags) {
             foreach ($tags as $attributes) {
                 $definition = $container->getDefinition($id);
-
-                $arguments = $definition->getArguments();
-
-                if (strlen($arguments[0]) == 0) {
-                    $definition->replaceArgument(0, $id);
-                }
-
-                if (strlen($arguments[2]) == 0) {
-                    $definition->replaceArgument(2, 'SonataAdminBundle:CRUD');
-                }
-
+                $parentDefinition = $definition instanceof DefinitionDecorator ?
+                    $container->getDefinition($definition->getParent()) :
+                    null;
+
+                $this->replaceDefaultArguments(array(
+                    0 => $id,
+                    2 => 'SonataAdminBundle:CRUD',
+                ), $definition, $parentDefinition);
                 $this->applyConfigurationFromAttribute($definition, $attributes);
                 $this->applyDefaults($container, $id, $attributes);
 
-                $arguments = $definition->getArguments();
+                $arguments = $parentDefinition ?
+                    array_merge($parentDefinition->getArguments(), $definition->getArguments()) :
+                    $definition->getArguments();
 
                 $admins[] = $id;
 
@@ -408,4 +408,27 @@ class AddDependencyCallsCompilerPass implements CompilerPassInterface
 
         $definition->addMethodCall('setTemplates', array($definedTemplates));
     }
+
+    /**
+     * Replace the empty arguments required by the Admin service definition.
+     *
+     * @param array           $defaultArguments
+     * @param Definition      $definition
+     * @param Definition|null $parentDefinition
+     */
+    private function replaceDefaultArguments(array $defaultArguments, Definition $definition, Definition $parentDefinition = null)
+    {
+        $arguments = $definition->getArguments();
+        $parentArguments = $parentDefinition ? $parentDefinition->getArguments() : array();
+
+        foreach ($defaultArguments as $index => $value) {
+            $declaredInParent = $parentDefinition && array_key_exists($index, $parentArguments);
+
+            if (strlen($declaredInParent ? $parentArguments[$index] : $arguments[$index]) == 0) {
+                $arguments[$declaredInParent ? sprintf('index_%s', $index) : $index] = $value;
+            }
+        }
+
+        $definition->setArguments($arguments);
+    }
 }

+ 58 - 0
Tests/DependencyInjection/Compiler/AddDependencyCallsCompilerPassTest.php

@@ -14,6 +14,7 @@ namespace Sonata\AdminBundle\Tests\DependencyInjection;
 use Sonata\AdminBundle\DependencyInjection\Compiler\AddDependencyCallsCompilerPass;
 use Sonata\AdminBundle\DependencyInjection\SonataAdminExtension;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
 
 /**
  * @author     Tiago Garcia
@@ -471,6 +472,63 @@ class AddDependencyCallsCompilerPassTest extends \PHPUnit_Framework_TestCase
         }
     }
 
+    public function testProcessAbstractAdminServiceInServiceDefinition()
+    {
+        $container = $this->getContainer();
+
+        $config = $this->config;
+        $config['dashboard']['groups'] = array();
+
+        $this->extension->load(array($config), $container);
+
+        $compilerPass = new AddDependencyCallsCompilerPass();
+        $container
+            ->register('sonata_abstract_post_admin')
+            ->setArguments(array('', 'Sonata\AdminBundle\Tests\DependencyInjection\Post', ''))
+            ->setAbstract(true);
+
+        $adminDefinition = new DefinitionDecorator('sonata_abstract_post_admin');
+        $adminDefinition
+            ->setClass('Sonata\AdminBundle\Tests\DependencyInjection\MockAbstractServiceAdmin')
+            ->setArguments(array(0 => 'extra_argument_1'))
+            ->addTag('sonata.admin', array('group' => 'sonata_post_one_group', 'manager_type' => 'orm'));
+
+        $adminTwoDefinition = new DefinitionDecorator('sonata_abstract_post_admin');
+        $adminTwoDefinition
+            ->setClass('Sonata\AdminBundle\Tests\DependencyInjection\MockAbstractServiceAdmin')
+            ->setArguments(array(0 => 'extra_argument_2', 'index_0' => 'should_not_override'))
+            ->addTag('sonata.admin', array('group' => 'sonata_post_two_group', 'manager_type' => 'orm'));
+
+        $container->addDefinitions(array(
+            'sonata_post_one_admin' => $adminDefinition,
+            'sonata_post_two_admin' => $adminTwoDefinition,
+        ));
+
+        $compilerPass->process($container);
+        $container->compile();
+
+        $pool = $container->get('sonata.admin.pool');
+        $adminServiceIds = $pool->getAdminServiceIds();
+
+        $this->assertContains('sonata_post_one_admin', $adminServiceIds);
+        $this->assertContains('sonata_post_two_admin', $adminServiceIds);
+
+        $this->assertTrue($container->hasDefinition('sonata_post_one_admin'));
+        $this->assertTrue($container->hasDefinition('sonata_post_two_admin'));
+
+        $definition = $container->getDefinition('sonata_post_one_admin');
+        $this->assertSame('sonata_post_one_admin', $definition->getArgument(0));
+        $this->assertSame('Sonata\AdminBundle\Tests\DependencyInjection\Post', $definition->getArgument(1));
+        $this->assertSame('SonataAdminBundle:CRUD', $definition->getArgument(2));
+        $this->assertSame('extra_argument_1', $definition->getArgument(3));
+
+        $definition = $container->getDefinition('sonata_post_two_admin');
+        $this->assertSame('sonata_post_two_admin', $definition->getArgument(0));
+        $this->assertSame('Sonata\AdminBundle\Tests\DependencyInjection\Post', $definition->getArgument(1));
+        $this->assertSame('SonataAdminBundle:CRUD', $definition->getArgument(2));
+        $this->assertSame('extra_argument_2', $definition->getArgument(3));
+    }
+
     /**
      * @return array
      */

+ 12 - 0
Tests/DependencyInjection/Compiler/ExtensionCompilerPassTest.php

@@ -419,6 +419,18 @@ class MockAdmin extends AbstractAdmin
 {
 }
 
+class MockAbstractServiceAdmin extends AbstractAdmin
+{
+    private $extraArgument;
+
+    public function __construct($code, $class, $baseControllerName, $extraArgument)
+    {
+        $this->extraArgument = $extraArgument;
+
+        parent::__construct($code, $class, $baseControllerName);
+    }
+}
+
 class Post
 {
 }