render_block_core_navigation_submenu

The timeline below displays how wordpress function render_block_core_navigation_submenu has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.3

/**
 * Renders the `core/navigation-submenu` block.
 *
 * @param array    $attributes The block attributes.
 * @param string   $content    The saved content.
 * @param WP_Block $block      The parsed block.
 *
 * @return string Returns the post content with the legacy widget added.
 */
function render_block_core_navigation_submenu($attributes, $content, $block)
{
    $navigation_link_has_id = isset($attributes['id']) && is_numeric($attributes['id']);
    $is_post_type = isset($attributes['kind']) && 'post-type' === $attributes['kind'];
    $is_post_type = $is_post_type || isset($attributes['type']) && ('post' === $attributes['type'] || 'page' === $attributes['type']);
    // Don't render the block's subtree if it is a draft.
    if ($is_post_type && $navigation_link_has_id && 'publish' !== get_post_status($attributes['id'])) {
        return '';
    }
    // Don't render the block's subtree if it has no label.
    if (empty($attributes['label'])) {
        return '';
    }
    $font_sizes = block_core_navigation_submenu_build_css_font_sizes($block->context);
    $style_attribute = $font_sizes['inline_styles'];
    $css_classes = trim(implode(' ', $font_sizes['css_classes']));
    $has_submenu = count($block->inner_blocks) > 0;
    $kind = empty($attributes['kind']) ? 'post_type' : str_replace('-', '_', $attributes['kind']);
    $is_active = !empty($attributes['id']) && get_queried_object_id() === (int) $attributes['id'] && !empty(get_queried_object()->{$kind});
    $show_submenu_indicators = isset($block->context['showSubmenuIcon']) && $block->context['showSubmenuIcon'];
    $open_on_click = isset($block->context['openSubmenusOnClick']) && $block->context['openSubmenusOnClick'];
    $open_on_hover_and_click = isset($block->context['openSubmenusOnClick']) && !$block->context['openSubmenusOnClick'] && $show_submenu_indicators;
    $wrapper_attributes = get_block_wrapper_attributes(array('class' => $css_classes . ' wp-block-navigation-item' . ($has_submenu ? ' has-child' : '') . ($open_on_click ? ' open-on-click' : '') . ($open_on_hover_and_click ? ' open-on-hover-click' : '') . ($is_active ? ' current-menu-item' : ''), 'style' => $style_attribute));
    $label = '';
    if (isset($attributes['label'])) {
        $label .= wp_kses_post($attributes['label']);
    }
    $aria_label = sprintf(
        /* translators: Accessibility text. %s: Parent page title. */
        __('%s submenu'),
        wp_strip_all_tags($label)
    );
    $html = '<li ' . $wrapper_attributes . '>';
    // If Submenus open on hover, we render an anchor tag with attributes.
    // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click.
    if (!$open_on_click) {
        $item_url = isset($attributes['url']) ? $attributes['url'] : '';
        // Start appending HTML attributes to anchor tag.
        $html .= '<a class="wp-block-navigation-item__content"';
        // The href attribute on a and area elements is not required;
        // when those elements do not have href attributes they do not create hyperlinks.
        // But also The href attribute must have a value that is a valid URL potentially
        // surrounded by spaces.
        // see: https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements.
        if (!empty($item_url)) {
            $html .= ' href="' . esc_url($item_url) . '"';
        }
        if ($is_active) {
            $html .= ' aria-current="page"';
        }
        if (isset($attributes['opensInNewTab']) && true === $attributes['opensInNewTab']) {
            $html .= ' target="_blank"  ';
        }
        if (isset($attributes['rel'])) {
            $html .= ' rel="' . esc_attr($attributes['rel']) . '"';
        } elseif (isset($attributes['nofollow']) && $attributes['nofollow']) {
            $html .= ' rel="nofollow"';
        }
        if (isset($attributes['title'])) {
            $html .= ' title="' . esc_attr($attributes['title']) . '"';
        }
        $html .= '>';
        // End appending HTML attributes to anchor tag.
        $html .= $label;
        $html .= '</a>';
        // End anchor tag content.
        if ($show_submenu_indicators) {
            // The submenu icon is rendered in a button here
            // so that there's a clickable element to open the submenu.
            $html .= '<button aria-label="' . esc_attr($aria_label) . '" class="wp-block-navigation__submenu-icon wp-block-navigation-submenu__toggle" aria-expanded="false">' . block_core_navigation_submenu_render_submenu_icon() . '</button>';
        }
    } else {
        // If menus open on click, we render the parent as a button.
        $html .= '<button aria-label="' . esc_attr($aria_label) . '" class="wp-block-navigation-item__content wp-block-navigation-submenu__toggle" aria-expanded="false">';
        // Wrap title with span to isolate it from submenu icon.
        $html .= '<span class="wp-block-navigation-item__label">';
        $html .= $label;
        $html .= '</span>';
        $html .= '</button>';
        $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>';
    }
    if ($has_submenu) {
        // Copy some attributes from the parent block to this one.
        // Ideally this would happen in the client when the block is created.
        if (array_key_exists('overlayTextColor', $block->context)) {
            $attributes['textColor'] = $block->context['overlayTextColor'];
        }
        if (array_key_exists('overlayBackgroundColor', $block->context)) {
            $attributes['backgroundColor'] = $block->context['overlayBackgroundColor'];
        }
        if (array_key_exists('customOverlayTextColor', $block->context)) {
            $attributes['style']['color']['text'] = $block->context['customOverlayTextColor'];
        }
        if (array_key_exists('customOverlayBackgroundColor', $block->context)) {
            $attributes['style']['color']['background'] = $block->context['customOverlayBackgroundColor'];
        }
        // This allows us to be able to get a response from wp_apply_colors_support.
        $block->block_type->supports['color'] = true;
        $colors_supports = wp_apply_colors_support($block->block_type, $attributes);
        $css_classes = 'wp-block-navigation__submenu-container';
        if (array_key_exists('class', $colors_supports)) {
            $css_classes .= ' ' . $colors_supports['class'];
        }
        $style_attribute = '';
        if (array_key_exists('style', $colors_supports)) {
            $style_attribute = $colors_supports['style'];
        }
        $inner_blocks_html = '';
        foreach ($block->inner_blocks as $inner_block) {
            $inner_blocks_html .= $inner_block->render();
        }
        if (strpos($inner_blocks_html, 'current-menu-item')) {
            $tag_processor = new WP_HTML_Tag_Processor($html);
            while ($tag_processor->next_tag(array('class_name' => 'wp-block-navigation-item__content'))) {
                $tag_processor->add_class('current-menu-ancestor');
            }
            $html = $tag_processor->get_updated_html();
        }
        $wrapper_attributes = get_block_wrapper_attributes(array('class' => $css_classes, 'style' => $style_attribute));
        $html .= sprintf('<ul %s>%s</ul>', $wrapper_attributes, $inner_blocks_html);
    }
    $html .= '</li>';
    return $html;
}

WordPress Version: 6.2

/**
 * Renders the `core/navigation-submenu` block.
 *
 * @param array    $attributes The block attributes.
 * @param string   $content    The saved content.
 * @param WP_Block $block      The parsed block.
 *
 * @return string Returns the post content with the legacy widget added.
 */
function render_block_core_navigation_submenu($attributes, $content, $block)
{
    $navigation_link_has_id = isset($attributes['id']) && is_numeric($attributes['id']);
    $is_post_type = isset($attributes['kind']) && 'post-type' === $attributes['kind'];
    $is_post_type = $is_post_type || isset($attributes['type']) && ('post' === $attributes['type'] || 'page' === $attributes['type']);
    // Don't render the block's subtree if it is a draft.
    if ($is_post_type && $navigation_link_has_id && 'publish' !== get_post_status($attributes['id'])) {
        return '';
    }
    // Don't render the block's subtree if it has no label.
    if (empty($attributes['label'])) {
        return '';
    }
    $colors = block_core_navigation_submenu_build_css_colors($block->context, $attributes);
    $font_sizes = block_core_navigation_submenu_build_css_font_sizes($block->context);
    $classes = array_merge($colors['css_classes'], $font_sizes['css_classes']);
    $style_attribute = $colors['inline_styles'] . $font_sizes['inline_styles'];
    $css_classes = trim(implode(' ', $classes));
    $has_submenu = count($block->inner_blocks) > 0;
    $is_active = !empty($attributes['id']) && get_queried_object_id() === (int) $attributes['id'];
    $show_submenu_indicators = isset($block->context['showSubmenuIcon']) && $block->context['showSubmenuIcon'];
    $open_on_click = isset($block->context['openSubmenusOnClick']) && $block->context['openSubmenusOnClick'];
    $open_on_hover_and_click = isset($block->context['openSubmenusOnClick']) && !$block->context['openSubmenusOnClick'] && $show_submenu_indicators;
    $wrapper_attributes = get_block_wrapper_attributes(array('class' => $css_classes . ' wp-block-navigation-item' . ($has_submenu ? ' has-child' : '') . ($open_on_click ? ' open-on-click' : '') . ($open_on_hover_and_click ? ' open-on-hover-click' : '') . ($is_active ? ' current-menu-item' : ''), 'style' => $style_attribute));
    $label = '';
    if (isset($attributes['label'])) {
        $label .= wp_kses_post($attributes['label']);
    }
    $aria_label = sprintf(
        /* translators: Accessibility text. %s: Parent page title. */
        __('%s submenu'),
        wp_strip_all_tags($label)
    );
    $html = '<li ' . $wrapper_attributes . '>';
    // If Submenus open on hover, we render an anchor tag with attributes.
    // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click.
    if (!$open_on_click) {
        $item_url = isset($attributes['url']) ? $attributes['url'] : '';
        // Start appending HTML attributes to anchor tag.
        $html .= '<a class="wp-block-navigation-item__content"';
        // The href attribute on a and area elements is not required;
        // when those elements do not have href attributes they do not create hyperlinks.
        // But also The href attribute must have a value that is a valid URL potentially
        // surrounded by spaces.
        // see: https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements.
        if (!empty($item_url)) {
            $html .= ' href="' . esc_url($item_url) . '"';
        }
        if ($is_active) {
            $html .= ' aria-current="page"';
        }
        if (isset($attributes['opensInNewTab']) && true === $attributes['opensInNewTab']) {
            $html .= ' target="_blank"  ';
        }
        if (isset($attributes['rel'])) {
            $html .= ' rel="' . esc_attr($attributes['rel']) . '"';
        } elseif (isset($attributes['nofollow']) && $attributes['nofollow']) {
            $html .= ' rel="nofollow"';
        }
        if (isset($attributes['title'])) {
            $html .= ' title="' . esc_attr($attributes['title']) . '"';
        }
        $html .= '>';
        // End appending HTML attributes to anchor tag.
        $html .= $label;
        $html .= '</a>';
        // End anchor tag content.
        if ($show_submenu_indicators) {
            // The submenu icon is rendered in a button here
            // so that there's a clickable element to open the submenu.
            $html .= '<button aria-label="' . esc_attr($aria_label) . '" class="wp-block-navigation__submenu-icon wp-block-navigation-submenu__toggle" aria-expanded="false">' . block_core_navigation_submenu_render_submenu_icon() . '</button>';
        }
    } else {
        // If menus open on click, we render the parent as a button.
        $html .= '<button aria-label="' . esc_attr($aria_label) . '" class="wp-block-navigation-item__content wp-block-navigation-submenu__toggle" aria-expanded="false">';
        // Wrap title with span to isolate it from submenu icon.
        $html .= '<span class="wp-block-navigation-item__label">';
        $html .= $label;
        $html .= '</span>';
        $html .= '</button>';
        $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>';
    }
    if ($has_submenu) {
        $colors = block_core_navigation_submenu_build_css_colors($block->context, $attributes, $has_submenu);
        $classes = array_merge(array('wp-block-navigation__submenu-container'), $colors['css_classes']);
        $css_classes = trim(implode(' ', $classes));
        $style_attribute = $colors['inline_styles'];
        $inner_blocks_html = '';
        foreach ($block->inner_blocks as $inner_block) {
            $inner_blocks_html .= $inner_block->render();
        }
        if (strpos($inner_blocks_html, 'current-menu-item')) {
            $tag_processor = new WP_HTML_Tag_Processor($html);
            while ($tag_processor->next_tag(array('class_name' => 'wp-block-navigation-item__content'))) {
                $tag_processor->add_class('current-menu-ancestor');
            }
            $html = $tag_processor->get_updated_html();
        }
        $wrapper_attributes = get_block_wrapper_attributes(array('class' => $css_classes, 'style' => $style_attribute));
        $html .= sprintf('<ul %s>%s</ul>', $wrapper_attributes, $inner_blocks_html);
    }
    $html .= '</li>';
    return $html;
}

WordPress Version: 6.1

/**
 * Renders the `core/navigation-submenu` block.
 *
 * @param array    $attributes The block attributes.
 * @param string   $content    The saved content.
 * @param WP_Block $block      The parsed block.
 *
 * @return string Returns the post content with the legacy widget added.
 */
function render_block_core_navigation_submenu($attributes, $content, $block)
{
    $navigation_link_has_id = isset($attributes['id']) && is_numeric($attributes['id']);
    $is_post_type = isset($attributes['kind']) && 'post-type' === $attributes['kind'];
    $is_post_type = $is_post_type || isset($attributes['type']) && ('post' === $attributes['type'] || 'page' === $attributes['type']);
    // Don't render the block's subtree if it is a draft.
    if ($is_post_type && $navigation_link_has_id && 'publish' !== get_post_status($attributes['id'])) {
        return '';
    }
    // Don't render the block's subtree if it has no label.
    if (empty($attributes['label'])) {
        return '';
    }
    $colors = block_core_navigation_submenu_build_css_colors($block->context, $attributes);
    $font_sizes = block_core_navigation_submenu_build_css_font_sizes($block->context);
    $classes = array_merge($colors['css_classes'], $font_sizes['css_classes']);
    $style_attribute = $colors['inline_styles'] . $font_sizes['inline_styles'];
    $css_classes = trim(implode(' ', $classes));
    $has_submenu = count($block->inner_blocks) > 0;
    $is_active = !empty($attributes['id']) && get_the_ID() === (int) $attributes['id'];
    $show_submenu_indicators = isset($block->context['showSubmenuIcon']) && $block->context['showSubmenuIcon'];
    $open_on_click = isset($block->context['openSubmenusOnClick']) && $block->context['openSubmenusOnClick'];
    $open_on_hover_and_click = isset($block->context['openSubmenusOnClick']) && !$block->context['openSubmenusOnClick'] && $show_submenu_indicators;
    $wrapper_attributes = get_block_wrapper_attributes(array('class' => $css_classes . ' wp-block-navigation-item' . ($has_submenu ? ' has-child' : '') . ($open_on_click ? ' open-on-click' : '') . ($open_on_hover_and_click ? ' open-on-hover-click' : '') . ($is_active ? ' current-menu-item' : ''), 'style' => $style_attribute));
    $label = '';
    if (isset($attributes['label'])) {
        $label .= wp_kses_post($attributes['label']);
    }
    $aria_label = sprintf(
        /* translators: Accessibility text. %s: Parent page title. */
        __('%s submenu'),
        wp_strip_all_tags($label)
    );
    $html = '<li ' . $wrapper_attributes . '>';
    // If Submenus open on hover, we render an anchor tag with attributes.
    // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click.
    if (!$open_on_click) {
        $item_url = isset($attributes['url']) ? $attributes['url'] : '';
        // Start appending HTML attributes to anchor tag.
        $html .= '<a class="wp-block-navigation-item__content"';
        // The href attribute on a and area elements is not required;
        // when those elements do not have href attributes they do not create hyperlinks.
        // But also The href attribute must have a value that is a valid URL potentially
        // surrounded by spaces.
        // see: https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements.
        if (!empty($item_url)) {
            $html .= ' href="' . esc_url($item_url) . '"';
        }
        if ($is_active) {
            $html .= ' aria-current="page"';
        }
        if (isset($attributes['opensInNewTab']) && true === $attributes['opensInNewTab']) {
            $html .= ' target="_blank"  ';
        }
        if (isset($attributes['rel'])) {
            $html .= ' rel="' . esc_attr($attributes['rel']) . '"';
        } elseif (isset($attributes['nofollow']) && $attributes['nofollow']) {
            $html .= ' rel="nofollow"';
        }
        if (isset($attributes['title'])) {
            $html .= ' title="' . esc_attr($attributes['title']) . '"';
        }
        $html .= '>';
        // End appending HTML attributes to anchor tag.
        $html .= $label;
        $html .= '</a>';
        // End anchor tag content.
        if ($show_submenu_indicators) {
            // The submenu icon is rendered in a button here
            // so that there's a clickable element to open the submenu.
            $html .= '<button aria-label="' . esc_attr($aria_label) . '" class="wp-block-navigation__submenu-icon wp-block-navigation-submenu__toggle" aria-expanded="false">' . block_core_navigation_submenu_render_submenu_icon() . '</button>';
        }
    } else {
        // If menus open on click, we render the parent as a button.
        $html .= '<button aria-label="' . esc_attr($aria_label) . '" class="wp-block-navigation-item__content wp-block-navigation-submenu__toggle" aria-expanded="false">';
        // Wrap title with span to isolate it from submenu icon.
        $html .= '<span class="wp-block-navigation-item__label">';
        $html .= $label;
        $html .= '</span>';
        $html .= '</button>';
        $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>';
    }
    if ($has_submenu) {
        $inner_blocks_html = '';
        foreach ($block->inner_blocks as $inner_block) {
            $inner_blocks_html .= $inner_block->render();
        }
        $html .= sprintf('<ul class="wp-block-navigation__submenu-container">%s</ul>', $inner_blocks_html);
    }
    $html .= '</li>';
    return $html;
}

WordPress Version: 5.9

/**
 * Renders the `core/navigation-submenu` block.
 *
 * @param array  $attributes The block attributes.
 * @param string $content The saved content.
 * @param object $block The parsed block.
 *
 * @return string Returns the post content with the legacy widget added.
 */
function render_block_core_navigation_submenu($attributes, $content, $block)
{
    $navigation_link_has_id = isset($attributes['id']) && is_numeric($attributes['id']);
    $is_post_type = isset($attributes['kind']) && 'post-type' === $attributes['kind'];
    $is_post_type = $is_post_type || isset($attributes['type']) && ('post' === $attributes['type'] || 'page' === $attributes['type']);
    // Don't render the block's subtree if it is a draft.
    if ($is_post_type && $navigation_link_has_id && 'publish' !== get_post_status($attributes['id'])) {
        return '';
    }
    // Don't render the block's subtree if it has no label.
    if (empty($attributes['label'])) {
        return '';
    }
    $colors = block_core_navigation_submenu_build_css_colors($block->context, $attributes);
    $font_sizes = block_core_navigation_submenu_build_css_font_sizes($block->context);
    $classes = array_merge($colors['css_classes'], $font_sizes['css_classes']);
    $style_attribute = $colors['inline_styles'] . $font_sizes['inline_styles'];
    $css_classes = trim(implode(' ', $classes));
    $has_submenu = count($block->inner_blocks) > 0;
    $is_active = !empty($attributes['id']) && get_the_ID() === $attributes['id'];
    $show_submenu_indicators = isset($block->context['showSubmenuIcon']) && $block->context['showSubmenuIcon'];
    $open_on_click = isset($block->context['openSubmenusOnClick']) && $block->context['openSubmenusOnClick'];
    $open_on_hover_and_click = isset($block->context['openSubmenusOnClick']) && !$block->context['openSubmenusOnClick'] && $show_submenu_indicators;
    $wrapper_attributes = get_block_wrapper_attributes(array('class' => $css_classes . ' wp-block-navigation-item' . ($has_submenu ? ' has-child' : '') . ($open_on_click ? ' open-on-click' : '') . ($open_on_hover_and_click ? ' open-on-hover-click' : '') . ($is_active ? ' current-menu-item' : ''), 'style' => $style_attribute));
    $label = '';
    if (isset($attributes['label'])) {
        $label .= wp_kses($attributes['label'], array('code' => array(), 'em' => array(), 'img' => array('scale' => array(), 'class' => array(), 'style' => array(), 'src' => array(), 'alt' => array()), 's' => array(), 'span' => array('style' => array()), 'strong' => array()));
    }
    $aria_label = sprintf(
        /* translators: Accessibility text. %s: Parent page title. */
        __('%s submenu'),
        wp_strip_all_tags($label)
    );
    $html = '<li ' . $wrapper_attributes . '>';
    // If Submenus open on hover, we render an anchor tag with attributes.
    // If submenu icons are set to show, we also render a submenu button, so the submenu can be opened on click.
    if (!$open_on_click) {
        $item_url = isset($attributes['url']) ? esc_url($attributes['url']) : '';
        // Start appending HTML attributes to anchor tag.
        $html .= '<a class="wp-block-navigation-item__content" href="' . $item_url . '"';
        if ($is_active) {
            $html .= ' aria-current="page"';
        }
        if (isset($attributes['opensInNewTab']) && true === $attributes['opensInNewTab']) {
            $html .= ' target="_blank"  ';
        }
        if (isset($attributes['rel'])) {
            $html .= ' rel="' . esc_attr($attributes['rel']) . '"';
        } elseif (isset($attributes['nofollow']) && $attributes['nofollow']) {
            $html .= ' rel="nofollow"';
        }
        if (isset($attributes['title'])) {
            $html .= ' title="' . esc_attr($attributes['title']) . '"';
        }
        $html .= '>';
        // End appending HTML attributes to anchor tag.
        $html .= $label;
        $html .= '</a>';
        // End anchor tag content.
        if ($show_submenu_indicators) {
            // The submenu icon is rendered in a button here
            // so that there's a clickable element to open the submenu.
            $html .= '<button aria-label="' . $aria_label . '" class="wp-block-navigation__submenu-icon wp-block-navigation-submenu__toggle" aria-expanded="false">' . block_core_navigation_submenu_render_submenu_icon() . '</button>';
        }
    } else {
        // If menus open on click, we render the parent as a button.
        $html .= '<button aria-label="' . $aria_label . '" class="wp-block-navigation-item__content wp-block-navigation-submenu__toggle" aria-expanded="false">';
        // Wrap title with span to isolate it from submenu icon.
        $html .= '<span class="wp-block-navigation-item__label">';
        $html .= $label;
        $html .= '</span>';
        $html .= '<span class="wp-block-navigation__submenu-icon">' . block_core_navigation_submenu_render_submenu_icon() . '</span>';
        $html .= '</button>';
    }
    if ($has_submenu) {
        $inner_blocks_html = '';
        foreach ($block->inner_blocks as $inner_block) {
            $inner_blocks_html .= $inner_block->render();
        }
        $html .= sprintf('<ul class="wp-block-navigation__submenu-container">%s</ul>', $inner_blocks_html);
    }
    $html .= '</li>';
    return $html;
}