Переглянути джерело

#4036 Add priority support for admin extensions (#4298)

Sam Van der Borght 8 роки тому
батько
коміт
aaf5cb1a65

+ 42 - 9
DependencyInjection/Compiler/ExtensionCompilerPass.php

@@ -27,6 +27,7 @@ class ExtensionCompilerPass implements CompilerPassInterface
     public function process(ContainerBuilder $container)
     {
         $universalExtensions = array();
+        $targets = array();
 
         foreach ($container->findTaggedServiceIds('sonata.admin.extension') as $id => $tags) {
             foreach ($tags as $attributes) {
@@ -37,17 +38,14 @@ class ExtensionCompilerPass implements CompilerPassInterface
                 }
 
                 if (isset($attributes['global']) && $attributes['global']) {
-                    $universalExtensions[] = $id;
+                    $universalExtensions[$id] = $attributes;
                 }
 
                 if (!$target || !$container->hasDefinition($target)) {
                     continue;
                 }
 
-                $container
-                    ->getDefinition($target)
-                    ->addMethodCall('addExtension', array(new Reference($id)))
-                ;
+                $this->addExtension($targets, $target, $id, $attributes);
             }
         }
 
@@ -57,17 +55,34 @@ class ExtensionCompilerPass implements CompilerPassInterface
         foreach ($container->findTaggedServiceIds('sonata.admin') as $id => $attributes) {
             $admin = $container->getDefinition($id);
 
-            foreach ($universalExtensions as $extension) {
-                $admin->addMethodCall('addExtension', array(new Reference($extension)));
+            if (!isset($targets[$id])) {
+                $targets[$id] = new \SplPriorityQueue();
+            }
+
+            foreach ($universalExtensions as $extension => $extensionAttributes) {
+                $this->addExtension($targets, $id, $extension, $extensionAttributes);
             }
 
             $extensions = $this->getExtensionsForAdmin($id, $admin, $container, $extensionMap);
 
             foreach ($extensions as $extension) {
                 if (!$container->has($extension)) {
-                    throw new \InvalidArgumentException(sprintf('Unable to find extension service for id %s', $extension));
+                    throw new \InvalidArgumentException(
+                        sprintf('Unable to find extension service for id %s', $extension)
+                    );
                 }
-                $admin->addMethodCall('addExtension', array(new Reference($extension)));
+
+                $this->addExtension($targets, $id, $extension, $attributes);
+            }
+        }
+
+        foreach ($targets as $target => $extensions) {
+            $extensions = iterator_to_array($extensions);
+            krsort($extensions);
+            $admin = $container->getDefinition($target);
+
+            foreach (array_values($extensions) as $extension) {
+                $admin->addMethodCall('addExtension', array($extension));
             }
         }
     }
@@ -197,4 +212,22 @@ class ExtensionCompilerPass implements CompilerPassInterface
 
         return $this->hasTrait($parentClass, $traitName);
     }
+
+    /**
+     * Add extension configuration to the targets array.
+     *
+     * @param array  $targets
+     * @param string $target
+     * @param string $extension
+     * @param array  $attributes
+     */
+    private function addExtension(array &$targets, $target, $extension, $attributes)
+    {
+        if (!isset($targets[$target])) {
+            $targets[$target] = new \SplPriorityQueue();
+        }
+
+        $priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
+        $targets[$target]->insert(new Reference($extension), $priority);
+    }
 }

+ 7 - 0
Resources/doc/reference/extensions.rst

@@ -35,6 +35,8 @@ You can include this information in the service definition of your extension.
 Add the tag *sonata.admin.extension* and use the *target* attribute to point to
 the admin you want to modify. Please note you can specify as many tags you want.
 Set the *global* attribute to *true* and the extension will be added to all admins.
+The *priority* attribute is *0* by default and can be a positive or negative integer.
+The higher the priority, the earlier it's executed.
 
 .. configuration-block::
 
@@ -52,6 +54,11 @@ Set the *global* attribute to *true* and the extension will be added to all admi
                 tags:
                     - { name: sonata.admin.extension, global: true }
 
+            app.important.extension:
+                class: AppBundle\Admin\Extension\ImportantAdminExtension
+                tags:
+                    - { name: sonata.admin.extension, priority: 5 }
+
 The second option is to add it to your config.yml file.
 
 .. configuration-block::

+ 4 - 4
Tests/DependencyInjection/Compiler/ExtensionCompilerPassTest.php

@@ -251,8 +251,8 @@ class ExtensionCompilerPassTest extends PHPUnit_Framework_TestCase
         $this->assertCount(4, $extensions);
 
         $this->assertInstanceOf(get_class($this->securityExtension), $extensions[0]);
-        $this->assertInstanceOf(get_class($this->publishExtension), $extensions[2]);
-        $this->assertInstanceOf(get_class($this->historyExtension), $extensions[3]);
+        $this->assertInstanceOf(get_class($this->publishExtension), $extensions[1]);
+        $this->assertInstanceOf(get_class($this->historyExtension), $extensions[2]);
 
         $def = $container->get('sonata_article_admin');
         $extensions = $def->getExtensions();
@@ -260,7 +260,7 @@ class ExtensionCompilerPassTest extends PHPUnit_Framework_TestCase
 
         $this->assertInstanceOf(get_class($this->securityExtension), $extensions[0]);
         $this->assertInstanceOf(get_class($this->publishExtension), $extensions[1]);
-        $this->assertInstanceOf(get_class($this->orderExtension), $extensions[3]);
+        $this->assertInstanceOf(get_class($this->orderExtension), $extensions[2]);
         $this->assertInstanceOf(get_class($this->filterExtension), $extensions[4]);
 
         $def = $container->get('sonata_news_admin');
@@ -268,7 +268,7 @@ class ExtensionCompilerPassTest extends PHPUnit_Framework_TestCase
         $this->assertCount(5, $extensions);
         $this->assertInstanceOf(get_class($this->securityExtension), $extensions[0]);
         $this->assertInstanceOf(get_class($this->orderExtension), $extensions[1]);
-        $this->assertInstanceOf(get_class($this->historyExtension), $extensions[3]);
+        $this->assertInstanceOf(get_class($this->historyExtension), $extensions[2]);
         $this->assertInstanceOf(get_class($this->filterExtension), $extensions[4]);
     }