PluginProbe
Gutenberg / 18.9.0
Gutenberg v18.9.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 18.9.0, at build/block-library/blocks/search.php

616 lines 23.2 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 ) {
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 = '';
40 $query_params_markup = '';
41 $inline_styles = gutenberg_styles_for_block_core_search( $attributes );
42 $color_classes = gutenberg_get_color_classes_for_block_core_search( $attributes );
43 $typography_classes = gutenberg_get_typography_classes_for_block_core_search( $attributes );
44 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
45 'button-inside' === $attributes['buttonPosition'];
46 // Border color classes need to be applied to the elements that have a border color.
47 $border_color_classes = gutenberg_get_border_color_classes_for_block_core_search( $attributes );
48 // This variable is a constant and its value is always false at this moment.
49 // It is defined this way because some values depend on it, in case it changes in the future.
50 $open_by_default = false;
51
52 $label_inner_html = empty( $attributes['label'] ) ? __( 'Search' ) : wp_kses_post( $attributes['label'] );
53 $label = new WP_HTML_Tag_Processor( sprintf( '<label %1$s>%2$s</label>', $inline_styles['label'], $label_inner_html ) );
54 if ( $label->next_tag() ) {
55 $label->set_attribute( 'for', $input_id );
56 $label->add_class( 'wp-block-search__label' );
57 if ( $show_label && ! empty( $attributes['label'] ) ) {
58 if ( ! empty( $typography_classes ) ) {
59 $label->add_class( $typography_classes );
60 }
61 } else {
62 $label->add_class( 'screen-reader-text' );
63 }
64 }
65
66 $input = new WP_HTML_Tag_Processor( sprintf( '<input type="search" name="s" required %s/>', $inline_styles['input'] ) );
67 $input_classes = array( 'wp-block-search__input' );
68 if ( ! $is_button_inside && ! empty( $border_color_classes ) ) {
69 $input_classes[] = $border_color_classes;
70 }
71 if ( ! empty( $typography_classes ) ) {
72 $input_classes[] = $typography_classes;
73 }
74 if ( $input->next_tag() ) {
75 $input->add_class( implode( ' ', $input_classes ) );
76 $input->set_attribute( 'id', $input_id );
77 $input->set_attribute( 'value', get_search_query() );
78 $input->set_attribute( 'placeholder', $attributes['placeholder'] );
79
80 // If it's interactive, enqueue the script module and add the directives.
81 $is_expandable_searchfield = 'button-only' === $button_position;
82 if ( $is_expandable_searchfield ) {
83 $suffix = wp_scripts_get_suffix();
84 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
85 $module_url = gutenberg_url( '/build/interactivity/search.min.js' );
86 }
87
88 wp_register_script_module(
89 '@wordpress/block-library/search',
90 isset( $module_url ) ? $module_url : includes_url( "blocks/search/view{$suffix}.js" ),
91 array( '@wordpress/interactivity' ),
92 defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
93 );
94 wp_enqueue_script_module( '@wordpress/block-library/search' );
95
96 $input->set_attribute( 'data-wp-bind--aria-hidden', '!context.isSearchInputVisible' );
97 $input->set_attribute( 'data-wp-bind--tabindex', 'state.tabindex' );
98
99 // Adding these attributes manually is needed until the Interactivity API
100 // SSR logic is added to core.
101 $input->set_attribute( 'aria-hidden', 'true' );
102 $input->set_attribute( 'tabindex', '-1' );
103 }
104 }
105
106 if ( count( $query_params ) > 0 ) {
107 foreach ( $query_params as $param => $value ) {
108 $query_params_markup .= sprintf(
109 '<input type="hidden" name="%s" value="%s" />',
110 esc_attr( $param ),
111 esc_attr( $value )
112 );
113 }
114 }
115
116 if ( $show_button ) {
117 $button_classes = array( 'wp-block-search__button' );
118 $button_internal_markup = '';
119 if ( ! empty( $color_classes ) ) {
120 $button_classes[] = $color_classes;
121 }
122 if ( ! empty( $typography_classes ) ) {
123 $button_classes[] = $typography_classes;
124 }
125
126 if ( ! $is_button_inside && ! empty( $border_color_classes ) ) {
127 $button_classes[] = $border_color_classes;
128 }
129 if ( ! $use_icon_button ) {
130 if ( ! empty( $attributes['buttonText'] ) ) {
131 $button_internal_markup = wp_kses_post( $attributes['buttonText'] );
132 }
133 } else {
134 $button_classes[] = 'has-icon';
135 $button_internal_markup =
136 '<svg class="search-icon" viewBox="0 0 24 24" width="24" height="24">
137 <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>
138 </svg>';
139 }
140
141 // Include the button element class.
142 $button_classes[] = wp_theme_get_element_class_name( 'button' );
143 $button = new WP_HTML_Tag_Processor( sprintf( '<button type="submit" %s>%s</button>', $inline_styles['button'], $button_internal_markup ) );
144
145 if ( $button->next_tag() ) {
146 $button->add_class( implode( ' ', $button_classes ) );
147 if ( 'button-only' === $attributes['buttonPosition'] ) {
148 $button->set_attribute( 'data-wp-bind--aria-label', 'state.ariaLabel' );
149 $button->set_attribute( 'data-wp-bind--aria-controls', 'state.ariaControls' );
150 $button->set_attribute( 'data-wp-bind--aria-expanded', 'context.isSearchInputVisible' );
151 $button->set_attribute( 'data-wp-bind--type', 'state.type' );
152 $button->set_attribute( 'data-wp-on--click', 'actions.openSearchInput' );
153
154 // Adding these attributes manually is needed until the Interactivity
155 // API SSR logic is added to core.
156 $button->set_attribute( 'aria-label', __( 'Expand search field' ) );
157 $button->set_attribute( 'aria-controls', 'wp-block-search__input-' . $input_id );
158 $button->set_attribute( 'aria-expanded', 'false' );
159 $button->set_attribute( 'type', 'button' );
160 } else {
161 $button->set_attribute( 'aria-label', wp_strip_all_tags( $attributes['buttonText'] ) );
162 }
163 }
164 }
165
166 $field_markup_classes = $is_button_inside ? $border_color_classes : '';
167 $field_markup = sprintf(
168 '<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
169 esc_attr( $field_markup_classes ),
170 $inline_styles['wrapper'],
171 $input . $query_params_markup . $button
172 );
173 $wrapper_attributes = get_block_wrapper_attributes(
174 array( 'class' => $classnames )
175 );
176 $form_directives = '';
177
178 // If it's interactive, add the directives.
179 if ( $is_expandable_searchfield ) {
180 $aria_label_expanded = __( 'Submit Search' );
181 $aria_label_collapsed = __( 'Expand search field' );
182 $form_context = wp_interactivity_data_wp_context(
183 array(
184 'isSearchInputVisible' => $open_by_default,
185 'inputId' => $input_id,
186 'ariaLabelExpanded' => $aria_label_expanded,
187 'ariaLabelCollapsed' => $aria_label_collapsed,
188 )
189 );
190 $form_directives = '
191 data-wp-interactive="core/search"'
192 . $form_context .
193 'data-wp-class--wp-block-search__searchfield-hidden="!context.isSearchInputVisible"
194 data-wp-on-async--keydown="actions.handleSearchKeydown"
195 data-wp-on-async--focusout="actions.handleSearchFocusout"
196 ';
197 }
198
199 return sprintf(
200 '<form role="search" method="get" action="%1s" %2s %3s>%4s</form>',
201 esc_url( home_url( '/' ) ),
202 $wrapper_attributes,
203 $form_directives,
204 $label . $field_markup
205 );
206 }
207
208 /**
209 * Registers the `core/search` block on the server.
210 *
211 * @since 5.2.0
212 */
213 function gutenberg_register_block_core_search() {
214 register_block_type_from_metadata(
215 __DIR__ . '/search',
216 array(
217 'render_callback' => 'gutenberg_render_block_core_search',
218 )
219 );
220 }
221 add_action( 'init', 'gutenberg_register_block_core_search', 20 );
222
223 /**
224 * Builds the correct top level classnames for the 'core/search' block.
225 *
226 * @since 5.6.0
227 *
228 * @param array $attributes The block attributes.
229 *
230 * @return string The classnames used in the block.
231 */
232 function gutenberg_classnames_for_block_core_search( $attributes ) {
233 $classnames = array();
234
235 if ( ! empty( $attributes['buttonPosition'] ) ) {
236 if ( 'button-inside' === $attributes['buttonPosition'] ) {
237 $classnames[] = 'wp-block-search__button-inside';
238 }
239
240 if ( 'button-outside' === $attributes['buttonPosition'] ) {
241 $classnames[] = 'wp-block-search__button-outside';
242 }
243
244 if ( 'no-button' === $attributes['buttonPosition'] ) {
245 $classnames[] = 'wp-block-search__no-button';
246 }
247
248 if ( 'button-only' === $attributes['buttonPosition'] ) {
249 $classnames[] = 'wp-block-search__button-only wp-block-search__searchfield-hidden';
250 }
251 }
252
253 if ( isset( $attributes['buttonUseIcon'] ) ) {
254 if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) {
255 if ( $attributes['buttonUseIcon'] ) {
256 $classnames[] = 'wp-block-search__icon-button';
257 } else {
258 $classnames[] = 'wp-block-search__text-button';
259 }
260 }
261 }
262
263 return implode( ' ', $classnames );
264 }
265
266 /**
267 * This generates a CSS rule for the given border property and side if provided.
268 * Based on whether the Search block is configured to display the button inside
269 * or not, the generated rule is injected into the appropriate collection of
270 * styles for later application in the block's markup.
271 *
272 * @since 6.1.0
273 *
274 * @param array $attributes The block attributes.
275 * @param string $property Border property to generate rule for e.g. width or color.
276 * @param string $side Optional side border. The dictates the value retrieved and final CSS property.
277 * @param array $wrapper_styles Current collection of wrapper styles.
278 * @param array $button_styles Current collection of button styles.
279 * @param array $input_styles Current collection of input styles.
280 */
281 function gutenberg_apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) {
282 $is_button_inside = isset( $attributes['buttonPosition'] ) && 'button-inside' === $attributes['buttonPosition'];
283
284 $path = array( 'style', 'border', $property );
285
286 if ( $side ) {
287 array_splice( $path, 2, 0, $side );
288 }
289
290 $value = _wp_array_get( $attributes, $path, false );
291
292 if ( empty( $value ) ) {
293 return;
294 }
295
296 if ( 'color' === $property && $side ) {
297 $has_color_preset = str_contains( $value, 'var:preset|color|' );
298 if ( $has_color_preset ) {
299 $named_color_value = substr( $value, strrpos( $value, '|' ) + 1 );
300 $value = sprintf( 'var(--wp--preset--color--%s)', $named_color_value );
301 }
302 }
303
304 $property_suffix = $side ? sprintf( '%s-%s', $side, $property ) : $property;
305
306 if ( $is_button_inside ) {
307 $wrapper_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
308 } else {
309 $button_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
310 $input_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
311 }
312 }
313
314 /**
315 * This adds CSS rules for a given border property e.g. width or color. It
316 * injects rules into the provided wrapper, button and input style arrays for
317 * uniform "flat" borders or those with individual sides configured.
318 *
319 * @since 6.1.0
320 *
321 * @param array $attributes The block attributes.
322 * @param string $property Border property to generate rule for e.g. width or color.
323 * @param array $wrapper_styles Current collection of wrapper styles.
324 * @param array $button_styles Current collection of button styles.
325 * @param array $input_styles Current collection of input styles.
326 */
327 function gutenberg_apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) {
328 gutenberg_apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles );
329 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'top', $wrapper_styles, $button_styles, $input_styles );
330 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'right', $wrapper_styles, $button_styles, $input_styles );
331 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'bottom', $wrapper_styles, $button_styles, $input_styles );
332 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'left', $wrapper_styles, $button_styles, $input_styles );
333 }
334
335 /**
336 * Builds an array of inline styles for the search block.
337 *
338 * The result will contain one entry for shared styles such as those for the
339 * inner input or button and a second for the inner wrapper should the block
340 * be positioning the button "inside".
341 *
342 * @since 5.8.0
343 *
344 * @param array $attributes The block attributes.
345 *
346 * @return array Style HTML attribute.
347 */
348 function gutenberg_styles_for_block_core_search( $attributes ) {
349 $wrapper_styles = array();
350 $button_styles = array();
351 $input_styles = array();
352 $label_styles = array();
353 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
354 'button-inside' === $attributes['buttonPosition'];
355 $show_label = ( isset( $attributes['showLabel'] ) ) && false !== $attributes['showLabel'];
356
357 // Add width styles.
358 $has_width = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] );
359
360 if ( $has_width ) {
361 $wrapper_styles[] = sprintf(
362 'width: %d%s;',
363 esc_attr( $attributes['width'] ),
364 esc_attr( $attributes['widthUnit'] )
365 );
366 }
367
368 // Add border width and color styles.
369 gutenberg_apply_block_core_search_border_styles( $attributes, 'width', $wrapper_styles, $button_styles, $input_styles );
370 gutenberg_apply_block_core_search_border_styles( $attributes, 'color', $wrapper_styles, $button_styles, $input_styles );
371 gutenberg_apply_block_core_search_border_styles( $attributes, 'style', $wrapper_styles, $button_styles, $input_styles );
372
373 // Add border radius styles.
374 $has_border_radius = ! empty( $attributes['style']['border']['radius'] );
375
376 if ( $has_border_radius ) {
377 $default_padding = '4px';
378 $border_radius = $attributes['style']['border']['radius'];
379
380 if ( is_array( $border_radius ) ) {
381 // Apply styles for individual corner border radii.
382 foreach ( $border_radius as $key => $value ) {
383 if ( null !== $value ) {
384 // Convert camelCase key to kebab-case.
385 $name = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
386
387 // Add shared styles for individual border radii for input & button.
388 $border_style = sprintf(
389 'border-%s-radius: %s;',
390 esc_attr( $name ),
391 esc_attr( $value )
392 );
393 $input_styles[] = $border_style;
394 $button_styles[] = $border_style;
395
396 // Add adjusted border radius styles for the wrapper element
397 // if button is positioned inside.
398 if ( $is_button_inside && intval( $value ) !== 0 ) {
399 $wrapper_styles[] = sprintf(
400 'border-%s-radius: calc(%s + %s);',
401 esc_attr( $name ),
402 esc_attr( $value ),
403 $default_padding
404 );
405 }
406 }
407 }
408 } else {
409 // Numeric check is for backwards compatibility purposes.
410 $border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
411 $border_style = sprintf( 'border-radius: %s;', esc_attr( $border_radius ) );
412 $input_styles[] = $border_style;
413 $button_styles[] = $border_style;
414
415 if ( $is_button_inside && intval( $border_radius ) !== 0 ) {
416 // Adjust wrapper border radii to maintain visual consistency
417 // with inner elements when button is positioned inside.
418 $wrapper_styles[] = sprintf(
419 'border-radius: calc(%s + %s);',
420 esc_attr( $border_radius ),
421 $default_padding
422 );
423 }
424 }
425 }
426
427 // Add color styles.
428 $has_text_color = ! empty( $attributes['style']['color']['text'] );
429 if ( $has_text_color ) {
430 $button_styles[] = sprintf( 'color: %s;', $attributes['style']['color']['text'] );
431 }
432
433 $has_background_color = ! empty( $attributes['style']['color']['background'] );
434 if ( $has_background_color ) {
435 $button_styles[] = sprintf( 'background-color: %s;', $attributes['style']['color']['background'] );
436 }
437
438 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
439 if ( $has_custom_gradient ) {
440 $button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
441 }
442
443 // Get typography styles to be shared across inner elements.
444 $typography_styles = esc_attr( get_typography_gutenberg_styles_for_block_core_search( $attributes ) );
445 if ( ! empty( $typography_styles ) ) {
446 $label_styles [] = $typography_styles;
447 $button_styles[] = $typography_styles;
448 $input_styles [] = $typography_styles;
449 }
450
451 // Typography text-decoration is only applied to the label and button.
452 if ( ! empty( $attributes['style']['typography']['textDecoration'] ) ) {
453 $text_decoration_value = sprintf( 'text-decoration: %s;', esc_attr( $attributes['style']['typography']['textDecoration'] ) );
454 $button_styles[] = $text_decoration_value;
455 // Input opts out of text decoration.
456 if ( $show_label ) {
457 $label_styles[] = $text_decoration_value;
458 }
459 }
460
461 return array(
462 'input' => ! empty( $input_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $input_styles ) ) ) ) : '',
463 'button' => ! empty( $button_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $button_styles ) ) ) ) : '',
464 'wrapper' => ! empty( $wrapper_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $wrapper_styles ) ) ) ) : '',
465 'label' => ! empty( $label_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $label_styles ) ) ) ) : '',
466 );
467 }
468
469 /**
470 * Returns typography classnames depending on whether there are named font sizes/families.
471 *
472 * @since 6.1.0
473 *
474 * @param array $attributes The block attributes.
475 *
476 * @return string The typography color classnames to be applied to the block elements.
477 */
478 function gutenberg_get_typography_classes_for_block_core_search( $attributes ) {
479 $typography_classes = array();
480 $has_named_font_family = ! empty( $attributes['fontFamily'] );
481 $has_named_font_size = ! empty( $attributes['fontSize'] );
482
483 if ( $has_named_font_size ) {
484 $typography_classes[] = sprintf( 'has-%s-font-size', esc_attr( $attributes['fontSize'] ) );
485 }
486
487 if ( $has_named_font_family ) {
488 $typography_classes[] = sprintf( 'has-%s-font-family', esc_attr( $attributes['fontFamily'] ) );
489 }
490
491 return implode( ' ', $typography_classes );
492 }
493
494 /**
495 * Returns typography styles to be included in an HTML style tag.
496 * This excludes text-decoration, which is applied only to the label and button elements of the search block.
497 *
498 * @since 6.1.0
499 *
500 * @param array $attributes The block attributes.
501 *
502 * @return string A string of typography CSS declarations.
503 */
504 function get_typography_gutenberg_styles_for_block_core_search( $attributes ) {
505 $typography_styles = array();
506
507 // Add typography styles.
508 if ( ! empty( $attributes['style']['typography']['fontSize'] ) ) {
509 $typography_styles[] = sprintf(
510 'font-size: %s;',
511 gutenberg_get_typography_font_size_value(
512 array(
513 'size' => $attributes['style']['typography']['fontSize'],
514 )
515 )
516 );
517
518 }
519
520 if ( ! empty( $attributes['style']['typography']['fontFamily'] ) ) {
521 $typography_styles[] = sprintf( 'font-family: %s;', $attributes['style']['typography']['fontFamily'] );
522 }
523
524 if ( ! empty( $attributes['style']['typography']['letterSpacing'] ) ) {
525 $typography_styles[] = sprintf( 'letter-spacing: %s;', $attributes['style']['typography']['letterSpacing'] );
526 }
527
528 if ( ! empty( $attributes['style']['typography']['fontWeight'] ) ) {
529 $typography_styles[] = sprintf( 'font-weight: %s;', $attributes['style']['typography']['fontWeight'] );
530 }
531
532 if ( ! empty( $attributes['style']['typography']['fontStyle'] ) ) {
533 $typography_styles[] = sprintf( 'font-style: %s;', $attributes['style']['typography']['fontStyle'] );
534 }
535
536 if ( ! empty( $attributes['style']['typography']['lineHeight'] ) ) {
537 $typography_styles[] = sprintf( 'line-height: %s;', $attributes['style']['typography']['lineHeight'] );
538 }
539
540 if ( ! empty( $attributes['style']['typography']['textTransform'] ) ) {
541 $typography_styles[] = sprintf( 'text-transform: %s;', $attributes['style']['typography']['textTransform'] );
542 }
543
544 return implode( '', $typography_styles );
545 }
546
547 /**
548 * Returns border color classnames depending on whether there are named or custom border colors.
549 *
550 * @since 5.9.0
551 *
552 * @param array $attributes The block attributes.
553 *
554 * @return string The border color classnames to be applied to the block elements.
555 */
556 function gutenberg_get_border_color_classes_for_block_core_search( $attributes ) {
557 $border_color_classes = array();
558 $has_custom_border_color = ! empty( $attributes['style']['border']['color'] );
559 $has_named_border_color = ! empty( $attributes['borderColor'] );
560
561 if ( $has_custom_border_color || $has_named_border_color ) {
562 $border_color_classes[] = 'has-border-color';
563 }
564
565 if ( $has_named_border_color ) {
566 $border_color_classes[] = sprintf( 'has-%s-border-color', esc_attr( $attributes['borderColor'] ) );
567 }
568
569 return implode( ' ', $border_color_classes );
570 }
571
572 /**
573 * Returns color classnames depending on whether there are named or custom text and background colors.
574 *
575 * @since 5.9.0
576 *
577 * @param array $attributes The block attributes.
578 *
579 * @return string The color classnames to be applied to the block elements.
580 */
581 function gutenberg_get_color_classes_for_block_core_search( $attributes ) {
582 $classnames = array();
583
584 // Text color.
585 $has_named_text_color = ! empty( $attributes['textColor'] );
586 $has_custom_text_color = ! empty( $attributes['style']['color']['text'] );
587 if ( $has_named_text_color ) {
588 $classnames[] = sprintf( 'has-text-color has-%s-color', $attributes['textColor'] );
589 } elseif ( $has_custom_text_color ) {
590 // If a custom 'textColor' was selected instead of a preset, still add the generic `has-text-color` class.
591 $classnames[] = 'has-text-color';
592 }
593
594 // Background color.
595 $has_named_background_color = ! empty( $attributes['backgroundColor'] );
596 $has_custom_background_color = ! empty( $attributes['style']['color']['background'] );
597 $has_named_gradient = ! empty( $attributes['gradient'] );
598 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
599 if (
600 $has_named_background_color ||
601 $has_custom_background_color ||
602 $has_named_gradient ||
603 $has_custom_gradient
604 ) {
605 $classnames[] = 'has-background';
606 }
607 if ( $has_named_background_color ) {
608 $classnames[] = sprintf( 'has-%s-background-color', $attributes['backgroundColor'] );
609 }
610 if ( $has_named_gradient ) {
611 $classnames[] = sprintf( 'has-%s-gradient-background', $attributes['gradient'] );
612 }
613
614 return implode( ' ', $classnames );
615 }
616