Completed
Branch XPathConvertorRefactor (13c9f8)
by Josh
08:27
created

SingleByteStringManipulation   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 15
c 0
b 0
f 0
lcom 1
cbo 1
dl 0
loc 169
rs 10

11 Methods

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