' . t('Attributes are HTML attributes that will be attached to the insert plugin.') . '
'; - break; + case 'help.page.linkit': + $output = ''; + $output .= '' . t('The Linkit module provides an easy interface for internal and external linking with wysiwyg editors by using an autocomplete field.') . '
'; + $output .= '' . t('Linkit profiles define how Linkit will operate on fields that have Linkit attached.') . '
'; + $output .= '' . t('The most common way to use Linkit is to enable Linkit on the Drupal Link plugin and associate a Linkit profile to it on a Text format.') . '
'; + return $output; + + case 'linkit.matchers': + $output = '' . t('Matchers defines how different data can be queried and displayed in the autocomplete suggestion list. Multiple matchers of the same type can be used at the same time to granulate the suggestions. The order of the added matchers defines in which order the suggestions will be presented.') . '
'; + return $output; } } +/** + * Implements hook_ckeditor_plugin_info_alter(). + */ +function linkit_ckeditor_plugin_info_alter(array &$plugins) { + if (isset($plugins['drupallink'])) { + $plugins['drupallink']['class'] = "Drupal\\linkit\\Plugin\\CKEditorPlugin\\LinkitDrupalLink"; + } +} /** - * Implements hook_form_BASE_FORM_ID_alter() for linkit_profile_form on behalf - * of the 'imce' module. - * - * Adds IMCE settings to the form. - * - * @see imce_form_linkit_profile_form_builder() + * Implements hook_form_FORM_ID_alter(). */ -function imce_form_linkit_profile_form_alter(&$form, FormStateInterface $form_state) { - /** @var \Drupal\Linkit\ProfileInterface $linkit_profile */ - $linkit_profile = $form_state->getFormObject()->getEntity(); +function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_state, $form_id) { + // Alter only the form with ID 'editor_link_dialog'. + if ($form_id !== 'editor_link_dialog') { + return; + } - $form['imce'] = array( - '#type' => 'details', - '#title' => t('IMCE integration'), - '#group' => 'additional_settings', - ); + /** @var Drupal\filter\Entity\FilterFormat $filter_format */ + $filter_format = $form_state->getBuildInfo()['args'][0]; - $form['imce']['imce_use'] = array( - '#type' => 'checkbox', - '#title' => t('Enable IMCE File Browser in the editor dialog.'), - '#default_value' => $linkit_profile->getThirdPartySetting('imce', 'use', FALSE), - ); + /** @var \Drupal\Core\Entity\EntityStorageInterface $editorStorage */ + $editorStorage = Drupal::service('entity.manager')->getStorage('editor'); - $scheme_options = \Drupal::service('stream_wrapper_manager')->getNames(StreamWrapperInterface::READ_VISIBLE); - $form['imce']['imce_scheme'] = array( - '#type' => 'radios', - '#title' => t('Scheme'), - '#options' => $scheme_options, - '#default_value' => $linkit_profile->getThirdPartySetting('imce', 'scheme', 'public'), - '#states' => [ - 'visible' => [ - ':input[name="imce_use"]' => ['checked' => TRUE], - ], + /** @var \Drupal\editor\EditorInterface $editor */ + $editor = $editorStorage->load($filter_format->id()); + $plugin_settings = $editor->getSettings()['plugins']['drupallink']; + + // Do not alter the form if Linkit is not enabled for this text format. + if (!isset($plugin_settings['linkit_enabled']) || (isset($plugin_settings['linkit_enabled']) && !$plugin_settings['linkit_enabled'])) { + return; + } + + $linkit_profile_id = $editor->getSettings()['plugins']['drupallink']['linkit_profile']; + + 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') ?: []; + } + + $form['href_dirty_check'] = [ + '#type' => 'hidden', + '#default_value' => isset($input['href']) ? $input['href'] : '', + ]; + + $form['attributes']['href'] = array_merge($form['attributes']['href'], [ + '#type' => 'linkit', + '#description' => t('Start typing to find content.'), + '#autocomplete_route_name' => 'linkit.autocomplete', + '#autocomplete_route_parameters' => [ + 'linkit_profile_id' => $linkit_profile_id, ], - ); + "#weight" => -10, + '#default_value' => isset($input['href']) ? $input['href'] : '', + ]); - $form['#entity_builders'][] = 'imce_form_linkit_profile_form_builder'; -} + $fields = [ + 'data-entity-type', + 'data-entity-uuid', + 'data-entity-substitution', + ]; -/** - * Entity builder for the linkit profile form with imce options. - * - * @see imce_form_linkit_profile_form_alter(). - */ -function imce_form_linkit_profile_form_builder($entity_type, ProfileInterface $linkit_profile, &$form, FormStateInterface $form_state) { - $linkit_profile->setThirdPartySetting('imce', 'use', $form_state->getValue('imce_use')); - $linkit_profile->setThirdPartySetting('imce', 'scheme', $form_state->getValue('imce_scheme')); -} + $form['attributes']["#weight"] = -100; -/** - * Implements hook_form_BASE_FORM_ID_alter() for linkit_editor_dialog_form on - * behalf of the 'imce' module. - * - * Adds a button to open the imce file browser if it is enabled. - */ -function imce_form_linkit_editor_dialog_form_alter(&$form, FormStateInterface $form_state) { - /** @var \Drupal\Linkit\ProfileInterface $linkit_profile */ - $linkit_profile = $form_state->getFormObject()->getLinkitProfile(); - - if($linkit_profile->getThirdPartySetting('imce', 'use', FALSE)) { - $form['imce-link'] = [ - '#type' => 'link', - '#title' => t('Open IMCE file browser'), - '#url' => Url::fromRoute('imce.page', [ - 'scheme' => $linkit_profile->getThirdPartySetting('imce', 'scheme', 'public'), - ]), - '#options' => array( - 'query' => array( - 'sendto' => 'linkitImce.sendto', - ), - ), - '#attributes' => [ - 'class' => ['linkit-imce-open'], - ], - '#attached' => [ - 'library' => [ - 'linkit/linkit.imce' - ], - ], - '#weight' => 1, + foreach ($fields as $field_name) { + $form['attributes'][$field_name] = [ + '#title' => $field_name, + '#type' => 'hidden', + '#default_value' => isset($input[$field_name]) ? $input[$field_name] : '', ]; } + + // Add #submit callback that handles the data-* attributes. + array_unshift($form['#submit'], 'linkit_form_editor_link_dialog_submit'); +} + +/** + * Handles the data-* attributes and href replacement when appropriate. + */ +function linkit_form_editor_link_dialog_submit(array &$form, FormStateInterface $form_state) { + $link_element = $form_state->get('link_element'); + + $href = $form_state->getValue(['attributes', 'href']); + $href_dirty_check = $form_state->getValue(['href_dirty_check']); + + if ($href !== $href_dirty_check) { + $form_state->unsetValue(['attributes', 'data-entity-type']); + $form_state->unsetValue(['attributes', 'data-entity-uuid']); + $form_state->unsetValue(['attributes', 'data-entity-substitution']); + } + + $fields = [ + 'href', + 'data-entity-type', + 'data-entity-uuid', + 'data-entity-substitution', + ]; + + foreach ($fields as $field_name) { + $value = $form_state->getValue(['attributes', $field_name]); + if (empty($value)) { + if (!empty($link_element)) { + $form_state->setValue(['attributes', $field_name], ''); + } + else { + $form_state->unsetValue(['attributes', $field_name]); + } + } + } } diff --git a/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml b/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml index e56ef4f4a..830dcded9 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml @@ -1,2 +1,2 @@ administer linkit profiles: - title: 'Administer linkit profiles' \ No newline at end of file + title: 'Administer linkit profiles' diff --git a/sites/all/modules/contrib/fields/linkit/linkit.routing.yml b/sites/all/modules/contrib/fields/linkit/linkit.routing.yml index 035952c0a..6a0d68d19 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.routing.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.routing.yml @@ -29,37 +29,6 @@ entity.linkit_profile.delete_form: requirements: _permission: 'administer linkit profiles' -linkit.attributes: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes' - defaults: - _form: '\Drupal\linkit\Form\Attribute\OverviewForm' - _title: 'Manage attributes' - requirements: - _permission: 'administer linkit profiles' - -linkit.attribute.add: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes/add' - defaults: - _form: '\Drupal\linkit\Form\Attribute\AddForm' - _title: 'Add attribute' - requirements: - _permission: 'administer linkit profiles' - -linkit.attribute.delete: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes/{plugin_instance_id}/delete' - defaults: - _form: '\Drupal\linkit\Form\Attribute\DeleteForm' - requirements: - _permission: 'administer linkit profiles' - -linkit.attribute.edit: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes/{plugin_instance_id}' - defaults: - _form: '\Drupal\linkit\Form\Attribute\EditForm' - _title_callback: 'Drupal\linkit\Controller\LinkitController::attributeTitle' - requirements: - _permission: 'administer linkit profiles' - linkit.matchers: path: '/admin/config/content/linkit/manage/{linkit_profile}/matchers' defaults: @@ -91,21 +60,12 @@ linkit.matcher.edit: requirements: _permission: 'administer linkit profiles' -linkit.linkit_dialog: - path: '/linkit/dialog/linkit/{filter_format}' - defaults: - _form: '\Drupal\linkit\Form\LinkitEditorDialog' - _title: 'Add link' - requirements: - _entity_access: 'filter_format.use' - options: - _theme: ajax_base_page - linkit.autocomplete: path: '/linkit/autocomplete/{linkit_profile_id}' defaults: _controller: '\Drupal\linkit\Controller\AutocompleteController::autocomplete' requirements: + # Access is handled by the matchers. _access: 'TRUE' options: _theme: ajax_base_page diff --git a/sites/all/modules/contrib/fields/linkit/linkit.services.yml b/sites/all/modules/contrib/fields/linkit/linkit.services.yml index 1deeb8679..e18ca32d2 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.services.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.services.yml @@ -1,11 +1,10 @@ services: - plugin.manager.linkit.attribute: - class: Drupal\linkit\AttributeManager - parent: default_plugin_manager - plugin.manager.linkit.matcher: class: Drupal\linkit\MatcherManager parent: default_plugin_manager - - linkit.result_manager: - class: Drupal\linkit\ResultManager + plugin.manager.linkit.substitution: + class: Drupal\linkit\SubstitutionManager + arguments: ['@entity_type.manager'] + parent: default_plugin_manager + linkit.suggestion_manager: + class: Drupal\linkit\SuggestionManager diff --git a/sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php b/sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php deleted file mode 100644 index d22b34bcd..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php +++ /dev/null @@ -1,69 +0,0 @@ -setConfiguration($configuration); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration() { - return [ - 'id' => $this->getPluginId(), - 'weight' => $this->weight, - 'settings' => $this->configuration, - ]; - } - - /** - * {@inheritdoc} - */ - public function setConfiguration(array $configuration) { - $configuration += [ - 'weight' => '0', - 'settings' => [], - ]; - $this->configuration = $configuration['settings'] + $this->defaultConfiguration(); - $this->weight = $configuration['weight']; - return $this; - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return []; - } - - /** - * {@inheritdoc} - */ - public function calculateDependencies() { - return []; - } - - /** - * {@inheritdoc} - */ - public function getLabel() { - return $this->pluginDefinition['label']; - } - - /** - * {@inheritdoc} - */ - public function getHtmlName() { - return $this->pluginDefinition['html_name']; - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - return $this->pluginDefinition['description']; - } - - /** - * {@inheritdoc} - */ - public function getWeight() { - return $this->weight; - } - - /** - * {@inheritdoc} - */ - public function setWeight($weight) { - $this->weight = $weight; - return $this; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php b/sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php deleted file mode 100644 index 3b4d88b40..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php +++ /dev/null @@ -1,46 +0,0 @@ -get($aID)->getWeight(); - $b_weight = $this->get($bID)->getWeight(); - if ($a_weight == $b_weight) { - return strnatcasecmp($this->get($aID)->getLabel(), $this->get($bID)->getLabel()); - } - - return ($a_weight < $b_weight) ? -1 : 1; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php b/sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php deleted file mode 100644 index d3e865ba6..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php +++ /dev/null @@ -1,78 +0,0 @@ -<a> tag. - * - * @return string - * The attribute html name. - */ - public function getHtmlName(); - - /** - * Returns the weight of the attribute. - * - * @return int|string - * Either the integer weight of the attribute or an empty string. - */ - public function getWeight(); - - /** - * Sets the weight for this attribute. - * - * @param int $weight - * The weight for this attribute. - * - * @return $this - */ - public function setWeight($weight); - - /** - * The form element structure for this attribute to be used in the dialog. - * - * @param mixed $default_value - * The default value for the element. Used when editing an attribute in the - * dialog. - * - * @return array - * The form element. - */ - public function buildFormElement($default_value); - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/AttributeManager.php b/sites/all/modules/contrib/fields/linkit/src/AttributeManager.php deleted file mode 100644 index 99d5a3b9f..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/AttributeManager.php +++ /dev/null @@ -1,29 +0,0 @@ -alterInfo('linkit_attribute'); - $this->setCacheBackend($cache_backend, 'linkit_attributes'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php b/sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php deleted file mode 100644 index 14ba4415c..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php +++ /dev/null @@ -1,16 +0,0 @@ -linkitProfileStorage = $linkit_profile_storage; - $this->resultManager = $resultManager; + $this->suggestionManager = $suggestionManager; } /** @@ -57,7 +55,7 @@ class AutocompleteController implements ContainerInjectionInterface { public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager')->getStorage('linkit_profile'), - $container->get('linkit.result_manager') + $container->get('linkit.suggestion_manager') ); } @@ -67,23 +65,31 @@ 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 $linkit_profile_id + * @param string $linkit_profile_id * The linkit profile id. - * @return JsonResponse + * + * @return \Symfony\Component\HttpFoundation\JsonResponse * A JSON response containing the autocomplete suggestions. */ public function autocomplete(Request $request, $linkit_profile_id) { $this->linkitProfile = $this->linkitProfileStorage->load($linkit_profile_id); - $string = Unicode::strtolower($request->query->get('q')); + $string = $request->query->get('q'); - $matches = $this->resultManager->getResults($this->linkitProfile, $string); + $suggestionCollection = $this->suggestionManager->getSuggestions($this->linkitProfile, Unicode::strtolower($string)); - $json_object = new \stdClass(); - $json_object->matches = $matches; + /* + * 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($json_object); + return new JsonResponse($suggestionCollection); } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php b/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php index d23e7d336..fdefd47ae 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php +++ b/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php @@ -1,10 +1,5 @@ t('Edit %label profile', array('%label' => $linkit_profile->label())); + return $this->t('Edit %label profile', ['%label' => $linkit_profile->label()]); } /** @@ -42,24 +37,7 @@ class LinkitController extends ControllerBase { public function matcherTitle(ProfileInterface $linkit_profile, $plugin_instance_id) { /** @var \Drupal\linkit\MatcherInterface $matcher */ $matcher = $linkit_profile->getMatcher($plugin_instance_id); - return $this->t('Edit %label matcher', array('%label' => $matcher->getLabel())); - } - - /** - * Route title callback. - * - * @param \Drupal\linkit\ProfileInterface $linkit_profile - * The profile. - * @param string $plugin_instance_id - * The plugin instance id. - * - * @return string - * The title for the attribute edit form. - */ - public function attributeTitle(ProfileInterface $linkit_profile, $plugin_instance_id) { - /** @var \Drupal\linkit\AttributeInterface $attribute */ - $attribute = $linkit_profile->getAttribute($plugin_instance_id); - return $this->t('Edit %label attribute', array('%label' => $attribute->getLabel())); + return $this->t('Edit %label matcher', ['%label' => $matcher->getLabel()]); } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php b/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php index 25e9a0f4f..5e533c514 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php +++ b/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php @@ -1,15 +1,9 @@ TRUE, '#size' => 60, - '#process' => array( - array($class, 'processLinkitAutocomplete'), - array($class, 'processGroup'), - ), - '#pre_render' => array( - array($class, 'preRenderLinkitElement'), - array($class, 'preRenderGroup'), - ), + '#process' => [ + [$class, 'processLinkitAutocomplete'], + [$class, 'processGroup'], + ], + '#pre_render' => [ + [$class, 'preRenderLinkitElement'], + [$class, 'preRenderGroup'], + ], '#theme' => 'input__textfield', - '#theme_wrappers' => array('form_element'), - ); + '#theme_wrappers' => ['form_element'], + ]; } /** @@ -63,7 +57,7 @@ class Linkit extends FormElement { $access = FALSE; if (!empty($element['#autocomplete_route_name'])) { - $parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : array(); + $parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : []; $url = Url::fromRoute($element['#autocomplete_route_name'], $parameters)->toString(TRUE); /** @var \Drupal\Core\Access\AccessManagerInterface $access_manager */ $access_manager = \Drupal::service('access_manager'); @@ -88,21 +82,10 @@ class Linkit extends FormElement { } /** - * Prepares a #type 'linkit' render element for input.html.twig. - * - * @param array $element - * An associative array containing the properties of the element. - * Properties used: #title, #value, #description, #size, #attributes. - * - * @return array - * The $element with prepared variables ready for input.html.twig. + * {@inheritdoc} */ public static function preRenderLinkitElement($element) { - $element['#attributes']['type'] = 'text'; - Element::setAttributes($element, array('id', 'name', 'value', 'size')); - static::setAttributes($element, array('form-text')); - - return $element; + return Textfield::preRenderTextfield($element); } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php b/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php index 785ff6365..651242f83 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php +++ b/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php @@ -1,15 +1,9 @@ getAttributes()->get($attribute_id); - } - - /** - * {@inheritdoc} - */ - public function getAttributes() { - if (!$this->attributeCollection) { - $this->attributeCollection = new AttributeCollection($this->getAttributeManager(), $this->attributes); - $this->attributeCollection->sort(); - } - return $this->attributeCollection; - } - - /** - * {@inheritdoc} - */ - public function addAttribute(array $configuration) { - $this->getAttributes()->addInstanceId($configuration['id'], $configuration); - return $configuration['id']; - } - - /** - * {@inheritdoc} - */ - public function removeAttribute($attribute_id) { - unset($this->attributes[$attribute_id]); - $this->getAttributes()->removeInstanceId($attribute_id); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAttributeConfig($attribute_id, array $configuration) { - $this->attributes[$attribute_id] = $configuration; - $this->getAttributes()->setInstanceConfiguration($attribute_id, $configuration); - return $this; - } - /** * {@inheritdoc} */ @@ -186,7 +113,7 @@ class Profile extends ConfigEntityBase implements ProfileInterface, EntityWithPl */ public function getMatchers() { if (!$this->matcherCollection) { - $this->matcherCollection = new MatcherCollection($this->getMatcherManager(), $this->matchers); + $this->matcherCollection = new MatcherCollection(\Drupal::service('plugin.manager.linkit.matcher'), $this->matchers); $this->matcherCollection->sort(); } return $this->matcherCollection; @@ -223,30 +150,9 @@ class Profile extends ConfigEntityBase implements ProfileInterface, EntityWithPl * {@inheritdoc} */ public function getPluginCollections() { - return array( - 'attributes' => $this->getAttributes(), + return [ 'matchers' => $this->getMatchers(), - ); - } - - /** - * Returns the attribute manager. - * - * @return \Drupal\Component\Plugin\PluginManagerInterface - * The attribute manager. - */ - protected function getAttributeManager() { - return \Drupal::service('plugin.manager.linkit.attribute'); - } - - /** - * Returns the matcher manager. - * - * @return \Drupal\Component\Plugin\PluginManagerInterface - * The matcher manager. - */ - protected function getMatcherManager() { - return \Drupal::service('plugin.manager.linkit.matcher'); + ]; } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php deleted file mode 100644 index 059ef512e..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php +++ /dev/null @@ -1,166 +0,0 @@ -manager = $manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.linkit.attribute') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return "linkit_attribute_add_form"; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, ProfileInterface $linkit_profile = NULL) { - $this->linkitProfile = $linkit_profile; - - $form['#attached']['library'][] = 'linkit/linkit.admin'; - $header = [ - 'label' => $this->t('Attributes'), - 'description' => $this->t('Description'), - ]; - - $form['plugin'] = [ - '#type' => 'tableselect', - '#header' => $header, - '#options' => $this->buildRows(), - '#empty' => $this->t('No attributes available.'), - '#multiple' => FALSE, - ]; - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save and continue'), - '#submit' => ['::submitForm'], - '#tableselect' => TRUE, - '#button_type' => 'primary', - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - if (empty($form_state->getValue('plugin'))) { - $form_state->setErrorByName('plugin', $this->t('No attribute selected.')); - } - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $form_state->cleanValues(); - - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->manager->createInstance($form_state->getValue('plugin')); - $plugin_id = $this->linkitProfile->addAttribute($plugin->getConfiguration()); - $this->linkitProfile->save(); - - $this->logger('linkit')->notice('Added %label attribute to the @profile profile.', [ - '%label' => $this->linkitProfile->getAttribute($plugin_id)->getLabel(), - '@profile' => $this->linkitProfile->label(), - ]); - - $is_configurable = $plugin instanceof ConfigurableAttributeInterface; - if ($is_configurable) { - $form_state->setRedirect('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $plugin_id, - ]); - } - else { - drupal_set_message($this->t('Added %label attribute.', ['%label' => $plugin->getLabel()])); - - $form_state->setRedirect('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - } - - /** - * Builds the table rows. - * - * Only attributes that is not already applied to the profile are shown. - * - * @return array - * An array of table rows. - */ - private function buildRows() { - $rows = []; - - $applied_plugins = $this->linkitProfile->getAttributes()->getConfiguration(); - $all_plugins = $this->manager->getDefinitions(); - uasort($all_plugins, function ($a, $b) { - return strnatcasecmp($a['label'], $b['label']); - }); - foreach (array_diff_key($all_plugins, $applied_plugins) as $definition) { - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->manager->createInstance($definition['id']); - - $row = [ - 'label' => (string) $plugin->getLabel(), - 'description' => (string) $plugin->getDescription(), - ]; - - $rows[$plugin->getPluginId()] = $row; - } - - return $rows; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php deleted file mode 100644 index d31e44b01..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php +++ /dev/null @@ -1,92 +0,0 @@ -t('Are you sure you want to delete the @plugin attribute from the %profile profile?', ['%profile' => $this->linkitProfile->label(), '@plugin' => $this->linkitAttribute->getLabel()]); - } - - /** - * {@inheritdoc} - */ - public function getCancelUrl() { - return Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'linkit_attribute_delete_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, ProfileInterface $linkit_profile = NULL, $plugin_instance_id = NULL) { - $this->linkitProfile = $linkit_profile; - - if (!$this->linkitProfile->getAttributes()->has($plugin_instance_id)) { - throw new NotFoundHttpException(); - } - - $this->linkitAttribute = $this->linkitProfile->getAttribute($plugin_instance_id); - return parent::buildForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - if ($this->linkitProfile->getAttributes()->has($this->linkitAttribute->getPluginId())) { - $this->linkitProfile->removeAttribute($this->linkitAttribute->getPluginId()); - $this->linkitProfile->save(); - - drupal_set_message($this->t('The attribute %label has been deleted.', ['%label' => $this->linkitAttribute->getLabel()])); - $this->logger('linkit')->notice('The attribute %label has been deleted in the @profile profile.', [ - '%label' => $this->linkitAttribute->getLabel(), - '@profile' => $this->linkitProfile->label(), - ]); - } - - $form_state->setRedirect('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php deleted file mode 100644 index 0b76601fb..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php +++ /dev/null @@ -1,96 +0,0 @@ -linkitProfile = $linkit_profile; - $this->linkitAttribute = $this->linkitProfile->getAttribute($plugin_instance_id); - $form['data'] = [ - '#tree' => true, - ]; - - $form['data'] += $this->linkitAttribute->buildConfigurationForm($form, $form_state); - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => $this->t('Save changes'), - '#submit' => array('::submitForm'), - '#button_type' => 'primary', - ); - $form['actions']['delete'] = array( - '#type' => 'link', - '#title' => $this->t('Delete'), - '#url' => Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $this->linkitAttribute->getPluginId(), - ]), - '#attributes' => [ - 'class' => ['button', 'button--danger'], - ], - ); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $form_state->cleanValues(); - $plugin_data = (new FormState())->setValues($form_state->getValue('data')); - $this->linkitAttribute->submitConfigurationForm($form, $plugin_data); - $this->linkitProfile->save(); - - drupal_set_message($this->t('Saved %label configuration.', array('%label' => $this->linkitAttribute->getLabel()))); - $this->logger('linkit')->notice('The attribute %label has been updated in the @profile profile.', [ - '%label' => $this->linkitAttribute->getLabel(), - '@profile' => $this->linkitProfile->label(), - ]); - - $form_state->setRedirect('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php deleted file mode 100644 index 267dd61d5..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php +++ /dev/null @@ -1,156 +0,0 @@ -manager = $manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.linkit.attribute') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return "linkit_attribute_overview_form"; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, ProfileInterface $linkit_profile = NULL) { - $this->linkitProfile = $linkit_profile; - - $form['plugins'] = [ - '#type' => 'table', - '#header' => [ - $this->t('Attribute'), - $this->t('Description'), - $this->t('Weight'), - $this->t('Operations'), - ], - '#empty' => $this->t('No attributes added.'), - '#tabledrag' => [ - [ - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'plugin-order-weight', - ], - ], - ]; - - foreach ($this->linkitProfile->getAttributes() as $plugin) { - $key = $plugin->getPluginId(); - - $form['plugins'][$key]['#attributes']['class'][] = 'draggable'; - $form['plugins'][$key]['#weight'] = $plugin->getWeight(); - - $form['plugins'][$key]['label'] = [ - '#plain_text' => (string) $plugin->getLabel(), - ]; - - $form['plugins'][$key]['description'] = [ - '#plain_text' => (string) $plugin->getDescription(), - ]; - - $form['plugins'][$key]['weight'] = [ - '#type' => 'weight', - '#title' => t('Weight for @title', ['@title' => (string) $plugin->getLabel()]), - '#title_display' => 'invisible', - '#default_value' => $plugin->getWeight(), - '#attributes' => ['class' => ['plugin-order-weight']], - ]; - - $form['plugins'][$key]['operations'] = [ - '#type' => 'operations', - '#links' => [], - ]; - - $is_configurable = $plugin instanceof ConfigurableAttributeInterface; - if ($is_configurable) { - $form['plugins'][$key]['operations']['#links']['edit'] = [ - 'title' => t('Edit'), - 'url' => Url::fromRoute('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $key, - ]), - ]; - } - - $form['plugins'][$key]['operations']['#links']['delete'] = [ - 'title' => t('Delete'), - 'url' => Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $key, - ]), - ]; - } - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save'), - '#button_type' => 'primary', - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - foreach ($form_state->getValue('plugins') as $id => $plugin_data) { - if ($this->linkitProfile->getAttributes()->has($id)) { - $this->linkitProfile->getAttribute($id)->setWeight($plugin_data['weight']); - } - } - $this->linkitProfile->save(); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php b/sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php deleted file mode 100644 index 8f3b8f571..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php +++ /dev/null @@ -1,207 +0,0 @@ -editorStorage = $editor_storage; - $this->linkitProfileStorage = $linkit_profile_storage; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity.manager')->getStorage('editor'), - $container->get('entity.manager')->getStorage('linkit_profile') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'linkit_editor_dialog_form'; - } - - /** - * {@inheritdoc} - * - * @param \Drupal\filter\Entity\FilterFormat $filter_format - * The filter format for which this dialog corresponds. - */ - public function buildForm(array $form, FormStateInterface $form_state, FilterFormat $filter_format = NULL) { - // The default values are set directly from \Drupal::request()->request, - // provided by the editor plugin opening the dialog. - $user_input = $form_state->getUserInput(); - $input = isset($user_input['editor_object']) ? $user_input['editor_object'] : []; - - /** @var \Drupal\editor\EditorInterface $editor */ - $editor = $this->editorStorage->load($filter_format->id()); - $linkit_profile_id = $editor->getSettings()['plugins']['linkit']['linkit_profile']; - $this->linkitProfile = $this->linkitProfileStorage->load($linkit_profile_id); - - $form['#tree'] = TRUE; - $form['#attached']['library'][] = 'editor/drupal.editor.dialog'; - $form['#prefix'] = 'title attribute to that of the (translated) referenced content'),
+ '#default_value' => $this->settings['title'],
+ '#attached' => [
+ 'library' => ['linkit/linkit.filter_html.admin'],
+ ],
+ ];
+ return $form;
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php
deleted file mode 100644
index e0a609f1b..000000000
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php
+++ /dev/null
@@ -1,38 +0,0 @@
- 'textfield',
- '#title' => t('Accesskey'),
- '#default_value' => $default_value,
- '#maxlength' => 255,
- '#size' => 40,
- '#placeholder' => t('The "accesskey" attribute value'),
- ];
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php
deleted file mode 100644
index 03787e7b4..000000000
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php
+++ /dev/null
@@ -1,41 +0,0 @@
- 'textfield',
-// '#title' => t('Class'),
-// '#maxlength' => 255,
-// '#size' => 40,
-// ];
-// }
-//
-//}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php
deleted file mode 100644
index 817b1ba09..000000000
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php
+++ /dev/null
@@ -1,38 +0,0 @@
- 'textfield',
- '#title' => t('Id'),
- '#default_value' => $default_value,
- '#maxlength' => 255,
- '#size' => 40,
- '#placeholder' => t('The "id" attribute value'),
- ];
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php
deleted file mode 100644
index 0c3286767..000000000
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php
+++ /dev/null
@@ -1,38 +0,0 @@
- 'textfield',
- '#title' => t('Relationship'),
- '#default_value' => $default_value,
- '#maxlength' => 255,
- '#size' => 40,
- '#placeholder' => t('The "rel" attribute value'),
- ];
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php
deleted file mode 100644
index ce4833757..000000000
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php
+++ /dev/null
@@ -1,96 +0,0 @@
-configuration['widget_type']) {
- case self::SELECT_LIST:
- return [
- '#type' => 'select',
- '#title' => t('Target'),
- '#options' => [
- '' => '',
- '_blank' => t('New window (_blank)'),
- '_top' => t('Top window (_top)'),
- '_self' => t('Same window (_self)'),
- '_parent' => t('Parent window (_parent)')
- ],
- '#default_value' => $default_value,
- ];
- case self::SIMPLE_CHECKBOX:
- return [
- '#type' => 'checkbox',
- '#title' => t('Open in new window'),
- '#default_value' => $default_value,
- '#return_value' => '_blank',
- ];
- }
-
- return [];
- }
-
- /**
- * {@inheritdoc}
- */
- public function defaultConfiguration() {
- return parent::defaultConfiguration() + [
- 'widget_type' => self::SIMPLE_CHECKBOX,
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
- $form['widget_type'] = [
- '#type' => 'radios',
- '#title' => $this->t('Widget type'),
- '#default_value' => $this->configuration['widget_type'],
- '#options' => [
- self::SELECT_LIST => $this->t('Selectlist with predefined targets.'),
- self::SIMPLE_CHECKBOX => $this->t('Simple checkbox to allow links to be opened in a new browser window or tab.'),
- ],
- ];
-
- return $form;
- }
-
- /**
- * {@inheritdoc}
- */
- public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
- }
-
- /**
- * {@inheritdoc}
- */
- public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
- $this->configuration['widget_type'] = $form_state->getValue('widget_type');
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php
deleted file mode 100644
index 6cd8f3e4b..000000000
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php
+++ /dev/null
@@ -1,82 +0,0 @@
- 'textfield',
- '#title' => t('Title'),
- '#default_value' => $default_value,
- '#maxlength' => 255,
- '#size' => 40,
- '#placeholder' => t('The "title" attribute value'),
- ];
-
- if ($this->configuration['automatic_title']) {
- $element['#attached']['library'][] = 'linkit/linkit.attribute.title';
- $element['#placeholder'] = t('The "title" attribute value (auto populated)');
- }
-
- return $element;
- }
-
- /**
- * {@inheritdoc}
- */
- public function defaultConfiguration() {
- return parent::defaultConfiguration() + [
- 'automatic_title' => FALSE,
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
- $form['automatic_title'] = [
- '#type' => 'checkbox',
- '#title' => $this->t('Automatically populate title'),
- '#default_value' => $this->configuration['automatic_title'],
- '#description' => $this->t('Automatically populate the title attribute with the title from the match selection.'),
- ];
-
- return $form;
- }
-
- /**
- * {@inheritdoc}
- */
- public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
- }
-
- /**
- * {@inheritdoc}
- */
- public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
- $this->configuration['automatic_title'] = $form_state->getValue('automatic_title');
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php
new file mode 100644
index 000000000..e9326b933
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php
@@ -0,0 +1,38 @@
+ ['contact'],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function buildEntityQuery($search_string) {
+ $query = parent::buildEntityQuery($search_string);
+
+ // Remove the personal contact form from the suggestion list.
+ $query->condition('id', 'personal', '<>');
+
+ return $query;
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php
new file mode 100644
index 000000000..c9513d94d
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php
@@ -0,0 +1,40 @@
+setLabel($this->t('E-mail @email', ['@email' => $string]))
+ ->setPath('mailto:' . Html::escape($string))
+ ->setGroup($this->t('E-mail'))
+ ->setDescription($this->t('Opens your mail client ready to e-mail @email', ['@email' => $string]));
+
+ $suggestions->addSuggestion($suggestion);
+ }
+ return $suggestions;
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php
index 33838206a..a8a85c8f3 100644
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php
+++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php
@@ -1,24 +1,31 @@
database = $database;
- $this->entityManager = $entity_manager;
+ $this->entityTypeManager = $entity_type_manager;
+ $this->entityTypeBundleInfo = $entity_type_bundle_info;
+ $this->entityRepository = $entity_repository;
$this->moduleHandler = $module_handler;
$this->currentUser = $current_user;
- $this->target_type = $plugin_definition['target_entity'];
+ $this->targetType = $plugin_definition['target_entity'];
+ $this->substitutionManager = $substitution_manager;
}
/**
@@ -89,9 +120,12 @@ class EntityMatcher extends ConfigurableMatcherBase {
$plugin_id,
$plugin_definition,
$container->get('database'),
- $container->get('entity.manager'),
+ $container->get('entity_type.manager'),
+ $container->get('entity_type.bundle.info'),
+ $container->get('entity.repository'),
$container->get('module_handler'),
- $container->get('current_user')
+ $container->get('current_user'),
+ $container->get('plugin.manager.linkit.substitution')
);
}
@@ -100,12 +134,12 @@ class EntityMatcher extends ConfigurableMatcherBase {
*/
public function getSummary() {
$summery = parent::getSummary();
- $entity_type = $this->entityManager->getDefinition($this->target_type);
+ $entity_type = $this->entityTypeManager->getDefinition($this->targetType);
- $result_description = $this->configuration['result_description'];
- if (!empty($result_description)) {
- $summery[] = $this->t('Result description: @result_description', [
- '@result_description' => $result_description
+ $metadata = $this->configuration['metadata'];
+ if (!empty($metadata)) {
+ $summery[] = $this->t('Metadata: @metadata', [
+ '@metadata' => $metadata,
]);
}
@@ -114,7 +148,7 @@ class EntityMatcher extends ConfigurableMatcherBase {
$bundles = [];
if ($has_bundle_filter) {
- $bundles_info = $this->entityManager->getBundleInfo($this->target_type);
+ $bundles_info = $this->entityTypeBundleInfo->getBundleInfo($this->targetType);
foreach ($this->configuration['bundles'] as $bundle) {
$bundles[] = $bundles_info[$bundle]['label'];
}
@@ -136,55 +170,93 @@ class EntityMatcher extends ConfigurableMatcherBase {
* {@inheritdoc}
*/
public function defaultConfiguration() {
- return parent::defaultConfiguration() + [
- 'result_description' => '',
+ return [
+ 'metadata' => '',
'bundles' => [],
'group_by_bundle' => FALSE,
- ];
+ 'substitution_type' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION,
+ ] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
- $entity_type = $this->entityManager->getDefinition($this->target_type);
- $form['result_description'] = [
- '#title' => $this->t('Result description'),
- '#type' => 'textfield',
- '#default_value' => $this->configuration['result_description'],
- '#size' => 120,
- '#maxlength' => 255,
+ $entity_type = $this->entityTypeManager->getDefinition($this->targetType);
+
+ $form['metadata'] = [
+ '#type' => 'details',
+ '#title' => $this->t('Suggestion metadata'),
+ '#open' => TRUE,
'#weight' => -100,
];
- $this->insertTokenList($form, [$this->target_type]);
+ $form['metadata']['metadata'] = [
+ '#title' => $this->t('Metadata'),
+ '#type' => 'textfield',
+ '#default_value' => $this->configuration['metadata'],
+ '#description' => $this->t('Metadata is shown together with each suggestion in the suggestion list.'),
+ '#size' => 120,
+ '#maxlength' => 255,
+ '#weight' => 0,
+ ];
+
+ $this->insertTokenList($form, [$this->targetType]);
// Filter the possible bundles to use if the entity has bundles.
if ($entity_type->hasKey('bundle')) {
$bundle_options = [];
- foreach ($this->entityManager->getBundleInfo($this->target_type) as $bundle_name => $bundle_info) {
+ foreach ($this->entityTypeBundleInfo->getBundleInfo($this->targetType) as $bundle_name => $bundle_info) {
$bundle_options[$bundle_name] = $bundle_info['label'];
}
- $form['bundles'] = [
- '#type' => 'checkboxes',
- '#title' => $this->t('Restrict to the selected bundles'),
- '#options' => $bundle_options,
- '#default_value' => $this->configuration['bundles'],
- '#description' => $this->t('If none of the checkboxes is checked, allow all bundles.'),
- '#element_validate' => [[get_class($this), 'elementValidateFilter']],
- '#weight' => -50,
+ $form['bundle_restrictions'] = [
+ '#type' => 'details',
+ '#title' => $this->t('Bundle restrictions'),
+ '#open' => TRUE,
+ '#weight' => -90,
];
- // Group the results by bundle.
- $form['group_by_bundle'] = [
+ $form['bundle_restrictions']['bundles'] = [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Restrict suggestions to the selected bundles'),
+ '#options' => $bundle_options,
+ '#default_value' => $this->configuration['bundles'],
+ '#description' => $this->t('If none of the checkboxes is checked, all bundles are allowed.'),
+ '#element_validate' => [[get_class($this), 'elementValidateFilter']],
+ ];
+
+ $form['bundle_grouping'] = [
+ '#type' => 'details',
+ '#title' => $this->t('Bundle grouping'),
+ '#open' => TRUE,
+ ];
+
+ // Group the suggestions by bundle.
+ $form['bundle_grouping']['group_by_bundle'] = [
'#type' => 'checkbox',
'#title' => $this->t('Group by bundle'),
'#default_value' => $this->configuration['group_by_bundle'],
- '#weight' => -50,
+ '#description' => $this->t('Group suggestions by their bundle.'),
];
}
+ $substitution_options = $this->substitutionManager->getApplicablePluginsOptionList($this->targetType);
+ $form['substitution'] = [
+ '#type' => 'details',
+ '#title' => $this->t('URL substitution'),
+ '#open' => TRUE,
+ '#weight' => 100,
+ '#access' => count($substitution_options) !== 1,
+ ];
+ $form['substitution']['substitution_type'] = [
+ '#title' => $this->t('Substitution Type'),
+ '#type' => 'select',
+ '#default_value' => $this->configuration['substitution_type'],
+ '#options' => $substitution_options,
+ '#description' => $this->t('Configure how the selected entity should be transformed into a URL for insertion.'),
+ ];
+
return $form;
}
@@ -198,9 +270,10 @@ class EntityMatcher extends ConfigurableMatcherBase {
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
- $this->configuration['result_description'] = $form_state->getValue('result_description');
+ $this->configuration['metadata'] = $form_state->getValue('metadata');
$this->configuration['bundles'] = $form_state->getValue('bundles');
$this->configuration['group_by_bundle'] = $form_state->getValue('group_by_bundle');
+ $this->configuration['substitution_type'] = $form_state->getValue('substitution_type');
}
/**
@@ -214,55 +287,64 @@ class EntityMatcher extends ConfigurableMatcherBase {
/**
* {@inheritdoc}
*/
- public function getMatches($string) {
+ public function execute($string) {
+ $suggestions = new SuggestionCollection();
$query = $this->buildEntityQuery($string);
- $result = $query->execute();
+ $query_result = $query->execute();
+ $url_results = $this->findEntityIdByUrl($string);
+ $result = array_merge($query_result, $url_results);
+ // If no results, return an empty suggestion collection.
if (empty($result)) {
- return [];
+ return $suggestions;
}
- $matches = [];
- $entities = $this->entityManager->getStorage($this->target_type)->loadMultiple($result);
+ $entities = $this->entityTypeManager->getStorage($this->targetType)->loadMultiple($result);
- foreach ($entities as $entity_id => $entity) {
+ foreach ($entities as $entity) {
// Check the access against the defined entity access handler.
/** @var \Drupal\Core\Access\AccessResultInterface $access */
$access = $entity->access('view', $this->currentUser, TRUE);
+
if (!$access->isAllowed()) {
continue;
}
- $matches[] = [
- 'title' => $this->buildLabel($entity),
- 'description' => $this->buildDescription($entity),
- 'path' => $this->buildPath($entity),
- 'group' => $this->buildGroup($entity),
- ];
+ $entity = $this->entityRepository->getTranslationFromContext($entity);
+ $suggestion = $this->createSuggestion($entity);
+ $suggestions->addSuggestion($suggestion);
}
- return $matches;
+ return $suggestions;
}
/**
* Builds an EntityQuery to get entities.
*
- * @param $match
+ * @param string $search_string
* Text to match the label against.
*
* @return \Drupal\Core\Entity\Query\QueryInterface
* The EntityQuery object with the basic conditions and sorting applied to
* it.
*/
- protected function buildEntityQuery($match) {
- $match = $this->database->escapeLike($match);
+ protected function buildEntityQuery($search_string) {
+ $search_string = $this->database->escapeLike($search_string);
- $entity_type = $this->entityManager->getDefinition($this->target_type);
- $query = $this->entityManager->getStorage($this->target_type)->getQuery();
+ $entity_type = $this->entityTypeManager->getDefinition($this->targetType);
+ $query = $this->entityTypeManager->getStorage($this->targetType)->getQuery();
$label_key = $entity_type->getKey('label');
if ($label_key) {
- $query->condition($label_key, '%' . $match . '%', 'LIKE');
+ // For configuration entities, the condition needs to be CONTAINS as
+ // the matcher does not support LIKE.
+ if ($entity_type instanceof ConfigEntityTypeInterface) {
+ $query->condition($label_key, $search_string, 'CONTAINS');
+ }
+ else {
+ $query->condition($label_key, '%' . $search_string . '%', 'LIKE');
+ }
+
$query->sort($label_key, 'ASC');
}
@@ -271,19 +353,51 @@ class EntityMatcher extends ConfigurableMatcherBase {
$query->condition($bundle_key, $this->configuration['bundles'], 'IN');
}
- // Add tags to let other modules alter the query.
- $query->addTag('linkit_entity_autocomplete');
- $query->addTag('linkit_entity_' . $this->target_type . '_autocomplete');
-
- // Add access tag for the query.
- $query->addTag('entity_access');
- $query->addTag($this->target_type . '_access');
+ $this->addQueryTags($query);
return $query;
}
/**
- * Builds the label string used in the match array.
+ * Adds query tags to the query.
+ *
+ * @param \Drupal\Core\Entity\Query\QueryInterface $query
+ * A query to add tags to.
+ */
+ protected function addQueryTags(QueryInterface $query) {
+ // Add tags to let other modules alter the query.
+ $query->addTag('linkit_entity_autocomplete');
+ $query->addTag('linkit_entity_' . $this->targetType . '_autocomplete');
+
+ // Add access tag for the query.
+ $query->addTag('entity_access');
+ $query->addTag($this->targetType . '_access');
+ }
+
+ /**
+ * Creates a suggestion.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The matched entity.
+ *
+ * @return \Drupal\linkit\Suggestion\EntitySuggestion
+ * A suggestion object with populated entity data.
+ */
+ protected function createSuggestion(EntityInterface $entity) {
+ $suggestion = new EntitySuggestion();
+ $suggestion->setLabel($this->buildLabel($entity))
+ ->setGroup($this->buildGroup($entity))
+ ->setDescription($this->buildDescription($entity))
+ ->setEntityUuid($entity->uuid())
+ ->setEntityTypeId($entity->getEntityTypeId())
+ ->setSubstitutionId($this->configuration['substitution_type'])
+ ->setPath($this->buildPath($entity));
+
+ return $suggestion;
+ }
+
+ /**
+ * Builds the label string used in the suggestion.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The matched entity.
@@ -291,39 +405,26 @@ class EntityMatcher extends ConfigurableMatcherBase {
* @return string
* The label for this entity.
*/
- protected function buildLabel($entity) {
+ protected function buildLabel(EntityInterface $entity) {
return Html::escape($entity->label());
}
/**
- * Builds the description string used in the match array.
+ * Builds the metadata string used in the suggestion.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The matched entity.
*
* @return string
- * The description for this entity.
+ * The metadata for this entity.
*/
- protected function buildDescription($entity) {
- $description = \Drupal::token()->replace($this->configuration['result_description'], [$this->target_type => $entity], []);
+ protected function buildDescription(EntityInterface $entity) {
+ $description = \Drupal::token()->replace($this->configuration['metadata'], [$this->targetType => $entity], ['clear' => TRUE]);
return LinkitXss::descriptionFilter($description);
}
/**
- * Builds the path string used in the match array.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The matched entity.
- *
- * @return string
- * The URL for this entity.
- */
- protected function buildPath($entity) {
- return $entity->toUrl()->toString();
- }
-
- /**
- * Builds the group string used in the match array.
+ * Builds the group string used in the suggestion.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The matched entity.
@@ -331,13 +432,13 @@ class EntityMatcher extends ConfigurableMatcherBase {
* @return string
* The match group for this entity.
*/
- protected function buildGroup($entity) {
+ protected function buildGroup(EntityInterface $entity) {
$group = $entity->getEntityType()->getLabel();
// If the entities by this entity should be grouped by bundle, get the
// name and append it to the group.
if ($this->configuration['group_by_bundle']) {
- $bundles = $this->entityManager->getBundleInfo($entity->getEntityTypeId());
+ $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
$bundle_label = $bundles[$entity->bundle()]['label'];
$group .= ' - ' . $bundle_label;
}
@@ -345,4 +446,43 @@ class EntityMatcher extends ConfigurableMatcherBase {
return $group;
}
+ /**
+ * Builds the path string used in the suggestion.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The matched entity.
+ *
+ * @return string
+ * The path for this entity.
+ */
+ protected function buildPath(EntityInterface $entity) {
+ return $entity->toUrl('canonical', ['path_processing' => FALSE])->toString();
+ }
+
+ /**
+ * Finds entity id from the given input.
+ *
+ * @param string $user_input
+ * The string to url parse.
+ *
+ * @return array
+ * An array with an entity id if the input can be parsed as an internal url
+ * and a match is found, otherwise an empty array.
+ */
+ protected function findEntityIdByUrl($user_input) {
+ $result = [];
+
+ try {
+ $params = Url::fromUserInput($user_input)->getRouteParameters();
+ if (key($params) === $this->targetType) {
+ $result = [end($params)];
+ }
+ }
+ catch (Exception $e) {
+ // Do nothing.
+ }
+
+ return $result;
+ }
+
}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php
index cb39ccfe6..28252a2fd 100644
--- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php
+++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php
@@ -1,21 +1,19 @@
t('Show image dimensions: @show_image_dimensions', [
+ if (!empty($this->configuration['file_extensions'])) {
+ $summary[] = $this->t('Limit matches to the following file extensions: @file_extensions', [
+ '@file_extensions' => str_replace(' ', ', ', $this->configuration['file_extensions']),
+ ]);
+ }
+
+ $summary[] = $this->t('Show image dimensions: @show_image_dimensions', [
'@show_image_dimensions' => $this->configuration['images']['show_dimensions'] ? $this->t('Yes') : $this->t('No'),
]);
- $summery[] = $this->t('Show image thumbnail: @show_image_thumbnail', [
+ $summary[] = $this->t('Show image thumbnail: @show_image_thumbnail', [
'@show_image_thumbnail' => $this->configuration['images']['show_thumbnail'] ? $this->t('Yes') : $this->t('No'),
]);
if ($this->moduleHandler->moduleExists('image') && $this->configuration['images']['show_thumbnail']) {
$image_style = ImageStyle::load($this->configuration['images']['thumbnail_image_style']);
- if (!is_null($image_style)) {
- $summery[] = $this->t('Thumbnail style: @thumbnail_style', [
- '@thumbnail_style' => $image_style->label(),
+ if (!is_null($image_style)) {
+ $summary[] = $this->t('Thumbnail style: @thumbnail_style', [
+ '@thumbnail_style' => $image_style->label(),
]);
}
}
- return $summery;
+ return $summary;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
- return parent::defaultConfiguration() + [
+ return [
+ 'file_extensions' => '',
+ 'file_status' => FILE_STATUS_PERMANENT,
'images' => [
'show_dimensions' => FALSE,
'show_thumbnail' => FALSE,
'thumbnail_image_style' => 'linkit_result_thumbnail',
],
- ];
+ 'substitution_type' => 'file',
+ ] + parent::defaultConfiguration();
}
/**
@@ -82,28 +89,46 @@ class FileMatcher extends EntityMatcher {
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
- $form['images'] = array(
+ $form['extensions'] = [
'#type' => 'details',
- '#title' => t('Image file settings'),
- '#description' => t('Extra settings for image files in the result.'),
+ '#title' => $this->t('File extensions'),
+ '#open' => TRUE,
+ '#weight' => -100,
+ ];
+
+ $file_extensions = str_replace(' ', ', ', $this->configuration['file_extensions']);
+ $form['extensions']['file_extensions'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Allowed file extensions'),
+ '#default_value' => $file_extensions,
+ '#description' => $this->t('Separate extensions with a space or comma and do not include the leading dot.'),
+ '#element_validate' => [['\Drupal\file\Plugin\Field\FieldType\FileItem', 'validateExtensions']],
+ '#maxlength' => 256,
+ ];
+
+ $form['images'] = [
+ '#type' => 'details',
+ '#title' => $this->t('Image file settings'),
+ '#description' => $this->t('Extra settings for image files in the result.'),
+ '#open' => TRUE,
'#tree' => TRUE,
- );
+ ];
$form['images']['show_dimensions'] = [
- '#title' => t('Show pixel dimensions'),
+ '#title' => $this->t('Show pixel dimensions'),
'#type' => 'checkbox',
'#default_value' => $this->configuration['images']['show_dimensions'],
];
if ($this->moduleHandler->moduleExists('image')) {
$form['images']['show_thumbnail'] = [
- '#title' => t('Show thumbnail'),
+ '#title' => $this->t('Show thumbnail'),
'#type' => 'checkbox',
'#default_value' => $this->configuration['images']['show_thumbnail'],
];
$form['images']['thumbnail_image_style'] = [
- '#title' => t('Thumbnail image style'),
+ '#title' => $this->t('Thumbnail image style'),
'#type' => 'select',
'#default_value' => $this->configuration['images']['thumbnail_image_style'],
'#options' => image_style_options(FALSE),
@@ -124,6 +149,8 @@ class FileMatcher extends EntityMatcher {
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state);
+ $this->configuration['file_extensions'] = $form_state->getValue('file_extensions');
+
$values = $form_state->getValue('images');
if (!$values['show_thumbnail']) {
$values['thumbnail_image_style'] = NULL;
@@ -135,9 +162,19 @@ class FileMatcher extends EntityMatcher {
/**
* {@inheritdoc}
*/
- protected function buildEntityQuery($match) {
- $query = parent::buildEntityQuery($match);
- $query->condition('status', FILE_STATUS_PERMANENT);
+ protected function buildEntityQuery($search_string) {
+ $query = parent::buildEntityQuery($search_string);
+
+ $query->condition('status', $this->configuration['file_status']);
+
+ if (!empty($this->configuration['file_extensions'])) {
+ $file_extensions = explode(' ', $this->configuration['file_extensions']);
+ $group = $query->orConditionGroup();
+ foreach ($file_extensions as $file_extension) {
+ $group->condition('filename', '%\.' . $this->database->escapeLike($file_extension), 'LIKE');
+ }
+ $query->condition($group);
+ }
return $query;
}
@@ -145,8 +182,8 @@ class FileMatcher extends EntityMatcher {
/**
* {@inheritdoc}
*/
- protected function buildDescription($entity) {
- $description_array = array();
+ protected function buildDescription(EntityInterface $entity) {
+ $description_array = [];
$description_array[] = parent::buildDescription($entity);
@@ -161,29 +198,27 @@ class FileMatcher extends EntityMatcher {
}
if ($this->configuration['images']['show_thumbnail'] && $this->moduleHandler->moduleExists('image')) {
- $image_element = array(
+ $image_element = [
'#weight' => -10,
'#theme' => 'image_style',
'#style_name' => $this->configuration['images']['thumbnail_image_style'],
'#uri' => $entity->getFileUri(),
- );
+ ];
$description_array[] = (string) \Drupal::service('renderer')->render($image_element);
}
}
- $description = implode(' -
-
-
'
+ filter_html_help: true
+ filter_html_nofollow: false
diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml
new file mode 100644
index 000000000..1bd9a2b6f
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml
@@ -0,0 +1,8 @@
+uuid: 69cd7d6b-3c80-4f49-9631-7fbd7b011d5d
+langcode: en
+status: true
+dependencies: { }
+name: 'Format 2'
+format: format_2
+weight: 0
+filters: { }
diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml
new file mode 100644
index 000000000..eb14f97a5
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml
@@ -0,0 +1,17 @@
+uuid: ff6b71a0-5051-4857-a0a8-28a670b7317d
+langcode: en
+status: true
+dependencies: { }
+name: 'Format 3'
+format: format_3
+weight: 0
+filters:
+ filter_html:
+ id: filter_html
+ provider: filter
+ status: true
+ weight: -10
+ settings:
+ allowed_html: ' -
-
-
'
+ filter_html_help: true
+ filter_html_nofollow: false
diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php
new file mode 100644
index 000000000..07a60f148
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php
@@ -0,0 +1,73 @@
+insert('config')
+ ->fields([
+ 'collection',
+ 'name',
+ 'data',
+ ])
+ ->values([
+ 'collection' => '',
+ 'name' => 'linkit.linkit_profile.' . $config['id'],
+ 'data' => serialize($config),
+ ])
+ ->execute();
+}
+
+// Configuration for text formats.
+$configs = [];
+$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/filter.format.format_1.yml'));
+$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/filter.format.format_2.yml'));
+$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/filter.format.format_3.yml'));
+foreach ($configs as $config) {
+ $connection->insert('config')
+ ->fields([
+ 'collection',
+ 'name',
+ 'data',
+ ])
+ ->values([
+ 'collection' => '',
+ 'name' => 'filter.format.' . $config['format'],
+ 'data' => serialize($config),
+ ])
+ ->execute();
+}
+
+// Configuration for editors.
+$configs = [];
+$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/editor.editor.format_1.yml'));
+$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/editor.editor.format_2.yml'));
+$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/editor.editor.format_3.yml'));
+foreach ($configs as $config) {
+ $connection->insert('config')
+ ->fields([
+ 'collection',
+ 'name',
+ 'data',
+ ])
+ ->values([
+ 'collection' => '',
+ 'name' => 'editor.editor.' . $config['format'],
+ 'data' => serialize($config),
+ ])
+ ->execute();
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml
new file mode 100644
index 000000000..bee4523d0
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml
@@ -0,0 +1,47 @@
+uuid: e91c2255-2146-46fb-af58-1b391113c352
+langcode: en
+status: true
+dependencies:
+ module:
+ - file
+ - node
+id: test_profile
+label: 'Test profile'
+description: 'This is a test profile'
+attributes:
+ target:
+ id: target
+ weight: 0
+ settings:
+ widget_type: simple_checkbox
+ title:
+ id: title
+ weight: 0
+ settings:
+ automatic_title: false
+ accesskey:
+ id: accesskey
+ weight: 0
+ settings: { }
+matchers:
+ fc48c807-2a9c-44eb-b86b-7e134c1aa252:
+ uuid: fc48c807-2a9c-44eb-b86b-7e134c1aa252
+ id: 'entity:node'
+ weight: 0
+ settings:
+ result_description: 'by [node:author] | [node:created:medium]'
+ bundles: { }
+ group_by_bundle: false
+ include_unpublished: false
+ b8d6d672-6377-493f-b492-3cc69511cf17:
+ uuid: b8d6d672-6377-493f-b492-3cc69511cf17
+ id: 'entity:file'
+ weight: 0
+ settings:
+ result_description: '[file:path] [file:url]'
+ bundles: null
+ group_by_bundle: null
+ images:
+ show_dimensions: false
+ show_thumbnail: false
+ thumbnail_image_style: null
diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml
new file mode 100644
index 000000000..c906d2f8c
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml
@@ -0,0 +1,24 @@
+uuid: 3cfc827f-07ff-456e-86db-a831e3770a03
+langcode: en
+status: true
+dependencies:
+ module:
+ - imce
+ - node
+third_party_settings:
+ imce:
+ use: 1
+ scheme: public
+id: test_profile_imce
+label: 'Test profile imce'
+description: 'This is a test profile with imce settings'
+matchers:
+ 556010a3-e317-48b3-b4ed-854c10f4b950:
+ uuid: 556010a3-e317-48b3-b4ed-854c10f4b950
+ id: 'entity:node'
+ weight: 0
+ settings:
+ result_description: 'by [node:author] | [node:created:medium]'
+ bundles: { }
+ group_by_bundle: false
+ include_unpublished: false
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml
index 2e78ae55c..ce29e8fcd 100644
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml
+++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml
@@ -1,13 +1,5 @@
# Schema for the configuration files of the Linkit test module.
-
-# Plugin \Drupal\linkit_test\Plugin\Linkit\Attribute\ConfigurableDummyAttribute
-linkit.attribute.configurable_dummy_attribute:
- type: linkit.attribute
- mapping:
- dummy_setting:
- type: boolean
-
# Plugin \Drupal\linkit_test\Plugin\Linkit\Matcher\ConfigurableDummyMatcher
linkit.matcher.configurable_dummy_matcher:
type: linkit.matcher
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml
index 0262e996d..d3ba29c9e 100644
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml
+++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml
@@ -5,12 +5,12 @@ type: module
# version: VERSION
# core: 8.x
dependencies:
- - linkit
- - field
- - text
+ - linkit:linkit
+ - drupal:field
+ - drupal:text
-# Information added by Drupal.org packaging script on 2017-03-21
-version: '8.x-4.3'
+# Information added by Drupal.org packaging script on 2018-03-08
+version: '8.x-5.0-beta7'
core: '8.x'
project: 'linkit'
-datestamp: 1490127367
+datestamp: 1520552594
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module
index 178e46d98..e2b2c055f 100644
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module
+++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module
@@ -4,13 +4,3 @@
* @file
* Support module for Linkit testing.
*/
-
-
-/**
- * Implements hook_linkit_attribute_alter().
- */
-function linkit_test_linkit_attribute_alter(&$linkit_attribute_info) {
- if (isset($linkit_attribute_info['dummyattribute'])) {
- $linkit_attribute_info['dummyattribute']['description'] = t('Altered dummy description');
- }
-}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php
deleted file mode 100644
index 7dde958bf..000000000
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php
+++ /dev/null
@@ -1,73 +0,0 @@
- 'textfield',
- '#title' => t('DummyAttribute'),
- '#default_value' => $default_value,
- '#maxlength' => 255,
- '#size' => 40,
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function defaultConfiguration() {
- return parent::defaultConfiguration() + [
- 'dummy_setting' => FALSE,
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
- $form['dummy_setting'] = [
- '#type' => 'checkbox',
- '#title' => $this->t('Dummy setting'),
- '#default_value' => $this->configuration['dummy_setting'],
- ];
-
- return $form;
- }
-
- /**
- * {@inheritdoc}
- */
- public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
- }
-
- /**
- * {@inheritdoc}
- */
- public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
- $this->configuration['dummy_setting'] = $form_state->getValue('dummy_setting');
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php
deleted file mode 100644
index 82581674c..000000000
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php
+++ /dev/null
@@ -1,37 +0,0 @@
- 'textfield',
- '#title' => t('DummyAttribute'),
- '#default_value' => $default_value,
- '#maxlength' => 255,
- '#size' => 40,
- ];
- }
-
-}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php
index 8bcc60b16..d190997ad 100644
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php
+++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php
@@ -1,18 +1,15 @@
'Configurable Dummy Matcher title',
- 'description' => 'Configurable Dummy Matcher description',
- 'path' => 'http://example.com',
- 'group' => 'Configurable Dummy Matcher',
- ];
+ public function execute($string) {
+ $suggestions = new SuggestionCollection();
+ $suggestion = new DescriptionSuggestion();
+ $suggestion->setLabel('Configurable Dummy Matcher title')
+ ->setPath('http://example.com')
+ ->setGroup('Configurable Dummy Matcher')
+ ->setDescription('Configurable Dummy Matcher description');
- return $matches;
+ $suggestions->addSuggestion($suggestion);
+
+ return $suggestions;
}
}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php
index 242e7145c..8a7386067 100644
--- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php
+++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php
@@ -1,17 +1,14 @@
setLabel('Dummy Matcher title')
+ ->setPath('http://example.com')
+ ->setGroup('Dummy Matcher');
- /**
- * {@inheritdoc}
- */
- public function getMatches($string) {
- $matches[] = [
- 'title' => 'DummyMatcher title',
- 'description' => 'DummyMatcher description',
- 'path' => 'http://example.com',
- 'group' => 'DummyMatcher',
- ];
+ $suggestions->addSuggestion($suggestion);
- return $matches;
+ return $suggestions;
}
}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php
new file mode 100644
index 000000000..e931e85ee
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php
@@ -0,0 +1,60 @@
+linkitProfile = $this->createProfile();
+ }
+
+ /**
+ * Tests the profile route title callback.
+ */
+ public function testProfileTitle() {
+ $this->drupalLogin($this->adminUser);
+
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id());
+
+ $this->assertSession()->pageTextContains('Edit ' . $this->linkitProfile->label() . ' profile');
+ }
+
+ /**
+ * Tests the matcher route title callback.
+ */
+ public function testMatcherTitle() {
+ $this->drupalLogin($this->adminUser);
+
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->container->get('plugin.manager.linkit.matcher')->createInstance('configurable_dummy_matcher');
+ $matcher_uuid = $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $matcher_uuid);
+
+ $this->assertSession()->pageTextContains('Edit ' . $plugin->getLabel() . ' matcher');
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php
new file mode 100644
index 000000000..dc661fd0a
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php
@@ -0,0 +1,48 @@
+placeBlock('page_title_block');
+ $this->placeBlock('local_tasks_block');
+ $this->placeBlock('local_actions_block');
+ $this->placeBlock('system_messages_block');
+
+ $this->adminUser = $this->drupalCreateUser(['administer linkit profiles']);
+ $this->webUser = $this->drupalCreateUser();
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php
new file mode 100644
index 000000000..2cf52ec1d
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php
@@ -0,0 +1,138 @@
+manager = $this->container->get('plugin.manager.linkit.matcher');
+
+ $this->linkitProfile = $this->createProfile();
+ }
+
+ /**
+ * Test the overview page.
+ */
+ public function testOverview() {
+ $this->drupalLogin($this->adminUser);
+
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers');
+ $this->assertSession()->pageTextContains(t('No matchers added.'));
+
+ // Make sure the 'Add matcher' action link is present.
+ $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/add');
+ }
+
+ /**
+ * Test adding a matcher to a profile.
+ */
+ public function testAdd() {
+ $this->drupalLogin($this->adminUser);
+
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/add');
+
+ // Create matcher.
+ $edit = [];
+ $edit['plugin'] = 'dummy_matcher';
+ $this->submitForm($edit, t('Save and continue'));
+
+ // Reload the profile.
+ $this->linkitProfile = Profile::load($this->linkitProfile->id());
+
+ $matcher_ids = $this->linkitProfile->getMatchers()->getInstanceIds();
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->linkitProfile->getMatcher(current($matcher_ids));
+
+ $this->assertSession()->responseContains(t('Added %label matcher.', ['%label' => $plugin->getLabel()]));
+ $this->assertSession()->pageTextNotContains(t('No matchers added.'));
+ }
+
+ /**
+ * Test adding a configurable attribute to a profile.
+ */
+ public function testAddConfigurable() {
+ $this->drupalLogin($this->adminUser);
+
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/add');
+
+ // Create configurable matcher.
+ $edit = [];
+ $edit['plugin'] = 'configurable_dummy_matcher';
+ $this->submitForm($edit, t('Save and continue'));
+
+ // Reload the profile.
+ $this->linkitProfile = Profile::load($this->linkitProfile->id());
+
+ $matcher_ids = $this->linkitProfile->getMatchers()->getInstanceIds();
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->linkitProfile->getMatcher(current($matcher_ids));
+
+ $this->assertSession()->addressEquals('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $plugin->getUuid());
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers');
+
+ $this->assertSession()->pageTextNotContains(t('No matchers added.'));
+ }
+
+ /**
+ * Test delete a matcher from a profile.
+ */
+ public function testDelete() {
+ $this->drupalLogin($this->adminUser);
+
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('dummy_matcher');
+
+ $plugin_uuid = $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ // Try delete a matcher that is not attached to the profile.
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/doesntexists/delete');
+ $this->assertSession()->statusCodeEquals('404');
+
+ // Go to the delete page, but press cancel.
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $plugin_uuid . '/delete');
+ $this->clickLink(t('Cancel'));
+ $this->assertSession()->addressEquals('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers');
+
+ // Delete the matcher from the profile.
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $plugin_uuid . '/delete');
+
+ $this->submitForm([], t('Confirm'));
+ $this->assertSession()->responseContains(t('The matcher %plugin has been deleted.', ['%plugin' => $plugin->getLabel()]));
+ $this->assertSession()->addressEquals('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers');
+ $this->assertSession()->pageTextContains(t('No matchers added.'));
+
+ /** @var \Drupal\linkit\Entity\Profile $updated_profile */
+ $updated_profile = Profile::load($this->linkitProfile->id());
+ $this->assertFalse($updated_profile->getMatchers()->has($plugin_uuid), 'The user matcher is deleted from the profile');
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php
new file mode 100644
index 000000000..3b840b9ab
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php
@@ -0,0 +1,128 @@
+drupalLogin($this->webUser);
+ $this->drupalGet('/admin/config/content/linkit');
+ $this->assertSession()->statusCodeEquals(403);
+ $this->drupalLogout();
+
+ // Login as an admin user and make sure the collection page is accessible.
+ $this->drupalLogin($this->adminUser);
+ $this->drupalGet('/admin/config/content/linkit');
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Make sure the 'Add profile' action link is present.
+ $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/add');
+
+ // Create multiple profiles.
+ $profiles = [];
+ $profiles[] = $this->createProfile();
+ $profiles[] = $this->createProfile();
+
+ // Refresh the page.
+ $this->drupalGet('/admin/config/content/linkit');
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Make sure that there is an edit and a delete operation link for all
+ // profiles.
+ foreach ($profiles as $profile) {
+ $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $profile->id());
+ $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $profile->id() . '/delete');
+ }
+ }
+
+ /**
+ * Creates profile.
+ */
+ public function testProfileCreation() {
+ $this->drupalLogin($this->adminUser);
+
+ // Make sure the profile add page is accessible.
+ $this->drupalGet('/admin/config/content/linkit/add');
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Create a profile.
+ $edit = [];
+ $edit['label'] = Unicode::strtolower($this->randomMachineName());
+ $edit['id'] = Unicode::strtolower($this->randomMachineName());
+ $edit['description'] = $this->randomMachineName(16);
+ $this->submitForm($edit, t('Save and manage matchers'));
+
+ // Make sure that the new profile was saved properly.
+ $this->assertSession()->responseContains(t('Created new profile %label.', ['%label' => $edit['label']]));
+ $this->drupalGet('/admin/config/content/linkit');
+ $this->assertSession()->pageTextContains($edit['label']);
+ }
+
+ /**
+ * Updates a profile.
+ */
+ public function testProfileUpdate() {
+ $this->drupalLogin($this->adminUser);
+
+ // Create a profile.
+ $profile = $this->createProfile();
+
+ // Make sure the profile edit page is accessible.
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $profile->id());
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Make sure the machine name field is disabled and that we have certain
+ // elements presented.
+ $this->assertSession()->elementNotExists('xpath', '//input[not(@disabled) and @name="id"]');
+ $this->assertSession()->buttonExists('Update profile');
+ $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $profile->id() . '/delete');
+
+ // Update the profile.
+ $edit = [];
+ $edit['label'] = $this->randomMachineName();
+ $edit['description'] = $this->randomMachineName(16);
+ $this->submitForm($edit, t('Update profile'));
+
+ // Make sure that the profile was updated properly.
+ $this->assertSession()->responseContains(t('Updated profile %label.', ['%label' => $edit['label']]));
+ $this->drupalGet('/admin/config/content/linkit');
+ $this->assertSession()->pageTextContains($edit['label']);
+ }
+
+ /**
+ * Delete a profile.
+ */
+ public function testProfileDelete() {
+ $this->drupalLogin($this->adminUser);
+
+ // Create a profile.
+ $profile = $this->createProfile();
+
+ $this->drupalGet('/admin/config/content/linkit/manage/' . $profile->id() . '/delete');
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Delete the profile.
+ $this->submitForm([], t('Delete'));
+
+ // Make sure that the profile was deleted properly.
+ $this->assertSession()->responseContains(t('The linkit profile %label has been deleted.', ['%label' => $profile->label()]));
+ $this->drupalGet('/admin/config/content/linkit');
+ $this->assertSession()->responseNotContains($profile->label());
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php
new file mode 100644
index 000000000..dfad7ab74
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php
@@ -0,0 +1,320 @@
+container->get('plugin.manager.linkit.matcher');
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+
+ $this->linkitProfile = $this->createProfile();
+ $plugin = $matcherManager->createInstance('entity:entity_test_mul');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ // Create text format, associate CKEditor.
+ $llama_format = FilterFormat::create([
+ 'format' => 'llama',
+ 'name' => 'Llama',
+ 'weight' => 0,
+ 'filters' => [],
+ ]);
+ $llama_format->save();
+ $editor = Editor::create([
+ 'format' => 'llama',
+ 'editor' => 'ckeditor',
+ ]);
+ $editor->save();
+
+ // Create "CKEditor" text editor plugin instance.
+ $this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor');
+
+ // Create a node type for testing.
+ NodeType::create(['type' => 'page', 'name' => 'page'])->save();
+
+ // Create a body field instance for the 'page' node type.
+ FieldConfig::create([
+ 'field_storage' => FieldStorageConfig::loadByName('node', 'body'),
+ 'bundle' => 'page',
+ 'label' => 'Body',
+ 'settings' => ['display_summary' => TRUE],
+ 'required' => TRUE,
+ ])->save();
+
+ // Assign widget settings for the 'default' form mode.
+ EntityFormDisplay::create([
+ 'targetEntityType' => 'node',
+ 'bundle' => 'page',
+ 'mode' => 'default',
+ 'status' => TRUE,
+ ])->setComponent('body', ['type' => 'text_textarea_with_summary'])->save();
+
+ // Customize the configuration.
+ $this->container->get('plugin.manager.editor')->clearCachedDefinitions();
+
+ $this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor');
+ $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions();
+ $settings = $editor->getSettings();
+ $settings['plugins']['drupallink']['linkit_enabled'] = TRUE;
+ $settings['plugins']['drupallink']['linkit_profile'] = $this->linkitProfile->id();
+ $editor->setSettings($settings);
+ $editor->save();
+
+ $account = $this->drupalCreateUser([
+ 'administer nodes',
+ 'create page content',
+ 'edit own page content',
+ 'use text format llama',
+ 'view test entity',
+ ]);
+
+ $this->drupalLogin($account);
+ }
+
+ /**
+ * Test the link dialog.
+ */
+ public function testLinkDialog() {
+ $session = $this->getSession();
+ $web_assert = $this->assertSession();
+ $page = $session->getPage();
+
+ // Adds additional languages.
+ $langcodes = ['sv', 'da', 'fi'];
+ foreach ($langcodes as $langcode) {
+ ConfigurableLanguage::createFromLangcode($langcode)->save();
+ }
+
+ // Create a test entity.
+ /** @var \Drupal\Core\Entity\EntityInterface $entity */
+ $entity = EntityTestMul::create(['name' => 'Foo']);
+ $entity->save();
+
+ // 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.
+ $href_field = $page->findField('attributes[href]');
+
+ // Make sure the href field is an autocomplete field.
+ $href_field->hasAttribute('data-autocomplete-path');
+ $href_field->hasClass('form-linkit-autocomplete');
+ $href_field->hasClass('ui-autocomplete-input');
+
+ // Make sure all fields are empty.
+ $this->assertEmpty($href_field->getValue(), 'Href field is empty.');
+ $this->assertEmptyWithJs('attributes[data-entity-type]');
+ $this->assertEmptyWithJs('attributes[data-entity-uuid]');
+ $this->assertEmptyWithJs('attributes[data-entity-substitution]');
+ $this->assertEmptyWithJs('href_dirty_check');
+
+ // Make sure the autocomplete result container is hidden.
+ $autocomplete_container = $page->find('css', 'ul.linkit-ui-autocomplete');
+ $this->assertFalse($autocomplete_container->isVisible());
+
+ // Trigger a keydown event to active a autocomplete search.
+ $href_field->keyDown('f');
+
+ // Wait for the results to load.
+ $this->getSession()->wait(5000, "jQuery('.linkit-result-line.ui-menu-item').length > 0");
+
+ // Make sure the autocomplete result container is visible.
+ $this->assertTrue($autocomplete_container->isVisible());
+
+ // Find all the autocomplete results.
+ $results = $page->findAll('css', '.linkit-result-line.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-line") and contains(@class, "ui-menu-item")][1]')->click();
+
+ // Make sure the linkit field field is populated with the node url.
+ $this->assertEquals($entity->toUrl()->toString(), $href_field->getValue(), 'The href field is populated with the node url.');
+
+ // Make sure all other fields are populated.
+ $this->assertEqualsWithJs('attributes[data-entity-type]', $entity->getEntityTypeId());
+ $this->assertEqualsWithJs('attributes[data-entity-uuid]', $entity->uuid());
+ $this->assertEqualsWithJs('attributes[data-entity-substitution]', 'canonical');
+ $this->assertEqualsWithJs('href_dirty_check', $entity->toUrl()->toString());
+
+ // Save the dialog input.
+ $this->click('.editor-link-dialog button:contains("Save")');
+
+ // Wait for the dialog to close.
+ $web_assert->assertWaitOnAjaxRequest();
+
+ $fields = [
+ 'data-entity-type' => $entity->getEntityTypeId(),
+ 'data-entity-uuid' => $entity->uuid(),
+ 'data-entity-substitution' => 'canonical',
+ 'href' => $entity->toUrl()->toString(),
+ ];
+ 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 . '"');
+ }
+
+ // Select the link in the editor.
+ $javascript = <<executeScript($javascript);
+
+ // 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.
+ $href_field = $page->findField('attributes[href]');
+ $this->assertEquals($entity->toUrl()->toString(), $href_field->getValue(), 'Href field contains the node url when edit.');
+
+ // Make sure all other fields are populated when editing a link.
+ $this->assertEqualsWithJs('attributes[data-entity-type]', $entity->getEntityTypeId());
+ $this->assertEqualsWithJs('attributes[data-entity-uuid]', $entity->uuid());
+ $this->assertEqualsWithJs('attributes[data-entity-substitution]', 'canonical');
+ $this->assertEqualsWithJs('href_dirty_check', $entity->toUrl()->toString());
+
+ // Edit the href field and set an external url.
+ $href_field->setValue('http://example.com');
+
+ // Save the dialog input.
+ $this->click('.editor-link-dialog button:contains("Save")');
+
+ // 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.
+ $javascript = <<getSession()->evaluateScript($javascript);
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php
new file mode 100644
index 000000000..7d2d79c64
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php
@@ -0,0 +1,59 @@
+drupalCreateUser([
+ 'administer filters',
+ ]);
+ $this->drupalLogin($account);
+ }
+
+ /**
+ * Tests that linkit filter is toggling the filter_html allowed tags.
+ */
+ public function testToggleLinkitFilter() {
+ $session = $this->getSession();
+ $page = $session->getPage();
+
+ // Go to add filter page.
+ $this->drupalGet('admin/config/content/formats/add');
+ $this->assertSession()->statusCodeEquals(200);
+
+ // Enable the 'Limit allowed HTML tags and correct faulty HTML' filter.
+ $page->findField('filters[filter_html][status]')->check();
+
+ $javascript = "(function (){ return jQuery('p.editor-update-message > strong').text(); })()";
+ $this->assertNotContains('', $session->evaluateScript($javascript));
+
+ // Enable the 'Linkit filter' filter.
+ $page->findField('filters[linkit][status]')->check();
+ $this->assertContains('', $session->evaluateScript($javascript));
+
+ // Disable the 'Linkit filter' filter.
+ $page->findField('filters[linkit][status]')->uncheck();
+ $this->assertNotContains('', $session->evaluateScript($javascript));
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php
new file mode 100644
index 000000000..24ca82273
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php
@@ -0,0 +1,83 @@
+getEntityTypeId() === "file") {
+ /** @var \Drupal\file\Entity\File $entity */
+ $href = file_create_url($entity->getFileUri());
+ }
+ else {
+ $href = $entity->toUrl()->toString();
+ }
+
+ $input = 'Link text';
+ $expected = 'Link text';
+ $this->assertSame($expected, $this->process($input, $langcode)->getProcessedText());
+ }
+
+ /**
+ * Asserts that Linkit filter correctly processes the content titles.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The entity object to check.
+ * @param string $langcode
+ * The language code of the text to be filtered.
+ */
+ protected function assertLinkitFilterWithTitle(EntityInterface $entity, $langcode = LanguageInterface::LANGCODE_SITE_DEFAULT) {
+ if ($entity->getEntityTypeId() === "file") {
+ /** @var \Drupal\file\Entity\File $entity */
+ $href = file_create_url($entity->getFileUri());
+ }
+ else {
+ $href = $entity->toUrl()->toString();
+ }
+
+ $input = 'Link text';
+ $expected = 'Link text';
+ $this->assertSame($expected, $this->process($input, $langcode)->getProcessedText());
+ }
+
+ /**
+ * Test helper method that wraps the filter process method.
+ *
+ * @param string $input
+ * The text string to be filtered.
+ * @param string $langcode
+ * The language code of the text to be filtered.
+ *
+ * @return \Drupal\filter\FilterProcessResult
+ * The filtered text, wrapped in a FilterProcessResult object, and possibly
+ * with associated assets, cacheability metadata and placeholders.
+ *
+ * @see \Drupal\filter\Plugin\FilterInterface::process
+ */
+ protected function process($input, $langcode = LanguageInterface::LANGCODE_SITE_DEFAULT) {
+ return $this->filter->process($input, $langcode);
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php
new file mode 100644
index 000000000..db6107aa7
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php
@@ -0,0 +1,32 @@
+createProfile(['description' => 'foo']);
+ $this->assertEquals('foo', $profile->getDescription());
+ $profile->setDescription('bar');
+ $this->assertEquals('bar', $profile->getDescription());
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php
new file mode 100644
index 000000000..cf3832a7e
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php
@@ -0,0 +1,49 @@
+installConfig(['block_content']);
+ $this->installEntitySchema('block_content');
+
+ $this->installEntitySchema('node');
+ $this->installConfig(['field', 'node']);
+
+ $this->manager = $this->container->get('plugin.manager.linkit.matcher');
+ }
+
+ /**
+ * Tests the deriver.
+ */
+ public function testDeriver() {
+ $definition = $this->manager->getDefinition('entity:block_content', FALSE);
+ $this->assertNull($definition);
+ $definition = $this->manager->getDefinition('entity:node', FALSE);
+ $this->assertNotNull($definition);
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php
new file mode 100644
index 000000000..5c167b869
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php
@@ -0,0 +1,259 @@
+createUser();
+
+ \Drupal::currentUser()->setAccount($this->createUser([], ['view test entity']));
+
+ \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();
+ }
+
+ /**
+ * Tests that inaccessible entities isn't included in the results.
+ */
+ public function testAutocompletionAccess() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->matcherManager->createInstance('entity:entity_test');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ $entity_1 = EntityTest::create(['name' => 'no_forbid_access']);
+ $entity_1->save();
+ $entity_2 = EntityTest::create(['name' => 'forbid_access']);
+ $entity_2->save();
+
+ $suggestions = $this->getAutocompleteResult('forbid');
+ $this->assertTrue(count($suggestions) == 1, 'Autocomplete returned the expected amount of suggestions.');
+ $this->assertSame($entity_1->label(), $suggestions[0]['label'], 'Autocomplete did not include the inaccessible entity.');
+ }
+
+ /**
+ * Tests that 'front' adds the front page match.
+ */
+ public function testAutocompletionFront() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->matcherManager->createInstance('front_page');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ $data = $this->getAutocompleteResult('front');
+ $this->assertSame('Front page', $data[0]['label'], 'Autocomplete returned the front page suggestion.');
+ }
+
+ /**
+ * Tests the autocomplete with an email address.
+ */
+ public function testAutocompletionEmail() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->matcherManager->createInstance('email');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ $email = 'drupal@example.com';
+ $data = $this->getAutocompleteResult($email);
+ $this->assertSame((string) new FormattableMarkup('E-mail @email', ['@email' => $email]), $data[0]['label'], 'Autocomplete returned email suggestion.');
+ $this->assertSame('mailto:' . $email, $data[0]['path'], 'Autocomplete returned email suggestion with an mailto href.');
+ }
+
+ /**
+ * Tests autocompletion in general.
+ */
+ public function testAutocompletion() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->matcherManager->createInstance('entity:entity_test');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ $entity_1 = EntityTest::create(['name' => 'Barbar']);
+ $entity_1->save();
+ $entity_2 = EntityTest::create(['name' => 'Foobar']);
+ $entity_2->save();
+ $entity_3 = EntityTest::create(['name' => 'Basbar']);
+ $entity_3->save();
+
+ // Search for something that doesn't exists.
+ $data = $this->getAutocompleteResult('no_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');
+ $this->assertTrue(count($data) == 1, 'Autocomplete returned the expected amount of suggestions.');
+ $this->assertSame(Html::escape($entity_3->label()), $data[0]['label'], 'Autocomplete returned the matching entity');
+
+ // Search for something that exists three times.
+ $data = $this->getAutocompleteResult('bar');
+ $this->assertTrue(count($data) == 3, 'Autocomplete returned the expected amount of suggestions.');
+ $this->assertSame(Html::escape($entity_1->label()), $data[0]['label'], 'Autocomplete returned the first matching entity.');
+ $this->assertSame(Html::escape($entity_3->label()), $data[1]['label'], 'Autocomplete returned the second matching entity.');
+ $this->assertSame(Html::escape($entity_2->label()), $data[2]['label'], 'Autocomplete returned the third matching entity.');
+
+ // Search for something with an empty string.
+ $data = $this->getAutocompleteResult('');
+ $this->assertEmpty(count($data), 'Autocomplete did not return any suggestions.');
+ }
+
+ /**
+ * Tests autocompletion with translated entities.
+ */
+ public function testAutocompletionTranslations() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->matcherManager->createInstance('entity:entity_test_mul');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ $this->setupLanguages();
+
+ $entity = EntityTestMul::create(['name' => 'Barbar']);
+
+ // Copy the array and shift the default language.
+ $translations = $this->langcodes;
+ array_shift($translations);
+
+ foreach ($translations as $langcode) {
+ $entity->addTranslation($langcode, ['name' => 'Barbar ' . $langcode]);
+ }
+
+ $entity->save();
+
+ foreach ($this->langcodes as $langcode) {
+ $this->config('system.site')->set('default_langcode', $langcode)->save();
+ $data = $this->getAutocompleteResult('bar');
+ $this->assertTrue(count($data) == 1, 'Autocomplete returned the expected amount of suggestions.');
+ $this->assertSame($entity->getTranslation($langcode)->label(), $data[0]['label'], 'Autocomplete returned the "no results."');
+ }
+ }
+
+ /**
+ * Returns the result of an Linkit autocomplete request.
+ *
+ * @param string $input
+ * The label of the entity to query by.
+ *
+ * @return array
+ * An array of suggestions.
+ */
+ protected function getAutocompleteResult($input) {
+ $request = Request::create('linkit/autocomplete/' . $this->linkitProfile->id());
+ $request->query->set('q', $input);
+
+ $controller = AutocompleteController::create($this->container);
+ $result = Json::decode($controller->autocomplete($request, $this->linkitProfile->id())->getContent());
+ return $result['suggestions'];
+ }
+
+ /**
+ * Creates a profile based on default settings.
+ *
+ * @param array $settings
+ * (optional) An associative array of settings for the profile, as used in
+ * entity_create(). Override the defaults by specifying the key and value
+ * in the array
+ *
+ * The following defaults are provided:
+ * - label: Random string.
+ *
+ * @return \Drupal\linkit\ProfileInterface
+ * The created profile entity.
+ *
+ * @todo Do a trait of this?
+ */
+ protected function createProfile(array $settings = []) {
+ // Populate defaults array.
+ $settings += [
+ 'id' => Unicode::strtolower($this->randomMachineName()),
+ 'label' => $this->randomMachineName(),
+ ];
+
+ $profile = Profile::create($settings);
+ $profile->save();
+
+ return $profile;
+ }
+
+ /**
+ * Returns the "no results" suggestion.
+ *
+ * @return array
+ * An array with a fixed value of no results.
+ *
+ * @todo Should this use some kind of t() function?
+ */
+ protected function noResults() {
+ return [
+ 'title' => 'No results',
+ ];
+ }
+
+ /**
+ * Adds additional languages.
+ */
+ protected function setupLanguages() {
+ $this->langcodes = ['sv', 'da', 'fi'];
+ foreach ($this->langcodes as $langcode) {
+ ConfigurableLanguage::createFromLangcode($langcode)->save();
+ }
+ array_unshift($this->langcodes, \Drupal::languageManager()->getDefaultLanguage()->getId());
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php
new file mode 100644
index 000000000..0a1963b44
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php
@@ -0,0 +1,243 @@
+installEntitySchema('entity_test');
+ $this->installSchema('system', ['key_value_expire']);
+
+ // Create a profile.
+ $this->linkitProfile = $this->createProfile();
+
+ /** @var \Drupal\linkit\MatcherManager $matcherManager */
+ $matcherManager = $this->container->get('plugin.manager.linkit.matcher');
+
+ // Add the entity_test matcher to the profile.
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $matcherManager->createInstance('entity:entity_test');
+ $this->linkitProfile->addMatcher($plugin->getConfiguration());
+ $this->linkitProfile->save();
+
+ // Add a text format.
+ $format = FilterFormat::create([
+ 'format' => 'filtered_html',
+ 'name' => 'Filtered HTML',
+ 'weight' => 0,
+ 'filters' => [],
+ ]);
+ $format->save();
+
+ // Set up editor.
+ $this->editor = Editor::create([
+ 'format' => 'filtered_html',
+ 'editor' => 'ckeditor',
+ ]);
+ $this->editor->setSettings([
+ 'plugins' => [
+ 'drupallink' => [
+ 'linkit_enabled' => TRUE,
+ 'linkit_profile' => $this->linkitProfile->id(),
+ ],
+ ],
+ ]);
+ $this->editor->save();
+ }
+
+ /**
+ * Tests adding a link.
+ */
+ public function testAdd() {
+ $entity_label = $this->randomString();
+ /** @var \Drupal\Core\Entity\EntityInterface $entity */
+ $entity = EntityTest::create(['name' => $entity_label]);
+ $entity->save();
+
+ $form_object = new EditorLinkDialog();
+
+ $input = [
+ 'editor_object' => [],
+ 'dialogOptions' => [
+ 'title' => 'Add Link',
+ 'dialogClass' => 'editor-link-dialog',
+ 'autoResize' => 'true',
+ ],
+ '_drupal_ajax' => '1',
+ 'ajax_page_state' => [
+ 'theme' => 'bartik',
+ 'theme_token' => 'some-token',
+ 'libraries' => '',
+ ],
+ ];
+ $form_state = (new FormState())
+ ->setRequestMethod('POST')
+ ->setUserInput($input)
+ ->addBuildInfo('args', [$this->editor]);
+
+ /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
+ $form_builder = $this->container->get('form_builder');
+ $form_id = $form_builder->getFormId($form_object, $form_state);
+ $form = $form_builder->retrieveForm($form_id, $form_state);
+ $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 linkit field.');
+ $this->assertEmpty($form['attributes']['href']['#default_value'], 'The linkit field is empty.');
+
+ $form_state->setValue(['attributes', 'href'], 'https://example.com/');
+ $form_state->setValue('href_dirty_check', '');
+ $form_state->setValue(['attributes', 'data-entity-type'], $this->randomString());
+ $form_state->setValue(['attributes', 'data-entity-uuid'], $this->randomString());
+ $form_state->setValue(['attributes', 'data-entity-substitution'], $this->randomString());
+ $form_builder->submitForm($form_object, $form_state);
+ $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-type']));
+ $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-uuid']));
+ $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-substitution']));
+
+ $entity_url = $entity->toUrl('canonical', ['path_processing' => FALSE])->toString();
+ $form_state->setValue(['attributes', 'href'], $entity_url);
+ $form_state->setValue('href_dirty_check', $entity_url);
+ $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_builder->submitForm($form_object, $form_state);
+
+ $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.');
+ }
+
+ /**
+ * Tests editing a link with data attributes.
+ */
+ public function testEditWithDataAttributes() {
+ $entity_label = $this->randomString();
+ /** @var \Drupal\Core\Entity\EntityInterface $entity */
+ $entity = EntityTest::create(['name' => $entity_label]);
+ $entity->save();
+ $entity_url = $entity->toUrl('canonical', ['path_processing' => FALSE])->toString();
+
+ $form_object = new EditorLinkDialog();
+
+ $input = [
+ 'editor_object' => [
+ 'href' => $entity_url,
+ 'data-entity-type' => $entity->getEntityTypeId(),
+ 'data-entity-uuid' => $entity->uuid(),
+ 'data-entity-substitution' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION,
+ ],
+ 'dialogOptions' => [
+ 'title' => 'Edit Link',
+ 'dialogClass' => 'editor-link-dialog',
+ 'autoResize' => 'true',
+ ],
+ '_drupal_ajax' => '1',
+ 'ajax_page_state' => [
+ 'theme' => 'bartik',
+ 'theme_token' => 'some-token',
+ 'libraries' => '',
+ ],
+ ];
+ $form_state = (new FormState())
+ ->setRequestMethod('POST')
+ ->setUserInput($input)
+ ->addBuildInfo('args', [$this->editor]);
+
+ /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
+ $form_builder = $this->container->get('form_builder');
+ $form_id = $form_builder->getFormId($form_object, $form_state);
+ $form = $form_builder->retrieveForm($form_id, $form_state);
+ $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_url, $form['attributes']['href']['#default_value'], 'The href field has the url 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.');
+ }
+
+ /**
+ * Tests editing a link without data attributes.
+ */
+ public function testEditWithoutDataAttributes() {
+ $form_object = new EditorLinkDialog();
+
+ $input = [
+ 'editor_object' => [
+ 'href' => 'http://example.com/',
+ ],
+ 'dialogOptions' => [
+ 'title' => 'Edit Link',
+ 'dialogClass' => 'editor-link-dialog',
+ 'autoResize' => 'true',
+ ],
+ '_drupal_ajax' => '1',
+ 'ajax_page_state' => [
+ 'theme' => 'bartik',
+ 'theme_token' => 'some-token',
+ 'libraries' => '',
+ ],
+ ];
+ $form_state = (new FormState())
+ ->setRequestMethod('POST')
+ ->setUserInput($input)
+ ->addBuildInfo('args', [$this->editor]);
+
+ /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
+ $form_builder = $this->container->get('form_builder');
+ $form_id = $form_builder->getFormId($form_object, $form_state);
+ $form = $form_builder->retrieveForm($form_id, $form_state);
+ $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 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/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php
new file mode 100644
index 000000000..bd2db531a
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php
@@ -0,0 +1,148 @@
+installEntitySchema('entity_test');
+ $this->installEntitySchema('entity_test_mul');
+ $this->installEntitySchema('file');
+
+ // Add Swedish, Danish and Finnish.
+ ConfigurableLanguage::createFromLangcode('sv')->save();
+ ConfigurableLanguage::createFromLangcode('da')->save();
+ ConfigurableLanguage::createFromLangcode('fi')->save();
+
+ /** @var \Drupal\Component\Plugin\PluginManagerInterface $manager */
+ $manager = $this->container->get('plugin.manager.filter');
+ $bag = new FilterPluginCollection($manager, []);
+ $this->filter = $bag->get('linkit');
+ }
+
+ /**
+ * Tests the linkit filter for entities with different access.
+ */
+ public function testFilterEntityAccess() {
+ // Create an entity that no one have access to.
+ $entity_no_access = EntityTest::create(['name' => 'forbid_access']);
+ $entity_no_access->save();
+
+ // Create an entity that is accessible.
+ $entity_with_access = EntityTest::create(['name' => $this->randomMachineName()]);
+ $entity_with_access->save();
+
+ // Automatically set the title.
+ $this->filter->setConfiguration(['settings' => ['title' => 1]]);
+
+ // Make sure the title is not included.
+ $input = 'Link text';
+ $this->assertFalse(strpos($this->process($input)->getProcessedText(), 'title'), 'The link does not contain a title attribute.');
+
+ $this->assertLinkitFilterWithTitle($entity_with_access);
+ }
+
+ /**
+ * Tests the linkit filter for entities with translations.
+ */
+ public function testFilterEntityTranslations() {
+ // Create an entity and add translations to that.
+ /** @var \Drupal\entity_test\Entity\EntityTestMul $entity */
+ $entity = EntityTestMul::create(['name' => $this->randomMachineName()]);
+ $entity->addTranslation('sv', ['name' => $this->randomMachineName(), 'langcode' => 'sv']);
+ $entity->addTranslation('da', ['name' => $this->randomMachineName(), 'langcode' => 'da']);
+ $entity->addTranslation('fi', ['name' => $this->randomMachineName(), 'langcode' => 'fi']);
+ $entity->save();
+
+ /** @var \Drupal\Core\Path\AliasStorageInterface $path_alias_storage */
+ $path_alias_storage = $this->container->get('path.alias_storage');
+
+ $url = $entity->toUrl()->toString();
+
+ // Add url aliases.
+ $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'en');
+ $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'sv');
+ $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'da');
+ $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'fi');
+
+ // Disable the automatic title attribute.
+ $this->filter->setConfiguration(['settings' => ['title' => 0]]);
+ /** @var \Drupal\Core\Language\Language $language */
+ foreach ($entity->getTranslationLanguages() as $language) {
+ $this->assertLinkitFilter($entity->getTranslation($language->getId()), $language->getId());
+ }
+
+ // Enable the automatic title attribute.
+ $this->filter->setConfiguration(['settings' => ['title' => 1]]);
+ /** @var \Drupal\Core\Language\Language $language */
+ foreach ($entity->getTranslationLanguages() as $language) {
+ $this->assertLinkitFilterWithTitle($entity->getTranslation($language->getId()), $language->getId());
+ }
+ }
+
+ /**
+ * Tests the linkit filter for file entities.
+ */
+ public function testFilterFileEntity() {
+ $file = File::create([
+ 'uid' => 1,
+ 'filename' => 'druplicon.txt',
+ 'uri' => 'public://druplicon.txt',
+ 'filemime' => 'text/plain',
+ 'status' => FILE_STATUS_PERMANENT,
+ ]);
+ $file->save();
+
+ // Disable the automatic title attribute.
+ $this->filter->setConfiguration(['settings' => ['title' => 0]]);
+ $this->assertLinkitFilter($file);
+
+ // Automatically set the title.
+ $this->filter->setConfiguration(['settings' => ['title' => 1]]);
+ $this->assertLinkitFilterWithTitle($file);
+ }
+
+ /**
+ * Tests that the linkit filter do not overwrite provided title attributes.
+ */
+ public function testTitleOverwritten() {
+ // Create an entity.
+ $entity = EntityTest::create(['name' => $this->randomMachineName()]);
+ $entity->save();
+
+ // Automatically set the title.
+ $this->filter->setConfiguration(['settings' => ['title' => 1]]);
+
+ // Make sure the title is not overwritten.
+ $input = 'Link text';
+ $this->assertTrue(strpos($this->process($input)->getProcessedText(), 'Do not override'), 'The filer is not overwrite the provided title attribute value.');
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php
new file mode 100644
index 000000000..737a0bb1f
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php
@@ -0,0 +1,71 @@
+installSchema('system', 'router');
+ $this->installSchema('system', 'sequences');
+ $this->installEntitySchema('user');
+ $this->installConfig(['filter']);
+ }
+
+ /**
+ * Creates a user.
+ *
+ * @param array $values
+ * (optional) The values used to create the entity.
+ * @param array $permissions
+ * (optional) Array of permission names to assign to user.
+ *
+ * @return \Drupal\user\Entity\User
+ * The created user entity.
+ */
+ protected function createUser(array $values = [], array $permissions = []) {
+ if ($permissions) {
+ // Create a new role and apply permissions to it.
+ $role = Role::create([
+ 'id' => strtolower($this->randomMachineName(8)),
+ 'label' => $this->randomMachineName(8),
+ ]);
+ $role->save();
+ user_role_grant_permissions($role->id(), $permissions);
+ $values['roles'][] = $role->id();
+ }
+
+ $account = User::create($values + [
+ 'name' => $this->randomMachineName(),
+ 'status' => 1,
+ ]);
+ $account->enforceIsNew();
+ $account->save();
+ return $account;
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php
new file mode 100644
index 000000000..7d8050337
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php
@@ -0,0 +1,58 @@
+createUser();
+
+ \Drupal::currentUser()->setAccount($this->createUser([], ['access site-wide contact form', 'view test entity translations']));
+
+ $this->manager = $this->container->get('plugin.manager.linkit.matcher');
+
+ ContactForm::create([
+ 'id' => 'lorem',
+ 'label' => 'Lorem',
+ ])->save();
+ }
+
+ /**
+ * Tests contact form matcher.
+ */
+ public function testMatcherWidthDefaultConfiguration() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:contact_form', []);
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(1, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php
new file mode 100644
index 000000000..4999aae1e
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php
@@ -0,0 +1,113 @@
+installEntitySchema('file');
+ $this->installSchema('system', ['key_value_expire']);
+ $this->installSchema('file', ['file_usage']);
+
+ $this->manager = $this->container->get('plugin.manager.linkit.matcher');
+
+ // Linkit doesn't care about the actual resource, only the entity.
+ foreach (['gif', 'jpg', 'png'] as $ext) {
+ $file = File::create([
+ 'uid' => 1,
+ 'filename' => 'image-test.' . $ext,
+ 'uri' => 'public://image-test.' . $ext,
+ 'filemime' => 'text/plain',
+ 'status' => FILE_STATUS_PERMANENT,
+ ]);
+ $file->save();
+ }
+
+ // Create user 1 who has special permissions.
+ \Drupal::currentUser()->setAccount($this->createUser(['uid' => 1]));
+ }
+
+ /**
+ * Tests file matcher.
+ */
+ public function testFileMatcherWithDefaultConfiguration() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:file', []);
+ $suggestions = $plugin->execute('image-test');
+ $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions.');
+ }
+
+ /**
+ * Tests file matcher with extension filer.
+ */
+ public function testFileMatcherWithExtensionFiler() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:file', [
+ 'settings' => [
+ 'file_extensions' => 'png',
+ ],
+ ]);
+
+ $suggestions = $plugin->execute('image-test');
+ $this->assertEquals(1, count($suggestions->getSuggestions()), 'Correct number of suggestions with single file extension filter.');
+
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:file', [
+ 'settings' => [
+ 'file_extensions' => 'png jpg',
+ ],
+ ]);
+
+ $suggestions = $plugin->execute('image-test');
+ $this->assertEquals(2, count($suggestions->getSuggestions()), 'Correct number of suggestions with multiple file extension filter.');
+ }
+
+ /**
+ * Tests file matcher with tokens in the matcher metadata.
+ */
+ public function testTermMatcherWidthMetadataTokens() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:file', [
+ 'settings' => [
+ 'metadata' => '[file:fid] [file:field_with_no_value]',
+ ],
+ ]);
+
+ $suggestionCollection = $plugin->execute('Lorem');
+ /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */
+ $suggestions = $suggestionCollection->getSuggestions();
+
+ foreach ($suggestions as $suggestion) {
+ $this->assertNotContains('[file:fid]', $suggestion->getDescription(), 'Raw token "[file:fid]" is not present in the description');
+ $this->assertNotContains('[file:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[file:field_with_no_value]" is not present in the description');
+ }
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php
new file mode 100644
index 000000000..8783a4f97
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php
@@ -0,0 +1,160 @@
+installEntitySchema('node');
+ $this->installConfig(['field', 'node']);
+
+ $this->manager = $this->container->get('plugin.manager.linkit.matcher');
+
+ // Set the current user to a new user, else the nodes will be created by an
+ // anonymous user.
+ \Drupal::currentUser()->setAccount($this->createUser());
+
+ $type1 = NodeType::create([
+ 'type' => 'test1',
+ 'name' => 'Test1',
+ ]);
+ $type1->save();
+
+ $type2 = NodeType::create([
+ 'type' => 'test2',
+ 'name' => 'Test2',
+ ]);
+ $type2->save();
+
+ // Nodes with type 1.
+ $node = Node::create([
+ 'title' => 'Lorem Ipsum 1',
+ 'type' => $type1->id(),
+ ]);
+ $node->save();
+
+ $node = Node::create([
+ 'title' => 'Lorem Ipsum 2',
+ 'type' => $type1->id(),
+ ]);
+ $node->save();
+
+ // Node with type 2.
+ $node = Node::create([
+ 'title' => 'Lorem Ipsum 3',
+ 'type' => $type2->id(),
+ ]);
+ $node->save();
+
+ // Unpublished node.
+ $node = Node::create([
+ 'title' => 'Lorem unpublishd',
+ 'type' => $type1->id(),
+ 'status' => FALSE,
+ ]);
+ $node->save();
+
+ // Set the current user to someone that is not the node owner.
+ \Drupal::currentUser()->setAccount($this->createUser([], ['access content']));
+ }
+
+ /**
+ * Tests node matcher.
+ */
+ public function testNodeMatcherWidthDefaultConfiguration() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:node', []);
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests node matcher with bundle filer.
+ */
+ public function testNodeMatcherWidthBundleFiler() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:node', [
+ 'settings' => [
+ 'bundles' => [
+ 'test1' => 'test1',
+ ],
+ ],
+ ]);
+
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(2, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests node matcher with include unpublished setting activated.
+ */
+ public function testNodeMatcherWidthIncludeUnpublished() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:node', [
+ 'settings' => [
+ 'include_unpublished' => TRUE,
+ ],
+ ]);
+
+ // Test without permissions to see unpublished nodes.
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+
+ // Set the current user to a user with 'bypass node access' permission.
+ \Drupal::currentUser()->setAccount($this->createUser([], ['bypass node access']));
+
+ // Test with permissions to see unpublished nodes.
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(4, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests node matcher with tokens in the matcher metadata.
+ */
+ public function testNodeMatcherWidthMetadataTokens() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:node', [
+ 'settings' => [
+ 'metadata' => '[node:nid] [node:field_with_no_value]',
+ ],
+ ]);
+
+ $suggestionCollection = $plugin->execute('Lorem');
+ /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */
+ $suggestions = $suggestionCollection->getSuggestions();
+
+ foreach ($suggestions as $suggestion) {
+ $this->assertNotContains('[node:nid]', $suggestion->getDescription(), 'Raw token "[node:nid]" is not present in the description');
+ $this->assertNotContains('[node:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[node:field_with_no_value]" is not present in the description');
+ }
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/TermMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/TermMatcherTest.php
similarity index 51%
rename from sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/TermMatcherTest.php
rename to sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/TermMatcherTest.php
index d28a484a2..22f2c446e 100644
--- a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/TermMatcherTest.php
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/TermMatcherTest.php
@@ -1,23 +1,20 @@
getStorage('taxonomy_vocabulary');
- $vocabulary = $vocabularyStorage->create([
- 'name' => $name,
- 'description' => $name,
- 'vid' => Unicode::strtolower($name),
- 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
- ]);
- $vocabulary->save();
- return $vocabulary;
- }
-
- /**
- * Creates and saves a new term with in vocabulary $vid.
- *
- * @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary
- * The vocabulary object.
- * @param array $values
- * (optional) An array of values to set, keyed by property name. If the
- * entity type has bundles, the bundle key has to be specified.
- *
- * @return \Drupal\taxonomy\Entity\Term
- * The new taxonomy term object.
- */
- private function createTerm(Vocabulary $vocabulary, $values = array()) {
- $filter_formats = filter_formats();
- $format = array_pop($filter_formats);
-
- $termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
- $term = $termStorage->create($values + array(
- 'name' => $this->randomMachineName(),
- 'description' => array(
- 'value' => $this->randomMachineName(),
- // Use the first available text format.
- 'format' => $format->id(),
- ),
- 'vid' => $vocabulary->id(),
- 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
- ));
- $term->save();
- return $term;
- }
-
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
- $this->drupalLogin($this->adminUser);
+
+ // Create user 1 who has special permissions.
+ $this->createUser();
+
+ \Drupal::currentUser()->setAccount($this->createUser([], ['access content']));
+
+ $this->installEntitySchema('taxonomy_term');
+
$this->manager = $this->container->get('plugin.manager.linkit.matcher');
$testing_vocabulary_1 = $this->createVocabulary('testing_vocabulary_1');
@@ -107,28 +59,101 @@ class TermMatcherTest extends LinkitTestBase {
/**
* Tests term matcher with default configuration.
*/
- function testTermMatcherWidthDefaultConfiguration() {
+ public function testTermMatcherWidthDefaultConfiguration() {
/** @var \Drupal\linkit\MatcherInterface $plugin */
$plugin = $this->manager->createInstance('entity:taxonomy_term', []);
- $matches = $plugin->getMatches('foo');
- $this->assertEqual(5, count($matches), 'Correct number of matches');
+ $suggestions = $plugin->execute('foo');
+ $this->assertEquals(5, count($suggestions->getSuggestions()), 'Correct number of suggestions');
}
/**
* Tests term matcher with bundle filer.
*/
- function testTermMatcherWidthBundleFiler() {
+ public function testTermMatcherWidthBundleFiler() {
/** @var \Drupal\linkit\MatcherInterface $plugin */
$plugin = $this->manager->createInstance('entity:taxonomy_term', [
'settings' => [
'bundles' => [
- 'testing_vocabulary_1' => 'testing_vocabulary_1'
+ 'testing_vocabulary_1' => 'testing_vocabulary_1',
],
],
]);
- $matches = $plugin->getMatches('foo');
- $this->assertEqual(3, count($matches), 'Correct number of matches');
+ $suggestions = $plugin->execute('foo');
+ $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests term matcher with tokens in the matcher metadata.
+ */
+ public function testTermMatcherWidthMetadataTokens() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:taxonomy_term', [
+ 'settings' => [
+ 'metadata' => '[term:tid] [term:field_with_no_value]',
+ ],
+ ]);
+
+ $suggestionCollection = $plugin->execute('Lorem');
+ /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */
+ $suggestions = $suggestionCollection->getSuggestions();
+
+ foreach ($suggestions as $suggestion) {
+ $this->assertNotContains('[term:nid]', $suggestion->getDescription(), 'Raw token "[term:nid]" is not present in the description');
+ $this->assertNotContains('[term:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[term:field_with_no_value]" is not present in the description');
+ }
+ }
+
+ /**
+ * Creates and saves a vocabulary.
+ *
+ * @param string $name
+ * The vocabulary name.
+ *
+ * @return \Drupal\Core\Entity\EntityInterface|\Drupal\taxonomy\VocabularyInterface
+ * The new vocabulary object.
+ */
+ private function createVocabulary($name) {
+ $vocabularyStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_vocabulary');
+ $vocabulary = $vocabularyStorage->create([
+ 'name' => $name,
+ 'description' => $name,
+ 'vid' => Unicode::strtolower($name),
+ 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
+ ]);
+ $vocabulary->save();
+ return $vocabulary;
+ }
+
+ /**
+ * Creates and saves a new term with in vocabulary $vid.
+ *
+ * @param \Drupal\taxonomy\VocabularyInterface $vocabulary
+ * The vocabulary object.
+ * @param array $values
+ * (optional) An array of values to set, keyed by property name. If the
+ * entity type has bundles, the bundle key has to be specified.
+ *
+ * @return \Drupal\taxonomy\Entity\Term
+ * The new taxonomy term object.
+ */
+ private function createTerm(VocabularyInterface $vocabulary, array $values = []) {
+ $filter_formats = filter_formats();
+ $format = array_pop($filter_formats);
+
+ $termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
+ $term = $termStorage->create($values + [
+ 'name' => $this->randomMachineName(),
+ 'description' => [
+ 'value' => $this->randomMachineName(),
+ // Use the first available text format.
+ 'format' => $format->id(),
+ ],
+ 'vid' => $vocabulary->id(),
+ 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
+ ]);
+ $term->save();
+ return $term;
}
}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php
new file mode 100644
index 000000000..a9d8df5b3
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php
@@ -0,0 +1,138 @@
+createUser();
+
+ \Drupal::currentUser()->setAccount($this->createUser([], ['access user profiles']));
+
+ $this->manager = $this->container->get('plugin.manager.linkit.matcher');
+
+ $custom_role = Role::create([
+ 'id' => 'custom_role',
+ 'label' => 'custom_role',
+ ]);
+ $custom_role->save();
+
+ $custom_role_admin = Role::create([
+ 'id' => 'custom_role_admin',
+ 'label' => 'custom_role_admin',
+ ]);
+ $custom_role_admin->save();
+
+ $this->createUser(['name' => 'lorem']);
+ $this->createUser(['name' => 'foo']);
+
+ $account = $this->createUser(['name' => 'ipsumlorem']);
+ $account->addRole($custom_role);
+ $account->save();
+
+ $account = $this->createUser(['name' => 'lorem_custom_role']);
+ $account->addRole($custom_role);
+ $account->save();
+
+ $account = $this->createUser(['name' => 'lorem_custom_role_admin']);
+ $account->addRole($custom_role_admin);
+ $account->save();
+
+ $account = $this->createUser(['name' => 'blocked_lorem']);
+ $account->block();
+ $account->save();
+ }
+
+ /**
+ * Tests user matcher.
+ */
+ public function testUserMatcherWidthDefaultConfiguration() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:user', []);
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(4, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests user matcher with role filer.
+ */
+ public function testUserMatcherWidthRoleFiler() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:user', [
+ 'settings' => [
+ 'roles' => [
+ 'custom_role' => 'custom_role',
+ ],
+ ],
+ ]);
+
+ $suggestions = $plugin->execute('Lorem');
+ $this->assertEquals(2, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests user matcher with include blocked setting activated.
+ */
+ public function testUserMatcherWidthIncludeBlocked() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:user', [
+ 'settings' => [
+ 'include_blocked' => TRUE,
+ ],
+ ]);
+
+ // Test without permissions to see blocked users.
+ $suggestions = $plugin->execute('blocked');
+ $this->assertEquals(0, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+
+ // Set the current user to a user with 'administer users' permission.
+ \Drupal::currentUser()->setAccount($this->createUser([], ['administer users']));
+
+ // Test with permissions to see blocked users.
+ $suggestions = $plugin->execute('blocked');
+ $this->assertEquals(1, count($suggestions->getSuggestions()), 'Correct number of suggestions');
+ }
+
+ /**
+ * Tests user matcher with tokens in the matcher metadata.
+ */
+ public function testTermMatcherWidthMetadataTokens() {
+ /** @var \Drupal\linkit\MatcherInterface $plugin */
+ $plugin = $this->manager->createInstance('entity:user', [
+ 'settings' => [
+ 'metadata' => '[user:uid] [term:field_with_no_value]',
+ ],
+ ]);
+
+ $suggestionCollection = $plugin->execute('Lorem');
+ /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */
+ $suggestions = $suggestionCollection->getSuggestions();
+
+ foreach ($suggestions as $suggestion) {
+ $this->assertNotContains('[user:uid]', $suggestion->getDescription(), 'Raw token "[user:nid]" is not present in the description');
+ $this->assertNotContains('[user:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[user:field_with_no_value]" is not present in the description');
+ }
+ }
+
+}
diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php
new file mode 100644
index 000000000..18f78943d
--- /dev/null
+++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php
@@ -0,0 +1,181 @@
+substitutionManager = $this->container->get('plugin.manager.linkit.substitution');
+ $this->entityTypeManager = $this->container->get('entity_type.manager');
+
+ $this->installEntitySchema('file');
+ $this->installEntitySchema('entity_test');
+ $this->installEntitySchema('media');
+ $this->installEntitySchema('media_type');
+ $this->installEntitySchema('field_storage_config');
+ $this->installEntitySchema('field_config');
+ $this->installSchema('file', ['file_usage']);
+
+ unset($GLOBALS['config']['system.file']);
+ \Drupal::configFactory()->getEditable('system.file')->set('default_scheme', 'public')->save();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function register(ContainerBuilder $container) {
+ parent::register($container);
+
+ $container->register('stream_wrapper.public', 'Drupal\Core\StreamWrapper\PublicStream')
+ ->addTag('stream_wrapper', ['scheme' => 'public']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUpFilesystem() {
+ $public_file_directory = $this->siteDirectory . '/files';
+
+ require_once 'core/includes/file.inc';
+
+ mkdir($this->siteDirectory, 0775);
+ mkdir($this->siteDirectory . '/files', 0775);
+ mkdir($this->siteDirectory . '/files/config/' . CONFIG_SYNC_DIRECTORY, 0775, TRUE);
+
+ $this->setSetting('file_public_path', $public_file_directory);
+
+ $GLOBALS['config_directories'] = [
+ CONFIG_SYNC_DIRECTORY => $this->siteDirectory . '/files/config/sync',
+ ];
+ }
+
+ /**
+ * Test the file substitution.
+ */
+ public function testFileSubstitutions() {
+ $fileSubstitution = $this->substitutionManager->createInstance('file');
+ $file = File::create([
+ 'uid' => 1,
+ 'filename' => 'druplicon.txt',
+ 'uri' => 'public://druplicon.txt',
+ 'filemime' => 'text/plain',
+ 'status' => FILE_STATUS_PERMANENT,
+ ]);
+ $file->save();
+ $this->assertEquals($GLOBALS['base_url'] . '/' . $this->siteDirectory . '/files/druplicon.txt', $fileSubstitution->getUrl($file)->getGeneratedUrl());
+
+ $entity_type = $this->entityTypeManager->getDefinition('file');
+ $this->assertTrue(FileSubstitutionPlugin::isApplicable($entity_type), 'The entity type File is applicable the file substitution.');
+
+ $entity_type = $this->entityTypeManager->getDefinition('entity_test');
+ $this->assertFalse(FileSubstitutionPlugin::isApplicable($entity_type), 'The entity type EntityTest is not applicable the file substitution.');
+ }
+
+ /**
+ * Test the canonical substitution.
+ */
+ public function testCanonicalSubstitution() {
+ $canonicalSubstitution = $this->substitutionManager->createInstance('canonical');
+ $entity = EntityTest::create([]);
+ $entity->save();
+ $this->assertEquals('/entity_test/1', $canonicalSubstitution->getUrl($entity)->getGeneratedUrl());
+
+ $entity_type = $this->entityTypeManager->getDefinition('entity_test');
+ $this->assertTrue(CanonicalSubstitutionPlugin::isApplicable($entity_type), 'The entity type EntityTest is applicable the canonical substitution.');
+
+ $entity_type = $this->entityTypeManager->getDefinition('file');
+ $this->assertFalse(CanonicalSubstitutionPlugin::isApplicable($entity_type), 'The entity type File is not applicable the canonical substitution.');
+ }
+
+ /**
+ * Test the media substitution.
+ */
+ public function testMediaSubstitution() {
+ // Set up media bundle and fields.
+ $media_type = MediaType::create([
+ 'label' => 'test',
+ 'id' => 'test',
+ 'description' => 'Test type.',
+ 'source' => 'file',
+ ]);
+ $media_type->save();
+ $source_field = $media_type->getSource()->createSourceField($media_type);
+ $source_field->getFieldStorageDefinition()->save();
+ $source_field->save();
+ $media_type->set('source_configuration', [
+ 'source_field' => $source_field->getName(),
+ ])->save();
+
+ $file = File::create([
+ 'uid' => 1,
+ 'filename' => 'druplicon.txt',
+ 'uri' => 'public://druplicon.txt',
+ 'filemime' => 'text/plain',
+ 'status' => FILE_STATUS_PERMANENT,
+ ]);
+ $file->save();
+
+ $media = Media::create([
+ 'bundle' => 'test',
+ $source_field->getName() => ['target_id' => $file->id()],
+ ]);
+ $media->save();
+
+ $media_substitution = $this->substitutionManager->createInstance('media');
+ $this->assertEquals($GLOBALS['base_url'] . '/' . $this->siteDirectory . '/files/druplicon.txt', $media_substitution->getUrl($media)->getGeneratedUrl());
+
+ $entity_type = $this->entityTypeManager->getDefinition('media');
+ $this->assertTrue(MediaSubstitutionPlugin::isApplicable($entity_type), 'The entity type Media is applicable the media substitution.');
+
+ $entity_type = $this->entityTypeManager->getDefinition('file');
+ $this->assertFalse(MediaSubstitutionPlugin::isApplicable($entity_type), 'The entity type File is not applicable the media substitution.');
+ }
+
+}
diff --git a/sites/default/config/sync/editor.editor.wysiwyg.yml b/sites/default/config/sync/editor.editor.wysiwyg.yml
index 833cb8d7a..239bc4af9 100644
--- a/sites/default/config/sync/editor.editor.wysiwyg.yml
+++ b/sites/default/config/sync/editor.editor.wysiwyg.yml
@@ -23,7 +23,6 @@ settings:
items:
- DrupalLink
- DrupalUnlink
- - Linkit
-
name: Listes
items:
@@ -47,12 +46,13 @@ settings:
- PasteText
- PasteFromWord
plugins:
+ drupallink:
+ linkit_enabled: true
+ linkit_profile: collection
stylescombo:
styles: ''
language:
language_list: un
- linkit:
- linkit_profile: collection
image_upload:
status: true
scheme: public
diff --git a/sites/default/config/sync/filter.format.wysiwyg.yml b/sites/default/config/sync/filter.format.wysiwyg.yml
index e26b2c49c..861c7eaab 100644
--- a/sites/default/config/sync/filter.format.wysiwyg.yml
+++ b/sites/default/config/sync/filter.format.wysiwyg.yml
@@ -6,6 +6,7 @@ dependencies:
- editor
- edlp_admin
- edlp_corpus
+ - linkit
- url_to_video_filter
name: wysiwyg
format: wysiwyg
@@ -48,7 +49,7 @@ filters:
status: false
weight: -43
settings:
- allowed_html: '