wp/wp-includes/blocks/search.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     6  */
     6  */
     7 
     7 
     8 /**
     8 /**
     9  * Dynamically renders the `core/search` block.
     9  * Dynamically renders the `core/search` block.
    10  *
    10  *
    11  * @param array $attributes The block attributes.
    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.
    12  *
    16  *
    13  * @return string The search block markup.
    17  * @return string The search block markup.
    14  */
    18  */
    15 function render_block_core_search( $attributes ) {
    19 function render_block_core_search( $attributes ) {
    16 	static $instance_id = 0;
       
    17 
       
    18 	// Older versions of the Search block defaulted the label and buttonText
    20 	// Older versions of the Search block defaulted the label and buttonText
    19 	// attributes to `__( 'Search' )` meaning that many posts contain `<!--
    21 	// attributes to `__( 'Search' )` meaning that many posts contain `<!--
    20 	// wp:search /-->`. Support these by defaulting an undefined label and
    22 	// wp:search /-->`. Support these by defaulting an undefined label and
    21 	// buttonText to `__( 'Search' )`.
    23 	// buttonText to `__( 'Search' )`.
    22 	$attributes = wp_parse_args(
    24 	$attributes = wp_parse_args(
    25 			'label'      => __( 'Search' ),
    27 			'label'      => __( 'Search' ),
    26 			'buttonText' => __( 'Search' ),
    28 			'buttonText' => __( 'Search' ),
    27 		)
    29 		)
    28 	);
    30 	);
    29 
    31 
    30 	$input_id         = 'wp-block-search__input-' . ++$instance_id;
    32 	$input_id            = wp_unique_id( 'wp-block-search__input-' );
    31 	$classnames       = classnames_for_block_core_search( $attributes );
    33 	$classnames          = classnames_for_block_core_search( $attributes );
    32 	$show_label       = ( ! empty( $attributes['showLabel'] ) ) ? true : false;
    34 	$show_label          = ( ! empty( $attributes['showLabel'] ) ) ? true : false;
    33 	$use_icon_button  = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false;
    35 	$use_icon_button     = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false;
    34 	$show_input       = ( ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'] ) ? false : true;
    36 	$show_button         = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true;
    35 	$show_button      = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true;
    37 	$button_position     = $show_button ? $attributes['buttonPosition'] : null;
    36 	$input_markup     = '';
    38 	$query_params        = ( ! empty( $attributes['query'] ) ) ? $attributes['query'] : array();
    37 	$button_markup    = '';
    39 	$button              = '';
    38 	$inline_styles    = styles_for_block_core_search( $attributes );
    40 	$query_params_markup = '';
    39 	$color_classes    = get_color_classes_for_block_core_search( $attributes );
    41 	$inline_styles       = styles_for_block_core_search( $attributes );
    40 	$is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
    42 	$color_classes       = get_color_classes_for_block_core_search( $attributes );
       
    43 	$typography_classes  = get_typography_classes_for_block_core_search( $attributes );
       
    44 	$is_button_inside    = ! empty( $attributes['buttonPosition'] ) &&
    41 		'button-inside' === $attributes['buttonPosition'];
    45 		'button-inside' === $attributes['buttonPosition'];
    42 	// Border color classes need to be applied to the elements that have a border color.
    46 	// Border color classes need to be applied to the elements that have a border color.
    43 	$border_color_classes = get_border_color_classes_for_block_core_search( $attributes );
    47 	$border_color_classes = 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;
    44 
    51 
    45 	$label_inner_html = empty( $attributes['label'] ) ? __( 'Search' ) : wp_kses_post( $attributes['label'] );
    52 	$label_inner_html = empty( $attributes['label'] ) ? __( 'Search' ) : wp_kses_post( $attributes['label'] );
    46 
    53 	$label            = new WP_HTML_Tag_Processor( sprintf( '<label %1$s>%2$s</label>', $inline_styles['label'], $label_inner_html ) );
    47 	$label_markup = sprintf(
    54 	if ( $label->next_tag() ) {
    48 		'<label for="%1$s" class="wp-block-search__label screen-reader-text">%2$s</label>',
    55 		$label->set_attribute( 'for', $input_id );
    49 		esc_attr( $input_id ),
    56 		$label->add_class( 'wp-block-search__label' );
    50 		$label_inner_html
    57 		if ( $show_label && ! empty( $attributes['label'] ) ) {
    51 	);
    58 			if ( ! empty( $typography_classes ) ) {
    52 	if ( $show_label && ! empty( $attributes['label'] ) ) {
    59 				$label->add_class( $typography_classes );
    53 		$label_markup = sprintf(
    60 			}
    54 			'<label for="%1$s" class="wp-block-search__label">%2$s</label>',
    61 		} else {
    55 			$input_id,
    62 			$label->add_class( 'screen-reader-text' );
    56 			$label_inner_html
    63 		}
    57 		);
    64 	}
    58 	}
    65 
    59 
    66 	$input         = new WP_HTML_Tag_Processor( sprintf( '<input type="search" name="s" required %s/>', $inline_styles['input'] ) );
    60 	if ( $show_input ) {
    67 	$input_classes = array( 'wp-block-search__input' );
    61 		$input_classes = ! $is_button_inside ? $border_color_classes : '';
    68 	if ( ! $is_button_inside && ! empty( $border_color_classes ) ) {
    62 		$input_markup  = sprintf(
    69 		$input_classes[] = $border_color_classes;
    63 			'<input type="search" id="%s" class="wp-block-search__input %s" name="s" value="%s" placeholder="%s" %s required />',
    70 	}
    64 			$input_id,
    71 	if ( ! empty( $typography_classes ) ) {
    65 			esc_attr( $input_classes ),
    72 		$input_classes[] = $typography_classes;
    66 			esc_attr( get_search_query() ),
    73 	}
    67 			esc_attr( $attributes['placeholder'] ),
    74 	if ( $input->next_tag() ) {
    68 			$inline_styles['input']
    75 		$input->add_class( implode( ' ', $input_classes ) );
    69 		);
    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 		}
    70 	}
   114 	}
    71 
   115 
    72 	if ( $show_button ) {
   116 	if ( $show_button ) {
       
   117 		$button_classes         = array( 'wp-block-search__button' );
    73 		$button_internal_markup = '';
   118 		$button_internal_markup = '';
    74 		$button_classes         = $color_classes;
   119 		if ( ! empty( $color_classes ) ) {
    75 		$aria_label             = '';
   120 			$button_classes[] = $color_classes;
    76 
   121 		}
    77 		if ( ! $is_button_inside ) {
   122 		if ( ! empty( $typography_classes ) ) {
    78 			$button_classes .= ' ' . $border_color_classes;
   123 			$button_classes[] = $typography_classes;
       
   124 		}
       
   125 
       
   126 		if ( ! $is_button_inside && ! empty( $border_color_classes ) ) {
       
   127 			$button_classes[] = $border_color_classes;
    79 		}
   128 		}
    80 		if ( ! $use_icon_button ) {
   129 		if ( ! $use_icon_button ) {
    81 			if ( ! empty( $attributes['buttonText'] ) ) {
   130 			if ( ! empty( $attributes['buttonText'] ) ) {
    82 				$button_internal_markup = wp_kses_post( $attributes['buttonText'] );
   131 				$button_internal_markup = wp_kses_post( $attributes['buttonText'] );
    83 			}
   132 			}
    84 		} else {
   133 		} else {
    85 			$aria_label      = sprintf( 'aria-label="%s"', esc_attr( wp_strip_all_tags( $attributes['buttonText'] ) ) );
   134 			$button_classes[]       = 'has-icon';
    86 			$button_classes .= ' has-icon';
       
    87 
       
    88 			$button_internal_markup =
   135 			$button_internal_markup =
    89 				'<svg id="search-icon" class="search-icon" viewBox="0 0 24 24" width="24" height="24">
   136 				'<svg class="search-icon" viewBox="0 0 24 24" width="24" height="24">
    90 					<path d="M13.5 6C10.5 6 8 8.5 8 11.5c0 1.1.3 2.1.9 3l-3.4 3 1 1.1 3.4-2.9c1 .9 2.2 1.4 3.6 1.4 3 0 5.5-2.5 5.5-5.5C19 8.5 16.5 6 13.5 6zm0 9.5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"></path>
   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>
    91 				</svg>';
   138 				</svg>';
    92 		}
   139 		}
    93 
   140 
    94 		$button_markup = sprintf(
   141 		// Include the button element class.
    95 			'<button type="submit" class="wp-block-search__button %s" %s %s>%s</button>',
   142 		$button_classes[] = wp_theme_get_element_class_name( 'button' );
    96 			esc_attr( $button_classes ),
   143 		$button           = new WP_HTML_Tag_Processor( sprintf( '<button type="submit" %s>%s</button>', $inline_styles['button'], $button_internal_markup ) );
    97 			$inline_styles['button'],
   144 
    98 			$aria_label,
   145 		if ( $button->next_tag() ) {
    99 			$button_internal_markup
   146 			$button->add_class( implode( ' ', $button_classes ) );
   100 		);
   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 		}
   101 	}
   164 	}
   102 
   165 
   103 	$field_markup_classes = $is_button_inside ? $border_color_classes : '';
   166 	$field_markup_classes = $is_button_inside ? $border_color_classes : '';
   104 	$field_markup         = sprintf(
   167 	$field_markup         = sprintf(
   105 		'<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
   168 		'<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
   106 		esc_attr( $field_markup_classes ),
   169 		esc_attr( $field_markup_classes ),
   107 		$inline_styles['wrapper'],
   170 		$inline_styles['wrapper'],
   108 		$input_markup . $button_markup
   171 		$input . $query_params_markup . $button
   109 	);
   172 	);
   110 	$wrapper_attributes   = get_block_wrapper_attributes( array( 'class' => $classnames ) );
   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 	}
   111 
   198 
   112 	return sprintf(
   199 	return sprintf(
   113 		'<form role="search" method="get" action="%s" %s>%s</form>',
   200 		'<form role="search" method="get" action="%1s" %2s %3s>%4s</form>',
   114 		esc_url( home_url( '/' ) ),
   201 		esc_url( home_url( '/' ) ),
   115 		$wrapper_attributes,
   202 		$wrapper_attributes,
   116 		$label_markup . $field_markup
   203 		$form_directives,
       
   204 		$label . $field_markup
   117 	);
   205 	);
   118 }
   206 }
   119 
   207 
   120 /**
   208 /**
   121  * Registers the `core/search` block on the server.
   209  * Registers the `core/search` block on the server.
       
   210  *
       
   211  * @since 5.2.0
   122  */
   212  */
   123 function register_block_core_search() {
   213 function register_block_core_search() {
   124 	register_block_type_from_metadata(
   214 	register_block_type_from_metadata(
   125 		__DIR__ . '/search',
   215 		__DIR__ . '/search',
   126 		array(
   216 		array(
   131 add_action( 'init', 'register_block_core_search' );
   221 add_action( 'init', 'register_block_core_search' );
   132 
   222 
   133 /**
   223 /**
   134  * Builds the correct top level classnames for the 'core/search' block.
   224  * Builds the correct top level classnames for the 'core/search' block.
   135  *
   225  *
       
   226  * @since 5.6.0
       
   227  *
   136  * @param array $attributes The block attributes.
   228  * @param array $attributes The block attributes.
   137  *
   229  *
   138  * @return string The classnames used in the block.
   230  * @return string The classnames used in the block.
   139  */
   231  */
   140 function classnames_for_block_core_search( $attributes ) {
   232 function classnames_for_block_core_search( $attributes ) {
   152 		if ( 'no-button' === $attributes['buttonPosition'] ) {
   244 		if ( 'no-button' === $attributes['buttonPosition'] ) {
   153 			$classnames[] = 'wp-block-search__no-button';
   245 			$classnames[] = 'wp-block-search__no-button';
   154 		}
   246 		}
   155 
   247 
   156 		if ( 'button-only' === $attributes['buttonPosition'] ) {
   248 		if ( 'button-only' === $attributes['buttonPosition'] ) {
   157 			$classnames[] = 'wp-block-search__button-only';
   249 			$classnames[] = 'wp-block-search__button-only wp-block-search__searchfield-hidden';
   158 		}
   250 		}
   159 	}
   251 	}
   160 
   252 
   161 	if ( isset( $attributes['buttonUseIcon'] ) ) {
   253 	if ( isset( $attributes['buttonUseIcon'] ) ) {
   162 		if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) {
   254 		if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) {
   170 
   262 
   171 	return implode( ' ', $classnames );
   263 	return implode( ' ', $classnames );
   172 }
   264 }
   173 
   265 
   174 /**
   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 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 apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) {
       
   328 	apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles );
       
   329 	apply_block_core_search_border_style( $attributes, $property, 'top', $wrapper_styles, $button_styles, $input_styles );
       
   330 	apply_block_core_search_border_style( $attributes, $property, 'right', $wrapper_styles, $button_styles, $input_styles );
       
   331 	apply_block_core_search_border_style( $attributes, $property, 'bottom', $wrapper_styles, $button_styles, $input_styles );
       
   332 	apply_block_core_search_border_style( $attributes, $property, 'left', $wrapper_styles, $button_styles, $input_styles );
       
   333 }
       
   334 
       
   335 /**
   175  * Builds an array of inline styles for the search block.
   336  * Builds an array of inline styles for the search block.
   176  *
   337  *
   177  * The result will contain one entry for shared styles such as those for the
   338  * The result will contain one entry for shared styles such as those for the
   178  * inner input or button and a second for the inner wrapper should the block
   339  * inner input or button and a second for the inner wrapper should the block
   179  * be positioning the button "inside".
   340  * be positioning the button "inside".
       
   341  *
       
   342  * @since 5.8.0
   180  *
   343  *
   181  * @param  array $attributes The block attributes.
   344  * @param  array $attributes The block attributes.
   182  *
   345  *
   183  * @return array Style HTML attribute.
   346  * @return array Style HTML attribute.
   184  */
   347  */
   185 function styles_for_block_core_search( $attributes ) {
   348 function styles_for_block_core_search( $attributes ) {
   186 	$wrapper_styles   = array();
   349 	$wrapper_styles   = array();
   187 	$button_styles    = array();
   350 	$button_styles    = array();
   188 	$input_styles     = array();
   351 	$input_styles     = array();
       
   352 	$label_styles     = array();
   189 	$is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
   353 	$is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
   190 		'button-inside' === $attributes['buttonPosition'];
   354 		'button-inside' === $attributes['buttonPosition'];
       
   355 	$show_label       = ( isset( $attributes['showLabel'] ) ) && false !== $attributes['showLabel'];
   191 
   356 
   192 	// Add width styles.
   357 	// Add width styles.
   193 	$has_width   = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] );
   358 	$has_width = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] );
   194 	$button_only = ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'];
   359 
   195 
   360 	if ( $has_width ) {
   196 	if ( $has_width && ! $button_only ) {
       
   197 		$wrapper_styles[] = sprintf(
   361 		$wrapper_styles[] = sprintf(
   198 			'width: %d%s;',
   362 			'width: %d%s;',
   199 			esc_attr( $attributes['width'] ),
   363 			esc_attr( $attributes['width'] ),
   200 			esc_attr( $attributes['widthUnit'] )
   364 			esc_attr( $attributes['widthUnit'] )
   201 		);
   365 		);
   202 	}
   366 	}
   203 
   367 
   204 	// Add border width styles.
   368 	// Add border width and color styles.
   205 	$has_border_width = ! empty( $attributes['style']['border']['width'] );
   369 	apply_block_core_search_border_styles( $attributes, 'width', $wrapper_styles, $button_styles, $input_styles );
   206 
   370 	apply_block_core_search_border_styles( $attributes, 'color', $wrapper_styles, $button_styles, $input_styles );
   207 	if ( $has_border_width ) {
   371 	apply_block_core_search_border_styles( $attributes, 'style', $wrapper_styles, $button_styles, $input_styles );
   208 		$border_width = $attributes['style']['border']['width'];
       
   209 
       
   210 		if ( $is_button_inside ) {
       
   211 			$wrapper_styles[] = sprintf( 'border-width: %s;', esc_attr( $border_width ) );
       
   212 		} else {
       
   213 			$button_styles[] = sprintf( 'border-width: %s;', esc_attr( $border_width ) );
       
   214 			$input_styles[]  = sprintf( 'border-width: %s;', esc_attr( $border_width ) );
       
   215 		}
       
   216 	}
       
   217 
   372 
   218 	// Add border radius styles.
   373 	// Add border radius styles.
   219 	$has_border_radius = ! empty( $attributes['style']['border']['radius'] );
   374 	$has_border_radius = ! empty( $attributes['style']['border']['radius'] );
   220 
   375 
   221 	if ( $has_border_radius ) {
   376 	if ( $has_border_radius ) {
   267 				);
   422 				);
   268 			}
   423 			}
   269 		}
   424 		}
   270 	}
   425 	}
   271 
   426 
   272 	// Add border color styles.
       
   273 	$has_border_color = ! empty( $attributes['style']['border']['color'] );
       
   274 
       
   275 	if ( $has_border_color ) {
       
   276 		$border_color = $attributes['style']['border']['color'];
       
   277 
       
   278 		// Apply wrapper border color if button placed inside.
       
   279 		if ( $is_button_inside ) {
       
   280 			$wrapper_styles[] = sprintf( 'border-color: %s;', esc_attr( $border_color ) );
       
   281 		} else {
       
   282 			$button_styles[] = sprintf( 'border-color: %s;', esc_attr( $border_color ) );
       
   283 			$input_styles[]  = sprintf( 'border-color: %s;', esc_attr( $border_color ) );
       
   284 		}
       
   285 	}
       
   286 
       
   287 	// Add color styles.
   427 	// Add color styles.
   288 	$has_text_color = ! empty( $attributes['style']['color']['text'] );
   428 	$has_text_color = ! empty( $attributes['style']['color']['text'] );
   289 	if ( $has_text_color ) {
   429 	if ( $has_text_color ) {
   290 		$button_styles[] = sprintf( 'color: %s;', esc_attr( $attributes['style']['color']['text'] ) );
   430 		$button_styles[] = sprintf( 'color: %s;', $attributes['style']['color']['text'] );
   291 	}
   431 	}
   292 
   432 
   293 	$has_background_color = ! empty( $attributes['style']['color']['background'] );
   433 	$has_background_color = ! empty( $attributes['style']['color']['background'] );
   294 	if ( $has_background_color ) {
   434 	if ( $has_background_color ) {
   295 		$button_styles[] = sprintf( 'background-color: %s;', esc_attr( $attributes['style']['color']['background'] ) );
   435 		$button_styles[] = sprintf( 'background-color: %s;', $attributes['style']['color']['background'] );
   296 	}
   436 	}
   297 
   437 
   298 	$has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
   438 	$has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
   299 	if ( $has_custom_gradient ) {
   439 	if ( $has_custom_gradient ) {
   300 		$button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
   440 		$button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
   301 	}
   441 	}
   302 
   442 
       
   443 	// Get typography styles to be shared across inner elements.
       
   444 	$typography_styles = esc_attr( get_typography_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 
   303 	return array(
   461 	return array(
   304 		'input'   => ! empty( $input_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $input_styles ) ) ) : '',
   462 		'input'   => ! empty( $input_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $input_styles ) ) ) ) : '',
   305 		'button'  => ! empty( $button_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $button_styles ) ) ) : '',
   463 		'button'  => ! empty( $button_styles ) ? sprintf( ' style="%s"', esc_attr( safecss_filter_attr( implode( ' ', $button_styles ) ) ) ) : '',
   306 		'wrapper' => ! empty( $wrapper_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $wrapper_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 ) ) ) ) : '',
   307 	);
   466 	);
   308 }
   467 }
   309 
   468 
   310 /**
   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 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_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 			wp_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 /**
   311  * Returns border color classnames depending on whether there are named or custom border colors.
   548  * Returns border color classnames depending on whether there are named or custom border colors.
   312  *
   549  *
       
   550  * @since 5.9.0
       
   551  *
   313  * @param array $attributes The block attributes.
   552  * @param array $attributes The block attributes.
   314  *
   553  *
   315  * @return string The border color classnames to be applied to the block elements.
   554  * @return string The border color classnames to be applied to the block elements.
   316  */
   555  */
   317 function get_border_color_classes_for_block_core_search( $attributes ) {
   556 function get_border_color_classes_for_block_core_search( $attributes ) {
       
   557 	$border_color_classes    = array();
   318 	$has_custom_border_color = ! empty( $attributes['style']['border']['color'] );
   558 	$has_custom_border_color = ! empty( $attributes['style']['border']['color'] );
   319 	$border_color_classes    = ! empty( $attributes['borderColor'] ) ? sprintf( 'has-border-color has-%s-border-color', $attributes['borderColor'] ) : '';
   559 	$has_named_border_color  = ! empty( $attributes['borderColor'] );
   320 	// If there's a border color style and no `borderColor` text string, we still want to add the generic `has-border-color` class name to the element.
   560 
   321 	if ( $has_custom_border_color && empty( $attributes['borderColor'] ) ) {
   561 	if ( $has_custom_border_color || $has_named_border_color ) {
   322 		$border_color_classes = 'has-border-color';
   562 		$border_color_classes[] = 'has-border-color';
   323 	}
   563 	}
   324 	return $border_color_classes;
   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 );
   325 }
   570 }
   326 
   571 
   327 /**
   572 /**
   328  * Returns color classnames depending on whether there are named or custom text and background colors.
   573  * Returns color classnames depending on whether there are named or custom text and background colors.
       
   574  *
       
   575  * @since 5.9.0
   329  *
   576  *
   330  * @param array $attributes The block attributes.
   577  * @param array $attributes The block attributes.
   331  *
   578  *
   332  * @return string The color classnames to be applied to the block elements.
   579  * @return string The color classnames to be applied to the block elements.
   333  */
   580  */