summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Stjerneman2016-09-01 22:17:30 +0200
committerEmil Stjerneman2016-09-01 22:17:30 +0200
commitf1fc37a424acf3e57f6140e0ec5616b34eb9c234 (patch)
treef86727b090c16744803f882f494529f4c1fd2184
parentd05f53fe36c841f874bea9059cc229b53232535c (diff)
by anon: Use separate fields for data attributes in the dialog.
-rw-r--r--js/autocomplete.js42
-rw-r--r--linkit.module109
-rw-r--r--src/Controller/AutocompleteController.php16
-rw-r--r--src/Plugin/Linkit/Matcher/EntityMatcher.php26
-rw-r--r--src/Suggestion/EntitySuggestion.php81
-rw-r--r--src/SuggestionManager.php26
-rw-r--r--tests/src/FunctionalJavascript/LinkitDialogTest.php228
-rw-r--r--tests/src/Kernel/LinkitAutocompleteTest.php5
-rw-r--r--tests/src/Kernel/LinkitEditorLinkDialogTest.php49
-rw-r--r--tests/src/Kernel/Matchers/FileMatcherTest.php13
-rw-r--r--tests/src/Kernel/Matchers/NodeMatcherTest.php13
-rw-r--r--tests/src/Kernel/Matchers/TermMatcherTest.php17
-rw-r--r--tests/src/Kernel/Matchers/UserMatcherTest.php13
13 files changed, 380 insertions, 258 deletions
diff --git a/js/autocomplete.js b/js/autocomplete.js
index 1570f10..2b1aa4d 100644
--- a/js/autocomplete.js
+++ b/js/autocomplete.js
@@ -60,23 +60,32 @@
* False to prevent further handlers.
*/
function selectHandler(event, ui) {
- event.target.value = ui.item.path;
- $('.linkit-link-information > span').text(ui.item.label);
- return false;
- }
+ var $form = $(event.target).closest('form');
+
+ if (ui.item.path != null) {
+ $('input[name="attributes[href]"]', $form).val(ui.item.path);
+ $('input[name="attributes[data-entity-type]"]', $form).val('');
+ $('input[name="attributes[data-entity-uuid]"]', $form).val('');
+ $('input[name="attributes[data-entity-substitution]"]', $form).val('');
+ event.target.value = ui.item.path;
+ }
+ else {
+ if (!ui.item.entity_type_id || !ui.item.entity_uuid || !ui.item.substitution_id) {
+ throw 'Missing data params.' + JSON.stringify(ui.item);
+ }
- /**
- * Handles an autocomplete response event.
- *
- * Updates the link information.
- *
- * @param {jQuery.Event} event
- * The event triggered.
- * @param {object} ui
- * The jQuery UI settings object.
- */
- function response(event, ui) {
- $('.linkit-link-information > span').text(event.target.value);
+ // The href needs to be set in order for the drupallink saveCallback to
+ // insert new anchor elements.
+ $('input[name="attributes[href]"]', $form).val('#');
+ $('input[name="attributes[data-entity-type]"]', $form).val(ui.item.entity_type_id);
+ $('input[name="attributes[data-entity-uuid]"]', $form).val(ui.item.entity_uuid);
+ $('input[name="attributes[data-entity-substitution]"]', $form).val(ui.item.substitution_id);
+ event.target.value = ui.item.label;
+ }
+
+ $('.linkit-link-information > span', $form).text(ui.item.label);
+
+ return false;
}
/**
@@ -175,7 +184,6 @@
renderItem: renderItem,
renderMenu: renderMenu,
select: selectHandler,
- response: response,
minLength: 1
},
ajax: {
diff --git a/linkit.module b/linkit.module
index 55cdd24..f70246d 100644
--- a/linkit.module
+++ b/linkit.module
@@ -78,18 +78,25 @@ function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_s
$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
- // bad protocol. We therefor have to restore the URI again when editing a
- // link. It is possible given that data-entity-type and data-entity-uuid is
- // set on the link element.
+ $form['linkit'] = [
+ '#title' => t('Link'),
+ '#type' => 'linkit',
+ '#description' => t('Start typing to find content or paste a URL.'),
+ '#autocomplete_route_name' => 'linkit.autocomplete',
+ '#autocomplete_route_parameters' => [
+ 'linkit_profile_id' => $linkit_profile_id,
+ ],
+ "#weight" => -10,
+ ];
+
+ // Determine what the default value of the linkit autocomplete field.
try {
if (!empty($input['data-entity-type']) && !empty($input['data-entity-uuid'])) {
/** @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = \Drupal::service('entity.repository')
->loadEntityByUuid($input['data-entity-type'], $input['data-entity-uuid']);
- $href = 'entity:' . $entity->getEntityTypeId() . '/' . $entity->id();
$access = !$entity->access('view', NULL, TRUE)->isForbidden();
+ $autocomplete_default_value = !empty($access) && $access ? $entity->label() : '';
}
}
catch (Exception $exception) {
@@ -98,30 +105,38 @@ function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_s
finally {
// If the href is not set, the data- attributes might not exists, or the
// href is external. In that case, use the given href.
- if (!isset($href)) {
- $href = isset($input['href']) ? $input['href'] : '';
+ if (!isset($autocomplete_default_value)) {
+ $autocomplete_default_value = isset($input['href']) ? $input['href'] : '';
}
}
- $form['attributes']['href'] = [
- '#title' => t('Link'),
- '#type' => 'linkit',
- '#default_value' => $href,
- '#description' => t('Start typing to find content or paste a URL.'),
- '#autocomplete_route_name' => 'linkit.autocomplete',
- '#autocomplete_route_parameters' => [
- 'linkit_profile_id' => $linkit_profile_id,
- ],
- ];
+ $form['linkit']['#default_value'] = $autocomplete_default_value;
- $form['attributes']['link-information'] = [
+ $form['link-information'] = [
'#type' => 'inline_template',
- '#template' => '<div class="form-item linkit-link-information"><strong>{% trans %}Links to:{% endtrans %}</strong> <span>{{ link_target }}</span></div>',
+ '#template' => '<div class="form-item linkit-link-information"><strong>{% trans %}Selected link:{% endtrans %}</strong> <span>{{ link_target }}</span></div>',
'#context' => [
- 'link_target' => !empty($entity) && !empty($access) && $access ? $entity->label() : $href,
+ 'link_target' => !empty($entity) && !empty($access) && $access ? $entity->label() : $autocomplete_default_value,
],
+ "#weight" => -10,
];
+ $fields = [
+ 'href',
+ 'data-entity-type',
+ 'data-entity-uuid',
+ 'data-entity-substitution',
+ ];
+
+ $form['attributes']["#weight"] = -100;
+
+ foreach ($fields as $field_name) {
+ $form['attributes'][$field_name] = [
+ '#type' => 'hidden',
+ '#default_value' => isset($input[$field_name]) ? $input[$field_name] : '',
+ ];
+ }
+
// Add IMCE button if IMCE is installed and enabled for the given profile.
if (Drupal::service('module_handler')->moduleExists('imce') && $linkit_profile->getThirdPartySetting('imce', 'use', FALSE)) {
$form['imce-link'] = [
@@ -146,57 +161,29 @@ function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_s
'#weight' => 10,
];
}
-
- // Add #validate callback that generates data-entity-type and
- // data-entity-uuid attributes from the href attribute when appropriate.
- array_unshift($form['#validate'], 'linkit_form_editor_link_dialog_validate');
+ // Add #submit callback that handles the data-* attributes.
+ array_unshift($form['#submit'], 'linkit_form_editor_link_dialog_submit');
}
/**
- * Generates data-entity-type and data-entity-uuid attributes from href.
+ * Handles the data-* attributes and href replacement when appropriate.
*/
-function linkit_form_editor_link_dialog_validate(array &$form, FormStateInterface $form_state) {
+function linkit_form_editor_link_dialog_submit(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);
+ $data_entity_type = $form_state->getValue(['attributes', 'data-entity-type']);
+ $data_entity_uuid = $form_state->getValue(['attributes', 'data-entity-uuid']);
- if (!$uri_parts || !isset($uri_parts['scheme']) || $uri_parts['scheme'] !== 'entity') {
- // 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($data_entity_type) || empty($data_entity_uuid)) {
if (!empty($link_element)) {
$form_state->setValue(['attributes', 'data-entity-type'], '');
$form_state->setValue(['attributes', 'data-entity-uuid'], '');
$form_state->setValue(['attributes', 'data-entity-substitution'], '');
}
- return;
- }
-
- // Parse the entity: URI into an entity type ID and entity ID.
- list($substitution_type, $entity_type_id, $entity_id) = explode('/', $uri_parts['path'], 3);
-
- // Check if the given entity type exists, to prevent the entity load method
- // to throw exceptions.
- $definition = \Drupal::entityTypeManager()->getDefinition($entity_type_id, FALSE);
- if (is_null($definition)) {
- $form_state->setError($form['attributes']['href'], t('Invalid URI'));
- return;
- }
-
- // Load the entity and populate the data-entity-type and data-entity-uuid
- // attributes as expected by filters.
- // @see \Drupal\editor\Plugin\Filter\EditorFileReference
- // @see \Drupal\linkit\Plugin\Filter\LinkitFilter
- $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
- if (!empty($entity)) {
- $form_state->setValue(['attributes', 'data-entity-type'], $entity->getEntityTypeId());
- $form_state->setValue(['attributes', 'data-entity-uuid'], $entity->uuid());
- $form_state->setValue(['attributes', 'data-entity-substitution'], $substitution_type);
- }
- else {
- $form_state->setError($form['attributes']['href'], t('Invalid URI'));
+ else {
+ $form_state->unsetValue(['attributes', 'data-entity-type']);
+ $form_state->unsetValue(['attributes', 'data-entity-uuid']);
+ $form_state->unsetValue(['attributes', 'data-entity-substitution']);
+ }
}
-
}
diff --git a/src/Controller/AutocompleteController.php b/src/Controller/AutocompleteController.php
index 63dfff9..aa98c7c 100644
--- a/src/Controller/AutocompleteController.php
+++ b/src/Controller/AutocompleteController.php
@@ -41,7 +41,7 @@ class AutocompleteController implements ContainerInjectionInterface {
*
* @param \Drupal\Core\Entity\EntityStorageInterface $linkit_profile_storage
* The linkit profile storage service.
- * @param SuggestionManager $suggestionManager
+ * @param \Drupal\linkit\SuggestionManager $suggestionManager
* The suggestion service.
*/
public function __construct(EntityStorageInterface $linkit_profile_storage, SuggestionManager $suggestionManager) {
@@ -65,12 +65,12 @@ class AutocompleteController implements ContainerInjectionInterface {
* Like other autocomplete functions, this function inspects the 'q' query
* parameter for the string to use to search for suggestions.
*
- * @param Request $request
+ * @param \Symfony\Component\HttpFoundation\Request $request
* The request.
* @param string $linkit_profile_id
* The linkit profile id.
*
- * @return JsonResponse
+ * @return \Symfony\Component\HttpFoundation\JsonResponse JsonResponse
* A JSON response containing the autocomplete suggestions.
*/
public function autocomplete(Request $request, $linkit_profile_id) {
@@ -79,6 +79,16 @@ class AutocompleteController implements ContainerInjectionInterface {
$suggestionCollection = $this->suggestionManager->getSuggestions($this->linkitProfile, $string);
+ /*
+ * If there are no suggestions from the matcher plugins, we have to add a
+ * special suggestion that have the same path as the given string so users
+ * can select it and use it anyway. This is a common use case with external
+ * links.
+ */
+ if (!count($suggestionCollection->getSuggestions()) && !empty($string)) {
+ $suggestionCollection = $this->suggestionManager->addUnscathedSuggestion($suggestionCollection, $string);
+ }
+
return new JsonResponse($suggestionCollection);
}
diff --git a/src/Plugin/Linkit/Matcher/EntityMatcher.php b/src/Plugin/Linkit/Matcher/EntityMatcher.php
index 1ae2dfb..595affa 100644
--- a/src/Plugin/Linkit/Matcher/EntityMatcher.php
+++ b/src/Plugin/Linkit/Matcher/EntityMatcher.php
@@ -13,9 +13,8 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\linkit\ConfigurableMatcherBase;
use Drupal\linkit\MatcherTokensTrait;
-use Drupal\linkit\SubstitutionManager;
use Drupal\linkit\SubstitutionManagerInterface;
-use Drupal\linkit\Suggestion\DescriptionSuggestion;
+use Drupal\linkit\Suggestion\EntitySuggestion;
use Drupal\linkit\Suggestion\SuggestionCollection;
use Drupal\linkit\Utility\LinkitXss;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -305,11 +304,13 @@ class EntityMatcher extends ConfigurableMatcherBase {
$entity = $this->entityRepository->getTranslationFromContext($entity);
- $suggestion = new DescriptionSuggestion();
+ $suggestion = new EntitySuggestion();
$suggestion->setLabel($this->buildLabel($entity))
- ->setPath($this->buildPath($entity))
->setGroup($this->buildGroup($entity))
- ->setDescription($this->buildDescription($entity));
+ ->setDescription($this->buildDescription($entity))
+ ->setEntityUuid($entity->uuid())
+ ->setEntityTypeId($entity->getEntityTypeId())
+ ->setSubstitutionId($this->configuration['substitution_type']);
$suggestions->addSuggestion($suggestion);
}
@@ -383,21 +384,6 @@ class EntityMatcher extends ConfigurableMatcherBase {
}
/**
- * Builds the path string used in the match array.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The matched entity.
- *
- * @return string
- * The entity: URL for this entity.
- *
- * @see \Drupal\Core\Url::fromEntityUri()
- */
- protected function buildPath(EntityInterface $entity) {
- return 'entity:' . $this->configuration['substitution_type'] . '/' . $entity->getEntityTypeId() . '/' . $entity->id();
- }
-
- /**
* Builds the group string used in the match array.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
diff --git a/src/Suggestion/EntitySuggestion.php b/src/Suggestion/EntitySuggestion.php
new file mode 100644
index 0000000..772db11
--- /dev/null
+++ b/src/Suggestion/EntitySuggestion.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace Drupal\linkit\Suggestion;
+
+/**
+ * Defines a entity suggestion.
+ */
+class EntitySuggestion extends DescriptionSuggestion {
+
+ /**
+ * The entity uuid.
+ *
+ * @var string
+ */
+ protected $entityUuid;
+
+ /**
+ * The entity type id.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The substitution id.
+ *
+ * @var string
+ */
+ protected $substitutionId;
+
+ /**
+ * Sets the entity uuid.
+ *
+ * @param string $entity_uuid
+ * The entity uuid.
+ *
+ * @return $this
+ */
+ public function setEntityUuid($entity_uuid) {
+ $this->entityUuid = $entity_uuid;
+ return $this;
+ }
+
+ /**
+ * Sets the entity type id.
+ *
+ * @param string $entity_type_id
+ * The entity type id.
+ *
+ * @return $this
+ */
+ public function setEntityTypeId($entity_type_id) {
+ $this->entityTypeId = $entity_type_id;
+ return $this;
+ }
+
+ /**
+ * Sets the substitution id.
+ *
+ * @param string $substitution_id
+ * The substitution id.
+ *
+ * @return $this
+ */
+ public function setSubstitutionId($substitution_id) {
+ $this->substitutionId = $substitution_id;
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function jsonSerialize() {
+ return parent::jsonSerialize() + [
+ 'entity_uuid' => $this->entityUuid,
+ 'entity_type_id' => $this->entityTypeId,
+ 'substitution_id' => $this->substitutionId,
+ ];
+ }
+
+}
diff --git a/src/SuggestionManager.php b/src/SuggestionManager.php
index 8253f04..82004c5 100644
--- a/src/SuggestionManager.php
+++ b/src/SuggestionManager.php
@@ -2,6 +2,9 @@
namespace Drupal\linkit;
+use Drupal\Component\Utility\Html;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\linkit\Suggestion\DescriptionSuggestion;
use Drupal\linkit\Suggestion\SuggestionCollection;
/**
@@ -9,6 +12,8 @@ use Drupal\linkit\Suggestion\SuggestionCollection;
*/
class SuggestionManager {
+ use StringTranslationTrait;
+
/**
* Gets the suggestions.
*
@@ -34,4 +39,25 @@ class SuggestionManager {
return $suggestions;
}
+ /**
+ * Adds an unscathed suggestion to the given suggestion collection.
+ *
+ * @param \Drupal\linkit\Suggestion\SuggestionCollection $suggestionCollection
+ * A suggestion collection to add the unscathed suggestion to.
+ * @param string $search_string
+ * The string ro use in the matchers.
+ *
+ * @return \Drupal\linkit\Suggestion\SuggestionCollection
+ * A suggestion collection.
+ */
+ public function addUnscathedSuggestion(SuggestionCollection $suggestionCollection, $search_string) {
+ $suggestion = new DescriptionSuggestion();
+ $suggestion->setLabel(Html::escape($search_string))
+ ->setGroup($this->t('No results'))
+ ->setDescription($this->t('Linkit could not find any suggestions. This URL will be used as is.'))
+ ->setPath($search_string);
+ $suggestionCollection->addSuggestion($suggestion);
+ return $suggestionCollection;
+ }
+
}
diff --git a/tests/src/FunctionalJavascript/LinkitDialogTest.php b/tests/src/FunctionalJavascript/LinkitDialogTest.php
index a77a60d..7420ae0 100644
--- a/tests/src/FunctionalJavascript/LinkitDialogTest.php
+++ b/tests/src/FunctionalJavascript/LinkitDialogTest.php
@@ -42,6 +42,13 @@ class LinkitDialogTest extends JavascriptTestBase {
protected $demoEntity;
/**
+ * A linkit profile.
+ *
+ * @var \Drupal\linkit\ProfileInterface
+ */
+ protected $linkitProfile;
+
+ /**
* {@inheritdoc}
*/
protected function setUp() {
@@ -50,9 +57,9 @@ class LinkitDialogTest extends JavascriptTestBase {
$matcherManager = $this->container->get('plugin.manager.linkit.matcher');
/** @var \Drupal\linkit\MatcherInterface $plugin */
$plugin = $matcherManager->createInstance('entity:node', []);
- $profile = $this->createProfile();
- $profile->addMatcher($plugin->getConfiguration());
- $profile->save();
+ $this->linkitProfile = $this->createProfile();
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
// Create text format, associate CKEditor.
$llama_format = FilterFormat::create([
@@ -98,7 +105,7 @@ class LinkitDialogTest extends JavascriptTestBase {
$this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions();
$settings = $editor->getSettings();
$settings['plugins']['drupallink']['linkit_enabled'] = TRUE;
- $settings['plugins']['drupallink']['linkit_profile'] = $profile->id();
+ $settings['plugins']['drupallink']['linkit_profile'] = $this->linkitProfile->id();
$editor->setSettings($settings);
$editor->save();
@@ -136,25 +143,30 @@ class LinkitDialogTest extends JavascriptTestBase {
// Wait for the form to load.
$web_assert->assertWaitOnAjaxRequest();
- // Find the href field.
- $input_field = $page->findField('attributes[href]');
+ // Find the linkit field.
+ $linkit_field = $page->findField('linkit');
+
+ // Make sure the linkit field is an autocomplete field.
+ $linkit_field->hasAttribute('data-autocomplete-path');
+ $linkit_field->hasClass('form-linkit-autocomplete');
+ $linkit_field->hasClass('ui-autocomplete-input');
- // Make sure linkit has altered the href field.
- $input_field->hasAttribute('data-autocomplete-path');
- $input_field->hasClass('form-linkit-autocomplete');
- $input_field->hasClass('ui-autocomplete-input');
+ // Make sure all fields are empty.
+ $this->assertEmpty($linkit_field->getValue(), 'Linkit field is empty.');
+ $this->assertEmptyWithJs('attributes[data-entity-type]');
+ $this->assertEmptyWithJs('attributes[data-entity-uuid]');
+ $this->assertEmptyWithJs('attributes[data-entity-substitution]');
+ $this->assertEmptyWithJs('attributes[href]');
+
+ // Make sure the link information is empty.
+ $this->assertEmpty($this->getLinkInfoText(), 'Link information is empty');
// Make sure the autocomplete result container is hidden.
$autocomplete_container = $page->find('css', 'ul.linkit-ui-autocomplete');
$this->assertFalse($autocomplete_container->isVisible());
- // 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->keyDown('f');
+ $linkit_field->keyDown('f');
// Wait for the results to load.
$this->getSession()->wait(5000, "jQuery('.linkit-result.ui-menu-item').length > 0");
@@ -169,13 +181,17 @@ class LinkitDialogTest extends JavascriptTestBase {
// Find the first result and click it.
$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:canonical/' . $this->demoEntity->getEntityTypeId() . '/' . $this->demoEntity->id(), $input_field->getValue(), 'The href field is populated with the node uri');
+ // Make sure the linkit field field is populated with the node label.
+ $this->assertEquals($this->demoEntity->label(), $linkit_field->getValue(), 'The linkit field is populated with the node label.');
// Make sure the link information is populated.
- $javascript = "(function (){ return jQuery('.linkit-link-information > span').text(); })()";
- $link_information = $session->evaluateScript($javascript);
- $this->assertEquals($this->demoEntity->label(), $link_information, 'Link information is populated');
+ $this->assertEquals($this->demoEntity->label(), $this->getLinkInfoText(), 'Link information is populated');
+
+ // Make sure all other fields are populated.
+ $this->assertEqualsWithJs('attributes[data-entity-type]', $this->demoEntity->getEntityTypeId());
+ $this->assertEqualsWithJs('attributes[data-entity-uuid]', $this->demoEntity->uuid());
+ $this->assertEqualsWithJs('attributes[data-entity-substitution]', 'canonical');
+ $this->assertEqualsWithJs('attributes[href]', '#');
// Save the dialog input.
$page->find('css', '.editor-link-dialog')->find('css', '.button.form-submit span')->click();
@@ -183,39 +199,27 @@ class LinkitDialogTest extends JavascriptTestBase {
// 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' => $this->demoEntity->getEntityTypeId(), 'data-entity-uuid' => $this->demoEntity->uuid()] as $attr => $value) {
- $javascript = <<<JS
- (function(){
- var iframes = document.getElementsByClassName('cke_wysiwyg_frame');
- if (iframes.length) {
- var doc = iframes[0].contentDocument || iframes[0].contentWindow.document;
- var link = doc.getElementsByTagName('a')[0];
- return link.getAttribute("$attr");
- }
- })()
-JS;
- $link_attr = $session->evaluateScript($javascript);
- $this->assertNotNull($link_attr);
- $this->assertEquals($value, $link_attr);
+ $fields = [
+ 'data-entity-type' => $this->demoEntity->getEntityTypeId(),
+ 'data-entity-uuid' => $this->demoEntity->uuid(),
+ 'data-entity-substitution' => 'canonical',
+ 'href' => '#',
+ ];
+ foreach ($fields as $attribute => $value) {
+ $link_attribute = $this->getLinkAttributeFromEditor($attribute);
+ $this->assertEquals($value, $link_attribute, 'The link contain an attribute by the name of "' . $attribute . '" with a value of "' . $value . '"');
}
- }
-
- /**
- * 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.');
+ // Select the link in the editor.
+ $javascript = <<<JS
+ (function(){
+ var editor = window.CKEDITOR.instances['edit-body-0-value'];
+ console.log(editor);
+ var element = editor.document.findOne( 'a' );
+ editor.getSelection().selectElement( element );
+ })()
+JS;
+ $session->executeScript($javascript);
// Click on the drupallink plugin.
$page->find('css', 'a.cke_button__drupallink')->click();
@@ -223,55 +227,127 @@ JS;
// Wait for the form to load.
$web_assert->assertWaitOnAjaxRequest();
- // Find the href field.
- $input_field = $page->findField('attributes[href]');
+ // Find the linkit field.
+ $linkit_field = $page->findField('linkit');
+ $this->assertEquals($this->demoEntity->label(), $linkit_field->getValue(), 'Linkit field has the correct value.');
- // 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');
+ // Make sure all other fields are populated when editing a link.
+ $this->assertEqualsWithJs('attributes[data-entity-type]', $this->demoEntity->getEntityTypeId());
+ $this->assertEqualsWithJs('attributes[data-entity-uuid]', $this->demoEntity->uuid());
+ $this->assertEqualsWithJs('attributes[data-entity-substitution]', 'canonical');
+ $this->assertEqualsWithJs('attributes[href]', '#');
+
+ // Make sure the link information is populated with the old label.
+ $this->assertEquals($this->demoEntity->label(), $this->getLinkInfoText(), 'Link information is populated');
// Trigger a keydown event to active a autocomplete search.
- $input_field->setValue('http://example.co');
- $input_field->keyDown('m');
+ $linkit_field->setValue('http://example.co');
+ $linkit_field->keyDown('m');
// Wait for the autocomplete to be done.
- $this->getSession()->wait(1000);
+ $this->getSession()->wait(5000, "jQuery('.linkit-result.ui-menu-item').length > 0");
- // Make sure the autocomplete result container is hidden.
- $this->assertFalse($page->find('css', 'ul.linkit-ui-autocomplete')->isVisible());
+ // Make sure the autocomplete result container is visible.
+ $this->assertTrue($autocomplete_container->isVisible());
+
+ // Find all the autocomplete results.
+ $results = $page->findAll('css', '.linkit-result.ui-menu-item');
+ $this->assertEquals(1, count($results), 'Found autocomplete result');
+
+ // Find the first result and click it.
+ $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('http://example.com', $input_field->getValue(), 'The href field is the same as the URI');
+ // Make sure the href field is populated with the external uri.
+ $this->assertEquals('http://example.com', $linkit_field->getValue(), 'The linkit 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');
+ $this->assertEquals('http://example.com', $this->getLinkInfoText(), 'Link information is populated');
+
+ $this->assertEmptyWithJs('attributes[data-entity-type]');
+ $this->assertEmptyWithJs('attributes[data-entity-uuid]');
+ $this->assertEmptyWithJs('attributes[data-entity-substitution]');
+ $this->assertEqualsWithJs('attributes[href]', 'http://example.com');
// 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();
+ $fields = [
+ 'data-entity-type',
+ 'data-entity-uuid',
+ 'data-entity-substitution',
+ ];
+ foreach ($fields as $attribute) {
+ $link_attribute = $this->getLinkAttributeFromEditor($attribute);
+ $this->assertNull($link_attribute, 'The link does not contain an attribute by the name of "' . $attribute . '"');
+ }
+
+ $href_attribute = $this->getLinkAttributeFromEditor('href');
+ $this->assertEquals('http://example.com', $href_attribute, 'The link href is correct.');
+ }
+
+ /**
+ * Asserts that a variable is empty.
+ *
+ * @param string $field_name
+ * The name of the field.
+ */
+ private function assertEmptyWithJs($field_name) {
+ $javascript = "(function (){ return jQuery('input[name=\"" . $field_name . "\"]').val(); })()";
+ $field_value = $this->getSession()->evaluateScript($javascript);
+ $this->assertEmpty($field_value, 'The "' . $field_name . '" field is empty.');
+ }
+
+ /**
+ * Asserts that two variables are equal.
+ *
+ * @param string $field_name
+ * The name of the field.
+ * @param string $expected
+ * The expected value.
+ */
+ private function assertEqualsWithJs($field_name, $expected) {
+ $javascript = "(function (){ return jQuery('input[name=\"" . $field_name . "\"]').val(); })()";
+ $field_value = $this->getSession()->evaluateScript($javascript);
+ $this->assertEquals($expected, $field_value, 'The "' . $field_name . '" field has a value of "' . $expected . '".');
+ }
+
+ /**
+ * Gets an attribute of the first link in the ckeditor editor.
+ *
+ * @param string $attribute
+ * The attribute name.
+ *
+ * @return string|null
+ * The attribute, or null if the attribute is not found on the element.
+ */
+ private function getLinkAttributeFromEditor($attribute) {
// 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 = <<<JS
+ $javascript = <<<JS
(function(){
var iframes = document.getElementsByClassName('cke_wysiwyg_frame');
if (iframes.length) {
var doc = iframes[0].contentDocument || iframes[0].contentWindow.document;
var link = doc.getElementsByTagName('a')[0];
- return link.getAttribute("$attr");
+ return link.getAttribute("$attribute");
}
})()
JS;
- $link_attr = $session->evaluateScript($javascript);
- $this->assertNull($link_attr, $attr . ' was not found');
- }
+ return $this->getSession()->evaluateScript($javascript);
+ }
+
+ /**
+ * Gets the text in the link information element.
+ *
+ * @return string
+ * The text in the link information element.
+ */
+ private function getLinkInfoText() {
+ $javascript = "(function (){ return jQuery('.linkit-link-information > span').text(); })()";
+ return $this->getSession()->evaluateScript($javascript);
}
}
diff --git a/tests/src/Kernel/LinkitAutocompleteTest.php b/tests/src/Kernel/LinkitAutocompleteTest.php
index 91524cb..971f216 100644
--- a/tests/src/Kernel/LinkitAutocompleteTest.php
+++ b/tests/src/Kernel/LinkitAutocompleteTest.php
@@ -55,13 +55,11 @@ class LinkitAutocompleteTest extends LinkitKernelTestBase {
parent::setUp();
\Drupal::service('router.builder')->rebuild();
-
$this->installEntitySchema('user');
$this->installEntitySchema('entity_test');
$this->installEntitySchema('entity_test_mul');
$this->matcherManager = $this->container->get('plugin.manager.linkit.matcher');
-
$this->linkitProfile = $this->createProfile();
}
@@ -130,7 +128,8 @@ class LinkitAutocompleteTest extends LinkitKernelTestBase {
// Search for something that doesn't exists.
$data = $this->getAutocompleteResult('no_suggestions');
- $this->assertEmpty(count($data), 'Autocomplete did not return any suggestions.');
+ $this->assertTrue(count($data) == 1, 'Autocomplete returned the expected amount of suggestions.');
+ $this->assertSame(Html::escape('no_suggestions'), $data[0]['label'], 'Autocomplete returned the "no result" suggestion.');
// Search for something that exists one time.
$data = $this->getAutocompleteResult('bas');
diff --git a/tests/src/Kernel/LinkitEditorLinkDialogTest.php b/tests/src/Kernel/LinkitEditorLinkDialogTest.php
index 774fb35..f12f66e 100644
--- a/tests/src/Kernel/LinkitEditorLinkDialogTest.php
+++ b/tests/src/Kernel/LinkitEditorLinkDialogTest.php
@@ -7,6 +7,7 @@ use Drupal\editor\Entity\Editor;
use Drupal\editor\Form\EditorLinkDialog;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\filter\Entity\FilterFormat;
+use Drupal\linkit\SubstitutionManagerInterface;
use Drupal\linkit\Tests\ProfileCreationTrait;
/**
@@ -121,25 +122,24 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$form_builder->prepareForm($form_id, $form, $form_state);
$form_builder->processForm($form_id, $form, $form_state);
- $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the href field.');
- $this->assertEquals('', $form['attributes']['href']['#default_value'], 'The href attribute is empty.');
- $this->assertEquals('', $form['attributes']['link-information']['#context']['link_target'], 'Link information is empty.');
+ $this->assertEquals('linkit.autocomplete', $form['linkit']['#autocomplete_route_name'], 'Linkit is enabled on the linkit field.');
+ $this->assertEquals('', $form['linkit']['#default_value'], 'The linkit field is empty.');
- $form_state->setValue(['attributes', 'href'], 'entity:canonical/missing_entity/1');
- $form_builder->submitForm($form_object, $form_state);
- $this->assertNotEmpty($form_state->getErrors(), 'Got validation errors for none existing entity type.');
-
- $form_state->setValue(['attributes', 'href'], 'url_without_schema');
+ $form_state->setValue('linkit', 'url_without_schema');
$form_builder->submitForm($form_object, $form_state);
$this->assertEmpty($form_state->getErrors(), 'Got no validation errors for url without schema.');
- $this->assertEquals('', $form_state->getValue(['attributes', 'data-entity-type']));
- $this->assertEquals('', $form_state->getValue(['attributes', 'data-entity-uuid']));
+ $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-type']));
+ $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-uuid']));
+
+ $form_state->setValue(['attributes', 'data-entity-type'], $entity->getEntityTypeId());
+ $form_state->setValue(['attributes', 'data-entity-uuid'], $entity->uuid());
+ $form_state->setValue(['attributes', 'data-entity-substitution'], SubstitutionManagerInterface::DEFAULT_SUBSTITUTION);
- $form_state->setValue(['attributes', 'href'], 'entity:canonical/entity_test/1');
$form_builder->submitForm($form_object, $form_state);
$this->assertEmpty($form_state->getErrors(), 'Got no validation errors for correct URI.');
$this->assertEquals($entity->getEntityTypeId(), $form_state->getValue(['attributes', 'data-entity-type']), 'Attribute "data-entity-type" exists and has the correct value.');
$this->assertEquals($entity->uuid(), $form_state->getValue(['attributes', 'data-entity-uuid']), 'Attribute "data-entity-uuid" exists and has the correct value.');
+ $this->assertEquals(SubstitutionManagerInterface::DEFAULT_SUBSTITUTION, $form_state->getValue(['attributes', 'data-entity-substitution']), 'Attribute "data-entity-substitution" exists and has the correct value.');
}
/**
@@ -157,9 +157,10 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$input = [
'editor_object' => [
- 'href' => 'entity:entity_test/1',
+ 'href' => '#',
'data-entity-type' => $entity->getEntityTypeId(),
'data-entity-uuid' => $entity->uuid(),
+ 'data-entity-substitution' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION,
],
'dialogOptions' => [
'title' => 'Edit Link',
@@ -185,17 +186,20 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$form_builder->prepareForm($form_id, $form, $form_state);
$form_builder->processForm($form_id, $form, $form_state);
- $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the href field.');
- $this->assertEquals('entity:entity_test/1', $form['attributes']['href']['#default_value'], 'The href attribute is empty.');
- $this->assertEquals($entity->label(), $form['attributes']['link-information']['#context']['link_target'], 'Link information is empty.');
+ $this->assertEquals('linkit.autocomplete', $form['linkit']['#autocomplete_route_name'], 'Linkit is enabled on the linkit field.');
+ $this->assertEquals($entity->label(), $form['linkit']['#default_value'], 'The linkit field has the label as default value.');
+ $this->assertEquals($entity->getEntityTypeId(), $form_state->getValue(['attributes', 'data-entity-type']), 'Attribute "data-entity-type" exists and has the correct value.');
+ $this->assertEquals($entity->uuid(), $form_state->getValue(['attributes', 'data-entity-uuid']), 'Attribute "data-entity-uuid" exists and has the correct value.');
+ $this->assertEquals(SubstitutionManagerInterface::DEFAULT_SUBSTITUTION, $form_state->getValue(['attributes', 'data-entity-substitution']), 'Attribute "data-entity-substitution" exists and has the correct value.');
// Make sure the dialog don't display entity labels for inaccessible
// entities.
$input = [
'editor_object' => [
- 'href' => 'entity:entity_test/2',
+ 'href' => '#',
'data-entity-type' => $entity_no_access->getEntityTypeId(),
'data-entity-uuid' => $entity_no_access->uuid(),
+ 'data-entity-substitution' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION,
],
'dialogOptions' => [
'title' => 'Edit Link',
@@ -221,9 +225,8 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$form_builder->prepareForm($form_id, $form, $form_state);
$form_builder->processForm($form_id, $form, $form_state);
- $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the href field.');
- $this->assertEquals('entity:entity_test/2', $form['attributes']['href']['#default_value'], 'The href attribute is empty.');
- $this->assertEquals('entity:entity_test/2', $form['attributes']['link-information']['#context']['link_target'], 'Link information is empty.');
+ $this->assertEquals('linkit.autocomplete', $form['linkit']['#autocomplete_route_name'], 'Linkit is enabled on the linkit field.');
+ $this->assertEmpty($form['linkit']['#default_value']);
}
/**
@@ -260,9 +263,11 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$form_builder->prepareForm($form_id, $form, $form_state);
$form_builder->processForm($form_id, $form, $form_state);
- $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the href field.');
- $this->assertEquals('http://example.com/', $form['attributes']['href']['#default_value'], 'The href attribute is empty.');
- $this->assertEquals('http://example.com/', $form['attributes']['link-information']['#context']['link_target'], 'Link information is empty.');
+ $this->assertEquals('linkit.autocomplete', $form['linkit']['#autocomplete_route_name'], 'Linkit is enabled on the href field.');
+ $this->assertEquals('http://example.com/', $form['linkit']['#default_value'], 'The linkit field default value is the external URI.');
+ $this->assertEmpty($form['attributes']['data-entity-type']['#default_value']);
+ $this->assertEmpty($form['attributes']['data-entity-uuid']['#default_value']);
+ $this->assertEmpty($form['attributes']['data-entity-substitution']['#default_value']);
}
}
diff --git a/tests/src/Kernel/Matchers/FileMatcherTest.php b/tests/src/Kernel/Matchers/FileMatcherTest.php
index a84f588..bbe002d 100644
--- a/tests/src/Kernel/Matchers/FileMatcherTest.php
+++ b/tests/src/Kernel/Matchers/FileMatcherTest.php
@@ -12,8 +12,6 @@ use Drupal\Tests\linkit\Kernel\LinkitKernelTestBase;
*/
class FileMatcherTest extends LinkitKernelTestBase {
- use AssertResultUriTrait;
-
/**
* Modules to enable.
*
@@ -54,17 +52,6 @@ class FileMatcherTest extends LinkitKernelTestBase {
}
/**
- * Tests the paths for results on a file matcher.
- */
- public function testMatcherResultsPath() {
- /** @var \Drupal\linkit\MatcherInterface $plugin */
- $plugin = $this->manager->createInstance('entity:file', []);
- $suggestions = $plugin->execute('image-test');
- $this->assertTrue(count($suggestions->getSuggestions()), 'Got suggestions');
- $this->assertResultUri($plugin, $suggestions);
- }
-
- /**
* Tests file matcher.
*/
public function testFileMatcherWithDefaultConfiguration() {
diff --git a/tests/src/Kernel/Matchers/NodeMatcherTest.php b/tests/src/Kernel/Matchers/NodeMatcherTest.php
index cb996dc..07be444 100644
--- a/tests/src/Kernel/Matchers/NodeMatcherTest.php
+++ b/tests/src/Kernel/Matchers/NodeMatcherTest.php
@@ -13,8 +13,6 @@ use Drupal\Tests\linkit\Kernel\LinkitKernelTestBase;
*/
class NodeMatcherTest extends LinkitKernelTestBase {
- use AssertResultUriTrait;
-
/**
* Modules to enable.
*
@@ -89,17 +87,6 @@ class NodeMatcherTest extends LinkitKernelTestBase {
}
/**
- * Tests the paths for results on a node matcher.
- */
- public function testMatcherResultsPath() {
- /** @var \Drupal\linkit\MatcherInterface $plugin */
- $plugin = $this->manager->createInstance('entity:node', []);
- $suggestions = $plugin->execute('Lorem');
- $this->assertTrue(count($suggestions->getSuggestions()), 'Got suggestions');
- $this->assertResultUri($plugin, $suggestions);
- }
-
- /**
* Tests node matcher.
*/
public function testNodeMatcherWidthDefaultConfiguration() {
diff --git a/tests/src/Kernel/Matchers/TermMatcherTest.php b/tests/src/Kernel/Matchers/TermMatcherTest.php
index 706a1cc..1a1a026 100644
--- a/tests/src/Kernel/Matchers/TermMatcherTest.php
+++ b/tests/src/Kernel/Matchers/TermMatcherTest.php
@@ -16,8 +16,6 @@ use Drupal\Tests\linkit\Kernel\LinkitKernelTestBase;
*/
class TermMatcherTest extends LinkitKernelTestBase {
- use AssertResultUriTrait;
-
/**
* Modules to enable.
*
@@ -54,21 +52,6 @@ class TermMatcherTest extends LinkitKernelTestBase {
}
/**
- * Tests the paths for results on a term matcher.
- */
- public function testMatcherResultsPath() {
- /** @var \Drupal\linkit\MatcherInterface $plugin */
- $plugin = $this->manager->createInstance('entity:taxonomy_term', [
- 'settings' => [
- 'file_status' => 0,
- ],
- ]);
- $suggestions = $plugin->execute('foo');
- $this->assertTrue(count($suggestions->getSuggestions()), 'Got suggestions');
- $this->assertResultUri($plugin, $suggestions);
- }
-
- /**
* Tests term matcher with default configuration.
*/
public function testTermMatcherWidthDefaultConfiguration() {
diff --git a/tests/src/Kernel/Matchers/UserMatcherTest.php b/tests/src/Kernel/Matchers/UserMatcherTest.php
index ecb0b92..9a6984a 100644
--- a/tests/src/Kernel/Matchers/UserMatcherTest.php
+++ b/tests/src/Kernel/Matchers/UserMatcherTest.php
@@ -12,8 +12,6 @@ use Drupal\user\Entity\Role;
*/
class UserMatcherTest extends LinkitKernelTestBase {
- use AssertResultUriTrait;
-
/**
* The matcher manager.
*
@@ -62,17 +60,6 @@ class UserMatcherTest extends LinkitKernelTestBase {
}
/**
- * Tests the paths for results on a user matcher.
- */
- public function testMatcherResultsPath() {
- /** @var \Drupal\linkit\MatcherInterface $plugin */
- $plugin = $this->manager->createInstance('entity:user', []);
- $suggestions = $plugin->execute('Lorem');
- $this->assertTrue(count($suggestions->getSuggestions()), 'Got suggestions');
- $this->assertResultUri($plugin, $suggestions);
- }
-
- /**
* Tests user matcher.
*/
public function testUserMatcherWidthDefaultConfiguration() {