Render image block on front end

[MAILPOET-2750]
This commit is contained in:
Rostislav Wolny
2020-04-02 10:53:27 +02:00
committed by Veljko V
parent 868a1aaaa6
commit 7a604fa10e
6 changed files with 176 additions and 1 deletions

View File

@@ -206,3 +206,30 @@ div.mailpoet_form_popup {
div.mailpoet_form_popup.active { div.mailpoet_form_popup.active {
display: block; display: block;
} }
// MailPoet Form - Image block
// Inspired by wp-image-block behaviour
.mailpoet_form_image {
&.is-style-rounded {
border-radius: 9999px;
}
.aligncenter {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.alignleft {
float: left;
margin-right: 1em;
}
.alignright {
float: right;
margin-left: 1em;
}
figcaption {
text-align: center;
}
}

View File

@@ -185,6 +185,7 @@ class ContainerConfigurator implements IContainerConfigurator {
$container->autowire(\MailPoet\Form\Block\Divider::class); $container->autowire(\MailPoet\Form\Block\Divider::class);
$container->autowire(\MailPoet\Form\Block\Html::class); $container->autowire(\MailPoet\Form\Block\Html::class);
$container->autowire(\MailPoet\Form\Block\Heading::class); $container->autowire(\MailPoet\Form\Block\Heading::class);
$container->autowire(\MailPoet\Form\Block\Image::class);
$container->autowire(\MailPoet\Form\Block\Paragraph::class); $container->autowire(\MailPoet\Form\Block\Paragraph::class);
$container->autowire(\MailPoet\Form\Block\Radio::class); $container->autowire(\MailPoet\Form\Block\Radio::class);
$container->autowire(\MailPoet\Form\Block\Segment::class); $container->autowire(\MailPoet\Form\Block\Segment::class);

48
lib/Form/Block/Image.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
namespace MailPoet\Form\Block;
class Image {
public function render(array $block): string {
if (empty($block['params']['url'])) {
return '';
}
return $this->wrapImage($block['params'], $this->renderImage($block['params']));
}
private function renderImage(array $params) {
$attributes = [];
$attributes[] = 'src="' . $params['url'] . '"';
$attributes[] = $params['alt'] ? 'alt="' . $params['alt'] . '"' : 'alt';
if ($params['title']) {
$attributes[] = 'title="' . $params['title'] . '"';
}
if ($params['id']) {
// WordPress automatically renders srcset based on this class
$attributes[] = 'class="wp-image-' . $params['id'] . '"';
}
if ($params['width']) {
$attributes[] = 'width="' . intval($params['width']) . '"';
}
if ($params['height']) {
$attributes[] = 'height="' . intval($params['height']) . '"';
}
return '<img ' . implode(' ', $attributes) . '" />';
}
private function wrapImage(array $params, string $img) {
// Figure
$figureClasses = ['size-' . $params['size_slug']];
if ($params['align']) {
$figureClasses[] = 'align' . $params['align'];
}
$caption = $params['caption'] ? "<figcaption>{$params['caption']}</figcaption>" : '';
$figure = '<figure class="' . implode(' ', $figureClasses) . '">' . $img . $caption . '</figure>';
// Main wrapper
$divClasses = ['mailpoet_form_image'];
if (trim($params['class_name'])) {
$divClasses[] = trim($params['class_name']);
}
return '<div class="' . implode(' ', $divClasses) . '">' . $figure . '</div>';
}
}

View File

@@ -9,6 +9,7 @@ use MailPoet\Form\Block\Date;
use MailPoet\Form\Block\Divider; use MailPoet\Form\Block\Divider;
use MailPoet\Form\Block\Heading; use MailPoet\Form\Block\Heading;
use MailPoet\Form\Block\Html; use MailPoet\Form\Block\Html;
use MailPoet\Form\Block\Image;
use MailPoet\Form\Block\Paragraph; use MailPoet\Form\Block\Paragraph;
use MailPoet\Form\Block\Radio; use MailPoet\Form\Block\Radio;
use MailPoet\Form\Block\Segment; use MailPoet\Form\Block\Segment;
@@ -30,6 +31,9 @@ class BlocksRenderer {
/** @var Html */ /** @var Html */
private $html; private $html;
/** @var Image */
private $image;
/** @var Radio */ /** @var Radio */
private $radio; private $radio;
@@ -67,6 +71,7 @@ class BlocksRenderer {
Date $date, Date $date,
Divider $divider, Divider $divider,
Html $html, Html $html,
Image $image,
Heading $heading, Heading $heading,
Paragraph $paragraph, Paragraph $paragraph,
Radio $radio, Radio $radio,
@@ -82,6 +87,7 @@ class BlocksRenderer {
$this->date = $date; $this->date = $date;
$this->divider = $divider; $this->divider = $divider;
$this->html = $html; $this->html = $html;
$this->image = $image;
$this->radio = $radio; $this->radio = $radio;
$this->segment = $segment; $this->segment = $segment;
$this->select = $select; $this->select = $select;
@@ -103,6 +109,10 @@ class BlocksRenderer {
$html .= $this->heading->render($block); $html .= $this->heading->render($block);
break; break;
case 'image':
$html .= $this->image->render($block);
break;
case 'paragraph': case 'paragraph':
$html .= $this->paragraph->render($block); $html .= $this->paragraph->render($block);
break; break;

View File

@@ -0,0 +1,78 @@
<?php
namespace MailPoet\Test\Form\Block;
use MailPoet\Form\Block\Image;
use MailPoet\Test\Form\HtmlParser;
require_once __DIR__ . '/../HtmlParser.php';
class ImageTest extends \MailPoetUnitTest {
/** @var Image */
private $image;
/** @var array */
private $block = [
'type' => 'image',
'id' => 'image',
'params' => [
'class_name' => 'my-class',
'align' => 'left',
'url' => 'http://example.com/image.jpg',
'alt' => 'Alt text',
'title' => 'Title',
'caption' => 'Caption',
'link_destination' => 'none',
'link' => null,
'id' => 123,
'size_slug' => 'medium',
'width' => 100,
'height' => 200,
],
];
/** @var HtmlParser */
private $htmlParser;
public function _before() {
parent::_before();
$this->image = new Image();
$this->htmlParser = new HtmlParser();
}
public function testItShouldRenderImageBlock() {
$html = $this->image->render($this->block);
$block = $this->htmlParser->getElementByXpath($html, '//div');
$blockClass = $this->htmlParser->getAttribute($block, 'class');
expect($blockClass->value)->equals('mailpoet_form_image my-class');
$figure = $this->htmlParser->getChildElement($block, 'figure');
$figureClass = $this->htmlParser->getAttribute($figure, 'class');
expect($figureClass->value)->equals('size-medium alignleft');
$img = $this->htmlParser->getChildElement($figure, 'img');
$imgSrc = $this->htmlParser->getAttribute($img, 'src');
expect($imgSrc->value)->equals('http://example.com/image.jpg');
$imgWidth = $this->htmlParser->getAttribute($img, 'width');
expect($imgWidth->value)->equals(100);
$imgHeight = $this->htmlParser->getAttribute($img, 'height');
expect($imgHeight->value)->equals(200);
$imgTitle = $this->htmlParser->getAttribute($img, 'title');
expect($imgTitle->value)->equals('Title');
$imgAlt = $this->htmlParser->getAttribute($img, 'alt');
expect($imgAlt->value)->equals('Alt text');
$caption = $this->htmlParser->getChildElement($figure, 'figcaption');
expect($caption->textContent)->equals('Caption');
}
public function testItRendersNothingWhenUrlIsEmpty() {
$block = $this->block;
$block['params']['url'] = null;
$html = $this->image->render($block);
expect($html)->equals('');
$block['params']['url'] = '';
$html = $this->image->render($block);
expect($html)->equals('');
}
}

View File

@@ -3,9 +3,20 @@
namespace MailPoet\Test\Form; namespace MailPoet\Test\Form;
class HtmlParser { class HtmlParser {
private $allowedHtml5Tags = ['<figure', '<figcaption'];
public function findByXpath(string $html, string $xpath): \DOMNodeList { public function findByXpath(string $html, string $xpath): \DOMNodeList {
$isHtml5 = str_replace($this->allowedHtml5Tags, '', $html) !== $html;
$dom = new \DOMDocument(); $dom = new \DOMDocument();
$dom->loadHTML($html); if ($isHtml5) {
// HTML 5 tags like figure, nav are not supported so we need to turn off errors
libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_clear_errors();
} else {
$dom->loadHTML($html);
}
$value = (new \DOMXPath($dom))->query($xpath); $value = (new \DOMXPath($dom))->query($xpath);
return $value ?: new \DOMNodeList(); return $value ?: new \DOMNodeList();
} }