From c16fbc5593178333e019957984a0a9ba5843f23f Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Tue, 20 May 2014 10:43:31 +0100
Subject: [PATCH] Issue #2267753 by pwolanin, YesCT, Berdir:
 ContentEntityDatabaseStorage::mapToStorageRecord  hard-codes
 $entity->$name->value.

---
 .../Entity/ContentEntityDatabaseStorage.php   | 23 +++++++++++++++----
 .../Field/Plugin/Field/FieldType/MapItem.php  | 15 ++++++++++++
 core/modules/shortcut/src/Entity/Shortcut.php |  5 ++--
 .../shortcut/src/Tests/ShortcutLinksTest.php  | 14 ++++++++++-
 4 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
index da6890e7a73c..221489420025 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -587,7 +587,7 @@ protected function invokeHook($hook, EntityInterface $entity) {
   /**
    * Maps from an entity object to the storage record.
    *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
    *   The entity object.
    * @param string $table_key
    *   (optional) The entity key identifying the target table. Defaults to
@@ -596,10 +596,9 @@ protected function invokeHook($hook, EntityInterface $entity) {
    * @return \stdClass
    *   The record to store.
    */
-  protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'base_table') {
+  protected function mapToStorageRecord(ContentEntityInterface $entity, $table_key = 'base_table') {
     $record = new \stdClass();
     $values = array();
-    $definitions = $entity->getFieldDefinitions();
     $schema = drupal_get_schema($this->entityType->get($table_key));
     $is_new = $entity->isNew();
 
@@ -611,7 +610,23 @@ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'bas
         $multi_column_fields[$field] = TRUE;
         continue;
       }
-      $values[$name] = isset($definitions[$name]) && isset($entity->$name->value) ? $entity->$name->value : NULL;
+      $values[$name] = NULL;
+      if ($entity->hasField($name)) {
+        // Only the first field item is stored.
+        $field_item = $entity->get($name)->first();
+        $main_property = $entity->getFieldDefinition($name)->getMainPropertyName();
+        if ($main_property && isset($field_item->$main_property)) {
+          // If the field has a main property, store the value of that.
+          $values[$name] = $field_item->$main_property;
+        }
+        elseif (!$main_property) {
+          // If there is no main property, get all properties from the first
+          // field item and assume that they will be stored serialized.
+          // @todo Give field types more control over this behavior in
+          //   https://drupal.org/node/2232427.
+          $values[$name] = $field_item->getValue();
+        }
+      }
     }
 
     // Handle fields that store multiple properties and match each property name
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php
index 4645b833a7b0..5ccc6d29515f 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php
@@ -104,4 +104,19 @@ public function __set($name, $value) {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function mainPropertyName() {
+    // A map item has no main property.
+    return NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    return empty($this->values);
+  }
+
 }
diff --git a/core/modules/shortcut/src/Entity/Shortcut.php b/core/modules/shortcut/src/Entity/Shortcut.php
index 5807c665161c..03be8c8d4c0d 100644
--- a/core/modules/shortcut/src/Entity/Shortcut.php
+++ b/core/modules/shortcut/src/Entity/Shortcut.php
@@ -100,15 +100,14 @@ public function setRouteName($route_name) {
    * {@inheritdoc}
    */
   public function getRouteParams() {
-    $value = $this->get('route_parameters')->getValue();
-    return reset($value);
+    return $this->get('route_parameters')->first()->getValue();
   }
 
   /**
    * {@inheritdoc}
    */
   public function setRouteParams($route_parameters) {
-    $this->set('route_parameters', array('value' => $route_parameters));
+    $this->set('route_parameters', array($route_parameters));
     return $this;
   }
 
diff --git a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
index a713cfcbd8ad..58cb3e4819e3 100644
--- a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
+++ b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\shortcut\Tests\ShortcutLinksTest.
+ * Contains \Drupal\shortcut\Tests\ShortcutLinksTest.
  */
 
 namespace Drupal\shortcut\Tests;
@@ -66,6 +66,18 @@ public function testShortcutLinkAdd() {
       $this->assertTrue(in_array($this->container->get('path.alias_manager')->getPathByAlias($test['path']), $paths), 'Shortcut created: ' . $test['path']);
       $this->assertLink($title, 0, 'Shortcut link found on the page.');
     }
+    $saved_set = shortcut_set_load($set->id());
+    // Test that saving and re-loading a shortcut preserves its values.
+    $shortcuts = $saved_set->getShortcuts();
+    foreach ($shortcuts as $entity) {
+      // Test the node routes with parameters.
+      if (strpos($entity->route_name->value, 'node.') === 0) {
+        $entity->save();
+        $loaded = entity_load('shortcut', $entity->id());
+        $this->assertEqual($entity->route_name->value, $loaded->route_name->value);
+        $this->assertEqual($entity->get('route_parameters')->first()->getValue(), $loaded->get('route_parameters')->first()->getValue());
+      }
+    }
   }
 
   /**
-- 
GitLab