Render image block on front end
[MAILPOET-2750]
This commit is contained in:
committed by
Veljko V
parent
868a1aaaa6
commit
7a604fa10e
@@ -206,3 +206,30 @@ div.mailpoet_form_popup {
|
||||
div.mailpoet_form_popup.active {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@@ -185,6 +185,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoet\Form\Block\Divider::class);
|
||||
$container->autowire(\MailPoet\Form\Block\Html::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\Radio::class);
|
||||
$container->autowire(\MailPoet\Form\Block\Segment::class);
|
||||
|
48
lib/Form/Block/Image.php
Normal file
48
lib/Form/Block/Image.php
Normal 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>';
|
||||
}
|
||||
}
|
@@ -9,6 +9,7 @@ use MailPoet\Form\Block\Date;
|
||||
use MailPoet\Form\Block\Divider;
|
||||
use MailPoet\Form\Block\Heading;
|
||||
use MailPoet\Form\Block\Html;
|
||||
use MailPoet\Form\Block\Image;
|
||||
use MailPoet\Form\Block\Paragraph;
|
||||
use MailPoet\Form\Block\Radio;
|
||||
use MailPoet\Form\Block\Segment;
|
||||
@@ -30,6 +31,9 @@ class BlocksRenderer {
|
||||
/** @var Html */
|
||||
private $html;
|
||||
|
||||
/** @var Image */
|
||||
private $image;
|
||||
|
||||
/** @var Radio */
|
||||
private $radio;
|
||||
|
||||
@@ -67,6 +71,7 @@ class BlocksRenderer {
|
||||
Date $date,
|
||||
Divider $divider,
|
||||
Html $html,
|
||||
Image $image,
|
||||
Heading $heading,
|
||||
Paragraph $paragraph,
|
||||
Radio $radio,
|
||||
@@ -82,6 +87,7 @@ class BlocksRenderer {
|
||||
$this->date = $date;
|
||||
$this->divider = $divider;
|
||||
$this->html = $html;
|
||||
$this->image = $image;
|
||||
$this->radio = $radio;
|
||||
$this->segment = $segment;
|
||||
$this->select = $select;
|
||||
@@ -103,6 +109,10 @@ class BlocksRenderer {
|
||||
$html .= $this->heading->render($block);
|
||||
break;
|
||||
|
||||
case 'image':
|
||||
$html .= $this->image->render($block);
|
||||
break;
|
||||
|
||||
case 'paragraph':
|
||||
$html .= $this->paragraph->render($block);
|
||||
break;
|
||||
|
78
tests/unit/Form/Block/ImageTest.php
Normal file
78
tests/unit/Form/Block/ImageTest.php
Normal 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('');
|
||||
}
|
||||
}
|
@@ -3,9 +3,20 @@
|
||||
namespace MailPoet\Test\Form;
|
||||
|
||||
class HtmlParser {
|
||||
|
||||
private $allowedHtml5Tags = ['<figure', '<figcaption'];
|
||||
|
||||
public function findByXpath(string $html, string $xpath): \DOMNodeList {
|
||||
$isHtml5 = str_replace($this->allowedHtml5Tags, '', $html) !== $html;
|
||||
$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);
|
||||
return $value ?: new \DOMNodeList();
|
||||
}
|
||||
|
Reference in New Issue
Block a user