FilterFormatFormBase.php

Same filename in other branches
  1. 9 core/modules/filter/src/FilterFormatFormBase.php
  2. 8.9.x core/modules/filter/src/FilterFormatFormBase.php
  3. 10 core/modules/filter/src/FilterFormatFormBase.php

Namespace

Drupal\filter

File

core/modules/filter/src/FilterFormatFormBase.php

View source
<?php

namespace Drupal\filter;

use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\filter\Plugin\Filter\FilterNull;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;

/**
 * Provides a base form for a filter format.
 */
abstract class FilterFormatFormBase extends EntityForm {
    
    /**
     * {@inheritdoc}
     */
    public function form(array $form, FormStateInterface $form_state) {
        $format = $this->entity;
        $is_fallback = $format->id() == $this->config('filter.settings')
            ->get('fallback_format');
        $form['#tree'] = TRUE;
        $form['#attached']['library'][] = 'filter/drupal.filter.admin';
        $form['name'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Name'),
            '#default_value' => $format->label(),
            '#required' => TRUE,
            '#weight' => -30,
        ];
        $form['format'] = [
            '#type' => 'machine_name',
            '#required' => TRUE,
            '#default_value' => $format->id(),
            '#maxlength' => 255,
            '#machine_name' => [
                'exists' => [
                    $this,
                    'exists',
                ],
                'source' => [
                    'name',
                ],
            ],
            '#disabled' => !$format->isNew(),
            '#weight' => -20,
        ];
        // Add user role access selection.
        $form['roles'] = [
            '#type' => 'checkboxes',
            '#title' => $this->t('Roles'),
            '#options' => array_map(fn(RoleInterface $role) => Html::escape($role->label()), Role::loadMultiple()),
            '#disabled' => $is_fallback,
            '#weight' => -10,
        ];
        if ($is_fallback) {
            $form['roles']['#description'] = $this->t('All roles for this text format must be enabled and cannot be changed.');
        }
        if (!$format->isNew()) {
            // If editing an existing text format, pre-select its current permissions.
            $form['roles']['#default_value'] = array_keys(filter_get_roles_by_format($format));
        }
        // Create filter plugin instances for all available filters, including both
        // enabled/configured ones as well as new and not yet configured ones.
        $filters = $format->filters();
        foreach ($filters as $filter_id => $filter) {
            // When a filter is missing, it is replaced by the null filter. Remove it
            // here, so that saving the form will remove the missing filter.
            if ($filter instanceof FilterNull) {
                $this->messenger()
                    ->addWarning($this->t('The %filter filter is missing, and will be removed once this format is saved.', [
                    '%filter' => $filter_id,
                ]));
                $filters->removeInstanceID($filter_id);
            }
        }
        // Filter status.
        $form['filters']['status'] = [
            '#type' => 'item',
            '#title' => $this->t('Enabled filters'),
            '#prefix' => '<div id="filters-status-wrapper">',
            '#suffix' => '</div>',
            // This item is used as a pure wrapping container with heading. Ignore its
            // value, since 'filters' should only contain filter definitions.
            // See https://www.drupal.org/node/1829202.
'#input' => FALSE,
        ];
        // Filter order (tabledrag).
        $form['filters']['order'] = [
            '#type' => 'table',
            // For filter.admin.js
'#attributes' => [
                'id' => 'filter-order',
            ],
            '#title' => $this->t('Filter processing order'),
            '#tabledrag' => [
                [
                    'action' => 'order',
                    'relationship' => 'sibling',
                    'group' => 'filter-order-weight',
                ],
            ],
            '#tree' => FALSE,
            '#input' => FALSE,
            '#theme_wrappers' => [
                'form_element',
            ],
        ];
        // Filter settings.
        $form['filter_settings'] = [
            '#type' => 'vertical_tabs',
            '#title' => $this->t('Filter settings'),
        ];
        foreach ($filters as $name => $filter) {
            $form['filters']['status'][$name] = [
                '#type' => 'checkbox',
                '#title' => $filter->getLabel(),
                '#default_value' => $filter->status,
                '#parents' => [
                    'filters',
                    $name,
                    'status',
                ],
                '#description' => $filter->getDescription(),
                '#weight' => $filter->weight,
            ];
            $form['filters']['order'][$name]['#attributes']['class'][] = 'draggable';
            $form['filters']['order'][$name]['#weight'] = $filter->weight;
            $form['filters']['order'][$name]['filter'] = [
                '#markup' => $filter->getLabel(),
            ];
            $form['filters']['order'][$name]['weight'] = [
                '#type' => 'weight',
                '#title' => $this->t('Weight for @title', [
                    '@title' => $filter->getLabel(),
                ]),
                '#title_display' => 'invisible',
                '#delta' => 50,
                '#default_value' => $filter->weight,
                '#parents' => [
                    'filters',
                    $name,
                    'weight',
                ],
                '#attributes' => [
                    'class' => [
                        'filter-order-weight',
                    ],
                ],
            ];
            // Ensure the resulting FilterFormat complies with `type: filter`.
            // @see core.data_types.schema.yml
            // @see \Drupal\filter\FilterFormatFormBase::submitForm()
            $form['filters']['order'][$name]['id'] = [
                '#type' => 'value',
                '#value' => $filter->getPluginId(),
                '#parents' => [
                    'filters',
                    $name,
                    'id',
                ],
            ];
            $form['filters']['order'][$name]['provider'] = [
                '#type' => 'value',
                '#value' => $filter->provider,
                '#parents' => [
                    'filters',
                    $name,
                    'provider',
                ],
            ];
            // Retrieve the settings form of the filter plugin. The plugin should not be
            // aware of the text format. Therefore, it only receives a set of minimal
            // base properties to allow advanced implementations to work.
            $settings_form = [
                '#parents' => [
                    'filters',
                    $name,
                    'settings',
                ],
                '#tree' => TRUE,
            ];
            $settings_form = $filter->settingsForm($settings_form, $form_state);
            if (!empty($settings_form)) {
                $form['filters']['settings'][$name] = [
                    '#type' => 'details',
                    '#title' => $filter->getLabel(),
                    '#open' => TRUE,
                    '#weight' => $filter->weight,
                    '#parents' => [
                        'filters',
                        $name,
                        'settings',
                    ],
                    '#group' => 'filter_settings',
                ];
                $form['filters']['settings'][$name] += $settings_form;
            }
        }
        return parent::form($form, $form_state);
    }
    
    /**
     * Determines if the format already exists.
     *
     * @param string $format_id
     *   The format ID
     *
     * @return bool
     *   TRUE if the format exists, FALSE otherwise.
     */
    public function exists($format_id) {
        return (bool) $this->entityTypeManager
            ->getStorage('filter_format')
            ->getQuery()
            ->condition('format', $format_id)
            ->execute();
    }
    
    /**
     * {@inheritdoc}
     */
    public function validateForm(array &$form, FormStateInterface $form_state) {
        parent::validateForm($form, $form_state);
        // @todo Move trimming upstream.
        $format_format = trim($form_state->getValue('format'));
        $format_name = trim($form_state->getValue('name'));
        // Ensure that the values to be saved later are exactly the ones validated.
        $form_state->setValueForElement($form['format'], $format_format);
        $form_state->setValueForElement($form['name'], $format_name);
        $format_exists = $this->entityTypeManager
            ->getStorage('filter_format')
            ->getQuery()
            ->condition('format', $format_format, '<>')
            ->condition('name', $format_name)
            ->execute();
        if ($format_exists) {
            $form_state->setErrorByName('name', $this->t('Text format names must be unique. A format named %name already exists.', [
                '%name' => $format_name,
            ]));
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function submitForm(array &$form, FormStateInterface $form_state) {
        parent::submitForm($form, $form_state);
        // Add the submitted form values to the text format, and save it.
        $format = $this->entity;
        foreach ($form_state->getValues() as $key => $value) {
            if ($key != 'filters') {
                $format->set($key, $value);
            }
            else {
                foreach ($value as $instance_id => $config) {
                    $format->setFilterConfig($instance_id, $config);
                }
            }
        }
        $format->save();
        // Save user permissions.
        if ($permission = $format->getPermissionName()) {
            foreach ($form_state->getValue('roles') as $rid => $enabled) {
                user_role_change_permissions($rid, [
                    $permission => $enabled,
                ]);
            }
        }
        return $this->entity;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function actions(array $form, FormStateInterface $form_state) {
        $actions = parent::actions($form, $form_state);
        $actions['submit']['#value'] = $this->t('Save configuration');
        return $actions;
    }

}

Classes

Title Deprecated Summary
FilterFormatFormBase Provides a base form for a filter format.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.