From 31256993e6a634f60749f4ff2349ddecaad0cea4 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Mon, 8 Apr 2013 15:27:35 +0100
Subject: [PATCH] Issue #1821848 by andypost, rbayliss, alexpott: Fixed Move
 image style load/update/delete operations into a new
 ImageStyleStorageController.

---
 core/modules/image/image.module               | 66 --------------
 .../image/ImageStyleStorageController.php     | 85 ++++++++++++++++---
 .../image/Tests/ImageAdminStylesTest.php      | 39 +++++++++
 3 files changed, 111 insertions(+), 79 deletions(-)

diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 7be1abd27516..b963a453025d 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -348,55 +348,6 @@ function image_file_predelete(File $file) {
   image_path_flush($file->uri);
 }
 
-/**
- * Implements hook_image_style_update().
- */
-function image_image_style_update(ImageStyle $style) {
-  if ($style->id() != $style->getOriginalID()) {
-    $instances = field_read_instances();
-    // Loop through all fields searching for image fields.
-    foreach ($instances as $instance) {
-      if ($instance['widget']['module'] == 'image') {
-        $view_modes = entity_get_view_modes($instance['entity_type']);
-        $view_modes = array('default') + array_keys($view_modes);
-        foreach ($view_modes as $view_mode) {
-          $display = entity_get_display($instance['entity_type'], $instance['bundle'], $view_mode);
-          $display_options = $display->getComponent($instance['field_name']);
-
-          // Check if the formatter involves an image style.
-          if ($display_options && $display_options['type'] == 'image' && $display_options['settings']['image_style'] == $style->getOriginalID()) {
-            // Update display information for any instance using the image
-            // style that was just deleted.
-            $display_options['settings']['image_style'] = $style->id();
-            $display->setComponent($instance['field_name'], $display_options)
-              ->save();
-          }
-        }
-        if ($instance['widget']['settings']['preview_image_style'] == $style->getOriginalID()) {
-          $instance['widget']['settings']['preview_image_style'] = $style->id();
-          field_update_instance($instance);
-        }
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_image_style_delete().
- */
-function image_image_style_delete(ImageStyle $style) {
-  // Flush cached media for the style.
-  image_style_flush($style);
-  // Check whether field instance settings need to be updated.
-  // In case no replacement style was specified, all image fields that are using
-  // the deleted style are left in a broken state.
-  if ($new_id = $style->get('replacementID')) {
-    // The deleted ID is still set as originalID.
-    $style->set('name', $new_id);
-    image_image_style_update($style);
-  }
-}
-
 /**
  * Implements hook_field_delete_field().
  */
@@ -542,23 +493,6 @@ function image_style_load($name) {
   return entity_load('image_style', $name);
 }
 
-/**
- * Implements hook_image_style_load.
- */
-function image_image_style_load($styles) {
-  foreach ($styles as $style) {
-    if (!empty($style->effects)) {
-      foreach ($style->effects as $ieid => $effect) {
-        $definition = image_effect_definition_load($effect['name']);
-        $effect = array_merge($definition, $effect);
-        $style->effects[$ieid] = $effect;
-      }
-      // Sort effects by weight.
-      uasort($style->effects, 'drupal_sort_weight');
-    }
-  }
-}
-
 /**
  * Gets an array of image styles suitable for using as select list options.
  *
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php
index 80db53f2b49b..4bbbbde67a21 100644
--- a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php
+++ b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Config\Entity\ConfigStorageController;
 use Drupal\Core\Config\Config;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\image\Plugin\Core\Entity\ImageStyle;
 
 /**
  * Defines a controller class for image styles.
@@ -17,19 +18,21 @@
 class ImageStyleStorageController extends ConfigStorageController {
 
   /**
-   * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importDelete().
+   * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::attachLoad().
    */
-  public function importDelete($name, Config $new_config, Config $old_config) {
-    $id = static::getIDFromConfigName($name, $this->entityInfo['config_prefix']);
-    $entities = $this->load(array($id));
-    $entity = $entities[$id];
-
-    // @todo image_style_delete() supports the notion of a "replacement style"
-    //   to be used by other modules instead of the deleted style. Essential!
-    //   But that is impossible currently, since the config system only knows
-    //   about deleted and added changes. Introduce an 'old_ID' key within
-    //   config objects as a standard?
-    return image_style_delete($entity);
+  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
+    foreach ($queried_entities as $style) {
+      if (!empty($style->effects)) {
+        foreach ($style->effects as $ieid => $effect) {
+          $definition = image_effect_definition_load($effect['name']);
+          $effect = array_merge($definition, $effect);
+          $style->effects[$ieid] = $effect;
+        }
+        // Sort effects by weight.
+        uasort($style->effects, 'drupal_sort_weight');
+      }
+    }
+    parent::attachLoad($queried_entities, $revision_id);
   }
 
   /**
@@ -37,8 +40,64 @@ public function importDelete($name, Config $new_config, Config $old_config) {
    */
   protected function postSave(EntityInterface $entity, $update) {
     if ($update && !empty($entity->original) && $entity->{$this->idKey} !== $entity->original->{$this->idKey}) {
-      // The old imagestyle name needs flushing after a rename.
+      // The old image style name needs flushing after a rename.
       image_style_flush($entity->original);
+      // Update field instance settings if necessary.
+      $this->replaceImageStyle($entity);
+    }
+  }
+
+  /**
+   * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::postDelete().
+   */
+  protected function postDelete($entities) {
+    foreach ($entities as $style) {
+      // Flush cached media for the deleted style.
+      image_style_flush($style);
+      // Check whether field instance settings need to be updated.
+      // In case no replacement style was specified, all image fields that are
+      // using the deleted style are left in a broken state.
+      if ($new_id = $style->get('replacementID')) {
+        // The deleted ID is still set as originalID.
+        $style->set('name', $new_id);
+        $this->replaceImageStyle($style);
+      }
+    }
+  }
+
+  /**
+   * Update field instance settings if the image style name is changed.
+   *
+   * @param ImageStyle $style
+   *   The image style.
+   */
+  protected function replaceImageStyle(ImageStyle $style) {
+    if ($style->id() != $style->getOriginalID()) {
+      $instances = field_read_instances();
+      // Loop through all fields searching for image fields.
+      foreach ($instances as $instance) {
+        if ($instance['widget']['module'] == 'image') {
+          $view_modes = entity_get_view_modes($instance['entity_type']);
+          $view_modes = array('default') + array_keys($view_modes);
+          foreach ($view_modes as $view_mode) {
+            $display = entity_get_display($instance['entity_type'], $instance['bundle'], $view_mode);
+            $display_options = $display->getComponent($instance['field_name']);
+
+            // Check if the formatter involves an image style.
+            if ($display_options && $display_options['type'] == 'image' && $display_options['settings']['image_style'] == $style->getOriginalID()) {
+              // Update display information for any instance using the image
+              // style that was just deleted.
+              $display_options['settings']['image_style'] = $style->id();
+              $display->setComponent($instance['field_name'], $display_options)
+                ->save();
+            }
+          }
+          if ($instance['widget']['settings']['preview_image_style'] == $style->getOriginalID()) {
+            $instance['widget']['settings']['preview_image_style'] = $style->id();
+            field_update_instance($instance);
+          }
+        }
+      }
     }
   }
 
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
index 84a5ed458485..4cb1dca043ce 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
@@ -333,4 +333,43 @@ function testEditEffect() {
     $this->assertText(t('Scale 12x19'));
   }
 
+  /**
+   * Tests image style configuration import that does a delete.
+   */
+  function testConfigImport() {
+    // Create a new style.
+    $style_name = strtolower($this->randomName(10));
+    $style_label = $this->randomString();
+    $style = entity_create('image_style', array('name' => $style_name, 'label' => $style_label));
+    $style->save();
+
+    // Create an image field that uses the new style.
+    $field_name = strtolower($this->randomName(10));
+    $this->createImageField($field_name, 'article');
+    entity_get_display('node', 'article', 'default')
+      ->setComponent($field_name, array(
+        'type' => 'image',
+        'settings' => array('image_style' => $style_name),
+      ))
+      ->save();
+
+    // Create a new node with an image attached.
+    $test_image = current($this->drupalGetTestFiles('image'));
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
+    $node = node_load($nid);
+
+    // Test that image is displayed using newly created style.
+    $this->drupalGet('node/' . $nid);
+    $this->assertRaw(image_style_url($style_name, file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid'])->uri), format_string('Image displayed using style @style.', array('@style' => $style_name)));
+
+    // Write empty manifest to staging.
+    $manifest_data = config('manifest.image.style')->get();
+    unset($manifest_data[$style_name]);
+    $staging = $this->container->get('config.storage.staging');
+    $staging->write('manifest.image.style', $manifest_data);
+    config_import();
+
+    $this->assertFalse(entity_load('image_style', $style_name), 'Style deleted after config import.');
+    $this->assertEqual($this->getImageCount($style), 0, 'Image style was flushed after being deleted by config import.');
+  }
 }
-- 
GitLab