htools-8.x-1.x-dev/src/Plugin/views/exposed_form/ExposedFormRegion.php
src/Plugin/views/exposed_form/ExposedFormRegion.php
<?php
namespace Drupal\htools\Plugin\views\exposed_form;
use Drupal\better_exposed_filters\Plugin\views\exposed_form\BetterExposedFilters;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
/**
* Exposed form plugin that provides configurable regions for each field
*
* @ingroup views_exposed_form_plugins
*
* @ViewsExposedForm(
* id = "exposed_form_region",
* title = @Translation("Exposed Form Region"),
* help = @Translation("Selectable regions to display the exposed form
* elements.")
* )
*/
class ExposedFormRegion extends BetterExposedFilters {
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$exposed_filters = [];
$view_filters = $this->view->display_handler->getHandlers('filter');
foreach ($view_filters as $filter => $filterOptions) {
if ($filterOptions->isExposed()) {
$exposed_filters[$filter] = !empty($filterOptions->options["expose"]["label"]) ? $filterOptions->options["expose"]["label"] : $filterOptions->options["expose"]["identifier"];
}
}
// Initialize options if any sort is exposed.
// Iterate over each sort and determine if any sorts are exposed.
$is_sort_exposed = FALSE;
/** @var \Drupal\views\Plugin\views\HandlerBase $sort */
foreach ($this->view->display_handler->getHandlers('sort') as $sort) {
if ($sort->isExposed()) {
$is_sort_exposed = TRUE;
break;
}
}
if ($is_sort_exposed) {
$exposed_filters['sort'] = $this->t('Sort');
}
// Initialize options if the pager is exposed.
$pager = $this->view->getPager();
if ($pager && $pager->usesExposed()) {
$exposed_filters['pager'] = $this->t('Pager');
}
// Building form with different options to configure different regions.
$form['regions'] = [
'#type' => 'details',
'#title' => $this->t('Regions configuration'),
'#tree' => TRUE,
];
for ($i = 0; $i < 4; $i++) {
$region = $i + 1;
$form['regions'][$i] = [
'#type' => 'details',
'#title' => $this->t("Region $region configuration"),
'#tree' => TRUE,
];
$form['regions'][$i]['layout'] = [
'#type' => 'checkboxes',
'#options' => $exposed_filters,
'#title' => $this->t("Layout of view sections"),
'#description' => $this->t('View regions to render exposed filter field'),
'#default_value' => $this->options['regions'][$i]['layout'] ?? [],
];
$form['regions'][$i]['hide_submit'] = [
'#type' => 'checkbox',
'#title' => $this->t('Hide submit button'),
'#description' => $this->t('Hide submit button in this region'),
'#default_value' => $this->options['regions'][$i]['hide_submit'] ?? TRUE,
];
$form['regions'][$i]['hide_reset'] = [
'#type' => 'checkbox',
'#title' => $this->t('Hide reset button'),
'#description' => $this->t('Enable reset button in this region'),
'#default_value' => $this->options['regions'][$i]['hide_reset'] ?? TRUE,
];
$form['regions'][$i]['enable_autosubmit'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable autosubmit'),
'#description' => $this->t('Enable autosubmit to form elements from this region.'),
'#default_value' => $this->options['regions'][$i]['enable_autosubmit'] ?? FALSE,
];
$form['regions'][$i]['include_submit'] = [
'#type' => 'checkbox',
'#title' => $this->t('Include form elements on submit.'),
'#description' => $this->t('If checked, the form elements will be included in the submit. This is useful if you want to use the exposed form as a filter for another view.'),
'#default_value' => $this->options['regions'][$i]['include_submit'] ?? TRUE,
];
}
}
/**
* {@inheritdoc}
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state) {
// Submit through 4 regions loop.
for ($i = 0; $i < 4; $i++) {
$form_state->setValue(['exposed_form_options','regions',$i], $form_state->getValue('exposed_form_options')['regions'][$i]);
}
parent::submitOptionsForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function renderExposedForm($block = FALSE) {
// Deal with any exposed filters we may have, before building.
$form_state = (new FormState())
->setStorage([
'view' => $this->view,
'display' => &$this->view->display_handler->display,
'rerender' => TRUE,
])
->setMethod('get')
->setAlwaysProcess()
->disableRedirect();
// Some types of displays (eg. attachments) may wish to use the exposed
// filters of their parent displays instead of showing an additional
// exposed filter form for the attachment as well as that for the parent.
if (!$this->view->display_handler->displaysExposed() || (!$block && $this->view->display_handler->getOption('exposed_block'))) {
$form_state->set('rerender', NULL);
}
if (!empty($this->ajax)) {
$form_state->set('ajax', TRUE);
}
$errors = $form_state->getErrors();
// If the exposed form had errors, do not build the view.
if (!empty($errors)) {
$this->view->build_info['abort'] = TRUE;
}
if (!$this->view->display_handler->displaysExposed() || (!$block && $this->view->display_handler->getOption('exposed_block'))) {
return [];
}
$view = $this->view;
$regions = $this->options['regions'];
$filter_handlers = !empty($view->display_handler->handlers['filter']) ? $view->display_handler->handlers['filter'] : NULL;
$sort_handlers = !empty($view->display_handler->handlers['sort']) ? $view->display_handler->handlers['sort'] : NULL;
$pager_handler = !empty($view->display_handler->handlers['pager']) ? $view->display_handler->handlers['pager'] : NULL;
$forms = [];
foreach ($regions as $key => $region) {
if (empty($region)) {
continue;
}
$form_state->set('region', $key);
$new_form = $form = \Drupal::formBuilder()->buildForm('\Drupal\htools\Form\ViewsExposedForm', $form_state);
// Attach filters responsive library.
$new_form['#attached']['library'][] = 'htools/responsive_filters';
if (!empty($pager_handler)) {
//$view->display_handler->handlers['pager'] = $pager_handler;
if (empty($region['pager']) && $pager_handler !== NULL) {
foreach ($pager_handler as $id => $handler) {
if ($handler->canExpose() && $handler->isExposed()) {
unset($new_form['pager']);
}
}
}
}
// Get extra region options.
$hide_submit = $region['hide_submit'] ?? TRUE;
$hide_reset = $region['hide_reset'] ?? TRUE;
$enable_autosubmit = $region['enable_autosubmit'] ?? FALSE;
$include_submit = $region['include_submit'] ?? TRUE;
if ($include_submit) {
$new_form['actions']['submit']['#attributes']['drupal-data-efr-submit'] = 'enabled';
$new_form['#attributes']['drupal-data-efr-include-submit'] = 'enabled';
if ($view->ajaxEnabled() == FALSE) {
$new_form['#attached']['library'][] = 'htools/multiple_submit';
}
}
// Apply auto-submit values.
if (!empty($enable_autosubmit)) {
// Add attributes from better exposed filters library.
$new_form = array_merge_recursive($new_form, [
'#attributes' => [
'data-bef-auto-submit-full-form' => '',
'data-bef-auto-submit' => '',
'data-bef-auto-submit-delay' => '500',
],
]);
$new_form['actions']['submit']['#attributes']['data-bef-auto-submit-click'] = '';
// Library to autosubmit
$new_form['#attached']['library'][] = 'better_exposed_filters/auto_submit';
}
// Hide submit reset button
if (!empty($hide_submit)) {
$new_form['actions']['submit']['#attributes']['class'][] = 'js-hide';
}
// Hide reset button
if (!empty($hide_reset)) {
$new_form['actions']['reset']['#attributes']['class'][] = 'js-hide';
}
// Clean sort handlers if needed.
if (!empty($sort_handlers)) {
//$view->display_handler->handlers['sort'] = $sort_handlers;
if (empty($region['layout']['sort']) && !empty($sort_handlers)) {
foreach ($sort_handlers as $id => $handler) {
if ($handler->canExpose() && $handler->isExposed()) {
if (!empty($new_form['sort'])) {
unset($new_form['sort']);
}
if (!empty($new_form['sort_bef_combine'])) {
unset($new_form['sort_bef_combine']);
}
}
}
}
}
//Clean pager exposed options
if (empty($region['layout']['pager'])){
if (!empty($new_form['items_per_page'])) {
unset($new_form['items_per_page']);
}
if (!empty($new_form['offset'])) {
unset($new_form['offset']);
}
}
// Clear form elements inside region, to avoid duplicated form elements.
if (!empty($filter_handlers)) {
//$view->display_handler->handlers['filter'] = $filter_handlers;
foreach ($filter_handlers as $handler) {
$filter_identifier = $handler->options['expose']['identifier'];
if ($handler->canExpose() && $handler->isExposed() && empty($region['layout'][$handler->field])) {
if (!empty($new_form[$handler->field])) {
unset($new_form[$handler->field]);
}
if (!empty($new_form[$filter_identifier . '_wrapper'])) {
unset($new_form[$filter_identifier . '_wrapper']);
}
if (!empty($new_form[$filter_identifier . '_collapsible'])) {
unset($new_form[$filter_identifier . '_collapsible']);
}
if (!empty($handler->configuration['field_name']) && !empty($new_form[$handler->configuration['field_name']])) {
unset($new_form[$handler->configuration['field_name']]);
continue;
}
if (!empty($handler->options['expose']['identifier']) && !empty($new_form[$handler->options['expose']['identifier']])) {
unset($new_form[$handler->options['expose']['identifier']]);
}
}else{
if (!empty($new_form[$filter_identifier . '_collapsible'])) {
unset($new_form[$filter_identifier . '_collapsible']['#groups'][$filter_identifier . '_collapsible']);
}
}
}
}
$forms[$key] = $new_form;
}
return $forms;
}
/**
* {@inheritdoc}
*/
public function exposedFormAlter(&$form, FormStateInterface $form_state) {
parent::exposedFormAlter($form, $form_state);
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['regions'] = ['default' => []];
return $options;
}
}
