I believe there is some broken logic in this patch...although I'm new to this issue so I might be missing something.

js/plugins/drupalentity/plugin.js lines 73 - 90 (on RC1 which includes the patch)

      var originalGetFocusedWidget = null;
      if (CKEDITOR.plugins.drupalimage) {
        originalGetFocusedWidget = CKEDITOR.plugins.drupalimage.getFocusedWidget;
      }
      else {
        CKEDITOR.plugins.drupalimage = {};
      }
      CKEDITOR.plugins.drupalimage.getFocusedWidget = function () {
        var ourFocusedWidget = getFocusedWidget(editor);
        if (ourFocusedWidget) {
          return ourFocusedWidget;
        }
        // If drupalimage is loaded, call that next, to not break its link command integration.
        if (CKEDITOR.plugins.drupalimage) {
          return originalGetFocusedWidget(editor);
        }
        return null;
      };

It's possible for line 87 'return originalGetFocusedWidget(editor);' to get called even if 'originalGetFocusedWidget' was never defined as a function since CKEDITOR.plugins.drupalimage is set in the else (line 78) even if it wasn't previously set. I'm not familiar enough with what this section is trying to solve to provide a solution that won't break something else, but maybe changing line 86 to:

if (originalGetFocusedWidget) {

would do the trick since it would be null if CKEDITOR.plugins.drupalimage isn't loaded.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

artis created an issue. See original summary.

artis’s picture

Wim Leers’s picture

Issue tags: +Media Initiative, +JavaScript, +Needs tests, +DevDaysCluj

Thanks so much for reporting this, @artis! 🙏 👍

Ideally, we'd have a functional JS test that tests Entity Embed without the drupalimage button enabled, that should reproduce the JS error. You can find similar test coverage you can start from in \Drupal\Tests\entity_embed\FunctionalJavascript\CKEditorIntegrationTest::testIntegration().

oknate’s picture

It took me a bit to understand the problem. Here's a simplified version of the issue:

var emptyVar = {};
if (emptyVar) {
console.log("emptyVar evaluates to true");
}

If you run the code above, you'll see that emptyVar evaluates to true and the condition runs.

Unlike a php array, an empty javascript object will evaluate to true.

So if our fake drupalimage plugin is set the else condition:

else {
  CKEDITOR.plugins.drupalimage = {};
 }

then this code could fire:

 if (CKEDITOR.plugins.drupalimage) {
  return originalGetFocusedWidget(editor);
}

So the patch, which checks if originalGetFocusedWidget is set is better.

-        if (CKEDITOR.plugins.drupalimage) {
+        if (originalGetFocusedWidget) {
           return originalGetFocusedWidget(editor);
         }
oknate’s picture

Steps to reproduce:

  • Use a format with both an entity embed button and the core drupalink ("Link") button enabled, but not the drupalimage button.
  • Go to add or edit a node
  • Click the "link" button without focusing on an entity embed.

If you press the drupalink button when not focused on the entity embed, the link dialog will fail to load (and an error will display in the console, although I don't know if we can test for the error directly.

If you focus on the entity embed and press the drupal link button, the error will not present itself.

artis’s picture

As for a test, there should be a test, but it's not clear to me that it should hold up fixing this bug. I'll explain:

We do NOT have the drupalimage button enabled on our Ckeditor, but instead are using entity embed buttons only. But the bug did not reveal itself during the use of those buttons. It was the LINK button which stopped functioning. Entity Embed buttons worked fine. The link button would do nothing but display the console error "TypeError: originalGetFocusedWidget is not a function" when clicked.

It took some digging but eventually, we found this section of code in this module which contained originalGetFocusedWidget and then proposed the solution after coming to the same evaluation as oknate.

So it seems to me that a test should exist in core for confirming that the link button works even if drupalimage is not present. Or it is possible that there is some entanglement between the link button and drupalimage that could be reconsidered. But it's unclear to me how practical a test would be in entity_embed for this specific issue.

Having said that, I do think a test that confirms that the entity embed buttons still work if drupalimage doesn't exist isn't a bad idea, but it probably would not have caught this particular bug and could be dealt with elsewhere.

As I said at the beginning of all this, I'm very late to the game and have very little emersion in this module (1 hour max) so take this all with a grain of salt. I understand why the patch fixes the issue but I have no knowledge of the purpose of this section of code in the grand scheme of the module.

oknate’s picture

I agree testing this is a bit silly considering it's a newly introduced bug, introduced by this module.

I mean, do we need to test all of core along with the module?

It wouldn't hurt. Adding test coverage for the proper functionality of the link button when not focused on an entity embed will make sure it doesn't resurface as plugin.js is modified. If it happened once, it could happen again.

Plus, we're directly overwriting the drupalimage plugin, and its method CKEDITOR.plugins.drupalimage.getFocusedWidget(). So it is quite relevant to this module to test how that overridden CKEDITOR.plugins.drupalimage object behaves.

The last submitted patch, 7: 3061050-7--TEST-ONLY.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Wim Leers’s picture

#6:

So it seems to me that a test should exist in core for confirming that the link button works even if drupalimage is not present.

This ☝️. Except not in core, but in this module :)


#7:

I agree testing this is a bit silly considering it's a newly introduced bug, introduced by this module.

I disagree. Because while this is indeed a pretty simple oversight/bug in the JS code I wrote last week, it actually is very valuable to have strong guarantees that this functionality works independently of the existing drupalimage functionality in Drupal core, since it's totally feasible to stop using all of that completely by using Entity Embed's CKEditor integration today (or the port of the subset thereof to Drupal core in Drupal 8.8).

I mean, do we need to test all of core along with the module?

Not all of core, but high-impact edge cases: yes. Because …

If it happened once, it could happen again.

… of this.

Having a test for this gives us a higher degree of confidence. If this were a simple bug unrelated to interactions with other dependencies, then I wouldn't be asking for test coverage.

Plus, we're directly overwriting the drupalimage plugin, and its method CKEDITOR.plugins.drupalimage.getFocusedWidget(). So it is quite relevant to this module to test how that overridden CKEDITOR.plugins.drupalimage object behaves.

Exactly! 👏


Thanks a lot to both of you!


+++ b/tests/src/FunctionalJavascript/MediaImageTest.php
@@ -574,12 +575,44 @@ class MediaImageTest extends EntityEmbedTestBase {
   public function testCkeditorWidgetIsLinkable() {
...
+    // Remove DrupalImage.
+    // See https://www.drupal.org/project/entity_embed/issues/3061050
+    $editor = Editor::load('full_html');
+    $settings = $editor->getSettings();

This is now ironically swapping one half of test edge cases for another!

It used to only test with drupalimage, now it's only testing without. We want to test with both.

oknate’s picture

oh, good point.

The last submitted patch, 9: 3061050-9-test_only_FAIL.patch, failed testing. View results

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

Yay, only MediaImageTest::testCkeditorWidgetIsLinkableWhenDrupalImageIsAbsent() is failing, as expected. This means that using drupallink when not focusing the Entity Embed CKEditor widget while drupalimage is present does work. We're now successfully verifying that only the one case that @artis discovered to fail is actually failing.

This is now 💯 🥳

  • Wim Leers committed 3e7a6f8 on 8.x-1.x authored by artis
    Issue #3061050 by artis, oknate, Wim Leers: "TypeError:...
Wim Leers’s picture

Status: Reviewed & tested by the community » Fixed

🚢

oknate’s picture

great, thanks!

mturner20’s picture

FileSize
1.24 KB

Here is a patch for version: 8.x-1.0-rc1

mturner20’s picture

FileSize
1.06 KB

Sorry the patch in comment 16 wasn't generated correctly

Here is a new patch for version: 8.x-1.0-rc1

mturner20’s picture

FileSize
1.38 KB

Here is a new patch for version: 8.x-1.0-rc1

mturner20’s picture

artis’s picture

This issue has already been fixed. If you are looking for a patch that applies to RC1 and doesn't include the tests then patch #2 will work. Otherwise, you could use the dev-1.x release since this has already been committed to that branch.

rosinegrean’s picture

Issue tags: -DevDaysCluj +DevDaysTransylvania
Wim Leers’s picture

Component: Code » CKEditor integration

Status: Fixed » Closed (fixed)

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