Update Posts transformer to extract images by splitting the DOM tree
This commit is contained in:
@ -2,6 +2,7 @@
|
||||
namespace MailPoet\Newsletter\Editor;
|
||||
|
||||
use pQuery;
|
||||
use MailPoet\Util\DOM as DOMUtil;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -17,29 +18,22 @@ class StructureTransformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hoists images to root level, preserves order
|
||||
* and inserts tags before top ancestor
|
||||
* Hoists images to root level, preserves order by splitting neighboring
|
||||
* elements and inserts tags as children of top ancestor
|
||||
*/
|
||||
private function hoistImagesToRoot($root) {
|
||||
protected function hoistImagesToRoot($root) {
|
||||
foreach($root->query('img') as $item) {
|
||||
$top_ancestor = $this->findTopAncestor($item);
|
||||
$top_ancestor = DOMUtil::findTopAncestor($item);
|
||||
$offset = $top_ancestor->index();
|
||||
|
||||
if($item->hasParent('a')) {
|
||||
$item = $item->parent;
|
||||
}
|
||||
|
||||
$item->changeParent($root, $offset);
|
||||
DOMUtil::splitOn($item->getRoot(), $item);
|
||||
}
|
||||
}
|
||||
|
||||
private static function findTopAncestor($item) {
|
||||
while($item->parent->parent !== null) {
|
||||
$item = $item->parent;
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms HTML tags into their respective JSON objects,
|
||||
* turns other root children into text blocks
|
||||
|
40
lib/Util/DOM.php
Normal file
40
lib/Util/DOM.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace MailPoet\Util;
|
||||
use pQuery\DomNode;
|
||||
|
||||
class DOM {
|
||||
|
||||
/**
|
||||
* Splits a DOM tree around the cut element, bringing it up to bound
|
||||
* ancestor and splitting left and right siblings into subtrees along
|
||||
* the way, retaining order and nesting level.
|
||||
*/
|
||||
static function splitOn(DomNode $bound, DomNode $cut_element) {
|
||||
$ignore_text_and_comment_nodes = false;
|
||||
for($parent = $cut_element->parent; $bound != $parent; $parent = $grandparent) {
|
||||
// Clone parent node without children, but with attributes
|
||||
$parent->after($parent->toString());
|
||||
$right = $parent->getNextSibling($ignore_text_and_comment_nodes);
|
||||
$right->clear();
|
||||
|
||||
while($sibling = $cut_element->getNextSibling($ignore_text_and_comment_nodes)) {
|
||||
$sibling->move($right);
|
||||
}
|
||||
|
||||
// Reattach cut_element and right siblings to grandparent
|
||||
$grandparent = $parent->parent;
|
||||
$index_after_parent = $parent->index() + 1;
|
||||
$right->move($grandparent, $index_after_parent);
|
||||
$index_after_parent = $parent->index() + 1;
|
||||
$cut_element->move($grandparent, $index_after_parent);
|
||||
}
|
||||
}
|
||||
|
||||
static function findTopAncestor(DomNode $item) {
|
||||
while($item->parent->parent !== null) {
|
||||
$item = $item->parent;
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
}
|
30
tests/unit/Newsletter/Editor/StructureTransformerTest.php
Normal file
30
tests/unit/Newsletter/Editor/StructureTransformerTest.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace MailPoet\Test\Newsletter\Editor;
|
||||
|
||||
use pQuery;
|
||||
use MailPoet\Newsletter\Editor\StructureTransformer;
|
||||
|
||||
class StructureTransformerTest extends \MailPoetTest {
|
||||
|
||||
function _before() {
|
||||
$this->transformer = new StructureTransformer();
|
||||
}
|
||||
|
||||
function testItExtractsImagesAsImageBlocks() {
|
||||
$html = '<p><i>italic</i><em>previous text<a href="#mylink"><img src="#myimage" /></a>next text</em><b>bolded</b></p>';
|
||||
|
||||
$blocks = $this->transformer->transform($html, false);
|
||||
|
||||
expect($blocks)->count(3);
|
||||
expect($blocks[0]['type'])->equals('text');
|
||||
expect($blocks[0]['text'])->equals('<p><i>italic</i><em>previous text</em></p>');
|
||||
|
||||
expect($blocks[1]['type'])->equals('image');
|
||||
expect($blocks[1]['src'])->equals('#myimage');
|
||||
expect($blocks[1]['link'])->equals('#mylink');
|
||||
|
||||
expect($blocks[2]['type'])->equals('text');
|
||||
expect($blocks[2]['text'])->equals('<p><em>next text</em><b>bolded</b></p>');
|
||||
}
|
||||
|
||||
}
|
29
tests/unit/Util/DOMTest.php
Normal file
29
tests/unit/Util/DOMTest.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace MailPoet\Test\Util;
|
||||
|
||||
use pQuery;
|
||||
use MailPoet\Util\DOM as DOMUtil;
|
||||
|
||||
class DOMTest extends \MailPoetTest {
|
||||
|
||||
function _before() {
|
||||
$this->root = pQuery::parseStr('<p><i>italic</i><em>previous text<a href="#mylink"><img src="#myimage" /></a>next text</em><b>bolded</b></p>');
|
||||
}
|
||||
|
||||
function testItDeepSplitsDOMTreeByElement() {
|
||||
DOMUtil::splitOn($this->root, $this->root->query('a')->offsetGet(0));
|
||||
|
||||
expect($this->root->html())->equals(
|
||||
'<p><i>italic</i><em>previous text</em></p>'.
|
||||
'<a href="#mylink"><img src="#myimage" /></a>'.
|
||||
'<p><em>next text</em><b>bolded</b></p>'
|
||||
);
|
||||
}
|
||||
|
||||
function testItFindsTopAncestor() {
|
||||
$image = $this->root->query('img')->offsetGet(0);
|
||||
$paragraph = $this->root->query('p')->offsetGet(0);
|
||||
|
||||
expect(DOMUtil::findTopAncestor($image))->equals($paragraph);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user