diff --git a/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/Layout/class-flex-layout-renderer.php b/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/Layout/class-flex-layout-renderer.php index 47f0f2e839..a35d431593 100644 --- a/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/Layout/class-flex-layout-renderer.php +++ b/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/Layout/class-flex-layout-renderer.php @@ -1,5 +1,11 @@ -get_email_styles(); - $flexGap = $themeStyles['spacing']['blockGap'] ?? '0px'; - $flexGapNumber = $settingsController->parse_number_from_string_with_pixels( $flexGap ); + /** + * Render inner blocks in flex layout. + * + * @param array $parsed_block Parsed block. + * @param Settings_Controller $settings_controller Settings controller. + * @return string + */ + public function render_inner_blocks_in_layout( array $parsed_block, Settings_Controller $settings_controller ): string { + $theme_styles = $settings_controller->get_email_styles(); + $flex_gap = $theme_styles['spacing']['blockGap'] ?? '0px'; + $flex_gap_number = $settings_controller->parse_number_from_string_with_pixels( $flex_gap ); - $marginTop = $parsedBlock['email_attrs']['margin-top'] ?? '0px'; - $justify = $parsedBlock['attrs']['layout']['justifyContent'] ?? 'left'; - $styles = wp_style_engine_get_styles( $parsedBlock['attrs']['style'] ?? array() )['css'] ?? ''; - $styles .= 'margin-top: ' . $marginTop . ';'; - $styles .= 'text-align: ' . $justify; + $margin_top = $parsed_block['email_attrs']['margin-top'] ?? '0px'; + $justify = $parsed_block['attrs']['layout']['justifyContent'] ?? 'left'; + $styles = wp_style_engine_get_styles( $parsed_block['attrs']['style'] ?? array() )['css'] ?? ''; + $styles .= 'margin-top: ' . $margin_top . ';'; + $styles .= 'text-align: ' . $justify; - // MS Outlook doesn't support style attribute in divs so we conditionally wrap the buttons in a table and repeat styles - $outputHtml = sprintf( + // MS Outlook doesn't support style attribute in divs so we conditionally wrap the buttons in a table and repeat styles. + $output_html = sprintf( '
', esc_attr( $styles ), esc_attr( $justify ) ); - $innerBlocks = $this->computeWidthsForFlexLayout( $parsedBlock, $settingsController, $flexGapNumber ); + $inner_blocks = $this->compute_widths_for_flex_layout( $parsed_block, $settings_controller, $flex_gap_number ); - foreach ( $innerBlocks as $key => $block ) { + foreach ( $inner_blocks as $key => $block ) { $styles = array(); if ( $block['email_attrs']['layout_width'] ?? null ) { $styles['width'] = $block['email_attrs']['layout_width']; } if ( $key > 0 ) { - $styles['padding-left'] = $flexGap; + $styles['padding-left'] = $flex_gap; } - $outputHtml .= ''; + $output_html .= ''; } - $outputHtml .= '
' . render_block( $block ) . '' . render_block( $block ) . '
+ $output_html .= ' '; - return $outputHtml; + return $output_html; } - private function computeWidthsForFlexLayout( array $parsedBlock, Settings_Controller $settingsController, float $flexGap ): array { + /** + * Compute widths for blocks in flex layout. + * + * @param array $parsed_block Parsed block. + * @param Settings_Controller $settings_controller Settings controller. + * @param float $flex_gap Flex gap. + * @return array + */ + private function compute_widths_for_flex_layout( array $parsed_block, Settings_Controller $settings_controller, float $flex_gap ): array { // When there is no parent width we can't compute widths so auto width will be used - if ( ! isset( $parsedBlock['email_attrs']['width'] ) ) { - return $parsedBlock['innerBlocks'] ?? array(); + if ( ! isset( $parsed_block['email_attrs']['width'] ) ) { + return $parsed_block['innerBlocks'] ?? array(); } - $blocksCount = count( $parsedBlock['innerBlocks'] ); - $totalUsedWidth = 0; // Total width assuming items without set width would consume proportional width - $parentWidth = $settingsController->parse_number_from_string_with_pixels( $parsedBlock['email_attrs']['width'] ); - $innerBlocks = $parsedBlock['innerBlocks'] ?? array(); + $blocks_count = count( $parsed_block['innerBlocks'] ); + $total_used_width = 0; // Total width assuming items without set width would consume proportional width + $parent_width = $settings_controller->parse_number_from_string_with_pixels( $parsed_block['email_attrs']['width'] ); + $inner_blocks = $parsed_block['innerBlocks'] ?? array(); - foreach ( $innerBlocks as $key => $block ) { - $blockWidthPercent = ( $block['attrs']['width'] ?? 0 ) ? intval( $block['attrs']['width'] ) : 0; - $blockWidth = floor( $parentWidth * ( $blockWidthPercent / 100 ) ); - // If width is not set, we assume it's 25% of the parent width - $totalUsedWidth += $blockWidth ?: floor( $parentWidth * ( 25 / 100 ) ); + foreach ( $inner_blocks as $key => $block ) { + $block_width_percent = ( $block['attrs']['width'] ?? 0 ) ? intval( $block['attrs']['width'] ) : 0; + $block_width = floor( $parent_width * ( $block_width_percent / 100 ) ); + // If width is not set, we assume it's 25% of the parent width. + $total_used_width += $block_width ? $block_width : floor( $parent_width * ( 25 / 100 ) ); - if ( ! $blockWidth ) { - $innerBlocks[ $key ]['email_attrs']['layout_width'] = null; // Will be rendered as auto + if ( ! $block_width ) { + $inner_blocks[ $key ]['email_attrs']['layout_width'] = null; // Will be rendered as auto. continue; } - $innerBlocks[ $key ]['email_attrs']['layout_width'] = $this->getWidthWithoutGap( $blockWidth, $flexGap, $blockWidthPercent ) . 'px'; + $inner_blocks[ $key ]['email_attrs']['layout_width'] = $this->get_width_without_gap( $block_width, $flex_gap, $block_width_percent ) . 'px'; } - // When there is only one block, or percentage is set reasonably we don't need to adjust and just render as set by user - if ( $blocksCount <= 1 || ( $totalUsedWidth <= $parentWidth ) ) { - return $innerBlocks; + // When there is only one block, or percentage is set reasonably we don't need to adjust and just render as set by user. + if ( $blocks_count <= 1 || ( $total_used_width <= $parent_width ) ) { + return $inner_blocks; } - foreach ( $innerBlocks as $key => $block ) { - $proportionalSpaceOverflow = $parentWidth / $totalUsedWidth; - $blockWidth = $block['email_attrs']['layout_width'] ? $settingsController->parse_number_from_string_with_pixels( $block['email_attrs']['layout_width'] ) : 0; - $blockProportionalWidth = $blockWidth * $proportionalSpaceOverflow; - $blockProportionalPercentage = ( $blockProportionalWidth / $parentWidth ) * 100; - $innerBlocks[ $key ]['email_attrs']['layout_width'] = $blockWidth ? $this->getWidthWithoutGap( $blockProportionalWidth, $flexGap, $blockProportionalPercentage ) . 'px' : null; + foreach ( $inner_blocks as $key => $block ) { + $proportional_space_overflow = $parent_width / $total_used_width; + $block_width = $block['email_attrs']['layout_width'] ? $settings_controller->parse_number_from_string_with_pixels( $block['email_attrs']['layout_width'] ) : 0; + $block_proportional_width = $block_width * $proportional_space_overflow; + $block_proportional_percentage = ( $block_proportional_width / $parent_width ) * 100; + $inner_blocks[ $key ]['email_attrs']['layout_width'] = $block_width ? $this->get_width_without_gap( $block_proportional_width, $flex_gap, $block_proportional_percentage ) . 'px' : null; } - return $innerBlocks; + return $inner_blocks; } /** @@ -88,9 +109,14 @@ class Flex_Layout_Renderer { * This is computed based on CSS rule used in the editor: * For block with width set to X percent * width: calc(X% - (var(--wp--style--block-gap) * (100 - X)/100))); + * + * @param float $block_width Block width in pixels. + * @param float $flex_gap Flex gap in pixels. + * @param float $block_width_percent Block width in percent. + * @return int */ - private function getWidthWithoutGap( float $blockWidth, float $flexGap, float $blockWidthPercent ): int { - $widthGapReduction = $flexGap * ( ( 100 - $blockWidthPercent ) / 100 ); - return intval( floor( $blockWidth - $widthGapReduction ) ); + private function get_width_without_gap( float $block_width, float $flex_gap, float $block_width_percent ): int { + $width_gap_reduction = $flex_gap * ( ( 100 - $block_width_percent ) / 100 ); + return intval( floor( $block_width - $width_gap_reduction ) ); } } diff --git a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-buttons.php b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-buttons.php index d178d935fa..1a1d1bc51c 100644 --- a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-buttons.php +++ b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-buttons.php @@ -22,6 +22,6 @@ class Buttons extends Abstract_Block_Renderer { if ( isset( $parsedBlock['attrs']['style']['typography']['fontSize'] ) ) { unset( $parsedBlock['attrs']['style']['typography']['fontSize'] ); } - return $this->flexLayoutRenderer->renderInnerBlocksInLayout( $parsedBlock, $settingsController ); + return $this->flexLayoutRenderer->render_inner_blocks_in_layout( $parsedBlock, $settingsController ); } } diff --git a/packages/php/email-editor/tests/integration/Engine/Renderer/ContentRenderer/Layout/Flex_Layout_Renderer_Test.php b/packages/php/email-editor/tests/integration/Engine/Renderer/ContentRenderer/Layout/Flex_Layout_Renderer_Test.php index 1f96c87fcc..5c97584e6e 100644 --- a/packages/php/email-editor/tests/integration/Engine/Renderer/ContentRenderer/Layout/Flex_Layout_Renderer_Test.php +++ b/packages/php/email-editor/tests/integration/Engine/Renderer/ContentRenderer/Layout/Flex_Layout_Renderer_Test.php @@ -37,7 +37,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { ], 'email_attrs' => [], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); verify($output)->stringContainsString('Dummy 1'); verify($output)->stringContainsString('Dummy 2'); } @@ -53,17 +53,17 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'email_attrs' => [], ]; // Default justification is left - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); verify($output)->stringContainsString('text-align: left'); verify($output)->stringContainsString('align="left"'); // Right justification $parsedBlock['attrs']['layout']['justifyContent'] = 'right'; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); verify($output)->stringContainsString('text-align: right'); verify($output)->stringContainsString('align="right"'); // Center justification $parsedBlock['attrs']['layout']['justifyContent'] = 'center'; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); verify($output)->stringContainsString('text-align: center'); verify($output)->stringContainsString('align="center"'); } @@ -79,7 +79,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'email_attrs' => [], ]; $parsedBlock['attrs']['layout']['justifyContent'] = '">
'); } @@ -104,7 +104,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'attrs' => ['width' => '25'], ], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); $flexItems = $this->getFlexItemsFromOutput($output); verify($flexItems[0])->stringContainsString('width:312px;'); verify($flexItems[1])->stringContainsString('width:148px;'); @@ -127,7 +127,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'attrs' => [], ], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); $flexItems = $this->getFlexItemsFromOutput($output); verify($flexItems[0])->stringContainsString('width:148px;'); verify($flexItems[1])->stringContainsString('width:148px;'); @@ -146,7 +146,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'attrs' => ['width' => '50'], ], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); $flexItems = $this->getFlexItemsFromOutput($output); verify($flexItems[0])->stringContainsString('width:312px;'); verify($flexItems[1])->stringContainsString('width:312px;'); @@ -173,7 +173,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'attrs' => ['width' => '25'], ], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); $flexItems = $this->getFlexItemsFromOutput($output); verify($flexItems[0])->stringContainsString('width:508px;'); verify($flexItems[1])->stringContainsString('width:105px;'); @@ -191,7 +191,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'attrs' => ['width' => '100'], ], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); $flexItems = $this->getFlexItemsFromOutput($output); verify($flexItems[0])->stringContainsString('width:312px;'); verify($flexItems[1])->stringContainsString('width:312px;'); @@ -210,7 +210,7 @@ class Flex_Layout_Renderer_Test extends \MailPoetTest { 'attrs' => [], ], ]; - $output = $this->renderer->renderInnerBlocksInLayout($parsedBlock, $this->settingsController); + $output = $this->renderer->render_inner_blocks_in_layout($parsedBlock, $this->settingsController); $flexItems = $this->getFlexItemsFromOutput($output); verify($flexItems[0])->stringContainsString('width:508px;'); verify($flexItems[1])->stringNotContainsString('width:');