Add preprocessor for calculating block width
[MAILPOET-5591]
This commit is contained in:
@@ -336,6 +336,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\EmailEditor::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\EmailApiController::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\SettingsController::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\Preprocessors\BlocksWidthPreprocessor::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\Preprocessors\CleanupPreprocessor::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\Preprocessors\TopLevelPreprocessor::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\Renderer::class)->setPublic(true);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace MailPoet\EmailEditor\Engine\Renderer;
|
||||
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\BlocksWidthPreprocessor;
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\CleanupPreprocessor;
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\Preprocessor;
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\TopLevelPreprocessor;
|
||||
@@ -12,10 +13,12 @@ class PreprocessManager {
|
||||
|
||||
public function __construct(
|
||||
CleanupPreprocessor $cleanupPreprocessor,
|
||||
TopLevelPreprocessor $topLevelPreprocessor
|
||||
TopLevelPreprocessor $topLevelPreprocessor,
|
||||
BlocksWidthPreprocessor $blocksWidthPreprocessor
|
||||
) {
|
||||
$this->registerPreprocessor($cleanupPreprocessor);
|
||||
$this->registerPreprocessor($topLevelPreprocessor);
|
||||
$this->registerPreprocessor($blocksWidthPreprocessor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,64 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\EmailEditor\Engine\Renderer\Preprocessors;
|
||||
|
||||
/**
|
||||
* This class sets the width of the blocks based on the layout width or column count.
|
||||
* The final width in pixels is stored in the email_attrs array because we would like to avoid changing the original attributes.
|
||||
*/
|
||||
class BlocksWidthPreprocessor implements Preprocessor {
|
||||
public function preprocess(array $parsedBlocks, array $layoutStyles): array {
|
||||
$layoutWidth = $layoutStyles['width'];
|
||||
// Subtract padding from the width of the layout element
|
||||
$layoutWidth -= $layoutStyles['padding']['left'] ?? 0;
|
||||
$layoutWidth -= $layoutStyles['padding']['right'] ?? 0;
|
||||
foreach ($parsedBlocks as $key => $block) {
|
||||
$width = $this->convertWithToPixels($block['attrs']['width'] ?? '100%', $layoutWidth);
|
||||
|
||||
if ($block['blockName'] === 'core/columns') {
|
||||
$block['innerBlocks'] = $this->addMissingColumnWidths($block['innerBlocks']);
|
||||
}
|
||||
|
||||
// Copy layout styles and update width and padding
|
||||
$modifiedLayoutStyles = $layoutStyles;
|
||||
$modifiedLayoutStyles['width'] = $width;
|
||||
$modifiedLayoutStyles['padding']['left'] = $this->parseNumberFromStringWithPixels($block['attrs']['style']['spacing']['padding']['left'] ?? '0px');
|
||||
$modifiedLayoutStyles['padding']['right'] = $this->parseNumberFromStringWithPixels($block['attrs']['style']['spacing']['padding']['right'] ?? '0px');
|
||||
|
||||
// Set current block values and reassign it to $parsedBlocks
|
||||
$block['email_attrs']['width'] = $width;
|
||||
$block['innerBlocks'] = $this->preprocess($block['innerBlocks'], $modifiedLayoutStyles);
|
||||
$parsedBlocks[$key] = $block;
|
||||
}
|
||||
return $parsedBlocks;
|
||||
}
|
||||
|
||||
// TODO: We could add support for other units like em, rem, etc.
|
||||
private function convertWithToPixels(string $currentWidth, float $layoutWidth): float {
|
||||
$width = $layoutWidth;
|
||||
if (strpos($currentWidth, '%') !== false) {
|
||||
$width = (float)str_replace('%', '', $currentWidth);
|
||||
$width = round($width / 100 * $layoutWidth);
|
||||
} elseif (strpos($currentWidth, 'px') !== false) {
|
||||
$width = $this->parseNumberFromStringWithPixels($currentWidth);
|
||||
}
|
||||
|
||||
return $width;
|
||||
}
|
||||
|
||||
private function parseNumberFromStringWithPixels(string $string): float {
|
||||
return (float)str_replace('px', '', $string);
|
||||
}
|
||||
|
||||
private function addMissingColumnWidths(array $columns): array {
|
||||
$columnsCount = count($columns);
|
||||
$defaultColumnsWidth = round(100 / $columnsCount, 2);
|
||||
|
||||
foreach ($columns as $key => $column) {
|
||||
if (!isset($column['attrs']['width'])) {
|
||||
$columns[$key]['attrs']['width'] = "{$defaultColumnsWidth}%";
|
||||
}
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
namespace unit\EmailEditor\Engine\Renderer;
|
||||
|
||||
use MailPoet\EmailEditor\Engine\Renderer\PreprocessManager;
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\BlocksWidthPreprocessor;
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\CleanupPreprocessor;
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\TopLevelPreprocessor;
|
||||
|
||||
@@ -24,10 +25,13 @@ class PreprocessManagerTest extends \MailPoetUnitTest {
|
||||
$cleanup = $this->createMock(CleanupPreprocessor::class);
|
||||
$cleanup->expects($this->once())->method('preprocess')->willReturn([]);
|
||||
|
||||
$blocksWidth = $this->createMock(BlocksWidthPreprocessor::class);
|
||||
$blocksWidth->expects($this->once())->method('preprocess')->willReturn([]);
|
||||
|
||||
$secondPreprocessor = $this->createMock(TopLevelPreprocessor::class);
|
||||
$secondPreprocessor->expects($this->once())->method('preprocess')->willReturn([]);
|
||||
|
||||
$preprocessManager = new PreprocessManager($cleanup, $topLevel);
|
||||
$preprocessManager = new PreprocessManager($cleanup, $topLevel, $blocksWidth);
|
||||
$preprocessManager->registerPreprocessor($secondPreprocessor);
|
||||
expect($preprocessManager->preprocess([], $layoutStyles))->equals([]);
|
||||
}
|
||||
|
@@ -0,0 +1,200 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace unit\EmailEditor\Engine\Renderer\Preprocessors;
|
||||
|
||||
use MailPoet\EmailEditor\Engine\Renderer\Preprocessors\BlocksWidthPreprocessor;
|
||||
|
||||
class BlocksWidthPreprocessorTest extends \MailPoetUnitTest {
|
||||
|
||||
/** @var BlocksWidthPreprocessor */
|
||||
private $preprocessor;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
$this->preprocessor = new BlocksWidthPreprocessor();
|
||||
}
|
||||
|
||||
public function testItCalculatesWidthWithoutPadding(): void {
|
||||
$blocks = [[
|
||||
'blockName' => 'core/columns',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '50%',
|
||||
],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '25%',
|
||||
],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '100px',
|
||||
],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
]];
|
||||
$result = $this->preprocessor->preprocess($blocks, ['width' => 660, 'padding' => ['left' => 0, 'right' => 0]]);
|
||||
$result = $result[0];
|
||||
expect($result['email_attrs']['width'])->equals(660);
|
||||
expect($result['innerBlocks'])->count(3);
|
||||
expect($result['innerBlocks'][0]['email_attrs']['width'])->equals(330); // 660 * 0.5
|
||||
expect($result['innerBlocks'][1]['email_attrs']['width'])->equals(165); // 660 * 0.25
|
||||
expect($result['innerBlocks'][2]['email_attrs']['width'])->equals(100);
|
||||
}
|
||||
|
||||
public function testItCalculatesWidthWithLayoutPadding(): void {
|
||||
$blocks = [[
|
||||
'blockName' => 'core/columns',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '33%',
|
||||
],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '100px',
|
||||
],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '20%',
|
||||
],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
]];
|
||||
$result = $this->preprocessor->preprocess($blocks, ['width' => 600, 'padding' => ['left' => 20, 'right' => 20]]);
|
||||
$result = $result[0];
|
||||
expect($result['innerBlocks'])->count(3);
|
||||
expect($result['innerBlocks'][0]['email_attrs']['width'])->equals(185); // (600 - 20 - 20) * 0.33
|
||||
expect($result['innerBlocks'][1]['email_attrs']['width'])->equals(100);
|
||||
expect($result['innerBlocks'][2]['email_attrs']['width'])->equals(112); // (600 - 20 - 20) * 0.2
|
||||
}
|
||||
|
||||
public function testItCalculatesWidthOfBlockInColumn(): void {
|
||||
$blocks = [[
|
||||
'blockName' => 'core/columns',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '40%',
|
||||
'style' => [
|
||||
'spacing' => [
|
||||
'padding' => [
|
||||
'left' => '10px',
|
||||
'right' => '10px',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/paragraph',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [
|
||||
'width' => '60%',
|
||||
'style' => [
|
||||
'spacing' => [
|
||||
'padding' => [
|
||||
'left' => '25px',
|
||||
'right' => '15px',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/paragraph',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]];
|
||||
$result = $this->preprocessor->preprocess($blocks, ['width' => 660, 'padding' => ['left' => 15, 'right' => 15]]);
|
||||
$innerBlocks = $result[0]['innerBlocks'];
|
||||
|
||||
expect($innerBlocks)->count(2);
|
||||
expect($innerBlocks[0]['email_attrs']['width'])->equals(252); // (660 - 15 - 15) * 0.4
|
||||
expect($innerBlocks[0]['innerBlocks'][0]['email_attrs']['width'])->equals(232); // paragraph: 252 - 10 - 10
|
||||
expect($innerBlocks[1]['email_attrs']['width'])->equals(378); // (660 - 15 - 15) * 0.6
|
||||
expect($innerBlocks[1]['innerBlocks'][0]['email_attrs']['width'])->equals(338); // paragraph: 378 - 25 - 15
|
||||
}
|
||||
|
||||
public function testItAddsMissingColumnWidth(): void {
|
||||
$blocks = [[
|
||||
'blockName' => 'core/columns',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/paragraph',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/paragraph',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'blockName' => 'core/column',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [
|
||||
[
|
||||
'blockName' => 'core/paragraph',
|
||||
'attrs' => [],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]];
|
||||
$result = $this->preprocessor->preprocess($blocks, ['width' => 660, 'padding' => ['left' => 30, 'right' => 30]]);
|
||||
$innerBlocks = $result[0]['innerBlocks'];
|
||||
|
||||
expect($innerBlocks)->count(3);
|
||||
expect($innerBlocks[0]['email_attrs']['width'])->equals(200); // (660 - 30 - 30) * 0.33
|
||||
expect($innerBlocks[0]['innerBlocks'][0]['email_attrs']['width'])->equals(200); // paragraph: 200
|
||||
expect($innerBlocks[1]['email_attrs']['width'])->equals(200); // (660 - 30 - 30) * 0.33
|
||||
expect($innerBlocks[1]['innerBlocks'][0]['email_attrs']['width'])->equals(200); // paragraph: 200
|
||||
expect($innerBlocks[2]['email_attrs']['width'])->equals(200); // (660 - 30 - 30) * 0.33
|
||||
expect($innerBlocks[2]['innerBlocks'][0]['email_attrs']['width'])->equals(200); // paragraph: 200
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user