View source
<?php
namespace Drupal\xbbcode\Form;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\xbbcode\Plugin\TagPluginInterface;
use Drupal\xbbcode\TagPluginCollection;
use Drupal\xbbcode\TagPluginManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use function count;
class TagSetForm extends EntityForm {
use LabeledFormTrait;
protected $tagStorage;
protected $formatStorage;
protected $pluginManager;
public function __construct(EntityStorageInterface $tagStorage, EntityStorageInterface $formatStorage, TagPluginManager $pluginManager) {
$this->tagStorage = $tagStorage;
$this->formatStorage = $formatStorage;
$this->pluginManager = $pluginManager;
}
public static function create(ContainerInterface $container) : self {
$typeManager = $container
->get('entity_type.manager');
return new static($typeManager
->getStorage('xbbcode_tag_set'), $typeManager
->getStorage('filter_format'), $container
->get('plugin.manager.xbbcode'));
}
public function form(array $form, FormStateInterface $form_state) : array {
$form = parent::form($form, $form_state);
$form = $this
->addLabelFields($form);
$form['_tags'] = [
'#type' => 'tableselect',
'#title' => $this
->t('Tags'),
'#header' => [
'name' => $this
->t('Tag name'),
'label' => $this
->t('Plugin'),
],
'#options' => [],
'#empty' => $this
->t('No custom tags or plugins are available.'),
];
$tagSet = $this->entity;
$plugins = new TagPluginCollection($this->pluginManager, $tagSet
->getTags());
$available = $this->pluginManager
->getDefinedIds();
$settings = [];
foreach ($plugins as $name => $plugin) {
$settings["enabled:{$name}"] = $this
->buildRow($plugin, TRUE);
$form['_tags']['#default_value']["enabled:{$name}"] = TRUE;
unset($available[$plugin
->getPluginId()]);
}
foreach ($available as $plugin_id) {
try {
$plugin = $this->pluginManager
->createInstance($plugin_id);
$settings["available:{$plugin_id}"] = $this
->buildRow($plugin, FALSE);
} catch (PluginException $exception) {
watchdog_exception('xbbcode', $exception);
}
}
foreach ($settings as $key => $row) {
foreach ((array) $row as $name => $cell) {
$form['_tags']['#options'][$key][$name]['data'] = $name;
}
}
$form['_settings'] = $settings;
$form['_settings']['#tree'] = TRUE;
$form['#pre_render'][] = static function (array $form) : array {
$table =& $form['_tags'];
$settings = $form['_settings'];
foreach (Element::children($settings) as $key) {
foreach ((array) $settings[$key] as $name => $cell) {
$table['#options'][$key][$name]['data'] = $cell;
}
}
unset($form['_settings']);
return $form;
};
$formats = $this->formatStorage
->getQuery()
->condition('filters.xbbcode.status', TRUE)
->execute();
if ($formats) {
$form['formats'] = [
'#type' => 'checkboxes',
'#title' => $this
->t('Text formats'),
'#description' => $this
->t('Text formats that use this tag set.'),
'#options' => [],
];
foreach ($this->formatStorage
->loadMultiple($formats) as $id => $format) {
$form['formats']['#options'][$id] = $format
->label();
}
if (!$this->entity
->isNew()) {
$form['formats']['#default_value'] = $this->formatStorage
->getQuery()
->condition('filters.xbbcode.settings.tags', $this->entity
->id())
->execute();
}
}
return parent::form($form, $form_state);
}
public function exists($id) : bool {
return (bool) $this->tagStorage
->getQuery()
->condition('id', $id)
->execute();
}
protected function buildRow(TagPluginInterface $plugin, $enabled) : array {
$row = [
'#enabled' => $enabled,
'#default_name' => $plugin
->getDefaultName(),
];
$path = $enabled ? 'enabled:' . $plugin
->getName() : 'available:' . $plugin
->getPluginId();
$row['name'] = [
'#type' => 'textfield',
'#title' => $this
->t('Tag name'),
'#title_display' => 'invisible',
'#required' => TRUE,
'#size' => 8,
'#field_prefix' => '[',
'#field_suffix' => ']',
'#default_value' => $plugin
->getName(),
'#pattern' => '[a-z0-9_-]+',
'#attributes' => [
'default' => $plugin
->getDefaultName(),
],
'#states' => [
'enabled' => [
':input[name="_tags[' . $path . ']"]' => [
'checked' => TRUE,
],
],
],
];
$row['label'] = [
'#type' => 'inline_template',
'#template' => '<strong>{{ plugin.label }}</strong><br />{{ plugin.description}}',
'#context' => [
'plugin' => $plugin,
],
];
$row['id'] = [
'#type' => 'value',
'#value' => $plugin
->getPluginId(),
];
return $row;
}
public function validateForm(array &$form, FormStateInterface $form_state) : void {
parent::validateForm($form, $form_state);
$exists = [];
$enabled = array_filter($form_state
->getValue('_tags'));
$settings =& $form_state
->getValue('_settings');
foreach (array_keys($enabled) as $key) {
$name = $settings[$key]['name'];
$exists[$name][$key] = $form['_settings'][$key]['name'];
}
foreach ($exists as $name => $rows) {
if (count($rows) > 1) {
foreach ((array) $rows as $row) {
$form_state
->setError($row, $this
->t('The name [@tag] is used by multiple tags.', [
'@tag' => $name,
]));
}
}
}
}
protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) : void {
parent::copyFormValuesToEntity($entity, $form, $form_state);
$enabled = array_keys(array_filter($form_state
->getValue('_tags')));
$settings =& $form_state
->getValue('_settings');
$tags = [];
foreach ($enabled as $key) {
$row = $settings[$key];
$tags[$row['name']] = $this
->buildPluginConfiguration($row);
}
$entity
->set('tags', $tags);
}
protected function buildPluginConfiguration(array $values) : array {
return [
'id' => $values['id'],
];
}
public function save(array $form, FormStateInterface $form_state) {
$result = parent::save($form, $form_state);
$old = $form['formats']['#default_value'];
$new = array_filter($form_state
->getValue('formats'));
$update = [
'' => array_diff_assoc($old, $new),
$this->entity
->id() => array_diff_assoc($new, $old),
];
foreach ($update as $tag_set => $formats) {
foreach ($this->formatStorage
->loadMultiple($formats) as $id => $format) {
$filter = $format
->filters('xbbcode');
$config = $filter
->getConfiguration();
$config['settings']['tags'] = $tag_set;
$filter
->setConfiguration($config);
$format
->save();
}
}
if ($result === SAVED_NEW) {
$this
->messenger()
->addStatus($this
->t('The BBCode tag set %set has been created.', [
'%set' => $this->entity
->label(),
]));
}
elseif ($result === SAVED_UPDATED) {
$this
->messenger()
->addStatus($this
->t('The BBCode tag set %set has been updated.', [
'%set' => $this->entity
->label(),
]));
}
$form_state
->setRedirectUrl($this->entity
->toUrl('collection'));
}
public function getEntity() : EntityInterface {
$entity = parent::getEntity();
assert($entity instanceof EntityInterface);
return $entity;
}
}