Passed
Push — master ( d34f9d...e217a6 )
by Josh
02:33
created

ConvertCurlyExpressionsInText::normalizeText()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 36
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 36
ccs 18
cts 18
cp 1
rs 9.6333
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2023 The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Configurator\TemplateNormalizations;
9
10
use DOMText;
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
*/
20
class 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
0 ignored issues
show
Bug introduced by
The type s9e\TextFormatter\Config...eNormalizations\DOMNode was not found. Did you mean DOMNode? If so, make sure to prefix the type with \.
Loading history...
32
	* @return void
33
	*/
34 3
	protected function insertTextBefore($text, $node)
35
	{
36 3
		if ($text > '')
37
		{
38 2
			$node->parentNode->insertBefore($this->createText($text), $node);
39
		}
40
	}
41
42
	/**
43
	* {@inheritdoc}
44
	*/
45 3
	protected function normalizeText(DOMText $node): void
46
	{
47 3
		$parentNode = $node->parentNode;
48
49 3
		preg_match_all(
50 3
			'#\\{([$@][-\\w]+)\\}#',
51 3
			$node->textContent,
52
			$matches,
53 3
			PREG_SET_ORDER | PREG_OFFSET_CAPTURE
54
		);
55
56 3
		$lastPos = 0;
57 3
		foreach ($matches as $m)
58
		{
59 3
			$pos = $m[0][1];
60
61
			// Catch up to current position
62 3
			if ($pos > $lastPos)
63
			{
64 2
				$text = substr($node->textContent, $lastPos, $pos - $lastPos);
65 2
				$this->insertTextBefore($text, $node);
66
			}
67 3
			$lastPos = $pos + strlen($m[0][0]);
68
69
			// Add the xsl:value-of element
70
			$parentNode
71 3
				->insertBefore($this->createElement('xsl:value-of'), $node)
72 3
				->setAttribute('select', $m[1][0]);
73
		}
74
75
		// Append the rest of the text
76 3
		$text = substr($node->textContent, $lastPos);
77 3
		$this->insertTextBefore($text, $node);
78
79
		// Now remove the old text node
80 3
		$parentNode->removeChild($node);
81
	}
82
}