View source
<?php
namespace Drupal\markdown\Plugin\Filter;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\filter\Entity\FilterFormat;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Drupal\markdown\Form\ParserConfigurationForm;
use Drupal\markdown\Form\SubformState;
use Drupal\markdown\Plugin\Markdown\ParserInterface;
use Drupal\markdown\PluginManager\ParserManagerInterface;
use Drupal\markdown\Traits\FilterFormatAwareTrait;
use Drupal\markdown\Traits\FormTrait;
use Drupal\markdown\Traits\MoreInfoTrait;
use Drupal\markdown\Traits\ParserAwareTrait;
use Drupal\markdown\Util\FilterAwareInterface;
use Drupal\markdown\Util\FilterFormatAwareInterface;
use Drupal\markdown\Util\ParserAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FilterMarkdown extends FilterBase implements ContainerFactoryPluginInterface, FilterMarkdownInterface, ParserAwareInterface {
use FilterFormatAwareTrait;
use FormTrait;
use MoreInfoTrait;
use ParserAwareTrait {
setParser as setParserTrait;
}
protected $elementInfo;
protected $parserManager;
public function __construct(array $configuration, $plugin_id, $plugin_definition, ElementInfoManagerInterface $elementInfo, ParserManagerInterface $parserManager) {
$this->elementInfo = $elementInfo;
$this->parserManager = $parserManager;
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('plugin.manager.element_info'), $container
->get('plugin.manager.markdown.parser'));
}
public function calculateDependencies() {
return $this
->getParser()
->calculateDependencies();
}
public function defaultConfiguration() {
$configuration = parent::defaultConfiguration();
$filterFormat = $this
->getFilterFormat();
$configuration['filterFormat'] = $filterFormat ? $filterFormat
->id() : NULL;
return $configuration;
}
public function getConfiguration() {
if (!$this->status) {
$configuration['id'] = $this
->getPluginId();
$configuration += $this
->defaultConfiguration();
return $configuration;
}
$configuration = parent::getConfiguration();
$filterFormat = $this
->getFilterFormat();
$configuration['filterFormat'] = $filterFormat ? $filterFormat
->id() : NULL;
return $configuration;
}
public function getParser() {
return $this->parser;
}
public function isEnabled() {
return !!$this->status;
}
public function process($text, $langcode = NULL) {
if (!empty($text)) {
$language = $langcode ? \Drupal::languageManager()
->getLanguage($langcode) : NULL;
$text = $this
->getParser()
->parse($text, $language);
}
return new FilterProcessResult($text);
}
public function setConfiguration(array $configuration) {
if (isset($configuration['filterFormat'])) {
if ($configuration['filterFormat'] instanceof FilterFormat) {
$this
->setFilterFormat($configuration['filterFormat']);
$configuration['filterFormat'] = $configuration['filterFormat']
->id();
}
elseif (is_string($configuration['filterFormat']) && (!$this->filterFormat || $this->filterFormat
->id() !== $configuration['filterFormat'])) {
if ($currentFilterFormat = drupal_static('markdown_filter_format_load')) {
$filterFormat = $currentFilterFormat;
}
else {
$filterFormat = FilterFormat::load($configuration['filterFormat']);
}
$this
->setFilterFormat($filterFormat);
}
}
$configuration += [
'settings' => [],
];
$parserConfiguration = $configuration['settings'];
if (isset($parserConfiguration['parser'])) {
if (\is_string($parserConfiguration['parser'])) {
$parserConfiguration['id'] = $parserConfiguration['parser'];
}
elseif (is_array($parserConfiguration['parser'])) {
$parserConfiguration += $parserConfiguration['parser'];
}
unset($parserConfiguration['parser']);
}
$parserId = !empty($parserConfiguration['id']) ? $parserConfiguration['id'] : $this->parserManager
->getDefaultParser()
->getPluginId();
$override = !empty($parserConfiguration['override']);
if (!$override) {
$render_strategy = isset($parserConfiguration['render_strategy']) ? $parserConfiguration['render_strategy'] : [];
$parserConfiguration = \Drupal::config("markdown.parser.{$parserId}")
->get() ?: [];
$parserConfiguration['render_strategy'] = $render_strategy;
}
$parser = $this->parserManager
->createInstance($parserId, array_merge([
'enabled' => TRUE,
], $parserConfiguration));
$this
->setParser($parser);
$parserConfiguration = array_merge([
'override' => $override,
], $parser
->getConfiguration());
if (!($parserConfiguration['override'] = $override)) {
unset($parserConfiguration['settings']);
unset($parserConfiguration['extensions']);
}
unset($parserConfiguration['weight']);
unset($parserConfiguration['dependencies']);
$configuration['settings'] = $parserConfiguration;
return parent::setConfiguration($configuration);
}
public function setParser(ParserInterface $parser = NULL) {
if ($parser instanceof FilterAwareInterface) {
$parser
->setFilter($this);
}
if ($parser instanceof FilterFormatAwareInterface && ($filterFormat = $this
->getFilterFormat())) {
$parser
->setFilterFormat($filterFormat);
$parser
->addCacheableDependency($filterFormat);
}
return $this
->setParserTrait($parser);
}
public function settingsForm(array $form, FormStateInterface $form_state) {
$form['#process'] = $this->elementInfo
->getInfoProperty('details', '#process', []);
$form['#process'][] = [
$this,
'processSubform',
];
if (!$this->filterFormat && ($formObject = $form_state
->getFormObject()) && $formObject instanceof EntityFormInterface && ($entity = $formObject
->getEntity()) && $entity instanceof FilterFormat) {
$this
->setFilterFormat($entity);
}
return $form;
}
public function processSubform(array $element, FormStateInterface $form_state, array &$complete_form) {
$subform_state = SubformState::createForSubform($element, $complete_form, $form_state);
if (($trigger = $form_state
->getTriggeringElement()) && isset($trigger['#ajax']['callback']) && $trigger['#ajax']['callback'] === '\\Drupal\\markdown\\Plugin\\Filter\\FilterMarkdown::ajaxChangeParser' && ($parserId = $subform_state
->getValue('id'))) {
$parents = $subform_state
->createParents();
$input =& NestedArray::getValue($form_state
->getUserInput(), $parents);
$values =& NestedArray::getValue($form_state
->getValues(), $parents);
if ($trigger['#type'] === 'select') {
$input = [
'id' => $parserId,
'override' => (int) (!empty($input['override'])),
];
$values = [
'id' => $parserId,
'override' => (int) (!empty($values['override'])),
];
}
$configuration = $this
->getConfiguration();
$configuration['settings'] = $values;
$this
->setConfiguration($configuration);
}
$parser = $this
->getParser();
$parserId = $parser
->getPluginId();
try {
$element = ParserConfigurationForm::create()
->setFilter($this)
->setParser($parser)
->processSubform($element, $form_state, $complete_form);
} catch (\Exception $exception) {
} catch (\Throwable $exception) {
}
if (isset($exception)) {
$element['error'] = static::createInlineMessage([
'error' => [
Markup::create($exception
->getMessage()),
],
]);
}
$markdownAjaxId = $form_state
->get('markdownAjaxId');
$labels = [];
foreach ($this->parserManager
->enabled() as $name => $enabledParser) {
$labels[$name] = $enabledParser
->getLabel(TRUE);
}
if (!$this->parserManager
->hasDefinition($parserId)) {
$labels[$parserId] = new FormattableMarkup('@label (missing)', [
'@label' => $parserId,
]);
}
$parserElement =& $element['parser'];
$parserElement['status'] = $parser
->buildStatus();
$parserElement['status']['#weight'] = -10;
$parserElement['id'] = static::createElement([
'#weight' => -9,
'#type' => 'select',
'#options' => $labels,
'#default_value' => $parserId,
'#description' => $parser
->getDescription(),
'#attributes' => [
'data' => [
'markdownSummary' => 'parser',
'markdownId' => $parserId,
'markdownInstalled' => $parser
->isInstalled(),
],
],
'#ajax' => [
'callback' => '\\Drupal\\markdown\\Plugin\\Filter\\FilterMarkdown::ajaxChangeParser',
'event' => 'change',
'wrapper' => $markdownAjaxId,
],
]);
$override = !empty($this
->getConfiguration()['settings']['override']);
$parserElement['override'] = static::createElement([
'#weight' => -8,
'#type' => 'radios',
'#options' => [
0 => $this
->t('Inherit site-wide settings'),
1 => $this
->t('Override site-wide settings'),
],
'#default_value' => (int) $override,
'#ajax' => [
'callback' => '\\Drupal\\markdown\\Plugin\\Filter\\FilterMarkdown::ajaxChangeParser',
'event' => 'change',
'wrapper' => $markdownAjaxId,
],
]);
if (($markdownParserEditUrl = Url::fromRoute('markdown.parser.edit', [
'parser' => $parser,
])) && $markdownParserEditUrl
->access()) {
$parserElement['override']['#description'] = $this
->t('Site-wide markdown settings can be adjusted by visiting the site-wide <a href=":markdown.parser.edit" target="_blank">@label</a> parser.', [
'@label' => $parser
->getLabel(FALSE),
':markdown.parser.edit' => $markdownParserEditUrl
->toString(),
]);
}
else {
$parserElement['override']['#description'] = $this
->t('Site-wide markdown settings can only be adjusted by administrators.');
}
if (!$override) {
$parserElement['settings']['#access'] = FALSE;
$parserElement['extensions']['#access'] = FALSE;
}
if ($url = $parser
->getUrl()) {
$parserElement['id']['#description'] = $this
->moreInfo($parserElement['id']['#description'], $url);
}
return $element;
}
public static function ajaxChangeParser(array $form, FormStateInterface $form_state) {
if (!($arrayParents = $form_state
->get('markdownSubformArrayParents'))) {
$arrayParents = array_slice($form_state
->getTriggeringElement()['#array_parents'], 0, -2);
}
$subform =& NestedArray::getValue($form, $arrayParents);
return $subform['ajax'];
}
public static function processTextFormat(array &$element, FormStateInterface $form_state, array &$complete_form) {
if (!isset($element['#format']) || !($formats = filter_formats()) || !isset($formats[$element['#format']])) {
return $element;
}
$format = $formats[$element['#format']];
try {
if (($markdown = $format
->filters('markdown')) && $markdown->status) {
$element['format']['help']['about'] = [
'#type' => 'link',
'#title' => Markup::create('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path></svg>'),
'#url' => Url::fromRoute('filter.tips_all')
->setOptions([
'attributes' => [
'class' => [
'markdown',
],
'target' => '_blank',
'title' => t('Styling with Markdown is supported'),
],
]),
];
}
} catch (PluginNotFoundException $exception) {
}
return $element;
}
public function tips($long = FALSE) {
if (!$long) {
return NULL;
}
return $this
->moreInfo($this
->t('Parses markdown and converts it to HTML.'), 'https://www.drupal.org/docs/8/modules/markdown');
}
}