PluginProbe
Gutenberg / 13.5.1
Gutenberg v13.5.1
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 13.5.1, at build/block-library/blocks/search.php

433 lines 16.0 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 * @param array $attributes The block attributes.
12 *
13 * @return string The search block markup.
14 */
15 function gutenberg_render_block_core_search( $attributes ) {
16 // Older versions of the Search block defaulted the label and buttonText
17 // attributes to `__( 'Search' )` meaning that many posts contain `<!--
18 // wp:search /-->`. Support these by defaulting an undefined label and
19 // buttonText to `__( 'Search' )`.
20 $attributes = wp_parse_args(
21 $attributes,
22 array(
23 'label' => __( 'Search' ),
24 'buttonText' => __( 'Search' ),
25 )
26 );
27
28 $input_id = wp_unique_id( 'wp-block-search__input-' );
29 $classnames = gutenberg_classnames_for_block_core_search( $attributes );
30 $show_label = ( ! empty( $attributes['showLabel'] ) ) ? true : false;
31 $use_icon_button = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false;
32 $show_input = ( ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'] ) ? false : true;
33 $show_button = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true;
34 $query_params = ( ! empty( $attributes['query'] ) ) ? $attributes['query'] : array();
35 $input_markup = '';
36 $button_markup = '';
37 $query_params_markup = '';
38 $inline_styles = gutenberg_styles_for_block_core_search( $attributes );
39 $color_classes = gutenberg_get_color_classes_for_block_core_search( $attributes );
40 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
41 'button-inside' === $attributes['buttonPosition'];
42 // Border color classes need to be applied to the elements that have a border color.
43 $border_color_classes = gutenberg_get_border_color_classes_for_block_core_search( $attributes );
44
45 $label_inner_html = empty( $attributes['label'] ) ? __( 'Search' ) : wp_kses_post( $attributes['label'] );
46
47 $label_markup = sprintf(
48 '<label for="%1$s" class="wp-block-search__label screen-reader-text">%2$s</label>',
49 esc_attr( $input_id ),
50 $label_inner_html
51 );
52 if ( $show_label && ! empty( $attributes['label'] ) ) {
53 $label_markup = sprintf(
54 '<label for="%1$s" class="wp-block-search__label">%2$s</label>',
55 $input_id,
56 $label_inner_html
57 );
58 }
59
60 if ( $show_input ) {
61 $input_classes = ! $is_button_inside ? $border_color_classes : '';
62 $input_markup = sprintf(
63 '<input type="search" id="%s" class="wp-block-search__input %s" name="s" value="%s" placeholder="%s" %s required />',
64 $input_id,
65 esc_attr( $input_classes ),
66 get_search_query(),
67 esc_attr( $attributes['placeholder'] ),
68 $inline_styles['input']
69 );
70 }
71
72 if ( count( $query_params ) > 0 ) {
73 foreach ( $query_params as $param => $value ) {
74 $query_params_markup .= sprintf(
75 '<input type="hidden" name="%s" value="%s" />',
76 esc_attr( $param ),
77 esc_attr( $value )
78 );
79 }
80 }
81
82 if ( $show_button ) {
83 $button_internal_markup = '';
84 $button_classes = $color_classes;
85 $aria_label = '';
86
87 if ( ! $is_button_inside ) {
88 $button_classes .= ' ' . $border_color_classes;
89 }
90 if ( ! $use_icon_button ) {
91 if ( ! empty( $attributes['buttonText'] ) ) {
92 $button_internal_markup = wp_kses_post( $attributes['buttonText'] );
93 }
94 } else {
95 $aria_label = sprintf( 'aria-label="%s"', esc_attr( wp_strip_all_tags( $attributes['buttonText'] ) ) );
96 $button_classes .= ' has-icon';
97
98 $button_internal_markup =
99 '<svg class="search-icon" viewBox="0 0 24 24" width="24" height="24">
100 <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>
101 </svg>';
102 }
103
104 // Include the button element class.
105 $button_classes .= ' ' . WP_Theme_JSON_GUTENBERG::__EXPERIMENTAL_ELEMENT_BUTTON_CLASS_NAME;
106
107 $button_markup = sprintf(
108 '<button type="submit" class="wp-block-search__button %s" %s %s>%s</button>',
109 esc_attr( $button_classes ),
110 $inline_styles['button'],
111 $aria_label,
112 $button_internal_markup
113 );
114 }
115
116 $field_markup_classes = $is_button_inside ? $border_color_classes : '';
117 $field_markup = sprintf(
118 '<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
119 esc_attr( $field_markup_classes ),
120 $inline_styles['wrapper'],
121 $input_markup . $query_params_markup . $button_markup
122 );
123 $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classnames ) );
124
125 return sprintf(
126 '<form role="search" method="get" action="%s" %s>%s</form>',
127 esc_url( home_url( '/' ) ),
128 $wrapper_attributes,
129 $label_markup . $field_markup
130 );
131 }
132
133 /**
134 * Registers the `core/search` block on the server.
135 */
136 function gutenberg_register_block_core_search() {
137 register_block_type_from_metadata(
138 __DIR__ . '/search',
139 array(
140 'render_callback' => 'gutenberg_render_block_core_search',
141 )
142 );
143 }
144 add_action( 'init', 'gutenberg_register_block_core_search', 20 );
145
146 /**
147 * Builds the correct top level classnames for the 'core/search' block.
148 *
149 * @param array $attributes The block attributes.
150 *
151 * @return string The classnames used in the block.
152 */
153 function gutenberg_classnames_for_block_core_search( $attributes ) {
154 $classnames = array();
155
156 if ( ! empty( $attributes['buttonPosition'] ) ) {
157 if ( 'button-inside' === $attributes['buttonPosition'] ) {
158 $classnames[] = 'wp-block-search__button-inside';
159 }
160
161 if ( 'button-outside' === $attributes['buttonPosition'] ) {
162 $classnames[] = 'wp-block-search__button-outside';
163 }
164
165 if ( 'no-button' === $attributes['buttonPosition'] ) {
166 $classnames[] = 'wp-block-search__no-button';
167 }
168
169 if ( 'button-only' === $attributes['buttonPosition'] ) {
170 $classnames[] = 'wp-block-search__button-only';
171 }
172 }
173
174 if ( isset( $attributes['buttonUseIcon'] ) ) {
175 if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) {
176 if ( $attributes['buttonUseIcon'] ) {
177 $classnames[] = 'wp-block-search__icon-button';
178 } else {
179 $classnames[] = 'wp-block-search__text-button';
180 }
181 }
182 }
183
184 return implode( ' ', $classnames );
185 }
186
187 /**
188 * This generates a CSS rule for the given border property and side if provided.
189 * Based on whether the Search block is configured to display the button inside
190 * or not, the generated rule is injected into the appropriate collection of
191 * styles for later application in the block's markup.
192 *
193 * @param array $attributes The block attributes.
194 * @param string $property Border property to generate rule for e.g. width or color.
195 * @param string $side Optional side border. The dictates the value retrieved and final CSS property.
196 * @param array $wrapper_styles Current collection of wrapper styles.
197 * @param array $button_styles Current collection of button styles.
198 * @param array $input_styles Current collection of input styles.
199 *
200 * @return void
201 */
202 function gutenberg_apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) {
203 $is_button_inside = 'button-inside' === _wp_array_get( $attributes, array( 'buttonPosition' ), false );
204
205 $path = array( 'style', 'border', $property );
206
207 if ( $side ) {
208 array_splice( $path, 2, 0, $side );
209 }
210
211 $value = _wp_array_get( $attributes, $path, false );
212
213 if ( empty( $value ) ) {
214 return;
215 }
216
217 if ( 'color' === $property && $side ) {
218 $has_color_preset = strpos( $value, 'var:preset|color|' ) !== false;
219 if ( $has_color_preset ) {
220 $named_color_value = substr( $value, strrpos( $value, '|' ) + 1 );
221 $value = sprintf( 'var(--wp--preset--color--%s)', $named_color_value );
222 }
223 }
224
225 $property_suffix = $side ? sprintf( '%s-%s', $side, $property ) : $property;
226
227 if ( $is_button_inside ) {
228 $wrapper_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
229 } else {
230 $button_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
231 $input_styles[] = sprintf( 'border-%s: %s;', $property_suffix, esc_attr( $value ) );
232 }
233 }
234
235 /**
236 * This adds CSS rules for a given border property e.g. width or color. It
237 * injects rules into the provided wrapper, button and input style arrays for
238 * uniform "flat" borders or those with individual sides configured.
239 *
240 * @param array $attributes The block attributes.
241 * @param string $property Border property to generate rule for e.g. width or color.
242 * @param array $wrapper_styles Current collection of wrapper styles.
243 * @param array $button_styles Current collection of button styles.
244 * @param array $input_styles Current collection of input styles.
245 *
246 * @return void
247 */
248 function gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) {
249 gutenberg_apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles );
250 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'top', $wrapper_styles, $button_styles, $input_styles );
251 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'right', $wrapper_styles, $button_styles, $input_styles );
252 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'bottom', $wrapper_styles, $button_styles, $input_styles );
253 gutenberg_apply_block_core_search_border_style( $attributes, $property, 'left', $wrapper_styles, $button_styles, $input_styles );
254 }
255
256 /**
257 * Builds an array of inline styles for the search block.
258 *
259 * The result will contain one entry for shared styles such as those for the
260 * inner input or button and a second for the inner wrapper should the block
261 * be positioning the button "inside".
262 *
263 * @param array $attributes The block attributes.
264 *
265 * @return array Style HTML attribute.
266 */
267 function gutenberg_styles_for_block_core_search( $attributes ) {
268 $wrapper_styles = array();
269 $button_styles = array();
270 $input_styles = array();
271 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
272 'button-inside' === $attributes['buttonPosition'];
273
274 // Add width styles.
275 $has_width = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] );
276 $button_only = ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'];
277
278 if ( $has_width && ! $button_only ) {
279 $wrapper_styles[] = sprintf(
280 'width: %d%s;',
281 esc_attr( $attributes['width'] ),
282 esc_attr( $attributes['widthUnit'] )
283 );
284 }
285
286 // Add border width and color styles.
287 gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, 'width', $wrapper_styles, $button_styles, $input_styles );
288 gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, 'color', $wrapper_styles, $button_styles, $input_styles );
289 gutenberg_gutenberg_apply_block_core_search_border_styles( $attributes, 'style', $wrapper_styles, $button_styles, $input_styles );
290
291 // Add border radius styles.
292 $has_border_radius = ! empty( $attributes['style']['border']['radius'] );
293
294 if ( $has_border_radius ) {
295 $default_padding = '4px';
296 $border_radius = $attributes['style']['border']['radius'];
297
298 if ( is_array( $border_radius ) ) {
299 // Apply styles for individual corner border radii.
300 foreach ( $border_radius as $key => $value ) {
301 if ( null !== $value ) {
302 // Convert camelCase key to kebab-case.
303 $name = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
304
305 // Add shared styles for individual border radii for input & button.
306 $border_style = sprintf(
307 'border-%s-radius: %s;',
308 esc_attr( $name ),
309 esc_attr( $value )
310 );
311 $input_styles[] = $border_style;
312 $button_styles[] = $border_style;
313
314 // Add adjusted border radius styles for the wrapper element
315 // if button is positioned inside.
316 if ( $is_button_inside && intval( $value ) !== 0 ) {
317 $wrapper_styles[] = sprintf(
318 'border-%s-radius: calc(%s + %s);',
319 esc_attr( $name ),
320 esc_attr( $value ),
321 $default_padding
322 );
323 }
324 }
325 }
326 } else {
327 // Numeric check is for backwards compatibility purposes.
328 $border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
329 $border_style = sprintf( 'border-radius: %s;', esc_attr( $border_radius ) );
330 $input_styles[] = $border_style;
331 $button_styles[] = $border_style;
332
333 if ( $is_button_inside && intval( $border_radius ) !== 0 ) {
334 // Adjust wrapper border radii to maintain visual consistency
335 // with inner elements when button is positioned inside.
336 $wrapper_styles[] = sprintf(
337 'border-radius: calc(%s + %s);',
338 esc_attr( $border_radius ),
339 $default_padding
340 );
341 }
342 }
343 }
344
345 // Add color styles.
346 $has_text_color = ! empty( $attributes['style']['color']['text'] );
347 if ( $has_text_color ) {
348 $button_styles[] = sprintf( 'color: %s;', esc_attr( $attributes['style']['color']['text'] ) );
349 }
350
351 $has_background_color = ! empty( $attributes['style']['color']['background'] );
352 if ( $has_background_color ) {
353 $button_styles[] = sprintf( 'background-color: %s;', esc_attr( $attributes['style']['color']['background'] ) );
354 }
355
356 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
357 if ( $has_custom_gradient ) {
358 $button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
359 }
360
361 return array(
362 'input' => ! empty( $input_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $input_styles ) ) ) : '',
363 'button' => ! empty( $button_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $button_styles ) ) ) : '',
364 'wrapper' => ! empty( $wrapper_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $wrapper_styles ) ) ) : '',
365 );
366 }
367
368 /**
369 * Returns border color classnames depending on whether there are named or custom border colors.
370 *
371 * @param array $attributes The block attributes.
372 *
373 * @return string The border color classnames to be applied to the block elements.
374 */
375 function gutenberg_get_border_color_classes_for_block_core_search( $attributes ) {
376 $border_color_classes = array();
377 $has_custom_border_color = ! empty( $attributes['style']['border']['color'] );
378 $has_named_border_color = ! empty( $attributes['borderColor'] );
379
380 if ( $has_custom_border_color || $has_named_border_color ) {
381 $border_color_classes[] = 'has-border-color';
382 }
383
384 if ( $has_named_border_color ) {
385 $border_color_classes[] = sprintf( 'has-%s-border-color', esc_attr( $attributes['borderColor'] ) );
386 }
387
388 return implode( ' ', $border_color_classes );
389 }
390
391 /**
392 * Returns color classnames depending on whether there are named or custom text and background colors.
393 *
394 * @param array $attributes The block attributes.
395 *
396 * @return string The color classnames to be applied to the block elements.
397 */
398 function gutenberg_get_color_classes_for_block_core_search( $attributes ) {
399 $classnames = array();
400
401 // Text color.
402 $has_named_text_color = ! empty( $attributes['textColor'] );
403 $has_custom_text_color = ! empty( $attributes['style']['color']['text'] );
404 if ( $has_named_text_color ) {
405 $classnames[] = sprintf( 'has-text-color has-%s-color', $attributes['textColor'] );
406 } elseif ( $has_custom_text_color ) {
407 // If a custom 'textColor' was selected instead of a preset, still add the generic `has-text-color` class.
408 $classnames[] = 'has-text-color';
409 }
410
411 // Background color.
412 $has_named_background_color = ! empty( $attributes['backgroundColor'] );
413 $has_custom_background_color = ! empty( $attributes['style']['color']['background'] );
414 $has_named_gradient = ! empty( $attributes['gradient'] );
415 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
416 if (
417 $has_named_background_color ||
418 $has_custom_background_color ||
419 $has_named_gradient ||
420 $has_custom_gradient
421 ) {
422 $classnames[] = 'has-background';
423 }
424 if ( $has_named_background_color ) {
425 $classnames[] = sprintf( 'has-%s-background-color', $attributes['backgroundColor'] );
426 }
427 if ( $has_named_gradient ) {
428 $classnames[] = sprintf( 'has-%s-gradient-background', $attributes['gradient'] );
429 }
430
431 return implode( ' ', $classnames );
432 }
433