plus-8.x-4.x-dev/src/Plugin/FormAlter/SystemThemeSettings.php
src/Plugin/FormAlter/SystemThemeSettings.php
<?php namespace Drupal\plus\Plugin\FormAlter; use Drupal\plus\Core\Form\FormAlterInterface; use Drupal\plus\Core\Form\FormSubmitInterface; use Drupal\plus\Core\Form\FormValidateInterface; use Drupal\plus\Plugin\ThemePluginBase; use Drupal\plus\Traits\PluginFormTrait; use Drupal\plus\Utility\ArrayObject; use Drupal\plus\Utility\Element; use Drupal\Core\Form\FormStateInterface; /** * Implements hook_form_system_theme_settings_alter(). * * @ingroup plugins_form_alter * @ingroup plugins_setting * * @FormAlter("system_theme_settings") */ class SystemThemeSettings extends ThemePluginBase implements FormAlterInterface, FormSubmitInterface, FormValidateInterface { use PluginFormTrait; /** * Sets up the vertical tab groupings. * * @param \Drupal\plus\Utility\Element $form * The Element object that comprises the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ protected function createGroups(Element $form, FormStateInterface $form_state) { // Vertical tabs for global settings provided by core or contrib modules. if (!isset($form['global'])) { $form['global'] = [ '#type' => 'vertical_tabs', '#weight' => -9, '#prefix' => '<h2><small>' . t('Override Global Settings') . '</small></h2>', ]; } // Iterate over existing children and move appropriate ones to global group. foreach ($form->children() as $child) { if ($child->isType(['details', 'fieldset']) && !$child->hasProperty('group')) { $child->setProperty('type', 'details'); $child->setProperty('group', 'global'); } } // Provide the necessary default groups. $form['bootstrap'] = [ '#type' => 'vertical_tabs', '#attached' => ['library' => ['bootstrap/theme-settings']], '#prefix' => '<h2><small>' . t('Bootstrap Settings') . '</small></h2>', '#weight' => -10, ]; $groups = [ 'general' => t('General'), 'components' => t('Components'), 'javascript' => t('JavaScript'), 'advanced' => t('Advanced'), ]; foreach ($groups as $group => $title) { $form[$group] = [ '#type' => 'details', '#title' => $title, '#group' => 'bootstrap', ]; } } /** * {@inheritdoc} */ public function formAlter(Element $form, FormStateInterface $form_state, $form_id = NULL) { $theme = $this->getFormTheme($form_state); // Do not continue if the theme is not Plus based. if (!$theme || !$theme->isPlus()) { unset($form['#submit'][0]); unset($form['#formValidate'][0]); return; } // Creates the necessary groups (vertical tabs) for a Bootstrap based theme. $this->createGroups($form, $form_state); // Iterate over all setting plugins and add them to the form. foreach ($theme->getSettingPlugin() as $setting) { if ($setting instanceof FormAlterInterface) { $setting->formAlter($form, $form_state); } } } /** * {@inheritdoc} */ public function formSubmit(Element $form, FormStateInterface $form_state) { $theme = $this->getFormTheme($form_state); if (!$theme) { return; } $cache_tags = new ArrayObject(); $save = FALSE; $settings = $theme->settings(); // Iterate over all setting plugins and manually save them since core's // process is severely limiting and somewhat broken. foreach ($theme->getSettingPlugin() as $name => $setting) { // Allow the setting to participate in the form submission process. if ($setting instanceof FormSubmitInterface) { $setting->formSubmit($form, $form_state); } // Retrieve the submitted value. $value = $form_state->getValue($name); // Determine if the setting has a new value that overrides the original. // Ignore "schemas" setting because it's handled by UpdatePluginManager. if ($name !== 'schemas' && $settings->overridesValue($name, $value)) { // Set the new value. $settings->set($name, $value); // Merge in any cache tags from the setting. $cache_tags->merge($setting->getCacheTags())->unique(); // Flag save. $save = TRUE; } // Remove value from the form state object so core doesn't re-save it. $form_state->unsetValue($name); } // Save the settings, if needed. if ($save) { $settings->save(); // Invalidate necessary cache tags. if ($cache_tags->count()) { \Drupal::service('cache_tags.invalidator')->invalidateTags($cache_tags->getArrayCopy()); } // Clear our internal theme cache so it can be rebuilt properly. $theme->getCache('settings')->deleteAll(); } } /** * {@inheritdoc} */ public function formValidate(Element $form, FormStateInterface $form_state) { $theme = $this->getFormTheme($form_state); if (!$theme) { return; } // Iterate over all setting plugins and allow them to participate. foreach ($theme->getSettingPlugin() as $setting) { // Allow settings to participate in the form validation process. if ($setting instanceof FormValidateInterface) { $setting->formValidate($form, $form_state); } } } /** * Retrieves the currently selected theme on the settings form. * * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @return \Drupal\plus\Plugin\Theme\ThemeInterface|false * The currently selected theme object or FALSE if not a Bootstrap theme. */ public function getFormTheme(FormStateInterface $form_state) { $build_info = $form_state->getBuildInfo(); return isset($build_info['args'][0]) ? $this->plus->getTheme($build_info['args'][0]) : FALSE; } }