Problem/Motivation

While trying to add a MapItem field to a content entity, a bug becomes evident that loading and saving the entity results in the value of the map becoming NULL.

berdir found the root cause in ContentEntityDatabaseStorage::mapToStorageRecord which hard-codes $entity->$name->value even though the "value" property of a field is not supposed to have a special meaning.

Proposed resolution

use the getMainPropertyName() method of the field definition to find which property to use, or whether (as for MapItem) all properties should be saved.

Remaining tasks

Add tests demonstrating the bug and fix.

API changes

none

Comments

pwolanin’s picture

Status: Active » Needs review
StatusFileSize
new3.35 KB

Here's a 1st patch, largely the work of berdir from the menu links sandbox.

andypost’s picture

Looks good, just a question

+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -612,7 +612,17 @@ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'bas
+        elseif (!$main_property) {
+          // If there is no main property, get all values.
+          $values[$name] = $entity->get($name)->first()->getValue();

Maybe supposed "first value"

fago’s picture

Patch looks good, just one remark:

  1. +++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
    @@ -612,7 +612,17 @@ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'bas
    +        if ($main_property && isset($entity->get($name)->$main_property)) {
    +          $values[$name] = $entity->get($name)->$main_property;
    

    That seems weird, why not just $entity->$name->$main_property ?
    If we go with methods we should probably do for $name and $main_property.

fago’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -612,7 +612,17 @@ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'bas
+          // If there is no main property, get all values.
+          $values[$name] = $entity->get($name)->first()->getValue();

That seems a bit weird but I guess it's required for the MapItem to work. Should we add a @todo to resolve this as part of #2232427: Allow field types to control how properties are mapped to and from storage?

berdir’s picture

I prefer to use get() because PhpStorm always adds those hints if you just do $name :) We have no method for ->$main_property that would do the same... would have to call getValue() then.

Adding a todo sounds good, but it's not enough, as we also need that special case for no main property. For example, compare MapItem and LinkItem, both need the serialization, but on a different level. We can combine it with better explaining what we are doing there to solve #1.

pwolanin’s picture

Status: Needs work » Needs review
StatusFileSize
new1.38 KB
new4.74 KB

As suggested by berdir, here's a small addition to the shortcut test that loads saves and re-loads a content entity that has a MapItem.

I get fails - the values don't match. This patch resolves the fails. The increment is the test-only patch.

Setting back to CNR to let the tests run. I'm not totally clear from #4 and 5 what kind of todo or other code doc is needed?

The last submitted patch, 6: 2267753-test-only-6.patch, failed testing.

berdir’s picture

StatusFileSize
new5.18 KB
new1.79 KB

Something like this I think.

yched’s picture

Minor :

+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -611,7 +610,22 @@ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'bas
+          // If there is no main property, get all values from the first field

I know the method is named ->getValue() (wasn't there an issue to rename it to toArray() BTW ?), but
"If there is no main property, get all *s/values/properties/*" would be clearer IMO.

Also, that whole mapToStorageRecord() method only knows how to store single-values fields anyway, so it would be a bit clearer if we started with an unconditional $item = $entity->get($name)->first();, and then do "this or that", rather than having comments in each if () branch explain that they both happen to restrict to the first item.

Other than that, looks good. I guess most of this "reasoning on the shape of the schema" will be moot anyway when schemas for base tables get auto-generated ?

+ Posted some thoughts about the notion of "main property", on which we attach more and more behavior, but that remains worringly vague IMO : #2269599: Clarify the notion of "main property" for a Field Type

pwolanin’s picture

StatusFileSize
new1.71 KB
new5.2 KB

Ok, I think this has all the changes yched suggests.

yched’s picture

Status: Needs review » Reviewed & tested by the community

Thanks. Works for me if still green.

yesct’s picture

StatusFileSize
new5.2 KB
new1.54 KB

I came by here catching up on #2227441: New plan, Phase 1:Review the architecture and overall implementation proposal for menu links as plugins and read through the whole patch. I noticed two tiny things (no : in @todo https://drupal.org/node/1354#todo and a sentence missing a period)
This should still be rtbc.

yesct’s picture

Status: Reviewed & tested by the community » Needs review
berdir’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, clean-up looks good.

fago’s picture

Yep, this looks good now. RTBC+1.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

  • Commit c16fbc5 on 8.x by catch:
    Issue #2267753 by pwolanin, YesCT, Berdir: ContentEntityDatabaseStorage...

Status: Fixed » Needs work

The last submitted patch, 12: 2267753-12.patch, failed testing.

catch’s picture

Status: Needs work » Needs review

Missed that this was retesting, reverting for now.

catch’s picture

12: 2267753-12.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 12: 2267753-12.patch, failed testing.

berdir’s picture

12: 2267753-12.patch queued for re-testing.

  • Commit 51edc99 on 8.x by catch:
    Revert "Issue #2267753 by pwolanin, YesCT, Berdir:...

The last submitted patch, 12: 2267753-12.patch, failed testing.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new5.2 KB
new825 bytes
amateescu’s picture

StatusFileSize
new5.28 KB
new954 bytes

More reroll :)

The last submitted patch, 25: 2267753-25.patch, failed testing.

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, re-roll looks good, bad timing.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

pwolanin’s picture

Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.