Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / views / src / Plugin / views / sort / SortPluginBase.php
1 <?php
2
3 namespace Drupal\views\Plugin\views\sort;
4
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Cache\CacheableDependencyInterface;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\views\Plugin\views\HandlerBase;
9
10 /**
11  * @defgroup views_sort_handlers Views sort handler plugins
12  * @{
13  * Plugins that handle sorting for Views.
14  *
15  * Sort handlers extend \Drupal\views\Plugin\views\sort:SortPluginBase. They
16  * must be annotated with \Drupal\views\Annotation\ViewsSort annotation, and
17  * they must be in plugin directory Plugin\views\sort.
18  *
19  * @ingroup views_plugins
20  * @see plugin_api
21  */
22
23 /**
24  * Base sort handler that has no options and performs a simple sort.
25  */
26 abstract class SortPluginBase extends HandlerBase implements CacheableDependencyInterface {
27
28   /**
29    * Determine if a sort can be exposed.
30    */
31   public function canExpose() {
32     return TRUE;
33   }
34
35   /**
36    * Called to add the sort to a query.
37    */
38   public function query() {
39     $this->ensureMyTable();
40     // Add the field.
41     $this->query->addOrderBy($this->tableAlias, $this->realField, $this->options['order']);
42   }
43
44   protected function defineOptions() {
45     $options = parent::defineOptions();
46
47     $options['order'] = ['default' => 'ASC'];
48     $options['exposed'] = ['default' => FALSE];
49     $options['expose'] = [
50       'contains' => [
51         'label' => ['default' => ''],
52       ],
53     ];
54     return $options;
55   }
56
57   /**
58    * Display whether or not the sort order is ascending or descending
59    */
60   public function adminSummary() {
61     if (!empty($this->options['exposed'])) {
62       return $this->t('Exposed');
63     }
64     switch ($this->options['order']) {
65       case 'ASC':
66       case 'asc':
67       default:
68         return $this->t('asc');
69
70       case 'DESC';
71       case 'desc';
72         return $this->t('desc');
73     }
74   }
75
76   /**
77    * Basic options for all sort criteria
78    */
79   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
80     parent::buildOptionsForm($form, $form_state);
81     if ($this->canExpose()) {
82       $this->showExposeButton($form, $form_state);
83     }
84     $form['op_val_start'] = ['#value' => '<div class="clearfix">'];
85     $this->showSortForm($form, $form_state);
86     $form['op_val_end'] = ['#value' => '</div>'];
87     if ($this->canExpose()) {
88       $this->showExposeForm($form, $form_state);
89     }
90   }
91
92   /**
93    * Shortcut to display the expose/hide button.
94    */
95   public function showExposeButton(&$form, FormStateInterface $form_state) {
96     $form['expose_button'] = [
97       '#prefix' => '<div class="views-expose clearfix">',
98       '#suffix' => '</div>',
99       // Should always come first
100       '#weight' => -1000,
101     ];
102
103     // Add a checkbox for JS users, which will have behavior attached to it
104     // so it can replace the button.
105     $form['expose_button']['checkbox'] = [
106       '#theme_wrappers' => ['container'],
107       '#attributes' => ['class' => ['js-only']],
108     ];
109     $form['expose_button']['checkbox']['checkbox'] = [
110       '#title' => $this->t('Expose this sort to visitors, to allow them to change it'),
111       '#type' => 'checkbox',
112     ];
113
114     // Then add the button itself.
115     if (empty($this->options['exposed'])) {
116       $form['expose_button']['markup'] = [
117         '#markup' => '<div class="description exposed-description" style="float: left; margin-right:10px">' . $this->t('This sort is not exposed. Expose it to allow the users to change it.') . '</div>',
118       ];
119       $form['expose_button']['button'] = [
120         '#limit_validation_errors' => [],
121         '#type' => 'submit',
122         '#value' => $this->t('Expose sort'),
123         '#submit' => [[$this, 'displayExposedForm']],
124       ];
125       $form['expose_button']['checkbox']['checkbox']['#default_value'] = 0;
126     }
127     else {
128       $form['expose_button']['markup'] = [
129         '#markup' => '<div class="description exposed-description">' . $this->t('This sort is exposed. If you hide it, users will not be able to change it.') . '</div>',
130       ];
131       $form['expose_button']['button'] = [
132         '#limit_validation_errors' => [],
133         '#type' => 'submit',
134         '#value' => $this->t('Hide sort'),
135         '#submit' => [[$this, 'displayExposedForm']],
136       ];
137       $form['expose_button']['checkbox']['checkbox']['#default_value'] = 1;
138     }
139   }
140
141   /**
142    * Simple validate handler
143    */
144   public function validateOptionsForm(&$form, FormStateInterface $form_state) {
145     $this->sortValidate($form, $form_state);
146     if (!empty($this->options['exposed'])) {
147       $this->validateExposeForm($form, $form_state);
148     }
149
150   }
151
152   /**
153    * Simple submit handler
154    */
155   public function submitOptionsForm(&$form, FormStateInterface $form_state) {
156     // Do not store this values.
157     $form_state->unsetValue('expose_button');
158
159     $this->sortSubmit($form, $form_state);
160     if (!empty($this->options['exposed'])) {
161       $this->submitExposeForm($form, $form_state);
162     }
163   }
164
165   /**
166    * Shortcut to display the value form.
167    */
168   protected function showSortForm(&$form, FormStateInterface $form_state) {
169     $options = $this->sortOptions();
170     if (!empty($options)) {
171       $form['order'] = [
172         '#title' => $this->t('Order'),
173         '#type' => 'radios',
174         '#options' => $options,
175         '#default_value' => $this->options['order'],
176       ];
177     }
178   }
179
180   protected function sortValidate(&$form, FormStateInterface $form_state) {}
181
182   public function sortSubmit(&$form, FormStateInterface $form_state) {}
183
184   /**
185    * Provide a list of options for the default sort form.
186    * Should be overridden by classes that don't override sort_form
187    */
188   protected function sortOptions() {
189     return [
190       'ASC' => $this->t('Sort ascending'),
191       'DESC' => $this->t('Sort descending'),
192     ];
193   }
194
195   public function buildExposeForm(&$form, FormStateInterface $form_state) {
196     // #flatten will move everything from $form['expose'][$key] to $form[$key]
197     // prior to rendering. That's why the preRender for it needs to run first,
198     // so that when the next preRender (the one for fieldsets) runs, it gets
199     // the flattened data.
200     array_unshift($form['#pre_render'], [get_class($this), 'preRenderFlattenData']);
201     $form['expose']['#flatten'] = TRUE;
202
203     $form['expose']['label'] = [
204       '#type' => 'textfield',
205       '#default_value' => $this->options['expose']['label'],
206       '#title' => $this->t('Label'),
207       '#required' => TRUE,
208       '#size' => 40,
209       '#weight' => -1,
210    ];
211   }
212
213   /**
214    * Provide default options for exposed sorts.
215    */
216   public function defaultExposeOptions() {
217     $this->options['expose'] = [
218       'label' => $this->definition['title'],
219     ];
220   }
221
222   /**
223    * {@inheritdoc}
224    */
225   public function getCacheMaxAge() {
226     // The result of a sort does not depend on outside information, so by
227     // default it is cacheable.
228     return Cache::PERMANENT;
229   }
230
231   /**
232    * {@inheritdoc}
233    */
234   public function getCacheContexts() {
235     $cache_contexts = [];
236     // Exposed sorts use GET parameters, so it depends on the current URL.
237     if ($this->isExposed()) {
238       $cache_contexts[] = 'url.query_args:sort_by';
239     }
240     return $cache_contexts;
241   }
242
243   /**
244    * {@inheritdoc}
245    */
246   public function getCacheTags() {
247     return [];
248   }
249
250 }
251
252 /**
253  * @}
254  */