Completed
Push — master ( 27f709...a3e52e )
by Josh
03:54
created

SingleByteStringManipulation::convertTranslate()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 12
cts 12
cp 1
rs 9.536
c 0
b 0
f 0
cc 3
nc 2
nop 3
crap 3

1 Method

Rating   Name   Duplication   Size   Complexity  
A SingleByteStringManipulation::isAsciiChars() 0 4 1
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2019 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors;
9
10
class SingleByteStringManipulation extends AbstractConvertor
11
{
12
	/**
13
	* {@inheritdoc}
14
	*/
15 80
	public function getMatchers(): array
16
	{
17
		return [
18 80
			'String:Concat'          => 'concat \\( ((?&String)) ((?:, (?&String) )+)?\\)',
19
			'String:NormalizeSpace'  => 'normalize-space \\( ((?&String)) \\)',
20
			'String:SubstringAfter'  => 'substring-after \\( ((?&String)) , ((?&LiteralString)) \\)',
21
			'String:SubstringBefore' => 'substring-before \\( ((?&String)) , ((?&String)) \\)',
22
			'String:Translate'       => 'translate \\( ((?&String)) , ((?&LiteralString)) , ((?&LiteralString)) \\)'
23
		];
24
	}
25
26
	/**
27
	* Convert a call to concat()
28
	*
29
	* @param  string $expr1 First argument
30
	* @param  string $expr2 All other comma-separated arguments, starting with a comma
31
	* @return string
32
	*/
33 4
	public function parseConcat($expr1, $expr2 = null)
34
	{
35 4
		$php = $this->recurse($expr1);
36 4
		if (isset($expr2))
37
		{
38 3
			$php .= '.' . $this->recurse('concat(' . ltrim($expr2, ',') . ')');
39
		}
40
41 4
		return $php;
42
	}
43
44
	/**
45
	* Convert a call to normalize-space()
46
	*
47
	* @param  string $expr
48
	* @return string
49
	*/
50 1
	public function parseNormalizeSpace($expr)
51
	{
52 1
		return "preg_replace('(\\\\s+)',' ',trim(" . $this->recurse($expr) . '))';
53
	}
54
55
	/**
56
	* Convert a call to substring-after() where the second argument is a literal string
57
	*
58
	* @param  string $expr
59
	* @param  string $str
60
	* @return string
61
	*/
62 1
	public function parseSubstringAfter($expr, $str)
63
	{
64 1
		return 'substr(strstr(' . $this->recurse($expr) . ',' . $this->recurse($str) . '),' . (strlen($str) - 2) . ')';
65
	}
66
67
	/**
68
	* Convert a call to substring-before()
69
	*
70
	* @param  string $expr1
71
	* @param  string $expr2
72
	* @return string
73
	*/
74 2
	public function parseSubstringBefore($expr1, $expr2)
75
	{
76 2
		return 'strstr(' . $this->recurse($expr1) . ',' . $this->recurse($expr2) . ',true)';
77
	}
78
79
	/**
80
	* Convert a call to translate() where the second and third arguments are literal strings
81
	*
82
	* @param  string $expr
83
	* @param  string $from
84
	* @param  string $to
85
	* @return string
86
	*/
87 2
	public function parseTranslate($expr, $from, $to)
88
	{
89 2
		$from = $this->splitStringChars($from);
90 2
		$to   = $this->splitStringChars($to);
91
92
		// Add missing elements to $to then remove duplicates from $from and keep matching elements
93 2
		$to   = array_pad($to, count($from), '');
94 2
		$from = array_unique($from);
95 2
		$to   = array_intersect_key($to, $from);
96
97
		// Build the arguments list for the strtr() call
98 2
		$args = [$this->recurse($expr)];
99 2
		if ($this->isAsciiChars($from) && $this->isAsciiChars($to))
100
		{
101 1
			$args[] = $this->serializeAsciiChars($from);
102 1
			$args[] = $this->serializeAsciiChars($to);
103
		}
104
		else
105
		{
106 1
			$args[] = $this->serializeMap($from, $to);
107
		}
108
109 2
		return 'strtr(' . implode(',', $args) . ')';
110
	}
111
112
	/**
113
	* Test whether given list of strings contains only single ASCII characters
114
	*
115
	* @param  string[] $chars
116
	* @return bool
117
	*/
118 2
	protected function isAsciiChars(array $chars)
119
	{
120 2
		return ([1] === array_unique(array_map('strlen', $chars)));
121
	}
122
123
	/**
124
	* Serialize a list of ASCII chars into a single PHP string
125
	*
126
	* @param  string[] $chars
127
	* @return string
128
	*/
129 1
	protected function serializeAsciiChars(array $chars)
130
	{
131 1
		return var_export(implode('', $chars), true);
132
	}
133
134
	/**
135
	* Serialize the lists of characters to replace with strtr()
136
	*
137
	* @param  string[] $from
138
	* @param  string[] $to
139
	* @return string
140
	*/
141 1
	protected function serializeMap(array $from, array $to)
142
	{
143 1
		$elements = [];
144 1
		foreach ($from as $k => $str)
145
		{
146 1
			$elements[] = var_export($str, true) . '=>' . var_export($to[$k], true);
147
		}
148
149 1
		return '[' . implode(',', $elements) . ']';
150
	}
151
152
	/**
153
	* Split individual characters from given literal string
154
	*
155
	* @param  string   $string Original string, including quotes
156
	* @return string[]
157
	*/
158 2
	protected function splitStringChars($string)
159
	{
160 2
		preg_match_all('(.)su', substr($string, 1, -1), $matches);
161
162 2
		return $matches[0];
163
	}
164
}