View source
<?php
namespace Drupal\markdown\Form;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Form\EnforcedResponseException;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginDependencyTrait;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\markdown\Markdown;
use Drupal\markdown\Plugin\Markdown\ExtensibleParserInterface;
use Drupal\markdown\Plugin\Markdown\ParserInterface;
use Drupal\markdown\Plugin\Markdown\RenderStrategyInterface;
use Drupal\markdown\Plugin\Markdown\SettingsInterface;
use Drupal\markdown\PluginManager\AllowedHtmlManager;
use Drupal\markdown\PluginManager\ParserManagerInterface;
use Drupal\markdown\Traits\FilterAwareTrait;
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\FilterHtml;
use Drupal\markdown\Util\ParserAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ParserConfigurationForm extends FormBase implements FilterAwareInterface, ParserAwareInterface {
use FilterAwareTrait;
use FormTrait;
use MoreInfoTrait;
use ParserAwareTrait;
use PluginDependencyTrait;
protected $cacheTagsInvalidator;
protected $elementInfo;
protected $parserManager;
protected $typedConfigManager;
public function __construct(ConfigFactoryInterface $configFactory, TypedConfigManagerInterface $typedConfigManager, CacheTagsInvalidatorInterface $cacheTagsInvalidator, ElementInfoManagerInterface $elementInfo, ParserManagerInterface $parserManager) {
$this->configFactory = $configFactory;
$this->cacheTagsInvalidator = $cacheTagsInvalidator;
$this->elementInfo = $elementInfo;
$this->parserManager = $parserManager;
$this->typedConfigManager = $typedConfigManager;
}
public static function create(ContainerInterface $container = NULL) {
if (!$container) {
$container = \Drupal::getContainer();
}
return new static($container
->get('config.factory'), $container
->get('config.typed'), $container
->get('cache_tags.invalidator'), $container
->get('plugin.manager.element_info'), $container
->get('plugin.manager.markdown.parser'));
}
public function getFormId() {
return 'markdown_parser_configuration';
}
public function buildForm(array $form, FormStateInterface $form_state, ParserInterface $parser = NULL) {
$this
->setParser($parser);
$form += [
'#parents' => [],
'#title' => $this
->t('Configure @parser', [
'@parser' => $parser
->getLabel(FALSE),
]),
];
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this
->t('Save configuration'),
'#button_type' => 'primary',
];
$form['#theme'] = 'system_config_form';
$form['#process'] = $this->elementInfo
->getInfoProperty('form', '#process', []);
$form['#process'][] = [
$this,
'processSubform',
];
return $form;
}
public function processSubform(array &$element, FormStateInterface $form_state, array &$complete_form) {
$form_state
->set('markdownSubformParents', $parents = isset($element['#parents']) ? $element['#parents'] : []);
$form_state
->set('markdownSubformArrayParents', $element['#array_parents']);
$element['#attached']['library'][] = 'markdown/admin';
if (!$this->parserManager
->installedDefinitions()) {
$error = $this
->t('No markdown parsers installed.');
}
elseif (!($parser = $this
->getParser())) {
$error = $this
->t('No markdown parser has been set. Unable to create the parser form.');
}
elseif ($parser
->getPluginId() === $this->parserManager
->getFallbackPluginId()) {
$error = $this
->t('Unknown parser: %parser_id.', [
'%parser_id' => $parser
->getOriginalPluginId(),
]);
}
if ($validationHandlers = $form_state
->getValidateHandlers()) {
if (!in_array([
$this,
'validateSubform',
], $validationHandlers)) {
array_unshift($validationHandlers, [
$this,
'validateSubform',
]);
$form_state
->setValidateHandlers($validationHandlers);
}
}
else {
$complete_form['#validate'][] = [
$this,
'validateSubform',
];
}
$form_state
->set('markdownAjaxId', $markdownAjaxId = Html::getUniqueId('markdown-parser-ajax'));
$element['ajax'] = static::createElement([
'#type' => 'container',
'#id' => $markdownAjaxId,
'#attributes' => [
'data' => [
'markdownElement' => 'wrapper',
],
],
]);
$element['ajax']['vertical_tabs'] = [
'#type' => 'vertical_tabs',
'#parents' => array_merge($parents, [
'vertical_tabs',
]),
];
$form_state
->set('markdownGroup', $group = implode('][', array_merge($parents, [
'vertical_tabs',
])));
$subform_state = SubformState::createForSubform($element, $complete_form, $form_state);
$element = $this
->buildParser($element, $subform_state);
if (isset($error)) {
if (($markdownOverview = Url::fromRoute('markdown.overview', [], [
'absolute' => TRUE,
])) && $markdownOverview
->access()) {
$error = $this
->t('@error Visit the <a href=":markdown.overview" target="_blank">Markdown Overview</a> page for more details.', [
'@error' => $error,
':markdown.overview' => $markdownOverview
->toString(),
]);
}
else {
$error = $this
->t('@error Ask your site administrator to install a <a href=":supported_parsers" target="_blank">supported markdown parser</a>.', [
'@error' => $error,
':supported_parsers' => Markdown::DOCUMENTATION_URL . '/parsers',
]);
}
if (!$this
->getFilter()) {
$this
->messenger()
->addError($error);
}
throw new EnforcedResponseException($this
->redirect('markdown.overview'), $error);
}
return $element;
}
protected function buildParser(array $element, SubformStateInterface $form_state) {
$parser = $this
->getParser();
$parserId = $parser
->getPluginId();
$markdownGroup = $form_state
->get('markdownGroup');
$markdownParents = $form_state
->get('markdownSubformParents');
$element['parser'] = [
'#weight' => -20,
'#type' => 'details',
'#title' => $this
->t('Parser'),
'#tree' => TRUE,
'#parents' => $markdownParents,
'#group' => $markdownGroup,
];
$parserElement =& $element['parser'];
$parserSubform = SubformState::createForSubform($parserElement, $element, $form_state);
$parserElement['id'] = static::createElement([
'#type' => 'hidden',
'#default_value' => $parserId,
'#attributes' => [
'data' => [
'markdownSummary' => 'parser',
'markdownSummaryValue' => $parser
->getLabel(),
'markdownId' => $parserId,
],
],
]);
$parserElement = $this
->buildRenderStrategy($parser, $parserElement, $parserSubform);
$parserElement = $this
->buildParserSettings($parser, $parserElement, $parserSubform);
$parserElement = $this
->buildParserExtensions($parser, $parserElement, $parserSubform);
return $element;
}
protected function buildParserSettings(ParserInterface $parser, array $element, SubformStateInterface $form_state) {
$element['settings'] = [
'#type' => 'details',
'#title' => $this
->t('Settings'),
'#open' => TRUE,
];
if ($parser instanceof PluginFormInterface) {
$parserSettingsSubform = SubformState::createForSubform($element['settings'], $element, $form_state);
$element['settings'] = $parser
->buildConfigurationForm($element['settings'], $parserSettingsSubform);
}
if (!Element::getVisibleChildren($element['settings'])) {
$element['settings']['#description'] = $this
->t('This parser has no settings to configure.');
}
return $element;
}
protected function buildParserExtensions(ParserInterface $parser, array $element, SubformStateInterface $form_state) {
if (!$parser instanceof ExtensibleParserInterface) {
return $element;
}
$markdownGroup = $form_state
->get('markdownGroup');
$extensions = $parser
->extensions();
if (!$extensions) {
return $element;
}
$parents = $element['#parents'];
$element['extensions'] = [
'#type' => 'container',
];
foreach ($extensions as $extensionId => $extension) {
$label = $extension
->getLabel(FALSE);
$url = $extension
->getUrl();
$element['extensions'][$extensionId] = [
'#type' => 'details',
'#title' => $label,
'#group' => $markdownGroup,
'#parents' => array_merge($parents, [
'extensions',
$extensionId,
]),
];
$extensionElement =& $element['extensions'][$extensionId];
$extensionSubform = SubformState::createForSubform($extensionElement, $element, $form_state);
$bundled = in_array($extensionId, $parser
->getBundledExtensionIds(), TRUE);
$installed = $extension
->isInstalled();
$enabled = $extensionSubform
->getValue('enabled', $extension
->isEnabled());
if ($experimental = $extension
->getExperimental()) {
$extensionElement['experimental'] = static::createInlineMessage([
'info' => [
$experimental === TRUE ? $this
->t('This is an experimental extension. Not all features or functionality may work.') : $experimental,
],
]);
}
$extensionElement['libraries'] = $extension
->buildStatus(!$installed);
$extensionElement['enabled'] = static::createElement([
'#type' => 'checkbox',
'#title' => $this
->t('Enable'),
'#description' => $this
->moreInfo($extension
->getDescription(), $url),
'#attributes' => [
'data' => [
'markdownElement' => 'extension',
'markdownSummary' => 'extension',
'markdownId' => $extensionId,
'markdownLabel' => $label,
'markdownInstalled' => $installed,
'markdownBundle' => $bundled ? $parser
->getLabel(FALSE) : FALSE,
'markdownRequires' => $extension
->requires(),
'markdownRequiredBy' => $extension
->requiredBy(),
],
],
'#default_value' => $bundled || $enabled,
'#disabled' => $bundled || !$installed,
]);
if ($installed && $extension instanceof PluginFormInterface) {
$extensionElement['settings'] = [
'#type' => 'details',
'#title' => $this
->t('Settings'),
'#open' => TRUE,
];
$extensionSettingsElement =& $extensionElement['settings'];
$extensionSettingsSubform = SubformState::createForSubform($extensionSettingsElement, $extensionElement, $extensionSubform);
$extensionSubform
->addElementState($extensionSettingsElement, 'visible', 'enabled', [
'checked' => TRUE,
]);
$extensionSettingsElement = $extension
->buildConfigurationForm($extensionSettingsElement, $extensionSettingsSubform);
$extensionSettingsElement['#access'] = !!Element::getVisibleChildren($extensionSettingsElement);
}
}
$element['extensions']['#access'] = !!Element::getVisibleChildren($element['extensions']);
return $element;
}
protected function buildRenderStrategy(ParserInterface $parser, array $element, SubformStateInterface $form_state, $siteWide = FALSE) {
$element['render_strategy'] = [
'#weight' => -10,
'#type' => 'details',
'#title' => $this
->t('Render Strategy'),
'#group' => $form_state
->get('markdownGroup'),
];
$renderStrategySubform =& $element['render_strategy'];
$renderStrategySubformState = SubformState::createForSubform($renderStrategySubform, $element, $form_state);
$renderStrategySubform['type'] = [
'#weight' => -10,
'#type' => 'select',
'#description' => $this
->t('Determines the strategy to use when dealing with user provided HTML markup.'),
'#default_value' => $renderStrategySubformState
->getValue('type', $parser
->getRenderStrategy()),
'#attributes' => [
'data-markdown-element' => 'render_strategy',
'data-markdown-summary' => 'render_strategy',
],
'#options' => [
RenderStrategyInterface::FILTER_OUTPUT => $this
->t('Filter Output'),
RenderStrategyInterface::ESCAPE_INPUT => $this
->t('Escape Input'),
RenderStrategyInterface::STRIP_INPUT => $this
->t('Strip Input'),
RenderStrategyInterface::NONE => $this
->t('None'),
],
];
$renderStrategySubform['type']['#description'] = $this
->moreInfo($renderStrategySubform['type']['#description'], RenderStrategyInterface::DOCUMENTATION_URL . '#xss');
$renderStrategySubform['plugins'] = [
'#weight' => -10,
'#type' => 'item',
'#input' => FALSE,
'#title' => $this
->t('Allowed HTML'),
'#description_display' => 'before',
'#description' => $this
->t('The following are registered <code>@MarkdownAllowedHtml</code> plugins that allow HTML tags and attributes based on configuration. These are typically provided by the parser itself, any of its enabled extensions that convert additional HTML tag and potentially various Drupal filters, modules or themes (if supported).'),
];
$renderStrategySubform['plugins']['#description'] = $this
->moreInfo($renderStrategySubform['plugins']['#description'], RenderStrategyInterface::DOCUMENTATION_URL);
$renderStrategySubformState
->addElementState($renderStrategySubform['plugins'], 'visible', 'type', [
'value' => RenderStrategyInterface::FILTER_OUTPUT,
]);
$allowedHtmlManager = AllowedHtmlManager::create();
foreach ($allowedHtmlManager
->appliesTo($parser) as $plugin_id => $allowedHtml) {
$pluginDefinition = $allowedHtml
->getPluginDefinition();
$label = isset($pluginDefinition['label']) ? $pluginDefinition['label'] : $plugin_id;
$description = isset($pluginDefinition['description']) ? $pluginDefinition['description'] : '';
$type = isset($pluginDefinition['type']) ? $pluginDefinition['type'] : 'other';
if (!isset($renderStrategySubform['plugins'][$type])) {
$renderStrategySubform['plugins'][$type] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => $this
->t(ucfirst($type) . 's'),
'#parents' => $renderStrategySubformState
->createParents([
'plugins',
]),
];
if ($type === 'module') {
$renderStrategySubform['plugins'][$type]['#weight'] = -10;
}
if ($type === 'filter') {
$renderStrategySubform['plugins'][$type]['#weight'] = -9;
$renderStrategySubform['plugins'][$type]['#description'] = $this
->t('NOTE: these will only be applied when the filter it represents is actually enabled.');
$renderStrategySubform['plugins'][$type]['#description_display'] = 'before';
}
if ($type === 'parser') {
$renderStrategySubform['plugins'][$type]['#weight'] = -8;
}
if ($type === 'extension') {
$renderStrategySubform['plugins'][$type]['#weight'] = -7;
$renderStrategySubform['plugins'][$type]['#title'] = $this
->t('Extensions');
$renderStrategySubform['plugins'][$type]['#description'] = $this
->t('NOTE: these will only be applied when the parser extension it represents is actually enabled.');
$renderStrategySubform['plugins'][$type]['#description_display'] = 'before';
}
if ($type === 'theme') {
$renderStrategySubform['plugins'][$type]['#weight'] = -6;
$renderStrategySubform['plugins'][$type]['#description'] = $this
->t('NOTE: these will only be applied when the theme that provides the plugin is the active theme or is a descendant of the active theme.');
$renderStrategySubform['plugins'][$type]['#description_display'] = 'before';
}
}
$allowedHtmlTags = $allowedHtml
->allowedHtmlTags($parser);
$allowedHtmlPlugins = $parser
->getAllowedHtmlPlugins();
$defaultValue = NULL;
if ($allowedHtmlTags) {
if (!isset($defaultValue) && isset($allowedHtmlPlugins[$plugin_id])) {
$defaultValue = $allowedHtmlPlugins[$plugin_id];
}
if (!isset($defaultValue)) {
if ($type === 'filter' && ($filter = $this
->getFilter()) && $filter instanceof FilterFormatAwareInterface && ($format = $filter
->getFilterFormat())) {
$definition = $allowedHtml
->getPluginDefinition();
$filterId = isset($definition['requiresFilter']) ? $definition['requiresFilter'] : $plugin_id;
$defaultValue = $format
->filters()
->has($filterId) ? !!$format
->filters($filterId)->status : FALSE;
}
elseif ($type === 'extension' && $parser instanceof ExtensibleParserInterface && $parser
->extensions()
->has($plugin_id)) {
$defaultValue = $parser
->extension($plugin_id)
->isEnabled();
}
else {
$defaultValue = TRUE;
}
}
}
$renderStrategySubform['plugins'][$type][$plugin_id] = [
'#type' => 'checkbox',
'#title' => $label,
'#disabled' => !$allowedHtmlTags,
'#description' => Markup::create(sprintf('%s<pre><code>%s</code></pre>', $description, $allowedHtmlTags ? htmlentities(FilterHtml::tagsToString($allowedHtmlTags)) : $this
->t('No HTML tags provided.'))),
'#default_value' => $renderStrategySubformState
->getValue([
'plugins',
$plugin_id,
], $defaultValue),
'#attributes' => [
'data-markdown-default-value' => $renderStrategySubformState
->getValue([
'plugins',
$plugin_id,
], $defaultValue) ? 'true' : 'false',
],
];
if ($plugin_id === 'markdown') {
$renderStrategySubform['plugins'][$type][$plugin_id]['#weight'] = -10;
}
if (!$allowedHtmlTags) {
continue;
}
if ($type === 'extension') {
if ($siteWide) {
$extensionDisabled = $defaultValue !== TRUE;
$renderStrategySubform['plugins'][$type][$plugin_id]['#disabled'] = $extensionDisabled;
if ($extensionDisabled) {
$renderStrategySubform['plugins'][$type][$plugin_id]['#title'] = new FormattableMarkup('@title @disabled', [
'@title' => $renderStrategySubform['plugins'][$type][$plugin_id]['#title'],
'@disabled' => $this
->t('(extension disabled)'),
]);
}
}
else {
$parents = array_merge(array_slice($renderStrategySubformState
->createParents(), 0, -1), [
'extensions',
$plugin_id,
'enabled',
]);
$selector = ':input[name="' . array_shift($parents) . '[' . implode('][', $parents) . ']"]';
$renderStrategySubform['plugins'][$type][$plugin_id]['#title'] = new FormattableMarkup('@title @disabled', [
'@title' => $renderStrategySubform['plugins'][$type][$plugin_id]['#title'],
'@disabled' => $renderStrategySubformState
->conditionalElement([
'#value' => $this
->t('(extension disabled)'),
], 'visible', $selector, [
'checked' => FALSE,
]),
]);
$renderStrategySubform['plugins'][$type][$plugin_id]['#states'] = [
'!checked' => [
$selector => [
'checked' => FALSE,
],
],
'disabled' => [
$selector => [
'checked' => FALSE,
],
],
];
}
}
elseif ($type === 'filter') {
$selector = ':input[name="filters[' . $plugin_id . '][status]"]';
$renderStrategySubform['plugins'][$type][$plugin_id]['#title'] = new FormattableMarkup('@title @disabled', [
'@title' => $renderStrategySubform['plugins'][$type][$plugin_id]['#title'],
'@disabled' => $renderStrategySubformState
->conditionalElement([
'#value' => $this
->t('(filter disabled)'),
], 'visible', $selector, [
'checked' => FALSE,
]),
]);
$renderStrategySubform['plugins'][$type][$plugin_id]['#states'] = [
'!checked' => [
$selector => [
'checked' => FALSE,
],
],
'disabled' => [
$selector => [
'checked' => FALSE,
],
],
];
}
}
$renderStrategySubform['plugins']['#access'] = !!Element::getVisibleChildren($renderStrategySubform['plugins']);
$renderStrategySubform['custom_allowed_html'] = [
'#weight' => -10,
'#type' => 'textarea',
'#title' => $this
->t('Custom Allowed HTML'),
'#description' => $this
->t('A list of additional custom allowed HTML tags that can be used. This follows the same rules as above; use cautiously and sparingly.'),
'#default_value' => $renderStrategySubformState
->getValue('custom_allowed_html', $parser
->getCustomAllowedHtml()),
'#attributes' => [
'data-markdown-element' => 'custom_allowed_html',
],
];
$renderStrategySubform['custom_allowed_html']['#description'] = $this
->moreInfo($renderStrategySubform['custom_allowed_html']['#description'], RenderStrategyInterface::DOCUMENTATION_URL);
FormTrait::resetToDefault($renderStrategySubform['custom_allowed_html'], 'custom_allowed_html', '', $renderStrategySubformState);
$renderStrategySubformState
->addElementState($renderStrategySubform['custom_allowed_html'], 'visible', 'type', [
'value' => RenderStrategyInterface::FILTER_OUTPUT,
]);
return $element;
}
public function getConfigFromValues($name, array $values) {
$config = $this->configFactory
->getEditable($name);
if (isset($values['parser']) && is_string($values['parser'])) {
$values['id'] = $values['parser'];
unset($values['parser']);
}
elseif (isset($values['parser']) && is_array($values['parser'])) {
$values += $values['parser'];
}
$parserId = isset($values['id']) ? (string) $values['id'] : '';
$parser = $this->parserManager
->createInstance($parserId, $values);
$configuration = $parser
->getSortedConfiguration();
$config
->setData($configuration);
return $config;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state
->cleanValues()
->getValues();
$parserId = isset($values['id']) ? (string) $values['id'] : $this
->getParser()
->getOriginalPluginId();
$config = $this
->getConfigFromValues("markdown.parser.{$parserId}", $values);
$config
->save();
$this->cacheTagsInvalidator
->invalidateTags([
"markdown.parser.{$parserId}",
]);
drupal_set_message($this
->t('The configuration options have been saved.'));
}
public function submitSubform(array &$form, FormStateInterface $form_state) {
if (!($arrayParents = $form_state
->get('markdownSubformArrayParents')) || !$form_state
->isSubmitted()) {
return;
}
$subform =& NestedArray::getValue($form, $arrayParents);
$subformState = SubformState::createForSubform($subform, $form, $form_state);
$parserId = $subformState
->getValue('id');
if ($parserId && $this->parserManager
->hasDefinition($parserId)) {
$parser = $this->parserManager
->createInstance($parserId, $subformState
->getValues());
if ($parser instanceof SettingsInterface && $parser instanceof PluginFormInterface && !empty($subform['parser']['settings'])) {
$parser
->submitConfigurationForm($subform['parser']['settings'], SubformState::createForSubform($subform['parser']['settings'], $subform, $subformState));
}
if ($parser instanceof ExtensibleParserInterface && !empty($subform['parser']['extensions'])) {
foreach ($parser
->extensions() as $extensionId => $extension) {
if ($extension instanceof SettingsInterface && $extension instanceof PluginFormInterface && isset($subform['parser']['extensions'][$extensionId]['settings'])) {
$parser
->submitConfigurationForm($subform['parser']['extensions'][$extensionId]['settings'], SubformState::createForSubform($subform['parser']['extensions'][$extensionId]['settings'], $subform, $subformState));
}
}
}
}
}
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
$values = $form_state
->cleanValues()
->getValues();
$parserId = isset($values['id']) ? (string) $values['id'] : $this
->getParser()
->getOriginalPluginId();
$config = $this
->getConfigFromValues("markdown.parser.{$parserId}", $values);
$typed_config = $this->typedConfigManager
->createFromNameAndData("markdown.parser.{$parserId}", $config
->get());
$violations = $typed_config
->validate();
foreach ($violations as $violation) {
$form_state
->setErrorByName(static::mapViolationPropertyPathsToFormNames($violation
->getPropertyPath()), $violation
->getMessage());
}
}
protected static function mapViolationPropertyPathsToFormNames($property_path) {
return str_replace('.', '][', $property_path);
}
public function validateSubform(array &$form, FormStateInterface $form_state) {
if (!($arrayParents = $form_state
->get('markdownSubformArrayParents')) || !$form_state
->isSubmitted()) {
return;
}
if ($submitHandlers = $form_state
->getSubmitHandlers()) {
if (!in_array([
$this,
'submitSubform',
], $submitHandlers)) {
array_unshift($submitHandlers, [
$this,
'submitSubform',
]);
$form_state
->setSubmitHandlers($submitHandlers);
}
}
else {
$complete_form =& $form_state
->getCompleteForm();
$complete_form['#submit'][] = [
$this,
'submitSubform',
];
}
$subform =& NestedArray::getValue($form, $arrayParents);
$subformState = SubformState::createForSubform($subform, $form, $form_state);
$parserId = $subformState
->getValue('id');
if ($parserId && $this->parserManager
->hasDefinition($parserId)) {
$parser = $this->parserManager
->createInstance($parserId, $subformState
->getValues());
if ($parser instanceof SettingsInterface && $parser instanceof PluginFormInterface && !empty($subform['parser']['settings'])) {
$parser
->validateConfigurationForm($subform['parser']['settings'], SubformState::createForSubform($subform['parser']['settings'], $subform, $subformState));
}
if ($parser instanceof ExtensibleParserInterface && !empty($subform['parser']['extensions'])) {
foreach ($parser
->extensions() as $extensionId => $extension) {
if ($extension instanceof SettingsInterface && $extension instanceof PluginFormInterface && isset($subform['parser']['extensions'][$extensionId]['settings'])) {
$extension
->validateConfigurationForm($subform['parser']['extensions'][$extensionId]['settings'], SubformState::createForSubform($subform['parser']['extensions'][$extensionId]['settings'], $subform, $subformState));
}
}
}
}
}
}