Completed
Branch XPathConvertorRefactor (245ee2)
by Josh
12:06
created

SingleByteStringManipulation   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 1
dl 0
loc 136
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getRegexpGroups() 0 8 1
A getRegexps() 0 8 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
			'SubstringAfter'  => 'String',
19
			'SubstringBefore' => 'String',
20
			'Translate'       => 'String'
21
		];
22
	}
23
24
	/**
25
	* {@inheritdoc}
26
	*/
27
	public function getRegexps()
28
	{
29
		return [
30
			'SubstringAfter'  => 'substring-after \\( ((?&String)) , ((?&LiteralString)) \\)',
31
			'SubstringBefore' => 'substring-before \\( ((?&String)) , ((?&String)) \\)',
32
			'Translate'       => 'translate \\( ((?&String)) , ((?&LiteralString)) , ((?&LiteralString)) \\)'
33
		];
34
	}
35
36
	/**
37
	* Convert a call to substring-after() where the second argument is a literal string
38
	*
39
	* @param  string $expr
40
	* @param  string $str
41
	* @return string
42
	*/
43
	public function convertSubstringAfter($expr, $str)
44
	{
45
		return 'substr(strstr(' . $this->convert($expr) . ',' . $this->convert($str) . '),' . (strlen($str) - 2) . ')';
46
	}
47
48
	/**
49
	* Convert a call to substring-before()
50
	*
51
	* @param  string $expr1
52
	* @param  string $expr2
53
	* @return string
54
	*/
55
	public function convertSubstringBefore($expr1, $expr2)
56
	{
57
		return 'strstr(' . $this->convert($expr1) . ',' . $this->convert($expr2) . ',true)';
58
	}
59
60
	/**
61
	* Convert a call to translate() where the second and third arguments are literal strings
62
	*
63
	* @param  string $expr
64
	* @param  string $from
65
	* @param  string $to
66
	* @return string
67
	*/
68
	public function convertTranslate($expr, $from, $to)
69
	{
70
		$from = $this->splitStringChars($from);
71
		$to   = $this->splitStringChars($to);
72
73
		// Add missing elements to $to then remove duplicates from $from and keep matching elements
74
		$to   = array_pad($to, count($from), '');
75
		$from = array_unique($from);
76
		$to   = array_intersect_key($to, $from);
77
78
		// Build the arguments list for the strtr() call
79
		$args = [$this->convert($expr)];
80
		if ($this->isAsciiChars($from) && $this->isAsciiChars($to))
81
		{
82
			$args[] = $this->serializeAsciiChars($from);
83
			$args[] = $this->serializeAsciiChars($to);
84
		}
85
		else
86
		{
87
			$args[] = $this->serializeMap($from, $to);
88
		}
89
90
		return 'strtr(' . implode(',', $args) . ')';
91
	}
92
93
	/**
94
	* Test whether given list of strings contains only single ASCII characters
95
	*
96
	* @param  string[] $chars
97
	* @return bool
98
	*/
99
	protected function isAsciiChars(array $chars)
100
	{
101
		return ([1] === array_unique(array_map('strlen', $chars)));
102
	}
103
104
	/**
105
	* Serialize a list of ASCII chars into a single PHP string
106
	*
107
	* @param  string[] $chars
108
	* @return string
109
	*/
110
	protected function serializeAsciiChars(array $chars)
111
	{
112
		return var_export(implode('', $chars), true);
113
	}
114
115
	/**
116
	* Serialize the lists of characters to replace with strtr()
117
	*
118
	* @param  string[] $from
119
	* @param  string[] $to
120
	* @return string
121
	*/
122
	protected function serializeMap(array $from, array $to)
123
	{
124
		$elements = [];
125
		foreach ($from as $k => $str)
126
		{
127
			$elements[] = var_export($str, true) . '=>' . var_export($to[$k], true);
128
		}
129
130
		return '[' . implode(',', $elements) . ']';
131
	}
132
133
	/**
134
	* Split individual characters from given literal string
135
	*
136
	* @param  string   $string Original string, including quotes
137
	* @return string[]
138
	*/
139
	protected function splitStringChars($string)
140
	{
141
		preg_match_all('(.)su', substr($string, 1, -1), $matches);
142
143
		return $matches[0];
144
	}
145
}