PluginProbe
Gutenberg / 16.6.0
Gutenberg v16.6.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / block-library / blocks / search.php

search.php in Gutenberg 16.6.0, at build/block-library/blocks/search.php

569 lines 22.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/search` block.
4 *
5 * @package WordPress
6 */
7
8 /**
9 * Dynamically renders the `core/search` block.
10 *
11 * @since 6.3.0 Using block.json `viewScript` to register script, and update `view_script_handles()` only when needed.
12 *
13 * @param array $attributes The block attributes.
14 * @param string $content The saved content.
15 * @param WP_Block $block The parsed block.
16 *
17 * @return string The search block markup.
18 */
19 function gutenberg_render_block_core_search( $attributes, $content, $block ) {
20 // Older versions of the Search block defaulted the label and buttonText
21 // attributes to `__( 'Search' )` meaning that many posts contain `<!--
22 // wp:search /-->`. Support these by defaulting an undefined label and
23 // buttonText to `__( 'Search' )`.
24 $attributes = wp_parse_args(
25 $attributes,
26 array(
27 'label' => __( 'Search' ),
28 'buttonText' => __( 'Search' ),
29 )
30 );
31
32 $input_id = wp_unique_id( 'wp-block-search__input-' );
33 $classnames = gutenberg_classnames_for_block_core_search( $attributes );
34 $show_label = ( ! empty( $attributes['showLabel'] ) ) ? true : false;
35 $use_icon_button = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false;
36 $show_button = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true;
37 $button_position = $show_button ? $attributes['buttonPosition'] : null;
38 $query_params = ( ! empty( $attributes['query'] ) ) ? $attributes['query'] : array();
39 $button_behavior = ( ! empty( $attributes['buttonBehavior'] ) ) ? $attributes['buttonBehavior'] : 'default';
40 $button = '';
41 $query_params_markup = '';
42 $inline_styles = gutenberg_styles_for_block_core_search( $attributes );
43 $color_classes = gutenberg_get_color_classes_for_block_core_search( $attributes );
44 $typography_classes = gutenberg_get_typography_classes_for_block_core_search( $attributes );
45 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
46 'button-inside' === $attributes['buttonPosition'];
47 // Border color classes need to be applied to the elements that have a border color.
48 $border_color_classes = gutenberg_get_border_color_classes_for_block_core_search( $attributes );
49
50 $label_inner_html = empty( $attributes['label'] ) ? __( 'Search' ) : wp_kses_post( $attributes['label'] );
51 $label = new WP_HTML_Tag_Processor( sprintf( '<label %1$s>%2$s</label>', $inline_styles['label'], $label_inner_html ) );
52 if ( $label->next_tag() ) {
53 $label->set_attribute( 'for', $input_id );
54 $label->add_class( 'wp-block-search__label' );
55 if ( $show_label && ! empty( $attributes['label'] ) ) {
56 if ( ! empty( $typography_classes ) ) {
57 $label->add_class( $typography_classes );
58 }
59 } else {
60 $label->add_class( 'screen-reader-text' );
61 }
62 }
63
64 $input = new WP_HTML_Tag_Processor( sprintf( '<input type="search" name="s" required %s/>', $inline_styles['input'] ) );
65 $input_classes = array( 'wp-block-search__input' );
66 if ( ! $is_button_inside && ! empty( $border_color_classes ) ) {
67 $input_classes[] = $border_color_classes;
68 }
69 if ( ! empty( $typography_classes ) ) {
70 $input_classes[] = $typography_classes;
71 }
72 if ( $input->next_tag() ) {
73 $input->add_class( implode( ' ', $input_classes ) );
74 $input->set_attribute( 'id', $input_id );
75 $input->set_attribute( 'value', get_search_query() );
76 $input->set_attribute( 'placeholder', $attributes['placeholder'] );
77
78 $is_expandable_searchfield = 'button-only' === $button_position && 'expand-searchfield' === $button_behavior;
79 if ( $is_expandable_searchfield ) {
80 $input->set_attribute( 'aria-hidden', 'true' );
81 $input->set_attribute( 'tabindex', '-1' );
82 }
83
84 // If the script already exists, there is no point in removing it from viewScript.
85 $view_js_file = 'wp-block-search-view';
86 if ( ! wp_script_is( $view_js_file ) ) {
87 $script_handles = $block->block_type->view_script_handles;
88
89 // If the script is not needed, and it is still in the `view_script_handles`, remove it.
90 if ( ! $is_expandable_searchfield && in_array( $view_js_file, $script_handles, true ) ) {
91 $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) );
92 }
93 // If the script is needed, but it was previously removed, add it again.
94 if ( $is_expandable_searchfield && ! in_array( $view_js_file, $script_handles, true ) ) {
95 $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) );
96 }
97 }
98 }
99
100 if ( count( $query_params ) > 0 ) {
101 foreach ( $query_params as $param => $value ) {
102 $query_params_markup .= sprintf(
103 '<input type="hidden" name="%s" value="%s" />',
104 esc_attr( $param ),
105 esc_attr( $value )
106 );
107 }
108 }
109
110 if ( $show_button ) {
111 $button_classes = array( 'wp-block-search__button' );
112 $button_internal_markup = '';
113 if ( ! empty( $color_classes ) ) {
114 $button_classes[] = $color_classes;
115 }
116 if ( ! empty( $typography_classes ) ) {
117 $button_classes[] = $typography_classes;
118 }
119
120 if ( ! $is_button_inside && ! empty( $border_color_classes ) ) {
121 $button_classes[] = $border_color_classes;
122 }
123 if ( ! $use_icon_button ) {
124 if ( ! empty( $attributes['buttonText'] ) ) {
125 $button_internal_markup = wp_kses_post( $attributes['buttonText'] );
126 }
127 } else {
128 $button_classes[] = 'has-icon';
129 $button_internal_markup =
130 '<svg class="search-icon" viewBox="0 0 24 24" width="24" height="24">
131 <path d="M13 5c-3.3 0-6 2.7-6 6 0 1.4.5 2.7 1.3 3.7l-3.8 3.8 1.1 1.1 3.8-3.8c1 .8 2.3 1.3 3.7 1.3 3.3 0 6-2.7 6-6S16.3 5 13 5zm0 10.5c-2.5 0-4.5-2-4.5-4.5s2-4.5 4.5-4.5 4.5 2 4.5 4.5-2 4.5-4.5 4.5z"></path>
132 </svg>';
133 }
134
135 // Include the button element class.
136 $button_classes[] = wp_theme_get_element_class_name( 'button' );
137 $button = new WP_HTML_Tag_Processor( sprintf( '<button type="submit" %s>%s</button>', $inline_styles['button'], $button_internal_markup ) );
138
139 if ( $button->next_tag() ) {
140 $button->add_class( implode( ' ', $button_classes ) );
141 if ( 'expand-searchfield' === $attributes['buttonBehavior'] && 'button-only' === $attributes['buttonPosition'] ) {
142 $button->set_attribute( 'aria-label', __( 'Expand search field' ) );
143 $button->set_attribute( 'data-toggled-aria-label', __( 'Submit Search' ) );
144 $button->set_attribute( 'aria-controls', 'wp-block-search__input-' . $input_id );
145 $button->set_attribute( 'aria-expanded', 'false' );
146 $button->set_attribute( 'type', 'button' ); // Will be set to submit after clicking.
147 } else {
148 $button->set_attribute( 'aria-label', wp_strip_all_tags( $attributes['buttonText'] ) );
149 }
150 }
151 }
152
153 $field_markup_classes = $is_button_inside ? $border_color_classes : '';
154 $field_markup = sprintf(
155 '<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
156 esc_attr( $field_markup_classes ),
157 $inline_styles['wrapper'],
158 $input . $query_params_markup . $button
159 );
160 $wrapper_attributes = get_block_wrapper_attributes(
161 array( 'class' => $classnames )
162 );
163
164 return sprintf(
165 '<form role="search" method="get" action="%s" %s>%s</form>',
166 esc_url( home_url( '/' ) ),
167 $wrapper_attributes,
168 $label . $field_markup
169 );
170 }
171
172 /**
173 * Registers the `core/search` block on the server.
174 */
175 function gutenberg_register_block_core_search() {
176 register_block_type_from_metadata(
177 __DIR__ . '/search',
178 array(
179 'render_callback' => 'gutenberg_render_block_core_search',
180 )
181 );
182 }
183 add_action( 'init', 'gutenberg_register_block_core_search', 20 );
184
185 /**
186 * Builds the correct top level classnames for the 'core/search' block.
187 *
188 * @param array $attributes The block attributes.
189 *
190 * @return string The classnames used in the block.
191 */
192 function gutenberg_classnames_for_block_core_search( $attributes ) {
193 $classnames = array();
194
195 if ( ! empty( $attributes['buttonPosition'] ) ) {
196 if ( 'button-inside' === $attributes['buttonPosition'] ) {
197 $classnames[] = 'wp-block-search__button-inside';
198 }
199
200 if ( 'button-outside' === $attributes['buttonPosition'] ) {
201 $classnames[] = 'wp-block-search__button-outside';
202 }
203
204 if ( 'no-button' === $attributes['buttonPosition'] ) {
205 $classnames[] = 'wp-block-search__no-button';
206 }
207
208 if ( 'button-only' === $attributes['buttonPosition'] ) {
209 $classnames[] = 'wp-block-search__button-only';
210 if ( ! empty( $attributes['buttonBehavior'] ) && 'expand-searchfield' === $attributes['buttonBehavior'] ) {
211 $classnames[] = 'wp-block-search__button-behavior-expand wp-block-search__searchfield-hidden';
212 }
213 }
214 }
215
216 if ( isset( $attributes['buttonUseIcon'] ) ) {
217 if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) {
218 if ( $attributes['buttonUseIcon'] ) {
219 $classnames[] = 'wp-block-search__icon-button';
220 } else {
221 $classnames[] = 'wp-block-search__text-button';
222 }
223 }
224 }
225
226 return implode( ' ', $classnames );
227 }
228
229 /**
230 * This generates a CSS rule for the given border property and side if provided.
231 * Based on whether the Search block is configured to display the button inside
232 * or not, the generated rule is injected into the appropriate collection of
233 * styles for later application in the block's markup.
234 *
235 * @param array $attributes The block attributes.
236 * @param string $property Border property to generate rule for e.g. width or color.
237 * @param string $side Optional side border. The dictates the value retrieved and final CSS property.
238 * @param array $wrapper_styles Current collection of wrapper styles.
239 * @param array $button_styles Current collection of button styles.
240 * @param array $input_styles Current collection of input styles.
241 *
242 * @return void
243 */
244 function gutenberg_apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) {
245 $is_button_inside = 'button-inside' === _wp_array_get( $attributes, array( 'buttonPosition' ), false );
246
247 $path = array( 'style', 'border', $property );
248
249 if ( $side ) {
250 array_splice( $path, 2, 0, $side );
251 }
252
253 $value = _wp_array_get( $attributes, $path, false );
254
255 if ( empty( $value ) ) {
256 return;
257 }
258
259 if ( 'color' === $property && $side ) {
260 $has_color_preset = str_contains( $value, 'var:preset|color|' );
261 if ( $has_color_preset ) {
262 $named_color_value = substr( $value, strrpos( $value, '|' ) + 1 );
263 $value = sprintf( 'var(--wp--preset--color--%s)', $named_color_value );
264 }
265 }
266
267 $property_suffix = $side ? sprintf( '%s-%s', $side, $property ) : $property;
268
269 if ( $is_button_inside ) {
270 $wrapper_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
271 } else {
272 $button_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
273 $input_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
274 }
275 }
276
277 /**
278 * This adds CSS rules for a given border property e.g. width or color. It
279 * injects rules into the provided wrapper, button and input style arrays for
280 * uniform "flat" borders or those with individual sides configured.
281 *
282 * @param array $attributes The block attributes.
283 * @param string $property Border property to generate rule for e.g. width or color.
284 * @param array $wrapper_styles Current collection of wrapper styles.
285 * @param array $button_styles Current collection of button styles.
286 * @param array $input_styles Current collection of input styles.
287 *
288 * @return void
289 */
290 function gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) {
291 gutenberg_apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles );
292 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'top', $wrapper_styles, $button_styles, $input_styles );
293 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'right', $wrapper_styles, $button_styles, $input_styles );
294 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'bottom', $wrapper_styles, $button_styles, $input_styles );
295 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'left', $wrapper_styles, $button_styles, $input_styles );
296 }
297
298 /**
299 * Builds an array of inline styles for the search block.
300 *
301 * The result will contain one entry for shared styles such as those for the
302 * inner input or button and a second for the inner wrapper should the block
303 * be positioning the button "inside".
304 *
305 * @param array $attributes The block attributes.
306 *
307 * @return array Style HTML attribute.
308 */
309 function gutenberg_styles_for_block_core_search( $attributes ) {
310 $wrapper_styles = array();
311 $button_styles = array();
312 $input_styles = array();
313 $label_styles = array();
314 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
315 'button-inside' === $attributes['buttonPosition'];
316 $show_label = ( isset( $attributes['showLabel'] ) ) && false !== $attributes['showLabel'];
317
318 // Add width styles.
319 $has_width = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] );
320
321 if ( $has_width ) {
322 $wrapper_styles[] = sprintf(
323 'width: %d%s;',
324 esc_attr( $attributes['width'] ),
325 esc_attr( $attributes['widthUnit'] )
326 );
327 }
328
329 // Add border width and color styles.
330 gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, 'width', $wrapper_styles, $button_styles, $input_styles );
331 gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, 'color', $wrapper_styles, $button_styles, $input_styles );
332 gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, 'style', $wrapper_styles, $button_styles, $input_styles );
333
334 // Add border radius styles.
335 $has_border_radius = ! empty( $attributes['style']['border']['radius'] );
336
337 if ( $has_border_radius ) {
338 $default_padding = '4px';
339 $border_radius = $attributes['style']['border']['radius'];
340
341 if ( is_array( $border_radius ) ) {
342 // Apply styles for individual corner border radii.
343 foreach ( $border_radius as $key => $value ) {
344 if ( null !== $value ) {
345 // Convert camelCase key to kebab-case.
346 $name = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
347
348 // Add shared styles for individual border radii for input & button.
349 $border_style = sprintf(
350 'border-%s-radius: %s;',
351 esc_attr( $name ),
352 esc_attr( $value )
353 );
354 $input_styles[] = $border_style;
355 $button_styles[] = $border_style;
356
357 // Add adjusted border radius styles for the wrapper element
358 // if button is positioned inside.
359 if ( $is_button_inside && intval( $value ) !== 0 ) {
360 $wrapper_styles[] = sprintf(
361 'border-%s-radius: calc(%s + %s);',
362 esc_attr( $name ),
363 esc_attr( $value ),
364 $default_padding
365 );
366 }
367 }
368 }
369 } else {
370 // Numeric check is for backwards compatibility purposes.
371 $border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
372 $border_style = sprintf( 'border-radius: %s;', esc_attr( $border_radius ) );
373 $input_styles[] = $border_style;
374 $button_styles[] = $border_style;
375
376 if ( $is_button_inside && intval( $border_radius ) !== 0 ) {
377 // Adjust wrapper border radii to maintain visual consistency
378 // with inner elements when button is positioned inside.
379 $wrapper_styles[] = sprintf(
380 'border-radius: calc(%s + %s);',
381 esc_attr( $border_radius ),
382 $default_padding
383 );
384 }
385 }
386 }
387
388 // Add color styles.
389 $has_text_color = ! empty( $attributes['style']['color']['text'] );
390 if ( $has_text_color ) {
391 $button_styles[] = sprintf( 'color: %s;', $attributes['style']['color']['text'] );
392 }
393
394 $has_background_color = ! empty( $attributes['style']['color']['background'] );
395 if ( $has_background_color ) {
396 $button_styles[] = sprintf( 'background-color: %s;', $attributes['style']['color']['background'] );
397 }
398
399 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
400 if ( $has_custom_gradient ) {
401 $button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
402 }
403
404 // Get typography styles to be shared across inner elements.
405 $typography_styles = esc_attr( get_typography_gutenberg_styles_for_block_core_search( $attributes ) );
406 if ( ! empty( $typography_styles ) ) {
407 $label_styles [] = $typography_styles;
408 $button_styles[] = $typography_styles;
409 $input_styles [] = $typography_styles;
410 }
411
412 // Typography text-decoration is only applied to the label and button.
413 if ( ! empty( $attributes['style']['typography']['textDecoration'] ) ) {
414 $text_decoration_value = sprintf( 'text-decoration: %s;', esc_attr( $attributes['style']['typography']['textDecoration'] ) );
415 $button_styles[] = $text_decoration_value;
416 // Input opts out of text decoration.
417 if ( $show_label ) {
418 $label_styles[] = $text_decoration_value;
419 }
420 }
421
422 return array(
423 'input' => ! empty( $input_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $input_styles ) ) ) ) : '',
424 'button' => ! empty( $button_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $button_styles ) ) ) ) : '',
425 'wrapper' => ! empty( $wrapper_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $wrapper_styles ) ) ) ) : '',
426 'label' => ! empty( $label_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $label_styles ) ) ) ) : '',
427 );
428 }
429
430 /**
431 * Returns typography classnames depending on whether there are named font sizes/families .
432 *
433 * @param array $attributes The block attributes.
434 *
435 * @return string The typography color classnames to be applied to the block elements.
436 */
437 function gutenberg_get_typography_classes_for_block_core_search( $attributes ) {
438 $typography_classes = array();
439 $has_named_font_family = ! empty( $attributes['fontFamily'] );
440 $has_named_font_size = ! empty( $attributes['fontSize'] );
441
442 if ( $has_named_font_size ) {
443 $typography_classes[] = sprintf( 'has-%s-font-size', esc_attr( $attributes['fontSize'] ) );
444 }
445
446 if ( $has_named_font_family ) {
447 $typography_classes[] = sprintf( 'has-%s-font-family', esc_attr( $attributes['fontFamily'] ) );
448 }
449
450 return implode( ' ', $typography_classes );
451 }
452
453 /**
454 * Returns typography styles to be included in an HTML style tag.
455 * This excludes text-decoration, which is applied only to the label and button elements of the search block.
456 *
457 * @param array $attributes The block attributes.
458 *
459 * @return string A string of typography CSS declarations.
460 */
461 function get_typography_gutenberg_styles_for_block_core_search( $attributes ) {
462 $typography_styles = array();
463
464 // Add typography styles.
465 if ( ! empty( $attributes['style']['typography']['fontSize'] ) ) {
466 $typography_styles[] = sprintf(
467 'font-size: %s;',
468 gutenberg_get_typography_font_size_value(
469 array(
470 'size' => $attributes['style']['typography']['fontSize'],
471 )
472 )
473 );
474
475 }
476
477 if ( ! empty( $attributes['style']['typography']['fontFamily'] ) ) {
478 $typography_styles[] = sprintf( 'font-family: %s;', $attributes['style']['typography']['fontFamily'] );
479 }
480
481 if ( ! empty( $attributes['style']['typography']['letterSpacing'] ) ) {
482 $typography_styles[] = sprintf( 'letter-spacing: %s;', $attributes['style']['typography']['letterSpacing'] );
483 }
484
485 if ( ! empty( $attributes['style']['typography']['fontWeight'] ) ) {
486 $typography_styles[] = sprintf( 'font-weight: %s;', $attributes['style']['typography']['fontWeight'] );
487 }
488
489 if ( ! empty( $attributes['style']['typography']['fontStyle'] ) ) {
490 $typography_styles[] = sprintf( 'font-style: %s;', $attributes['style']['typography']['fontStyle'] );
491 }
492
493 if ( ! empty( $attributes['style']['typography']['lineHeight'] ) ) {
494 $typography_styles[] = sprintf( 'line-height: %s;', $attributes['style']['typography']['lineHeight'] );
495 }
496
497 if ( ! empty( $attributes['style']['typography']['textTransform'] ) ) {
498 $typography_styles[] = sprintf( 'text-transform: %s;', $attributes['style']['typography']['textTransform'] );
499 }
500
501 return implode( '', $typography_styles );
502 }
503
504 /**
505 * Returns border color classnames depending on whether there are named or custom border colors.
506 *
507 * @param array $attributes The block attributes.
508 *
509 * @return string The border color classnames to be applied to the block elements.
510 */
511 function gutenberg_get_border_color_classes_for_block_core_search( $attributes ) {
512 $border_color_classes = array();
513 $has_custom_border_color = ! empty( $attributes['style']['border']['color'] );
514 $has_named_border_color = ! empty( $attributes['borderColor'] );
515
516 if ( $has_custom_border_color || $has_named_border_color ) {
517 $border_color_classes[] = 'has-border-color';
518 }
519
520 if ( $has_named_border_color ) {
521 $border_color_classes[] = sprintf( 'has-%s-border-color', esc_attr( $attributes['borderColor'] ) );
522 }
523
524 return implode( ' ', $border_color_classes );
525 }
526
527 /**
528 * Returns color classnames depending on whether there are named or custom text and background colors.
529 *
530 * @param array $attributes The block attributes.
531 *
532 * @return string The color classnames to be applied to the block elements.
533 */
534 function gutenberg_get_color_classes_for_block_core_search( $attributes ) {
535 $classnames = array();
536
537 // Text color.
538 $has_named_text_color = ! empty( $attributes['textColor'] );
539 $has_custom_text_color = ! empty( $attributes['style']['color']['text'] );
540 if ( $has_named_text_color ) {
541 $classnames[] = sprintf( 'has-text-color has-%s-color', $attributes['textColor'] );
542 } elseif ( $has_custom_text_color ) {
543 // If a custom 'textColor' was selected instead of a preset, still add the generic `has-text-color` class.
544 $classnames[] = 'has-text-color';
545 }
546
547 // Background color.
548 $has_named_background_color = ! empty( $attributes['backgroundColor'] );
549 $has_custom_background_color = ! empty( $attributes['style']['color']['background'] );
550 $has_named_gradient = ! empty( $attributes['gradient'] );
551 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
552 if (
553 $has_named_background_color ||
554 $has_custom_background_color ||
555 $has_named_gradient ||
556 $has_custom_gradient
557 ) {
558 $classnames[] = 'has-background';
559 }
560 if ( $has_named_background_color ) {
561 $classnames[] = sprintf( 'has-%s-background-color', $attributes['backgroundColor'] );
562 }
563 if ( $has_named_gradient ) {
564 $classnames[] = sprintf( 'has-%s-gradient-background', $attributes['gradient'] );
565 }
566
567 return implode( ' ', $classnames );
568 }
569