theme_region_wrapper-1.0.x-dev/theme_region_wrapper.module
theme_region_wrapper.module
<?php
/**
* @file
* Alters enabled theme's region wrapper output.
*/
use Drupal\Core\Form\FormStateInterface;
/**
* Implements hook_theme_registry_alter().
*/
function theme_region_wrapper_theme_registry_alter(array &$theme_registry):void {
// Only override the region template if it came from core. Allow themes that
// have overridden the region template to take precedence.
if (strpos($theme_registry['region']['path'], 'core') !== 0) {
return;
}
$module_path = \Drupal::service('extension.list.module')->getPath('theme_region_wrapper');
$theme_registry['region']['path'] = $module_path . '/templates';
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function theme_region_wrapper_form_system_theme_settings_alter(array &$form, FormStateInterface $form_state):void {
$form['#validate'][] = 'theme_region_wrapper_scheme_form_validate';
// Execute submit function at first to avoid saving unused values.
array_unshift($form['#submit'], 'theme_region_wrapper_scheme_form_submit');
$build_info = $form_state->getBuildInfo();
if (isset($build_info['args'][0]) && ($theme = $build_info['args'][0])) {
$module_settings = \Drupal::configFactory()->get('theme_region_wrapper.settings');
$wrapper_elements = $module_settings->get('wrapper_elements');
$form['region_wrapper'] = [
'#type' => 'table',
'#header' => [
t('Region'),
t('Wrapper Output'),
],
'#weight' => -1,
'#sticky' => TRUE,
'#theme_wrappers' => [
'details' => [
'#summary_attributes' => [
'id' => 'region_wrapper_form',
'open' => 'open',
],
'#title' => t('Theme region wrapper settings'),
],
],
];
$regions = system_region_list($theme, REGIONS_VISIBLE);
$theme_config_key = "$theme.settings";
$theme_config = \Drupal::configFactory()->get($theme_config_key);
foreach ($regions as $region => $label) {
$region_config_values = $theme_config->get("third_party_settings.theme_region_wrapper.$region");
if (is_null($region_config_values)) {
$region_config_values = [
'element' => NULL,
'classes' => NULL,
'aria_role' => NULL,
];
}
else {
$region_config_values += [
'element' => NULL,
'classes' => NULL,
'aria_role' => NULL,
];
}
$form['region_wrapper'][$region]['label'] = [
'#plain_text' => $label,
];
$form['region_wrapper'][$region]['form'] = [
'element' => [
'#type' => 'select',
'#title' => t('Element'),
'#options' => [
'none' => t('None'),
'div' => 'DIV',
] + $wrapper_elements,
'#default_value' => is_null($region_config_values['element']) ? 'div' : $region_config_values['element'],
'#description' => t('Choose the HTML element to wrap around this region.'),
],
'classes' => [
'#type' => 'textfield',
'#title' => t('CSS classes'),
'#default_value' => is_null($region_config_values['classes']) ? '' : $region_config_values['classes'],
'#description' => t('Separate multiple classes by spaces.'),
'#states' => [
'invisible' => [
":input[name='region_wrapper[$region][form][element]']" => ['value' => 'none'],
],
],
],
'aria_role' => [
'#type' => 'textfield',
'#title' => t('WAI-ARIA role'),
'#default_value' => is_null($region_config_values['aria_role']) ? '' : $region_config_values['aria_role'],
'#size' => 30,
'#description' => t('Specify a role attribute value for this wrapper element.'),
'#states' => [
'invisible' => [
":input[name='region_wrapper[$region][form][element]']" => [
['value' => 'none'],
'or',
['value' => 'main'],
'or',
['value' => 'nav'],
'or',
['value' => 'template'],
],
],
],
],
];
}
}
}
/**
* Form validation handler for theme settings form.
*/
function theme_region_wrapper_scheme_form_validate(array &$form, FormStateInterface $form_state):void {
$regions = $form_state->getValue('region_wrapper');
$aria_prohibited_elements = ['main', 'nav', 'template'];
foreach ($regions as $region => $input_values) {
$element = $input_values['form']['element'] ?? '';
$aria_role = $input_values['form']['aria_role'] ?? '';
if (in_array($element, $aria_prohibited_elements, TRUE) !== FALSE && $aria_role != '') {
$form_name = "region_wrapper][$region][form][element";
$form_state->setErrorByName($form_name, 'Selected element is not permit any ARIA roles.');
}
}
}
/**
* Form submission handler for theme settings form.
*/
function theme_region_wrapper_scheme_form_submit(array &$form, FormStateInterface $form_state):void {
$build_info = $form_state->getBuildInfo();
$theme = $build_info['args'][0];
$regions = $form_state->getValue('region_wrapper');
$theme_config_key = "$theme.settings";
$theme_config = \Drupal::configFactory()->getEditable($theme_config_key);
$new_settings = [];
foreach ($regions as $region => $input_values) {
$region_config_values = $input_values['form'];
$new_settings[$region] = $region_config_values;
}
$theme_config->set("third_party_settings.theme_region_wrapper", $new_settings);
$theme_config->save();
$form_state->unsetValue('region_wrapper');
}
/**
* Implements hook_preprocess_HOOK().
*/
function theme_region_wrapper_preprocess_region(array &$variables):void {
$active_theme = \Drupal::theme()->getActiveTheme()->getName();
$theme_config_key = "$active_theme.settings";
$theme_config = \Drupal::configFactory()->get($theme_config_key);
$region = $variables['region'];
$region_config_values = $theme_config->get("third_party_settings.theme_region_wrapper.$region");
if (is_null($region_config_values)) {
return;
}
if (strlen(trim($region_config_values['classes'])) > 0) {
$classes = explode(' ', trim($region_config_values['classes']));
foreach ($classes as $class) {
$variables['attributes']['class'][] = $class;
}
}
$variables['region_wrapper']['element'] = $region_config_values['element'];
$variables['attributes']['role'] = $region_config_values['aria_role'];
}
