2 /** |
2 /** |
3 * Server-side rendering of the `core/navigation-submenu` block. |
3 * Server-side rendering of the `core/navigation-submenu` block. |
4 * |
4 * |
5 * @package WordPress |
5 * @package WordPress |
6 */ |
6 */ |
7 |
|
8 /** |
|
9 * Build an array with CSS classes and inline styles defining the colors |
|
10 * which will be applied to the navigation markup in the front-end. |
|
11 * |
|
12 * @param array $context Navigation block context. |
|
13 * @param array $attributes Block attributes. |
|
14 * @return array Colors CSS classes and inline styles. |
|
15 */ |
|
16 function block_core_navigation_submenu_build_css_colors( $context, $attributes ) { |
|
17 $colors = array( |
|
18 'css_classes' => array(), |
|
19 'inline_styles' => '', |
|
20 ); |
|
21 |
|
22 $is_sub_menu = isset( $attributes['isTopLevelItem'] ) ? ( ! $attributes['isTopLevelItem'] ) : false; |
|
23 |
|
24 // Text color. |
|
25 $named_text_color = null; |
|
26 $custom_text_color = null; |
|
27 |
|
28 if ( $is_sub_menu && array_key_exists( 'customOverlayTextColor', $context ) ) { |
|
29 $custom_text_color = $context['customOverlayTextColor']; |
|
30 } elseif ( $is_sub_menu && array_key_exists( 'overlayTextColor', $context ) ) { |
|
31 $named_text_color = $context['overlayTextColor']; |
|
32 } elseif ( array_key_exists( 'customTextColor', $context ) ) { |
|
33 $custom_text_color = $context['customTextColor']; |
|
34 } elseif ( array_key_exists( 'textColor', $context ) ) { |
|
35 $named_text_color = $context['textColor']; |
|
36 } elseif ( isset( $context['style']['color']['text'] ) ) { |
|
37 $custom_text_color = $context['style']['color']['text']; |
|
38 } |
|
39 |
|
40 // If has text color. |
|
41 if ( ! is_null( $named_text_color ) ) { |
|
42 // Add the color class. |
|
43 array_push( $colors['css_classes'], 'has-text-color', sprintf( 'has-%s-color', $named_text_color ) ); |
|
44 } elseif ( ! is_null( $custom_text_color ) ) { |
|
45 // Add the custom color inline style. |
|
46 $colors['css_classes'][] = 'has-text-color'; |
|
47 $colors['inline_styles'] .= sprintf( 'color: %s;', $custom_text_color ); |
|
48 } |
|
49 |
|
50 // Background color. |
|
51 $named_background_color = null; |
|
52 $custom_background_color = null; |
|
53 |
|
54 if ( $is_sub_menu && array_key_exists( 'customOverlayBackgroundColor', $context ) ) { |
|
55 $custom_background_color = $context['customOverlayBackgroundColor']; |
|
56 } elseif ( $is_sub_menu && array_key_exists( 'overlayBackgroundColor', $context ) ) { |
|
57 $named_background_color = $context['overlayBackgroundColor']; |
|
58 } elseif ( array_key_exists( 'customBackgroundColor', $context ) ) { |
|
59 $custom_background_color = $context['customBackgroundColor']; |
|
60 } elseif ( array_key_exists( 'backgroundColor', $context ) ) { |
|
61 $named_background_color = $context['backgroundColor']; |
|
62 } elseif ( isset( $context['style']['color']['background'] ) ) { |
|
63 $custom_background_color = $context['style']['color']['background']; |
|
64 } |
|
65 |
|
66 // If has background color. |
|
67 if ( ! is_null( $named_background_color ) ) { |
|
68 // Add the background-color class. |
|
69 array_push( $colors['css_classes'], 'has-background', sprintf( 'has-%s-background-color', $named_background_color ) ); |
|
70 } elseif ( ! is_null( $custom_background_color ) ) { |
|
71 // Add the custom background-color inline style. |
|
72 $colors['css_classes'][] = 'has-background'; |
|
73 $colors['inline_styles'] .= sprintf( 'background-color: %s;', $custom_background_color ); |
|
74 } |
|
75 |
|
76 return $colors; |
|
77 } |
|
78 |
7 |
79 /** |
8 /** |
80 * Build an array with CSS classes and inline styles defining the font sizes |
9 * Build an array with CSS classes and inline styles defining the font sizes |
81 * which will be applied to the navigation markup in the front-end. |
10 * which will be applied to the navigation markup in the front-end. |
|
11 * |
|
12 * @since 5.9.0 |
82 * |
13 * |
83 * @param array $context Navigation block context. |
14 * @param array $context Navigation block context. |
84 * @return array Font size CSS classes and inline styles. |
15 * @return array Font size CSS classes and inline styles. |
85 */ |
16 */ |
86 function block_core_navigation_submenu_build_css_font_sizes( $context ) { |
17 function block_core_navigation_submenu_build_css_font_sizes( $context ) { |
96 if ( $has_named_font_size ) { |
27 if ( $has_named_font_size ) { |
97 // Add the font size class. |
28 // Add the font size class. |
98 $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] ); |
29 $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] ); |
99 } elseif ( $has_custom_font_size ) { |
30 } elseif ( $has_custom_font_size ) { |
100 // Add the custom font size inline style. |
31 // Add the custom font size inline style. |
101 $font_sizes['inline_styles'] = sprintf( 'font-size: %s;', $context['style']['typography']['fontSize'] ); |
32 $font_sizes['inline_styles'] = sprintf( |
|
33 'font-size: %s;', |
|
34 wp_get_typography_font_size_value( |
|
35 array( |
|
36 'size' => $context['style']['typography']['fontSize'], |
|
37 ) |
|
38 ) |
|
39 ); |
102 } |
40 } |
103 |
41 |
104 return $font_sizes; |
42 return $font_sizes; |
105 } |
43 } |
106 |
44 |
107 /** |
45 /** |
108 * Returns the top-level submenu SVG chevron icon. |
46 * Returns the top-level submenu SVG chevron icon. |
|
47 * |
|
48 * @since 5.9.0 |
109 * |
49 * |
110 * @return string |
50 * @return string |
111 */ |
51 */ |
112 function block_core_navigation_submenu_render_submenu_icon() { |
52 function block_core_navigation_submenu_render_submenu_icon() { |
113 return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" focusable="false"><path d="M1.50002 4L6.00002 8L10.5 4" stroke-width="1.5"></path></svg>'; |
53 return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" focusable="false"><path d="M1.50002 4L6.00002 8L10.5 4" stroke-width="1.5"></path></svg>'; |
114 } |
54 } |
115 |
55 |
116 /** |
56 /** |
117 * Renders the `core/navigation-submenu` block. |
57 * Renders the `core/navigation-submenu` block. |
|
58 * |
|
59 * @since 5.9.0 |
118 * |
60 * |
119 * @param array $attributes The block attributes. |
61 * @param array $attributes The block attributes. |
120 * @param string $content The saved content. |
62 * @param string $content The saved content. |
121 * @param WP_Block $block The parsed block. |
63 * @param WP_Block $block The parsed block. |
122 * |
64 * |
123 * @return string Returns the post content with the legacy widget added. |
65 * @return string Returns the post content with the legacy widget added. |
124 */ |
66 */ |
125 function render_block_core_navigation_submenu( $attributes, $content, $block ) { |
67 function render_block_core_navigation_submenu( $attributes, $content, $block ) { |
126 |
|
127 $navigation_link_has_id = isset( $attributes['id'] ) && is_numeric( $attributes['id'] ); |
68 $navigation_link_has_id = isset( $attributes['id'] ) && is_numeric( $attributes['id'] ); |
128 $is_post_type = isset( $attributes['kind'] ) && 'post-type' === $attributes['kind']; |
69 $is_post_type = isset( $attributes['kind'] ) && 'post-type' === $attributes['kind']; |
129 $is_post_type = $is_post_type || isset( $attributes['type'] ) && ( 'post' === $attributes['type'] || 'page' === $attributes['type'] ); |
70 $is_post_type = $is_post_type || isset( $attributes['type'] ) && ( 'post' === $attributes['type'] || 'page' === $attributes['type'] ); |
130 |
71 |
131 // Don't render the block's subtree if it is a draft. |
72 // Don't render the block's subtree if it is a draft. |
136 // Don't render the block's subtree if it has no label. |
77 // Don't render the block's subtree if it has no label. |
137 if ( empty( $attributes['label'] ) ) { |
78 if ( empty( $attributes['label'] ) ) { |
138 return ''; |
79 return ''; |
139 } |
80 } |
140 |
81 |
141 $colors = block_core_navigation_submenu_build_css_colors( $block->context, $attributes ); |
|
142 $font_sizes = block_core_navigation_submenu_build_css_font_sizes( $block->context ); |
82 $font_sizes = block_core_navigation_submenu_build_css_font_sizes( $block->context ); |
143 $classes = array_merge( |
83 $style_attribute = $font_sizes['inline_styles']; |
144 $colors['css_classes'], |
84 |
145 $font_sizes['css_classes'] |
85 $css_classes = trim( implode( ' ', $font_sizes['css_classes'] ) ); |
146 ); |
|
147 $style_attribute = ( $colors['inline_styles'] . $font_sizes['inline_styles'] ); |
|
148 |
|
149 $css_classes = trim( implode( ' ', $classes ) ); |
|
150 $has_submenu = count( $block->inner_blocks ) > 0; |
86 $has_submenu = count( $block->inner_blocks ) > 0; |
151 $is_active = ! empty( $attributes['id'] ) && ( get_the_ID() === $attributes['id'] ); |
87 $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] ); |
|
88 $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind ); |
|
89 |
|
90 if ( is_post_type_archive() ) { |
|
91 $queried_archive_link = get_post_type_archive_link( get_queried_object()->name ); |
|
92 if ( $attributes['url'] === $queried_archive_link ) { |
|
93 $is_active = true; |
|
94 } |
|
95 } |
152 |
96 |
153 $show_submenu_indicators = isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon']; |
97 $show_submenu_indicators = isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon']; |
154 $open_on_click = isset( $block->context['openSubmenusOnClick'] ) && $block->context['openSubmenusOnClick']; |
98 $open_on_click = isset( $block->context['openSubmenusOnClick'] ) && $block->context['openSubmenusOnClick']; |
155 $open_on_hover_and_click = isset( $block->context['openSubmenusOnClick'] ) && ! $block->context['openSubmenusOnClick'] && |
99 $open_on_hover_and_click = isset( $block->context['openSubmenusOnClick'] ) && ! $block->context['openSubmenusOnClick'] && |
156 $show_submenu_indicators; |
100 $show_submenu_indicators; |
181 // If Submenus open on hover, we render an anchor tag with attributes. |
125 // If Submenus open on hover, we render an anchor tag with attributes. |
182 // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click. |
126 // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click. |
183 if ( ! $open_on_click ) { |
127 if ( ! $open_on_click ) { |
184 $item_url = isset( $attributes['url'] ) ? $attributes['url'] : ''; |
128 $item_url = isset( $attributes['url'] ) ? $attributes['url'] : ''; |
185 // Start appending HTML attributes to anchor tag. |
129 // Start appending HTML attributes to anchor tag. |
186 $html .= '<a class="wp-block-navigation-item__content" href="' . esc_url( $item_url ) . '"'; |
130 $html .= '<a class="wp-block-navigation-item__content"'; |
|
131 |
|
132 // The href attribute on a and area elements is not required; |
|
133 // when those elements do not have href attributes they do not create hyperlinks. |
|
134 // But also The href attribute must have a value that is a valid URL potentially |
|
135 // surrounded by spaces. |
|
136 // see: https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements. |
|
137 if ( ! empty( $item_url ) ) { |
|
138 $html .= ' href="' . esc_url( $item_url ) . '"'; |
|
139 } |
187 |
140 |
188 if ( $is_active ) { |
141 if ( $is_active ) { |
189 $html .= ' aria-current="page"'; |
142 $html .= ' aria-current="page"'; |
190 } |
143 } |
191 |
144 |
232 $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>'; |
185 $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>'; |
233 |
186 |
234 } |
187 } |
235 |
188 |
236 if ( $has_submenu ) { |
189 if ( $has_submenu ) { |
|
190 // Copy some attributes from the parent block to this one. |
|
191 // Ideally this would happen in the client when the block is created. |
|
192 if ( array_key_exists( 'overlayTextColor', $block->context ) ) { |
|
193 $attributes['textColor'] = $block->context['overlayTextColor']; |
|
194 } |
|
195 if ( array_key_exists( 'overlayBackgroundColor', $block->context ) ) { |
|
196 $attributes['backgroundColor'] = $block->context['overlayBackgroundColor']; |
|
197 } |
|
198 if ( array_key_exists( 'customOverlayTextColor', $block->context ) ) { |
|
199 $attributes['style']['color']['text'] = $block->context['customOverlayTextColor']; |
|
200 } |
|
201 if ( array_key_exists( 'customOverlayBackgroundColor', $block->context ) ) { |
|
202 $attributes['style']['color']['background'] = $block->context['customOverlayBackgroundColor']; |
|
203 } |
|
204 |
|
205 // This allows us to be able to get a response from wp_apply_colors_support. |
|
206 $block->block_type->supports['color'] = true; |
|
207 $colors_supports = wp_apply_colors_support( $block->block_type, $attributes ); |
|
208 $css_classes = 'wp-block-navigation__submenu-container'; |
|
209 if ( array_key_exists( 'class', $colors_supports ) ) { |
|
210 $css_classes .= ' ' . $colors_supports['class']; |
|
211 } |
|
212 |
|
213 $style_attribute = ''; |
|
214 if ( array_key_exists( 'style', $colors_supports ) ) { |
|
215 $style_attribute = $colors_supports['style']; |
|
216 } |
|
217 |
237 $inner_blocks_html = ''; |
218 $inner_blocks_html = ''; |
238 foreach ( $block->inner_blocks as $inner_block ) { |
219 foreach ( $block->inner_blocks as $inner_block ) { |
239 $inner_blocks_html .= $inner_block->render(); |
220 $inner_blocks_html .= $inner_block->render(); |
240 } |
221 } |
241 |
222 |
|
223 if ( strpos( $inner_blocks_html, 'current-menu-item' ) ) { |
|
224 $tag_processor = new WP_HTML_Tag_Processor( $html ); |
|
225 while ( $tag_processor->next_tag( array( 'class_name' => 'wp-block-navigation-item__content' ) ) ) { |
|
226 $tag_processor->add_class( 'current-menu-ancestor' ); |
|
227 } |
|
228 $html = $tag_processor->get_updated_html(); |
|
229 } |
|
230 |
|
231 $wrapper_attributes = get_block_wrapper_attributes( |
|
232 array( |
|
233 'class' => $css_classes, |
|
234 'style' => $style_attribute, |
|
235 ) |
|
236 ); |
|
237 |
242 $html .= sprintf( |
238 $html .= sprintf( |
243 '<ul class="wp-block-navigation__submenu-container">%s</ul>', |
239 '<ul %s>%s</ul>', |
|
240 $wrapper_attributes, |
244 $inner_blocks_html |
241 $inner_blocks_html |
245 ); |
242 ); |
|
243 |
246 } |
244 } |
247 |
245 |
248 $html .= '</li>'; |
246 $html .= '</li>'; |
249 |
247 |
250 return $html; |
248 return $html; |
251 } |
249 } |
252 |
250 |
253 /** |
251 /** |
254 * Register the navigation submenu block. |
252 * Register the navigation submenu block. |
|
253 * |
|
254 * @since 5.9.0 |
255 * |
255 * |
256 * @uses render_block_core_navigation_submenu() |
256 * @uses render_block_core_navigation_submenu() |
257 * @throws WP_Error An WP_Error exception parsing the block definition. |
257 * @throws WP_Error An WP_Error exception parsing the block definition. |
258 */ |
258 */ |
259 function register_block_core_navigation_submenu() { |
259 function register_block_core_navigation_submenu() { |