Version 1
[yaffs-website] / web / themes / contrib / bootstrap / src / Plugin / Form / SystemThemeSettings.php
1 <?php
2 /**
3  * @file
4  * Contains \Drupal\bootstrap\Plugin\Form\SystemThemeSettings.
5  */
6
7 namespace Drupal\bootstrap\Plugin\Form;
8
9 use Drupal\bootstrap\Annotation\BootstrapForm;
10 use Drupal\bootstrap\Bootstrap;
11 use Drupal\bootstrap\Utility\Element;
12 use Drupal\Core\Form\FormStateInterface;
13
14 /**
15  * Implements hook_form_system_theme_settings_alter().
16  *
17  * @ingroup plugins_form
18  * @ingroup plugins_setting
19  *
20  * @BootstrapForm("system_theme_settings")
21  */
22 class SystemThemeSettings extends FormBase implements FormInterface {
23
24   /**
25    * {@inheritdoc}
26    */
27   public function alterFormElement(Element $form, FormStateInterface $form_state, $form_id = NULL) {
28     $theme = $this->getTheme($form, $form_state);
29     if (!$theme) {
30       return;
31     }
32
33     // Creates the necessary groups (vertical tabs) for a Bootstrap based theme.
34     $this->createGroups($form, $form_state);
35
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);
39     }
40   }
41
42   /**
43    * Sets up the vertical tab groupings.
44    *
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.
49    */
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'])) {
53       $form['global'] = [
54         '#type' => 'vertical_tabs',
55         '#weight' => -9,
56         '#prefix' => '<h2><small>' . t('Override Global Settings') . '</small></h2>',
57       ];
58     }
59
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');
65       }
66     }
67
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>',
73       '#weight' => -10,
74     ];
75     $groups = [
76       'general' => t('General'),
77       'components' => t('Components'),
78       'javascript' => t('JavaScript'),
79       'advanced' => t('Advanced'),
80     ];
81     foreach ($groups as $group => $title) {
82       $form[$group] = [
83         '#type' => 'details',
84         '#title' => $title,
85         '#group' => 'bootstrap',
86       ];
87     }
88   }
89
90   /**
91    * Retrieves the currently selected theme on the settings form.
92    *
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.
97    *
98    * @return \Drupal\bootstrap\Theme|FALSE
99    *   The currently selected theme object or FALSE if not a Bootstrap theme.
100    */
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;
104
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]);
109     }
110
111     return $theme;
112   }
113
114   /**
115    * {@inheritdoc}
116    */
117   public static function submitFormElement(Element $form, FormStateInterface $form_state) {
118     $theme = self::getTheme($form, $form_state);
119     if (!$theme) {
120       return;
121     }
122
123     $cache_tags = [];
124     $save = FALSE;
125     $settings = $theme->settings();
126
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);
135
136       // Retrieve the submitted value.
137       $value = $form_state->getValue($name);
138
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);
144
145         // Retrieve the cache tags for the setting.
146         $cache_tags = array_unique(array_merge($setting->getCacheTags()));
147
148         // Flag the save.
149         $save = TRUE;
150       }
151
152       // Remove value from the form state object so core doesn't re-save it.
153       $form_state->unsetValue($name);
154     }
155
156     // Save the settings, if needed.
157     if ($save) {
158       $settings->save();
159
160       // Invalidate necessary cache tags.
161       if ($cache_tags) {
162         \Drupal::service('cache_tags.invalidator')->invalidateTags($cache_tags);
163       }
164
165       // Clear our internal theme cache so it can be rebuilt properly.
166       $theme->getCache('settings')->deleteAll();
167     }
168   }
169
170   /**
171    * {@inheritdoc}
172    */
173   public static function validateFormElement(Element $form, FormStateInterface $form_state) {
174     $theme = self::getTheme($form, $form_state);
175     if (!$theme) {
176       return;
177     }
178
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);
186     }
187   }
188
189 }