Blocks #606840: Enable internal page cache by default.

This fixes the 34 failures o/t parent issue in:

  • \Drupal\user\Tests\UserRegistrationTest

This test modifies the field_config, field_storage_config entities for the User entity, as well as the 'register' form display for User entities. It modifies each of them individually, and then verifies that the registration form is updated accordingly. But due to page caching being enabled (in the parent issue), those changes are not actually reflected.

But, really, this is the only example in core that points to a wider problem. This is the only example in core of an entity form that is accessible by anonymous users (the only other one is the comment form, but that is special, because it's rendered via #post_render_cache — see #2099131: Use #pre_render pattern for entity render caching). But the wider problem is that entity forms don't have the necessary cache tags associated.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers’s picture

Status: Active » Needs review
FileSize
2 KB

UserRegistrationTest does this at the very end:

    // Check that the 'add more' button works.
    $field_storage->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
    $field_storage->save();
    foreach (array('js', 'nojs') as $js) {
      …

i.e. it test the exact same thing, but with different input values, both with JS (AJAXy form) and without JS (regular form). Each separately works fine. But running both in succession causes this failure on my machine:

[31-Mar-2015 15:47:14 Europe/Brussels] Uncaught PHP Exception Drupal\Core\Entity\EntityStorageException: "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '4a0944f2-9f46-4187-9f09-9b3743105ef6' for key 'user_field__uuid__value': INSERT INTO {users} (uid, uuid, langcode) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2); Array	

I'm hoping it's something that's specific to my machine…

Wim Leers’s picture

Title: EntityFormDisplay should associate cache tags of field_config, field_config_storage, entity_form_display with the $form » EntityFormDisplay should update $form with cache tags of FieldConfig, FieldStorageConfig, EntityFormDisplay config entities
Wim Leers’s picture

Issue tags: +Needs tests
Wim Leers’s picture

Issue tags: -Needs tests
FileSize
5.24 KB
3.26 KB

And tests.

The last submitted patch, 1: entity_form_display_cache_tags-2463029-1.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 4: entity_form_display_cache_tags-2463029-4.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
5.43 KB
1.34 KB

Status: Needs review » Needs work

The last submitted patch, 7: entity_form_display_cache_tags-2463029-7.patch, failed testing.

Berdir’s picture

To clarify: There's nothing special about the user registration form, user registration form isn't the only entity form that is visible to anon users (not even the only one by default), we just don't have test coverage for others. The contact form is also accessible to anon by default, for example.

+++ b/core/modules/user/src/Tests/UserRegistrationTest.php
@@ -220,14 +220,23 @@ function testRegistrationWithUserFields() {
+    $check_cache_tags = function() {
+      $this->assertCacheTag('config:core.entity_form_display.user.user.register');
+      $this->assertCacheTag('config:field.field.user.user.test_user_field');
+      $this->assertCacheTag('config:field.storage.user.test_user_field');
+      $this->assertCacheTag('config:user.settings');
+    };

You like this pattern, but I personally prefer having a real method for those helper methods, I'm not wondering how those are reported, for example. You can name a real method asssertSomething() and then call to it will be shown, which is more helpful.

Wim Leers’s picture

Status: Needs work » Needs review
Issue tags: +blocker
FileSize
5.65 KB
4.68 KB

Fixed failures, addressed Berdir's concerns :)

Wim Leers’s picture

Status: Needs review » Needs work

The last submitted patch, 11: entity_form_display_cache_tags-2463029-11.patch, failed testing.

Fabianx’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
    @@ -150,6 +152,9 @@ public function getRenderer($field_name) {
    +    /** @var \Drupal\Core\Render\RendererInterface $renderer */
    +    $renderer = \Drupal::service('renderer');
    +
    

    Uh? Should this not be injected into the class?

  2. +++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
    @@ -165,9 +170,23 @@ public function buildForm(FieldableEntityInterface $entity, array &$form, FormSt
    +        if ($field_definition instanceof ConfigEntityInterface) {
    +          $renderer->addDependency($form['name'], $field_definition);
    +          $field_storage_definition = $field_definition->getFieldStorageDefinition();
    +          if ($field_storage_definition instanceof ConfigEntityInterface) {
    

    Should these not check for CacheableDependencyInterface?

  3. +++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
    @@ -165,9 +170,23 @@ public function buildForm(FieldableEntityInterface $entity, array &$form, FormSt
    +    // Associate the cache tags for the form display.
    +    $renderer->addDependency($form, $this);
    +
    

    Is it ensured that $this always implements CacheableDependencyInterface?

Berdir’s picture

EntityFormDisplay is an entity so yes, it always implements that interface, and we can't inject dependencies in entities.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
5.69 KB
3.19 KB

Fixed my super retarded mistake that caused >3K failures. Rerolling when in a hurry = bad idea.

#13:

  1. Fixed.
  2. Hah, yes, thanks. This patch was rolled before entities implemented that interface, that's why :)
  3. Yes, as #14 says.

Status: Needs review » Needs work

The last submitted patch, 15: entity_form_display_cache_tags-2463029-11.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
6.04 KB

#15 had the right interdiff, but the wrong patch. Here's the patch I meant to upload. Sorry for the noise.

Fabianx’s picture

+++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
@@ -165,9 +174,23 @@ public function buildForm(FieldableEntityInterface $entity, array &$form, FormSt
+        $field_definition = $this->getFieldDefinition($name);
+        if ($field_definition instanceof CacheableDependencyInterface) {
+          $this->renderer->addDependency($form[$name], $field_definition);
+          $field_storage_definition = $field_definition->getFieldStorageDefinition();

I think the logic is not correct here:

Unless I miss something the field storage definition should be added regardless of the interface of the $field_definition.

E.g.:

if ($field_def instanceof ...) {
  $renderer->addDep();
}

if ($field_def) {
  $field_storage_def = ...;
  if ($field_stor_def instanceof ...) {
    $renderer->addDep();
  }
}

The rest looks good!

Wim Leers’s picture

Issue summary: View changes
FileSize
5.31 KB
1.25 KB

Oh, good point!

(Also fixed a rebase conflict; the changes to WebTestBase for improved debug output are no longer necessary, another issue landed them already.)

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

RTBC, looks great now!

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 4553018 and pushed to 8.0.x. Thanks!

  • alexpott committed 4553018 on 8.0.x
    Issue #2463029 by Wim Leers: EntityFormDisplay should update $form with...

Status: Fixed » Closed (fixed)

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