Problem/Motivation

It seems that since DrupalCon Barcelona a yet unspecified change (possibly #2488568: Add a TypedDataManagerInterface and use it for typed parameters was made to Drupal core that caused \Drupal\Core\TypedData\TypedData and child objects to contain the typed data manager. The class, however, does not prevent the manager from being serialized. This becomes a problem when adding fields to entities, and submitting the form.

Steps to reproduce:

  1. Install Payment 8.x-2.x.
  2. Add a Payment Form field to user entities.
  3. For best results, disable JavaScript.
  4. Edit your own account, and click Add and configure a new line item.
  5. Confirm that \Drupal\Core\Database\Connection::__sleep() throws an exception.

Proposed resolution

Potentially make \Drupal\Core\TypedData\TypedData use \Drupal\Core\DependencyInjection\DependencySerializationTrait. I have confirmed this fixes the bug, but it may not be the best possible solution.

Remaining tasks

Find the best solution and implement it.

User interface changes

None.

API changes

None.

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Xano created an issue. See original summary.

Xano’s picture

Status: Active » Needs review
Issue tags: +Needs tests
FileSize
681 bytes

This is the suggested fix, but perhaps it's not the best one. We also need to find out how to test this. I'm not sure, especially because this looks like something our existing suite should have caught, considering its coverage and all the integration tests we have.

Berdir’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Contributed project blocker, +rc target triage

This prevents the Payment module from working, so tagging accordingly. I don't think we need tests, it's relatively hard to test in a useful way. We already have unit tests for the trait.

We have this trait on entity, plugin and various other base classes.

Note that this is a minor BC break: subclasses that implement this trait already would get a annoying PHP strict notice (some sort of notice, I think it is strict) but it's very easy to fix. And not adding it can result in *very* hard to track down bugs.

Berdir’s picture

Ah, now I remembed where I've seen this before. It was in #2053415: Allow typed data plugins to receive injected dependencies, back then it was still a base class but same problem. We had to add it when we started to actually inject dependencies there.

TypedData now actually supports it but core doesn't use it much. But this will happen when someone actually uses that.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 2: drupal_2615790_2.patch, failed testing.

Berdir’s picture

Status: Needs work » Reviewed & tested by the community

Retested, looks like a testbot issue.

ricovandevin’s picture

I can confirm that the patch from #2 fixes this bug.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 2: drupal_2615790_2.patch, failed testing.

Xano’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs tests

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 2: drupal_2615790_2.patch, failed testing.

Xano’s picture

Status: Needs work » Reviewed & tested by the community
dawehner’s picture

That bug is indeed really annoying!

This issue thought has a potential API break, right? What happens if other subclasses of TypedData had that trait already, for some reasons ...

Xano’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
533 bytes

@alexpott suggested this approach to limit the BC break.

Berdir’s picture

A comment would be great, and possibly the @todo for 9.x that @alexpott mentioned to use the trait?

dawehner’s picture

Yeah we better need a comment but yeah I really tried that on debugging some contrib module and something conflicted when you just put it into TypedData using the trait before ...

... What about adding a weekup method as well?

catch’s picture

As well as the @todo is it worth a new Base class that does use the trait?

Berdir’s picture

Status: Needs review » Needs work

You usually don't extend from TypedData directly, but from e.g. FieldItemBase, so I'm not sure how much that would really help.

Xano’s picture

Status: Needs work » Needs review
FileSize
827 bytes
937 bytes

What about adding a weekup method as well?

We do not need to implement ::__wakeup(), because \Drupal\Core\TypedData\TypedDataTrait::getTypedDataManager() lazyloads the typed data manager.

Xano’s picture

FileSize
949 bytes

::sleep() did not return an array if strings, but none of our tests caught that. I noticed this when running contrib tests (the same that exposed this bug in the first place).

Xano’s picture

FileSize
1.04 KB
1011 bytes

We had one more service to unset before serialization. I tested this using Payment, and all its tests pass with this patch applied.

dawehner’s picture

Do you mind adding a quick test to ensure this actually works? serialize($entity->name) should be enough.

Xano’s picture

The last submitted patch, 22: drupal_2615790_22_test_only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 22: drupal_2615790_22.patch, failed testing.

The last submitted patch, 22: drupal_2615790_22_test_only.patch, failed testing.

The last submitted patch, 22: drupal_2615790_22.patch, failed testing.

Xano’s picture

Thanks to Simpletest for being communicative.

The last submitted patch, 27: drupal_2615790_27_test_only.patch, failed testing.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -rc target triage

Looks good even I haven't see the $sut thing

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/tests/Drupal/Tests/Core/TypedData/TypedDataTest.php
@@ -0,0 +1,52 @@
+  /**
+   * The subject under test.
+   *
+   * @var \Drupal\Core\TypedData\TypedData
+   */
+  protected $sut;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $data_definition = $this->getMock(DataDefinitionInterface::class);
+    $this->sut = $this->getMockForAbstractClass(TypedData::class, [$data_definition]);
+  }

I think is quite a big assumption that any other test methods added to this unit test will need the same mocked class. Therefore lets get rid of the introduction of sut - the world does not need more tlas to get in the way of understanding stuff - and just do everything in the testSleep() method with no properties.

Xano’s picture

Xano’s picture

Status: Needs work » Needs review
Berdir’s picture

Status: Needs review » Needs work

Per our IRC discussion, lets use a different variable name, $typed_data or something.

Xano’s picture

Status: Needs work » Needs review
FileSize
1.33 KB
2.44 KB

SUT is a known acronym for these things. I advocate in favor, because using different names for the system under test in different tests is unnecessarily confusing when reading the code line by line.

Berdir’s picture

Status: Needs review » Needs work

Still has $serialized_sut in there ;)

Xano’s picture

Status: Needs work » Needs review
FileSize
976 bytes
2.46 KB
Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Thank you.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.1.x and cherry-picked to 8.0.x. Thanks!

  • catch committed 28c003b on
    Issue #2615790 by Xano: Field item properties do not prevent the...

  • catch committed fc24a2e on
    Issue #2615790 by Xano: Field item properties do not prevent the...

Status: Fixed » Closed (fixed)

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