Security update to Drupal 8.4.6
[yaffs-website] / web / core / modules / settings_tray / settings_tray.module
1 <?php
2
3 /**
4  * @file
5  * Allows configuring blocks and other configuration from the site front-end.
6  */
7
8 use Drupal\Core\Asset\AttachedAssetsInterface;
9 use Drupal\Core\Routing\RouteMatchInterface;
10 use Drupal\settings_tray\Block\BlockEntityOffCanvasForm;
11 use Drupal\settings_tray\Form\SystemBrandingOffCanvasForm;
12 use Drupal\settings_tray\Form\SystemMenuOffCanvasForm;
13
14 /**
15  * Implements hook_help().
16  */
17 function settings_tray_help($route_name, RouteMatchInterface $route_match) {
18   switch ($route_name) {
19     case 'help.page.settings_tray':
20       $output = '<h3>' . t('About') . '</h3>';
21       $output .= '<p>' . t('The Settings Tray module provides an \'edit mode\' in which clicking on a block opens a slide-out tray which allows configuration to be altered without leaving the page.For more information, see the <a href=":settings-tray-documentation">online documentation for the Settings Tray module</a>.', [':settings-tray-documentation' => 'https://www.drupal.org/documentation/modules/settings_tray']) . '</p>';
22       $output .= '<h3>' . t('Uses') . '</h3>';
23       $output .= '<dl>';
24       $output .= '<dt>' . t('Editing blocks on the same page in the slide-out tray') . '</dt>';
25       $output .= '</dl>';
26       return ['#markup' => $output];
27   }
28 }
29
30 /**
31  * Implements hook_contextual_links_view_alter().
32  *
33  * Change Configure Blocks into off_canvas links.
34  */
35 function settings_tray_contextual_links_view_alter(&$element, $items) {
36   if (isset($element['#links']['settings-trayblock-configure'])) {
37     // Place settings_tray link first.
38     $settings_tray_link = $element['#links']['settings-trayblock-configure'];
39     unset($element['#links']['settings-trayblock-configure']);
40     $element['#links'] = ['settings-trayblock-configure' => $settings_tray_link] + $element['#links'];
41
42     // If this is content block change title to avoid duplicate "Quick Edit".
43     if (isset($element['#links']['block-contentblock-edit'])) {
44       $element['#links']['settings-trayblock-configure']['title'] = t('Quick edit settings');
45     }
46
47     $element['#attached']['library'][] = 'settings_tray/drupal.off_canvas';
48   }
49 }
50
51 /**
52  * Implements hook_block_view_alter().
53  */
54 function settings_tray_block_view_alter(array &$build) {
55   // Force a new 'data-contextual-id' attribute on blocks when this module is
56   // enabled so as not to reuse stale data cached client-side.
57   // @todo Remove when https://www.drupal.org/node/2773591 is fixed.
58   $build['#contextual_links']['settings_tray'] = [
59     'route_parameters' => [],
60   ];
61 }
62
63 /**
64  * Implements hook_element_info_alter().
65  */
66 function settings_tray_element_info_alter(&$type) {
67   if (isset($type['page'])) {
68     $type['page']['#theme_wrappers']['settings_tray_page_wrapper'] = ['#weight' => -1000];
69   }
70 }
71
72 /**
73  * Implements hook_theme().
74  */
75 function settings_tray_theme() {
76   return [
77     'settings_tray_page_wrapper' => [
78       'variables' => ['children' => NULL],
79     ],
80   ];
81 }
82
83 /**
84  * Implements hook_entity_type_build().
85  */
86 function settings_tray_entity_type_build(array &$entity_types) {
87   /* @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
88   $entity_types['block']
89     ->setFormClass('off_canvas', BlockEntityOffCanvasForm::class)
90     ->setLinkTemplate('off_canvas-form', '/admin/structure/block/manage/{block}/off-canvas');
91 }
92
93 /**
94  * Implements hook_preprocess_HOOK() for block templates.
95  */
96 function settings_tray_preprocess_block(&$variables) {
97   // Only blocks that have an settings_tray form will have a "Quick Edit" link.
98   // We could wait for the contextual links to be initialized on the client
99   // side,  and then add the class and data- attribute below there (via
100   // JavaScript). But that would mean that it would be impossible to show
101   // Settings Tray's clickable regions immediately when the page loads. When
102   // latency is high, this will cause flicker.
103   // @see \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck
104   /** @var \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck $access_checker */
105   $access_checker = \Drupal::service('access_check.settings_tray.block.settings_tray_form');
106   /** @var \Drupal\Core\Block\BlockManagerInterface $block_plugin_manager */
107   $block_plugin_manager = \Drupal::service('plugin.manager.block');
108   /** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */
109   $block_plugin = $block_plugin_manager->createInstance($variables['plugin_id']);
110   if ($access_checker->accessBlockPlugin($block_plugin)->isAllowed()) {
111     // Add class and attributes to all blocks to allow Javascript to target.
112     $variables['attributes']['class'][] = 'settings-tray-editable';
113     $variables['attributes']['data-drupal-settingstray'] = 'editable';
114   }
115 }
116
117 /**
118  * Implements hook_toolbar_alter().
119  *
120  * Alters the 'contextual' toolbar tab if it exists (meaning the user is allowed
121  * to use contextual links) and if they can administer blocks.
122  *
123  * @todo Remove the "administer blocks" requirement in
124  *   https://www.drupal.org/node/2822965.
125  *
126  * @see contextual_toolbar()
127  */
128 function settings_tray_toolbar_alter(&$items) {
129   $items['contextual']['#cache']['contexts'][] = 'user.permissions';
130   if (isset($items['contextual']['tab']) && \Drupal::currentUser()->hasPermission('administer blocks')) {
131     $items['contextual']['#weight'] = -1000;
132     $items['contextual']['#attached']['library'][] = 'settings_tray/drupal.settings_tray';
133     $items['contextual']['tab']['#attributes']['data-drupal-settingstray'] = 'toggle';
134
135     // Set a class on items to mark whether they should be active in edit mode.
136     // @todo Create a dynamic method for modules to set their own items.
137     //   https://www.drupal.org/node/2784589.
138     $edit_mode_items = ['contextual', 'block_place'];
139     foreach ($items as $key => $item) {
140       if (!in_array($key, $edit_mode_items) && (!isset($items[$key]['#wrapper_attributes']['class']) || !in_array('hidden', $items[$key]['#wrapper_attributes']['class']))) {
141         $items[$key]['#wrapper_attributes']['class'][] = 'edit-mode-inactive';
142       }
143     }
144   }
145 }
146
147 /**
148  * Implements hook_block_alter().
149  *
150  * Ensures every block plugin definition has an 'settings_tray' form specified.
151  *
152  * @see \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck
153  */
154 function settings_tray_block_alter(&$definitions) {
155   foreach ($definitions as &$definition) {
156     // If a block plugin already defines its own 'settings_tray' form, use that
157     // form instead of specifying one here.
158     if (isset($definition['forms']['settings_tray'])) {
159       continue;
160     }
161
162     switch ($definition['id']) {
163       // Use specialized forms for certain blocks that do not yet provide the
164       // form with their own annotation.
165       // @todo Move these into the corresponding block plugin annotations in
166       //   https://www.drupal.org/node/2896356.
167       case 'system_menu_block':
168         $definition['forms']['settings_tray'] = SystemMenuOffCanvasForm::class;
169         break;
170
171       case 'system_branding_block':
172         $definition['forms']['settings_tray'] = SystemBrandingOffCanvasForm::class;
173         break;
174
175       // No off-canvas form for the page title block, despite it having
176       // contextual links: it's too confusing that you're editing configuration,
177       // not content, so the title itself cannot actually be changed.
178       // @todo Move these into the corresponding block plugin annotations in
179       //   https://www.drupal.org/node/2896356.
180       case 'page_title_block':
181         $definition['forms']['settings_tray'] = FALSE;
182         break;
183
184       case 'system_main_block':
185         $definition['forms']['settings_tray'] = FALSE;
186         break;
187
188       case 'help_block':
189         $definition['forms']['settings_tray'] = FALSE;
190         break;
191
192       // Otherwise, use the block plugin's normal form rather than
193       // a custom form for Settings Tray.
194       default:
195         $definition['forms']['settings_tray'] = $definition['class'];
196         break;
197     }
198   }
199 }
200
201 /**
202  * Implements hook_css_alter().
203  */
204 function settings_tray_css_alter(&$css, AttachedAssetsInterface $assets) {
205   // @todo Remove once conditional ordering is introduced in
206   //   https://www.drupal.org/node/1945262.
207   $path = drupal_get_path('module', 'settings_tray') . '/css/settings_tray.theme.css';
208   if (isset($css[$path])) {
209     // Use 200 to come after CSS_AGGREGATE_THEME.
210     $css[$path]['group'] = 200;
211   }
212 }