From 7827f1d7ddb55471e862405afd8dd4476dd295d3 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Tue, 13 Aug 2013 06:01:50 +0100
Subject: [PATCH] Issue #2050227 by damiankloip, pwolanin: Add local action
 plugin deriver to use YAML discovery for static definitions.

---
 .../Derivative/StaticLocalActionDeriver.php   | 115 ++++++++++++++++++
 .../Menu/LocalAction/StaticLocalAction.php    |  21 ++++
 .../system/Tests/Menu/LocalActionTest.php     |   1 +
 .../menu_test/menu_test.local_actions.yml     |   5 +
 .../Menu/LocalAction/AddViewLocalAction.php   |  24 ----
 .../views_ui/views_ui.local_actions.yml       |   5 +
 6 files changed, 147 insertions(+), 24 deletions(-)
 create mode 100644 core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php
 create mode 100644 core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php
 create mode 100644 core/modules/system/tests/modules/menu_test/menu_test.local_actions.yml
 delete mode 100644 core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/LocalAction/AddViewLocalAction.php
 create mode 100644 core/modules/views_ui/views_ui.local_actions.yml

diff --git a/core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php b/core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php
new file mode 100644
index 000000000000..166089d92d95
--- /dev/null
+++ b/core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Menu\Plugin\Derivative\StaticLocalActionDeriver.
+ */
+
+namespace Drupal\Core\Menu\Plugin\Derivative;
+
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface;
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Core\StringTranslation\TranslationManager;
+use Drupal\Component\Utility\String;
+use Drupal\Component\Discovery\YamlDiscovery;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides plugin derivatives for local actions provided in YAML files.
+ */
+class StaticLocalActionDeriver implements ContainerDerivativeInterface {
+
+  /**
+   * List of derivative definitions.
+   *
+   * @var array
+   */
+  protected $derivatives = array();
+
+  /**
+   * The base plugin ID.
+   *
+   * @var string
+   */
+  protected $basePluginId;
+
+  /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * The translation manager.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationManager
+   */
+  protected $translationManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $base_plugin_id,
+      $container->get('module_handler'),
+      $container->get('string_translation')
+    );
+  }
+
+  /**
+   * Constructs a StaticLocalActionDeriver object.
+   *
+   * @param string $base_plugin_id
+   *   The base plugin ID.
+   * @param\Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   * @param \Drupal\Core\StringTranslation\TranslationManager translation_manager
+   *   The translation manager.
+   */
+  public function __construct($base_plugin_id, ModuleHandlerInterface $module_handler, TranslationManager $translation_manager) {
+    $this->basePluginId = $base_plugin_id;
+    $this->moduleHandler = $module_handler;
+    $this->translationManager = $translation_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinition($derivative_id, array $base_plugin_definition) {
+    if (!empty($this->derivatives) && !empty($this->derivatives[$derivative_id])) {
+      return $this->derivatives[$derivative_id];
+    }
+    $this->getDerivativeDefinitions($base_plugin_definition);
+    return $this->derivatives[$derivative_id];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions(array $base_plugin_definition) {
+    $yaml_discovery = new YamlDiscovery('local_actions', $this->moduleHandler->getModuleDirectories());
+    $required_keys = array('title' => 1, 'route_name' => 1, 'appears_on' => 1);
+
+    foreach ($yaml_discovery->findAll() as $module => $local_actions) {
+      if (!empty($local_actions)) {
+        foreach ($local_actions as $name => $info) {
+          if ($missing_keys = array_diff_key($required_keys, array_intersect_key($info, $required_keys))) {
+            throw new PluginException(String::format('Static local action @name is missing @keys', array('@name' => $name, '@keys' => implode(', ', array_keys($missing_keys)))));
+          }
+
+          $info += array('provider' => $module);
+          // Make sure 'appears_on' is an array.
+          $info['appears_on'] = (array) $info['appears_on'];
+          $info['title'] = $this->translationManager->translate($info['title']);
+          $this->derivatives[$name] = $info + $base_plugin_definition;
+        }
+      }
+    }
+
+    return $this->derivatives;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php b/core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php
new file mode 100644
index 000000000000..b0e0e9d083b8
--- /dev/null
+++ b/core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Annotation\StaticLocalAction.
+ */
+
+namespace Drupal\Core\Menu\Plugin\Menu\LocalAction;
+
+use Drupal\Core\Annotation\Menu\LocalAction;
+use Drupal\Core\Menu\LocalActionBase;
+
+/**
+ * @LocalAction(
+ *   id = "local_action_static",
+ *   derivative = "Drupal\Core\Menu\Plugin\Derivative\StaticLocalActionDeriver"
+ * )
+ */
+class StaticLocalAction extends LocalActionBase {
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/LocalActionTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/LocalActionTest.php
index 81fe57dab6e2..014d58f5561f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/LocalActionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/LocalActionTest.php
@@ -40,6 +40,7 @@ public function testLocalAction() {
       'menu-test-local-action/dynamic-title' => 'My dynamic-title action',
       'menu-test-local-action/hook_menu' => 'My hook_menu action',
       'menu-test-local-action/routing' => 'My routing action',
+      'menu-test-local-action/routing' => 'My YAML discovery action',
     ));
   }
 
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.local_actions.yml b/core/modules/system/tests/modules/menu_test/menu_test.local_actions.yml
new file mode 100644
index 000000000000..04e9b0aa3277
--- /dev/null
+++ b/core/modules/system/tests/modules/menu_test/menu_test.local_actions.yml
@@ -0,0 +1,5 @@
+menu_test_local_action4:
+ route_name: menu_test_local_action3
+ title: 'My YAML discovery action'
+ appears_on:
+   - menu_test_local_action1
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/LocalAction/AddViewLocalAction.php b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/LocalAction/AddViewLocalAction.php
deleted file mode 100644
index 406107f4d77b..000000000000
--- a/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/LocalAction/AddViewLocalAction.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\views_ui\Plugin\Menu\AddViewLocalAction.
- */
-
-namespace Drupal\views_ui\Plugin\Menu\LocalAction;
-
-use Drupal\Core\Annotation\Translation;
-use Drupal\Core\Menu\LocalActionBase;
-use Drupal\Core\Annotation\Menu\LocalAction;
-
-/**
- * @LocalAction(
- *   id = "views_add_local_action",
- *   route_name = "views_ui.add",
- *   title = @Translation("Add new view"),
- *   appears_on = {"views_ui.list"}
- * )
- */
-class AddViewLocalAction extends LocalActionBase {
-
-}
diff --git a/core/modules/views_ui/views_ui.local_actions.yml b/core/modules/views_ui/views_ui.local_actions.yml
new file mode 100644
index 000000000000..6a0ded0d267c
--- /dev/null
+++ b/core/modules/views_ui/views_ui.local_actions.yml
@@ -0,0 +1,5 @@
+views_add_local_action:
+  route_name: views_ui.add
+  title: 'Add new view'
+  appears_on:
+    - views_ui.list
-- 
GitLab