-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Navigation Submenu: Refactor to use the block supports function #48936
Changes from 9 commits
17f38a2
996abf1
68526bd
44fd29c
02b199b
99bc885
bb098ed
4807578
168a906
67f9d9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,66 +14,6 @@ | |
* @param bool $is_sub_menu Whether the block is a sub-menu. | ||
* @return array Colors CSS classes and inline styles. | ||
*/ | ||
function block_core_navigation_submenu_build_css_colors( $context, $attributes, $is_sub_menu = false ) { | ||
$colors = array( | ||
'css_classes' => array(), | ||
'inline_styles' => '', | ||
); | ||
|
||
// Text color. | ||
$named_text_color = null; | ||
$custom_text_color = null; | ||
|
||
if ( $is_sub_menu && array_key_exists( 'customOverlayTextColor', $context ) ) { | ||
$custom_text_color = $context['customOverlayTextColor']; | ||
} elseif ( $is_sub_menu && array_key_exists( 'overlayTextColor', $context ) ) { | ||
$named_text_color = $context['overlayTextColor']; | ||
} elseif ( array_key_exists( 'customTextColor', $context ) ) { | ||
$custom_text_color = $context['customTextColor']; | ||
} elseif ( array_key_exists( 'textColor', $context ) ) { | ||
$named_text_color = $context['textColor']; | ||
} elseif ( isset( $context['style']['color']['text'] ) ) { | ||
$custom_text_color = $context['style']['color']['text']; | ||
} | ||
|
||
// If has text color. | ||
if ( ! is_null( $named_text_color ) ) { | ||
// Add the color class. | ||
array_push( $colors['css_classes'], 'has-text-color', sprintf( 'has-%s-color', $named_text_color ) ); | ||
} elseif ( ! is_null( $custom_text_color ) ) { | ||
// Add the custom color inline style. | ||
$colors['css_classes'][] = 'has-text-color'; | ||
$colors['inline_styles'] .= sprintf( 'color: %s;', $custom_text_color ); | ||
} | ||
|
||
// Background color. | ||
$named_background_color = null; | ||
$custom_background_color = null; | ||
|
||
if ( $is_sub_menu && array_key_exists( 'customOverlayBackgroundColor', $context ) ) { | ||
$custom_background_color = $context['customOverlayBackgroundColor']; | ||
} elseif ( $is_sub_menu && array_key_exists( 'overlayBackgroundColor', $context ) ) { | ||
$named_background_color = $context['overlayBackgroundColor']; | ||
} elseif ( array_key_exists( 'customBackgroundColor', $context ) ) { | ||
$custom_background_color = $context['customBackgroundColor']; | ||
} elseif ( array_key_exists( 'backgroundColor', $context ) ) { | ||
$named_background_color = $context['backgroundColor']; | ||
} elseif ( isset( $context['style']['color']['background'] ) ) { | ||
$custom_background_color = $context['style']['color']['background']; | ||
} | ||
|
||
// If has background color. | ||
if ( ! is_null( $named_background_color ) ) { | ||
// Add the background-color class. | ||
array_push( $colors['css_classes'], 'has-background', sprintf( 'has-%s-background-color', $named_background_color ) ); | ||
} elseif ( ! is_null( $custom_background_color ) ) { | ||
// Add the custom background-color inline style. | ||
$colors['css_classes'][] = 'has-background'; | ||
$colors['inline_styles'] .= sprintf( 'background-color: %s;', $custom_background_color ); | ||
} | ||
|
||
return $colors; | ||
} | ||
|
||
/** | ||
* Build an array with CSS classes and inline styles defining the font sizes | ||
|
@@ -129,7 +69,6 @@ function block_core_navigation_submenu_render_submenu_icon() { | |
* @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'] ); | ||
|
@@ -144,15 +83,10 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) { | |
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'] ); | ||
$style_attribute = $font_sizes['inline_styles']; | ||
|
||
$css_classes = trim( implode( ' ', $classes ) ); | ||
$css_classes = trim( implode( ' ', $font_sizes['css_classes'] ) ); | ||
$has_submenu = count( $block->inner_blocks ) > 0; | ||
$is_active = ! empty( $attributes['id'] ) && ( get_queried_object_id() === (int) $attributes['id'] ); | ||
|
||
|
@@ -249,14 +183,33 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) { | |
} | ||
|
||
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 ) ); | ||
// Copy some attributes from the parent block to this one. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unusual code so should we be more specific about what's happening here? |
||
// Ideally this would happen in the client when the block is created. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it ideal? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking that then the sub-menu block would be the one to control it, rather than being orchestrated by the parent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure. The reason it's orchestrated by the parent is so you can set the colors for all children in a single place rather than have to visit every single child block and configure the colors. We could make it so changing one child block's colors changes all of them but I think that's very confusing. I would consider leaving the controls in place on the Nav block but allowing the values set their to determine the defaults for controls we expose on the child blocks. That means we still have a single place to se the colors. Let me know if I've misunderstood here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what I envisage is that the controls remain on the parent block, but when they are set, the block updates the child blocks in the client, so that the block itself handles all of the logic about the display. That way nothing about the submenu blocks is stored in the parent block, its just a UI layer which allows the user to update multiple blocks at once. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Follow up then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Absolutely. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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']; | ||
} | ||
|
||
$style_attribute = $colors['inline_styles']; | ||
// This allows us to be able to get a response from gutenberg_apply_colors_support. | ||
$block->block_type->supports['color'] = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it ok to modify this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not rely on the actual block supports. If someone decides to disable block supports for this block then we should respect that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we do that then users will be able to modify the settings for the submenu block in the UI, independently from the parent block. I think what we need to do is move the color settings from the navigation block to the submenu block, which will require a UI update and a block transform, and a lot of thinking about backwards compatibility. I do think we should do all of that, but if I had done it in this PR you'd be telling me it was too big, so this is just a first step toward that goal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok sure. I agree with small PRs. I was thinking that as So yes I think this workaround is an ok tradeoff for being able to utilise the standardised color code generation. What's the long term plan? Expose UI in the Submenu Block to allow changing colors on individual blocks but have the initial settings still coming from the parent Nav block? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree that we still need a way to set it on the Nav block so that you don't need to change it for every child, but I've not given much thought to how that would work in practice yet. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had the same gut reaction initially and even tried to code a variant that just relies on block supports, but we do have some blockers there. However:
@jasmussen is that a problem really? |
||
$colors_supports = gutenberg_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 ) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
<?php | ||
/** | ||
* Tests server side rendering of core/navigation-submenu | ||
* | ||
* @package Gutenberg | ||
* @subpackage block-library | ||
*/ | ||
|
||
/** | ||
* Tests for various cases in Navigation Submenu rendering | ||
*/ | ||
class Render_Block_Navigation_Submenu_Test extends WP_UnitTestCase { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @scruffian What do you think of the test coverage? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we use the navigation block itself in the tests rather than the navigation submenu block? I think I prefer using the submenu block as you have done, as it feels more inline with the future direction of the block.
|
||
private static $category; | ||
private static $page; | ||
private static $draft; | ||
private static $custom_draft; | ||
private static $custom_post; | ||
|
||
|
||
/** | ||
* @var array|null | ||
*/ | ||
private $original_block_supports; | ||
|
||
public static function set_up_before_class() { | ||
self::$page = self::factory()->post->create_and_get( | ||
array( | ||
'post_type' => 'page', | ||
'post_status' => 'publish', | ||
'post_name' => 'tabby', | ||
'post_title' => 'Tabby cats', | ||
'post_content' => 'Tabby cat content', | ||
'post_excerpt' => 'Tabby cat', | ||
) | ||
); | ||
} | ||
|
||
public function set_up() { | ||
parent::set_up(); | ||
|
||
$this->original_block_supports = WP_Block_Supports::$block_to_render; | ||
WP_Block_Supports::$block_to_render = array( | ||
'attrs' => array(), | ||
'blockName' => '', | ||
); | ||
} | ||
|
||
public function tear_down() { | ||
WP_Block_Supports::$block_to_render = $this->original_block_supports; | ||
parent::tear_down(); | ||
} | ||
|
||
/** | ||
* @group submenu-color-inheritance | ||
* @covers ::gutenberg_render_block_core_navigation_submenu | ||
*/ | ||
public function test_should_apply_preset_colors_inherited_from_parent_block_via_context() { | ||
$page_id = self::$page->ID; | ||
|
||
$parsed_blocks = parse_blocks( | ||
'<!-- wp:navigation-submenu {"label":"Submenu Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} --> | ||
<!-- wp:navigation-link {"label":"Submenu Item Link Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} /--> | ||
<!-- /wp:navigation-submenu -->' | ||
); | ||
|
||
$this->assertEquals( 1, count( $parsed_blocks ), 'Submenu block not parsable.' ); | ||
|
||
$block = $parsed_blocks[0]; | ||
|
||
// Colors inherited from parent Navigation block. | ||
$context = array( | ||
'overlayTextColor' => 'purple', | ||
'overlayBackgroundColor' => 'yellow', | ||
); | ||
|
||
$navigation_link_block = new WP_Block( $block, $context ); | ||
draganescu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
$rendered_html = gutenberg_render_block_core_navigation_submenu( | ||
$navigation_link_block->attributes, | ||
array(), | ||
$navigation_link_block | ||
); | ||
|
||
$p = new WP_HTML_Tag_Processor( $rendered_html ); | ||
draganescu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
$p->next_tag( | ||
array( | ||
'tag_name' => 'ul', | ||
'class_name' => 'wp-block-navigation__submenu-container', | ||
) | ||
); | ||
$p->get_attribute( 'class' ); | ||
|
||
$this->assertEquals( | ||
'wp-block-navigation__submenu-container has-text-color has-purple-color has-background has-yellow-background-color', | ||
$p->get_attribute( 'class' ), | ||
'Submenu block colors inherited from context not applied correctly' | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried using Open to opinions on whether this is a good idea. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the worry about the more simplistic approach? Is it important that we have the test care about equaling all of those classnames in that order? Or should the classname include all 5 of the classes but in any order? If it's not important that it only equals that, it could be nice to check that it contains the classnames so it doesn't fail unnecessarily. I'm not versed in the block nav though, so I'm not sure what the main considerations are. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If the test fails it's quite difficult to see the difference between the two strings. Where the output for equals seemed clearer. Also the Tag Processor makes it clearer we are asserting directly on the |
||
} | ||
|
||
/** | ||
* @group submenu-color-inheritance | ||
* @covers ::gutenberg_render_block_core_navigation_submenu | ||
*/ | ||
public function test_should_apply_custom_colors_inherited_from_parent_block_via_context() { | ||
$page_id = self::$page->ID; | ||
|
||
$parsed_blocks = parse_blocks( | ||
'<!-- wp:navigation-submenu {"label":"Submenu Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} --> | ||
<!-- wp:navigation-link {"label":"Submenu Item Link Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} /--> | ||
<!-- /wp:navigation-submenu -->' | ||
); | ||
|
||
$this->assertEquals( 1, count( $parsed_blocks ), 'Submenu block not parsable.' ); | ||
|
||
$block = $parsed_blocks[0]; | ||
|
||
// Colors inherited from parent Navigation block. | ||
$context = array( | ||
'customOverlayTextColor' => '#BCC60A', | ||
'customOverlayBackgroundColor' => '#E10E0E', | ||
); | ||
|
||
$navigation_link_block = new WP_Block( $block, $context ); | ||
|
||
$this->assertStringContainsString( | ||
'<ul style="color:' . $context['customOverlayTextColor'] . ';background-color:' . $context['customOverlayBackgroundColor'] . ';" class="wp-block-navigation__submenu-container has-text-color has-background">', | ||
gutenberg_render_block_core_navigation_submenu( | ||
$navigation_link_block->attributes, | ||
array(), | ||
$navigation_link_block | ||
), | ||
'Submenu block colors inherited from context not applied correctly' | ||
); | ||
} | ||
|
||
/** | ||
* @group submenu-color-inheritance | ||
* @covers ::gutenberg_render_block_core_navigation_submenu | ||
*/ | ||
public function test_should_apply_mix_of_preset_and_custom_colors_inherited_from_parent_block_via_context() { | ||
$page_id = self::$page->ID; | ||
|
||
$parsed_blocks = parse_blocks( | ||
'<!-- wp:navigation-submenu {"label":"Submenu Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} --> | ||
<!-- wp:navigation-link {"label":"Submenu Item Link Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} /--> | ||
<!-- /wp:navigation-submenu -->' | ||
); | ||
|
||
$this->assertEquals( 1, count( $parsed_blocks ), 'Submenu block not parsable.' ); | ||
|
||
$block = $parsed_blocks[0]; | ||
|
||
// Colors inherited from parent Navigation block. | ||
$context = array( | ||
'overlayTextColor' => 'purple', | ||
'customOverlayBackgroundColor' => '#E10E0E', | ||
); | ||
|
||
$navigation_link_block = new WP_Block( $block, $context ); | ||
|
||
$this->assertStringContainsString( | ||
'<ul style="background-color:' . $context['customOverlayBackgroundColor'] . ';" class="wp-block-navigation__submenu-container has-text-color has-' . $context['overlayTextColor'] . '-color has-background">', | ||
gutenberg_render_block_core_navigation_submenu( | ||
$navigation_link_block->attributes, | ||
array(), | ||
$navigation_link_block | ||
), | ||
'Submenu block colors inherited from context not applied correctly' | ||
); | ||
} | ||
|
||
/** | ||
* @group submenu-color-inheritance | ||
* @covers ::gutenberg_render_block_core_navigation_submenu | ||
*/ | ||
public function test_should_not_apply_custom_colors_if_missing_from_context() { | ||
$page_id = self::$page->ID; | ||
|
||
$parsed_blocks = parse_blocks( | ||
'<!-- wp:navigation-submenu {"label":"Submenu Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} --> | ||
<!-- wp:navigation-link {"label":"Submenu Item Link Label","type":"page","id":' . $page_id . ',"url":"http://localhost:8888/?page_id=' . $page_id . '","kind":"post-type"} /--> | ||
<!-- /wp:navigation-submenu -->' | ||
); | ||
|
||
$this->assertEquals( 1, count( $parsed_blocks ), 'Submenu block not parsable.' ); | ||
|
||
$block = $parsed_blocks[0]; | ||
|
||
// Intentionally empty - no colors. | ||
$context = array(); | ||
|
||
$navigation_link_block = new WP_Block( $block, $context ); | ||
|
||
$actual = gutenberg_render_block_core_navigation_submenu( | ||
$navigation_link_block->attributes, | ||
array(), | ||
$navigation_link_block | ||
); | ||
|
||
$this->assertStringContainsString( | ||
'<ul class="wp-block-navigation__submenu-container">', | ||
$actual, | ||
'Submenu block should not apply colors if missing from context' | ||
); | ||
|
||
$this->assertStringNotContainsString( | ||
$actual, | ||
'has-text-color has-background', | ||
'Submenu block should not apply "has-*" color classes if missing from context' | ||
); | ||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love it that we can ditch this custom code 🥳