4 * Contains \Drupal\bootstrap\Plugin\Form\SystemThemeSettings.
7 namespace Drupal\bootstrap\Plugin\Form;
9 use Drupal\bootstrap\Annotation\BootstrapForm;
10 use Drupal\bootstrap\Bootstrap;
11 use Drupal\bootstrap\Utility\Element;
12 use Drupal\Core\Form\FormStateInterface;
15 * Implements hook_form_system_theme_settings_alter().
17 * @ingroup plugins_form
18 * @ingroup plugins_setting
20 * @BootstrapForm("system_theme_settings")
22 class SystemThemeSettings extends FormBase implements FormInterface {
27 public function alterFormElement(Element $form, FormStateInterface $form_state, $form_id = NULL) {
28 $theme = $this->getTheme($form, $form_state);
33 // Creates the necessary groups (vertical tabs) for a Bootstrap based theme.
34 $this->createGroups($form, $form_state);
36 // Iterate over all setting plugins and add them to the form.
37 foreach ($theme->getSettingPlugin() as $setting) {
38 $setting->alterForm($form->getArray(), $form_state);
43 * Sets up the vertical tab groupings.
45 * @param \Drupal\bootstrap\Utility\Element $form
46 * The Element object that comprises the form.
47 * @param \Drupal\Core\Form\FormStateInterface $form_state
48 * The current state of the form.
50 protected function createGroups(Element $form, FormStateInterface $form_state) {
51 // Vertical tabs for global settings provided by core or contrib modules.
52 if (!isset($form['global'])) {
54 '#type' => 'vertical_tabs',
56 '#prefix' => '<h2><small>' . t('Override Global Settings') . '</small></h2>',
60 // Iterate over existing children and move appropriate ones to global group.
61 foreach ($form->children() as $child) {
62 if ($child->isType(['details', 'fieldset']) && !$child->hasProperty('group')) {
63 $child->setProperty('type', 'details');
64 $child->setProperty('group', 'global');
68 // Provide the necessary default groups.
69 $form['bootstrap'] = [
70 '#type' => 'vertical_tabs',
71 '#attached' => ['library' => ['bootstrap/theme-settings']],
72 '#prefix' => '<h2><small>' . t('Bootstrap Settings') . '</small></h2>',
76 'general' => t('General'),
77 'components' => t('Components'),
78 'javascript' => t('JavaScript'),
79 'advanced' => t('Advanced'),
81 foreach ($groups as $group => $title) {
85 '#group' => 'bootstrap',
91 * Retrieves the currently selected theme on the settings form.
93 * @param \Drupal\bootstrap\Utility\Element $form
94 * The Element object that comprises the form.
95 * @param \Drupal\Core\Form\FormStateInterface $form_state
96 * The current state of the form.
98 * @return \Drupal\bootstrap\Theme|FALSE
99 * The currently selected theme object or FALSE if not a Bootstrap theme.
101 public static function getTheme(Element $form, FormStateInterface $form_state) {
102 $build_info = $form_state->getBuildInfo();
103 $theme = isset($build_info['args'][0]) ? Bootstrap::getTheme($build_info['args'][0]) : FALSE;
105 // Do not continue if the theme is not Bootstrap specific.
106 if (!$theme || !$theme->isBootstrap()) {
107 unset($form['#submit'][0]);
108 unset($form['#validate'][0]);
117 public static function submitFormElement(Element $form, FormStateInterface $form_state) {
118 $theme = self::getTheme($form, $form_state);
125 $settings = $theme->settings();
127 // Iterate over all setting plugins and manually save them since core's
128 // process is severely limiting and somewhat broken.
129 foreach ($theme->getSettingPlugin() as $name => $setting) {
130 // Allow the setting to participate in the form submission process.
131 // Must call the "submitForm" method in case any setting actually uses it.
132 // It should, in turn, invoke "submitFormElement", if the setting that
133 // overrides it is implemented properly.
134 $setting->submitForm($form->getArray(), $form_state);
136 // Retrieve the submitted value.
137 $value = $form_state->getValue($name);
139 // Determine if the setting has a new value that overrides the original.
140 // Ignore the schemas "setting" because it's handled by UpdateManager.
141 if ($name !== 'schemas' && $settings->overridesValue($name, $value)) {
142 // Set the new value.
143 $settings->set($name, $value);
145 // Retrieve the cache tags for the setting.
146 $cache_tags = array_unique(array_merge($setting->getCacheTags()));
152 // Remove value from the form state object so core doesn't re-save it.
153 $form_state->unsetValue($name);
156 // Save the settings, if needed.
160 // Invalidate necessary cache tags.
162 \Drupal::service('cache_tags.invalidator')->invalidateTags($cache_tags);
165 // Clear our internal theme cache so it can be rebuilt properly.
166 $theme->getCache('settings')->deleteAll();
173 public static function validateFormElement(Element $form, FormStateInterface $form_state) {
174 $theme = self::getTheme($form, $form_state);
179 // Iterate over all setting plugins and allow them to participate.
180 foreach ($theme->getSettingPlugin() as $setting) {
181 // Allow the setting to participate in the form validation process.
182 // Must call the "validateForm" method in case any setting actually uses it.
183 // It should, in turn, invoke "validateFormElement", if the setting that
184 // overrides it is implemented properly.
185 $setting->validateForm($form->getArray(), $form_state);