class Freelinking in Freelinking 8.3
Same name in this branch
- 8.3 src/Annotation/Freelinking.php \Drupal\freelinking\Annotation\Freelinking
- 8.3 src/Plugin/Filter/Freelinking.php \Drupal\freelinking\Plugin\Filter\Freelinking
Same name and namespace in other branches
- 4.0.x src/Plugin/Filter/Freelinking.php \Drupal\freelinking\Plugin\Filter\Freelinking
Freelinking input filter plugin.
Plugin annotation
@Filter(
id = "freelinking",
title = @Translation("Freelinking"),
description = @Translation("Allows for a flexible format for linking content."),
type = \Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE,
provider = "freelinking",
status = false,
settings = {
"default": "nodetitle",
"global_options": {
"ignore_upi": false
},
"plugins": {},
},
weight = "0"
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\filter\Plugin\FilterBase implements FilterInterface
- class \Drupal\freelinking\Plugin\Filter\Freelinking implements ContainerFactoryPluginInterface
- class \Drupal\filter\Plugin\FilterBase implements FilterInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of Freelinking
1 file declares its use of Freelinking
- FreelinkingTest.php in tests/
src/ Unit/ Plugin/ Filter/ FreelinkingTest.php
4 string references to 'Freelinking'
- DrupalOrgTest::testBuildLink in tests/
src/ Unit/ Plugin/ freelinking/ DrupalOrgTest.php - Asserts that buildLink returns appropriate render array.
- freelinking.info.yml in ./
freelinking.info.yml - freelinking.info.yml
- freelinking.schema.yml in config/
schema/ freelinking.schema.yml - config/schema/freelinking.schema.yml
- FreelinkingTest::setUp in tests/
src/ Unit/ Plugin/ Filter/ FreelinkingTest.php
File
- src/
Plugin/ Filter/ Freelinking.php, line 33
Namespace
Drupal\freelinking\Plugin\FilterView source
class Freelinking extends FilterBase implements ContainerFactoryPluginInterface {
/**
* Freelinking plugin manager.
*
* @var \Drupal\freelinking\FreelinkingManagerInterface
*/
protected $freelinkingManager;
/**
* Current user account.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Initialize method.
*
* @param array $configuration
* The plugin configuration.
* @param string $plugin_id
* The plugin ID.
* @param array $plugin_definition
* The plugin definition array.
* @param \Drupal\freelinking\FreelinkingManagerInterface $freelinkingManager
* The Freelinking plugin manager.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user account.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, FreelinkingManagerInterface $freelinkingManager, AccountProxyInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->freelinkingManager = $freelinkingManager;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('freelinking.manager'), $container
->get('current_user'));
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$plugins = $this->freelinkingManager
->getDefinitions();
$form['default'] = [
'#type' => 'textfield',
'#title' => $this
->t('Default plugin'),
'#description' => $this
->t('Default plugin to use when no indicator is specified. “Nodetitle” mimics previous versions of Freelinking.'),
'#default_value' => $this->settings['default'],
'#required' => TRUE,
];
$form['global_options'] = [
'#tree' => TRUE,
'ignore_upi' => [
'#type' => 'select',
'#title' => $this
->t('Ignore Unknown Plugin Indicators (UPI)'),
'#description' => $this
->t('Choose whether to ignore markup that may look like freelinking or does not have a valid plugin.'),
'#options' => [
0 => $this
->t('Display an error'),
1 => $this
->t('Ignore indicators'),
],
'#required' => TRUE,
'#default_value' => $this->settings['global_options']['ignore_upi'],
],
];
$form['plugins'] = [
'#tree' => TRUE,
];
foreach ($plugins as $plugin_name => $plugin_definition) {
$config = $this
->extractPluginSettings($plugin_name, $this->settings['plugins']);
$plugin_settings = isset($config['settings']) ? $config['settings'] : [];
$plugin = $this->freelinkingManager
->createInstance($plugin_name, [
'settings' => $plugin_settings,
]);
$form['plugins'][$plugin_name] = [
'#tree' => TRUE,
'#type' => 'fieldset',
'#collapsible' => FALSE,
'#title' => $plugin_definition['title'],
'plugin' => [
'#type' => 'value',
'#value' => $plugin_name,
],
'enabled' => [
'#type' => 'checkbox',
'#title' => $this
->t('Enable'),
'#default_value' => isset($config['enabled']) ? $config['enabled'] : FALSE,
],
'settings' => [
'#tree' => TRUE,
'#type' => 'container',
] + $plugin
->settingsForm($form, $form_state),
];
// Hide the enabled checkbox if the plugin is always enabled.
if ($plugin
->isHidden()) {
$form['plugins'][$plugin_name]['enabled']['#disabled'] = TRUE;
$form['plugins'][$plugin_name]['enabled']['#default_value'] = TRUE;
}
}
return $form;
}
/**
* {@inheritdoc}
*/
public function tips($long = FALSE) {
$text = $this
->t('Freelinking helps you easily create HTML links. Links take the form of <code>[[indicator:target|Title]].</code>');
if (!$long) {
if (isset($this->settings['default']) && 'NONE' !== $this->settings['default']) {
$plugin = $this->freelinkingManager
->createInstance($this->settings['default']);
$text .= ' ' . $plugin
->getTip();
}
return $text;
}
$content = <<<EOF
<p>Freelinking helps you easily create HTML links. Links take the form of <code>[[indicator:target|Title]].</code><br />
Below is a list of available types of freelinks you may use, organized as <strong>Plugin Name</strong>: [<em>indicator</em>].</p>
<ul>
EOF;
// Assemble tips for each allowed plugin.
$allowed_plugins = $this
->extractAllowedPlugins($this->settings['plugins']);
foreach ($allowed_plugins as $plugin_name => $plugin_info) {
$settings = isset($plugin_info['settings']) ? $plugin_info['settings'] : [];
$plugin = $this->freelinkingManager
->createInstance($plugin_info['plugin'], $settings);
$content .= '<li><strong>' . $plugin
->getPluginDefinition()['title'] . '</strong> [<em>' . $plugin
->getIndicator() . '</em>]: ' . $plugin
->getTip() . '</li>';
}
$content .= '</ul>';
// Ignore phpcs warning because tips are dynamically generated based on
// plugins. This follows the pattern in core.
// @see \Drupal\filter\Plugin\Filter\FilterAlign::tips().
return $this
->t($content);
}
/**
* {@inheritdoc}
*/
public function process($text, $langcode) {
$defaultplugin = $this->settings['default'];
// Ignore the node language if the current user's preferred language is
// different so that links can be generated in the user's native language.
$user_langcode = $langcode != $this->currentUser
->getPreferredLangcode() ? $this->currentUser
->getPreferredLangcode() : $langcode;
$result = new FilterProcessResult($text);
// $pattern = '/(\[\[([a-z0-9\_]+):([^\]]+)\]\])/';.
// @todo why not go back to preg_match_all for double square bracket syntax?
// @see https://www.drupal.org/node/647940
$start = 0;
$remain = $text;
$newtext = '';
// Begin an indefinite loop until it is manually broken.
while (TRUE) {
$offset = 0;
// Break when there is no remaining text to process.
if (empty($remain)) {
break;
}
// Begin freelinking parse or reset.
if ('[' === $remain[0] && '[' === $remain[1]) {
$infreelinkp = TRUE;
$delim = ']]';
}
else {
$infreelinkp = FALSE;
$delim = '[[';
}
// Break out of loop if cannot find anything in remaining text.
$pos = strpos($remain, $delim);
if (FALSE === $pos) {
break;
}
// Get the next chunk of text until the position of the delimiter above,
// and if in freelinking, start processing, otherwise set remaining text
// to the next chunk from the beginning delimiter.
$chunk_all = substr($remain, $start, $pos);
if ($infreelinkp) {
$chunk_stripped = substr($chunk_all, 2);
// Find the indicator (plugin) from the first set of characters up until
// the colon, or use the default plugin.
$indicatorPosition = strpos($chunk_stripped, ':');
if (FALSE === $indicatorPosition) {
$indicator = $defaultplugin;
$target = $chunk_stripped;
}
else {
$indicator = substr($chunk_stripped, 0, $indicatorPosition);
$target = substr($chunk_stripped, $indicatorPosition + 1);
}
// Load the current plugin from the indicator and available plugins.
$current_plugin = $this->freelinkingManager
->getPluginFromIndicator($indicator, $this
->extractAllowedPlugins($this->settings['plugins']), $this->settings);
if (!$this->settings['global_options']['ignore_upi'] || $current_plugin) {
// Lazy Builder callback and context must be scalar.
if (!$current_plugin) {
$link = $result
->createPlaceholder('freelinking.manager:createErrorElement', [
$indicator,
]);
}
else {
// Serialize plugin settings as a string.
$plugin_settings = self::extractPluginSettings($current_plugin
->getPluginId(), $this->settings['plugins']);
// Failover plugin settings need to be extracted here and passed in
// to the placeholder as well.
if ($current_plugin
->getFailoverPluginId()) {
$failover_settings = self::extractPluginSettings($current_plugin
->getFailoverPluginId(), $this->settings['plugins']);
}
else {
$failover_settings = [];
}
$link = $result
->createPlaceholder('freelinking.manager:createFreelinkElement', [
$current_plugin
->getPluginId(),
$target,
$indicator,
$user_langcode,
serialize($plugin_settings),
serialize($failover_settings),
]);
}
if ($link) {
$chunk_all = $link;
$offset = 2;
}
}
$remain = substr($remain, $pos + $offset);
}
else {
$remain = substr($remain, $pos);
}
$newtext .= $chunk_all;
}
$newtext .= $remain;
$result
->setProcessedText($newtext);
return $result;
}
/**
* Extract plugin information from freelinking plugin settings.
*
* @param string $plugin_name
* The plugin ID.
* @param array $plugins
* The plugin array with settings.
*
* @return array
* The plugin information.
*/
public static function extractPluginSettings($plugin_name, array $plugins) {
return array_reduce($plugins, function (&$result, $info) use ($plugin_name) {
if ($info['plugin'] === $plugin_name) {
$result = $info;
}
return $result;
}, []);
}
/**
* Extract plugin names that are enabled from configuration.
*
* @param array $plugins
* The array of plugin information from the settings.
*
* @return array
* An indexed array of allowed plugin information.
*/
protected function extractAllowedPlugins(array $plugins) {
return array_reduce($plugins, function (&$result, $info) {
if ($info['enabled']) {
$result[$info['plugin']] = $info;
}
return $result;
}, []);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FilterBase:: |
public | property | The name of the provider that owns this filter. | |
FilterBase:: |
public | property | An associative array containing the configured settings of this filter. | |
FilterBase:: |
public | property | A Boolean indicating whether this filter is enabled. | |
FilterBase:: |
public | property | The weight of this filter compared to others in a filter collection. | |
FilterBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
1 |
FilterBase:: |
public | function |
Gets default configuration for this plugin. Overrides ConfigurableInterface:: |
|
FilterBase:: |
public | function |
Gets this plugin's configuration. Overrides ConfigurableInterface:: |
|
FilterBase:: |
public | function |
Returns the administrative description for this filter plugin. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Returns HTML allowed by this filter's configuration. Overrides FilterInterface:: |
4 |
FilterBase:: |
public | function |
Returns the administrative label for this filter plugin. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Returns the processing type of this filter plugin. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Prepares the text for processing. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Sets the configuration for this plugin instance. Overrides ConfigurableInterface:: |
1 |
FilterInterface:: |
constant | HTML tag and attribute restricting filters to prevent XSS attacks. | ||
FilterInterface:: |
constant | Non-HTML markup language filters that generate HTML. | ||
FilterInterface:: |
constant | Irreversible transformation filters. | ||
FilterInterface:: |
constant | Reversible transformation filters. | ||
Freelinking:: |
protected | property | Current user account. | |
Freelinking:: |
protected | property | Freelinking plugin manager. | |
Freelinking:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
Freelinking:: |
protected | function | Extract plugin names that are enabled from configuration. | |
Freelinking:: |
public static | function | Extract plugin information from freelinking plugin settings. | |
Freelinking:: |
public | function |
Performs the filter processing. Overrides FilterInterface:: |
|
Freelinking:: |
public | function |
Generates a filter's settings form. Overrides FilterBase:: |
|
Freelinking:: |
public | function |
Generates a filter's tip. Overrides FilterBase:: |
|
Freelinking:: |
public | function |
Initialize method. Overrides FilterBase:: |
|
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |