From 9def61241e1a5251bd61cb0f97280025676800fc Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Thu, 16 Apr 2015 14:35:09 +0200
Subject: [PATCH] Issue #2388023 by GoZ: File/Image field formatters don't add
 a cache tag for the file they display

---
 .../FieldFormatter/GenericFileFormatter.php   |  3 +++
 .../Field/FieldFormatter/TableFormatter.php   |  3 +++
 .../FieldFormatter/UrlPlainFormatter.php      |  7 ++++++-
 .../Field/FieldFormatter/ImageFormatter.php   |  2 ++
 .../image/src/Tests/ImageFieldDisplayTest.php | 20 +++++++++++++------
 5 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php
index cb917eb13f88..f37003711069 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php
@@ -34,6 +34,9 @@ public function viewElements(FieldItemListInterface $items) {
         '#theme' => 'file_link',
         '#file' => $file,
         '#description' => $item->description,
+        '#cache' => array(
+          'tags' => $file->getCacheTags(),
+        ),
       );
       // Pass field item attributes to the theme function.
       if (isset($item->_attributes)) {
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/TableFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/TableFormatter.php
index 460450dec8cb..9bf55ee9e6f1 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/TableFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/TableFormatter.php
@@ -37,6 +37,9 @@ public function viewElements(FieldItemListInterface $items) {
             'data' => array(
               '#theme' => 'file_link',
               '#file' => $file,
+              '#cache' => array(
+                'tags' => $file->getCacheTags(),
+              ),
             ),
           ),
           array('data' => format_size($file->getSize())),
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php
index 26b78f7222fc..f61a98d06d2a 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php
@@ -29,7 +29,12 @@ public function viewElements(FieldItemListInterface $items) {
     $elements = array();
 
     foreach ($this->getEntitiesToView($items) as $delta => $file) {
-      $elements[$delta] = array('#markup' => file_create_url($file->getFileUri()));
+      $elements[$delta] = array(
+        '#markup' => file_create_url($file->getFileUri()),
+        '#cache' => array(
+          'tags' => $file->getCacheTags(),
+        ),
+      );
     }
 
     return $elements;
diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
index 0e12d10aa5ba..294c561c9bcb 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
@@ -17,6 +17,7 @@
 use Drupal\Core\Utility\LinkGeneratorInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Cache\Cache;
 
 /**
  * Plugin implementation of the 'image' formatter.
@@ -211,6 +212,7 @@ public function viewElements(FieldItemListInterface $items) {
         $image_uri = $file->getFileUri();
         $url = Url::fromUri(file_create_url($image_uri));
       }
+      $cache_tags = Cache::mergeTags($cache_tags, $file->getCacheTags());
 
       // Extract field item attributes for the theme function, and unset them
       // from the $item so that the field template does not re-render them.
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index c11243707bf1..2679328610d0 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -94,7 +94,8 @@ function _testImageFieldFormatters($scheme) {
     $node = $node_storage->load($nid);
 
     // Test that the default formatter is being used.
-    $image_uri = file_load($node->{$field_name}->target_id)->getFileUri();
+    $file = $node->{$field_name}->entity;
+    $image_uri = $file->getFileUri();
     $image = array(
       '#theme' => 'image',
       '#uri' => $image_uri,
@@ -123,6 +124,7 @@ function _testImageFieldFormatters($scheme) {
     );
     $default_output = '<a href="' . file_create_url($image_uri) . '">' . drupal_render($image) . '</a>';
     $this->drupalGet('node/' . $nid);
+    $this->assertCacheTag($file->getCacheTags()[0]);
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.');
@@ -154,6 +156,7 @@ function _testImageFieldFormatters($scheme) {
       '#height' => 20,
     );
     $this->drupalGet('node/' . $nid);
+    $this->assertCacheTag($file->getCacheTags()[0]);
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $elements = $this->xpath(
@@ -187,8 +190,8 @@ function _testImageFieldFormatters($scheme) {
     );
     $default_output = drupal_render($image_style);
     $this->drupalGet('node/' . $nid);
-    $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags'));
-    $this->assertTrue(in_array('config:image.style.thumbnail', $cache_tags));
+    $image_style = ImageStyle::load('thumbnail');
+    $this->assertCacheTag($image_style->getCacheTags()[0]);
     $this->assertRaw($default_output, 'Image style thumbnail formatter displaying correctly on full node view.');
 
     if ($scheme == 'private') {
@@ -247,9 +250,10 @@ function testImageFieldSettings() {
     // style.
     $node_storage->resetCache(array($nid));
     $node = $node_storage->load($nid);
+    $file = $node->{$field_name}->entity;
     $image_style = array(
       '#theme' => 'image_style',
-      '#uri' => file_load($node->{$field_name}->target_id)->getFileUri(),
+      '#uri' => $file->getFileUri(),
       '#width' => 40,
       '#height' => 20,
       '#style_name' => 'medium',
@@ -260,7 +264,7 @@ function testImageFieldSettings() {
     // Add alt/title fields to the image and verify that they are displayed.
     $image = array(
       '#theme' => 'image',
-      '#uri' => file_load($node->{$field_name}->target_id)->getFileUri(),
+      '#uri' => $file->getFileUri(),
       '#alt' => $alt,
       '#title' => $this->randomMachineName(),
       '#width' => 40,
@@ -362,6 +366,7 @@ function testImageFieldDefaultImage() {
     );
     $default_output = str_replace("\n", NULL, drupal_render($image));
     $this->drupalGet('node/' . $node->id());
+    $this->assertCacheTag($file->getCacheTags()[0]);
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $this->assertRaw($default_output, 'Default image displayed when no user supplied image is present.');
@@ -375,15 +380,17 @@ function testImageFieldDefaultImage() {
     $nid = $this->uploadNodeImage($images[1], $field_name, 'article', $alt);
     $node_storage->resetCache(array($nid));
     $node = $node_storage->load($nid);
+    $file = $node->{$field_name}->entity;
     $image = array(
       '#theme' => 'image',
-      '#uri' => file_load($node->{$field_name}->target_id)->getFileUri(),
+      '#uri' => $file->getFileUri(),
       '#width' => 40,
       '#height' => 20,
       '#alt' => $alt,
     );
     $image_output = str_replace("\n", NULL, drupal_render($image));
     $this->drupalGet('node/' . $nid);
+    $this->assertCacheTag($file->getCacheTags()[0]);
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $this->assertNoRaw($default_output, 'Default image is not displayed when user supplied image is present.');
@@ -431,6 +438,7 @@ function testImageFieldDefaultImage() {
     );
     $default_output = str_replace("\n", NULL, drupal_render($image));
     $this->drupalGet('node/' . $node->id());
+    $this->assertCacheTag($file->getCacheTags()[0]);
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $this->assertRaw($default_output, 'Default private image displayed when no user supplied image is present.');
-- 
GitLab