3 namespace Drupal\filter;
5 use Drupal\Core\Entity\EntityForm;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\filter\Plugin\Filter\FilterNull;
10 * Provides a base form for a filter format.
12 abstract class FilterFormatFormBase extends EntityForm {
17 public function form(array $form, FormStateInterface $form_state) {
18 $format = $this->entity;
19 $is_fallback = ($format->id() == $this->config('filter.settings')->get('fallback_format'));
21 $form['#tree'] = TRUE;
22 $form['#attached']['library'][] = 'filter/drupal.filter.admin';
25 '#type' => 'textfield',
26 '#title' => $this->t('Name'),
27 '#default_value' => $format->label(),
32 '#type' => 'machine_name',
34 '#default_value' => $format->id(),
37 'exists' => [$this, 'exists'],
40 '#disabled' => !$format->isNew(),
44 // Add user role access selection.
46 '#type' => 'checkboxes',
47 '#title' => $this->t('Roles'),
48 '#options' => array_map('\Drupal\Component\Utility\Html::escape', user_role_names()),
49 '#disabled' => $is_fallback,
53 $form['roles']['#description'] = $this->t('All roles for this text format must be enabled and cannot be changed.');
55 if (!$format->isNew()) {
56 // If editing an existing text format, pre-select its current permissions.
57 $form['roles']['#default_value'] = array_keys(filter_get_roles_by_format($format));
60 // Create filter plugin instances for all available filters, including both
61 // enabled/configured ones as well as new and not yet unconfigured ones.
62 $filters = $format->filters();
63 foreach ($filters as $filter_id => $filter) {
64 // When a filter is missing, it is replaced by the null filter. Remove it
65 // here, so that saving the form will remove the missing filter.
66 if ($filter instanceof FilterNull) {
67 drupal_set_message($this->t('The %filter filter is missing, and will be removed once this format is saved.', ['%filter' => $filter_id]), 'warning');
68 $filters->removeInstanceID($filter_id);
73 $form['filters']['status'] = [
75 '#title' => $this->t('Enabled filters'),
76 '#prefix' => '<div id="filters-status-wrapper">',
77 '#suffix' => '</div>',
78 // This item is used as a pure wrapping container with heading. Ignore its
79 // value, since 'filters' should only contain filter definitions.
80 // See https://www.drupal.org/node/1829202.
83 // Filter order (tabledrag).
84 $form['filters']['order'] = [
86 // For filter.admin.js
87 '#attributes' => ['id' => 'filter-order'],
88 '#title' => $this->t('Filter processing order'),
92 'relationship' => 'sibling',
93 'group' => 'filter-order-weight',
98 '#theme_wrappers' => ['form_element'],
101 $form['filter_settings'] = [
102 '#type' => 'vertical_tabs',
103 '#title' => $this->t('Filter settings'),
106 foreach ($filters as $name => $filter) {
107 $form['filters']['status'][$name] = [
108 '#type' => 'checkbox',
109 '#title' => $filter->getLabel(),
110 '#default_value' => $filter->status,
111 '#parents' => ['filters', $name, 'status'],
112 '#description' => $filter->getDescription(),
113 '#weight' => $filter->weight,
116 $form['filters']['order'][$name]['#attributes']['class'][] = 'draggable';
117 $form['filters']['order'][$name]['#weight'] = $filter->weight;
118 $form['filters']['order'][$name]['filter'] = [
119 '#markup' => $filter->getLabel(),
121 $form['filters']['order'][$name]['weight'] = [
123 '#title' => $this->t('Weight for @title', ['@title' => $filter->getLabel()]),
124 '#title_display' => 'invisible',
126 '#default_value' => $filter->weight,
127 '#parents' => ['filters', $name, 'weight'],
128 '#attributes' => ['class' => ['filter-order-weight']],
131 // Retrieve the settings form of the filter plugin. The plugin should not be
132 // aware of the text format. Therefore, it only receives a set of minimal
133 // base properties to allow advanced implementations to work.
135 '#parents' => ['filters', $name, 'settings'],
138 $settings_form = $filter->settingsForm($settings_form, $form_state);
139 if (!empty($settings_form)) {
140 $form['filters']['settings'][$name] = [
141 '#type' => 'details',
142 '#title' => $filter->getLabel(),
144 '#weight' => $filter->weight,
145 '#parents' => ['filters', $name, 'settings'],
146 '#group' => 'filter_settings',
148 $form['filters']['settings'][$name] += $settings_form;
151 return parent::form($form, $form_state);
155 * Determines if the format already exists.
157 * @param string $format_id
161 * TRUE if the format exists, FALSE otherwise.
163 public function exists($format_id) {
164 return (bool) $this->entityTypeManager
165 ->getStorage('filter_format')
167 ->condition('format', $format_id)
174 public function validateForm(array &$form, FormStateInterface $form_state) {
175 parent::validateForm($form, $form_state);
177 // @todo Move trimming upstream.
178 $format_format = trim($form_state->getValue('format'));
179 $format_name = trim($form_state->getValue('name'));
181 // Ensure that the values to be saved later are exactly the ones validated.
182 $form_state->setValueForElement($form['format'], $format_format);
183 $form_state->setValueForElement($form['name'], $format_name);
185 $format_exists = $this->entityTypeManager
186 ->getStorage('filter_format')
188 ->condition('format', $format_format, '<>')
189 ->condition('name', $format_name)
191 if ($format_exists) {
192 $form_state->setErrorByName('name', $this->t('Text format names must be unique. A format named %name already exists.', ['%name' => $format_name]));
199 public function submitForm(array &$form, FormStateInterface $form_state) {
200 parent::submitForm($form, $form_state);
202 // Add the submitted form values to the text format, and save it.
203 $format = $this->entity;
204 foreach ($form_state->getValues() as $key => $value) {
205 if ($key != 'filters') {
206 $format->set($key, $value);
209 foreach ($value as $instance_id => $config) {
210 $format->setFilterConfig($instance_id, $config);
216 // Save user permissions.
217 if ($permission = $format->getPermissionName()) {
218 foreach ($form_state->getValue('roles') as $rid => $enabled) {
219 user_role_change_permissions($rid, [$permission => $enabled]);
223 $form_state->setRedirect('filter.admin_overview');
225 return $this->entity;
231 protected function actions(array $form, FormStateInterface $form_state) {
232 $actions = parent::actions($form, $form_state);
233 $actions['submit']['#value'] = $this->t('Save configuration');