Skip to content

Instantly share code, notes, and snippets.

@labboy0276
Created May 6, 2020 17:19
Show Gist options
  • Save labboy0276/8d7aaf07a71c15013a137ed3e381c808 to your computer and use it in GitHub Desktop.
Save labboy0276/8d7aaf07a71c15013a137ed3e381c808 to your computer and use it in GitHub Desktop.
WordPress (or any PHP framework) DomDocument HTML output alter
<?php
/**
* Use to easily alter HTML Output.
*/
class MarkupAlter {
/**
* The content we are altering.
*
* @var string
*/
protected $content;
/**
* The DOM Document.
*
* @var \DOMDocument;
*/
protected $dom;
/**
* MarkupAlter constructor.
*
* @param mixed $content
* The content we are altering.
*/
public function __construct($content) {
$this->content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
}
/**
* Initialize our DOM.
*
* @return void
* The initialized DOM.
*/
protected function initDom() {
libxml_use_internal_errors(true);
// Load our DOM.
$this->dom = new \DOMDocument;
// Load the current string without wrappers.
$this->dom->loadHTML($this->content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
}
/**
* Uses HTML DOM to alter the classes of a string.
*
* @param string $tag
* The tag we are altering.
* @param string $attr
* The class we are altering.
* @param string $type
* The type of attribute we are altering.
* @param bool $keep
* If we are keeping the original classes.
*
* @return string
* The altered content.
*/
public function alterDomAttr($tag, $attr, $type = "class", $keep = true) {
$this->initDom();
// Go through and add the class we are adding.
foreach ($this->dom->getElementsByTagName($tag) as $node) {
$orig = $node->hasAttribute($type) && $keep ? $node->getAttribute($type) . ' ' : '';
$node->setAttribute($type, $orig . $attr);
}
// Return the DOM Markup.
return $this->dom->saveHTML();
}
/**
* Uses HTML DOM to wrap tag in another tag.
*
* @param string $tag
* The tag we are altering.
* @param string $wrap_tag
* The tag we are wrapping.
* @param string $wrap_attr
* The class we adding to our tag.
*
* @return string
* The altered content.
*/
public function wrapHtmlTags($tag, $wrap_tag = 'div', $wrap_attr = '') {
$this->initDom();
// Create new wrapping tag.
$new_tag = $this->dom->createElement($wrap_tag);
if (!empty($wrap_attr)) {
$new_tag->setAttribute('class', $wrap_attr);
}
foreach ($this->dom->getElementsByTagName($tag) as $node) {
// Clone our created tag.
$new_tag_clone = $new_tag->cloneNode();
// Replace original tag with this wrapper tag.
$node->parentNode->replaceChild($new_tag_clone, $node);
// Append this orig tag to new tag.
$new_tag_clone->appendChild($node);
}
// Return the DOM Markup.
return $this->dom->saveHTML();
}
/**
* Replaces the tags of a string.
*
* @param $tag
* The tag we are replacing
* @param $replacement
* The tag we are injecting.
*
* @return string
* The altered content.
*/
public function replaceHtmlTags($tag, $replacement) {
// It is easier to use str_replace than HTML DOM.
$this->content = str_replace("<" . $tag, "<" . $replacement, $this->content);
$this->content = str_replace("</" . $tag . ">", "</" . $replacement . ">", $this->content);
return $this->content;
}
}
@labboy0276
Copy link
Author

labboy0276 commented May 6, 2020

I use this when we have to alter output in WordPress with plugins like Gravity Forms and FacetWP.

You can use this to:

  1. Add in a class or data attribute to an existing element easily (via alterDomAttr)
  2. Wrap an element in another element (via wrapHtmlTags)
  3. Replace the html tag of an element (via replaceHtmlTags)

I typically use it like this in a hook:

$output = (new MarkupAlter($output))->wrapHtmlTags('a', 'div', 'page-item');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment