From 53f6c5a4b1de9d5304059ad0d9644acf54fe7940 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 27 Jul 2015 13:36:15 +0100
Subject: [PATCH] Issue #2512062 by dsnopek, tim.plunkett, Wim Leers:
 VariantInterface extends ConfigurablePluginInterface so
 PageDisplayVariantSelectionEvent should allow passing configuration to the
 Variant (to enable Panels Everywhere)

---
 .../Core/Render/MainContent/HtmlRenderer.php  |  4 +-
 .../PageDisplayVariantSelectionEvent.php      | 32 +++++++++++
 .../DisplayVariant/SimplePageVariant.php      |  1 +
 .../src/Tests/Render/DisplayVariantTest.php   | 37 +++++++++++++
 .../display_variant_test.info.yml             |  6 +++
 .../display_variant_test.services.yml         |  5 ++
 .../TestPageDisplayVariantSubscriber.php      | 38 +++++++++++++
 .../DisplayVariant/TestDisplayVariant.php     | 54 +++++++++++++++++++
 8 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 core/modules/system/src/Tests/Render/DisplayVariantTest.php
 create mode 100644 core/modules/system/tests/modules/display_variant_test/display_variant_test.info.yml
 create mode 100644 core/modules/system/tests/modules/display_variant_test/display_variant_test.services.yml
 create mode 100644 core/modules/system/tests/modules/display_variant_test/src/EventSubscriber/TestPageDisplayVariantSubscriber.php
 create mode 100644 core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php

diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
index b53d1e51e1b7..7e06aabd4556 100644
--- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
+++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
@@ -201,7 +201,9 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte
       if (!$page_display instanceof PageVariantInterface) {
         throw new \LogicException('Cannot render the main content for this page because the provided display variant does not implement PageVariantInterface.');
       }
-      $page_display->setMainContent($main_content);
+      $page_display
+        ->setMainContent($main_content)
+        ->setConfiguration($event->getPluginConfiguration());
 
       // Generate a #type => page render array using the page display variant,
       // the page display will build the content for the various page regions.
diff --git a/core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php b/core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php
index 17771bde00a7..5e2f2257c877 100644
--- a/core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php
+++ b/core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php
@@ -25,6 +25,13 @@ class PageDisplayVariantSelectionEvent extends Event {
    */
   protected $pluginId;
 
+  /**
+   * The configuration for the selected page display variant.
+   *
+   * @var array
+   */
+  protected $pluginConfiguration = [];
+
   /**
    * The current route match.
    *
@@ -50,9 +57,12 @@ public function __construct($plugin_id, RouteMatchInterface $route_match) {
    *
    * @param string $plugin_id
    *   The ID of the page display variant plugin to use.
+   *
+   * @return $this
    */
   public function setPluginId($plugin_id) {
     $this->pluginId = $plugin_id;
+    return $this;
   }
 
   /**
@@ -64,6 +74,28 @@ public function getPluginId() {
     return $this->pluginId;
   }
 
+  /**
+   * Set the configuration for the selected page display variant.
+   *
+   * @param array $configuration
+   *   The configuration for the selected page display variant.
+   *
+   * @return $this
+   */
+  public function setPluginConfiguration(array $configuration) {
+    $this->pluginConfiguration = $configuration;
+    return $this;
+  }
+
+  /**
+   * Get the configuration for the selected page display variant.
+   *
+   * @return array
+   */
+  public function getPluginConfiguration() {
+    return $this->pluginConfiguration;
+  }
+
   /**
    * Gets the current route match.
    *
diff --git a/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php b/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php
index 66f908605c4b..baef3257078a 100644
--- a/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php
+++ b/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php
@@ -32,6 +32,7 @@ class SimplePageVariant extends VariantBase implements PageVariantInterface {
    */
   public function setMainContent(array $main_content) {
     $this->mainContent = $main_content;
+    return $this;
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Render/DisplayVariantTest.php b/core/modules/system/src/Tests/Render/DisplayVariantTest.php
new file mode 100644
index 000000000000..432aacf9290a
--- /dev/null
+++ b/core/modules/system/src/Tests/Render/DisplayVariantTest.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Render\DisplayVariantTest.
+ */
+
+namespace Drupal\system\Tests\Render;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests selecting a display variant.
+ *
+ * @group Render
+ */
+class DisplayVariantTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('display_variant_test');
+
+  /**
+   * Tests selecting the variant and passing configuration.
+   */
+  function testPageDisplayVariantSelectionEvent() {
+    // Tests that our display variant was selected, and that its configuration
+    // was passed correctly. If the configuration wasn't passed, we'd get an
+    // error page here.
+    $this->drupalGet('<front>');
+    $this->assertRaw('A very important, required value.');
+  }
+
+}
diff --git a/core/modules/system/tests/modules/display_variant_test/display_variant_test.info.yml b/core/modules/system/tests/modules/display_variant_test/display_variant_test.info.yml
new file mode 100644
index 000000000000..53e543c3a354
--- /dev/null
+++ b/core/modules/system/tests/modules/display_variant_test/display_variant_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Display variant tests'
+type: module
+description: 'Support module for testing display variants.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/system/tests/modules/display_variant_test/display_variant_test.services.yml b/core/modules/system/tests/modules/display_variant_test/display_variant_test.services.yml
new file mode 100644
index 000000000000..654a0cf7e760
--- /dev/null
+++ b/core/modules/system/tests/modules/display_variant_test/display_variant_test.services.yml
@@ -0,0 +1,5 @@
+services:
+  display_variant_test.page_display_variant_subscriber:
+    class: Drupal\display_variant_test\EventSubscriber\TestPageDisplayVariantSubscriber
+    tags:
+      - { name: 'event_subscriber', priority: 1000 }
diff --git a/core/modules/system/tests/modules/display_variant_test/src/EventSubscriber/TestPageDisplayVariantSubscriber.php b/core/modules/system/tests/modules/display_variant_test/src/EventSubscriber/TestPageDisplayVariantSubscriber.php
new file mode 100644
index 000000000000..b8154c781ead
--- /dev/null
+++ b/core/modules/system/tests/modules/display_variant_test/src/EventSubscriber/TestPageDisplayVariantSubscriber.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\display_variant_test\EventSubscriber\TestPageDisplayVariantSubscriber.
+ */
+
+namespace Drupal\display_variant_test\EventSubscriber;
+
+use Drupal\Core\Render\PageDisplayVariantSelectionEvent;
+use Drupal\Core\Render\RenderEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Selects the test page display variant.
+ */
+class TestPageDisplayVariantSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Selects the page display variant.
+   *
+   * @param \Drupal\Core\Render\PageDisplayVariantSelectionEvent $event
+   *   The event to process.
+   */
+  public function onSelectPageDisplayVariant(PageDisplayVariantSelectionEvent $event) {
+    $event->setPluginId('display_variant_test');
+    $event->setPluginConfiguration(['required_configuration' => 'A very important, required value.']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  static function getSubscribedEvents() {
+    $events[RenderEvents::SELECT_PAGE_DISPLAY_VARIANT][] = array('onSelectPageDisplayVariant');
+    return $events;
+  }
+
+}
diff --git a/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php b/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php
new file mode 100644
index 000000000000..20572720543b
--- /dev/null
+++ b/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\display_variant_test\Plugin\DisplayVariant\TestDisplayVariant.
+ */
+
+namespace Drupal\display_variant_test\Plugin\DisplayVariant;
+
+use Drupal\Core\Display\VariantBase;
+use Drupal\Core\Display\PageVariantInterface;
+
+/**
+ * Provides a display variant that requires configuration.
+ *
+ * @DisplayVariant(
+ *   id = "display_variant_test",
+ *   admin_label = @Translation("Test display variant")
+ * )
+ */
+class TestDisplayVariant extends VariantBase implements PageVariantInterface {
+
+  /**
+   * The render array representing the main page content.
+   *
+   * @var array
+   */
+  protected $mainContent = [];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setMainContent(array $main_content) {
+    $this->mainContent = $main_content;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+    $config = $this->getConfiguration();
+    if (empty($config['required_configuration'])) {
+      throw new \Exception('Required configuration is missing!');
+    }
+
+    $build = [];
+    $build['content']['default'] = [
+      '#markup' => $config['required_configuration'],
+    ];
+    return $build;
+  }
+
+}
-- 
GitLab