Problem/Motivation

I get the following error in the log when I have two instances of an image effect in a style, whose configuration form specifies an Ajax callback:

PHP Fatal error: Call to a member function validateConfigurationForm() on a non-object in /[...]/core/modules/image/src/Form/ImageEffectFormBase.php on line 111

This happens when editing one of the effect configurations, not when adding them.

Proposed resolution

Let ImageEffectFormBase implement \Serializable, and let ::serialize store only the ImageStyle id and ImageEffect uuid instead of the entire objects.
::unserialize to reload ImageStyle from storage based on the serialized id, and ImageEffect got based on the serialized uuid from the reloaded ImageStyle object.

Remaining tasks

  • Review

User interface changes

None

API changes

None

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mondrake’s picture

Status: Active » Needs review
FileSize
5.4 KB

Test only patch showing the problem.

Status: Needs review » Needs work

The last submitted patch, 1: 2393387-1-test-only.patch, failed testing.

mondrake’s picture

Status: Needs work » Active

Back to active.

mondrake’s picture

Component: plugin system » image.module
Issue summary: View changes
Status: Active » Needs review
Issue tags: +Plugin system
FileSize
6.86 KB
1.46 KB

The problem seems to be with the serialization/unserialization of the imageEffect object while saving the form to KVE for Ajax caching.

The patch attached uses magic __sleep() and __wakeup() methods to ensure that the imageEffect object is recreated upon reading the form from cache.

mondrake queued 1: 2393387-1-test-only.patch for re-testing.

The last submitted patch, 1: 2393387-1-test-only.patch, failed testing.

mondrake queued 1: 2393387-1-test-only.patch for re-testing.

The last submitted patch, 1: 2393387-1-test-only.patch, failed testing.

mondrake’s picture

FileSize
5.4 KB
6.87 KB

Rerolled.

The last submitted patch, 9: 2393387-9-test-only.patch, failed testing.

mondrake queued 9: 2393387-9-test-only.patch for re-testing.

The last submitted patch, 9: 2393387-9-test-only.patch, failed testing.

mondrake’s picture

FileSize
5.41 KB
6.87 KB

Rerolled

The last submitted patch, 13: 2393387-13-test-only.patch, failed testing.

Xano’s picture

Status: Needs review » Needs work

Nice catch! I would store the plugin in $form_state instead. That will remove the need for using magic serialization methods.

mondrake’s picture

Status: Needs work » Postponed
Related issues: +#1977206: Default serialization of ConfigEntities

Re. #15, in fact, I think the problem here is with the serialization/unserialization of the ImageStyle config entity, so adding elements to $form_state seems not to me the way to go.

I tested the test-only patch in #13 with the latest patch in #1977206: Default serialization of ConfigEntities, and the failure seems to be gone. This may support the point that the problem is generally with ConfigEntity serialization.

Postponing on that issue.

The last submitted patch, 13: 2393387-13-test-only.patch, failed testing.

mondrake’s picture

Status: Postponed » Needs review
FileSize
5.21 KB

Rerolled test-only, to check if #2263569: Bypass form caching by default for forms using #ajax. makes any difference here.

mondrake’s picture

Status: Needs review » Fixed

#2263569: Bypass form caching by default for forms using #ajax. fixed this issue too - AJAX forms are no longer cached, so the root cause, being ImageStyle config entity getting serialised and placed in the form cache, is no longer there.

mondrake’s picture

mondrake’s picture

Status: Fixed » Needs review
FileSize
1.64 KB
5.29 KB

Actually no, unfortunately. The issue is still there as soon as the form hits the KVE cache. New test-only patch to demonstrate the issue.

Status: Needs review » Needs work

The last submitted patch, 22: 2393387-22-test-only.patch, failed testing.

mondrake’s picture

Status: Needs work » Needs review
FileSize
6.76 KB

Reroll of patch in #13 with test-only from #22

mondrake’s picture

FileSize
3.96 KB
7.79 KB

An alternative fix, implementing \Serializable on ImageEffectFormBase. This is taking cues from #1977206: Default serialization of ConfigEntities, and avoids usage of magic __sleep and __wakeup methods.

tim.plunkett’s picture

Can you test this again without the Serializable fixes? Like a tests-only patch? AJAX forms have been changed a lot recently, this may be obsolete.

mondrake’s picture

@tim.plunkett thanks for feedback. I submitted a retesting request for the test-only in #22, that should still apply. Locally it was failing today on an updated HEAD.

The last submitted patch, 22: 2393387-22-test-only.patch, failed testing.

mondrake’s picture

FileSize
5.29 KB

Status: Needs review » Needs work

The last submitted patch, 30: 2393387-30-test-only.patch, failed testing.

mondrake’s picture

Reuploading test-only + fix.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

mondrake queued 32: 2393387-32.patch for re-testing.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

xjm’s picture

Issue tags: +Triaged core major

Confirmed that this is still a bug per the testing above. We can fix this in a patch release.

Status: Needs review » Needs work

The last submitted patch, 32: 2393387-32.patch, failed testing.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

The last submitted patch, 32: 2393387-32.patch, failed testing.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

mondrake’s picture

Status: Needs work » Needs review

Full patch in #32 is green. Setting to needs review.

mondrake’s picture

Issue summary: View changes

Updated IS with the solution proposed in #25 and later.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

gnuget’s picture

Status: Needs review » Needs work

This looks great, I just found a few details.

The main problem to I found on this patch is the short array syntax and the old syntax is mixed, I think we should use one or the other but just one, (I would prefer the short syntax).

  1. +++ b/core/modules/image/src/Form/ImageEffectFormBase.php
    @@ -148,4 +149,53 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +    $serviceIds = [];
    

    I think here it should be $service_ids = [];

  2. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -276,6 +276,47 @@ function testStyle() {
    +    $effect_edit = array(
    

    In this patch in another line we used the array's short syntax but here no, I think we should use it here as well to keep the consistency in the patch.

  3. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -276,6 +276,47 @@ function testStyle() {
    +    $edit = array(
    

    short syntax too.

  4. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -276,6 +276,47 @@ function testStyle() {
    +    $this->assertRaw(t('Style %name was created.', array('%name' => $style_label)));
    

    Array Short syntax as well.

  5. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -276,6 +276,47 @@ function testStyle() {
    +    $this->drupalPostForm($style_path, array('new' => 'image_module_test_ajax'), t('Add'));
    

    short syntax.

  6. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -276,6 +276,47 @@ function testStyle() {
    +    $this->drupalPostForm($style_path, array('new' => 'image_module_test_ajax'), t('Add'));
    

    short syntax.

  7. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -276,6 +276,47 @@ function testStyle() {
    +    $style = $style = ImageStyle::load($style_name);
    

    This looks weird, is there a reason why we are doing this?

  8. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,92 @@
    +    return array(
    

    short syntax.

  9. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,92 @@
    +    $form['test_parameter'] = array(
    

    short syntax.

  10. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,92 @@
    +    $form['ajax_refresh'] = array(
    

    short syntax.

  11. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,92 @@
    +        'callback' => array($this, 'ajaxCallback'),
    

    short syntax.

  12. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,92 @@
    +    $form['ajax_value'] = array(
    

    short syntax.

  13. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,92 @@
    +    $item = array(
    

    short syntax.

mondrake’s picture

Status: Needs work » Postponed

Thanks for your review, @gnuget!

It looks like #2650588: Entities with plugin collections should be updated before serialization would solve this issue on the config entity level instead of the approach here, which is on the form level. See comment #2650588-24: Entities with plugin collections should be updated before serialization.

Let's wait for that to go in before continuing, if it is confirmed it will be fixed then I still think it would be worth to have a test only patch to ensure that we do not get regressions in the future.

The last submitted patch, 32: 2393387-32-test-only.patch, failed testing.

mondrake’s picture

I retested the test-only patch in #32 after commit of #2650588: Entities with plugin collections should be updated before serialization, and it came back green. So the issue is fixed.

I think there are two options for this issue now:
1. We just close it as a duplicate
2. We still review/commit only the test code to prevent possible future regressions. The patch attached here is the test-only in #32, with the changes suggested by @gnuget in #46.

Not changing priority/issue title ATM, as it was triaged major earlier.

alexpott’s picture

Title: WSOD editing image effect when configuration form is Ajax enabled » Add test for editing image effect when configuration form is Ajax enabled
Category: Bug report » Task
Priority: Major » Normal

I'm +1 on adding the test.

gnuget’s picture

I reviewed this again and I just found one really small thing.

  1. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,90 @@
    +use Drupal\Core\Image\ImageInterface;
    +use Drupal\image\ConfigurableImageEffectBase;
    +
    +
    +/**
    + * Provides a test effect using Ajax in the configuration form.
    + *
    

    Let's remove this extra line here.

Without that extra line this is RTBC to me.

mondrake’s picture

gnuget’s picture

Status: Needs review » Reviewed & tested by the community
tim.plunkett’s picture

  1. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -292,6 +292,47 @@ function testStyle() {
    +   * Test for editing Ajax enabled effect forms.
    

    Tests editing Ajax-enabled image effect forms.

  2. +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
    @@ -292,6 +292,47 @@ function testStyle() {
    +  function testAjaxEnabledEffectForm() {
    

    public function

  3. +++ b/core/modules/image/tests/modules/image_module_test/src/Plugin/ImageEffect/AjaxTestImageEffect.php
    @@ -0,0 +1,89 @@
    +      '#type'  => 'button',
    +      '#value' => $this->t('Ajax refresh'),
    +      '#ajax'  => ['callback' => [$this, 'ajaxCallback']],
    ...
    +      '#id'   => 'ajax-value',
    +      '#type'   => 'item',
    ...
    +      '#type'   => 'item',
    

    Weird extra spaces here, should only be one

Also can you post a second patch that includes a revert of the core issue that fixed this, so we know for sure the test is testing the right stuff?

mondrake’s picture

Assigned: Unassigned » mondrake
Status: Reviewed & tested by the community » Needs work
mondrake’s picture

Thanks @tim.plunkett!

Changes as suggested. The test-only patch reverts commit 9bd6902 from #2650588: Entities with plugin collections should be updated before serialization.

The last submitted patch, 56: interdiff_52-56.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 56: 2393387-56-test-only.patch, failed testing.

mondrake’s picture

Status: Needs work » Needs review

Sorry wrong .patch extension for the interdiff file.

mondrake’s picture

Status: Needs review » Reviewed & tested by the community

I think I can set this back to RTBC - changes in #56 are minor and it was RTBC before. The test-only patch in #56 show how, reverting the fix in #2650588: Entities with plugin collections should be updated before serialization, we get a failure when posting the form.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 822a21f and pushed to 8.0.x and 8.1.x. Thanks!

  • alexpott committed 208be78 on 8.1.x
    Issue #2393387 by mondrake, gnuget, tim.plunkett: Add test for editing...

  • alexpott committed 822a21f on 8.0.x
    Issue #2393387 by mondrake, gnuget, tim.plunkett: Add test for editing...

Status: Fixed » Closed (fixed)

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