Add blocks preprocessor
Currently, we need to wrap top-level non-column blocks into a single column. This is done in the preprocessor. [MAILPOET-5540]
This commit is contained in:
committed by
Jan Lysý
parent
69a87e8146
commit
968ff6754e
@@ -319,6 +319,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
|||||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\BodyRenderer::class)->setPublic(true);
|
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\BodyRenderer::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\BlocksRenderer::class)->setPublic(true);
|
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\BlocksRenderer::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\BlocksRegistry::class)->setPublic(true);
|
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\BlocksRegistry::class)->setPublic(true);
|
||||||
|
$container->autowire(\MailPoet\EmailEditor\Engine\Renderer\Preprocessor::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\EmailEditor\Integrations\Core\Initializer::class)->setPublic(true);
|
$container->autowire(\MailPoet\EmailEditor\Integrations\Core\Initializer::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\EmailEditor\Integrations\MailPoet\EmailEditor::class)->setPublic(true);
|
$container->autowire(\MailPoet\EmailEditor\Integrations\MailPoet\EmailEditor::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\EmailEditor\Integrations\MailPoet\EmailApiController::class)->setPublic(true);
|
$container->autowire(\MailPoet\EmailEditor\Integrations\MailPoet\EmailApiController::class)->setPublic(true);
|
||||||
|
@@ -13,10 +13,7 @@ class BodyRenderer {
|
|||||||
$this->blocksRenderer = $blocksRenderer;
|
$this->blocksRenderer = $blocksRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderBody(string $postContent): string {
|
public function renderBody(array $parsedBlocks): string {
|
||||||
$parser = new \WP_Block_Parser();
|
|
||||||
$parsedBlocks = $parser->parse($postContent);
|
|
||||||
// @todo We need to wrap top level blocks which are not in columns into a column
|
|
||||||
return $this->blocksRenderer->render($parsedBlocks);
|
return $this->blocksRenderer->render($parsedBlocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
52
mailpoet/lib/EmailEditor/Engine/Renderer/Preprocessor.php
Normal file
52
mailpoet/lib/EmailEditor/Engine/Renderer/Preprocessor.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace MailPoet\EmailEditor\Engine\Renderer;
|
||||||
|
|
||||||
|
class Preprocessor {
|
||||||
|
|
||||||
|
const SINGLE_COLUMN_TEMPLATE = [
|
||||||
|
'blockName' => 'core/columns',
|
||||||
|
'attrs' => [],
|
||||||
|
'innerBlocks' => [[
|
||||||
|
'blockName' => 'core/column',
|
||||||
|
'attrs' => [],
|
||||||
|
'innerBlocks' => [],
|
||||||
|
]],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function preprocess(array $parsedBlocks): array {
|
||||||
|
return $this->addTopLevelColumns($parsedBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In the editor we allow putting content blocks directly into the root level of the email.
|
||||||
|
* But for rendering purposes it is more convenient to have them wrapped in a single column.
|
||||||
|
* This method walks through the first level of blocks and wraps non column blocks into a single column.
|
||||||
|
*/
|
||||||
|
private function addTopLevelColumns(array $parsedBlocks): array {
|
||||||
|
$wrappedParsedBlocks = [];
|
||||||
|
$nonColumnsBlocksBuffer = [];
|
||||||
|
foreach ($parsedBlocks as $block) {
|
||||||
|
// The next block is columns so we can flush the buffer and add the columns block
|
||||||
|
if ($block['blockName'] === 'core/columns') {
|
||||||
|
if ($nonColumnsBlocksBuffer) {
|
||||||
|
$columnsBlock = self::SINGLE_COLUMN_TEMPLATE;
|
||||||
|
$columnsBlock['innerBlocks'][0]['innerBlocks'] = $nonColumnsBlocksBuffer;
|
||||||
|
$nonColumnsBlocksBuffer = [];
|
||||||
|
$wrappedParsedBlocks[] = $columnsBlock;
|
||||||
|
}
|
||||||
|
$wrappedParsedBlocks[] = $block;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Non columns block so we add it to the buffer
|
||||||
|
$nonColumnsBlocksBuffer[] = $block;
|
||||||
|
}
|
||||||
|
// Flush the buffer if there are any blocks left
|
||||||
|
if ($nonColumnsBlocksBuffer) {
|
||||||
|
$columnsBlock = self::SINGLE_COLUMN_TEMPLATE;
|
||||||
|
$columnsBlock['innerBlocks'][0]['innerBlocks'] = $nonColumnsBlocksBuffer;
|
||||||
|
$wrappedParsedBlocks[] = $columnsBlock;
|
||||||
|
}
|
||||||
|
return $wrappedParsedBlocks;
|
||||||
|
}
|
||||||
|
}
|
@@ -13,6 +13,9 @@ class Renderer {
|
|||||||
/** @var BodyRenderer */
|
/** @var BodyRenderer */
|
||||||
private $bodyRenderer;
|
private $bodyRenderer;
|
||||||
|
|
||||||
|
/** @var Preprocessor */
|
||||||
|
private $preprocessor;
|
||||||
|
|
||||||
const TEMPLATE_FILE = 'template.html';
|
const TEMPLATE_FILE = 'template.html';
|
||||||
const STYLES_FILE = 'styles.css';
|
const STYLES_FILE = 'styles.css';
|
||||||
|
|
||||||
@@ -21,14 +24,21 @@ class Renderer {
|
|||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
\MailPoetVendor\CSS $cssInliner,
|
\MailPoetVendor\CSS $cssInliner,
|
||||||
|
Preprocessor $preprocessor,
|
||||||
BodyRenderer $bodyRenderer
|
BodyRenderer $bodyRenderer
|
||||||
) {
|
) {
|
||||||
$this->cssInliner = $cssInliner;
|
$this->cssInliner = $cssInliner;
|
||||||
|
$this->preprocessor = $preprocessor;
|
||||||
$this->bodyRenderer = $bodyRenderer;
|
$this->bodyRenderer = $bodyRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(\WP_Post $post, string $subject, string $preHeader, string $language, $metaRobots = ''): array {
|
public function render(\WP_Post $post, string $subject, string $preHeader, string $language, $metaRobots = ''): array {
|
||||||
$renderedBody = $this->bodyRenderer->renderBody($post->post_content); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
$parser = new \WP_Block_Parser();
|
||||||
|
$parsedBlocks = $parser->parse($post->post_content); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||||
|
|
||||||
|
$parsedBlocks = $this->preprocessor->preprocess($parsedBlocks);
|
||||||
|
$renderedBody = $this->bodyRenderer->renderBody($parsedBlocks);
|
||||||
|
|
||||||
$styles = (string)file_get_contents(dirname(__FILE__) . '/' . self::STYLES_FILE);
|
$styles = (string)file_get_contents(dirname(__FILE__) . '/' . self::STYLES_FILE);
|
||||||
$styles = apply_filters('mailpoet_email_renderer_styles', $styles, $post);
|
$styles = apply_filters('mailpoet_email_renderer_styles', $styles, $post);
|
||||||
|
|
||||||
|
@@ -0,0 +1,63 @@
|
|||||||
|
<?php declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace MailPoet\EmailEditor\Engine\Renderer;
|
||||||
|
|
||||||
|
class PreprocessorTest extends \MailPoetUnitTest {
|
||||||
|
|
||||||
|
private $paragraphBlock = [
|
||||||
|
'blockName' => 'core/paragraph',
|
||||||
|
'attrs' => [],
|
||||||
|
'innerHTML' => 'Paragraph content',
|
||||||
|
];
|
||||||
|
|
||||||
|
private $columnsBlock = [
|
||||||
|
'blockName' => 'core/columns',
|
||||||
|
'attrs' => [],
|
||||||
|
'innerBlocks' => [[
|
||||||
|
'blockName' => 'core/column',
|
||||||
|
'attrs' => [],
|
||||||
|
'innerBlocks' => [],
|
||||||
|
]],
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var Preprocessor */
|
||||||
|
private $preprocessor;
|
||||||
|
|
||||||
|
public function _before() {
|
||||||
|
parent::_before();
|
||||||
|
$this->preprocessor = new Preprocessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItWrapsSingleTopLevelBlockIntoColumns() {
|
||||||
|
$parsedDocument = [$this->paragraphBlock];
|
||||||
|
$result = $this->preprocessor->preprocess($parsedDocument);
|
||||||
|
expect($result[0]['blockName'])->equals('core/columns');
|
||||||
|
expect($result[0]['innerBlocks'][0]['blockName'])->equals('core/column');
|
||||||
|
expect($result[0]['innerBlocks'][0]['innerBlocks'][0]['blockName'])->equals('core/paragraph');
|
||||||
|
expect($result[0]['innerBlocks'][0]['innerBlocks'][0]['innerHTML'])->equals('Paragraph content');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntWrapColumns() {
|
||||||
|
$parsedDocumentWithMultipleColumns = [$this->columnsBlock, $this->columnsBlock];
|
||||||
|
$result = $this->preprocessor->preprocess($parsedDocumentWithMultipleColumns);
|
||||||
|
expect($result)->equals($parsedDocumentWithMultipleColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItWrapsTopLevelBlocksSpreadBetweenColumns() {
|
||||||
|
$parsedDocument = [$this->paragraphBlock, $this->columnsBlock, $this->paragraphBlock, $this->paragraphBlock];
|
||||||
|
// We expect to wrap top level paragraph blocks into columns so the result should three columns blocks
|
||||||
|
$result = $this->preprocessor->preprocess($parsedDocument);
|
||||||
|
expect($result)->count(3);
|
||||||
|
// First columns contain columns with one paragraph block
|
||||||
|
expect($result[0]['innerBlocks'][0]['blockName'])->equals('core/column');
|
||||||
|
expect($result[0]['innerBlocks'][0]['innerBlocks'][0]['blockName'])->equals('core/paragraph');
|
||||||
|
// Second columns remains empty
|
||||||
|
expect($result[1]['innerBlocks'][0]['blockName'])->equals('core/column');
|
||||||
|
expect($result[1]['innerBlocks'][0]['innerBlocks'])->isEmpty();
|
||||||
|
// Third columns contain columns with two paragraph blocks
|
||||||
|
expect($result[2]['innerBlocks'][0]['blockName'])->equals('core/column');
|
||||||
|
expect($result[2]['innerBlocks'][0]['innerBlocks'])->count(2);
|
||||||
|
expect($result[2]['innerBlocks'][0]['innerBlocks'][0]['blockName'])->equals('core/paragraph');
|
||||||
|
expect($result[2]['innerBlocks'][0]['innerBlocks'][1]['blockName'])->equals('core/paragraph');
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user