Extend the template syntax through normalization

In the following example, we create a custom normalization that replaces pairs of comments in the form <!-- IF FOO -->, <!-- ENDIF --> with a normal <xsl:if test="$FOO"> element. Since template normalization is automatically run on every template, this effectively extends the template syntax to support this new construct.

$configurator = new s9e\TextFormatter\Configurator;

// We prepend our callback so that it's executed before comments are removed
$configurator->templateNormalizer->prepend(
    function (DOMNode $template)
    {
        $dom   = $template->ownerDocument;
        $xpath = new DOMXPath($dom);
        $query = '//comment()[. = " ENDIF "]';

        // Query all ENDIF comments
        foreach ($xpath->query($query) as $comment)
        {
            // Iterate backwards from the ENDIF comment until we find an IF comment
            $node = $comment->previousSibling;

            while ($node)
            {
                if ($node->nodeType === XML_COMMENT_NODE
                 && preg_match('/^ IF (\\w+) $/', $node->textContent, $m))
                {
                    break;
                }

                $node = $node->previousSibling;
            }

            if (empty($m))
            {
                continue;
            }

            // Create the xsl:if element that will replace the pair of comments
            $xslIf = $dom->createElementNS('http://www.w3.org/1999/XSL/Transform', 'if');
            $xslIf->setAttribute('test', '$' . $m[1]);

            // Iterate forward from the IF comment to the ENDIF and move nodes to the xsl:if
            while (!$node->nextSibling->isSameNode($comment))
            {
                $xslIf->appendChild($node->parentNode->removeChild($node->nextSibling));
            }

            // All that's left is to remove the ENDIF comment and replace the IF comment with xsl:if
            $node->parentNode->removeChild($node->nextSibling);
            $node->parentNode->replaceChild($xslIf, $node);
        }
    }
)->onlyOnce = true;

echo $configurator->templateNormalizer->normalizeTemplate('
    <!-- IF S_USER_LOGGED_IN -->
    <div>Welcome!</div>
    <!-- ENDIF -->
');
<xsl:if test="$S_USER_LOGGED_IN"><div>Welcome!</div></xsl:if>