editor_advanced_link-8.x-1.8/src/Plugin/CKEditor5Plugin/AdvancedLink.php
src/Plugin/CKEditor5Plugin/AdvancedLink.php
<?php
declare(strict_types=1);
namespace Drupal\editor_advanced_link\Plugin\CKEditor5Plugin;
use Drupal\ckeditor5\Plugin\CKEditor5PluginConfigurableTrait;
use Drupal\ckeditor5\Plugin\CKEditor5PluginDefault;
use Drupal\ckeditor5\Plugin\CKEditor5PluginConfigurableInterface;
use Drupal\ckeditor5\Plugin\CKEditor5PluginElementsSubsetInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\editor\EditorInterface;
/**
* CKEditor 5 Advanced Link plugin.
*/
class AdvancedLink extends CKEditor5PluginDefault implements CKEditor5PluginConfigurableInterface, CKEditor5PluginElementsSubsetInterface {
use CKEditor5PluginConfigurableTrait;
/**
* The default configuration for this plugin.
*
* @var string[][]
*/
const DEFAULT_CONFIGURATION = [
'enabled_attributes' => [],
];
/**
* All <a> attributes that this plugin supports.
*
* @var array
*/
const SUPPORTED_ATTRIBUTES = [
'aria-label' => TRUE,
'title' => TRUE,
'class' => TRUE,
'id' => TRUE,
'target' => ['_blank'],
'rel' => TRUE,
];
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return static::DEFAULT_CONFIGURATION;
}
/**
* Gets all valid choices for the "enabled_attributes" setting.
*
* @see editor_advanced_link.schema.yml
*
* @return string[]
* All valid choices.
*/
public static function validChoices(): array {
return array_keys(self::SUPPORTED_ATTRIBUTES);
}
/**
* Gets all enabled attributes.
*
* @return string[]
* The values in the plugins.ckeditor5_link.enabled_attributes config.
*/
private function getEnabledAttributes(): array {
return $this->configuration['enabled_attributes'];
}
/**
* {@inheritdoc}
*
* Form for choosing which additional <a> attributes are available.
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['enabled_attributes'] = [
'#type' => 'fieldset',
'#title' => $this->t('Enabled attributes'),
'#description' => $this->t('These are the attributes that will appear when creating or editing links.'),
];
// UI labels corresponding to each of the supported attributes.
$config_ui_labels = [
'aria-label' => $this->t('ARIA label'),
'title' => $this->t('Title'),
'class' => $this->t('CSS classes'),
'id' => $this->t('ID'),
'target' => $this->t('Open in new window'),
'rel' => $this->t('Link relationship'),
];
assert(count(self::SUPPORTED_ATTRIBUTES) === count($config_ui_labels));
foreach (array_keys(self::SUPPORTED_ATTRIBUTES) as $attribute) {
$form['enabled_attributes'][$attribute] = [
'#type' => 'checkbox',
'#title' => $this->t('@label (<code>@attribute</code>)', [
'@label' => $config_ui_labels[$attribute],
'@attribute' => Html::escape(self::getAllowedHtmlForSupportedAttribute($attribute)),
]),
'#return_value' => $attribute,
];
$form['enabled_attributes'][$attribute]['#default_value'] = in_array($attribute, $this->configuration['enabled_attributes'], TRUE);
}
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
// Match the config schema structure at
// ckeditor5.plugin.editor_advanced_link_link.
$form_value = $form_state->getValue('enabled_attributes');
$config_value = array_values(array_filter($form_value));
$form_state->setValue('enabled_attributes', $config_value);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['enabled_attributes'] = $form_state->getValue('enabled_attributes');
}
/**
* {@inheritdoc}
*
* Filters the enabled attributes to those chosen in editor config.
*/
public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array {
$enabled_attributes = $this->getEnabledAttributes();
$supported_attributes = $static_plugin_config['editorAdvancedLink']['options'];
$config = [];
if (in_array('target', $enabled_attributes, TRUE)) {
$config['link']['decorators'][] = [
'mode' => 'manual',
'label' => $this->t('Open in new window'),
'attributes' => [
'target' => '_blank',
],
];
}
return $config + [
'editorAdvancedLink' => [
'options' => array_intersect($supported_attributes, $enabled_attributes),
],
];
}
/**
* {@inheritdoc}
*/
public function getElementsSubset(): array {
$subset = [];
foreach ($this->getEnabledAttributes() as $attribute) {
$subset[] = self::getAllowedHtmlForSupportedAttribute($attribute);
}
return $subset;
}
/**
* Gets the allowed HTML string representation for a supported attribute.
*
* @param string $attribute
* One of self::SUPPORTED_ATTRIBUTES.
*
* @return string
* The corresponding allowed HTML string representation.
*/
public static function getAllowedHtmlForSupportedAttribute(string $attribute): string {
if (!array_key_exists($attribute, self::SUPPORTED_ATTRIBUTES)) {
throw new \OutOfBoundsException();
}
$allowed_values = self::SUPPORTED_ATTRIBUTES[$attribute];
if ($allowed_values === TRUE) {
// For attributes for which any value can be created.
return sprintf('<a %s>', $attribute);
}
else {
// For attributes for which only a single value can be created.
return sprintf('<a %s="%s">', $attribute, implode(' ', $allowed_values));
}
}
}
