35 protected $_blocks =
'address article area aside blockquote caption col colgroup dd 36 details div dl dt fieldset figure figcaption footer form h1 h2 h3 h4 h5 h6 header 37 hr hgroup legend map math menu nav noscript p pre section select style summary 38 table tbody td tfoot th thead tr ul ol option li';
43 protected $_inlines =
'a abbr audio b button canvas caption cite code command datalist 44 del dfn em embed i iframe img input ins kbd keygen label map mark meter object 45 output progress q rp rt ruby s samp script select small source span strong style 46 sub sup textarea time var video wbr';
53 protected $_descendList =
'article aside blockquote body details div footer form 61 protected $_alterList =
'article aside blockquote body details div footer header 73 $this->_blocks = preg_split(
'@\\s+@', $this->_blocks);
74 $this->_descendList = preg_split(
'@\\s+@', $this->_descendList);
75 $this->_alterList = preg_split(
'@\\s+@', $this->_alterList);
76 $this->_inlines = preg_split(
'@\\s+@', $this->_inlines);
77 $this->_unique =
md5(__FILE__);
104 $this->_doc = new \DOMDocument();
108 $use_internal_errors = libxml_use_internal_errors(
true);
110 $load_result = $this->_doc->loadHTML(
"<html><meta http-equiv='content-type' content='text/html; charset={$this->encoding}'><body>{$html}</body></html>", LIBXML_NOBLANKS);
112 libxml_use_internal_errors($use_internal_errors);
117 $this->_xpath = new \DOMXPath($this->_doc);
120 $nodeList = $this->_xpath->query(
'//body[1]');
121 if ($nodeList->item(0) instanceof \DOMText) {
124 $this->_xpath = new \DOMXPath($this->_doc);
125 $nodeList = $this->_xpath->query(
'//body[1]');
127 if ($nodeList->item(0) instanceof \DOMText) {
129 throw new RuntimeException(
'DOMXPath::query for BODY element returned a text node');
136 $html = $this->_doc->saveHTML();
141 $html = preg_replace(
'/(' . $this->_unique .
'NL){2,}/',
'</autop><autop>', $html);
142 $html =
str_replace([$this->_unique .
'BR', $this->_unique .
'NL',
'<br>'],
145 $html =
str_replace(
'<br /></autop>',
'</autop>', $html);
151 $use_internal_errors = libxml_use_internal_errors(
true);
153 $load_result = $this->_doc->loadHTML($html);
155 libxml_clear_errors();
156 libxml_use_internal_errors($use_internal_errors);
162 $this->_xpath = new \DOMXPath($this->_doc);
165 foreach ($this->_xpath->query(
'//autop') as $autop) {
168 if (
trim($autop->textContent) !==
'') {
171 foreach ($autop->childNodes as $node) {
172 if ($node->nodeType === XML_ELEMENT_NODE) {
181 $autop->setAttribute(
'r',
'1');
186 foreach ($this->_xpath->query(
'//div') as $el) {
188 $autops = $this->_xpath->query(
'./autop', $el);
189 if ($autops->length === 1) {
190 $firstAutop = $autops->item(0);
192 $firstAutop->setAttribute(
'r',
'1');
196 $html = $this->_doc->saveHTML();
200 $bodyEnd =
elgg_strpos($html,
'</body>', $bodyStart + 6);
201 $html =
elgg_substr($html, $bodyStart + 6, $bodyEnd - $bodyStart - 6);
204 $html = preg_replace(
'@<autop r="1">(.*?)</autop>@',
'\\1', $html);
211 return str_replace($this->_unique .
'AMP',
'&', $html);
223 $elsToProcess = [$el];
224 $inlinesToProcess = [];
225 while ($el = array_shift($elsToProcess)) {
228 $alterInline = in_array($el->nodeName, $this->_alterList);
232 $ltrimFirstTextNode =
true;
239 $isFollowingBr =
false;
241 $node = $el->firstChild;
242 while (isset($node)) {
247 $autop = $el->insertBefore($this->_doc->createElement(
'autop'), $node);
251 $isElement = ($node->nodeType === XML_ELEMENT_NODE);
253 $isBlock = in_array($node->nodeName, $this->_blocks);
256 $ltrimFirstTextNode =
false;
263 $isText = ($node->nodeType === XML_TEXT_NODE);
264 $isLastInline = (!$node->nextSibling
265 || ($node->nextSibling->nodeType === XML_ELEMENT_NODE
266 && in_array($node->nextSibling->nodeName, $this->_blocks)));
268 $isFollowingBr = ($node->nodeName ===
'br');
272 $nodeText = $node->nodeValue;
274 if ($ltrimFirstTextNode) {
276 $nodeText = ltrim($nodeText);
277 $ltrimFirstTextNode =
false;
281 if ($isFollowingBr &&
preg_match(
'@^[ \\t]*\\n[ \\t]*@', $nodeText, $matches)) {
288 $nodeText =
rtrim($nodeText);
291 $nodeText =
str_replace(
"\n", $this->_unique .
'NL', $nodeText);
293 $node = $node->nextSibling;
296 $tmpNode->nodeValue = $nodeText;
297 $autop->appendChild($tmpNode);
303 if ($isBlock || !$node->nextSibling) {
305 if (in_array($node->nodeName, $this->_descendList)) {
306 $elsToProcess[] = $node;
312 $ltrimFirstTextNode =
true;
318 if ($isElement &&
elgg_strpos($tmpNode->textContent,
"\n") !==
false) {
319 $inlinesToProcess[] = $tmpNode;
322 $node = $node->nextSibling;
323 $autop->appendChild($tmpNode);
328 $node = $node->nextSibling;
334 while ($el = array_shift($inlinesToProcess)) {
335 $ignoreLeadingNewline =
false;
336 foreach ($el->childNodes as $node) {
337 if ($node->nodeType === XML_ELEMENT_NODE) {
338 if ($node->nodeValue ===
'BR') {
339 $ignoreLeadingNewline =
true;
341 $ignoreLeadingNewline =
false;
342 if (
elgg_strpos($node->textContent,
"\n") !==
false) {
343 $inlinesToProcess[] = $node;
346 }
elseif ($node->nodeType === XML_TEXT_NODE) {
347 $text = $node->nodeValue;
348 if (
$text[0] ===
"\n" && $ignoreLeadingNewline) {
350 $ignoreLeadingNewline =
false;
__construct()
Constructor.
Exception thrown if an error which can only be found on runtime occurs.
Create wrapper P and BR elements in HTML depending on newlines.
if($item instanceof\ElggEntity) elseif($item instanceof\ElggRiverItem) elseif($item instanceof\ElggRelationship) elseif(is_callable([$item, 'getType']))
elgg_strlen()
Wrapper function for mb_strlen().
$html
A wrapper to render a section of the page shell.
elgg_strpos()
Wrapper function for mb_strpos().
addParagraphs(\DOMElement $el)
Add P and BR elements as necessary.
elgg_substr()
Wrapper function for mb_substr().
process($html)
Create wrapper P and BR elements in HTML depending on newlines.