summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam2016-08-22 18:17:19 +0200
committerEmil Stjerneman2016-08-22 18:17:19 +0200
commitc689cd001eb6b64f89414bd138c7cd94be36cecf (patch)
tree8c06c0447aa367b0ab36279bef056503851114b9
parent01b39f632949b48b2cf5706a3893d48a33a4a8d0 (diff)
Issue #2786049 by Sam152, anon: Make entity URL substitutions pluggable to support a wider variety of use cases
-rw-r--r--config/optional/linkit.linkit_profile.default.yml3
-rw-r--r--config/schema/linkit.schema.yml2
-rw-r--r--linkit.install31
-rw-r--r--linkit.module4
-rw-r--r--linkit.services.yml4
-rw-r--r--src/Annotation/Substitution.php35
-rw-r--r--src/Plugin/Filter/LinkitFilter.php41
-rw-r--r--src/Plugin/Linkit/Matcher/EntityMatcher.php30
-rw-r--r--src/Plugin/Linkit/Substitution/Canonical.php26
-rw-r--r--src/Plugin/Linkit/Substitution/File.php32
-rw-r--r--src/SubstitutionInterface.php24
-rw-r--r--src/SubstitutionManager.php43
-rw-r--r--src/SubstitutionManagerInterface.php41
-rw-r--r--src/Tests/Update/LinkitUpdate8501.php58
-rw-r--r--tests/fixtures/update/8501/editor.editor.format_1.yml25
-rw-r--r--tests/fixtures/update/8501/filter.format.format_1.yml17
-rw-r--r--tests/fixtures/update/8501/linkit-update-8501.php66
-rw-r--r--tests/fixtures/update/8501/linkit.linkit_profile.test_profile.yml47
-rw-r--r--tests/src/FunctionalJavascript/LinkitDialogTest.php2
-rw-r--r--tests/src/Kernel/LinkitEditorLinkDialogTest.php4
-rw-r--r--tests/src/Kernel/Matchers/AssertResultUriTrait.php2
-rw-r--r--tests/src/Kernel/SubstitutionPluginTest.php83
22 files changed, 595 insertions, 25 deletions
diff --git a/config/optional/linkit.linkit_profile.default.yml b/config/optional/linkit.linkit_profile.default.yml
index 23af68b..fe06c78 100644
--- a/config/optional/linkit.linkit_profile.default.yml
+++ b/config/optional/linkit.linkit_profile.default.yml
@@ -15,4 +15,5 @@ matchers:
result_description: 'by [node:author] | [node:created:medium]'
bundles: { }
group_by_bundle: false
- include_unpublished: false \ No newline at end of file
+ include_unpublished: false
+ substitution_type: canonical
diff --git a/config/schema/linkit.schema.yml b/config/schema/linkit.schema.yml
index 7038dc9..3952576 100644
--- a/config/schema/linkit.schema.yml
+++ b/config/schema/linkit.schema.yml
@@ -43,6 +43,8 @@ linkit.matcher.entity:
nullable: true
group_by_bundle:
type: boolean
+ substitution_type:
+ type: string
linkit.matcher.entity:*:
type: linkit.matcher.entity
diff --git a/linkit.install b/linkit.install
index 97c68d2..0b42ea9 100644
--- a/linkit.install
+++ b/linkit.install
@@ -122,3 +122,34 @@ function linkit_update_8500() {
$config->save(TRUE);
}
}
+
+/**
+ * Prepare anchor attributes for substitution plugins.
+ */
+function linkit_update_8501() {
+ $config_factory = \Drupal::configFactory();
+
+ // Update all filter formats that allow the data-entity-uuid attribute to also
+ // allow the data-entity-substitution attribute.
+ foreach ($config_factory->listAll('filter.format.') as $id) {
+ $filter = $config_factory->getEditable($id);
+ if ($allowed_html = $filter->get('filters.filter_html.settings.allowed_html')) {
+ $allowed_html = str_replace('data-entity-uuid', 'data-entity-uuid data-entity-substitution', $allowed_html);
+ $filter->set('filters.filter_html.settings.allowed_html', $allowed_html);
+ $filter->save(TRUE);
+ }
+ }
+
+ // Update all "file" matchers to the "file" substitution plugin, to maintain
+ // existing behavior out of the box.
+ $config_factory = \Drupal::configFactory();
+ foreach ($config_factory->listAll('linkit.linkit_profile.') as $id) {
+ $profile = $config_factory->getEditable($id);
+ foreach ($profile->get('matchers') as $key => $matcher) {
+ $settings = $profile->get('matchers.' . $key . '.settings');
+ $settings['substitution_type'] = $matcher['id'] === 'entity:file' ? 'file' : 'canonical';
+ $profile->set('matchers.' . $key . '.settings', $settings);
+ }
+ $profile->save(TRUE);
+ }
+}
diff --git a/linkit.module b/linkit.module
index 2920c70..55cdd24 100644
--- a/linkit.module
+++ b/linkit.module
@@ -169,12 +169,13 @@ function linkit_form_editor_link_dialog_validate(array &$form, FormStateInterfac
if (!empty($link_element)) {
$form_state->setValue(['attributes', 'data-entity-type'], '');
$form_state->setValue(['attributes', 'data-entity-uuid'], '');
+ $form_state->setValue(['attributes', 'data-entity-substitution'], '');
}
return;
}
// Parse the entity: URI into an entity type ID and entity ID.
- list($entity_type_id, $entity_id) = explode('/', $uri_parts['path'], 2);
+ list($substitution_type, $entity_type_id, $entity_id) = explode('/', $uri_parts['path'], 3);
// Check if the given entity type exists, to prevent the entity load method
// to throw exceptions.
@@ -192,6 +193,7 @@ function linkit_form_editor_link_dialog_validate(array &$form, FormStateInterfac
if (!empty($entity)) {
$form_state->setValue(['attributes', 'data-entity-type'], $entity->getEntityTypeId());
$form_state->setValue(['attributes', 'data-entity-uuid'], $entity->uuid());
+ $form_state->setValue(['attributes', 'data-entity-substitution'], $substitution_type);
}
else {
$form_state->setError($form['attributes']['href'], t('Invalid URI'));
diff --git a/linkit.services.yml b/linkit.services.yml
index 2c8904f..529c589 100644
--- a/linkit.services.yml
+++ b/linkit.services.yml
@@ -2,6 +2,8 @@ services:
plugin.manager.linkit.matcher:
class: Drupal\linkit\MatcherManager
parent: default_plugin_manager
-
+ plugin.manager.linkit.substitution:
+ class: Drupal\linkit\SubstitutionManager
+ parent: default_plugin_manager
linkit.suggestion_manager:
class: Drupal\linkit\SuggestionManager
diff --git a/src/Annotation/Substitution.php b/src/Annotation/Substitution.php
new file mode 100644
index 0000000..99183ba
--- /dev/null
+++ b/src/Annotation/Substitution.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\linkit\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a substitution annotation object.
+ *
+ * @Annotation
+ */
+class Substitution extends Plugin {
+
+ /**
+ * The plugin ID.
+ *
+ * @var string
+ */
+ public $id;
+
+ /**
+ * The human-readable name of the substitution.
+ *
+ * @var \Drupal\Core\Annotation\Translation
+ */
+ public $label;
+
+ /**
+ * An array of applicable entity types.
+ *
+ * @var array
+ */
+ public $entity_types = [];
+
+}
diff --git a/src/Plugin/Filter/LinkitFilter.php b/src/Plugin/Filter/LinkitFilter.php
index 02636cc..fdf19f0 100644
--- a/src/Plugin/Filter/LinkitFilter.php
+++ b/src/Plugin/Filter/LinkitFilter.php
@@ -8,6 +8,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
+use Drupal\linkit\SubstitutionManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -38,6 +39,13 @@ class LinkitFilter extends FilterBase implements ContainerFactoryPluginInterface
protected $entityRepository;
/**
+ * The substitution manager.
+ *
+ * @var \Drupal\linkit\SubstitutionManagerInterface
+ */
+ protected $substitutionManager;
+
+ /**
* Constructs a LinkitFilter object.
*
* @param array $configuration
@@ -49,10 +57,11 @@ class LinkitFilter extends FilterBase implements ContainerFactoryPluginInterface
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository service.
*/
- public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityRepositoryInterface $entity_repository) {
+ public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityRepositoryInterface $entity_repository, SubstitutionManagerInterface $substitution_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityRepository = $entity_repository;
+ $this->substitutionManager = $substitution_manager;
}
/**
@@ -63,7 +72,8 @@ class LinkitFilter extends FilterBase implements ContainerFactoryPluginInterface
$configuration,
$plugin_id,
$plugin_definition,
- $container->get('entity.repository')
+ $container->get('entity.repository'),
+ $container->get('plugin.manager.linkit.substitution')
);
}
@@ -83,24 +93,25 @@ class LinkitFilter extends FilterBase implements ContainerFactoryPluginInterface
// Load the appropriate translation of the linked entity.
$entity_type = $element->getAttribute('data-entity-type');
$uuid = $element->getAttribute('data-entity-uuid');
+
+ // Make the substitution optional, for backwards compatibility,
+ // maintaining the previous hard-coded direct file link assumptions,
+ // for content created before the substitution feature.
+ if (!$substitution_type = $element->getAttribute('data-entity-substitution')) {
+ $substitution_type = $entity_type === 'file' ? 'file' : SubstitutionManagerInterface::DEFAULT_SUBSTITUTION;
+ }
+
$entity = $this->entityRepository->loadEntityByUuid($entity_type, $uuid);
if ($entity) {
+
$entity = $this->entityRepository->getTranslationFromContext($entity, $langcode);
- // Set the appropriate href attribute.
- // The file entity has not declared any "links" in its entity
- // definition. We therefor have to use the file entity specific
- // getFileUri() instead.
- if ($entity_type === 'file') {
- /** @var \Drupal\file\Entity\File $entity */
- $url = file_create_url($entity->getFileUri());
- $element->setAttribute('href', $url);
- }
- else {
- $url = $entity->toUrl('canonical')->toString(TRUE);
- $element->setAttribute('href', $url->getGeneratedUrl());
- }
+ /** @var \Drupal\Core\GeneratedUrl $url */
+ $url = $this->substitutionManager
+ ->createInstance($substitution_type)
+ ->getUrl($entity);
+ $element->setAttribute('href', $url->getGeneratedUrl());
$access = $entity->access('view', NULL, TRUE);
// Set the appropriate title attribute.
diff --git a/src/Plugin/Linkit/Matcher/EntityMatcher.php b/src/Plugin/Linkit/Matcher/EntityMatcher.php
index 4c656f1..812a076 100644
--- a/src/Plugin/Linkit/Matcher/EntityMatcher.php
+++ b/src/Plugin/Linkit/Matcher/EntityMatcher.php
@@ -13,6 +13,8 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\linkit\ConfigurableMatcherBase;
use Drupal\linkit\MatcherTokensTrait;
+use Drupal\linkit\SubstitutionManager;
+use Drupal\linkit\SubstitutionManagerInterface;
use Drupal\linkit\Suggestion\DescriptionSuggestion;
use Drupal\linkit\Suggestion\SuggestionCollection;
use Drupal\linkit\Utility\LinkitXss;
@@ -81,9 +83,16 @@ class EntityMatcher extends ConfigurableMatcherBase {
protected $targetType;
/**
+ * The substitution manager.
+ *
+ * @var \Drupal\linkit\SubstitutionManagerInterface
+ */
+ protected $substitutionManager;
+
+ /**
* {@inheritdoc}
*/
- public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityRepositoryInterface $entity_repository, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
+ public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityRepositoryInterface $entity_repository, ModuleHandlerInterface $module_handler, AccountInterface $current_user, SubstitutionManagerInterface $substitution_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
if (empty($plugin_definition['target_entity'])) {
@@ -96,6 +105,7 @@ class EntityMatcher extends ConfigurableMatcherBase {
$this->moduleHandler = $module_handler;
$this->currentUser = $current_user;
$this->targetType = $plugin_definition['target_entity'];
+ $this->substitutionManager = $substitution_manager;
}
/**
@@ -111,7 +121,8 @@ class EntityMatcher extends ConfigurableMatcherBase {
$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')
);
}
@@ -160,6 +171,7 @@ class EntityMatcher extends ConfigurableMatcherBase {
'result_description' => '',
'bundles' => [],
'group_by_bundle' => FALSE,
+ 'substitution_type' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION,
];
}
@@ -205,6 +217,17 @@ class EntityMatcher extends ConfigurableMatcherBase {
];
}
+ $substitution_options = $this->substitutionManager->getApplicablePluginsOptionList($this->targetType);
+ $form['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.'),
+ '#weight' => -49,
+ '#access' => count($substitution_options) !== 1,
+ ];
+
return $form;
}
@@ -221,6 +244,7 @@ class EntityMatcher extends ConfigurableMatcherBase {
$this->configuration['result_description'] = $form_state->getValue('result_description');
$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');
}
/**
@@ -344,7 +368,7 @@ class EntityMatcher extends ConfigurableMatcherBase {
* @see \Drupal\Core\Url::fromEntityUri()
*/
protected function buildPath(EntityInterface $entity) {
- return 'entity:' . $entity->getEntityTypeId() . '/' . $entity->id();
+ return 'entity:' . $this->configuration['substitution_type'] . '/' . $entity->getEntityTypeId() . '/' . $entity->id();
}
/**
diff --git a/src/Plugin/Linkit/Substitution/Canonical.php b/src/Plugin/Linkit/Substitution/Canonical.php
new file mode 100644
index 0000000..10b1db8
--- /dev/null
+++ b/src/Plugin/Linkit/Substitution/Canonical.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\linkit\Plugin\Linkit\Substitution;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\linkit\SubstitutionInterface;
+use Drupal\views\Plugin\views\PluginBase;
+
+/**
+ * A substitution plugin for the canonical URL of an entity.
+ *
+ * @Substitution(
+ * id = "canonical",
+ * label = @Translation("Canonical URL"),
+ * )
+ */
+class Canonical extends PluginBase implements SubstitutionInterface {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUrl(EntityInterface $entity) {
+ return $entity->toUrl('canonical')->toString(TRUE);
+ }
+
+}
diff --git a/src/Plugin/Linkit/Substitution/File.php b/src/Plugin/Linkit/Substitution/File.php
new file mode 100644
index 0000000..b74bc50
--- /dev/null
+++ b/src/Plugin/Linkit/Substitution/File.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Drupal\linkit\Plugin\Linkit\Substitution;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\GeneratedUrl;
+use Drupal\linkit\SubstitutionInterface;
+use Drupal\views\Plugin\views\PluginBase;
+
+/**
+ * A substitution plugin for the URL to a file.
+ *
+ * @Substitution(
+ * id = "file",
+ * label = @Translation("Direct File URL"),
+ * entity_types = {"file"},
+ * )
+ */
+class File extends PluginBase implements SubstitutionInterface {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUrl(EntityInterface $entity) {
+ $url = new GeneratedUrl();
+ /** @var \Drupal\file\FileInterface $entity */
+ $url->setGeneratedUrl(file_create_url($entity->getFileUri()));
+ $url->addCacheableDependency($entity);
+ return $url;
+ }
+
+}
diff --git a/src/SubstitutionInterface.php b/src/SubstitutionInterface.php
new file mode 100644
index 0000000..1760c0b
--- /dev/null
+++ b/src/SubstitutionInterface.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Drupal\linkit;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Interface for substitution plugins.
+ */
+interface SubstitutionInterface extends PluginInspectionInterface {
+
+ /**
+ * Get the URL associated with a given entity.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The entity to get a URL for.
+ *
+ * @return \Drupal\Core\GeneratedUrl
+ * A url to replace.
+ */
+ public function getUrl(EntityInterface $entity);
+
+}
diff --git a/src/SubstitutionManager.php b/src/SubstitutionManager.php
new file mode 100644
index 0000000..1bb6437
--- /dev/null
+++ b/src/SubstitutionManager.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Drupal\linkit;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\DefaultPluginManager;
+
+/**
+ * A plugin manager for the substitution plugins.
+ */
+class SubstitutionManager extends DefaultPluginManager implements SubstitutionManagerInterface {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
+ parent::__construct('Plugin/Linkit/Substitution', $namespaces, $module_handler, 'Drupal\linkit\SubstitutionInterface', 'Drupal\linkit\Annotation\Substitution');
+ $this->alterInfo('linkit_substitution');
+ $this->setCacheBackend($cache_backend, 'linkit_substitution');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterPluginDefinitions($definitions, $entity_type_id) {
+ return array_filter($definitions, function($definition) use ($entity_type_id) {
+ return empty($definition['entity_types']) || in_array($entity_type_id, $definition['entity_types']);
+ });
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getApplicablePluginsOptionList($entity_type_id) {
+ $options = [];
+ foreach ($this->filterPluginDefinitions($this->getDefinitions(), $entity_type_id) as $id => $definition) {
+ $options[$id] = $definition['label'];
+ }
+ return $options;
+ }
+
+}
diff --git a/src/SubstitutionManagerInterface.php b/src/SubstitutionManagerInterface.php
new file mode 100644
index 0000000..074f084
--- /dev/null
+++ b/src/SubstitutionManagerInterface.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Drupal\linkit;
+
+use Drupal\Component\Plugin\PluginManagerInterface;
+
+/**
+ * An interface for the substitution manager.
+ */
+interface SubstitutionManagerInterface extends PluginManagerInterface {
+
+ /**
+ * Get the default substitution.
+ */
+ const DEFAULT_SUBSTITUTION = 'canonical';
+
+ /**
+ * Filter a list of plugin definitions by entity ID.
+ *
+ * @param array $definitions
+ * An array of plugin definitions.
+ * @param string $entity_type_id
+ * The entity type ID to get applicable plugins for.
+ *
+ * @return array
+ * The definitions appropriate for the given entity ID.
+ */
+ public function filterPluginDefinitions($definitions, $entity_type_id);
+
+ /**
+ * Get a form API options list for the entity ID.
+ *
+ * @param string $entity_type_id
+ * The entity type ID.
+ *
+ * @return array
+ * An options list.
+ */
+ public function getApplicablePluginsOptionList($entity_type_id);
+
+}
diff --git a/src/Tests/Update/LinkitUpdate8501.php b/src/Tests/Update/LinkitUpdate8501.php
new file mode 100644
index 0000000..cadbec6
--- /dev/null
+++ b/src/Tests/Update/LinkitUpdate8501.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Drupal\linkit\Tests\Update;
+
+use Drupal\filter\Entity\FilterFormat;
+use Drupal\system\Tests\Update\UpdatePathTestBase;
+
+/**
+ * Tests Linkit upgrade path for update 8501.
+ *
+ * @group Update
+ */
+class LinkitUpdate8501 extends UpdatePathTestBase {
+
+ /**
+ * The config factory service.
+ *
+ * @var \Drupal\Core\Config\ConfigFactoryInterface
+ */
+ protected $configFactory;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+ $this->configFactory = $this->container->get('config.factory');
+ }
+
+ /**
+ * Set database dump files to be used.
+ */
+ protected function setDatabaseDumpFiles() {
+ $this->databaseDumpFiles = [
+ __DIR__ . '/../../../tests/fixtures/update/linkit-4-to-5/drupal-8.linkit-enabled.standard.php.gz',
+ __DIR__ . '/../../../tests/fixtures/update/8501/linkit-update-8501.php',
+ ];
+ }
+
+ /**
+ * Tests linkit_update_8501().
+ *
+ * @see linkit_update_8501()
+ */
+ public function testLinkitUpdate8501() {
+ $this->runUpdates();
+
+ $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile');
+ $this->assertEqual('canonical', $test_profile->get('matchers.fc48c807-2a9c-44eb-b86b-7e134c1aa252.settings.substitution_type'), 'Content matcher has a substitution type of canonical.');
+ $this->assertEqual('file', $test_profile->get('matchers.b8d6d672-6377-493f-b492-3cc69511cf17.settings.substitution_type'), 'File matcher has a substitution type of file.');
+
+ $htmlRestrictions = FilterFormat::load('format_1')->getHtmlRestrictions();
+ $this->assertTrue(array_key_exists("data-entity-type", $htmlRestrictions['allowed']['a']));
+ $this->assertTrue(array_key_exists("data-entity-uuid", $htmlRestrictions['allowed']['a']));
+ $this->assertTrue(array_key_exists("data-entity-substitution", $htmlRestrictions['allowed']['a']));
+ }
+
+}
diff --git a/tests/fixtures/update/8501/editor.editor.format_1.yml b/tests/fixtures/update/8501/editor.editor.format_1.yml
new file mode 100644
index 0000000..46a0f3f
--- /dev/null
+++ b/tests/fixtures/update/8501/editor.editor.format_1.yml
@@ -0,0 +1,25 @@
+uuid: 5600b759-8f91-49fa-88f0-a69f4c8ed440
+langcode: en
+status: true
+dependencies:
+ config:
+ - filter.format.format_1
+ module:
+ - ckeditor
+format: format_1
+editor: ckeditor
+settings:
+ toolbar:
+ rows:
+ -
+ -
+ name: Links
+ items:
+ - Linkit
+ plugins:
+ stylescombo:
+ styles: ''
+ language:
+ language_list: un
+ linkit:
+ linkit_profile: test_profile
diff --git a/tests/fixtures/update/8501/filter.format.format_1.yml b/tests/fixtures/update/8501/filter.format.format_1.yml
new file mode 100644
index 0000000..619bba2
--- /dev/null
+++ b/tests/fixtures/update/8501/filter.format.format_1.yml
@@ -0,0 +1,17 @@
+uuid: ff6b71a0-5051-4857-a0a8-28a670b7317d
+langcode: en
+status: true
+dependencies: { }
+name: 'Format 1'
+format: format_1
+weight: 0
+filters:
+ filter_html:
+ id: filter_html
+ provider: filter
+ status: true
+ weight: -10
+ settings:
+ allowed_html: '<a href hreflang data-entity-type data-entity-uuid> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type=''1 A I''> <li> <dl> <dt> <dd> <h2 id=''jump-*''> <h3 id> <h4 id> <h5 id> <h6 id>'
+ filter_html_help: true
+ filter_html_nofollow: false
diff --git a/tests/fixtures/update/8501/linkit-update-8501.php b/tests/fixtures/update/8501/linkit-update-8501.php
new file mode 100644
index 0000000..d7bdc2b
--- /dev/null
+++ b/tests/fixtures/update/8501/linkit-update-8501.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Database fixture for testing the upgrade path for Linkit 4 to 5.
+ *
+ * Contains database additions to drupal-8.bare.standard.php.gz for testing the
+ * upgrade path for Linkit 4 to 5.
+ */
+
+use Drupal\Component\Serialization\Yaml;
+use Drupal\Core\Database\Database;
+
+$connection = Database::getConnection();
+
+// Configuration for linkit profiles.
+$config = Yaml::decode(file_get_contents(__DIR__ . '/linkit.linkit_profile.test_profile.yml'));
+$connection->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'));
+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'));
+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/tests/fixtures/update/8501/linkit.linkit_profile.test_profile.yml b/tests/fixtures/update/8501/linkit.linkit_profile.test_profile.yml
new file mode 100644
index 0000000..bee4523
--- /dev/null
+++ b/tests/fixtures/update/8501/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/tests/src/FunctionalJavascript/LinkitDialogTest.php b/tests/src/FunctionalJavascript/LinkitDialogTest.php
index df0f528..a77a60d 100644
--- a/tests/src/FunctionalJavascript/LinkitDialogTest.php
+++ b/tests/src/FunctionalJavascript/LinkitDialogTest.php
@@ -170,7 +170,7 @@ class LinkitDialogTest extends JavascriptTestBase {
$page->find('xpath', '(//li[contains(@class, "linkit-result") and contains(@class, "ui-menu-item")])[1]')->click();
// Make sure the href field is populated with the node uri.
- $this->assertEquals('entity:' . $this->demoEntity->getEntityTypeId() . '/' . $this->demoEntity->id(), $input_field->getValue(), 'The href field is populated with the node uri');
+ $this->assertEquals('entity:canonical/' . $this->demoEntity->getEntityTypeId() . '/' . $this->demoEntity->id(), $input_field->getValue(), 'The href field is populated with the node uri');
// Make sure the link information is populated.
$javascript = "(function (){ return jQuery('.linkit-link-information > span').text(); })()";
diff --git a/tests/src/Kernel/LinkitEditorLinkDialogTest.php b/tests/src/Kernel/LinkitEditorLinkDialogTest.php
index 1a02b19..774fb35 100644
--- a/tests/src/Kernel/LinkitEditorLinkDialogTest.php
+++ b/tests/src/Kernel/LinkitEditorLinkDialogTest.php
@@ -125,7 +125,7 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$this->assertEquals('', $form['attributes']['href']['#default_value'], 'The href attribute is empty.');
$this->assertEquals('', $form['attributes']['link-information']['#context']['link_target'], 'Link information is empty.');
- $form_state->setValue(['attributes', 'href'], 'entity:missing_entity/1');
+ $form_state->setValue(['attributes', 'href'], 'entity:canonical/missing_entity/1');
$form_builder->submitForm($form_object, $form_state);
$this->assertNotEmpty($form_state->getErrors(), 'Got validation errors for none existing entity type.');
@@ -135,7 +135,7 @@ class LinkitEditorLinkDialogTest extends LinkitKernelTestBase {
$this->assertEquals('', $form_state->getValue(['attributes', 'data-entity-type']));
$this->assertEquals('', $form_state->getValue(['attributes', 'data-entity-uuid']));
- $form_state->setValue(['attributes', 'href'], 'entity:entity_test/1');
+ $form_state->setValue(['attributes', 'href'], 'entity:canonical/entity_test/1');
$form_builder->submitForm($form_object, $form_state);
$this->assertEmpty($form_state->getErrors(), 'Got no validation errors for correct URI.');
$this->assertEquals($entity->getEntityTypeId(), $form_state->getValue(['attributes', 'data-entity-type']), 'Attribute "data-entity-type" exists and has the correct value.');
diff --git a/tests/src/Kernel/Matchers/AssertResultUriTrait.php b/tests/src/Kernel/Matchers/AssertResultUriTrait.php
index 1ccc656..9398c57 100644
--- a/tests/src/Kernel/Matchers/AssertResultUriTrait.php
+++ b/tests/src/Kernel/Matchers/AssertResultUriTrait.php
@@ -19,7 +19,7 @@ trait AssertResultUriTrait {
*/
public function assertResultUri($entity_type, SuggestionCollection $suggestions) {
foreach ($suggestions->getSuggestions() as $suggestion) {
- $this->assertTrue(preg_match("/^entity:" . $entity_type . "\\/\\w+$/i", $suggestion->getPath()), 'Result URI correct formatted.');
+ $this->assertTrue(preg_match("/^entity:canonical\/" . $entity_type . "\\/\\w+$/i", $suggestion->getPath()), 'Result URI correct formatted.');
}
}
diff --git a/tests/src/Kernel/SubstitutionPluginTest.php b/tests/src/Kernel/SubstitutionPluginTest.php
new file mode 100644
index 0000000..d43346d
--- /dev/null
+++ b/tests/src/Kernel/SubstitutionPluginTest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Drupal\Tests\linkit\Kernel;
+
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\file\Entity\File;
+
+/**
+ * Tests the substitution plugins.
+ *
+ * @group linkit
+ */
+class SubstitutionPluginTest extends LinkitKernelTestBase {
+
+ /**
+ * The substitution manager.
+ *
+ * @var \Drupal\linkit\SubstitutionManagerInterface
+ */
+ protected $substitutionManager;
+
+ /**
+ * The file substitution plugin.
+ *
+ * @var \Drupal\linkit\SubstitutionInterface
+ */
+ protected $fileSubstitution;
+
+ /**
+ * The canonical substitution plugin.
+ *
+ * @var \Drupal\linkit\SubstitutionInterface
+ */
+ protected $canonicalSubstitution;
+
+ /**
+ * Additional modules to enable.
+ *
+ * @var array
+ */
+ public static $modules = [
+ 'file',
+ 'entity_test',
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ parent::setUp();
+ $this->substitutionManager = $this->container->get('plugin.manager.linkit.substitution');
+ $this->fileSubstitution = $this->substitutionManager->createInstance('file');
+ $this->canonicalSubstitution = $this->substitutionManager->createInstance('canonical');
+
+ $this->installEntitySchema('file');
+ $this->installEntitySchema('entity_test');
+ }
+
+ /**
+ * Test the file substitution.
+ */
+ public function testFileSubstitutions() {
+ $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', $this->fileSubstitution->getUrl($file)->getGeneratedUrl());
+ }
+
+ /**
+ * Test the canonical URL substitution.
+ */
+ public function testCanonicalSubstutition() {
+ $entity = EntityTest::create([]);
+ $entity->save();
+ $this->assertEquals('/entity_test/1', $this->canonicalSubstitution->getUrl($entity)->getGeneratedUrl());
+ }
+
+}