diff --git a/src/wp-includes/blocks/navigation.php b/src/wp-includes/blocks/navigation.php new file mode 100644 index 0000000000000..13b6df425626a --- /dev/null +++ b/src/wp-includes/blocks/navigation.php @@ -0,0 +1,195 @@ + array(), + 'inline_styles' => '', + ); + + $has_named_text_color = array_key_exists( 'textColor', $attributes ); + $has_custom_text_color = array_key_exists( 'customTextColor', $attributes ); + + // If has text color. + if ( $has_custom_text_color || $has_named_text_color ) { + // Add has-text-color class. + $colors['css_classes'][] = 'has-text-color'; + } + + if ( $has_named_text_color ) { + // Add the color class. + $colors['css_classes'][] = sprintf( 'has-%s-color', $attributes['textColor'] ); + } elseif ( $has_custom_text_color ) { + // Add the custom color inline style. + $colors['inline_styles'] = sprintf( 'color: %s;', $attributes['customTextColor'] ); + } + + return $colors; +} + +/** + * 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. + * + * @param array $attributes Navigation block attributes. + * @return array Font size CSS classes and inline styles. + */ +function build_css_font_sizes( $attributes ) { + // CSS classes. + $font_sizes = array( + 'css_classes' => array(), + 'inline_styles' => '', + ); + + $has_named_font_size = array_key_exists( 'fontSize', $attributes ); + $has_custom_font_size = array_key_exists( 'customFontSize', $attributes ); + + if ( $has_named_font_size ) { + // Add the font size class. + $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $attributes['fontSize'] ); + } elseif ( $has_custom_font_size ) { + // Add the custom font size inline style. + $font_sizes['inline_styles'] = sprintf( 'font-size: %spx;', $attributes['customFontSize'] ); + } + + return $font_sizes; +} + +/** + * Renders the `core/navigation` block on server. + * + * @param array $attributes The block attributes. + * @param array $content The saved content. + * @param array $block The parsed block. + * + * @return string Returns the post content with the legacy widget added. + */ +function render_block_navigation( $attributes, $content, $block ) { + $colors = build_css_colors( $attributes ); + $font_sizes = build_css_font_sizes( $attributes ); + $classes = array_merge( + $colors['css_classes'], + $font_sizes['css_classes'], + array( 'wp-block-navigation' ), + isset( $attributes['className'] ) ? array( $attributes['className'] ) : array(), + isset( $attributes['itemsJustification'] ) ? array( 'items-justified-' . $attributes['itemsJustification'] ) : array(), + isset( $attributes['align'] ) ? array( 'align' . $attributes['align'] ) : array() + ); + $class_attribute = sprintf( ' class="%s"', esc_attr( implode( ' ', $classes ) ) ); + $style_attribute = ( $colors['inline_styles'] || $font_sizes['inline_styles'] ) + ? sprintf( ' style="%s"', esc_attr( $colors['inline_styles'] ) . esc_attr( $font_sizes['inline_styles'] ) ) + : ''; + + return sprintf( + '', + $class_attribute, + $style_attribute, + build_navigation_html( $block, $colors, $font_sizes ) + ); +} + +/** + * Walks the inner block structure and returns an HTML list for it. + * + * @param array $block The block. + * @param array $colors Contains inline styles and CSS classes to apply to navigation item. + * @param array $font_sizes Contains inline styles and CSS classes to apply to navigation item. + * + * @return string Returns an HTML list from innerBlocks. + */ +function build_navigation_html( $block, $colors, $font_sizes ) { + $html = ''; + $classes = array_merge( + $colors['css_classes'], + $font_sizes['css_classes'] + ); + $css_classes = implode( ' ', $classes ); + $class_attribute = sprintf( ' class="wp-block-navigation-link__content %s"', esc_attr( trim( $css_classes ) ) ); + $style_attribute = ( $colors['inline_styles'] || $font_sizes['inline_styles'] ) + ? sprintf( ' style="%s"', esc_attr( $colors['inline_styles'] ) . esc_attr( $font_sizes['inline_styles'] ) ) + : ''; + + foreach ( (array) $block['innerBlocks'] as $key => $block ) { + + $html .= ''; + } + return ''; +} + +/** + * Register the navigation block. + * + * @uses render_block_navigation() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ +function register_block_core_navigation() { + + register_block_type( + 'core/navigation', + array( + 'attributes' => array( + 'className' => array( + 'type' => 'string', + ), + 'textColor' => array( + 'type' => 'string', + ), + 'customTextColor' => array( + 'type' => 'string', + ), + 'fontSize' => array( + 'type' => 'string', + ), + 'customFontSize' => array( + 'type' => 'number', + ), + 'itemsJustification' => array( + 'type' => 'string', + ), + ), + + 'render_callback' => 'render_block_navigation', + ) + ); +} +add_action( 'init', 'register_block_core_navigation' ); diff --git a/src/wp-settings.php b/src/wp-settings.php index 13f9bbb3a51e1..230b54010a6d5 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -263,6 +263,7 @@ require( ABSPATH . WPINC . '/blocks/categories.php' ); require( ABSPATH . WPINC . '/blocks/latest-comments.php' ); require( ABSPATH . WPINC . '/blocks/latest-posts.php' ); +require( ABSPATH . WPINC . '/blocks/navigation.php' ); require( ABSPATH . WPINC . '/blocks/rss.php' ); require( ABSPATH . WPINC . '/blocks/search.php' ); require( ABSPATH . WPINC . '/blocks/shortcode.php' ); diff --git a/tests/phpunit/includes/functions.php b/tests/phpunit/includes/functions.php index 4fcb1601e303a..a69354d9b798c 100644 --- a/tests/phpunit/includes/functions.php +++ b/tests/phpunit/includes/functions.php @@ -301,6 +301,7 @@ function _unhook_block_registration() { remove_action( 'init', 'register_block_core_categories' ); remove_action( 'init', 'register_block_core_latest_comments' ); remove_action( 'init', 'register_block_core_latest_posts' ); + remove_action( 'init', 'register_block_core_navigation' ); remove_action( 'init', 'register_block_core_rss' ); remove_action( 'init', 'register_block_core_search' ); remove_action( 'init', 'register_block_core_shortcode' ); diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php index 0aeebb4352b83..1a207db546cf8 100644 --- a/tests/phpunit/tests/rest-api/rest-schema-setup.php +++ b/tests/phpunit/tests/rest-api/rest-schema-setup.php @@ -126,6 +126,7 @@ public function test_expected_routes_in_schema() { '/wp/v2/block-renderer/(?Pcore/categories)', '/wp/v2/block-renderer/(?Pcore/latest-comments)', '/wp/v2/block-renderer/(?Pcore/latest-posts)', + '/wp/v2/block-renderer/(?Pcore/navigation)', '/wp/v2/block-renderer/(?Pcore/rss)', '/wp/v2/block-renderer/(?Pcore/search)', '/wp/v2/block-renderer/(?Pcore/shortcode)', diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 9c130539b789c..c709db9f6f5e5 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -4632,6 +4632,46 @@ mockedApiResponse.Schema = { } ] }, + "/wp/v2/block-renderer/(?Pcore/navigation)": { + "namespace": "wp/v2", + "methods": [ + "GET" + ], + "endpoints": [ + { + "methods": [ + "GET" + ], + "args": { + "name": { + "required": false, + "description": "Unique registered name for the block.", + "type": "string" + }, + "context": { + "required": false, + "default": "view", + "enum": [ + "edit" + ], + "description": "Scope under which the request is made; determines fields present in response.", + "type": "string" + }, + "attributes": { + "required": false, + "default": [], + "description": "Attributes for core/navigation block", + "type": "object" + }, + "post_id": { + "required": false, + "description": "ID of the post context.", + "type": "integer" + } + } + } + ] + }, "/wp/v2/block-renderer/(?Pcore/rss)": { "namespace": "wp/v2", "methods": [ diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index ab9e2fdef1e51..a62245312645e 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -101,6 +101,7 @@ module.exports = function( env = { environment: 'production', watch: false, buil 'categories', 'latest-comments', 'latest-posts', + 'navigation', 'rss', 'search', 'shortcode',