View source
<?php
namespace Drupal\freelinking\Plugin\Filter;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Drupal\freelinking\FreelinkingManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class Freelinking extends FilterBase implements ContainerFactoryPluginInterface {
protected $freelinkingManager;
protected $currentUser;
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;
}
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'));
}
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),
];
if ($plugin
->isHidden()) {
$form['plugins'][$plugin_name]['enabled']['#disabled'] = TRUE;
$form['plugins'][$plugin_name]['enabled']['#default_value'] = TRUE;
}
}
return $form;
}
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;
$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>';
return $this
->t($content);
}
public function process($text, $langcode) {
$defaultplugin = $this->settings['default'];
$user_langcode = $langcode != $this->currentUser
->getPreferredLangcode() ? $this->currentUser
->getPreferredLangcode() : $langcode;
$result = new FilterProcessResult($text);
$start = 0;
$remain = $text;
$newtext = '';
while (TRUE) {
$offset = 0;
if (empty($remain)) {
break;
}
if ('[' === $remain[0] && '[' === $remain[1]) {
$infreelinkp = TRUE;
$delim = ']]';
}
else {
$infreelinkp = FALSE;
$delim = '[[';
}
$pos = strpos($remain, $delim);
if (FALSE === $pos) {
break;
}
$chunk_all = substr($remain, $start, $pos);
if ($infreelinkp) {
$chunk_stripped = substr($chunk_all, 2);
$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);
}
$current_plugin = $this->freelinkingManager
->getPluginFromIndicator($indicator, $this
->extractAllowedPlugins($this->settings['plugins']), $this->settings);
if (!$this->settings['global_options']['ignore_upi'] || $current_plugin) {
if (!$current_plugin) {
$link = $result
->createPlaceholder('freelinking.manager:createErrorElement', [
$indicator,
]);
}
else {
$plugin_settings = self::extractPluginSettings($current_plugin
->getPluginId(), $this->settings['plugins']);
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;
}
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;
}, []);
}
protected function extractAllowedPlugins(array $plugins) {
return array_reduce($plugins, function (&$result, $info) {
if ($info['enabled']) {
$result[$info['plugin']] = $info;
}
return $result;
}, []);
}
}