From 0f8684f79bba742c767073ecd96473770ae42a19 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Thu, 10 Dec 2015 15:31:33 +0000
Subject: [PATCH] Issue #2619332 by joelpittet, jmarkel, Wim Leers, Berdir,
 chintan.vyas, netsensei: Color scheme config changes aren't reflected in
 cached pages

---
 core/modules/color/color.module               | 12 ++--
 core/modules/color/color.services.yml         |  6 ++
 .../ColorConfigCacheInvalidator.php           | 61 +++++++++++++++++++
 core/modules/color/src/Tests/ColorTest.php    | 41 ++++++++++++-
 .../Tests/PageCacheTagsIntegrationTest.php    |  2 +
 5 files changed, 115 insertions(+), 7 deletions(-)
 create mode 100644 core/modules/color/color.services.yml
 create mode 100644 core/modules/color/src/EventSubscriber/ColorConfigCacheInvalidator.php

diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index dd48e4ac0eab..15619ff4c023 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -9,7 +9,7 @@
 use Drupal\Component\Utility\Bytes;
 use Drupal\Component\Utility\Environment;
 use Drupal\Core\Block\BlockPluginInterface;
-use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Render\Element\Textfield;
@@ -118,9 +118,13 @@ function color_block_view_system_branding_block_alter(array &$build, BlockPlugin
  */
 function color_block_view_pre_render(array $build) {
   $theme_key = \Drupal::theme()->getActiveTheme()->getName();
+  $config = \Drupal::config('color.theme.' . $theme_key);
+  CacheableMetadata::createFromRenderArray($build)
+    ->addCacheableDependency($config)
+    ->applyTo($build);
 
   // Override logo.
-  $logo = \Drupal::config('color.theme.' . $theme_key)->get('logo');
+  $logo = $config->get('logo');
   if ($logo && $build['content']['site_logo'] && preg_match('!' . $theme_key . '/logo.svg$!', $build['content']['site_logo']['#uri'])) {
     $build['content']['site_logo']['#uri'] = file_create_url($logo);
   }
@@ -193,7 +197,6 @@ function color_get_palette($theme, $default = FALSE) {
  * @see color_scheme_form_submit()
  */
 function color_scheme_form($complete_form, FormStateInterface $form_state, $theme) {
-  $base = drupal_get_path('module', 'color');
   $info = color_get_info($theme);
 
   $info['schemes'][''] = array('title' => t('Custom'), 'colors' => array());
@@ -500,9 +503,6 @@ function color_scheme_form_submit($form, FormStateInterface $form_state) {
     ->set('stylesheets', $css)
     ->set('files', $paths['files'])
     ->save();
-
-  // Clear the library cache.
-  Cache::invalidateTags(['library_info']);
 }
 
 /**
diff --git a/core/modules/color/color.services.yml b/core/modules/color/color.services.yml
new file mode 100644
index 000000000000..9575785b6bb3
--- /dev/null
+++ b/core/modules/color/color.services.yml
@@ -0,0 +1,6 @@
+services:
+  color.config_cache_invalidator:
+    class: Drupal\color\EventSubscriber\ColorConfigCacheInvalidator
+    arguments: ['@cache_tags.invalidator']
+    tags:
+      - { name: event_subscriber }
diff --git a/core/modules/color/src/EventSubscriber/ColorConfigCacheInvalidator.php b/core/modules/color/src/EventSubscriber/ColorConfigCacheInvalidator.php
new file mode 100644
index 000000000000..3af8d404239e
--- /dev/null
+++ b/core/modules/color/src/EventSubscriber/ColorConfigCacheInvalidator.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\color\EventSubscriber\ColorConfigCacheInvalidator.
+ */
+
+namespace Drupal\color\EventSubscriber;
+
+use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * A subscriber invalidating cache tags when color config objects are saved.
+ */
+class ColorConfigCacheInvalidator implements EventSubscriberInterface {
+
+  /**
+   * The cache tags invalidator.
+   *
+   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
+   */
+  protected $cacheTagsInvalidator;
+
+  /**
+   * Constructs a ColorConfigCacheInvalidator object.
+   *
+   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
+   *   The cache tags invalidator.
+   */
+  public function __construct(CacheTagsInvalidatorInterface $cache_tags_invalidator) {
+    $this->cacheTagsInvalidator = $cache_tags_invalidator;
+  }
+
+  /**
+   * Invalidate cache tags when a color theme config object changes.
+   *
+   * @param \Drupal\Core\Config\ConfigCrudEvent $event
+   *   The Event to process.
+   */
+  public function onChange(ConfigCrudEvent $event) {
+    // Changing a theme's color settings causes the theme's asset library
+    // containing the color CSS file to be altered to use a different file.
+    if (strpos($event->getConfig()->getName(), 'color.theme.') === 0) {
+      $this->cacheTagsInvalidator->invalidateTags(['library_info']);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events[ConfigEvents::SAVE][] = ['onChange'];
+    $events[ConfigEvents::DELETE][] = ['onChange'];
+
+    return $events;
+  }
+
+}
diff --git a/core/modules/color/src/Tests/ColorTest.php b/core/modules/color/src/Tests/ColorTest.php
index 1d1b72e334e8..b5ed67aba60a 100644
--- a/core/modules/color/src/Tests/ColorTest.php
+++ b/core/modules/color/src/Tests/ColorTest.php
@@ -22,7 +22,7 @@ class ColorTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('color', 'color_test');
+  public static $modules = array('color', 'color_test', 'block');
 
   /**
    * A user with administrative permissions.
@@ -194,4 +194,43 @@ function testLogoSettingOverride() {
     $this->assertIdentical($GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png', $this->getDrupalSettings()['color']['logo']);
   }
 
+  /**
+   * Test whether the scheme can be set, viewed anonymously and reset.
+   */
+  function testOverrideAndResetScheme() {
+    $settings_path = 'admin/appearance/settings/bartik';
+    $this->config('system.theme')
+      ->set('default', 'bartik')
+      ->save();
+
+    // Place branding block with site name and slogan into header region.
+    $this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
+
+    $this->drupalGet('');
+    $this->assertNoRaw('files/color/bartik-', 'Make sure the color logo is not being used.');
+    $this->assertRaw('bartik/logo.svg', 'Make sure the original bartik logo exists.');
+
+    // Log in and set the color scheme to 'slate'.
+    $this->drupalLogin($this->bigUser);
+    $edit['scheme'] = 'slate';
+    $this->drupalPostForm($settings_path, $edit, t('Save configuration'));
+
+    // Visit the homepage and ensure color changes.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertRaw('files/color/bartik-', 'Make sure the color logo is being used.');
+    $this->assertNoRaw('bartik/logo.svg', 'Make sure the original bartik logo does not exist.');
+
+    // Log in and set the color scheme back to default (delete config).
+    $this->drupalLogin($this->bigUser);
+    $edit['scheme'] = 'default';
+    $this->drupalPostForm($settings_path, $edit, t('Save configuration'));
+
+    // Log out and ensure there is no color and we have the original logo.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertNoRaw('files/color/bartik-', 'Make sure the color logo is not being used.');
+    $this->assertRaw('bartik/logo.svg', 'Make sure the original bartik logo exists.');
+  }
+
 }
diff --git a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
index 22ae7b2b4051..ab1c8f2ca79e 100644
--- a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
@@ -105,6 +105,7 @@ function testPageCacheTags() {
       'user:0',
       'user:' . $author_1->id(),
       'config:filter.format.basic_html',
+      'config:color.theme.bartik',
       'config:search.settings',
       'config:system.menu.account',
       'config:system.menu.tools',
@@ -142,6 +143,7 @@ function testPageCacheTags() {
       'node_view',
       'node:' . $node_2->id(),
       'user:' . $author_2->id(),
+      'config:color.theme.bartik',
       'config:filter.format.full_html',
       'config:search.settings',
       'config:system.menu.account',
-- 
GitLab