Updated the Bootstrap theme.
[yaffs-website] / web / themes / contrib / bootstrap / src / Plugin / Form / SystemThemeSettings.php
1 <?php
2
3 namespace Drupal\bootstrap\Plugin\Form;
4
5 use Drupal\bootstrap\Bootstrap;
6 use Drupal\bootstrap\Plugin\Setting\DeprecatedSettingInterface;
7 use Drupal\bootstrap\Utility\Element;
8 use Drupal\Core\Form\FormStateInterface;
9
10 /**
11  * Implements hook_form_system_theme_settings_alter().
12  *
13  * @ingroup plugins_form
14  * @ingroup plugins_setting
15  *
16  * @BootstrapForm("system_theme_settings")
17  */
18 class SystemThemeSettings extends FormBase implements FormInterface {
19
20   /**
21    * {@inheritdoc}
22    */
23   public function alterFormElement(Element $form, FormStateInterface $form_state, $form_id = NULL) {
24     $theme = $this->getTheme($form, $form_state);
25     if (!$theme) {
26       return;
27     }
28
29     // Creates the necessary groups (vertical tabs) for a Bootstrap based theme.
30     $this->createGroups($form, $form_state);
31
32     // Iterate over all setting plugins and add them to the form.
33     foreach ($theme->getSettingPlugin() as $setting) {
34       $setting->alterForm($form->getArray(), $form_state);
35     }
36   }
37
38   /**
39    * Sets up the vertical tab groupings.
40    *
41    * @param \Drupal\bootstrap\Utility\Element $form
42    *   The Element object that comprises the form.
43    * @param \Drupal\Core\Form\FormStateInterface $form_state
44    *   The current state of the form.
45    */
46   protected function createGroups(Element $form, FormStateInterface $form_state) {
47     // Vertical tabs for global settings provided by core or contrib modules.
48     if (!isset($form['global'])) {
49       $form['global'] = [
50         '#type' => 'vertical_tabs',
51         '#weight' => -9,
52         '#prefix' => '<h2><small>' . t('Override Global Settings') . '</small></h2>',
53       ];
54     }
55
56     // Iterate over existing children and move appropriate ones to global group.
57     foreach ($form->children() as $child) {
58       if ($child->isType(['details', 'fieldset']) && !$child->hasProperty('group')) {
59         $child->setProperty('type', 'details');
60         $child->setProperty('group', 'global');
61       }
62     }
63
64     // Provide the necessary default groups.
65     $form['bootstrap'] = [
66       '#type' => 'vertical_tabs',
67       '#attached' => ['library' => ['bootstrap/theme-settings']],
68       '#prefix' => '<h2><small>' . t('Bootstrap Settings') . '</small></h2>',
69       '#weight' => -10,
70     ];
71     $groups = [
72       'general' => t('General'),
73       'components' => t('Components'),
74       'javascript' => t('JavaScript'),
75       'advanced' => t('Advanced'),
76     ];
77     foreach ($groups as $group => $title) {
78       $form[$group] = [
79         '#type' => 'details',
80         '#title' => $title,
81         '#group' => 'bootstrap',
82       ];
83     }
84   }
85
86   /**
87    * Retrieves the currently selected theme on the settings form.
88    *
89    * @param \Drupal\bootstrap\Utility\Element $form
90    *   The Element object that comprises the form.
91    * @param \Drupal\Core\Form\FormStateInterface $form_state
92    *   The current state of the form.
93    *
94    * @return \Drupal\bootstrap\Theme|false
95    *   The currently selected theme object or FALSE if not a Bootstrap theme.
96    */
97   public static function getTheme(Element $form, FormStateInterface $form_state) {
98     $build_info = $form_state->getBuildInfo();
99     $theme = isset($build_info['args'][0]) ? Bootstrap::getTheme($build_info['args'][0]) : FALSE;
100
101     // Do not continue if the theme is not Bootstrap specific.
102     if (!$theme || !$theme->isBootstrap()) {
103       unset($form['#submit'][0]);
104       unset($form['#validate'][0]);
105     }
106
107     return $theme;
108   }
109
110   /**
111    * {@inheritdoc}
112    */
113   public static function submitFormElement(Element $form, FormStateInterface $form_state) {
114     $theme = self::getTheme($form, $form_state);
115     if (!$theme) {
116       return;
117     }
118
119     $cache_tags = [];
120     $save = FALSE;
121     $settings = $theme->settings();
122
123     // Iterate over all setting plugins and manually save them since core's
124     // process is severely limiting and somewhat broken.
125     foreach ($theme->getSettingPlugin() as $name => $setting) {
126       // Skip saving deprecated settings.
127       if ($setting instanceof DeprecatedSettingInterface) {
128         $form_state->unsetValue($name);
129         continue;
130       }
131
132       // Allow the setting to participate in the form submission process.
133       // Must call the "submitForm" method in case any setting actually uses it.
134       // It should, in turn, invoke "submitFormElement", if the setting that
135       // overrides it is implemented properly.
136       $setting->submitForm($form->getArray(), $form_state);
137
138       // Retrieve the submitted value.
139       $value = $form_state->getValue($name);
140
141       // Determine if the setting has a new value that overrides the original.
142       // Ignore the schemas "setting" because it's handled by UpdateManager.
143       if ($name !== 'schemas' && $settings->overridesValue($name, $value)) {
144         // Set the new value.
145         $settings->set($name, $value);
146
147         // Retrieve the cache tags for the setting.
148         $cache_tags = array_unique(array_merge($setting->getCacheTags()));
149
150         // Flag the save.
151         $save = TRUE;
152       }
153
154       // Remove value from the form state object so core doesn't re-save it.
155       $form_state->unsetValue($name);
156     }
157
158     // Save the settings, if needed.
159     if ($save) {
160       $settings->save();
161
162       // Invalidate necessary cache tags.
163       if ($cache_tags) {
164         \Drupal::service('cache_tags.invalidator')->invalidateTags($cache_tags);
165       }
166
167       // Clear our internal theme cache so it can be rebuilt properly.
168       $theme->getCache('settings')->deleteAll();
169     }
170   }
171
172   /**
173    * {@inheritdoc}
174    */
175   public static function validateFormElement(Element $form, FormStateInterface $form_state) {
176     $theme = self::getTheme($form, $form_state);
177     if (!$theme) {
178       return;
179     }
180
181     // Iterate over all setting plugins and allow them to participate.
182     foreach ($theme->getSettingPlugin() as $setting) {
183       // Allow the setting to participate in the form validation process.
184       // Must call the "validateForm" method in case any setting actually uses
185       // it. It should, in turn, invoke "validateFormElement", if the setting
186       // that overrides it is implemented properly.
187       $setting->validateForm($form->getArray(), $form_state);
188     }
189   }
190
191 }