From 6fa50c64eb5bd5a765c89968b0725921ae777358 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Thu, 16 May 2013 08:29:16 +0100
Subject: [PATCH] Issue #1043198 by tim.plunkett, tstoeckler, swentel,
 larowlan: Convert view modes to ConfigEntity.

---
 core/includes/entity.api.php                  | 42 +--------
 core/includes/entity.inc                      | 13 +--
 .../entity.view_mode.custom_block.full.yml    |  4 +
 .../block/custom_block/custom_block.module    | 10 --
 core/modules/book/book.module                 | 11 ---
 .../config/entity.view_mode.node.print.yml    |  4 +
 core/modules/comment/comment.module           | 10 --
 .../config/entity.view_mode.comment.full.yml  |  4 +
 .../Drupal/entity/EntityViewModeInterface.php | 17 ++++
 .../EntityViewModeStorageController.php       | 32 +++++++
 .../Plugin/Core/Entity/EntityViewMode.php     | 94 +++++++++++++++++++
 core/modules/field/field.module               | 16 ++--
 .../modules/field_test/field_test.entity.inc  |  4 +-
 core/modules/field_ui/field_ui.module         | 17 ++++
 .../field_ui/Access/ViewModeAccessCheck.php   |  2 +-
 .../lib/Drupal/field_ui/DisplayOverview.php   |  6 +-
 .../config/entity.view_mode.file.full.yml     |  4 +
 core/modules/file/file.module                 | 10 --
 .../config/entity.view_mode.node.full.yml     |  4 +
 .../node/config/entity.view_mode.node.rss.yml |  4 +
 .../config/entity.view_mode.node.teaser.yml   |  4 +
 core/modules/node/node.module                 | 27 ------
 .../entity.view_mode.node.search_index.yml    |  4 +
 .../entity.view_mode.node.search_result.yml   |  4 +
 .../Upgrade/FilledStandardUpgradePathTest.php |  7 ++
 core/modules/system/system.install            | 51 ++++++++++
 ...tity.view_mode.entity_test_render.full.yml |  4 +
 ...tity.view_mode.entity_test_render.test.yml |  4 +
 .../modules/entity_test/entity_test.module    | 14 ---
 .../tests/upgrade/drupal-7.field.database.php | 10 +-
 .../entity.view_mode.taxonomy_term.full.yml   |  4 +
 ...ity.view_mode.taxonomy_vocabulary.full.yml |  4 +
 core/modules/taxonomy/taxonomy.module         | 13 ---
 .../config/entity.view_mode.user.compact.yml  |  4 +
 .../config/entity.view_mode.user.full.yml     |  4 +
 core/modules/user/user.module                 | 14 ---
 36 files changed, 303 insertions(+), 177 deletions(-)
 create mode 100644 core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml
 create mode 100644 core/modules/book/config/entity.view_mode.node.print.yml
 create mode 100644 core/modules/comment/config/entity.view_mode.comment.full.yml
 create mode 100644 core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php
 create mode 100644 core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php
 create mode 100644 core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php
 create mode 100644 core/modules/file/config/entity.view_mode.file.full.yml
 create mode 100644 core/modules/node/config/entity.view_mode.node.full.yml
 create mode 100644 core/modules/node/config/entity.view_mode.node.rss.yml
 create mode 100644 core/modules/node/config/entity.view_mode.node.teaser.yml
 create mode 100644 core/modules/search/config/entity.view_mode.node.search_index.yml
 create mode 100644 core/modules/search/config/entity.view_mode.node.search_result.yml
 create mode 100644 core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml
 create mode 100644 core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml
 create mode 100644 core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml
 create mode 100644 core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml
 create mode 100644 core/modules/user/config/entity.view_mode.user.compact.yml
 create mode 100644 core/modules/user/config/entity.view_mode.user.full.yml

diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php
index 656f08872210..65725b660b06 100644
--- a/core/includes/entity.api.php
+++ b/core/includes/entity.api.php
@@ -30,46 +30,6 @@ function hook_entity_info(&$entity_info) {
   $entity_info['node']['controllers']['form']['mymodule_foo'] = 'Drupal\mymodule\NodeFooFormController';
 }
 
-/**
- * Describe the view modes for entity types.
- *
- * View modes let entities be displayed differently depending on the context.
- * For instance, a node can be displayed differently on its own page ('full'
- * mode), on the home page or taxonomy listings ('teaser' mode), or in an RSS
- * feed ('rss' mode). Modules taking part in the display of the entity (notably
- * the Field API) can adjust their behavior depending on the requested view
- * mode. An additional 'default' view mode is available for all entity types.
- * This view mode is not intended for actual entity display, but holds default
- * display settings. For each available view mode, administrators can configure
- * whether it should use its own set of field display settings, or just
- * replicate the settings of the 'default' view mode, thus reducing the amount
- * of display configurations to keep track of.
- *
- * @return array
- *   An associative array of all entity view modes, keyed by the entity
- *   type name, and then the view mode name, with the following keys:
- *   - label: The human-readable name of the view mode.
- *   - custom_settings: A boolean specifying whether the view mode should by
- *     default use its own custom field display settings. If FALSE, entities
- *     displayed in this view mode will reuse the 'default' display settings
- *     by default (e.g. right after the module exposing the view mode is
- *     enabled), but administrators can later use the Field UI to apply custom
- *     display settings specific to the view mode.
- *
- * @see entity_get_view_modes()
- * @see hook_entity_view_mode_info_alter()
- */
-function hook_entity_view_mode_info() {
-  $view_modes['user']['full'] = array(
-    'label' => t('User account'),
-  );
-  $view_modes['user']['compact'] = array(
-    'label' => t('Compact'),
-    'custom_settings' => TRUE,
-  );
-  return $view_modes;
-}
-
 /**
  * Alter the view modes for entity types.
  *
@@ -80,7 +40,7 @@ function hook_entity_view_mode_info() {
  * @see hook_entity_view_mode_info()
  */
 function hook_entity_view_mode_info_alter(&$view_modes) {
-  $view_modes['user']['full']['custom_settings'] = TRUE;
+  $view_modes['user']['full']['status'] = TRUE;
 }
 
 /**
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 41e8add0d2aa..53d8bcf6983a 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -121,13 +121,10 @@ function entity_get_view_modes($entity_type = NULL) {
       $view_modes = $cache->data;
     }
     else {
-      $view_modes = module_invoke_all('entity_view_mode_info');
-      foreach ($view_modes as $type => $entity_info) {
-        foreach ($entity_info as $view_mode => $view_mode_info) {
-          $view_modes[$type][$view_mode] += array(
-            'custom_settings' => FALSE,
-          );
-        }
+      $view_modes = array();
+      foreach (entity_load_multiple('view_mode') as $view_mode) {
+        list($view_mode_entity_type, $view_mode_name) = explode('.', $view_mode->id(), 2);
+        $view_modes[$view_mode_entity_type][$view_mode_name] = (array) $view_mode;
       }
       drupal_alter('entity_view_mode_info', $view_modes);
       cache()->set("entity_view_mode_info:$langcode", $view_modes, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
@@ -704,7 +701,7 @@ function entity_get_render_display(EntityInterface $entity, $view_mode) {
   // configuration of the view mode for this bundle, this will be either the
   // display associated to the view mode, or the 'default' display.
   $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
-  $render_view_mode = !empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default';
+  $render_view_mode = !empty($view_mode_settings[$view_mode]['status']) ? $view_mode : 'default';
 
   $display = entity_get_display($entity_type, $bundle, $render_view_mode);
   $display->originalViewMode = $view_mode;
diff --git a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml
new file mode 100644
index 000000000000..ebacec5a62ad
--- /dev/null
+++ b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml
@@ -0,0 +1,4 @@
+id: custom_block.full
+label: Full
+status: '0'
+targetEntityType: custom_block
diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module
index e674f7b343f9..99738b39af4c 100644
--- a/core/modules/block/custom_block/custom_block.module
+++ b/core/modules/block/custom_block/custom_block.module
@@ -185,16 +185,6 @@ function custom_block_entity_bundle_info() {
   return $bundles;
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function custom_block_entity_view_mode_info() {
-  $view_modes['custom_block']['full'] = array(
-    'label' => t('Full'),
-  );
-  return $view_modes;
-}
-
 /**
  * Adds the default body field to a custom block type.
  *
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 887f95f19b81..3ac47f427bd2 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -255,17 +255,6 @@ function book_admin_paths() {
   }
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function book_entity_view_mode_info() {
-  // Add the 'Print' view mode for nodes.
-  $view_modes['node']['print'] = array(
-    'label' => t('Print'),
-  );
-  return $view_modes;
-}
-
 /**
  * Returns an array of all books.
  *
diff --git a/core/modules/book/config/entity.view_mode.node.print.yml b/core/modules/book/config/entity.view_mode.node.print.yml
new file mode 100644
index 000000000000..fe45f505b8f8
--- /dev/null
+++ b/core/modules/book/config/entity.view_mode.node.print.yml
@@ -0,0 +1,4 @@
+id: node.print
+label: Print
+status: '0'
+targetEntityType: node
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index ba2acb720337..717a25b25d59 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -97,16 +97,6 @@ function comment_help($path, $arg) {
   }
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function comment_entity_view_mode_info() {
-  $view_modes['comment']['full'] = array(
-    'label' => t('Full comment'),
-  );
-  return $view_modes;
-}
-
 /**
  * Implements hook_entity_bundle_info().
  */
diff --git a/core/modules/comment/config/entity.view_mode.comment.full.yml b/core/modules/comment/config/entity.view_mode.comment.full.yml
new file mode 100644
index 000000000000..e48fbd764229
--- /dev/null
+++ b/core/modules/comment/config/entity.view_mode.comment.full.yml
@@ -0,0 +1,4 @@
+id: comment.full
+label: Full comment
+status: '0'
+targetEntityType: comment
diff --git a/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php b/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php
new file mode 100644
index 000000000000..718479ff771d
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\EntityViewModeInterface.
+ */
+
+namespace Drupal\entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+
+/**
+ * Provides an interface defining an entity view mode entity.
+ */
+interface EntityViewModeInterface extends ConfigEntityInterface {
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php b/core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php
new file mode 100644
index 000000000000..495f0c9c796e
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\EntityViewModeStorageController.
+ */
+
+namespace Drupal\entity;
+
+use Drupal\Core\Config\Entity\ConfigStorageController;
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Defines the storage controller class for entity view modes.
+ */
+class EntityViewModeStorageController extends ConfigStorageController {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function preSave(EntityInterface $view_mode) {
+    entity_info_cache_clear();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function preDelete($view_modes) {
+    entity_info_cache_clear();
+  }
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php
new file mode 100644
index 000000000000..c2c54dd916b3
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Plugin\Core\Entity\EntityViewMode.
+ */
+
+namespace Drupal\entity\Plugin\Core\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\Annotation\EntityType;
+use Drupal\Core\Annotation\Translation;
+use Drupal\entity\EntityViewModeInterface;
+
+/**
+ * Defines the view mode configuration entity class.
+ *
+ * View modes let entities be displayed differently depending on the context.
+ * For instance, a node can be displayed differently on its own page ('full'
+ * mode), on the home page or taxonomy listings ('teaser' mode), or in an RSS
+ * feed ('rss' mode). Modules taking part in the display of the entity (notably
+ * the Field API) can adjust their behavior depending on the requested view
+ * mode. An additional 'default' view mode is available for all entity types.
+ * This view mode is not intended for actual entity display, but holds default
+ * display settings. For each available view mode, administrators can configure
+ * whether it should use its own set of field display settings, or just
+ * replicate the settings of the 'default' view mode, thus reducing the amount
+ * of display configurations to keep track of.
+ *
+ * @see entity_get_view_modes()
+ * @see hook_entity_view_mode_info_alter()
+ *
+ * @EntityType(
+ *   id = "view_mode",
+ *   label = @Translation("View mode"),
+ *   module = "entity",
+ *   controllers = {
+ *     "storage" = "Drupal\entity\EntityViewModeStorageController"
+ *   },
+ *   config_prefix = "entity.view_mode",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class EntityViewMode extends ConfigEntityBase implements EntityViewModeInterface {
+
+  /**
+   * The ID of the view mode.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The UUID of the view mode.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The human-readable name of the view mode.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The entity type this view mode is used for.
+   *
+   * This is not to be confused with EntityViewMode::entityType which is
+   * inherited from Entity::entityType and equals 'view_mode' for any view mode
+   * entity.
+   *
+   * @var string
+   */
+  public $targetEntityType;
+
+  /**
+   * Whether or not this view mode has custom settings by default.
+   *
+   * If FALSE, entities displayed in this view mode will reuse the 'default'
+   * display settings by default (e.g. right after the module exposing the view
+   * mode is enabled), but administrators can later use the Field UI to apply
+   * custom display settings specific to the view mode.
+   *
+   * @var bool
+   */
+  public $status = FALSE;
+
+}
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 7660f5744541..2cb7679b6004 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -574,9 +574,9 @@ function _field_sort_items_value_helper($a, $b) {
  *   elements:
  *   - view_modes: An associative array keyed by view mode, with the following
  *     key/value pairs:
- *     - custom_settings: Boolean specifying whether the view mode uses a
- *       dedicated set of display options (TRUE), or the 'default' options
- *       (FALSE). Defaults to FALSE.
+ *     - status: Boolean specifying whether the view mode uses a dedicated set
+ *       of display options (TRUE), or the 'default' options (FALSE). Defaults
+ *       to FALSE.
  *   - extra_fields: An associative array containing the form and display
  *     settings for extra fields (also known as pseudo-fields):
  *     - form: An associative array whose keys are the names of extra fields,
@@ -623,9 +623,9 @@ function field_bundle_settings($entity_type, $bundle, $settings = NULL) {
  *
  * @return
  *   An array keyed by view mode, with the following key/value pairs:
- *   - custom_settings: Boolean specifying whether the view mode uses a
- *     dedicated set of display options (TRUE), or the 'default' options
- *     (FALSE). Defaults to FALSE.
+ *   - status: Boolean specifying whether the view mode uses a dedicated set of
+ *     display options (TRUE), or the 'default' options (FALSE). Defaults to
+ *     FALSE.
  */
 function field_view_mode_settings($entity_type, $bundle) {
   $cache = &drupal_static(__FUNCTION__, array());
@@ -638,8 +638,8 @@ function field_view_mode_settings($entity_type, $bundle) {
     // settings by default.
     $view_modes = entity_get_view_modes($entity_type);
     foreach ($view_modes as $view_mode => $view_mode_info) {
-      if (!isset($settings[$view_mode]['custom_settings']) && $view_mode_info['custom_settings']) {
-        $settings[$view_mode]['custom_settings'] = TRUE;
+      if (!isset($settings[$view_mode]['status']) && $view_mode_info['status']) {
+        $settings[$view_mode]['status'] = TRUE;
       }
     }
     $cache[$entity_type][$bundle] = $settings;
diff --git a/core/modules/field/tests/modules/field_test/field_test.entity.inc b/core/modules/field/tests/modules/field_test/field_test.entity.inc
index d5b5e57ab8db..32f20b34c1bd 100644
--- a/core/modules/field/tests/modules/field_test/field_test.entity.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.entity.inc
@@ -38,11 +38,11 @@ function field_test_entity_view_mode_info_alter(&$view_modes) {
       $view_modes[$entity_type] = array(
         'full' => array(
           'label' => t('Full object'),
-          'custom_settings' => TRUE,
+          'status' => TRUE,
         ),
         'teaser' => array(
           'label' => t('Teaser'),
-          'custom_settings' => TRUE,
+          'status' => TRUE,
         ),
       );
     }
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index 88d2ce7090c0..cce8734cc7ff 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -1,9 +1,12 @@
 <?php
+
 /**
  * @file
  * Allows administrators to attach custom fields to fieldable types.
  */
 
+use Drupal\entity\EntityViewModeInterface;
+
 /**
  * Implements hook_help().
  */
@@ -347,3 +350,17 @@ function field_ui_library_info() {
 
   return $libraries;
 }
+
+/**
+ * Implements hook_view_mode_presave().
+ */
+function field_ui_view_mode_presave(EntityViewModeInterface $view_mode) {
+  state()->set('menu_rebuild_needed', TRUE);
+}
+
+/**
+ * Implements hook_view_mode_delete().
+ */
+function field_ui_view_mode_delete(EntityViewModeInterface $view_mode) {
+  state()->set('menu_rebuild_needed', TRUE);
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php
index 640ae847d4c6..1ddb8b5922d3 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php
@@ -32,7 +32,7 @@ public function access(Route $route, Request $request) {
       $view_mode = $request->attributes->get('view_mode');
 
       $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
-      $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['custom_settings']);
+      $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['status']);
       if ($visibility) {
         $permission = $route->getRequirement('_field_ui_view_mode_access');
         return user_access($permission);
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
index cf4f6dec9814..f8c440b96b53 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -361,7 +361,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle);
         foreach ($view_modes as $view_mode_name => $view_mode_info) {
           $options[$view_mode_name] = $view_mode_info['label'];
-          if (!empty($view_mode_settings[$view_mode_name]['custom_settings'])) {
+          if (!empty($view_mode_settings[$view_mode_name]['status'])) {
             $default[] = $view_mode_name;
           }
         }
@@ -476,7 +476,7 @@ public function submitForm(array &$form, array &$form_state) {
       $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle);
 
       foreach ($form_values['view_modes_custom'] as $view_mode => $value) {
-        if (!empty($value) && empty($view_mode_settings[$view_mode]['custom_settings'])) {
+        if (!empty($value) && empty($view_mode_settings[$view_mode]['status'])) {
           // If no display exists for the newly enabled view mode, initialize
           // it with those from the 'default' view mode, which were used so
           // far.
@@ -489,7 +489,7 @@ public function submitForm(array &$form, array &$form_state) {
           $path = $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/display/$view_mode";
           drupal_set_message(t('The %view_mode mode now uses custom display settings. You might want to <a href="@url">configure them</a>.', array('%view_mode' => $view_mode_label, '@url' => url($path))));
         }
-        $bundle_settings['view_modes'][$view_mode]['custom_settings'] = !empty($value);
+        $bundle_settings['view_modes'][$view_mode]['status'] = !empty($value);
       }
 
       // Save updated bundle settings.
diff --git a/core/modules/file/config/entity.view_mode.file.full.yml b/core/modules/file/config/entity.view_mode.file.full.yml
new file mode 100644
index 000000000000..60808f9ea899
--- /dev/null
+++ b/core/modules/file/config/entity.view_mode.file.full.yml
@@ -0,0 +1,4 @@
+id: file.full
+label: File default
+status: '0'
+targetEntityType: file
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 79b63ef9abf5..18dae26ca997 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -90,16 +90,6 @@ function file_element_info() {
   return $types;
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function file_entity_view_mode_info() {
-  $view_modes['file']['full'] = array(
-    'label' => t('File default'),
-  );
-  return $view_modes;
-}
-
 /**
  * Loads file entities from the database.
  *
diff --git a/core/modules/node/config/entity.view_mode.node.full.yml b/core/modules/node/config/entity.view_mode.node.full.yml
new file mode 100644
index 000000000000..af6d938b1b85
--- /dev/null
+++ b/core/modules/node/config/entity.view_mode.node.full.yml
@@ -0,0 +1,4 @@
+id: node.full
+label: Full content
+status: '0'
+targetEntityType: node
diff --git a/core/modules/node/config/entity.view_mode.node.rss.yml b/core/modules/node/config/entity.view_mode.node.rss.yml
new file mode 100644
index 000000000000..984b05fbec63
--- /dev/null
+++ b/core/modules/node/config/entity.view_mode.node.rss.yml
@@ -0,0 +1,4 @@
+id: node.rss
+label: RSS
+status: '0'
+targetEntityType: node
diff --git a/core/modules/node/config/entity.view_mode.node.teaser.yml b/core/modules/node/config/entity.view_mode.node.teaser.yml
new file mode 100644
index 000000000000..2089b94199cf
--- /dev/null
+++ b/core/modules/node/config/entity.view_mode.node.teaser.yml
@@ -0,0 +1,4 @@
+id: node.teaser
+label: Teaser
+status: '1'
+targetEntityType: node
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 183bdd832ab0..ae25bb197e0d 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -180,33 +180,6 @@ function node_theme() {
   );
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function node_entity_view_mode_info() {
-  $view_modes['node']['full'] = array(
-    'label' => t('Full content'),
-  );
-  $view_modes['node']['teaser'] = array(
-    'label' => t('Teaser'),
-    'custom_settings' => TRUE,
-  );
-  $view_modes['node']['rss'] = array(
-    'label' => t('RSS'),
-  );
-  // Search integration is provided by node.module, so search-related
-  // view modes for nodes are defined here and not in search.module.
-  if (module_exists('search')) {
-    $view_modes['node']['search_index'] = array(
-      'label' => t('Search index'),
-    );
-    $view_modes['node']['search_result'] = array(
-      'label' => t('Search result'),
-    );
-  }
-  return $view_modes;
-}
-
 /**
  * Implements hook_entity_bundle_info().
  */
diff --git a/core/modules/search/config/entity.view_mode.node.search_index.yml b/core/modules/search/config/entity.view_mode.node.search_index.yml
new file mode 100644
index 000000000000..ed22c30962a4
--- /dev/null
+++ b/core/modules/search/config/entity.view_mode.node.search_index.yml
@@ -0,0 +1,4 @@
+id: node.search_index
+label: Search index
+status: '0'
+targetEntityType: node
diff --git a/core/modules/search/config/entity.view_mode.node.search_result.yml b/core/modules/search/config/entity.view_mode.node.search_result.yml
new file mode 100644
index 000000000000..1608657df63a
--- /dev/null
+++ b/core/modules/search/config/entity.view_mode.node.search_result.yml
@@ -0,0 +1,4 @@
+id: node.search_result
+label: Search result
+status: '0'
+targetEntityType: node
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilledStandardUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilledStandardUpgradePathTest.php
index 9fe332866aff..33f790310de9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilledStandardUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilledStandardUpgradePathTest.php
@@ -99,6 +99,13 @@ public function testFilledStandardUpgrade() {
     $this->assertEqual($blog_type->module, 'node', "Content type 'blog' has been reassigned from the blog module to the node module.");
     $this->assertEqual($blog_type->base, 'node_content', "The base string used to construct callbacks corresponding to content type 'Blog' has been reassigned to 'node_content'.");
 
+    // Each entity type has a 'full' view mode, ensure it was migrated.
+    $all_view_modes = entity_get_view_modes();
+    $this->assertTrue(!empty($all_view_modes), 'The view modes have been migrated.');
+    foreach ($all_view_modes as $entity_view_modes) {
+      $this->assertTrue(isset($entity_view_modes['full']));
+    }
+
     // Check that user data has been migrated correctly.
     $query = db_query('SELECT * FROM {users_data}');
 
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 2a6f76cc2474..c3a9cda61964 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2141,6 +2141,57 @@ function system_update_8055() {
   }
 }
 
+/**
+ * Moves entity view modes to config.
+ *
+ * @ingroup config_upgrade
+ */
+function system_update_8056() {
+  // We cannot call entity_get_info() in an update hook, so we hardcode the view
+  // modes. Only the node entity type's teaser view mode is set to custom by
+  // default, we check specifically for that below. The only way to add custom
+  // view modes in Drupal 7 was hook_entity_info_alter(), which still works in
+  // Drupal 8.
+  $entity_view_modes = array(
+    'node' => array(
+      'full' => 'Full content',
+      'teaser' => 'Teaser',
+      'rss' => 'RSS',
+      'search_index' => 'Search index',
+      'search_result' => 'Search result',
+      'print' => 'Print',
+    ),
+    'file' => array(
+      'full' => 'File default',
+    ),
+    'comment' => array(
+      'full' => 'Full comment',
+    ),
+    'user' => array(
+      'full' => 'User account',
+      'compact' => 'Compact',
+    ),
+    'taxonomy_term' => array(
+      'full' => 'Taxonomy term page',
+    ),
+    'taxonomy_vocabulary' => array(
+      'full' => 'Taxonomy vocabulary',
+    ),
+  );
+
+  foreach ($entity_view_modes as $entity_type => $view_modes) {
+    foreach ($view_modes as $key => $name) {
+      $status = in_array($key, array('teaser', 'compact'));
+      config("entity.view_mode.$entity_type.$key")
+        ->set('id', "$entity_type.$key")
+        ->set('label', $name)
+        ->set('targetEntityType', $entity_type)
+        ->set('status', $status)
+        ->save();
+    }
+  }
+}
+
 /**
  * @} End of "defgroup updates-7.x-to-8.x".
  * The next series of updates should start at 9000.
diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml
new file mode 100644
index 000000000000..8902bc3c2094
--- /dev/null
+++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml
@@ -0,0 +1,4 @@
+id: entity_test_render.full
+label: Full
+status: '0'
+targetEntityType: entity_test_render
diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml
new file mode 100644
index 000000000000..a0d108bb1237
--- /dev/null
+++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml
@@ -0,0 +1,4 @@
+id: entity_test_render.test
+label: Test
+status: '0'
+targetEntityType: entity_test_render
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 673ab6714df1..07707382adb0 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -338,20 +338,6 @@ function entity_test_label_callback($entity_type, $entity, $langcode = NULL) {
   return 'label callback ' . $entity->name->value;
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function entity_test_entity_view_mode_info() {
-  $view_modes['entity_test_render']['full'] = array(
-    'label' => t('Full'),
-  );
-  $view_modes['entity_test_render']['test'] = array(
-    'label' => t('Test'),
-  );
-
-  return $view_modes;
-}
-
 /**
  * Implements hook_entity_field_access().
  *
diff --git a/core/modules/system/tests/upgrade/drupal-7.field.database.php b/core/modules/system/tests/upgrade/drupal-7.field.database.php
index 9434c7cf8cb7..48950aac6387 100644
--- a/core/modules/system/tests/upgrade/drupal-7.field.database.php
+++ b/core/modules/system/tests/upgrade/drupal-7.field.database.php
@@ -12,19 +12,19 @@
 $value = array(
   'view_modes' => array(
     'teaser' => array(
-      'custom_settings' => 1,
+      'status' => 1,
     ),
     'full' => array(
-      'custom_settings' => 0,
+      'status' => 0,
     ),
     'rss' => array(
-      'custom_settings' => 0,
+      'status' => 0,
     ),
     'search_index' => array(
-      'custom_settings' => 0,
+      'status' => 0,
     ),
     'search_result' => array(
-      'custom_settings' => 0,
+      'status' => 0,
     ),
   ),
   'extra_fields' => array(
diff --git a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml
new file mode 100644
index 000000000000..100547ebc268
--- /dev/null
+++ b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml
@@ -0,0 +1,4 @@
+id: taxonomy_term.full
+label: Taxonomy term page
+status: '0'
+targetEntityType: taxonomy_term
diff --git a/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml b/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml
new file mode 100644
index 000000000000..bb470917676d
--- /dev/null
+++ b/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml
@@ -0,0 +1,4 @@
+id: vocabulary.full
+label: Taxonomy vocabulary
+status: '0'
+targetEntityType: taxonomy_vocabulary
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 419e0baf11b4..2557008a3bc4 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -105,19 +105,6 @@ function taxonomy_permission() {
   return $permissions;
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function taxonomy_entity_view_mode_info() {
-  $view_modes['taxonomy_term']['full'] = array(
-    'label' => t('Taxonomy term page'),
-  );
-  $view_modes['taxonomy_vocabulary']['full'] = array(
-    'label' => t('Taxonomy vocabulary'),
-  );
-  return $view_modes;
-}
-
 /**
  * Implements hook_entity_bundle_info().
  */
diff --git a/core/modules/user/config/entity.view_mode.user.compact.yml b/core/modules/user/config/entity.view_mode.user.compact.yml
new file mode 100644
index 000000000000..c27265b188d2
--- /dev/null
+++ b/core/modules/user/config/entity.view_mode.user.compact.yml
@@ -0,0 +1,4 @@
+id: user.compact
+label: Compact
+status: '1'
+targetEntityType: user
diff --git a/core/modules/user/config/entity.view_mode.user.full.yml b/core/modules/user/config/entity.view_mode.user.full.yml
new file mode 100644
index 000000000000..ac1ca2005cdb
--- /dev/null
+++ b/core/modules/user/config/entity.view_mode.user.full.yml
@@ -0,0 +1,4 @@
+id: user.full
+label: User account
+status: '0'
+targetEntityType: user
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 3ae6154a7805..67c31188d854 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -121,20 +121,6 @@ function user_page_build(&$page) {
   $page['#attached']['css'][$path . '/user.css'] = array('every_page' => TRUE);
 }
 
-/**
- * Implements hook_entity_view_mode_info().
- */
-function user_entity_view_mode_info() {
-  $view_modes['user']['full'] = array(
-    'label' => t('User account'),
-  );
-  $view_modes['user']['compact'] = array(
-    'label' => t('Compact'),
-    'custom_settings' => TRUE,
-  );
-  return $view_modes;
-}
-
 /**
  * Implements hook_entity_bundle_info().
  */
-- 
GitLab