Problem/Motivation

After opening the 'Edit media' dialog after inserting a media embed in the WYSIWYG, the log is getting a warning, due to an undefined index error.

Set up:

  • Clean install of D8.8
  • enable Media and Media Library
  • On the Full HTML format, enable "Embed Media" filter
  • Drag "Insert from Media Library" button onto the Active Toolbar
  • For filter settings for the "Embed Media" filter, under "Media types selectable in the Media Library", only allow "Image"
  • under "View modes selectable in the 'Edit media' dialog", don't select any
  • save Full HTML text format
  • go to an article and select Full HTML text format in the WYSWIYG
  • Click the "Edit Media" button and save the dialog
  • Go to /admin/reports/dblog
  • Observe notice

Corresponding log entries include:

Notice: Undefined index: data-view-mode in Drupal\media\Form\EditorMediaDialog->buildForm() 
(line 176 of /Users/nathanandersen/dev/d8test/core/modules/media/src/Form/EditorMediaDialog.php)

Note: When the media is inserted, from the Media Library, it doesn't have the data-view-mode assigned:

<drupal-media data-align="center" data-entity-type="media" data-entity-uuid="01209b81-278f-4082-826c-5aa98cb70e6e"></drupal-media>

This issue was split off from #3100067: Unable to adjust anything after inserting Drupal Media, as it was noted in the original bug report, but doesn't seem to be related that issue.

Proposed resolution

Check if the index is undefined before attempting to use it.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

oknate created an issue. See original summary.

oknate’s picture

Status: Active » Needs review
FileSize
902 bytes

Here's a fix for this. I recommend we test manually. I don't think we should write a test that checks if this notice shows up in the logs. We can confirm it manually.

Update: this was the wrong patch, see #4 for the corrected patch.

oknate’s picture

Issue summary: View changes
oknate’s picture

Status: Needs review » Needs work
FileSize
987 bytes

Uploaded the wrong patch.

phenaproxima’s picture

Issue tags: +Needs tests

Looks okay to me. We will, however, need a test. But it need not be complex -- it can be a unit or (preferably) kernel test. All it needs to do is directly execute the bad code path, and the notice will cause PHPUnit to fail the test.

oknate’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
5.67 KB
6.64 KB

Here's test coverage. This will be useful too to test any future changes to that form.

The last submitted patch, 6: 3100470-6--FAIL.patch, failed testing. View results

phenaproxima’s picture

This looks pretty good to me -- nice work, @oknate! I think we might be able to simplify parts of the test, though.

  1. +++ b/core/modules/media/src/Form/EditorMediaDialog.php
    @@ -173,7 +173,8 @@ public function buildForm(array $form, FormStateInterface $form_state, EditorInt
    +    $default_view_mode = !empty($media_embed_element['data-view-mode']) ? $media_embed_element['data-view-mode'] : NULL;
    

    I think that, since we are using PHP 7 now, we can use the more terse null-coalesce operator here, like so:

    $default_view_mode = $media_embed_element['data-view-mode'] ?? NULL;
    
  2. +++ b/core/modules/media/tests/src/Kernel/EditorMediaDialogTest.php
    @@ -0,0 +1,199 @@
    +    $image = File::create([
    +      'uri' => $this->getTestFiles('image')[0]->uri,
    +      'uid' => 2,
    +    ]);
    +    $image->setPermanent();
    +    $image->save();
    +
    +    // Create a sample media entity to be embedded.
    +    $media_type = $this->createMediaType('image', ['id' => 'image']);
    +    EntityViewMode::create([
    +      'id' => 'media.foobar',
    +      'targetEntityType' => 'media',
    +      'status' => TRUE,
    +      'enabled' => TRUE,
    +      'label' => $this->randomMachineName(),
    +    ])->save();
    +    EntityViewDisplay::create([
    +      'targetEntityType' => 'media',
    +      'bundle' => $media_type->id(),
    +      'mode' => 'foobar',
    +      'status' => TRUE,
    +    ])->removeComponent('thumbnail')
    +      ->removeComponent('created')
    +      ->removeComponent('uid')
    +      ->setComponent('field_media_image', [
    +        'label' => 'visually_hidden',
    +        'type' => 'image',
    +        'settings' => [
    +          'image_style' => 'medium',
    +          'image_link' => 'file',
    +        ],
    +        'third_party_settings' => [],
    +        'weight' => 1,
    +        'region' => 'content',
    +      ])
    +      ->save();
    +    $media = Media::create([
    +      'uuid' => static::EMBEDDED_ENTITY_UUID,
    +      'bundle' => 'image',
    +      'name' => 'Screaming hairy armadillo',
    +      'field_media_image' => [
    +        [
    +          'target_id' => $image->id(),
    +          'alt' => 'default alt',
    +          'title' => 'default title',
    +        ],
    +      ],
    +    ])->setOwner($user);
    +    $media->save();
    +    $this->embeddedEntity = $media;
    +
    +    FilterFormat::create([
    +      'format' => 'test_format',
    +      'name' => 'Test format',
    +      'filters' => [
    +        'media_embed' => ['status' => TRUE],
    +      ],
    +    ])->save();
    +    $this->editor = Editor::create([
    +      'editor' => 'ckeditor',
    +      'format' => 'test_format',
    +    ]);
    +    $this->editor->save();
    

    This all seems pretty intense -- more like stuff we'd need in a functional test. Can we get away with using mocked objects for at least some of these things?

  3. +++ b/core/modules/media/tests/src/Kernel/EditorMediaDialogTest.php
    @@ -0,0 +1,199 @@
    +    $this->userInput = [
    +      'editor_object' => [
    +        'attributes' => [
    +          'data-entity-type' => 'media',
    +          'data-entity-uuid' => $this->embeddedEntity->uuid(),
    +          'data-align' => 'center',
    +        ],
    +        'hasCaption' => 'false',
    +        'label' => $this->embeddedEntity->label(),
    +        'link' => '',
    +        'hostEntityLangcode' => $this->embeddedEntity->language()->getId(),
    +        'classes' => '',
    +      ],
    +    ];
    

    I don't think this needs to be in a property of the class.

  4. +++ b/core/modules/media/tests/src/Kernel/EditorMediaDialogTest.php
    @@ -0,0 +1,199 @@
    +    $this->assertEquals('default alt', $build['alt']['#placeholder']);
    +    $this->assertEquals('center', $build['align']['#default_value']);
    +    $this->assertEquals(FALSE, $build['caption']['#default_value']);
    +    $this->assertEmpty($build['view_mode']['#options']);
    +    $this->assertEquals(FALSE, $build['view_mode']['#default_value']);
    

    So, I don't know if we need these assertions. We're just testing that the code path doesn't trigger a notice. So honestly, if $build comes back at all without failing the test, we can just use $this->pass() to mark the test as passed.

phenaproxima’s picture

Title: EditorMediaDialog notice, undefined index » EditorMediaDialog triggers an "undefined index" notice for data-view-mode
FileSize
2.59 KB
3.75 KB

Did some refactoring of the test; I was able to remove a lot of lines. It's more sparse now, but we can always add more coverage to it later as needed. For now, it's best to just have it test the one thing we want it to test.

phenaproxima’s picture

Reverting an accidental out-of-scope change here.

The last submitted patch, 9: 3100470-9-FAIL.patch, failed testing. View results

bnjmnm’s picture

Status: Needs review » Needs work

Two small changes and this should be ready.

  1. +++ b/core/modules/media/tests/src/Kernel/EditorMediaDialogTest.php
    @@ -0,0 +1,94 @@
    +    'editor',
    

    The editor module is not necessary for the test.

  2. +++ b/core/modules/media/tests/src/Kernel/EditorMediaDialogTest.php
    @@ -0,0 +1,94 @@
    +    $this->installSchema('system', 'sequences');
    

    The system sequences schema is not necessary for the test.

Wim Leers’s picture

#12: nice catches!

+++ b/core/modules/media/tests/src/Kernel/EditorMediaDialogTest.php
@@ -0,0 +1,94 @@
+class EditorMediaDialogTest extends KernelTestBase {
...
+    $form_state = new FormState();
+    $form_state->setUserInput([
...
+    $form_state->setRequestMethod('POST');
...
+    EditorMediaDialog::create($this->container)
+      ->buildForm([], $form_state, $editor->reveal());
+    $this->pass('Form was built without errors.');

Clever :) I like it. Much simpler than the usual functional tests.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
3.4 KB
668 bytes

Thank you both! Made the changes requested by @bnjmnm.

Wim Leers’s picture

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

Assigned: oknate » Unassigned

Unassigning myself. Thanks for the improvements @phenaproxima and @bnjmnm!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 14: 3100470-14.patch, failed testing. View results

MeenakshiG’s picture

Status: Needs work » Needs review
FileSize
3.4 KB

Re-rolled the patch

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, @Meenakshi.g!

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 61aa003c83 to 9.0.x and d44b969798 to 8.9.x and 2f209a4eb0 to 8.8.x. Thanks!

Backported to 8.8.x as this is a non disruptive bug fix.

  • alexpott committed 61aa003 on 9.0.x
    Issue #3100470 by phenaproxima, oknate, Meenakshi.g, Wim Leers, bnjmnm:...

  • alexpott committed d44b969 on 8.9.x
    Issue #3100470 by phenaproxima, oknate, Meenakshi.g, Wim Leers, bnjmnm:...

  • alexpott committed 2f209a4 on 8.8.x
    Issue #3100470 by phenaproxima, oknate, Meenakshi.g, Wim Leers, bnjmnm:...

Status: Fixed » Closed (fixed)

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