5526b02fd4fb98851165f99843dfe99cc48cb95f
[yaffs-website] / web / core / modules / filter / src / FilterFormatFormBase.php
1 <?php
2
3 namespace Drupal\filter;
4
5 use Drupal\Core\Entity\EntityForm;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\filter\Plugin\Filter\FilterNull;
8
9 /**
10  * Provides a base form for a filter format.
11  */
12 abstract class FilterFormatFormBase extends EntityForm {
13
14   /**
15    * {@inheritdoc}
16    */
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'));
20
21     $form['#tree'] = TRUE;
22     $form['#attached']['library'][] = 'filter/drupal.filter.admin';
23
24     $form['name'] = [
25       '#type' => 'textfield',
26       '#title' => $this->t('Name'),
27       '#default_value' => $format->label(),
28       '#required' => TRUE,
29       '#weight' => -30,
30     ];
31     $form['format'] = [
32       '#type' => 'machine_name',
33       '#required' => TRUE,
34       '#default_value' => $format->id(),
35       '#maxlength' => 255,
36       '#machine_name' => [
37         'exists' => [$this, 'exists'],
38         'source' => ['name'],
39       ],
40       '#disabled' => !$format->isNew(),
41       '#weight' => -20,
42     ];
43
44     // Add user role access selection.
45     $form['roles'] = [
46       '#type' => 'checkboxes',
47       '#title' => $this->t('Roles'),
48       '#options' => array_map('\Drupal\Component\Utility\Html::escape', user_role_names()),
49       '#disabled' => $is_fallback,
50       '#weight' => -10,
51     ];
52     if ($is_fallback) {
53       $form['roles']['#description'] = $this->t('All roles for this text format must be enabled and cannot be changed.');
54     }
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));
58     }
59
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         $this->messenger()->addWarning($this->t('The %filter filter is missing, and will be removed once this format is saved.', ['%filter' => $filter_id]));
68         $filters->removeInstanceID($filter_id);
69       }
70     }
71
72     // Filter status.
73     $form['filters']['status'] = [
74       '#type' => 'item',
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.
81       '#input' => FALSE,
82     ];
83     // Filter order (tabledrag).
84     $form['filters']['order'] = [
85       '#type' => 'table',
86       // For filter.admin.js
87       '#attributes' => ['id' => 'filter-order'],
88       '#title' => $this->t('Filter processing order'),
89       '#tabledrag' => [
90         [
91          'action' => 'order',
92          'relationship' => 'sibling',
93          'group' => 'filter-order-weight',
94         ],
95       ],
96       '#tree' => FALSE,
97       '#input' => FALSE,
98       '#theme_wrappers' => ['form_element'],
99     ];
100     // Filter settings.
101     $form['filter_settings'] = [
102       '#type' => 'vertical_tabs',
103       '#title' => $this->t('Filter settings'),
104     ];
105
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,
114       ];
115
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(),
120       ];
121       $form['filters']['order'][$name]['weight'] = [
122         '#type' => 'weight',
123         '#title' => $this->t('Weight for @title', ['@title' => $filter->getLabel()]),
124         '#title_display' => 'invisible',
125         '#delta' => 50,
126         '#default_value' => $filter->weight,
127         '#parents' => ['filters', $name, 'weight'],
128         '#attributes' => ['class' => ['filter-order-weight']],
129       ];
130
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.
134       $settings_form = [
135         '#parents' => ['filters', $name, 'settings'],
136         '#tree' => TRUE,
137       ];
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(),
143           '#open' => TRUE,
144           '#weight' => $filter->weight,
145           '#parents' => ['filters', $name, 'settings'],
146           '#group' => 'filter_settings',
147         ];
148         $form['filters']['settings'][$name] += $settings_form;
149       }
150     }
151     return parent::form($form, $form_state);
152   }
153
154   /**
155    * Determines if the format already exists.
156    *
157    * @param string $format_id
158    *   The format ID
159    *
160    * @return bool
161    *   TRUE if the format exists, FALSE otherwise.
162    */
163   public function exists($format_id) {
164     return (bool) $this->entityTypeManager
165       ->getStorage('filter_format')
166       ->getQuery()
167       ->condition('format', $format_id)
168       ->execute();
169   }
170
171   /**
172    * {@inheritdoc}
173    */
174   public function validateForm(array &$form, FormStateInterface $form_state) {
175     parent::validateForm($form, $form_state);
176
177     // @todo Move trimming upstream.
178     $format_format = trim($form_state->getValue('format'));
179     $format_name = trim($form_state->getValue('name'));
180
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);
184
185     $format_exists = $this->entityTypeManager
186       ->getStorage('filter_format')
187       ->getQuery()
188       ->condition('format', $format_format, '<>')
189       ->condition('name', $format_name)
190       ->execute();
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]));
193     }
194   }
195
196   /**
197    * {@inheritdoc}
198    */
199   public function submitForm(array &$form, FormStateInterface $form_state) {
200     parent::submitForm($form, $form_state);
201
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);
207       }
208       else {
209         foreach ($value as $instance_id => $config) {
210           $format->setFilterConfig($instance_id, $config);
211         }
212       }
213     }
214     $format->save();
215
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]);
220       }
221     }
222
223     $form_state->setRedirect('filter.admin_overview');
224
225     return $this->entity;
226   }
227
228   /**
229    * {@inheritdoc}
230    */
231   protected function actions(array $form, FormStateInterface $form_state) {
232     $actions = parent::actions($form, $form_state);
233     $actions['submit']['#value'] = $this->t('Save configuration');
234     return $actions;
235   }
236
237 }