1<?php
2
3/**
4* @package   s9e\TextFormatter
5* @copyright Copyright (c) 2010-2021 The s9e authors
6* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7*/
8namespace s9e\TextFormatter\Configurator\TemplateNormalizations;
9
10use DOMNode;
11
12/**
13* Convert simple expressions in curly brackets in text into xsl:value-of elements
14*
15* Will replace
16*     <span>{$FOO}{@bar}</span>
17* with
18*     <span><xsl:value-of value="$FOO"/><xsl:value-of value="@bar"/></span>
19*/
20class ConvertCurlyExpressionsInText extends AbstractNormalization
21{
22	/**
23	* {@inheritdoc}
24	*/
25	protected $queries = ['//*[namespace-uri() != $XSL]/text()[contains(., "{@") or contains(., "{$")]'];
26
27	/**
28	* Insert a text node before given node
29	*
30	* @param  string  $text
31	* @param  DOMNode $node
32	* @return void
33	*/
34	protected function insertTextBefore($text, $node)
35	{
36		if ($text > '')
37		{
38			$node->parentNode->insertBefore($this->createText($text), $node);
39		}
40	}
41
42	/**
43	* {@inheritdoc}
44	*/
45	protected function normalizeNode(DOMNode $node)
46	{
47		$parentNode = $node->parentNode;
48
49		preg_match_all(
50			'#\\{([$@][-\\w]+)\\}#',
51			$node->textContent,
52			$matches,
53			PREG_SET_ORDER | PREG_OFFSET_CAPTURE
54		);
55
56		$lastPos = 0;
57		foreach ($matches as $m)
58		{
59			$pos = $m[0][1];
60
61			// Catch up to current position
62			if ($pos > $lastPos)
63			{
64				$text = substr($node->textContent, $lastPos, $pos - $lastPos);
65				$this->insertTextBefore($text, $node);
66			}
67			$lastPos = $pos + strlen($m[0][0]);
68
69			// Add the xsl:value-of element
70			$parentNode
71				->insertBefore($this->createElement('xsl:value-of'), $node)
72				->setAttribute('select', $m[1][0]);
73		}
74
75		// Append the rest of the text
76		$text = substr($node->textContent, $lastPos);
77		$this->insertTextBefore($text, $node);
78
79		// Now remove the old text node
80		$parentNode->removeChild($node);
81	}
82}