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

369 lines 12.9 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 static $instance_id = 0;
17
18 // Older versions of the Search block defaulted the label and buttonText
19 // attributes to `__( 'Search' )` meaning that many posts contain `<!--
20 // wp:search /-->`. Support these by defaulting an undefined label and
21 // buttonText to `__( 'Search' )`.
22 $attributes = wp_parse_args(
23 $attributes,
24 array(
25 'label' => __( 'Search' ),
26 'buttonText' => __( 'Search' ),
27 )
28 );
29
30 $input_id = 'wp-block-search__input-' . ++$instance_id;
31 $classnames = gutenberg_classnames_for_block_core_search( $attributes );
32 $show_label = ( ! empty( $attributes['showLabel'] ) ) ? true : false;
33 $use_icon_button = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false;
34 $show_input = ( ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'] ) ? false : true;
35 $show_button = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true;
36 $input_markup = '';
37 $button_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 esc_attr( get_search_query() ),
67 esc_attr( $attributes['placeholder'] ),
68 $inline_styles['input']
69 );
70 }
71
72 if ( $show_button ) {
73 $button_internal_markup = '';
74 $button_classes = $color_classes;
75 $aria_label = '';
76
77 if ( ! $is_button_inside ) {
78 $button_classes .= ' ' . $border_color_classes;
79 }
80 if ( ! $use_icon_button ) {
81 if ( ! empty( $attributes['buttonText'] ) ) {
82 $button_internal_markup = wp_kses_post( $attributes['buttonText'] );
83 }
84 } else {
85 $aria_label = sprintf( 'aria-label="%s"', esc_attr( wp_strip_all_tags( $attributes['buttonText'] ) ) );
86 $button_classes .= ' has-icon';
87
88 $button_internal_markup =
89 '<svg id="search-icon" 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>
91 </svg>';
92 }
93
94 $button_markup = sprintf(
95 '<button type="submit" class="wp-block-search__button %s" %s %s>%s</button>',
96 esc_attr( $button_classes ),
97 $inline_styles['button'],
98 $aria_label,
99 $button_internal_markup
100 );
101 }
102
103 $field_markup_classes = $is_button_inside ? $border_color_classes : '';
104 $field_markup = sprintf(
105 '<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
106 esc_attr( $field_markup_classes ),
107 $inline_styles['wrapper'],
108 $input_markup . $button_markup
109 );
110 $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classnames ) );
111
112 return sprintf(
113 '<form role="search" method="get" action="%s" %s>%s</form>',
114 esc_url( home_url( '/' ) ),
115 $wrapper_attributes,
116 $label_markup . $field_markup
117 );
118 }
119
120 /**
121 * Registers the `core/search` block on the server.
122 */
123 function gutenberg_register_block_core_search() {
124 register_block_type_from_metadata(
125 __DIR__ . '/search',
126 array(
127 'render_callback' => 'gutenberg_render_block_core_search',
128 )
129 );
130 }
131 add_action( 'init', 'gutenberg_register_block_core_search', 20 );
132
133 /**
134 * Builds the correct top level classnames for the 'core/search' block.
135 *
136 * @param array $attributes The block attributes.
137 *
138 * @return string The classnames used in the block.
139 */
140 function gutenberg_classnames_for_block_core_search( $attributes ) {
141 $classnames = array();
142
143 if ( ! empty( $attributes['buttonPosition'] ) ) {
144 if ( 'button-inside' === $attributes['buttonPosition'] ) {
145 $classnames[] = 'wp-block-search__button-inside';
146 }
147
148 if ( 'button-outside' === $attributes['buttonPosition'] ) {
149 $classnames[] = 'wp-block-search__button-outside';
150 }
151
152 if ( 'no-button' === $attributes['buttonPosition'] ) {
153 $classnames[] = 'wp-block-search__no-button';
154 }
155
156 if ( 'button-only' === $attributes['buttonPosition'] ) {
157 $classnames[] = 'wp-block-search__button-only';
158 }
159 }
160
161 if ( isset( $attributes['buttonUseIcon'] ) ) {
162 if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) {
163 if ( $attributes['buttonUseIcon'] ) {
164 $classnames[] = 'wp-block-search__icon-button';
165 } else {
166 $classnames[] = 'wp-block-search__text-button';
167 }
168 }
169 }
170
171 return implode( ' ', $classnames );
172 }
173
174 /**
175 * Builds an array of inline styles for the search block.
176 *
177 * 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
179 * be positioning the button "inside".
180 *
181 * @param array $attributes The block attributes.
182 *
183 * @return array Style HTML attribute.
184 */
185 function gutenberg_styles_for_block_core_search( $attributes ) {
186 $wrapper_styles = array();
187 $button_styles = array();
188 $input_styles = array();
189 $is_button_inside = ! empty( $attributes['buttonPosition'] ) &&
190 'button-inside' === $attributes['buttonPosition'];
191
192 // Add width styles.
193 $has_width = ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] );
194 $button_only = ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'];
195
196 if ( $has_width && ! $button_only ) {
197 $wrapper_styles[] = sprintf(
198 'width: %d%s;',
199 esc_attr( $attributes['width'] ),
200 esc_attr( $attributes['widthUnit'] )
201 );
202 }
203
204 // Add border width styles.
205 $has_border_width = ! empty( $attributes['style']['border']['width'] );
206
207 if ( $has_border_width ) {
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
218 // Add border radius styles.
219 $has_border_radius = ! empty( $attributes['style']['border']['radius'] );
220
221 if ( $has_border_radius ) {
222 $default_padding = '4px';
223 $border_radius = $attributes['style']['border']['radius'];
224
225 if ( is_array( $border_radius ) ) {
226 // Apply styles for individual corner border radii.
227 foreach ( $border_radius as $key => $value ) {
228 if ( null !== $value ) {
229 // Convert camelCase key to kebab-case.
230 $name = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
231
232 // Add shared styles for individual border radii for input & button.
233 $border_style = sprintf(
234 'border-%s-radius: %s;',
235 esc_attr( $name ),
236 esc_attr( $value )
237 );
238 $input_styles[] = $border_style;
239 $button_styles[] = $border_style;
240
241 // Add adjusted border radius styles for the wrapper element
242 // if button is positioned inside.
243 if ( $is_button_inside && intval( $value ) !== 0 ) {
244 $wrapper_styles[] = sprintf(
245 'border-%s-radius: calc(%s + %s);',
246 esc_attr( $name ),
247 esc_attr( $value ),
248 $default_padding
249 );
250 }
251 }
252 }
253 } else {
254 // Numeric check is for backwards compatibility purposes.
255 $border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
256 $border_style = sprintf( 'border-radius: %s;', esc_attr( $border_radius ) );
257 $input_styles[] = $border_style;
258 $button_styles[] = $border_style;
259
260 if ( $is_button_inside && intval( $border_radius ) !== 0 ) {
261 // Adjust wrapper border radii to maintain visual consistency
262 // with inner elements when button is positioned inside.
263 $wrapper_styles[] = sprintf(
264 'border-radius: calc(%s + %s);',
265 esc_attr( $border_radius ),
266 $default_padding
267 );
268 }
269 }
270 }
271
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.
288 $has_text_color = ! empty( $attributes['style']['color']['text'] );
289 if ( $has_text_color ) {
290 $button_styles[] = sprintf( 'color: %s;', esc_attr( $attributes['style']['color']['text'] ) );
291 }
292
293 $has_background_color = ! empty( $attributes['style']['color']['background'] );
294 if ( $has_background_color ) {
295 $button_styles[] = sprintf( 'background-color: %s;', esc_attr( $attributes['style']['color']['background'] ) );
296 }
297
298 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
299 if ( $has_custom_gradient ) {
300 $button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
301 }
302
303 return array(
304 'input' => ! empty( $input_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $input_styles ) ) ) : '',
305 'button' => ! empty( $button_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $button_styles ) ) ) : '',
306 'wrapper' => ! empty( $wrapper_styles ) ? sprintf( ' style="%s"', safecss_filter_attr( implode( ' ', $wrapper_styles ) ) ) : '',
307 );
308 }
309
310 /**
311 * Returns border color classnames depending on whether there are named or custom border colors.
312 *
313 * @param array $attributes The block attributes.
314 *
315 * @return string The border color classnames to be applied to the block elements.
316 */
317 function gutenberg_get_border_color_classes_for_block_core_search( $attributes ) {
318 $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'] ) : '';
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.
321 if ( $has_custom_border_color && empty( $attributes['borderColor'] ) ) {
322 $border_color_classes = 'has-border-color';
323 }
324 return $border_color_classes;
325 }
326
327 /**
328 * Returns color classnames depending on whether there are named or custom text and background colors.
329 *
330 * @param array $attributes The block attributes.
331 *
332 * @return string The color classnames to be applied to the block elements.
333 */
334 function gutenberg_get_color_classes_for_block_core_search( $attributes ) {
335 $classnames = array();
336
337 // Text color.
338 $has_named_text_color = ! empty( $attributes['textColor'] );
339 $has_custom_text_color = ! empty( $attributes['style']['color']['text'] );
340 if ( $has_named_text_color ) {
341 $classnames[] = sprintf( 'has-text-color has-%s-color', $attributes['textColor'] );
342 } elseif ( $has_custom_text_color ) {
343 // If a custom 'textColor' was selected instead of a preset, still add the generic `has-text-color` class.
344 $classnames[] = 'has-text-color';
345 }
346
347 // Background color.
348 $has_named_background_color = ! empty( $attributes['backgroundColor'] );
349 $has_custom_background_color = ! empty( $attributes['style']['color']['background'] );
350 $has_named_gradient = ! empty( $attributes['gradient'] );
351 $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
352 if (
353 $has_named_background_color ||
354 $has_custom_background_color ||
355 $has_named_gradient ||
356 $has_custom_gradient
357 ) {
358 $classnames[] = 'has-background';
359 }
360 if ( $has_named_background_color ) {
361 $classnames[] = sprintf( 'has-%s-background-color', $attributes['backgroundColor'] );
362 }
363 if ( $has_named_gradient ) {
364 $classnames[] = sprintf( 'has-%s-gradient-background', $attributes['gradient'] );
365 }
366
367 return implode( ' ', $classnames );
368 }
369