From f8f024e3aaef1d29bc489f05e36c1ccbc394fbc6 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 4 May 2015 17:22:30 -0700
Subject: [PATCH] Issue #2030637 by yched, Mile23, daffie, Alumei, tidrif,
 chertzog, Berdir, swentel, ofry: Expand
 FieldConfig/BaseFieldOverride/FieldConfigBase with methods

---
 core/lib/Drupal/Core/Entity/EntityManager.php |  4 +-
 .../lib/Drupal/Core/Field/FieldConfigBase.php | 86 +++++++++++++------
 .../Core/Field/FieldConfigInterface.php       | 62 +++++++++++--
 core/lib/Drupal/Core/Field/FieldItemBase.php  |  1 -
 core/lib/Drupal/Core/Field/FieldItemList.php  |  7 +-
 core/modules/comment/comment.module           |  2 +-
 .../src/Tests/CommentCacheTagsTest.php        |  2 +-
 .../src/Tests/CommentFieldAccessTest.php      |  2 +-
 .../comment/src/Tests/CommentTestBase.php     |  4 +-
 .../src/Tests/CommentValidationTest.php       |  2 +-
 .../src/Tests/ConfigExportImportUITest.php    |  2 +-
 .../content_translation.module                |  2 +-
 .../datetime/src/Tests/DateTimeFieldTest.php  | 14 +--
 .../entity_reference/entity_reference.module  |  4 +-
 core/modules/field/field.module               |  4 +-
 core/modules/field/src/Entity/FieldConfig.php |  2 +-
 .../src/FieldConfigAccessControlHandler.php   |  4 +-
 core/modules/field/src/FieldConfigStorage.php |  6 +-
 .../field/src/Tests/BulkDeleteTest.php        |  6 +-
 .../EntityReferenceItemTest.php               |  2 +-
 .../field/src/Tests/FieldAttachOtherTest.php  | 12 +--
 .../src/Tests/FieldAttachStorageTest.php      | 16 ++--
 .../modules/field/src/Tests/FieldCrudTest.php | 14 +--
 .../field/src/Tests/FieldImportCreateTest.php |  4 +-
 .../field/src/Tests/FieldStorageCrudTest.php  |  6 +-
 core/modules/field/src/Tests/FormTest.php     |  4 +-
 .../field/src/Tests/TranslationTest.php       |  6 +-
 .../field_ui/src/FieldConfigListBuilder.php   | 10 +--
 .../src/Form/FieldConfigDeleteForm.php        |  6 +-
 .../field_ui/src/Form/FieldConfigEditForm.php |  8 +-
 .../field_ui/src/Tests/ManageFieldsTest.php   |  2 +-
 .../file/src/Tests/FileFieldTestBase.php      |  2 +-
 .../file/src/Tests/FileFieldWidgetTest.php    |  7 +-
 core/modules/image/image.module               | 19 ++--
 .../src/Tests/ImageFieldDefaultImagesTest.php | 14 +--
 .../image/src/Tests/ImageFieldDisplayTest.php |  2 +-
 .../src/Tests/ImageFieldValidateTest.php      | 10 +--
 core/modules/link/src/Tests/LinkFieldTest.php |  6 +-
 .../options/src/Tests/OptionsWidgetsTest.php  | 10 +--
 .../search/src/Tests/SearchCommentTest.php    |  4 +-
 core/modules/taxonomy/src/Tests/TermTest.php  |  4 +-
 .../src/Tests/UserEntityReferenceTest.php     |  6 +-
 42 files changed, 240 insertions(+), 150 deletions(-)

diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 888fe410e40d..ae6009d3f6b8 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -1213,8 +1213,8 @@ public function onBundleRename($bundle_old, $bundle_new, $entity_type_id) {
     // Rename existing base field bundle overrides.
     $overrides = $this->getStorage('base_field_override')->loadByProperties(array('entity_type' => $entity_type_id, 'bundle' => $bundle_old));
     foreach ($overrides as $override) {
-      $override->set('id', $entity_type_id . '.' . $bundle_new . '.' . $override->field_name);
-      $override->bundle = $bundle_new;
+      $override->set('id', $entity_type_id . '.' . $bundle_new . '.' . $override->getName());
+      $override->set('bundle', $bundle_new);
       $override->allowBundleRename();
       $override->save();
     }
diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php
index 1f462414fa60..fa34ca3b2ff9 100644
--- a/core/lib/Drupal/Core/Field/FieldConfigBase.php
+++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php
@@ -28,14 +28,14 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var string
    */
-  public $id;
+  protected $id;
 
   /**
    * The field name.
    *
    * @var string
    */
-  public $field_name;
+  protected $field_name;
 
   /**
    * The field type.
@@ -48,21 +48,21 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var string
    */
-  public $field_type;
+  protected $field_type;
 
   /**
    * The name of the entity type the field is attached to.
    *
    * @var string
    */
-  public $entity_type;
+  protected $entity_type;
 
   /**
    * The name of the bundle the field is attached to.
    *
    * @var string
    */
-  public $bundle;
+  protected $bundle;
 
   /**
    * The human-readable label for the field.
@@ -75,7 +75,7 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var string
    */
-  public $label;
+  protected $label;
 
   /**
    * The field description.
@@ -86,7 +86,7 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var string
    */
-  public $description = '';
+  protected $description = '';
 
   /**
    * Field-type specific settings.
@@ -96,7 +96,7 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var array
    */
-  public $settings = array();
+  protected $settings = array();
 
   /**
    * Flag indicating whether the field is required.
@@ -107,7 +107,7 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var bool
    */
-  public $required = FALSE;
+  protected $required = FALSE;
 
   /**
    * Flag indicating whether the field is translatable.
@@ -116,7 +116,7 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var bool
    */
-  public $translatable = TRUE;
+  protected $translatable = TRUE;
 
   /**
    * Default field value.
@@ -164,7 +164,7 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
    *
    * @var string
    */
-  public $default_value_callback = '';
+  protected $default_value_callback = '';
 
   /**
    * The field storage object.
@@ -302,20 +302,31 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
   /**
    * {@inheritdoc}
    */
-  public function getSettings() {
-    return $this->settings + $this->getFieldStorageDefinition()->getSettings();
+  public function getLabel() {
+    return $this->label();
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getSetting($setting_name) {
-    if (array_key_exists($setting_name, $this->settings)) {
-      return $this->settings[$setting_name];
-    }
-    else {
-      return $this->getFieldStorageDefinition()->getSetting($setting_name);
-    }
+  public function setLabel($label) {
+    $this->label = $label;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->description;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setDescription($description) {
+    $this->description = $description;
+    return $this;
   }
 
   /**
@@ -337,23 +348,35 @@ public function setTranslatable($translatable) {
   /**
    * {@inheritdoc}
    */
-  public function setLabel($label) {
-    $this->label = $label;
+  public function getSettings() {
+    return $this->settings + $this->getFieldStorageDefinition()->getSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setSettings(array $settings) {
+    $this->settings = $settings;
     return $this;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getLabel() {
-    return $this->label();
+  public function getSetting($setting_name) {
+    if (array_key_exists($setting_name, $this->settings)) {
+      return $this->settings[$setting_name];
+    }
+    else {
+      return $this->getFieldStorageDefinition()->getSetting($setting_name);
+    }
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getDescription() {
-    return $this->description;
+  public function setSetting($setting_name, $value) {
+    $this->settings[$setting_name] = $value;
   }
 
   /**
@@ -363,6 +386,14 @@ public function isRequired() {
     return $this->required;
   }
 
+  /**
+   * [@inheritdoc}
+   */
+  public function setRequired($required) {
+    $this->required = $required;
+    return $this;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -420,6 +451,9 @@ public static function createFromDataType($type) {
     return BaseFieldDefinition::createFromDataType($type);
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function getDataType() {
     return 'list';
   }
diff --git a/core/lib/Drupal/Core/Field/FieldConfigInterface.php b/core/lib/Drupal/Core/Field/FieldConfigInterface.php
index f9c0267d7f6a..11da0dfb7b88 100644
--- a/core/lib/Drupal/Core/Field/FieldConfigInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldConfigInterface.php
@@ -31,6 +31,19 @@ interface FieldConfigInterface extends FieldDefinitionInterface, ConfigEntityInt
    */
   public function setLabel($label);
 
+  /**
+   * Sets a human readable description.
+   *
+   * Descriptions are usually used on user interfaces where the data is edited
+   * or displayed.
+   *
+   * @param string $description
+   *   The description for this field.
+   *
+   * @return $this
+   */
+  public function setDescription($description);
+
   /**
    * Sets whether the field is translatable.
    *
@@ -42,13 +55,43 @@ public function setLabel($label);
   public function setTranslatable($translatable);
 
   /**
-   * Allows a bundle to be renamed.
+   * Sets field settings (overwrites existing settings).
    *
-   * Renaming a bundle on the instance is allowed when an entity's bundle
-   * is renamed and when field_entity_bundle_rename() does internal
-   * housekeeping.
+   * @param array $settings
+   *   The array of field settings.
+   *
+   * @return $this
    */
-  public function allowBundleRename();
+  public function setSettings(array $settings);
+
+  /**
+   * Sets the value for a field setting by name.
+   *
+   * @param string $setting_name
+   *   The name of the setting.
+   * @param mixed $value
+   *   The value of the setting.
+   *
+   * @return $this
+   */
+  public function setSetting($setting_name, $value);
+
+  /**
+   * Sets whether the field can be empty.
+   *
+   * If a field is required, an entity needs to have at least a valid,
+   * non-empty item in that field's FieldItemList in order to pass validation.
+   *
+   * An item is considered empty if its isEmpty() method returns TRUE.
+   * Typically, that is if at least one of its required properties is empty.
+   *
+   * @param bool $required
+   *   TRUE if the field is required. FALSE otherwise.
+   *
+   * @return $this
+   *   The current object, for a fluent interface.
+   */
+  public function setRequired($required);
 
   /**
    * Sets a default value.
@@ -191,4 +234,13 @@ public function addConstraint($constraint_name, $options = NULL);
    */
   public function setConstraints(array $constraints);
 
+  /**
+   * Allows a bundle to be renamed.
+   *
+   * Renaming a bundle on the instance is allowed when an entity's bundle
+   * is renamed and when field_entity_bundle_rename() does internal
+   * housekeeping.
+   */
+  public function allowBundleRename();
+
 }
diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php
index 1bb5486c41a3..fd521a9ec7c5 100644
--- a/core/lib/Drupal/Core/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Field/FieldItemBase.php
@@ -12,7 +12,6 @@
 use Drupal\Core\TypedData\DataDefinitionInterface;
 use Drupal\Core\TypedData\Plugin\DataType\Map;
 use Drupal\Core\TypedData\TypedDataInterface;
-use Drupal\user;
 
 /**
  * An entity field item.
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 37dad2a1f5de..aa10c6f50a53 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -314,7 +314,7 @@ public function defaultValuesFormValidate(array $element, array &$form, FormStat
     $widget->extractFormValues($this, $element, $form_state);
     // Force a non-required field definition.
     // @see self::defaultValueWidget().
-    $this->definition->required = FALSE;
+    $this->getFieldDefinition()->setRequired(FALSE);
     $violations = $this->validate();
 
     // Assign reported errors to the correct form element.
@@ -354,8 +354,9 @@ protected function defaultValueWidget(FormStateInterface $form_state) {
       $entity = $this->getEntity();
 
       // Force a non-required widget.
-      $this->getFieldDefinition()->required = FALSE;
-      $this->getFieldDefinition()->description = '';
+      $definition = $this->getFieldDefinition();
+      $definition->setRequired(FALSE);
+      $definition->setDescription('');
 
       // Use the widget currently configured for the 'default' form mode, or
       // fallback to the default widget for the field type.
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index debc2d3e9ae5..103f71dbac90 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -144,7 +144,7 @@ function comment_field_config_create(FieldConfigInterface $field) {
   if ($field->getType() == 'comment' && !$field->isSyncing()) {
     // Assign default values for the field.
     if (!isset($field->default_value)) {
-      $field->default_value = array();
+      $field->setDefaultValue(array());
     }
     $field->default_value += array(array());
     $field->default_value[0] += array(
diff --git a/core/modules/comment/src/Tests/CommentCacheTagsTest.php b/core/modules/comment/src/Tests/CommentCacheTagsTest.php
index 04e0848b9bab..52264340fd71 100644
--- a/core/modules/comment/src/Tests/CommentCacheTagsTest.php
+++ b/core/modules/comment/src/Tests/CommentCacheTagsTest.php
@@ -54,7 +54,7 @@ protected function createEntity() {
 
     // Display comments in a flat list; threaded comments are not render cached.
     $field = FieldConfig::loadByName('entity_test', 'bar', 'comment');
-    $field->settings['default_mode'] = CommentManagerInterface::COMMENT_MODE_FLAT;
+    $field->setSetting('default_mode', CommentManagerInterface::COMMENT_MODE_FLAT);
     $field->save();
 
     // Create a "Camelids" test entity.
diff --git a/core/modules/comment/src/Tests/CommentFieldAccessTest.php b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
index 654d1b0d3f4a..bd08dfea59ae 100644
--- a/core/modules/comment/src/Tests/CommentFieldAccessTest.php
+++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
@@ -136,7 +136,7 @@ public function testAccessToAdministrativeFields() {
     // Change the second field's anonymous contact setting.
     $instance = FieldConfig::loadByName('entity_test', 'entity_test', 'comment_other');
     // Default is 'May not contact', for this field - they may contact.
-    $instance->settings['anonymous'] = COMMENT_ANONYMOUS_MAY_CONTACT;
+    $instance->setSetting('anonymous', COMMENT_ANONYMOUS_MAY_CONTACT);
     $instance->save();
 
     // Create three "Comments". One is owned by our edit-enabled user.
diff --git a/core/modules/comment/src/Tests/CommentTestBase.php b/core/modules/comment/src/Tests/CommentTestBase.php
index ecc999a63e29..8ebc4e7dd0db 100644
--- a/core/modules/comment/src/Tests/CommentTestBase.php
+++ b/core/modules/comment/src/Tests/CommentTestBase.php
@@ -117,7 +117,7 @@ public function postComment($entity, $comment, $subject = '', $contact = NULL, $
     else {
       $field = FieldConfig::loadByName('node', 'article', $field_name);
     }
-    $preview_mode = $field->settings['preview'];
+    $preview_mode = $field->getSetting('preview');
 
     // Must get the page before we test for fields.
     if ($entity !== NULL) {
@@ -314,7 +314,7 @@ public function setCommentsPerPage($number, $field_name = 'comment') {
    */
   public function setCommentSettings($name, $value, $message, $field_name = 'comment') {
     $field = FieldConfig::loadByName('node', 'article', $field_name);
-    $field->settings[$name] = $value;
+    $field->setSetting($name, $value);
     $field->save();
     // Display status message.
     $this->pass($message);
diff --git a/core/modules/comment/src/Tests/CommentValidationTest.php b/core/modules/comment/src/Tests/CommentValidationTest.php
index d3567f6ff3f2..79b949764e04 100644
--- a/core/modules/comment/src/Tests/CommentValidationTest.php
+++ b/core/modules/comment/src/Tests/CommentValidationTest.php
@@ -139,7 +139,7 @@ public function testValidation() {
     $comment->set('thread', NULL);
 
     // Force anonymous users to enter contact details.
-    $field->settings['anonymous'] = COMMENT_ANONYMOUS_MUST_CONTACT;
+    $field->setSetting('anonymous', COMMENT_ANONYMOUS_MUST_CONTACT);
     $field->save();
     // Reset the node entity.
     \Drupal::entityManager()->getStorage('node')->resetCache([$node->id()]);
diff --git a/core/modules/config/src/Tests/ConfigExportImportUITest.php b/core/modules/config/src/Tests/ConfigExportImportUITest.php
index 668b28703a67..3adc1a23b3cd 100644
--- a/core/modules/config/src/Tests/ConfigExportImportUITest.php
+++ b/core/modules/config/src/Tests/ConfigExportImportUITest.php
@@ -150,7 +150,7 @@ public function testExportImport() {
     // Delete the custom field.
     $fields = FieldConfig::loadMultiple();
     foreach ($fields as $field) {
-      if ($field->field_name == $this->fieldName) {
+      if ($field->getName() == $this->fieldName) {
         $field->delete();
       }
     }
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 2751862d7751..82a866b3944d 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -330,7 +330,7 @@ function content_translation_entity_extra_field_info() {
  */
 function content_translation_form_field_config_edit_form_alter(array &$form, FormStateInterface $form_state) {
   $field = $form_state->getFormObject()->getEntity();
-  $bundle_is_translatable = \Drupal::service('content_translation.manager')->isEnabled($field->entity_type, $field->bundle);
+  $bundle_is_translatable = \Drupal::service('content_translation.manager')->isEnabled($field->getTargetEntityTypeId(), $field->getTargetBundle());
 
   $form['translatable'] = array(
     '#type' => 'checkbox',
diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
index e2223dc016c7..f3fcae182a3b 100644
--- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php
+++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
@@ -75,7 +75,7 @@ protected function setUp() {
     ));
     $this->field->save();
 
-    entity_get_form_display($this->field->entity_type, $this->field->bundle, 'default')
+    entity_get_form_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'default')
       ->setComponent($field_name, array(
         'type' => 'datetime_default',
       ))
@@ -86,7 +86,7 @@ protected function setUp() {
       'label' => 'hidden',
       'settings' => array('format_type' => 'medium'),
     );
-    entity_get_display($this->field->entity_type, $this->field->bundle, 'full')
+    entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
       ->setComponent($field_name, $this->displayOptions)
       ->save();
   }
@@ -130,7 +130,7 @@ function testDateField() {
       foreach ($values as $new_value) {
         // Update the entity display settings.
         $this->displayOptions['settings'] = array($setting => $new_value);
-        entity_get_display($this->field->entity_type, $this->field->bundle, 'full')
+        entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
           ->setComponent($field_name, $this->displayOptions)
           ->save();
 
@@ -149,7 +149,7 @@ function testDateField() {
     // Verify that the plain formatter works.
     $this->displayOptions['type'] = 'datetime_plain';
     $this->displayOptions['settings'] = array();
-    entity_get_display($this->field->entity_type, $this->field->bundle, 'full')
+    entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
       ->setComponent($field_name, $this->displayOptions)
       ->save();
     $expected = $date->format(DATETIME_DATE_STORAGE_FORMAT);
@@ -196,7 +196,7 @@ function testDatetimeField() {
       foreach ($values as $new_value) {
         // Update the entity display settings.
         $this->displayOptions['settings'] = array($setting => $new_value);
-        entity_get_display($this->field->entity_type, $this->field->bundle, 'full')
+        entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
           ->setComponent($field_name, $this->displayOptions)
           ->save();
 
@@ -215,7 +215,7 @@ function testDatetimeField() {
     // Verify that the plain formatter works.
     $this->displayOptions['type'] = 'datetime_plain';
     $this->displayOptions['settings'] = array();
-    entity_get_display($this->field->entity_type, $this->field->bundle, 'full')
+    entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
       ->setComponent($field_name, $this->displayOptions)
       ->save();
     $expected = $date->format(DATETIME_DATETIME_STORAGE_FORMAT);
@@ -233,7 +233,7 @@ function testDatelistWidget() {
     $this->fieldStorage->save();
 
     // Change the widget to a datelist widget.
-    entity_get_form_display($this->field->entity_type, $this->field->bundle, 'default')
+    entity_get_form_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'default')
       ->setComponent($field_name, array(
         'type' => 'datetime_datelist',
         'settings' => array(
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 4ffa3c465c47..650f519c1005 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -95,7 +95,7 @@ function entity_reference_field_storage_config_update(FieldStorageConfigInterfac
 
   foreach ($field_storage->getBundles() as $bundle) {
     $field = FieldConfig::loadByName($field_storage->getTargetEntityTypeId(), $bundle, $field_storage->getName());
-    $field->settings['handler_settings'] = array();
+    $field->setSetting('handler_settings', []);
     $field->save();
   }
 }
@@ -119,7 +119,7 @@ function entity_reference_field_config_presave(FieldConfigInterface $field) {
   $target_type = $field->getFieldStorageDefinition()->getSetting('target_type');
   $selection_manager = \Drupal::service('plugin.manager.entity_reference_selection');
   list($current_handler) = explode(':', $field->getSetting('handler'), 2);
-  $field->settings['handler'] = $selection_manager->getPluginId($target_type, $current_handler);
+  $field->setSetting('handler', $selection_manager->getPluginId($target_type, $current_handler));
 }
 
 /**
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 91ec6b9dc172..a0074923e0f8 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -227,9 +227,9 @@ function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundl
 function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
   $fields = entity_load_multiple_by_properties('field_config', array('entity_type' => $entity_type, 'bundle' => $bundle_old, 'include_deleted' => TRUE));
   foreach ($fields as $field) {
-    $id_new = $field->entity_type . '.' . $bundle_new . '.' . $field->field_name;
+    $id_new = $field->getTargetEntityTypeId() . '.' . $bundle_new . '.' . $field->getName();
     $field->set('id', $id_new);
-    $field->bundle = $bundle_new;
+    $field->set('bundle', $bundle_new);
     // Save non-deleted fields.
     if (!$field->isDeleted()) {
       $field->allowBundleRename();
diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php
index d7f2dd0a3ebf..ad5127bf15e1 100644
--- a/core/modules/field/src/Entity/FieldConfig.php
+++ b/core/modules/field/src/Entity/FieldConfig.php
@@ -46,7 +46,7 @@ class FieldConfig extends FieldConfigBase implements FieldConfigInterface {
    *
    * @var bool
    */
-  public $deleted = FALSE;
+  protected $deleted = FALSE;
 
   /**
    * The associated FieldStorageConfig entity.
diff --git a/core/modules/field/src/FieldConfigAccessControlHandler.php b/core/modules/field/src/FieldConfigAccessControlHandler.php
index c4087651bdd4..1edcb0fe021f 100644
--- a/core/modules/field/src/FieldConfigAccessControlHandler.php
+++ b/core/modules/field/src/FieldConfigAccessControlHandler.php
@@ -29,10 +29,10 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
         return AccessResult::forbidden()->cacheUntilEntityChanges($field_storage_entity);
       }
       else {
-        return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->entity_type . ' fields')->cacheUntilEntityChanges($field_storage_entity);
+        return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields')->cacheUntilEntityChanges($field_storage_entity);
       }
     }
-    return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->entity_type . ' fields');
+    return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields');
   }
 
 }
diff --git a/core/modules/field/src/FieldConfigStorage.php b/core/modules/field/src/FieldConfigStorage.php
index 89ea1818c3dd..bb6a25769b76 100644
--- a/core/modules/field/src/FieldConfigStorage.php
+++ b/core/modules/field/src/FieldConfigStorage.php
@@ -158,8 +158,12 @@ public function loadByProperties(array $conditions = array()) {
             $checked_value = $field->uuid();
             break;
 
+          case 'deleted';
+            $checked_value = $field->isDeleted();
+            break;
+
           default:
-            $checked_value = $field->$key;
+            $checked_value = $field->get($key);
             break;
         }
 
diff --git a/core/modules/field/src/Tests/BulkDeleteTest.php b/core/modules/field/src/Tests/BulkDeleteTest.php
index de49be1d5e87..85fcdb827a60 100644
--- a/core/modules/field/src/Tests/BulkDeleteTest.php
+++ b/core/modules/field/src/Tests/BulkDeleteTest.php
@@ -179,7 +179,7 @@ function testDeleteField() {
     $fields = entity_load_multiple_by_properties('field_config', array('field_storage_uuid' => $field_storage->uuid(), 'deleted' => TRUE, 'include_deleted' => TRUE));
     $this->assertEqual(count($fields), 1, 'There is one deleted field');
     $field = $fields[$field->uuid()];
-    $this->assertEqual($field->bundle, $bundle, 'The deleted field is for the correct bundle');
+    $this->assertEqual($field->getTargetBundle(), $bundle, 'The deleted field is for the correct bundle');
 
     // Check that the actual stored content did not change during delete.
     $storage = \Drupal::entityManager()->getStorage($this->entityTypeId);
@@ -309,7 +309,7 @@ function testPurgeFieldStorage() {
 
     // The field still exists, deleted.
     $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid(), 'include_deleted' => TRUE));
-    $this->assertTrue(isset($fields[$field->uuid()]) && $fields[$field->uuid()]->deleted, 'The field exists and is deleted');
+    $this->assertTrue(isset($fields[$field->uuid()]) && $fields[$field->uuid()]->isDeleted(), 'The field exists and is deleted');
 
     // Purge again to purge the field.
     field_purge_batch(0);
@@ -344,7 +344,7 @@ function testPurgeFieldStorage() {
 
     // The field and the storage still exist, deleted.
     $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid(), 'include_deleted' => TRUE));
-    $this->assertTrue(isset($fields[$field->uuid()]) && $fields[$field->uuid()]->deleted, 'The field exists and is deleted');
+    $this->assertTrue(isset($fields[$field->uuid()]) && $fields[$field->uuid()]->isDeleted(), 'The field exists and is deleted');
     $storages = entity_load_multiple_by_properties('field_storage_config', array('uuid' => $field_storage->uuid(), 'include_deleted' => TRUE));
     $this->assertTrue(isset($storages[$field_storage->uuid()]) && $storages[$field_storage->uuid()]->isDeleted(), 'The field storage exists and is deleted');
 
diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php
index 859551dbbda6..e75f33aaaf9e 100644
--- a/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php
+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php
@@ -246,7 +246,7 @@ public function testSelectionHandlerSettings() {
     $field = FieldConfig::load($field->id());
     $this->assertTrue($field->getSetting('handler') == 'default:entity_test');
 
-    $field->settings['handler'] = 'views';
+    $field->setSetting('handler', 'views');
     $field->save();
     $field = FieldConfig::load($field->id());
     $this->assertTrue($field->getSetting('handler') == 'views');
diff --git a/core/modules/field/src/Tests/FieldAttachOtherTest.php b/core/modules/field/src/Tests/FieldAttachOtherTest.php
index af92af7bc6e9..e13c39e3aa59 100644
--- a/core/modules/field/src/Tests/FieldAttachOtherTest.php
+++ b/core/modules/field/src/Tests/FieldAttachOtherTest.php
@@ -165,7 +165,7 @@ function testEntityDisplayViewMultiple() {
    */
   function testEntityCache() {
     // Initialize random values and a test entity.
-    $entity_init = entity_create('entity_test', array('type' => $this->fieldTestData->field->bundle));
+    $entity_init = entity_create('entity_test', array('type' => $this->fieldTestData->field->getTargetBundle()));
     $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
 
     // Non-cacheable entity type.
@@ -248,10 +248,10 @@ function testEntityFormDisplayBuildForm() {
     $this->createFieldWithStorage('_2');
 
     $entity_type = 'entity_test';
-    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->bundle));
+    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()));
 
     // Test generating widgets for all fields.
-    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->bundle, 'default');
+    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
     $form = array();
     $form_state = new FormState();
     $display->buildForm($entity, $form, $form_state);
@@ -268,7 +268,7 @@ function testEntityFormDisplayBuildForm() {
     }
 
     // Test generating widgets for all fields.
-    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->bundle, 'default');
+    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
     foreach ($display->getComponents() as $name => $options) {
       if ($name != $this->fieldTestData->field_name_2) {
         $display->removeComponent($name);
@@ -293,10 +293,10 @@ function testEntityFormDisplayExtractFormValues() {
     $this->createFieldWithStorage('_2');
 
     $entity_type = 'entity_test';
-    $entity_init = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->bundle));
+    $entity_init = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()));
 
     // Build the form for all fields.
-    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->bundle, 'default');
+    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
     $form = array();
     $form_state = new FormState();
     $display->buildForm($entity_init, $form, $form_state);
diff --git a/core/modules/field/src/Tests/FieldAttachStorageTest.php b/core/modules/field/src/Tests/FieldAttachStorageTest.php
index f51ce1df0485..77c7bacfe9a0 100644
--- a/core/modules/field/src/Tests/FieldAttachStorageTest.php
+++ b/core/modules/field/src/Tests/FieldAttachStorageTest.php
@@ -195,7 +195,7 @@ function testFieldAttachSaveEmptyDataDefaultValue() {
     $this->createFieldWithStorage('', $entity_type);
 
     // Add a default value function.
-    $this->fieldTestData->field->default_value_callback = 'field_test_default_value';
+    $this->fieldTestData->field->set('default_value_callback', 'field_test_default_value');
     $this->fieldTestData->field->save();
 
     // Verify that fields are populated with default values.
@@ -223,7 +223,7 @@ function testFieldAttachDelete() {
     $entity_type = 'entity_test_rev';
     $this->createFieldWithStorage('', $entity_type);
     $cardinality = $this->fieldTestData->field_storage->getCardinality();
-    $entity = entity_create($entity_type, array('type' => $this->fieldTestData->field->bundle));
+    $entity = entity_create($entity_type, array('type' => $this->fieldTestData->field->getTargetBundle()));
     $vids = array();
 
     // Create revision 0
@@ -291,7 +291,7 @@ function testEntityCreateRenameBundle() {
     entity_create('field_config', $this->fieldTestData->field_definition)->save();
 
     // Save an entity with data in the field.
-    $entity = entity_create($entity_type, array('type' => $this->fieldTestData->field->bundle));
+    $entity = entity_create($entity_type, array('type' => $this->fieldTestData->field->getTargetBundle()));
     $values = $this->_generateTestFieldValues($cardinality);
     $entity->{$this->fieldTestData->field_name} = $values;
 
@@ -305,7 +305,7 @@ function testEntityCreateRenameBundle() {
 
     // Check that the field definition has been updated.
     $this->fieldTestData->field = FieldConfig::loadByName($entity_type, $new_bundle, $this->fieldTestData->field_name);
-    $this->assertIdentical($this->fieldTestData->field->bundle, $new_bundle, "Bundle name has been updated in the field.");
+    $this->assertIdentical($this->fieldTestData->field->getTargetBundle(), $new_bundle, "Bundle name has been updated in the field.");
 
     // Verify the field data is present on load.
     $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId());
@@ -341,7 +341,7 @@ function testEntityDeleteBundle() {
     $field = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
-      'bundle' => $this->fieldTestData->field->bundle,
+      'bundle' => $this->fieldTestData->field->getTargetBundle(),
       'label' => $this->randomMachineName() . '_label',
       'description' => $this->randomMachineName() . '_description',
       'weight' => mt_rand(0, 127),
@@ -349,7 +349,7 @@ function testEntityDeleteBundle() {
     entity_create('field_config', $field)->save();
 
     // Save an entity with data for both fields
-    $entity = entity_create($entity_type, array('type' => $this->fieldTestData->field->bundle));
+    $entity = entity_create($entity_type, array('type' => $this->fieldTestData->field->getTargetBundle()));
     $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
     $entity->{$this->fieldTestData->field_name} = $values;
     $entity->{$field_name} = $this->_generateTestFieldValues(1);
@@ -360,7 +360,7 @@ function testEntityDeleteBundle() {
     $this->assertEqual(count($entity->{$field_name}), 1, 'Second field got loaded');
 
     // Delete the bundle.
-    entity_test_delete_bundle($this->fieldTestData->field->bundle, $entity_type);
+    entity_test_delete_bundle($this->fieldTestData->field->getTargetBundle(), $entity_type);
 
     // Verify no data gets loaded
     $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId());
@@ -371,7 +371,7 @@ function testEntityDeleteBundle() {
     $this->assertTrue(empty($entity->{$field_name}), 'No data for second field');
 
     // Verify that the fields are gone.
-    $this->assertFalse(FieldConfig::load('entity_test.' . $this->fieldTestData->field->bundle . '.' . $this->fieldTestData->field_name), "First field is deleted");
+    $this->assertFalse(FieldConfig::load('entity_test.' . $this->fieldTestData->field->getTargetBundle() . '.' . $this->fieldTestData->field_name), "First field is deleted");
     $this->assertFalse(FieldConfig::load('entity_test.' . $field['bundle']. '.' . $field_name), "Second field is deleted");
   }
 
diff --git a/core/modules/field/src/Tests/FieldCrudTest.php b/core/modules/field/src/Tests/FieldCrudTest.php
index 66d727c43737..5dd60e3072e9 100644
--- a/core/modules/field/src/Tests/FieldCrudTest.php
+++ b/core/modules/field/src/Tests/FieldCrudTest.php
@@ -146,8 +146,8 @@ function testReadField() {
     // Read the field back.
     $field = FieldConfig::load('entity_test.' . $this->fieldDefinition['bundle'] . '.' . $this->fieldDefinition['field_name']);
     $this->assertTrue($this->fieldDefinition['field_name'] == $field->getName(), 'The field was properly read.');
-    $this->assertTrue($this->fieldDefinition['entity_type'] == $field->entity_type, 'The field was properly read.');
-    $this->assertTrue($this->fieldDefinition['bundle'] == $field->bundle, 'The field was properly read.');
+    $this->assertTrue($this->fieldDefinition['entity_type'] == $field->getTargetEntityTypeId(), 'The field was properly read.');
+    $this->assertTrue($this->fieldDefinition['bundle'] == $field->getTargetBundle(), 'The field was properly read.');
   }
 
   /**
@@ -158,10 +158,10 @@ function testUpdateField() {
 
     // Check that basic changes are saved.
     $field = FieldConfig::load('entity_test.' . $this->fieldDefinition['bundle'] . '.' . $this->fieldDefinition['field_name']);
-    $field->required = !$field->isRequired();
-    $field->label = $this->randomMachineName();
-    $field->description = $this->randomMachineName();
-    $field->settings['test_field_setting'] = $this->randomMachineName();
+    $field->setRequired(!$field->isRequired());
+    $field->setLabel($this->randomMachineName());
+    $field->set('description', $this->randomMachineName());
+    $field->setSetting('test_field_setting', $this->randomMachineName());
     $field->save();
 
     $field_new = FieldConfig::load('entity_test.' . $this->fieldDefinition['bundle'] . '.' . $this->fieldDefinition['field_name']);
@@ -195,7 +195,7 @@ function testDeleteField() {
 
     // Make sure the field is marked as deleted when it is specifically loaded.
     $field = current(entity_load_multiple_by_properties('field_config', array('entity_type' => 'entity_test', 'field_name' => $this->fieldDefinition['field_name'], 'bundle' => $this->fieldDefinition['bundle'], 'include_deleted' => TRUE)));
-    $this->assertTrue(!empty($field->deleted), 'A deleted field is marked for deletion.');
+    $this->assertTrue($field->isDeleted(), 'A deleted field is marked for deletion.');
 
     // Try to load the field normally and make sure it does not show up.
     $field = FieldConfig::load('entity_test.' . '.' . $this->fieldDefinition['bundle'] . '.' . $this->fieldDefinition['field_name']);
diff --git a/core/modules/field/src/Tests/FieldImportCreateTest.php b/core/modules/field/src/Tests/FieldImportCreateTest.php
index 7d56a7f54d81..0d465660b331 100644
--- a/core/modules/field/src/Tests/FieldImportCreateTest.php
+++ b/core/modules/field/src/Tests/FieldImportCreateTest.php
@@ -53,8 +53,8 @@ function testImportCreateDefault() {
     // A field storage with two fields.
     $field_storage_2 = FieldStorageConfig::load($field_storage_id_2);
     $this->assertTrue($field_storage_2, 'The second field was created.');
-    $this->assertTrue($field->bundle, 'test_bundle', 'The second field was created on bundle test_bundle.');
-    $this->assertTrue($field->bundle, 'test_bundle_2', 'The second field was created on bundle test_bundle_2.');
+    $this->assertTrue($field->getTargetBundle(), 'test_bundle', 'The second field was created on bundle test_bundle.');
+    $this->assertTrue($field->getTargetBundle(), 'test_bundle_2', 'The second field was created on bundle test_bundle_2.');
 
     // Tests fields.
     $ids = \Drupal::entityQuery('field_config')
diff --git a/core/modules/field/src/Tests/FieldStorageCrudTest.php b/core/modules/field/src/Tests/FieldStorageCrudTest.php
index ac9f60179417..8912783e2b19 100644
--- a/core/modules/field/src/Tests/FieldStorageCrudTest.php
+++ b/core/modules/field/src/Tests/FieldStorageCrudTest.php
@@ -329,7 +329,7 @@ function testDelete() {
     // Make sure that this field is marked as deleted when it is
     // specifically loaded.
     $field = current(entity_load_multiple_by_properties('field_config', array('entity_type' => 'entity_test', 'field_name' => $field_definition['field_name'], 'bundle' => $field_definition['bundle'], 'include_deleted' => TRUE)));
-    $this->assertTrue(!empty($field->deleted), 'A field whose storage was deleted is marked for deletion.');
+    $this->assertTrue($field->isDeleted(), 'A field whose storage was deleted is marked for deletion.');
 
     // Try to load the storage normally and make sure it does not show up.
     $field_storage = FieldStorageConfig::load('entity_test.' . $field_storage_definition['field_name']);
@@ -343,7 +343,7 @@ function testDelete() {
     $another_field_storage = FieldStorageConfig::load('entity_test.' . $another_field_storage_definition['field_name']);
     $this->assertTrue(!empty($another_field_storage) && !$another_field_storage->isDeleted(), 'A non-deleted storage is not marked for deletion.');
     $another_field = FieldConfig::load('entity_test.' . $another_field_definition['bundle'] . '.' . $another_field_definition['field_name']);
-    $this->assertTrue(!empty($another_field) && empty($another_field->deleted), 'A field whose storage was not deleted is not marked for deletion.');
+    $this->assertTrue(!empty($another_field) && !$another_field->isDeleted(), 'A field whose storage was not deleted is not marked for deletion.');
 
     // Try to create a new field the same name as a deleted field and
     // write data into it.
@@ -352,7 +352,7 @@ function testDelete() {
     $field_storage = FieldStorageConfig::load('entity_test.' . $field_storage_definition['field_name']);
     $this->assertTrue(!empty($field_storage) && !$field_storage->isDeleted(), 'A new storage with a previously used name is created.');
     $field = FieldConfig::load('entity_test.' . $field_definition['bundle'] . '.' . $field_definition['field_name'] );
-    $this->assertTrue(!empty($field) && empty($field->deleted), 'A new field for a previously used field name is created.');
+    $this->assertTrue(!empty($field) && !$field->isDeleted(), 'A new field for a previously used field name is created.');
 
     // Save an entity with data for the field
     $entity = entity_create('entity_test');
diff --git a/core/modules/field/src/Tests/FormTest.php b/core/modules/field/src/Tests/FormTest.php
index 4d242f208b6b..dc2d7a97c4ca 100644
--- a/core/modules/field/src/Tests/FormTest.php
+++ b/core/modules/field/src/Tests/FormTest.php
@@ -589,7 +589,7 @@ function testHiddenField() {
     // widget.
     $this->field->default_value = array();
     $this->field->save();
-    entity_get_form_display($entity_type, $this->field->bundle, 'default')
+    entity_get_form_display($entity_type, $this->field->getTargetBundle(), 'default')
       ->setComponent($this->field->getName(), array(
         'type' => 'test_field_widget',
       ))
@@ -609,7 +609,7 @@ function testHiddenField() {
     $this->assertEqual($entity->{$field_name}->value, $value, 'Field value was updated');
 
     // Set the field back to hidden.
-    entity_get_form_display($entity_type, $this->field->bundle, 'default')
+    entity_get_form_display($entity_type, $this->field->getTargetBundle(), 'default')
       ->removeComponent($this->field->getName())
       ->save();
 
diff --git a/core/modules/field/src/Tests/TranslationTest.php b/core/modules/field/src/Tests/TranslationTest.php
index 870c664e1313..2b9e30c91259 100644
--- a/core/modules/field/src/Tests/TranslationTest.php
+++ b/core/modules/field/src/Tests/TranslationTest.php
@@ -118,7 +118,7 @@ function testTranslatableFieldSaveLoad() {
     // Prepare the field translations.
     $entity_type_id = 'entity_test';
     field_test_entity_info_translatable($entity_type_id, TRUE);
-    $entity = entity_create($entity_type_id, array('type' => $this->field->bundle));
+    $entity = entity_create($entity_type_id, array('type' => $this->field->getTargetBundle()));
     $field_translations = array();
     $available_langcodes = array_keys($this->container->get('language_manager')->getLanguages());
     $entity->langcode->value = reset($available_langcodes);
@@ -156,7 +156,7 @@ function testTranslatableFieldSaveLoad() {
     asort($translation_langcodes);
     $translation_langcodes = array_values($translation_langcodes);
 
-    $values = array('type' => $field->bundle, 'langcode' => $translation_langcodes[0]);
+    $values = array('type' => $field->getTargetBundle(), 'langcode' => $translation_langcodes[0]);
     $entity = entity_create($entity_type_id, $values);
     foreach ($translation_langcodes as $langcode) {
       $values[$this->fieldName][$langcode] = $this->_generateTestFieldValues($this->fieldStorage->getCardinality());
@@ -174,7 +174,7 @@ function testTranslatableFieldSaveLoad() {
 
     // Check that explicit empty values are not overridden with default values.
     foreach (array(NULL, array()) as $empty_items) {
-      $values = array('type' => $field->bundle, 'langcode' => $translation_langcodes[0]);
+      $values = array('type' => $field->getTargetBundle(), 'langcode' => $translation_langcodes[0]);
       $entity = entity_create($entity_type_id, $values);
       foreach ($translation_langcodes as $langcode) {
         $values[$this->fieldName][$langcode] = $this->_generateTestFieldValues($this->fieldStorage->getCardinality());
diff --git a/core/modules/field_ui/src/FieldConfigListBuilder.php b/core/modules/field_ui/src/FieldConfigListBuilder.php
index fe59dd603a9e..ed8d9f413a36 100644
--- a/core/modules/field_ui/src/FieldConfigListBuilder.php
+++ b/core/modules/field_ui/src/FieldConfigListBuilder.php
@@ -164,18 +164,18 @@ public function getDefaultOperations(EntityInterface $entity) {
     /** @var \Drupal\field\FieldConfigInterface $entity */
     $operations = parent::getDefaultOperations($entity);
 
-    if ($entity->access('update') && $entity->hasLinkTemplate("{$entity->entity_type}-field-edit-form")) {
+    if ($entity->access('update') && $entity->hasLinkTemplate("{$entity->getTargetEntityTypeId()}-field-edit-form")) {
       $operations['edit'] = array(
         'title' => $this->t('Edit'),
         'weight' => 10,
-        'url' => $entity->urlInfo("{$entity->entity_type}-field-edit-form"),
+        'url' => $entity->urlInfo("{$entity->getTargetEntityTypeId()}-field-edit-form"),
       );
     }
-    if ($entity->access('delete') && $entity->hasLinkTemplate("{$entity->entity_type}-field-delete-form")) {
+    if ($entity->access('delete') && $entity->hasLinkTemplate("{$entity->getTargetEntityTypeId()}-field-delete-form")) {
       $operations['delete'] = array(
         'title' => $this->t('Delete'),
         'weight' => 100,
-        'url' => $entity->urlInfo("{$entity->entity_type}-field-delete-form"),
+        'url' => $entity->urlInfo("{$entity->getTargetEntityTypeId()}-field-delete-form"),
       );
     }
 
@@ -183,7 +183,7 @@ public function getDefaultOperations(EntityInterface $entity) {
       'title' => $this->t('Storage settings'),
       'weight' => 20,
       'attributes' => array('title' => $this->t('Edit storage settings.')),
-      'url' => $entity->urlInfo("{$entity->entity_type}-storage-edit-form"),
+      'url' => $entity->urlInfo("{$entity->getTargetEntityTypeId()}-storage-edit-form"),
     );
     $operations['edit']['attributes']['title'] = $this->t('Edit field settings.');
     $operations['delete']['attributes']['title'] = $this->t('Delete field.');
diff --git a/core/modules/field_ui/src/Form/FieldConfigDeleteForm.php b/core/modules/field_ui/src/Form/FieldConfigDeleteForm.php
index 5baa57d16bec..2aacd8859660 100644
--- a/core/modules/field_ui/src/Form/FieldConfigDeleteForm.php
+++ b/core/modules/field_ui/src/Form/FieldConfigDeleteForm.php
@@ -48,7 +48,7 @@ public static function create(ContainerInterface $container) {
    * {@inheritdoc}
    */
   public function getCancelUrl() {
-    return FieldUI::getOverviewRouteInfo($this->entity->entity_type, $this->entity->bundle);
+    return FieldUI::getOverviewRouteInfo($this->entity->getTargetEntityTypeId(), $this->entity->getTargetBundle());
   }
 
   /**
@@ -56,8 +56,8 @@ public function getCancelUrl() {
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
     $field_storage = $this->entity->getFieldStorageDefinition();
-    $bundles = $this->entityManager->getBundleInfo($this->entity->entity_type);
-    $bundle_label = $bundles[$this->entity->bundle]['label'];
+    $bundles = $this->entityManager->getBundleInfo($this->entity->getTargetEntityTypeId());
+    $bundle_label = $bundles[$this->entity->getTargetBundle()]['label'];
 
     if ($field_storage && !$field_storage->isLocked()) {
       $this->entity->delete();
diff --git a/core/modules/field_ui/src/Form/FieldConfigEditForm.php b/core/modules/field_ui/src/Form/FieldConfigEditForm.php
index 8a3cd54e0a29..866ff9a48ab6 100644
--- a/core/modules/field_ui/src/Form/FieldConfigEditForm.php
+++ b/core/modules/field_ui/src/Form/FieldConfigEditForm.php
@@ -40,7 +40,7 @@ public function form(array $form, FormStateInterface $form_state) {
 
     $form_title = $this->t('%field settings for %bundle', array(
       '%field' => $this->entity->getLabel(),
-      '%bundle' => $bundles[$this->entity->bundle]['label'],
+      '%bundle' => $bundles[$this->entity->getTargetBundle()]['label'],
     ));
     $form['#title'] = $form_title;
 
@@ -79,7 +79,7 @@ public function form(array $form, FormStateInterface $form_state) {
     // Create an arbitrary entity object (used by the 'default value' widget).
     $ids = (object) array(
       'entity_type' => $this->entity->getTargetEntityTypeId(),
-      'bundle' => $this->entity->bundle,
+      'bundle' => $this->entity->getTargetBundle(),
       'entity_id' => NULL
     );
     $form['#entity'] = _field_create_entity_from_ids($ids);
@@ -125,7 +125,7 @@ protected function actions(array $form, FormStateInterface $form_state) {
       $target_entity_type = $this->entityManager->getDefinition($this->entity->getTargetEntityTypeId());
       $route_parameters = [
         'field_config' => $this->entity->id(),
-      ] + FieldUI::getRouteBundleParameter($target_entity_type, $this->entity->bundle);
+      ] + FieldUI::getRouteBundleParameter($target_entity_type, $this->entity->getTargetBundle());
       $url = new Url('entity.field_config.' . $target_entity_type->id() . '_field_delete_form', $route_parameters);
 
       if ($this->getRequest()->query->has('destination')) {
@@ -188,7 +188,7 @@ public function save(array $form, FormStateInterface $form_state) {
       $form_state->setRedirectUrl($next_destination);
     }
     else {
-      $form_state->setRedirectUrl(FieldUI::getOverviewRouteInfo($this->entity->getTargetEntityTypeId(), $this->entity->bundle));
+      $form_state->setRedirectUrl(FieldUI::getOverviewRouteInfo($this->entity->getTargetEntityTypeId(), $this->entity->getTargetBundle()));
     }
   }
 
diff --git a/core/modules/field_ui/src/Tests/ManageFieldsTest.php b/core/modules/field_ui/src/Tests/ManageFieldsTest.php
index 83c573546b3a..b4acad494c9f 100644
--- a/core/modules/field_ui/src/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/src/Tests/ManageFieldsTest.php
@@ -427,7 +427,7 @@ function testDefaultValue() {
     $this->assertEqual($field->default_value, NULL, 'The default value was correctly saved.');
 
     // Check that the default widget is used when the field is hidden.
-    entity_get_form_display($field->entity_type, $field->bundle, 'default')
+    entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
       ->removeComponent($field_name)->save();
     $this->drupalGet($admin_path);
     $this->assertFieldById($element_id, '', 'The default value widget was displayed when field is hidden.');
diff --git a/core/modules/file/src/Tests/FileFieldTestBase.php b/core/modules/file/src/Tests/FileFieldTestBase.php
index 25ef7f281e21..e0da957d1339 100644
--- a/core/modules/file/src/Tests/FileFieldTestBase.php
+++ b/core/modules/file/src/Tests/FileFieldTestBase.php
@@ -133,7 +133,7 @@ function attachFileField($name, $entity_type, $bundle, $field_settings = array()
    */
   function updateFileField($name, $type_name, $field_settings = array(), $widget_settings = array()) {
     $field = FieldConfig::loadByName('node', $type_name, $name);
-    $field->settings = array_merge($field->settings, $field_settings);
+    $field->setSettings(array_merge($field->getSettings(), $field_settings));
     $field->save();
 
     entity_get_form_display('node', $type_name, 'default')
diff --git a/core/modules/file/src/Tests/FileFieldWidgetTest.php b/core/modules/file/src/Tests/FileFieldWidgetTest.php
index 5cd74b81c6b6..ec02bb4795d6 100644
--- a/core/modules/file/src/Tests/FileFieldWidgetTest.php
+++ b/core/modules/file/src/Tests/FileFieldWidgetTest.php
@@ -228,12 +228,13 @@ function testPrivateFileSetting() {
     $field_name = strtolower($this->randomMachineName());
     $this->createFileField($field_name, 'node', $type_name);
     $field = FieldConfig::loadByName('node', $type_name, $field_name);
+    $field_id = $field->id();
 
     $test_file = $this->getTestFile('text');
 
     // Change the field setting to make its files private, and upload a file.
     $edit = array('settings[uri_scheme]' => 'private');
-    $this->drupalPostForm("admin/structure/types/manage/$type_name/fields/$field->id/storage", $edit, t('Save field settings'));
+    $this->drupalPostForm("admin/structure/types/manage/$type_name/fields/$field_id/storage", $edit, t('Save field settings'));
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
     $node_storage->resetCache(array($nid));
     $node = $node_storage->load($nid);
@@ -246,12 +247,12 @@ function testPrivateFileSetting() {
 
     // Ensure we can't change 'uri_scheme' field settings while there are some
     // entities with uploaded files.
-    $this->drupalGet("admin/structure/types/manage/$type_name/fields/$field->id/storage");
+    $this->drupalGet("admin/structure/types/manage/$type_name/fields/$field_id/storage");
     $this->assertFieldByXpath('//input[@id="edit-settings-uri-scheme-public" and @disabled="disabled"]', 'public', 'Upload destination setting disabled.');
 
     // Delete node and confirm that setting could be changed.
     $node->delete();
-    $this->drupalGet("admin/structure/types/manage/$type_name/fields/$field->id/storage");
+    $this->drupalGet("admin/structure/types/manage/$type_name/fields/$field_id/storage");
     $this->assertFieldByXpath('//input[@id="edit-settings-uri-scheme-public" and not(@disabled)]', 'public', 'Upload destination setting enabled.');
   }
 
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 2e8697311e16..6074a4ba7b71 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -7,7 +7,6 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\field\Entity\FieldConfig;
 use Drupal\file\Entity\File;
 use Drupal\field\FieldStorageConfigInterface;
 use Drupal\field\FieldConfigInterface;
@@ -330,6 +329,7 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
 function image_entity_presave(EntityInterface $entity) {
   // Get the default image settings, return if not saving an image field storage
   // or image field entity.
+  $default_image = [];
   if (($entity instanceof FieldStorageConfigInterface || $entity instanceof FieldConfigInterface) && $entity->getType() == 'image') {
     $default_image = $entity->getSetting('default_image');
   }
@@ -356,16 +356,9 @@ function image_entity_presave(EntityInterface $entity) {
       }
     }
   }
-
-  // @todo Simplify this in https://www.drupal.org/node/2030637, when both
-  //   interfaces have a setSetting() method.
-  if ($entity instanceof FieldStorageConfigInterface) {
-    $entity->setSetting('default_image', $default_image);
-  }
-  elseif ($entity instanceof FieldConfig) {
-    $entity->settings['default_image'] = $default_image;
-  }
-
+  // Both FieldStorageConfigInterface and FieldConfigInterface have a
+  // setSetting() method.
+  $entity->setSetting('default_image', $default_image);
 }
 
 /**
@@ -421,7 +414,7 @@ function image_field_config_update(FieldConfigInterface $field) {
   $prior_instance = $field->original;
 
   $uuid_new = $field->getSetting('default_image')['uuid'];
-  $uuid_old = $prior_instance->settings['default_image']['uuid'];
+  $uuid_old = $prior_instance->getSetting('default_image')['uuid'];
 
   // If the old and new files do not match, update the default accordingly.
   $file_new = $uuid_new ? \Drupal::entityManager()->loadEntityByUuid('file', $uuid_new) : FALSE;
@@ -473,7 +466,7 @@ function image_field_config_delete(FieldConfigInterface $field) {
   }
 
   // The value of a managed_file element can be an array if #extended == TRUE.
-  $uuid = $field->settings['default_image']['uuid'];
+  $uuid = $field->getSetting('default_image')['uuid'];
 
   // Remove the default image when the instance is deleted.
   if ($uuid && ($file = \Drupal::entityManager()->loadEntityByUuid('file', $uuid))) {
diff --git a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php
index 90009b852f85..39e0d50d96fe 100644
--- a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php
@@ -69,7 +69,7 @@ public function testDefaultImages() {
     // The field default image id should be 2.
     $this->assertEqual($field->getSetting('default_image')['uuid'], $default_images['field']->uuid());
 
-    // Also test \Drupal\field\Entity\FieldConfig::getSetting().
+    // Also test \Drupal\field\Entity\FieldConfig::getSettings().
     $this->assertEqual($field->getSettings()['default_image']['uuid'], $default_images['field']->uuid());
 
     $field_storage = $field->getFieldStorageDefinition();
@@ -85,7 +85,7 @@ public function testDefaultImages() {
       'field_storage' => $field_storage,
       'bundle' => 'page',
       'label' => $field->label(),
-      'required' => $field->required,
+      'required' => $field->isRequired(),
       'settings' => array(
         'default_image' => array(
           'uuid' => $default_images['field2']->uuid(),
@@ -98,7 +98,7 @@ public function testDefaultImages() {
     ));
     $field2->save();
 
-    $widget_settings = entity_get_form_display('node', $field->bundle, 'default')->getComponent($field_name);
+    $widget_settings = entity_get_form_display('node', $field->getTargetBundle(), 'default')->getComponent($field_name);
     entity_get_form_display('node', 'page', 'default')
       ->setComponent($field_name, $widget_settings)
       ->save();
@@ -213,7 +213,9 @@ public function testDefaultImages() {
     );
 
     // Upload a new default for the article's field field.
-    $field->settings['default_image']['uuid'] = $default_images['field_new']->uuid();
+    $default_image_settings = $field->getSetting('default_image');
+    $default_image_settings['uuid'] = $default_images['field_new']->uuid();
+    $field->setSetting('default_image', $default_image_settings);
     $field->save();
 
     // Confirm the new field field default is used on the article field
@@ -258,7 +260,9 @@ public function testDefaultImages() {
     $this->assertRaw($file->getFilename());
 
     // Remove the instance default from articles.
-    $field->settings['default_image']['uuid'] = 0;
+    $default_image_settings = $field->getSetting('default_image');
+    $default_image_settings['uuid'] = 0;
+    $field->setSetting('default_image', $default_image_settings);
     $field->save();
 
     // Confirm the article field field default has been removed.
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index 2679328610d0..875a2a2d90e7 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -82,7 +82,7 @@ function _testImageFieldFormatters($scheme) {
 
     // After previewing, make the alt field required. It cannot be required
     // during preview because the form validation will fail.
-    $instance->settings['alt_field_required'] = 1;
+    $instance->setSetting('alt_field_required', 1);
     $instance->save();
 
     // Create alt text for the image.
diff --git a/core/modules/image/src/Tests/ImageFieldValidateTest.php b/core/modules/image/src/Tests/ImageFieldValidateTest.php
index fa52d064ac2f..938176a1d0c9 100644
--- a/core/modules/image/src/Tests/ImageFieldValidateTest.php
+++ b/core/modules/image/src/Tests/ImageFieldValidateTest.php
@@ -80,8 +80,8 @@ function testRequiredAttributes() {
     $this->assertText(t('Alternative text field is required.'));
     $this->assertText(t('Title field is required.'));
 
-    $instance->settings['alt_field_required'] = 0;
-    $instance->settings['title_field_required'] = 0;
+    $instance->setSetting('alt_field_required', 0);
+    $instance->setSetting('title_field_required', 0);
     $instance->save();
 
     $edit = array(
@@ -92,9 +92,9 @@ function testRequiredAttributes() {
     $this->assertNoText(t('Alternative text field is required.'));
     $this->assertNoText(t('Title field is required.'));
 
-    $instance->settings['required'] = 0;
-    $instance->settings['alt_field_required'] = 1;
-    $instance->settings['title_field_required'] = 1;
+    $instance->setSetting('required', 0);
+    $instance->setSetting('alt_field_required', 1);
+    $instance->setSetting('title_field_required', 1);
     $instance->save();
 
     $edit = array(
diff --git a/core/modules/link/src/Tests/LinkFieldTest.php b/core/modules/link/src/Tests/LinkFieldTest.php
index 735938d41573..a1cdc6580ffe 100644
--- a/core/modules/link/src/Tests/LinkFieldTest.php
+++ b/core/modules/link/src/Tests/LinkFieldTest.php
@@ -153,13 +153,13 @@ function testURLValidation() {
     $this->assertInvalidEntries($field_name, $invalid_external_entries + $invalid_internal_entries);
 
     // Test external URLs for 'link_type' = LinkItemInterface::LINK_EXTERNAL.
-    $this->field->settings['link_type'] = LinkItemInterface::LINK_EXTERNAL;
+    $this->field->setSetting('link_type', LinkItemInterface::LINK_EXTERNAL);
     $this->field->save();
     $this->assertValidEntries($field_name, $valid_external_entries);
     $this->assertInvalidEntries($field_name, $valid_internal_entries + $invalid_external_entries);
 
     // Test external URLs for 'link_type' = LinkItemInterface::LINK_INTERNAL.
-    $this->field->settings['link_type'] = LinkItemInterface::LINK_INTERNAL;
+    $this->field->setSetting('link_type', LinkItemInterface::LINK_INTERNAL);
     $this->field->save();
     $this->assertValidEntries($field_name, $valid_internal_entries);
     $this->assertInvalidEntries($field_name, $valid_external_entries + $invalid_internal_entries);
@@ -253,7 +253,7 @@ function testLinkTitle() {
     // Verify that the link text field works according to the field setting.
     foreach (array(DRUPAL_DISABLED, DRUPAL_REQUIRED, DRUPAL_OPTIONAL) as $title_setting) {
       // Update the link title field setting.
-      $this->field->settings['title'] = $title_setting;
+      $this->field->setSetting('title', $title_setting);
       $this->field->save();
 
       // Display creation form.
diff --git a/core/modules/options/src/Tests/OptionsWidgetsTest.php b/core/modules/options/src/Tests/OptionsWidgetsTest.php
index cb58e9d96449..56d84187fd06 100644
--- a/core/modules/options/src/Tests/OptionsWidgetsTest.php
+++ b/core/modules/options/src/Tests/OptionsWidgetsTest.php
@@ -134,7 +134,7 @@ function testRadioButtons() {
     // Check that required radios with one option is auto-selected.
     $this->card1->setSetting('allowed_values', [99 => 'Only allowed value']);
     $this->card1->save();
-    $field->required = TRUE;
+    $field->setRequired(TRUE);
     $field->save();
     $this->drupalGet('entity_test/manage/' . $entity->id());
     $this->assertFieldChecked('edit-card-1-99');
@@ -223,7 +223,7 @@ function testCheckBoxes() {
     // Required checkbox with one option is auto-selected.
     $this->card2->setSetting('allowed_values', [99 => 'Only allowed value']);
     $this->card2->save();
-    $field->required = TRUE;
+    $field->setRequired(TRUE);
     $field->save();
     $this->drupalGet('entity_test/manage/' . $entity->id());
     $this->assertFieldChecked('edit-card-2-99');
@@ -285,7 +285,7 @@ function testSelectListSingle() {
     $this->assertNoOptionSelected('edit-card-1', 2);
 
     // Make the field non required.
-    $field->required = FALSE;
+    $field->setRequired(FALSE);
     $field->save();
 
     // Display form.
@@ -407,7 +407,7 @@ function testSelectListMultiple() {
     $this->assertFieldValues($entity_init, 'card_2', array());
 
     // A required select list does not have an empty key.
-    $field->required = TRUE;
+    $field->setRequired(TRUE);
     $field->save();
     $this->drupalGet('entity_test/manage/' . $entity->id());
     $this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-2')), 'A required select list does not have an empty key.');
@@ -421,7 +421,7 @@ function testSelectListMultiple() {
     $this->card2->setSetting('allowed_values', []);
     $this->card2->setSetting('allowed_values_function', 'options_test_allowed_values_callback');
     $this->card2->save();
-    $field->required = FALSE;
+    $field->setRequired(FALSE);
     $field->save();
 
     // Display form: with no field data, nothing is selected.
diff --git a/core/modules/search/src/Tests/SearchCommentTest.php b/core/modules/search/src/Tests/SearchCommentTest.php
index 27e660941a3d..f674a0de0785 100644
--- a/core/modules/search/src/Tests/SearchCommentTest.php
+++ b/core/modules/search/src/Tests/SearchCommentTest.php
@@ -105,7 +105,7 @@ function testSearchResultsComment() {
 
     // Make preview optional.
     $field = FieldConfig::loadByName('node', 'article', 'comment');
-    $field->settings['preview'] = DRUPAL_OPTIONAL;
+    $field->setSetting('preview', DRUPAL_OPTIONAL);
     $field->save();
 
     // Allow anonymous users to search content.
@@ -178,7 +178,7 @@ function testSearchResultsCommentAccess() {
     // Create a node.
     // Make preview optional.
     $field = FieldConfig::loadByName('node', 'article', 'comment');
-    $field->settings['preview'] = DRUPAL_OPTIONAL;
+    $field->setSetting('preview', DRUPAL_OPTIONAL);
     $field->save();
     $this->node = $this->drupalCreateNode(array('type' => 'article'));
 
diff --git a/core/modules/taxonomy/src/Tests/TermTest.php b/core/modules/taxonomy/src/Tests/TermTest.php
index eaa0617cb7da..49c711f7854b 100644
--- a/core/modules/taxonomy/src/Tests/TermTest.php
+++ b/core/modules/taxonomy/src/Tests/TermTest.php
@@ -198,7 +198,7 @@ function testTaxonomyNode() {
   function testNodeTermCreationAndDeletion() {
     // Enable tags in the vocabulary.
     $field = $this->field;
-    entity_get_form_display($field->entity_type, $field->bundle, 'default')
+    entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
       ->setComponent($field->getName(), array(
         'type' => 'entity_reference_autocomplete_tags',
         'settings' => array(
@@ -510,7 +510,7 @@ function testTaxonomyGetTermByName() {
   function testReSavingTags() {
     // Enable tags in the vocabulary.
     $field = $this->field;
-    entity_get_form_display($field->entity_type, $field->bundle, 'default')
+    entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
       ->setComponent($field->getName(), array(
         'type' => 'entity_reference_autocomplete_tags',
       ))
diff --git a/core/modules/user/src/Tests/UserEntityReferenceTest.php b/core/modules/user/src/Tests/UserEntityReferenceTest.php
index 1323fcd636b4..6c8bca84f61f 100644
--- a/core/modules/user/src/Tests/UserEntityReferenceTest.php
+++ b/core/modules/user/src/Tests/UserEntityReferenceTest.php
@@ -67,11 +67,13 @@ protected function setUp() {
    */
   function testUserSelectionByRole() {
     $field_definition = FieldConfig::loadByName('user', 'user', 'user_reference');
-    $field_definition->settings['handler_settings']['filter']['role'] = array(
+    $handler_settings = $field_definition->getSetting('handler_settings');
+    $handler_settings['filter']['role'] = array(
       $this->role1->id() => $this->role1->id(),
       $this->role2->id() => 0,
     );
-    $field_definition->settings['handler_settings']['filter']['type'] = 'role';
+    $handler_settings['filter']['type'] = 'role';
+    $field_definition->setSetting('handler_settings', $handler_settings);
     $field_definition->save();
 
     $user1 = $this->createUser(array('name' => 'aabb'));
-- 
GitLab