Including security review as a submodule - with patched for Yaffs.
[yaffs-website] / web / modules / contrib / environment_indicator / environment_indicator.module
1 <?php
2
3 /**
4  * @file
5  * Module implementation file.
6  */
7
8 use Drupal\Core\Cache\Cache;
9 use Drupal\Core\Entity\EntityInterface;
10 use Drupal\Core\Routing\RouteMatchInterface;
11 use Drupal\Core\Url;
12 use Drupal\environment_indicator\Entity\EnvironmentIndicator;
13
14 /**
15  * Implements hook_help().
16  */
17 function environment_indicator_help($route_name, RouteMatchInterface $route_match) {
18   switch ($route_name) {
19     case 'environment_indicator.settings':
20       $output = '<p>' . t('The Environment Indicator adds a coloured strip to the site informing you which environment you are currently in (Development, Staging, Production, etc.)') . '</p>';
21       $output .= '<p>' . t('The Environment Indicator\'s visibility depends upon the permissions of the viewer. The <a href="@permissions">access environment indicator</a> permission must be enabled for a user role in order for users of that role to see the indicator.', [
22           '@permissions' => Url::fromRoute('user.admin_permissions', [], ['fragment' => 'module-environment_indicator'])
23             ->toString(),
24         ]) . '</p>';
25       $output .= '<p>'. t('The recommended way to add information about your release is to set the \'environment_indicator.current_release\' state. Use your git hooks to set the state using drush: <code>drush sset environment_indicator.current_release v1.2.44</code>') .'</p>';
26       return $output;
27
28     case 'entity.environment_indicator.collection':
29       $output = '<p>' . t('The environment indicator switcher allows you to create a menu to switch between your environments easily.') . '</p>';
30       $output .= '<p>' . t('You will need to declare all the environments you want to switch. It is advisable that you set your environments in the switcher with the same colors that you use in every environment\'s settings.php.') . '</p>';
31       return $output;
32
33     case 'help.page.environment_indicator':
34       $output = '<p>' . t('The Environment Indicator adds a coloured strip to the site informing you which environment you are currently in (Development, Staging, Production, etc.') . '</p>';
35       $output .= '<p>' . t('The Environment Indicator <a href="@settings">settings page</a> allows you to modify some elements of the indicator\'s behavior and appearance. Since the appearance of the indicator is dependent on your site theme, substantial customisations require modifications to your site\'s theme and CSS files.', ['@settings' => Url::fromRoute('environment_indicator.settings')]) . '</p>';
36       $output .= '<p>' . t('The Environment Indicator\'s visibility depends upon the permissions of the viewer. The <a href="@permissions">access environment indicator</a> permission must be enabled for a user role in order for users of that role to see the indicator.', ['@permissions' => Url::fromRoute('user.admin_permissions', [], ['fragment' => 'module-environment_indicator'])]) . '</p>';
37       $output .= '<p>' . t('Modify the "environment_indicator.indicator" configuration object to control how the environment indicator is presented:') . '</p>';
38       $output .= '<dl>';
39       $output .= '<dt><em>$config[\'environment_indicator.indicator\'][\'bg_color\']</em></dt><dd>' . t('A valid CSS color for the background of the indicator.') . '<br/>$config[\'environment_indicator.indicator\'][\'bg_color\'];<br /></dd></dt>';
40       $output .= '<dt><em>$config[\'environment_indicator.indicator\'][\'fg_color\']</em></dt><dd>' . t('A valid CSS color for the text of the indicator.') . '<br/>$config[\'environment_indicator.indicator\'][\'fg_color\'] = \'#555533\';<br /></dd></dt>';
41       $output .= '<dt><em>$config[\'environment_indicator.indicator\'][\'name\']</em></dt><dd>' . t('The text that will be displayed on the indicator.') . '<br/>$config[\'environment_indicator.indicator\'][\'name\'] = \'Staging\';<br /></dd></dt>';
42       $output .= '</dl>';
43       $output .= '<p>'. t('The recommended way to add information about your release is to set the \'environment_indicator.current_release\' state. Use your git hooks to set the state using drush: <code>drush sset environment_indicator.current_release v1.2.44</code>') .'</p>';
44
45       return $output;
46   }
47
48   return NULL;
49 }
50
51 /**
52  * Implements hook_page_top().
53  */
54 function environment_indicator_page_top(array &$page_top) {
55   if (_environment_indicator_external_integration_is_enabled('toolbar')) {
56     return;
57   }
58   $active_environment = \Drupal::config('environment_indicator.indicator');
59   $page_top['indicator'] = [
60     '#type' => 'environment_indicator',
61     '#title' => $active_environment->get('name'),
62     '#fg_color' => $active_environment->get('fg_color'),
63     '#bg_color' => $active_environment->get('bg_color'),
64     '#description' => \Drupal::state()->get('environment_indicator.current_release'),
65     '#access' => \Drupal::currentUser()
66       ->hasPermission('access environment indicator'),
67     '#attached' => [
68       'library' => ['environment_indicator/drupal.environment_indicator'],
69     ],
70   ];
71
72   // Only add the environment indicator switcher if there are environments to
73   // switch to.
74   if ($items = _environment_indicator_switcher_links()) {
75     $page_top['indicator']['switcher'] = [
76       '#theme' => 'links',
77       '#links' => $items,
78       '#attributes' => [
79         'class' => ['environment-switcher-container'],
80         'style' => 'border-top: 1px solid ' . \Drupal::config('environment_indicator.indicator')
81             ->get('fg_color'),
82       ],
83     ];
84     $page_top['indicator']['#attributes'] = [
85       'style' => 'cursor: pointer',
86       'title' => t('Show the environment switcher.'),
87     ];
88     $page_top['indicator'] += [
89       '#cache' => [
90         'tags' => Cache::mergeTags(['config:environment_indicator.settings'], _environment_indicator_switcher_cache_tags()),
91       ],
92     ];
93   }
94 }
95
96 /**
97  * Implements hook_theme().
98  */
99 function environment_indicator_theme($existing, $type, $theme, $path) {
100   return [
101     'environment_indicator' => [
102       'render element' => 'element',
103     ],
104   ];
105 }
106
107 /**
108  * Prepares variables for environment indicator element templates.
109  *
110  * Default template: environment-indicator.html.twig.
111  *
112  * @param array $variables
113  *   An associative array containing:
114  *   - element: An associative array containing the properties of the element.
115  *     Properties used: #title, #value, #description, #required, #attributes.
116  */
117 function template_preprocess_environment_indicator(&$variables) {
118   $element = $variables['element'];
119   $variables['title'] = empty($element['#title']) ? '' : $element['#title'];
120   $variables['fg_color'] = empty($element['#fg_color']) ? '' : $element['#fg_color'];
121   if (!empty($element['#description'])) {
122     $variables['description'] = $element['#description'];
123   }
124   // Ensure #attributes is set.
125   $element += ['#attributes' => []];
126   $attributes = $element['#attributes'];
127   // Make sure to override existing colors.
128   $style = empty($attributes['style']) ? '' : $attributes['style'];
129   $structured_styles = _environment_indicator_parse_style($style);
130   $structured_styles['background-color'] = empty($element['#bg_color']) ? '' : $element['#bg_color'];
131   $structured_styles['color'] = empty($element['#fg_color']) ? '' : $element['#fg_color'];
132   // Now put everything back together as an string.
133   $data = [];
134   foreach ($structured_styles as $css_property => $css_value) {
135     $data[] = sprintf('%s: %s', $css_property, $css_value);
136   }
137   $attributes['style'] = implode('; ', $data);
138   $attributes['id'] = (empty($attributes['id']) ? (empty($attributes['#id']) ? 'environment-indicator' : $attributes['#id']) : $attributes['id']);
139   $variables['attributes'] = $attributes;
140   $variables['switcher'] = isset($element['switcher']) ? $element['switcher'] : '';
141 }
142
143 /**
144  * Helper function that takes a styles string and parses the individual items.
145  *
146  * @param string $style
147  *   The style string for the HTML element.
148  *
149  * @return array
150  *   An structured array with key value pairs with the CSS properties and their
151  *   values.
152  */
153 function _environment_indicator_parse_style($style) {
154   $structured_styles = [];
155   // Get every individual style.
156   $styles = array_filter(explode(';', $style));
157   foreach ($styles as $item) {
158     list($item_name, $item_value) = explode(':', $item);
159     trim($item_name);
160     trim($item_value);
161     $structured_styles[$item_name] = $item_value;
162   }
163   return $structured_styles;
164 }
165
166 /**
167  * Implements hook_toolbar().
168  */
169 function environment_indicator_toolbar() {
170   $active_environment = \Drupal::config('environment_indicator.indicator');
171   $permission = \Drupal::currentUser()
172     ->hasPermission('access environment indicator');
173   $items['environment_indicator'] = [
174     // Include the toolbar_tab_wrapper to style the link like a toolbar tab.
175     // Exclude the theme wrapper if custom styling is desired.
176     '#type' => 'toolbar_item',
177     '#access' => $permission,
178     '#cache' => [
179       'tags' => Cache::mergeTags(['config:environment_indicator.settings'], _environment_indicator_switcher_cache_tags()),
180     ],
181     '#weight' => 125,
182   ];
183   if (!_environment_indicator_external_integration_is_enabled('toolbar')) {
184     return $items;
185   }
186   $title = $active_environment->get('name');
187   $release_info = \Drupal::state()->get('environment_indicator.current_release');
188   $title = empty($release_info) ? $title : $title . ' (' . $release_info . ')';
189   $items['environment_indicator'] += [
190     'tab' => [
191       '#type' => 'link',
192       '#access' => $permission,
193       '#title' => $title,
194       '#url' => \Drupal\Core\Url::fromRoute('environment_indicator.settings'),
195       '#attributes' => [
196         'title' => t('Environments'),
197         'class' => [
198           'toolbar-icon',
199           'toolbar-item',
200           'toolbar-icon-environment',
201         ],
202       ],
203     ],
204     'tray' => [
205       '#heading' => t('Environment switcher'),
206       '#wrapper_attributes' => [],
207       '#access' => $permission,
208       'configure' => [
209         '#type' => 'link',
210         '#title' => t('Configure'),
211         '#url' => \Drupal\Core\Url::fromRoute('environment_indicator.settings'),
212         '#weight' => 100,
213         '#attributes' => [
214           'title' => t('Environment switcher configuration'),
215           'class' => ['edit-environments'],
216         ],
217       ],
218     ],
219     '#attached' => [
220       'library' => ['environment_indicator/drupal.environment_indicator'],
221       'drupalSettings' => [
222         'environmentIndicator' => [
223           'name' => $active_environment->get('name'),
224           'fgColor' => $active_environment->get('fg_color'),
225           'bgColor' => $active_environment->get('bg_color'),
226           'addFavicon' => \Drupal::config('environment_indicator.settings')
227             ->get('favicon'),
228         ],
229       ],
230     ],
231   ];
232
233   if ($links = _environment_indicator_switcher_toolbar_links()) {
234     $items['environment_indicator']['tray']['links'] = $links;
235   }
236   return $items;
237 }
238
239 /**
240  * Helper function to get the links for the toolbar.
241  *
242  * @return array
243  *   A renderable array for the toolbar tray.
244  */
245 function _environment_indicator_switcher_toolbar_links() {
246   if (!$items = _environment_indicator_switcher_links()) {
247     return [];
248   };
249   $menu = [
250     '#theme' => 'links__toolbar_shortcuts',
251     '#links' => $items,
252     '#attributes' => [
253       'class' => ['toolbar-menu'],
254     ],
255   ];
256   return $menu;
257 }
258
259 /**
260  * Helper function that generates the environment switcher links.
261  *
262  * @return array
263  *   A renderable array with the links.
264  */
265 function _environment_indicator_switcher_links() {
266   if (!$environment_entities = EnvironmentIndicator::loadMultiple()) {
267     return [];
268   }
269   $current = \Drupal\Core\Url::fromRoute('<current>');
270   $current_path = $current->toString();
271   return array_map(function (EnvironmentIndicator $entity) use ($current_path) {
272     return [
273       'attributes' => [
274         'style' => 'color: ' . $entity->getFgColor() . '; background-color: ' . $entity->getBgColor() . ';',
275         'title' => t('Opens the current page in the selected environment.'),
276       ],
277       'title' => t('Open in: @label', ['@label' => $entity->label()]),
278       'url' => \Drupal\Core\Url::fromUri($entity->getUrl() . $current_path),
279       'type' => 'link',
280     ];
281   }, $environment_entities);
282 }
283
284 /**
285  * Helper function that checks if there is external integration.
286  *
287  * @param string $integration
288  *   Name of the integration: toolbar, admin_menu, ...
289  *
290  * @return bool
291  *   TRUE if integration is enabled. FALSE otherwise.
292  */
293 function _environment_indicator_external_integration_is_enabled($integration) {
294   if ($integration == 'toolbar') {
295     $access = \Drupal::moduleHandler()->moduleExists('toolbar');
296     $access = $access && in_array('toolbar', \Drupal::config('environment_indicator.settings')
297         ->get('toolbar_integration'));
298     $access = $access && \Drupal::currentUser()
299         ->hasPermission('access toolbar');
300     return $access;
301   }
302   return FALSE;
303 }
304
305 /**
306  * Get the cache tags for the environment indicator switcher.
307  *
308  * @return string[]
309  *   The cache tags.
310  */
311 function _environment_indicator_switcher_cache_tags() {
312   /* @var EnvironmentIndicator[] $environment_entities */
313   if (!$environment_entities = EnvironmentIndicator::loadMultiple()) {
314     return [];
315   }
316
317   $cache_tags = [];
318   foreach ($environment_entities as $entity) {
319     $cache_tags = Cache::mergeTags($cache_tags, $entity->getCacheTags());
320   }
321
322   return $cache_tags;
323 }
324
325 /**
326  * Loads an environment indicator in a procedural way.
327  *
328  * @param string $environment_id
329  *   The entity ID.
330  *
331  * @return EntityInterface|null
332  *   The loaded entity or null otherwise.
333  */
334 function environment_indicator_load($environment_id) {
335   return \Drupal::entityTypeManager()
336     ->getStorage('environment_indicator')
337     ->load($environment_id);
338 }