diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/blocks/navigation-link.php --- a/wp/wp-includes/blocks/navigation-link.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/blocks/navigation-link.php Fri Sep 05 18:40:08 2025 +0200 @@ -1,6 +1,6 @@ array(), 'inline_styles' => '', ); - $is_sub_menu = isset( $attributes['isTopLevelLink'] ) ? ( ! $attributes['isTopLevelLink'] ) : false; - // Text color. $named_text_color = null; $custom_text_color = null; @@ -80,6 +81,8 @@ * Build an array with CSS classes and inline styles defining the font sizes * which will be applied to the navigation markup in the front-end. * + * @since 5.9.0 + * * @param array $context Navigation block context. * @return array Font size CSS classes and inline styles. */ @@ -98,7 +101,14 @@ $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] ); } elseif ( $has_custom_font_size ) { // Add the custom font size inline style. - $font_sizes['inline_styles'] = sprintf( 'font-size: %s;', $context['style']['typography']['fontSize'] ); + $font_sizes['inline_styles'] = sprintf( + 'font-size: %s;', + wp_get_typography_font_size_value( + array( + 'size' => $context['style']['typography']['fontSize'], + ) + ) + ); } return $font_sizes; @@ -107,6 +117,8 @@ /** * Returns the top-level submenu SVG chevron icon. * + * @since 5.9.0 + * * @return string */ function block_core_navigation_link_render_submenu_icon() { @@ -114,8 +126,43 @@ } /** + * Decodes a url if it's encoded, returning the same url if not. + * + * @since 6.2.0 + * + * @param string $url The url to decode. + * + * @return string $url Returns the decoded url. + */ +function block_core_navigation_link_maybe_urldecode( $url ) { + $is_url_encoded = false; + $query = parse_url( $url, PHP_URL_QUERY ); + $query_params = wp_parse_args( $query ); + + foreach ( $query_params as $query_param ) { + $can_query_param_be_encoded = is_string( $query_param ) && ! empty( $query_param ); + if ( ! $can_query_param_be_encoded ) { + continue; + } + if ( rawurldecode( $query_param ) !== $query_param ) { + $is_url_encoded = true; + break; + } + } + + if ( $is_url_encoded ) { + return rawurldecode( $url ); + } + + return $url; +} + + +/** * Renders the `core/navigation-link` block. * + * @since 5.9.0 + * * @param array $attributes The block attributes. * @param string $content The saved content. * @param WP_Block $block The parsed block. @@ -140,17 +187,23 @@ return ''; } - $colors = block_core_navigation_link_build_css_colors( $block->context, $attributes ); $font_sizes = block_core_navigation_link_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'] ); + $style_attribute = $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'] ); + $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 ); + + if ( is_post_type_archive() ) { + $queried_archive_link = get_post_type_archive_link( get_queried_object()->name ); + if ( $attributes['url'] === $queried_archive_link ) { + $is_active = true; + } + } $wrapper_attributes = get_block_wrapper_attributes( array( @@ -164,7 +217,7 @@ // Start appending HTML attributes to anchor tag. if ( isset( $attributes['url'] ) ) { - $html .= ' href="' . esc_url( $attributes['url'] ) . '"'; + $html .= ' href="' . esc_url( block_core_navigation_link_maybe_urldecode( $attributes['url'] ) ) . '"'; } if ( $is_active ) { @@ -233,6 +286,8 @@ /** * Returns a navigation link variation * + * @since 5.9.0 + * * @param WP_Taxonomy|WP_Post_Type $entity post type or taxonomy entity. * @param string $kind string of value 'taxonomy' or 'post-type'. * @@ -291,19 +346,40 @@ } /** - * Register the navigation link block. + * Filters the registered variations for a block type. + * Returns the dynamically built variations for all post-types and taxonomies. + * + * @since 6.5.0 * - * @uses render_block_core_navigation() - * @throws WP_Error An WP_Error exception parsing the block definition. + * @param array $variations Array of registered variations for a block type. + * @param WP_Block_Type $block_type The full block type object. */ -function register_block_core_navigation_link() { +function block_core_navigation_link_filter_variations( $variations, $block_type ) { + if ( 'core/navigation-link' !== $block_type->name ) { + return $variations; + } + + $generated_variations = block_core_navigation_link_build_variations(); + return array_merge( $variations, $generated_variations ); +} + +/** + * Returns an array of variations for the navigation link block. + * + * @since 6.5.0 + * + * @return array + */ +function block_core_navigation_link_build_variations() { $post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' ); $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' ); - // Use two separate arrays as a way to order the variations in the UI. - // Known variations (like Post Link and Page Link) are added to the - // `built_ins` array. Variations for custom post types and taxonomies are - // added to the `variations` array and will always appear after `built-ins. + /* + * Use two separate arrays as a way to order the variations in the UI. + * Known variations (like Post Link and Page Link) are added to the + * `built_ins` array. Variations for custom post types and taxonomies are + * added to the `variations` array and will always appear after `built-ins. + */ $built_ins = array(); $variations = array(); @@ -328,12 +404,28 @@ } } + return array_merge( $built_ins, $variations ); +} + +/** + * Registers the navigation link block. + * + * @since 5.9.0 + * + * @uses render_block_core_navigation_link() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ +function register_block_core_navigation_link() { register_block_type_from_metadata( __DIR__ . '/navigation-link', array( 'render_callback' => 'render_block_core_navigation_link', - 'variations' => array_merge( $built_ins, $variations ), ) ); } add_action( 'init', 'register_block_core_navigation_link' ); +/** + * Creates all variations for post types / taxonomies dynamically (= each time when variations are requested). + * Do not use variation_callback, to also account for unregistering post types/taxonomies later on. + */ +add_action( 'get_block_type_variations', 'block_core_navigation_link_filter_variations', 10, 2 );