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

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