# Run the sanitize a document fragment algorithm on fragment.
$this->sanitizeDocumentFragment($fragment);
# Return fragment.
return $fragment;
}
/** Creates a copy of the input as a document fragment, which can then be safely manipulated
*
* @param \DOMDocument|\DOMDocumentFragment $input The input to clone
*/
protected function createDocumentFragment(\DOMNode $input): \DOMDocumentFragment {
assert($input instanceof \DOMDocument || $input instanceof \DOMDocumentFragment, new \Exception("Parameter \$input must be of type \DOMDocument|\DOMDocumentFragment"));
# To create a document fragment named fragment from an input of type
# Document or DocumentFragment, run these steps:
# Let node be null.
$node = null;
# Switch based on input’s type:
# If input is of type DocumentFragment, then:
# Set node to input.
# If input is of type Document, then:
# Set node to input’s documentElement.
if ($input instanceof \DOMDocumentFragment) {
$node = $input;
} elseif ($input instanceof \DOMDocument) {
$node = $input->documentElement;
}
# Let clone be the result of running clone a node on node with the
# clone children flag set.
$clone = $node->cloneNode(true);
# Let fragment be a new DocumentFragment whose node document is node’s
/** Iterates over a document fragment and sanitizes its nodes
*
* @param \DOMDocumentFragment $fragment The document fragment to sanitize
*/
protected function sanitizeDocumentFragment(\DOMDocumentFragment $fragment): void {
# To sanitize a document fragment named fragment with a Sanitizer
# sanitizer run these steps:
# Let m be a map that maps nodes to a sanitize action.
# Let nodes be a list containing the inclusive descendants of fragment, in tree order.
// Basically we won't be doing things this way. Rather than treating
// all of the fragment's nodes as a flat list, we'll walk the
// fragment and decide as we go, till have visited every node
$node = $fragment->firstChild;
# For each node in nodes:
while ($node) {
# Let action be the result of running the sanitize a node algorithm on node with sanitizer.
$action = $this->sanitizeNode($node);
assert(in_array($action, [self::ACTION_BLOCK, self::ACTION_DROP, self::ACTION_KEEP]), new \Exception("The result of sanitizing a node must be one of the three actions"));
# Set m[node] to action.
# For each node in nodes:
// Again, we're taking action one node at a time; m[node] is simply $action
if ($action === self::ACTION_DROP) {
# If m[node] is drop, remove node.
$victim = $node;
$node = $this->nextNode($node, false);
$victim->parentNode->removeChild($victim);
} else if ($action === self::ACTION_BLOCK) {
# If m[node] is block, create a DocumentFragment fragment,
# append all of node’s children to fragment, and replace
# node within node’s parent with fragment.
// This is a bit confusing because the variable name "fragment"
// is re-used; this is a different fragment from the input