getEmailStyles();
$flexGap = $themeStyles['spacing']['blockGap'] ?? '0px';
$flexGapNumber = $settingsController->parseNumberFromStringWithPixels($flexGap);
$innerBlocks = $this->computeWidthsForFlexLayout($parsedBlock, $settingsController, $flexGapNumber);
// MS Outlook doesn't support style attribute in divs so we conditionally wrap the buttons in a table and repeat styles
$outputHtml = '
';
foreach ($innerBlocks as $key => $block) {
$styles = [];
if ($block['email_attrs']['layout_width'] ?? null) {
$styles['width'] = $block['email_attrs']['layout_width'];
}
if ($key > 0) {
$styles['padding-left'] = $flexGap;
}
$outputHtml .= '' . render_block($block) . ' | ';
}
$outputHtml .= '
';
$wpGeneratedStyles = wp_style_engine_get_styles($parsedBlock['attrs']['style'] ?? []);
$styles = $wpGeneratedStyles['css'] ?? '';
$marginTop = $parsedBlock['email_attrs']['margin-top'] ?? '0px';
$styles .= 'margin-top: ' . $marginTop . ';';
$justify = esc_attr($parsedBlock['attrs']['layout']['justifyContent'] ?? 'left');
$styles .= 'text-align: ' . $justify;
$outputHtml = str_replace('{style}', $styles, $outputHtml);
$outputHtml = str_replace('{align}', $justify, $outputHtml);
return $outputHtml;
}
private function computeWidthsForFlexLayout(array $parsedBlock, SettingsController $settingsController, float $flexGap): array {
$blocksCount = count($parsedBlock['innerBlocks']);
$totalUsedWidth = 0; // Total width assuming items without set width would consume proportional width
$parentWidth = $settingsController->parseNumberFromStringWithPixels($parsedBlock['email_attrs']['width'] ?? SettingsController::EMAIL_WIDTH);
$innerBlocks = $parsedBlock['innerBlocks'] ?? [];
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));
if (!$blockWidth) {
$innerBlocks[$key]['email_attrs']['layout_width'] = null; // Will be rendered as auto
continue;
}
$innerBlocks[$key]['email_attrs']['layout_width'] = $this->getWidthWithoutGap($blockWidth, $flexGap, $blockWidthPercent) . '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;
}
foreach ($innerBlocks as $key => $block) {
$proportionalSpaceOverflow = $parentWidth / $totalUsedWidth;
$blockWidth = $block['email_attrs']['layout_width'] ? $settingsController->parseNumberFromStringWithPixels($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;
}
return $innerBlocks;
}
/**
* How much of width we will strip to keep some space for the gap
* 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)));
*/
private function getWidthWithoutGap(float $blockWidth, float $flexGap, float $blockWidthPercent): int {
$widthGapReduction = $flexGap * ((100 - $blockWidthPercent) / 100);
return intval(floor($blockWidth - $widthGapReduction));
}
}