diff --git a/js/autocomplete.js b/js/autocomplete.js index a8d9e6cda1411ebb10b7336b791fee2ad5b8cd6a..1570f108f981560517c0f88cab6e026a3c84b8a4 100644 --- a/js/autocomplete.js +++ b/js/autocomplete.js @@ -76,9 +76,7 @@ * The jQuery UI settings object. */ function response(event, ui) { - if (ui.content.length === 0) { - $('.linkit-link-information > span').text(event.target.value); - } + $('.linkit-link-information > span').text(event.target.value); } /** diff --git a/linkit.module b/linkit.module index ce676dfff7d65ca5208d3fb58acee0561f05c468..c073d26196a626ec6de938a16972ae0749776b90 100644 --- a/linkit.module +++ b/linkit.module @@ -40,10 +40,15 @@ function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_s /** @var \Drupal\linkit\Entity\Profile $linkit_profile */ $linkit_profile = Drupal::entityTypeManager()->getStorage('linkit_profile')->load($linkit_profile_id); - $user_input = $form_state->getUserInput(); - $input = isset($user_input['editor_object']) ? $user_input['editor_object'] : []; - $data_entity_type = isset($input['data-entity-type']) ? $input['data-entity-type'] : ''; - $data_entity_uuid = isset($input['data-entity-uuid']) ? $input['data-entity-uuid'] : ''; + if (isset($form_state->getUserInput()['editor_object'])) { + $input = $form_state->getUserInput()['editor_object']; + $form_state->set('link_element', $input); + $form_state->setCached(TRUE); + } + else { + // Retrieve the link element's attributes from form state. + $input = $form_state->get('link_element') ?: []; + } // If the filter_html filter is activated, or any other filters using // XSS:filter(), it will remove 'entity:' from the href as it thinks it's a @@ -51,10 +56,10 @@ function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_s // link. It is possible given that data-entity-type and data-entity-uuid is // set on the link element. try { - if (!empty($data_entity_type) && !empty($data_entity_uuid)) { + if (!empty($input['data-entity-type']) && !empty($input['data-entity-uuid'])) { /** @var \Drupal\Core\Entity\EntityInterface $entity */ $entity = \Drupal::service('entity.repository') - ->loadEntityByUuid($data_entity_type, $data_entity_uuid); + ->loadEntityByUuid($input['data-entity-type'], $input['data-entity-uuid']); $href = 'entity:' . $entity->getEntityTypeId() . '/' . $entity->id(); $access = !$entity->access('view', NULL, TRUE)->isForbidden(); } @@ -123,13 +128,20 @@ function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_s * Generates data-entity-type and data-entity-uuid attributes from href. */ function linkit_form_editor_link_dialog_validate(array &$form, FormStateInterface $form_state) { + $link_element = $form_state->get('link_element'); + // Check if the 'href' attribute contains a entity: URI. $href = $form_state->getValue(['attributes', 'href']); $uri_parts = parse_url($href); if (!$uri_parts || !isset($uri_parts['scheme']) || $uri_parts['scheme'] !== 'entity') { - $form_state->setValue(['attributes', 'data-entity-type'], ''); - $form_state->setValue(['attributes', 'data-entity-uuid'], ''); + // Only set the data attributes to an empty string if the link is edited. + // This is to prevent new links that does not point to entities to have + // empty data attributes. + if (!empty($link_element)) { + $form_state->setValue(['attributes', 'data-entity-type'], ''); + $form_state->setValue(['attributes', 'data-entity-uuid'], ''); + } return; } diff --git a/tests/src/FunctionalJavascript/LinkitDialogTest.php b/tests/src/FunctionalJavascript/LinkitDialogTest.php index 7786a1afdf319c38067f8f5acecf46cc3d1472a7..df0f528565f045769bb69496b492837f9cf3d881 100644 --- a/tests/src/FunctionalJavascript/LinkitDialogTest.php +++ b/tests/src/FunctionalJavascript/LinkitDialogTest.php @@ -116,22 +116,22 @@ class LinkitDialogTest extends JavascriptTestBase { * Test the link dialog. */ public function testLinkDialog() { + $session = $this->getSession(); + $web_assert = $this->assertSession(); + $page = $session->getPage(); + // Create test nodes. $this->demoEntity = $this->createNode(['title' => 'Foo']); // Go to node creation page. $this->drupalGet('node/add/page'); - $session = $this->getSession(); - $web_assert = $this->assertSession(); - $page = $session->getPage(); // Wait until the editor has been loaded. $ckeditor_loaded = $this->getSession()->wait(5000, "jQuery('.cke_contents').length > 0"); $this->assertTrue($ckeditor_loaded, 'The editor has been loaded.'); // Click on the drupallink plugin. - $link_button = $page->find('css', 'a.cke_button__drupallink'); - $link_button->click(); + $page->find('css', 'a.cke_button__drupallink')->click(); // Wait for the form to load. $web_assert->assertWaitOnAjaxRequest(); @@ -167,8 +167,7 @@ class LinkitDialogTest extends JavascriptTestBase { $this->assertEquals(1, count($results), 'Found autocomplete result'); // Find the first result and click it. - $result_selection = $page->find('xpath', '(//li[contains(@class, "linkit-result") and contains(@class, "ui-menu-item")])[1]'); - $result_selection->click(); + $page->find('xpath', '(//li[contains(@class, "linkit-result") and contains(@class, "ui-menu-item")])[1]')->click(); // Make sure the href field is populated with the node uri. $this->assertEquals('entity:' . $this->demoEntity->getEntityTypeId() . '/' . $this->demoEntity->id(), $input_field->getValue(), 'The href field is populated with the node uri'); @@ -179,8 +178,7 @@ class LinkitDialogTest extends JavascriptTestBase { $this->assertEquals($this->demoEntity->label(), $link_information, 'Link information is populated'); // Save the dialog input. - $button = $page->find('css', '.editor-link-dialog')->find('css', '.button.form-submit span'); - $button->click(); + $page->find('css', '.editor-link-dialog')->find('css', '.button.form-submit span')->click(); // Wait for the dialog to close. $web_assert->assertWaitOnAjaxRequest(); @@ -204,4 +202,76 @@ JS; } } + /** + * Tests adding a link with no data attributes. + */ + public function testLinkDialogWithNonDataAttributes() { + $session = $this->getSession(); + $web_assert = $this->assertSession(); + $page = $session->getPage(); + + // Go to node creation page. + $this->drupalGet('node/add/page'); + + // Wait until the editor has been loaded. + $ckeditor_loaded = $this->getSession()->wait(5000, "jQuery('.cke_contents').length > 0"); + $this->assertTrue($ckeditor_loaded, 'The editor has been loaded.'); + + // Click on the drupallink plugin. + $page->find('css', 'a.cke_button__drupallink')->click(); + + // Wait for the form to load. + $web_assert->assertWaitOnAjaxRequest(); + + // Find the href field. + $input_field = $page->findField('attributes[href]'); + + // Make sure the link information is empty. + $javascript = "(function (){ return jQuery('.linkit-link-information > span').text(); })()"; + $link_information = $session->evaluateScript($javascript); + $this->assertEquals('', $link_information, 'Link information is empty'); + + // Trigger a keydown event to active a autocomplete search. + $input_field->setValue('http://example.co'); + $input_field->keyDown('m'); + + // Wait for the autocomplete to be done. + $this->getSession()->wait(1000); + + // Make sure the autocomplete result container is hidden. + $this->assertFalse($page->find('css', 'ul.linkit-ui-autocomplete')->isVisible()); + + // Make sure the href field is populated with the node uri. + $this->assertEquals('http://example.com', $input_field->getValue(), 'The href field is the same as the URI'); + + // Make sure the link information is populated. + $javascript = "(function (){ return jQuery('.linkit-link-information > span').text(); })()"; + $link_information = $session->evaluateScript($javascript); + $this->assertEquals('http://example.com', $link_information, 'Link information is populated'); + + // Save the dialog input. + $button = $page->find('css', '.editor-link-dialog')->find('css', '.button.form-submit span'); + $button->click(); + + // Wait for the dialog to close. + $web_assert->assertWaitOnAjaxRequest(); + + // We can't use $session->switchToIFrame() here, because the iframe does not + // have a name. + foreach (['data-entity-type', 'data-entity-uuid'] as $attr) { + $javascript = <<evaluateScript($javascript); + $this->assertNull($link_attr, $attr . ' was not found'); + } + } + }