View source
<?php
namespace Drupal\contextual_range_filter\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Views;
class ContextualRangeFilterAssignmentForm extends ConfigFormBase {
public function getFormId() {
return 'contextual_range_filter_settings';
}
protected function getEditableConfigNames() {
return [
'contextual_range_filter.settings',
];
}
public function buildForm(array $form, FormStateInterface $form_state) {
$range_fields = [
'date_field_names' => [],
'numeric_field_names' => [],
'string_field_names' => [],
];
$class_path = 'Drupal\\views\\Plugin\\views\\argument';
$argument_info = Views::pluginManager('argument')
->getDefinitions();
foreach (Views::getAllViews() as $view) {
$view_name = $view
->get('label');
if (views_view_is_disabled($view)) {
$view_name .= ' (' . $this
->t('disabled') . ')';
}
foreach ($view
->get('display') as $display) {
if (!empty($display['display_options']['arguments'])) {
foreach ($display['display_options']['arguments'] as $contextual_filter) {
$plugin_id = $contextual_filter['plugin_id'];
$class = $argument_info[$plugin_id]['class'];
$is_date_handler = is_a($class, "{$class_path}\\Date", TRUE);
$is_string_handler = is_a($class, "{$class_path}\\StringArgument", TRUE);
$is_numeric_handler = !$is_date_handler && !$is_string_handler;
if ($is_date_handler || $is_numeric_handler || $is_string_handler) {
$title = "{$plugin_id}: " . $contextual_filter['id'];
$machine_name = $contextual_filter['table'] . ':' . $contextual_filter['field'];
if ($is_date_handler) {
$title_used = isset($range_fields['date_field_names'][$machine_name][$title]);
if (!$title_used || !in_array($view_name, $range_fields['date_field_names'][$machine_name][$title])) {
$range_fields['date_field_names'][$machine_name][$title][] = $view_name;
}
}
elseif ($is_numeric_handler) {
$title_used = isset($range_fields['numeric_field_names'][$machine_name][$title]);
if (!$title_used || !in_array($view_name, $range_fields['numeric_field_names'][$machine_name][$title])) {
$range_fields['numeric_field_names'][$machine_name][$title][] = $view_name;
}
}
elseif ($is_string_handler) {
$title_used = isset($range_fields['string_field_names'][$machine_name][$title]);
if (!$title_used || !in_array($view_name, $range_fields['string_field_names'][$machine_name][$title])) {
$range_fields['string_field_names'][$machine_name][$title][] = $view_name;
}
}
}
}
}
}
}
$form['field_names'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Select contextual filters to be converted to contextual range filters'),
];
$config = $this->configFactory
->get('contextual_range_filter.settings');
$labels = [
$this
->t('date'),
$this
->t('numeric'),
$this
->t('string'),
];
$label = reset($labels);
foreach ($range_fields as $type => $data) {
$options = [];
foreach ($data as $machine_name => $view_names) {
$title = key($view_names);
$views_list = implode(', ', $view_names[$title]);
$replace = [
'%field' => $title,
'@views' => $views_list,
];
$options[$machine_name] = $this
->t('%field in view @views', $replace);
$form['#view_names'][$machine_name] = $view_names;
}
$form['field_names'][$type] = [
'#type' => 'checkboxes',
'#title' => $this
->t('Select which of the below contextual <em>@label</em> filters should be converted to <em>@label range</em> filters:', [
'@label' => $label,
]),
'#default_value' => $config
->get($type) ?: [],
'#options' => $options,
];
$label = next($labels);
}
$form['actions']['note'] = [
'#markup' => '<p><em>' . $this
->t('Caches will be cleared as part of this operation. This may take a while.') . '</em></p>',
'#weight' => 1,
];
return parent::buildForm($form, $form_state);
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->configFactory
->getEditable('contextual_range_filter.settings');
foreach ([
'numeric',
'string',
'date',
] as $type) {
$field_names = $type . '_field_names';
$filters = array_filter($form_state
->getValue($field_names));
$saved_filters = $config
->get($field_names) ?: [];
$added_filters = array_diff($filters, $saved_filters);
$removed_filters = array_diff($saved_filters, $filters);
$changed_filters = array_merge($added_filters, $removed_filters);
if (empty($changed_filters)) {
continue;
}
$config
->set($field_names, $filters);
$changed_view_names = [];
foreach ($changed_filters as $filter_name) {
if (!empty($form['#view_names'][$filter_name])) {
foreach ($form['#view_names'][$filter_name] as $view_names) {
foreach ($view_names as $view_name) {
if (!in_array($view_name, $changed_view_names)) {
$changed_view_names[] = $view_name;
}
}
}
}
}
$range_type = $type . '_range';
foreach (Views::getAllViews() as $view) {
$view_name = $view
->get('label');
if (in_array($view_name, $changed_view_names)) {
$display =& $view
->getDisplay('default');
foreach ($changed_filters as $filter_name) {
$field_name = substr($filter_name, strpos($filter_name, ":") + 1);
if (isset($display['display_options']['arguments'][$field_name]['plugin_id'])) {
$plugin_id = in_array($filter_name, $added_filters) ? $range_type : $type;
$display['display_options']['arguments'][$field_name]['plugin_id'] = $plugin_id;
}
$this
->messenger()
->addStatus($this
->t('Updated contextual filter(s) on view %view_name.', [
'%view_name' => $view_name,
]));
$view
->save();
}
}
}
}
$config
->save();
drupal_flush_all_caches();
parent::submitForm($form, $form_state);
}
}