PluginProbe
Gutenberg / 12.6.0
Gutenberg v12.6.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 7.4.0 All 402 releases
gutenberg / build / block-library / blocks / search.php

search.php in Gutenberg 12.6.0, at build/block-library/blocks/search.php

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