-
Notifications
You must be signed in to change notification settings - Fork 7
/
glisseo.theme
380 lines (342 loc) · 11.2 KB
/
glisseo.theme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
<?php
/**
* @file
* Custom hooks and functions special for theme.
*/
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Twig\TwigFunction;
/**
* Provides macro function to generate BEM classes.
*
* Examples:
*
* @code
* {{ bem('a') }} // a
* @endcode
*
* @code
* {{ bem('a', null, ['b']) }} // a a--b
* @endcode
*
* @code
* {{ bem('a', 'b') }} // a a__b
* @endcode
*
* @code
* {{ bem('a', 'b', ['c', 'd']) }} // a__b a__b--c a__b--d
* @endcode
*
* @param string $block
* The Block name.
* @param string|null $element
* The Element name. If not needed pass empty string or null.
* @param array|null $modifiers
* An array with Block Modifiers.
*
* @return string
* String with classes.
*/
function _glisseo_bem(string $block, string $element = NULL, array $modifiers = NULL) {
$classes = [];
$bem_modifiers = is_array($modifiers) ? $modifiers : [];
$class = $block;
if ($element && strlen($element) > 0) {
$class .= "__{$element}";
}
$classes[] = Html::getClass($class);
if (!empty($bem_modifiers)) {
foreach ($modifiers as $modifier) {
// If NULl value is passed, ignore it to avoid broken classes 'block--'.
if (!is_string($modifier) || strlen($modifier) < 1) {
continue;
}
$classes[] = Html::getClass($class . '--' . $modifier);
}
}
return implode(' ', $classes);
}
/**
* Compose BEM Block class name based passed values.
*
* This is helpful when Block name must be composed from a lot of values, some
* of which is can be NULL or skipped. This is generally helpful when working
* with entities.
*
* @param array $pieces
* The values to build Block name from. Each NULL value will be skipped.
*
* @return string
* The Block class name.
*/
function _glisseo_bem_block(array $pieces) {
$pieces = array_filter($pieces, function ($value) {
return is_string($value) && strlen($value) > 0;
});
$pieces = array_map(function ($value) {
// Remove all leading underscores. This is the case for entities view mode.
// Layout Builder for example uses '_custom' view mode. This is bad name for
// Block generation.
$value = ltrim($value, '_');
return $value;
}, $pieces);
return Html::getClass(implode('-', $pieces));
}
/**
* Implements hook_twig_tweak_functions_alter().
*/
function glisseo_twig_tweak_functions_alter(array &$functions) {
$functions[] = new TwigFunction('bem', '_glisseo_bem');
$functions[] = new TwigFunction('bem_block', '_glisseo_bem_block');
}
/**
* Implements hook_preprocess_HOOK() for block.html.twig.
*/
function glisseo_preprocess_block(array &$variables) {
$elements = $variables['elements'];
// Block ID used for generate BEM class "block--[block_id]".
// If this block used in layout, we handle it a bit different for more
// clean classes.
if (in_array($elements['#base_plugin_id'], [
'extra_field_block',
'field_block',
])) {
$variables['block_id'] = str_replace(':', '-', $elements['#derivative_plugin_id']);
}
elseif (!empty($elements['#id'])) {
$variables['block_id'] = $elements['#id'];
}
elseif (!empty($elements['#derivative_plugin_id'])) {
// Programmatically called plugins will not have id.
$variables['block_id'] = $elements['#derivative_plugin_id'];
}
else {
$variables['block_id'] = $elements['#base_plugin_id'];
}
if ($variables['base_plugin_id'] == 'block_content') {
/** @var \Drupal\block_content\Entity\BlockContent $block_content */
$block_content = $variables['content']['#block_content'];
$variables['block_content_bundle'] = $block_content->bundle();
}
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*
* This hook add new theme hook suggestion for taxonomy terms:
* - taxonomy-term--VIEW.html.twig.
* - taxonomy-term--TYPE--VIEW.html.twig.
* - taxonomy-term--TID--VIEW.html.twig.
*/
function glisseo_theme_suggestions_taxonomy_term_alter(array &$suggestions, $variables, $hook) {
$taxonomy_term = $variables['elements']['#taxonomy_term'];
$view_mode = $variables['elements']['#view_mode'];
array_unshift($suggestions, 'taxonomy_term__' . $view_mode);
// Theme suggestion taxonomy-term--TYPE--VIEW must be inserted right after
// default suggestion taxonomy-term--TYPE.
foreach ($suggestions as $key => $suggestion) {
if ($suggestion == 'taxonomy_term__' . $taxonomy_term->bundle()) {
array_splice($suggestions, $key + 1, 0, 'taxonomy_term__' . $taxonomy_term->bundle() . '__' . $view_mode);
break;
}
}
$suggestions[] = 'taxonomy_term__' . $taxonomy_term->id() . '__' . $view_mode;
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*
* This hook add new theme hook suggestion for paragraphs:
* - paragraph--{ID}--{VIEW_MODE}.html.twig
* - paragraph--{ID}.html.twig
*/
function glisseo_theme_suggestions_paragraph_alter(array &$suggestion, $variables, $hook) {
$paragraph = $variables['elements']['#paragraph'];
$view_mode = $variables['elements']['#view_mode'];
$suggestion[] = 'paragraph__' . $paragraph->id();
$suggestion[] = 'paragraph__' . $paragraph->id() . '__' . $view_mode;
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*
* Add new theme hook suggestion by block content type.
* - block--{BLOCK_TYPE}.html.twig
*/
function glisseo_theme_suggestions_block_alter(array &$suggestions, $variables, $hook) {
if (isset($variables['elements']['content']['#block_content'])) {
array_splice($suggestions, 1, 0, 'block__bundle__' . $variables['elements']['content']['#block_content']->bundle());
}
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*
* Add new theme hook suggestion to comment type.
* - comment--{BUNDLE}--{VIEW_MODE}.html.twig
*/
function glisseo_theme_suggestions_comment_alter(array &$suggestions, array $variables) {
$elements = $variables['elements'];
$comment = $elements['#comment'];
$view_mode = $elements['#view_mode'];
$bundle = $comment->bundle();
$suggestions[] = 'comment__' . $bundle . '__' . $view_mode;
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*
* Adds new theme hook suggestion to user entity.
* - user--{VIEW_MODE}.html.twig.
*/
function glisseo_theme_suggestions_user_alter(array &$suggestions, array $variables) {
$suggestion = [
'user',
$variables['elements']['#view_mode'],
];
$suggestions[] = implode('__', $suggestion);
}
/**
* Implements hook_preprocess_HOOK().
*/
function glisseo_preprocess_field(&$variables) {
$element = $variables['element'];
$variables['entity_type'] = $element['#entity_type'];
$variables['bundle'] = $element['#bundle'];
$variables['view_mode'] = $element['#view_mode'];
// Fix for block view mode. Block template by default has 'full' view mode,
// but inside it field will get default, this will break BEM model and we fix
// it.
if ($variables['entity_type'] == 'block_content' && $variables['view_mode'] == 'default') {
$variables['view_mode'] = 'full';
}
// Sometimes view_mode can be missed and we set it to default.
// e.g. paragraphs_library_item entity.
if (strlen($variables['view_mode']) == 0) {
$variables['view_mode'] = 'default';
}
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*
* Adds new theme suggestions for fields.
* - field--{ENTITY}--{BUNDLE}--{FIELD_NAME}--{ENTITY_ID}.html.twig
* - field--{ENTITY}--{BUNDLE}--{FIELD_NAME}--{VIEW_MODE}.html.twig
*/
function glisseo_theme_suggestions_field_alter(array &$suggestions, array $variables) {
$entity = $variables['element']['#object'];
$suggestion_name = [
'field',
$variables['element']['#entity_type'],
$variables['element']['#bundle'],
$variables['element']['#field_name'],
$variables['element']['#view_mode'],
];
$suggestions[] = implode('__', $suggestion_name);
$suggestion_name = [
'field',
$variables['element']['#entity_type'],
$variables['element']['#bundle'],
$variables['element']['#field_name'],
$entity->id(),
];
$suggestions[] = implode('__', $suggestion_name);
}
/**
* Implements hook_preprocess_HOOK() for details.html.twig.
*/
function glisseo_preprocess_details(array &$variables) {
$element = &$variables['element'];
$variables['name'] = isset($element['#id']) ? preg_replace([
'/^edit\-/',
'/\-\d+$/',
], '', $element['#id']) : '';
}
/**
* Implements hook_element_info_alter().
*
* Add additional processing for some elements.
*/
function glisseo_element_info_alter(array &$types) {
foreach ($types as $name => $element_info) {
// Add process callback to all @FormElement elements.
if (isset($element_info['#input']) && $element_info['#input']) {
$types[$name]['#process'][] = '_glisseo_process_form_element';
}
}
}
/**
* Additional processing for specific form elements.
*
* @todo consider use it or remove.
*/
function _glisseo_process_form_element(array &$element, FormStateInterface $form_state, &$complete_form) {
if (!empty($complete_form['#form_id'])) {
// Add additional variable to element to determine parent form id.
$element['#form_element_form_id'] = $complete_form['#form_id'];
}
return $element;
}
/**
* Implements hook_preprocess().
*/
function glisseo_preprocess(array &$variables, $hook) {
if (isset($variables['element']) && isset($variables['element']['#form_element_form_id'])) {
$variables['form_element_form_id'] = $variables['element']['#form_element_form_id'];
}
}
/**
* Implements hook_preprocess_HOOK() for input.html.twig.
*/
function glisseo_preprocess_input(array &$variables) {
$element = $variables['element'];
$variables['element_type'] = $element['#type'];
if (isset($element['#name'])) {
$variables['element_name'] = $element['#name'];
}
// Remove duplicate classes. We handle them in template.
if ($element['#type'] == 'submit') {
$button_classes = ['button'];
if (isset($element['#button_type'])) {
$variables['button_type'] = $element['#button_type'];
$button_classes[] = 'button--' . Html::getClass($variables['button_type']);
}
$variables['attributes']['class'] = array_filter($variables['attributes']['class'], function ($class) use ($button_classes) {
return !in_array($class, $button_classes);
});
}
}
/**
* Implements hook_preprocess_HOOK() for select.html.twig.
*/
function glisseo_preprocess_select(array &$variables) {
$variables['multiple'] = $variables['element']['#multiple'];
}
/**
* Implements hook_preprocess_HOOK() for user.html.twig.
*/
function glisseo_preprocess_user(array &$variables) {
if (isset($variables['elements']['#view_mode'])) {
$variables['view_mode'] = $variables['elements']['#view_mode'];
}
else {
$variables['view_mode'] = 'default';
}
}
/**
* Implements hook_preprocess_HOOK() for comment.html.twig.
*/
function glisseo_preprocess_comment(array &$variables) {
if (isset($variables['elements']['#view_mode'])) {
$variables['view_mode'] = $variables['elements']['#view_mode'];
}
else {
$variables['view_mode'] = 'default';
}
}
/**
* Implements hook_preprocess_HOOK() for commerce-product.html.twig.
*/
function glisseo_preprocess_commerce_product(array &$variables) {
if (isset($variables['elements']['#view_mode'])) {
$variables['view_mode'] = $variables['elements']['#view_mode'];
}
else {
$variables['view_mode'] = 'default';
}
}