PluginProbe
Gutenberg / 23.2.0
Gutenberg v23.2.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 / scripts / block-library / navigation-submenu.php
build/scripts/block-library
accordion 6 months ago accordion-heading 9 months ago accordion-item 4 months ago accordion-panel 7 months ago archives 7 months ago audio 10 months ago avatar 7 months ago block 7 months ago breadcrumbs 7 months ago button 6 months ago buttons 7 months ago calendar 7 months ago categories 7 months ago code 10 months ago column 10 months ago columns 10 months ago comment-author-avatar 10 months ago comment-author-name 7 months ago comment-content 7 months ago comment-date 7 months ago comment-edit-link 7 months ago comment-reply-link 7 months ago comment-template 7 months ago comments 7 months ago comments-pagination 7 months ago comments-pagination-next 7 months ago comments-pagination-numbers 7 months ago comments-pagination-previous 7 months ago comments-title 7 months ago cover 10 months ago details 10 months ago embed 7 months ago file 10 months ago footnotes 7 months ago form 4 months ago form-input 4 months ago form-submission-notification 4 months ago form-submit-button 4 months ago freeform 7 months ago gallery 6 months ago group 4 months ago heading 7 months ago home-link 7 months ago html 5 months ago icon 5 months ago image 6 months ago latest-comments 7 months ago latest-posts 7 months ago list 7 months ago list-item 5 months ago loginout 7 months ago math 7 months ago media-text 10 months ago missing 7 months ago more 7 months ago navigation 6 months ago navigation-link 5 months ago navigation-overlay-close 6 months ago navigation-submenu 6 months ago nextpage 5 months ago page-list 6 months ago page-list-item 6 months ago paragraph 6 months ago pattern 9 months ago playlist 6 months ago playlist-track 6 months ago post-author 6 months ago post-author-biography 6 months ago post-author-name 6 months ago post-comment 10 months ago post-comments-count 6 months ago post-comments-form 6 months ago post-comments-link 6 months ago post-content 7 months ago post-date 5 months ago post-excerpt 5 months ago post-featured-image 7 months ago post-navigation-link 6 months ago post-template 7 months ago post-terms 6 months ago post-time-to-read 6 months ago post-title 6 months ago preformatted 10 months ago pullquote 4 months ago query 6 months ago query-no-results 7 months ago query-pagination 7 months ago query-pagination-next 7 months ago query-pagination-numbers 7 months ago query-pagination-previous 7 months ago query-title 6 months ago query-total 7 months ago quote 10 months ago read-more 7 months ago rss 7 months ago search 4 months ago separator 10 months ago shortcode 5 months ago site-logo 7 months ago site-tagline 6 months ago site-title 6 months ago social-link 7 months ago social-links 7 months ago spacer 10 months ago tab 4 months ago tab-list 4 months ago tab-panel 4 months ago tab-panels 4 months ago table 10 months ago table-of-contents 7 months ago tabs 4 months ago tag-cloud 7 months ago template-part 10 months ago term-count 7 months ago term-description 6 months ago term-name 7 months ago term-template 7 months ago terms-query 7 months ago text-columns 10 months ago verse 6 months ago video 10 months ago accordion-item.php 2.9 KB 5 months ago accordion.php 1.2 KB 10 months ago archives.php 4.4 KB 7 months ago avatar.php 5.6 KB 7 months ago block.php 4.1 KB 10 months ago blocks-manifest.php 213.3 KB 4 months ago breadcrumbs.php 19.0 KB 7 months ago button.php 4.2 KB 6 months ago calendar.php 6.1 KB 10 months ago categories.php 4.9 KB 7 months ago comment-author-avatar.php 2.5 KB 7 months ago comment-author-name.php 2.1 KB 10 months ago comment-content.php 2.4 KB 10 months ago comment-date.php 1.9 KB 10 months ago comment-edit-link.php 1.7 KB 10 months ago comment-reply-link.php 2.1 KB 10 months ago comment-template.php 4.5 KB 10 months ago comments-pagination-next.php 1.9 KB 10 months ago comments-pagination-numbers.php 1.6 KB 10 months ago comments-pagination-previous.php 1.8 KB 10 months ago comments-pagination.php 1.3 KB 10 months ago comments-title.php 2.8 KB 7 months ago comments.php 6.7 KB 10 months ago cover.php 7.3 KB 5 months ago details.php 1.5 KB 5 months ago file.php 1.9 KB 10 months ago footnotes.php 3.8 KB 7 months ago form-input.php 1.2 KB 10 months ago form-submission-notification.php 1.5 KB 10 months ago form.php 5.8 KB 10 months ago gallery.php 8.9 KB 6 months ago heading.php 1.3 KB 10 months ago home-link.php 4.9 KB 5 months ago icon.php 4.0 KB 6 months ago image.php 17.4 KB 4 months ago index.js 2.6 MB 3 months ago index.js.map 3.9 MB 3 months ago index.min.asset.php 696 B 3 months ago index.min.js 1.1 MB 3 months ago index.min.js.map 4.0 MB 3 months ago latest-comments.php 5.4 KB 7 months ago latest-posts.php 8.7 KB 4 months ago list.php 1.3 KB 10 months ago loginout.php 2.1 KB 5 months ago media-text.php 4.2 KB 6 months ago navigation-link.php 15.3 KB 5 months ago navigation-overlay-close.php 1.8 KB 6 months ago navigation-submenu.php 11.0 KB 5 months ago navigation.php 63.6 KB 3 months ago page-list-item.php 385 B 10 months ago page-list.php 14.3 KB 5 months ago paragraph.php 1.2 KB 7 months ago pattern.php 1.8 KB 10 months ago playlist-track.php 2.1 KB 6 months ago playlist.php 4.6 KB 6 months ago post-author-biography.php 1.5 KB 10 months ago post-author-name.php 1.9 KB 10 months ago post-author.php 2.7 KB 10 months ago post-comment.php 429 B 10 months ago post-comments-count.php 1.3 KB 10 months ago post-comments-form.php 2.8 KB 10 months ago post-comments-link.php 2.2 KB 10 months ago post-content.php 2.3 KB 10 months ago post-date.php 3.6 KB 7 months ago post-excerpt.php 4.3 KB 7 months ago post-featured-image.php 9.1 KB 6 months ago post-navigation-link.php 4.7 KB 7 months ago post-template.php 5.9 KB 4 months ago post-terms.php 3.6 KB 10 months ago post-time-to-read.php 6.3 KB 7 months ago post-title.php 2.1 KB 7 months ago query-no-results.php 1.8 KB 10 months ago query-pagination-next.php 3.6 KB 6 months ago query-pagination-numbers.php 4.6 KB 6 months ago query-pagination-previous.php 3.4 KB 6 months ago query-pagination.php 1.2 KB 10 months ago query-title.php 2.7 KB 6 months ago query-total.php 2.5 KB 6 months ago query.php 5.6 KB 10 months ago read-more.php 1.8 KB 10 months ago rss.php 4.5 KB 10 months ago search.php 24.1 KB 4 months ago shortcode.php 779 B 10 months ago site-logo.php 6.4 KB 10 months ago site-tagline.php 1.2 KB 10 months ago site-title.php 1.9 KB 10 months ago social-link.php 66.2 KB 7 months ago tab-list.php 2.1 KB 4 months ago tab-panel.php 2.1 KB 4 months ago tab.php 2.1 KB 4 months ago table-of-contents.php 1.2 KB 10 months ago tabs.php 4.6 KB 4 months ago tag-cloud.php 1.6 KB 10 months ago template-part.php 10.3 KB 6 months ago term-count.php 1.8 KB 10 months ago term-description.php 1.8 KB 10 months ago term-name.php 2.0 KB 7 months ago term-template.php 4.5 KB 7 months ago video.php 2.7 KB 10 months ago

navigation-submenu.php in Gutenberg 23.2.0, at build/scripts/block-library/navigation-submenu.php

321 lines 11.0 KB Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/navigation-submenu` block.
4 *
5 * @package WordPress
6 */
7
8 require_once __DIR__ . '/navigation-link/shared/item-should-render.php';
9 require_once __DIR__ . '/navigation-link/shared/render-submenu-icon.php';
10 require_once __DIR__ . '/navigation-link/shared/build-css-font-sizes.php';
11
12 /**
13 * Returns the submenu visibility value with backward compatibility
14 * for the deprecated openSubmenusOnClick attribute.
15 *
16 * This function centralizes the migration logic from the boolean
17 * openSubmenusOnClick to the new submenuVisibility enum.
18 *
19 * Backward compatibility handling:
20 * - Legacy blocks (saved before migration, never opened in editor):
21 * Have openSubmenusOnClick in database. Parent Navigation block passes it via context.
22 * We prioritize openSubmenusOnClick to preserve the original behavior.
23 *
24 * - Migrated blocks (opened in editor after migration):
25 * JavaScript deprecation removes openSubmenusOnClick and sets submenuVisibility.
26 * We use submenuVisibility since openSubmenusOnClick is null.
27 *
28 * - New blocks (created after migration):
29 * Only have submenuVisibility, openSubmenusOnClick is null.
30 * We use submenuVisibility.
31 *
32 * @since 6.9.0
33 *
34 * @param array $context Block context from parent Navigation block.
35 * @return string The visibility mode: 'hover', 'click', or 'always'.
36 */
37 function gutenberg_block_core_navigation_submenu_get_submenu_visibility( $context ) {
38 $deprecated_open_submenus_on_click = $context['openSubmenusOnClick'] ?? null;
39
40 // For backward compatibility, prioritize the legacy attribute if present. If it has been loaded and saved in the editor, then
41 // the deprecated attribute will be replaced by submenuVisibility.
42 if ( null !== $deprecated_open_submenus_on_click ) {
43 // Convert boolean to string: true -> 'click', false -> 'hover'.
44 return ! empty( $deprecated_open_submenus_on_click ) ? 'click' : 'hover';
45 }
46
47 $submenu_visibility = $context['submenuVisibility'] ?? null;
48
49 // Use submenuVisibility for migrated/new blocks.
50 return $submenu_visibility ?? 'hover';
51 }
52
53 /**
54 * Renders the `core/navigation-submenu` block.
55 *
56 * @since 5.9.0
57 *
58 * @param array $attributes The block attributes.
59 * @param string $content The saved content.
60 * @param WP_Block $block The parsed block.
61 *
62 * @return string Returns the post content with the legacy widget added.
63 */
64 function gutenberg_render_block_core_navigation_submenu( $attributes, $content, $block ) {
65 // Check if this navigation item should render based on post status.
66 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
67 if ( ! gutenberg_block_core_shared_navigation_item_should_render( $attributes, $block ) ) {
68 return '';
69 }
70 }
71
72 // Don't render the block's subtree if it has no label.
73 if ( empty( $attributes['label'] ) ) {
74 return '';
75 }
76
77 // The build system prefixes this function with "gutenberg_" to avoid
78 // collisions with the core version. Until this function is backported to
79 // core, we need to guard its use and only call the prefixed name in
80 // the plugin.
81 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
82 $font_sizes = gutenberg_block_core_shared_navigation_build_css_font_sizes( $block->context );
83 } else {
84 $font_sizes = block_core_shared_navigation_build_css_font_sizes( $block->context );
85 }
86 $style_attribute = $font_sizes['inline_styles'];
87
88 // Render inner blocks first to check if any menu items will actually display.
89 $inner_blocks_html = '';
90 foreach ( $block->inner_blocks as $inner_block ) {
91 $inner_blocks_html .= $inner_block->render();
92 }
93 $has_submenu = ! empty( trim( $inner_blocks_html ) );
94
95 $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] );
96 $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind );
97
98 if ( is_post_type_archive() && ! empty( $attributes['url'] ) ) {
99 $queried_archive_link = get_post_type_archive_link( get_queried_object()->name );
100 if ( $attributes['url'] === $queried_archive_link ) {
101 $is_active = true;
102 }
103 }
104
105 $show_submenu_indicators = isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon'];
106 $computed_visibility = gutenberg_block_core_navigation_submenu_get_submenu_visibility( $block->context );
107 $open_on_click = 'click' === $computed_visibility;
108 $open_on_hover = 'hover' === $computed_visibility;
109 $open_on_hover_and_click = $open_on_hover && $show_submenu_indicators;
110
111 $classes = array(
112 'wp-block-navigation-item',
113 );
114 $classes = array_merge(
115 $classes,
116 $font_sizes['css_classes']
117 );
118 if ( $has_submenu ) {
119 $classes[] = 'has-child';
120 }
121 if ( $open_on_click ) {
122 $classes[] = 'open-on-click';
123 }
124 if ( $open_on_hover_and_click ) {
125 $classes[] = 'open-on-hover-click';
126 }
127 if ( 'always' === $computed_visibility ) {
128 $classes[] = 'open-always';
129 }
130 if ( $is_active ) {
131 $classes[] = 'current-menu-item';
132 }
133
134 $wrapper_attributes = get_block_wrapper_attributes(
135 array(
136 'class' => implode( ' ', $classes ),
137 'style' => $style_attribute,
138 )
139 );
140
141 $label = '';
142
143 if ( isset( $attributes['label'] ) ) {
144 $label .= wp_kses_post( $attributes['label'] );
145 }
146
147 $aria_label = sprintf(
148 /* translators: Accessibility text. %s: Parent page title. */
149 __( '%s submenu' ),
150 wp_strip_all_tags( $label )
151 );
152
153 $html = '<li ' . $wrapper_attributes . '>';
154
155 // If Submenus open on hover or are always open, we render an anchor tag with attributes.
156 // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click.
157 if ( ! $open_on_click ) {
158 $item_url = $attributes['url'] ?? '';
159 // Start appending HTML attributes to anchor tag.
160 $html .= '<a class="wp-block-navigation-item__content"';
161
162 // The href attribute on a and area elements is not required;
163 // when those elements do not have href attributes they do not create hyperlinks.
164 // But also The href attribute must have a value that is a valid URL potentially
165 // surrounded by spaces.
166 // see: https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements.
167 if ( ! empty( $item_url ) ) {
168 $html .= ' href="' . esc_url( $item_url ) . '"';
169 }
170
171 if ( $is_active ) {
172 $html .= ' aria-current="page"';
173 }
174
175 if ( isset( $attributes['opensInNewTab'] ) && true === $attributes['opensInNewTab'] ) {
176 $html .= ' target="_blank" ';
177 }
178
179 if ( isset( $attributes['rel'] ) ) {
180 $html .= ' rel="' . esc_attr( $attributes['rel'] ) . '"';
181 } elseif ( isset( $attributes['nofollow'] ) && $attributes['nofollow'] ) {
182 $html .= ' rel="nofollow"';
183 }
184
185 if ( isset( $attributes['title'] ) ) {
186 $html .= ' title="' . esc_attr( $attributes['title'] ) . '"';
187 }
188
189 $html .= '>';
190 // End appending HTML attributes to anchor tag.
191
192 $html .= '<span class="wp-block-navigation-item__label">';
193 $html .= $label;
194 $html .= '</span>';
195
196 // Add description if available.
197 if ( ! empty( $attributes['description'] ) ) {
198 $html .= '<span class="wp-block-navigation-item__description">';
199 $html .= wp_kses_post( $attributes['description'] );
200 $html .= '</span>';
201 }
202
203 $html .= '</a>';
204 // End anchor tag content.
205
206 if ( $show_submenu_indicators && $has_submenu ) {
207 // The submenu icon is rendered in a button here
208 // so that there's a clickable element to open the submenu.
209 $html .= '<button aria-label="' . esc_attr( $aria_label ) . '" class="wp-block-navigation__submenu-icon wp-block-navigation-submenu__toggle" aria-expanded="false">';
210 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
211 $html .= gutenberg_block_core_shared_navigation_render_submenu_icon();
212 } else {
213 $html .= block_core_shared_navigation_render_submenu_icon();
214 }
215 $html .= '</button>';
216 }
217 } else {
218 $html .= '<button aria-label="' . esc_attr( $aria_label ) . '" class="wp-block-navigation-item__content wp-block-navigation-submenu__toggle" aria-expanded="false">';
219
220 // Wrap title with span to isolate it from submenu icon.
221 $html .= '<span class="wp-block-navigation-item__label">';
222
223 $html .= $label;
224
225 $html .= '</span>';
226
227 // Add description if available.
228 if ( ! empty( $attributes['description'] ) ) {
229 $html .= '<span class="wp-block-navigation-item__description">';
230 $html .= wp_kses_post( $attributes['description'] );
231 $html .= '</span>';
232 }
233
234 $html .= '</button>';
235
236 if ( $has_submenu ) {
237 $html .= '<span class="wp-block-navigation__submenu-icon">';
238 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
239 $html .= gutenberg_block_core_shared_navigation_render_submenu_icon();
240 } else {
241 $html .= block_core_shared_navigation_render_submenu_icon();
242 }
243 $html .= '</span>';
244 }
245 }
246
247 if ( $has_submenu ) {
248 // Copy some attributes from the parent block to this one.
249 // Ideally this would happen in the client when the block is created.
250 if ( array_key_exists( 'overlayTextColor', $block->context ) ) {
251 $attributes['textColor'] = $block->context['overlayTextColor'];
252 }
253 if ( array_key_exists( 'overlayBackgroundColor', $block->context ) ) {
254 $attributes['backgroundColor'] = $block->context['overlayBackgroundColor'];
255 }
256 if ( array_key_exists( 'customOverlayTextColor', $block->context ) ) {
257 $attributes['style']['color']['text'] = $block->context['customOverlayTextColor'];
258 }
259 if ( array_key_exists( 'customOverlayBackgroundColor', $block->context ) ) {
260 $attributes['style']['color']['background'] = $block->context['customOverlayBackgroundColor'];
261 }
262
263 // This allows us to be able to get a response from gutenberg_apply_colors_support.
264 $block->block_type->supports['color'] = true;
265 $colors_supports = gutenberg_apply_colors_support( $block->block_type, $attributes );
266 $css_classes = 'wp-block-navigation__submenu-container';
267 if ( array_key_exists( 'class', $colors_supports ) ) {
268 $css_classes .= ' ' . $colors_supports['class'];
269 }
270
271 $style_attribute = '';
272 if ( array_key_exists( 'style', $colors_supports ) ) {
273 $style_attribute = $colors_supports['style'];
274 }
275
276 if ( strpos( $inner_blocks_html, 'current-menu-item' ) ) {
277 $tag_processor = new WP_HTML_Tag_Processor( $html );
278 while ( $tag_processor->next_tag( array( 'class_name' => 'wp-block-navigation-item' ) ) ) {
279 $tag_processor->add_class( 'current-menu-ancestor' );
280 }
281 $html = $tag_processor->get_updated_html();
282 }
283
284 $wrapper_attributes = get_block_wrapper_attributes(
285 array(
286 'class' => $css_classes,
287 'style' => $style_attribute,
288 )
289 );
290
291 $html .= sprintf(
292 '<ul %s>%s</ul>',
293 $wrapper_attributes,
294 $inner_blocks_html
295 );
296
297 }
298
299 $html .= '</li>';
300
301 return $html;
302 }
303
304 /**
305 * Register the navigation submenu block.
306 *
307 * @since 5.9.0
308 *
309 * @uses gutenberg_render_block_core_navigation_submenu()
310 * @throws WP_Error An WP_Error exception parsing the block definition.
311 */
312 function gutenberg_register_block_core_navigation_submenu() {
313 register_block_type_from_metadata(
314 __DIR__ . '/navigation-submenu',
315 array(
316 'render_callback' => 'gutenberg_render_block_core_navigation_submenu',
317 )
318 );
319 }
320 add_action( 'init', 'gutenberg_register_block_core_navigation_submenu', 20 );
321