From 6dff701751a8f46646ee83fb4b7d1b53c43bfb7c Mon Sep 17 00:00:00 2001
From: Claudiu Cristea <clau.cristea@gmail.com>
Date: Wed, 24 Jul 2013 21:33:07 +0300
Subject: [PATCH] Issue #1788542 by tim-e, andypost, fubhy, claudiu.cristea,
 speely: Use EntityFormController and EntityListController for image styles.

---
 core/modules/image/image.admin.inc                 | 299 ---------------------
 core/modules/image/image.module                    |  30 +--
 core/modules/image/image.routing.yml               |  21 ++
 .../Drupal/image/ImageStyleAccessController.php    |  33 +++
 .../Drupal/image/ImageStyleAddFormController.php   |  66 +++++
 .../lib/Drupal/image/ImageStyleFormController.php  | 237 ++++++++++++++++
 .../lib/Drupal/image/ImageStyleListController.php  | 106 ++++++++
 .../Drupal/image/Plugin/Core/Entity/ImageStyle.php |   6 +-
 .../image/Plugin/Menu/ImageStyleAddLocalAction.php |  24 ++
 .../lib/Drupal/image/Tests/ImageStyleListTest.php  |  57 ++++
 10 files changed, 554 insertions(+), 325 deletions(-)
 create mode 100644 core/modules/image/lib/Drupal/image/ImageStyleAccessController.php
 create mode 100644 core/modules/image/lib/Drupal/image/ImageStyleAddFormController.php
 create mode 100644 core/modules/image/lib/Drupal/image/ImageStyleFormController.php
 create mode 100644 core/modules/image/lib/Drupal/image/ImageStyleListController.php
 create mode 100644 core/modules/image/lib/Drupal/image/Plugin/Menu/ImageStyleAddLocalAction.php
 create mode 100644 core/modules/image/lib/Drupal/image/Tests/ImageStyleListTest.php

diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index 1e2646f..18d9209 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -11,305 +11,6 @@
 use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
- * Menu callback; Listing of all current image styles.
- */
-function image_style_list() {
-  $page = array();
-
-  $styles = entity_load_multiple('image_style');
-  $page['image_style_list'] = array(
-    '#markup' => theme('image_style_list', array('styles' => $styles)),
-    '#attached' => array(
-      'css' => array(drupal_get_path('module', 'image') . '/css/image.admin.css' => array()),
-    ),
-  );
-
-  return $page;
-
-}
-
-/**
- * Form builder; Edit an image style name and effects order.
- *
- * @param $form_state
- *   An associative array containing the current state of the form.
- * @param $style
- *   An image style array.
- * @ingroup forms
- * @see image_style_form_submit()
- */
-function image_style_form($form, &$form_state, ImageStyleInterface $style) {
-  $title = t('Edit style %name', array('%name' => $style->label()));
-  drupal_set_title($title, PASS_THROUGH);
-
-  $form_state['image_style'] = $style;
-  $form['#tree'] = TRUE;
-  $form['#attached']['css'][drupal_get_path('module', 'image') . '/css/image.admin.css'] = array();
-
-  // Show the thumbnail preview.
-  $form['preview'] = array(
-    '#type' => 'item',
-    '#title' => t('Preview'),
-    '#markup' => theme('image_style_preview', array('style' => $style)),
-  );
-
-  $form['label'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Administrative label'),
-    '#default_value' => $style->label(),
-    '#required' => TRUE,
-  );
-  $form['name'] = array(
-    '#type' => 'machine_name',
-    '#default_value' => $style->id(),
-    '#machine_name' => array(
-      'exists' => 'image_style_load',
-    ),
-    '#required' => TRUE,
-  );
-
-  // Build the list of existing image effects for this image style.
-  $form['effects'] = array(
-    '#theme' => 'image_style_effects',
-  );
-  foreach ($style->getEffects()->sort() as $effect) {
-    $key = $effect->getUuid();
-    $form['effects'][$key]['#weight'] = isset($form_state['input']['effects']) ? $form_state['input']['effects'][$key]['weight'] : NULL;
-    $form['effects'][$key]['label'] = array(
-      '#markup' => String::checkPlain($effect->label()),
-    );
-    $form['effects'][$key]['summary'] = $effect->getSummary();
-    $form['effects'][$key]['weight'] = array(
-      '#type' => 'weight',
-      '#title' => t('Weight for @title', array('@title' => $effect->label())),
-      '#title_display' => 'invisible',
-      '#default_value' => $effect->getWeight(),
-    );
-
-    $links = array();
-    $is_configurable = $effect instanceof ConfigurableImageEffectInterface;
-    if ($is_configurable) {
-      $links['edit'] = array(
-        'title' => t('edit'),
-        'href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key,
-      );
-    }
-    $links['delete'] = array(
-      'title' => t('delete'),
-      'href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key . '/delete',
-    );
-    $form['effects'][$key]['operations'] = array(
-      '#type' => 'operations',
-      '#links' => $links,
-    );
-    $form['effects'][$key]['configure'] = array(
-      '#type' => 'link',
-      '#title' => t('edit'),
-      '#href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key,
-      '#access' => $is_configurable,
-    );
-    $form['effects'][$key]['remove'] = array(
-      '#type' => 'link',
-      '#title' => t('delete'),
-      '#href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key . '/delete',
-    );
-  }
-
-  // Build the new image effect addition form and add it to the effect list.
-  $new_effect_options = array();
-  $effects = Drupal::service('plugin.manager.image.effect')->getDefinitions();
-  uasort($effects, function ($a, $b) {
-    return strcasecmp($a['id'], $b['id']);
-  });
-  foreach ($effects as $effect => $definition) {
-    $new_effect_options[$effect] = $definition['label'];
-  }
-  $form['effects']['new'] = array(
-    '#tree' => FALSE,
-    '#weight' => isset($form_state['input']['weight']) ? $form_state['input']['weight'] : NULL,
-  );
-  $form['effects']['new']['new'] = array(
-    '#type' => 'select',
-    '#title' => t('Effect'),
-    '#title_display' => 'invisible',
-    '#options' => $new_effect_options,
-    '#empty_option' => t('Select a new effect'),
-  );
-  $form['effects']['new']['weight'] = array(
-    '#type' => 'weight',
-    '#title' => t('Weight for new effect'),
-    '#title_display' => 'invisible',
-    '#default_value' => count($form['effects']) - 1,
-  );
-  $form['effects']['new']['add'] = array(
-    '#type' => 'submit',
-    '#value' => t('Add'),
-    '#validate' => array('image_style_form_add_validate'),
-    '#submit' => array('image_style_form_submit', 'image_style_form_add_submit'),
-  );
-
-  // Show the Override or Submit button for this style.
-  $form['actions'] = array('#type' => 'actions');
-  $form['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Update style'),
-  );
-
-  return $form;
-}
-
-/**
- * Validate handler for adding a new image effect to an image style.
- */
-function image_style_form_add_validate($form, &$form_state) {
-  if (!$form_state['values']['new']) {
-    form_error($form['effects']['new']['new'], t('Select an effect to add.'));
-  }
-}
-
-/**
- * Submit handler for adding a new image effect to an image style.
- */
-function image_style_form_add_submit($form, &$form_state) {
-  $style = $form_state['image_style'];
-  // Check if this field has any configuration options.
-  $effect = Drupal::service('plugin.manager.image.effect')->getDefinition($form_state['values']['new']);
-
-  // Load the configuration form for this option.
-  if (is_subclass_of($effect['class'], '\Drupal\image\ConfigurableImageEffectInterface')) {
-    $path = 'admin/config/media/image-styles/manage/' . $style->id() . '/add/' . $form_state['values']['new'];
-    $form_state['redirect'] = array($path, array('query' => array('weight' => $form_state['values']['weight'])));
-  }
-  // If there's no form, immediately add the image effect.
-  else {
-    $effect = array(
-      'id' => $effect['id'],
-      'data' => array(),
-      'weight' => $form_state['values']['weight'],
-    );
-    $style->saveImageEffect($effect);
-    drupal_set_message(t('The image effect was successfully applied.'));
-  }
-}
-
-/**
- * Submit handler for saving an image style.
- */
-function image_style_form_submit($form, &$form_state) {
-  $style = $form_state['image_style'];
-
-  // Update image effect weights.
-  if (!empty($form_state['values']['effects'])) {
-    foreach ($form_state['values']['effects'] as $uuid => $effect_data) {
-      if ($style->getEffects()->has($uuid)) {
-        $style->getEffect($uuid)->setWeight($effect_data['weight']);
-      }
-    }
-  }
-
-  $style->set('name', $form_state['values']['name']);
-  $style->set('label', $form_state['values']['label']);
-  $status = $style->save();
-
-  if ($status == SAVED_UPDATED) {
-    drupal_set_message(t('Changes to the style have been saved.'));
-  }
-  $form_state['redirect'] = 'admin/config/media/image-styles/manage/' . $style->id();
-}
-
-/**
- * Form builder; Form for adding a new image style.
- *
- * @ingroup forms
- * @see image_style_add_form_submit()
- */
-function image_style_add_form($form, &$form_state) {
-  $form['label'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Administrative label'),
-    '#default_value' => '',
-    '#required' => TRUE,
-  );
-  $form['name'] = array(
-    '#type' => 'machine_name',
-    '#machine_name' => array(
-      'exists' => 'image_style_load',
-    ),
-    '#default_value' => '',
-    '#required' => TRUE,
-  );
-
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Create new style'),
-  );
-
-  return $form;
-}
-
-/**
- * Submit handler for adding a new image style.
- */
-function image_style_add_form_submit($form, &$form_state) {
-  $style = entity_create('image_style', array(
-    'name' => $form_state['values']['name'],
-    'label' => $form_state['values']['label'],
-  ));
-  $style->save();
-  drupal_set_message(t('Style %name was created.', array('%name' => $style->label())));
-  $form_state['redirect'] = 'admin/config/media/image-styles/manage/' . $style->id();
-}
-
-/**
- * Returns HTML for the page containing the list of image styles.
- *
- * @param $variables
- *   An associative array containing:
- *   - styles: An array of all the image styles returned by image_get_styles().
- *
- * @see image_get_styles()
- * @ingroup themeable
- */
-function theme_image_style_list($variables) {
-  $styles = $variables['styles'];
-
-  $header = array(t('Style name'), t('Operations'));
-  $rows = array();
-
-  foreach ($styles as $style) {
-    $row = array();
-    $row[] = l($style->label(), 'admin/config/media/image-styles/manage/' . $style->id());
-    $links = array();
-    $links['edit'] = array(
-      'title' => t('edit'),
-      'href' => 'admin/config/media/image-styles/manage/' . $style->id(),
-      'class' => array('image-style-link'),
-    );
-    $links['delete'] = array(
-      'title' => t('delete'),
-      'href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/delete',
-      'class' => array('image-style-link'),
-    );
-    $row[] = array(
-      'data' => array(
-        '#type' => 'operations',
-        '#links' => $links,
-      ),
-    );
-    $rows[] = $row;
-  }
-
-  if (empty($rows)) {
-    $rows[] = array(array(
-      'colspan' => 4,
-      'data' => t('There are currently no styles. <a href="!url">Add a new one</a>.', array('!url' => url('admin/config/media/image-styles/add'))),
-    ));
-  }
-
-  return theme('table', array('header' => $header, 'rows' => $rows));
-}
-
-/**
  * Returns HTML for a listing of the effects within a specific image style.
  *
  * @param $variables
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index fefbf00..c1918eb 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -96,42 +96,26 @@ function image_menu() {
   $items['admin/config/media/image-styles'] = array(
     'title' => 'Image styles',
     'description' => 'Configure styles that can be used for resizing or adjusting images on display.',
-    'page callback' => 'image_style_list',
-    'access arguments' => array('administer image styles'),
-    'file' => 'image.admin.inc',
+    'route_name' => 'image_style_list',
   );
   $items['admin/config/media/image-styles/list'] = array(
     'title' => 'List',
     'description' => 'List the current image styles on the site.',
-    'page callback' => 'image_style_list',
-    'access arguments' => array('administer image styles'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
-    'file' => 'image.admin.inc',
   );
   $items['admin/config/media/image-styles/add'] = array(
-    'title' => 'Add style',
-    'description' => 'Add a new image style.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('image_style_add_form'),
-    'access arguments' => array('administer image styles'),
-    'type' => MENU_LOCAL_ACTION,
-    'weight' => 2,
-    'file' => 'image.admin.inc',
+    'route_name' => 'image_style_add',
+    'type' => MENU_SIBLING_LOCAL_TASK,
+    'weight' => 1,
   );
   $items['admin/config/media/image-styles/manage/%image_style'] = array(
     'title' => 'Edit style',
-    'title callback' => 'entity_page_label',
-    'title arguments' => array(5),
     'description' => 'Configure an image style.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('image_style_form', 5),
-    'access arguments' => array('administer image styles'),
-    'file' => 'image.admin.inc',
+    'route_name' => 'image_style_edit',
   );
   $items['admin/config/media/image-styles/manage/%image_style/edit'] = array(
     'title' => 'Edit',
     'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
   );
   $items['admin/config/media/image-styles/manage/%image_style/delete'] = array(
     'title' => 'Delete',
@@ -178,10 +162,6 @@ function image_theme() {
     ),
 
     // Theme functions in image.admin.inc.
-    'image_style_list' => array(
-      'variables' => array('styles' => NULL),
-      'file' => 'image.admin.inc',
-    ),
     'image_style_effects' => array(
       'render element' => 'form',
       'file' => 'image.admin.inc',
diff --git a/core/modules/image/image.routing.yml b/core/modules/image/image.routing.yml
index 3625dbe..c5b83ce 100644
--- a/core/modules/image/image.routing.yml
+++ b/core/modules/image/image.routing.yml
@@ -1,3 +1,17 @@
+image_style_add:
+  pattern: '/admin/config/media/image-styles/add'
+  defaults:
+    _entity_form: image_style.add
+  requirements:
+    _permission: 'administer image styles'
+
+image_style_edit:
+  pattern: '/admin/config/media/image-styles/manage/{image_style}'
+  defaults:
+    _entity_form: image_style.edit
+  requirements:
+    _permission: 'administer image styles'
+
 image_style_delete:
   pattern: 'admin/config/media/image-styles/manage/{image_style}/delete'
   defaults:
@@ -12,6 +26,13 @@ image_effect_delete:
   requirements:
     _permission: 'administer image styles'
 
+image_style_list:
+  pattern: '/admin/config/media/image-styles'
+  defaults:
+    _entity_list: 'image_style'
+  requirements:
+    _permission: 'administer image styles'
+
 image_style_private:
   pattern: '/system/files/styles/{image_style}/{scheme}'
   defaults:
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleAccessController.php b/core/modules/image/lib/Drupal/image/ImageStyleAccessController.php
new file mode 100644
index 0000000..02c43df
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/ImageStyleAccessController.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\ImageStyleAccessController.
+ */
+
+namespace Drupal\image;
+
+use \Drupal\Core\Entity\EntityAccessController;
+use \Drupal\Core\Entity\EntityInterface;
+use \Drupal\Core\Session\AccountInterface;
+
+/**
+ * Defines an access controller for the image style entity.
+ *
+ * @see \Drupal\image\Plugin\Core\Entity\ImageStyle
+ */
+class ImageStyleAccessController extends EntityAccessController {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
+    switch ($operation) {
+      case 'create':
+      case 'update':
+      case 'delete':
+        return $account->hasPermission('administer image styles');
+        break;
+    }
+  }
+}
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleAddFormController.php b/core/modules/image/lib/Drupal/image/ImageStyleAddFormController.php
new file mode 100644
index 0000000..996c5df
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/ImageStyleAddFormController.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\ImageStyleAddFormController.
+ */
+
+namespace Drupal\image;
+
+use Drupal\Core\Entity\EntityFormController;
+
+/**
+ * Base form controller for image style addition forms.
+ */
+class ImageStyleAddFormController extends EntityFormController {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(array $form, array &$form_state) {
+    $form = parent::form($form, $form_state);
+
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Administrative label'),
+      '#default_value' => $this->entity->label(),
+      '#required' => TRUE,
+      '#weight' => 20,
+    );
+    $form['name'] = array(
+      '#type' => 'machine_name',
+      '#machine_name' => array(
+        'exists' => 'image_style_load',
+      ),
+      '#default_value' => $this->entity->id(),
+      '#required' => TRUE,
+      '#weight' => 30,
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(array $form, array &$form_state) {
+    $this->entity->save();
+    drupal_set_message(t('Style %name was created.', array('%name' => $this->entity->label())));
+    $uri = $this->entity->uri();
+    watchdog('image', 'Style %name was created.', array('%name' => $this->entity->label()), WATCHDOG_NOTICE, l(t('Edit'), $uri['path']));
+    $form_state['redirect'] = 'admin/config/media/image-styles/manage/' . $this->entity->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function actions(array $form, array &$form_state) {
+    $actions = parent::actions($form, $form_state);
+
+    $actions['submit']['#value'] = t('Create new style');
+    unset($actions['delete']);
+
+    return $actions;
+  }
+
+}
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleFormController.php b/core/modules/image/lib/Drupal/image/ImageStyleFormController.php
new file mode 100644
index 0000000..e27f4ab
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/ImageStyleFormController.php
@@ -0,0 +1,237 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\ImageStyleFormController.
+ */
+
+namespace Drupal\image;
+
+use Drupal\Core\Entity\EntityFormController;
+use Drupal\image\ImageStyleInterface;
+use Drupal\Component\Utility\String;
+
+/**
+ * Base form controller for image style edit forms.
+ */
+class ImageStyleFormController extends EntityFormController {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(array $form, array &$form_state) {
+    $form = parent::form($form, $form_state);
+    $style = $this->entity;
+
+    // @todo Remove drupal_set_title() in http://drupal.org/node/1981644
+    $title = t('Edit style %name', array('%name' => $style->label()));
+    drupal_set_title($title, PASS_THROUGH);
+
+    $form['#tree'] = TRUE;
+    $form['#attached']['css'][drupal_get_path('module', 'image') . '/css/image.admin.css'] = array();
+
+    // Show the thumbnail preview.
+    form_load_include($form_state, 'inc', 'image', 'image.admin');
+    $form['preview'] = array(
+      '#type' => 'item',
+      '#title' => t('Preview'),
+      '#markup' => theme('image_style_preview', array('style' => $style)),
+    );
+
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Image style name'),
+      '#default_value' => $style->label(),
+      '#required' => TRUE,
+    );
+    $form['name'] = array(
+      '#type' => 'machine_name',
+      '#machine_name' => array(
+        'exists' => 'image_style_load',
+      ),
+      '#default_value' => $style->id(),
+      '#required' => TRUE,
+    );
+
+    // Build the list of existing image effects for this image style.
+    $form['effects'] = array(
+      '#theme' => 'image_style_effects',
+    );
+    foreach ($style->getEffects()->sort() as $effect) {
+      $key = $effect->getUuid();
+      $form['effects'][$key]['#weight'] = isset($form_state['input']['effects']) ? $form_state['input']['effects'][$key]['weight'] : NULL;
+      $form['effects'][$key]['label'] = array(
+        '#markup' => String::checkPlain($effect->label()),
+      );
+      $form['effects'][$key]['summary'] = $effect->getSummary();
+      $form['effects'][$key]['weight'] = array(
+        '#type' => 'weight',
+        '#title' => t('Weight for @title', array('@title' => $effect->label())),
+        '#title_display' => 'invisible',
+        '#default_value' => $effect->getWeight(),
+      );
+
+      $links = array();
+      $is_configurable = $effect instanceof ConfigurableImageEffectInterface;
+      if ($is_configurable) {
+        $links['edit'] = array(
+          'title' => t('edit'),
+          'href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key,
+        );
+      }
+      $links['delete'] = array(
+        'title' => t('delete'),
+        'href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key . '/delete',
+      );
+      $form['effects'][$key]['operations'] = array(
+        '#type' => 'operations',
+        '#links' => $links,
+      );
+      $form['effects'][$key]['configure'] = array(
+        '#type' => 'link',
+        '#title' => t('edit'),
+        '#href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key,
+        '#access' => $is_configurable,
+      );
+      $form['effects'][$key]['remove'] = array(
+        '#type' => 'link',
+        '#title' => t('delete'),
+        '#href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key . '/delete',
+      );
+    }
+
+    // Build the new image effect addition form and add it to the effect list.
+    $new_effect_options = array();
+    $effects = \Drupal::service('plugin.manager.image.effect')->getDefinitions();
+    uasort($effects, function ($a, $b) {
+      return strcasecmp($a['id'], $b['id']);
+    });
+    foreach ($effects as $effect => $definition) {
+      $new_effect_options[$effect] = $definition['label'];
+    }
+    $form['effects']['new'] = array(
+      '#tree' => FALSE,
+      '#weight' => isset($form_state['input']['weight']) ? $form_state['input']['weight'] : NULL,
+    );
+    $form['effects']['new']['new'] = array(
+      '#type' => 'select',
+      '#title' => t('Effect'),
+      '#title_display' => 'invisible',
+      '#options' => $new_effect_options,
+      '#empty_option' => t('Select a new effect'),
+    );
+    $form['effects']['new']['weight'] = array(
+      '#type' => 'weight',
+      '#title' => t('Weight for new effect'),
+      '#title_display' => 'invisible',
+      '#default_value' => count($form['effects']) - 1,
+    );
+    $form['effects']['new']['add'] = array(
+      '#type' => 'submit',
+      '#value' => t('Add'),
+      '#validate' => array(array($this, 'effectValidate')),
+      '#submit' => array(array($this, 'effectSave')),
+    );
+
+    return $form;
+  }
+
+  /**
+   * Validate handler for image effect.
+   */
+  public function effectValidate($form, &$form_state) {
+    if (!$form_state['values']['new']) {
+      form_error($form['effects']['new']['new'], t('Select an effect to add.'));
+    }
+  }
+
+  /**
+   * Submit handler for image effect.
+   */
+  public function effectSave($form, &$form_state) {
+    $style = $this->entity;
+
+    // Update image effect weights.
+    if (!empty($form_state['values']['effects'])) {
+      $this->updateEffectWeights($style, $form_state['values']['effects']);
+    }
+
+    $style->set('name', $form_state['values']['name']);
+    $style->set('label', $form_state['values']['label']);
+    $status = $style->save();
+
+    if ($status == SAVED_UPDATED) {
+      drupal_set_message(t('Changes to the style have been saved.'));
+    }
+
+    // Check if this field has any configuration options.
+    $effect = \Drupal::service('plugin.manager.image.effect')->getDefinition($form_state['values']['new']);
+
+    // Load the configuration form for this option.
+    if (is_subclass_of($effect['class'], '\Drupal\image\ConfigurableImageEffectInterface')) {
+      $path = 'admin/config/media/image-styles/manage/' . $style->id() . '/add/' . $form_state['values']['new'];
+      $form_state['redirect'] = array($path, array('query' => array('weight' => $form_state['values']['weight'])));
+    }
+    // If there's no form, immediately add the image effect.
+    else {
+      $effect = array(
+        'id' => $effect['id'],
+        'data' => array(),
+        'weight' => $form_state['values']['weight'],
+      );
+      $effect_id = $style->saveImageEffect($effect);
+      if (!empty($effect_id)) {
+        drupal_set_message(t('The image effect was successfully applied.'));
+      }
+      $form_state['redirect'] = 'admin/config/media/image-styles/manage/' . $style->id();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(array $form, array &$form_state) {
+    $style = $this->entity;
+
+    // Update image effect weights.
+    if (!empty($form_state['values']['effects'])) {
+      $this->updateEffectWeights($style, $form_state['values']['effects']);
+    }
+       
+    $style->save();
+    drupal_set_message(t('Changes to the style have been saved.'));
+    $uri = $this->entity->uri();
+    watchdog('image', 'Style %label has been updated.', array('%label' => $this->entity->label()), WATCHDOG_NOTICE, l(t('Edit'), $uri['path']));
+    $form_state['redirect'] = 'admin/config/media/image-styles/manage/' . $this->entity->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function actions(array $form, array &$form_state) {
+    $actions = parent::actions($form, $form_state);
+
+    $actions['submit']['#value'] = t('Update style');
+    unset($actions['delete']);
+
+    return $actions;
+  }
+
+  /**
+   * Update image effect weights.
+   *
+   * @param \Drupal\image\ImageStyleInterface $style
+   *   The image style object to be updated.
+   * @param array $effects
+   *   Associative array with effects having effect uuid as keys and and array
+   *   with effect data as values.
+   */
+  protected function updateEffectWeights(ImageStyleInterface $style, array $effects) {    
+    foreach ($effects as $uuid => $effect_data) {
+      if ($style->getEffects()->has($uuid)) {
+        $style->getEffect($uuid)->setWeight($effect_data['weight']);
+      }
+    }
+  }
+
+}
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleListController.php b/core/modules/image/lib/Drupal/image/ImageStyleListController.php
new file mode 100644
index 0000000..78659df
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/ImageStyleListController.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\ImageStyleListController.
+ */
+
+namespace Drupal\image;
+
+use Drupal\Core\Config\Entity\ConfigEntityListController;
+use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Routing\PathBasedGeneratorInterface;
+use Drupal\Core\StringTranslation\TranslationManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Component\Utility\String;
+
+/**
+ * Provides a listing of image styles.
+ */
+class ImageStyleListController extends ConfigEntityListController implements EntityControllerInterface {
+
+  /**
+   * The URL generator.
+   *
+   * @var \Drupal\Core\Routing\PathBasedGeneratorInterface
+   */
+  protected $urlGenerator;
+
+  /**
+   * The translation manager service.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationManager
+   */
+  protected $translationManager;
+
+  /**
+   * Constructs a new ImageStyleListController object.
+   *
+   * @param string $entity_type
+   *   The type of entity to be listed.
+   * @param array $entity_info
+   *   An array of entity info for the entity type.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
+   *   The entity storage controller class.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke hooks on.
+   * @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
+   *   The URL generator.
+   * @param \Drupal\Core\StringTranslation\TranslationManager $translation_manager
+   *   The translation manager.
+   */
+  public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, PathBasedGeneratorInterface $url_generator, TranslationManager $translation_manager) {
+    parent::__construct($entity_type, $entity_info, $storage, $module_handler);
+    $this->urlGenerator = $url_generator;
+    $this->translationManager = $translation_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+    return new static(
+      $entity_type,
+      $entity_info,
+      $container->get('plugin.manager.entity')->getStorageController($entity_type),
+      $container->get('module_handler'),
+      $container->get('url_generator'),
+      $container->get('string_translation')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildHeader() {
+    $row = parent::buildHeader();
+    unset($row['id']);
+    $row['label'] = $this->translationManager->translate('Style name');
+    return $row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row = parent::buildRow($entity);
+    unset($row['id']);
+    $row['label'] = String::checkPlain($entity->label());
+    return $row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render() {
+    $build = parent::render();
+    $build['#empty'] = $this->translationManager->translate('There are currently no styles. <a href="!url">Add a new one</a>.', array(
+      '!url' => $this->urlGenerator->generateFromPath('admin/config/media/image-styles/add'),
+    ));
+    return $build;
+  }
+
+}
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
index ed17dee..7d6362a 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
@@ -27,9 +27,13 @@
  *   module = "image",
  *   controllers = {
  *     "form" = {
+ *       "add" = "Drupal\image\ImageStyleAddFormController",
+ *       "edit" = "Drupal\image\ImageStyleFormController",
  *       "delete" = "Drupal\image\Form\ImageStyleDeleteForm"
  *     },
- *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController"
+ *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *     "list" = "Drupal\image\ImageStyleListController",
+ *     "access" = "Drupal\image\ImageStyleAccessController"
  *   },
  *   uri_callback = "image_style_entity_uri",
  *   config_prefix = "image.style",
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Menu/ImageStyleAddLocalAction.php b/core/modules/image/lib/Drupal/image/Plugin/Menu/ImageStyleAddLocalAction.php
new file mode 100644
index 0000000..90b1eb4
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/Plugin/Menu/ImageStyleAddLocalAction.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\image\Plugin\Menu\ImageStyleAddLocalAction.
+ */
+
+namespace Drupal\image\Plugin\Menu;
+
+use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Menu\LocalActionBase;
+use Drupal\Core\Annotation\Menu\LocalAction;
+
+/**
+ * @LocalAction(
+ *   id = "image_style_add_action",
+ *   route_name = "image_style_add",
+ *   title = @Translation("Add image style"),
+ *   appears_on = {"image_style_list"}
+ * )
+ */
+class ImageStyleAddLocalAction extends LocalActionBase {
+
+}
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageStyleListTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageStyleListTest.php
new file mode 100644
index 0000000..f48a1c0
--- /dev/null
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageStyleListTest.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\image\Tests\ImageStyleListTest.
+ */
+
+namespace Drupal\image\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests access to overview page and operation links
+ */
+class ImageStyleListTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('image');
+
+  /**
+   * A user with the permission to administer image styles.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $adminUser;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Image styles list',
+      'description' => 'Tests access to overview page and operation links.',
+      'group' => 'Image',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $style = entity_create('image_style', array('name' => 'style_foo', 'label' => $this->randomString()));
+    $style->save();
+
+    $this->adminUser = $this->drupalCreateUser(array('administer image styles'));
+    $this->drupalLogin($this->adminUser);
+  }
+
+  /**
+   * Tests access for the image style listing.
+   */
+  function testImageStyleAccess() {
+    $this->drupalGet('admin/config/media/image-styles');
+    $this->clickLink(t('Edit'));
+  }
+
+}
-- 
1.8.3.1

