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