Completed
Branch MetaCharacters (da2f1d)
by Josh
01:29
created

Builder::setInput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
/**
4
* @package   s9e\RegexpBuilder
5
* @copyright Copyright (c) 2016-2018 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\RegexpBuilder;
9
10
use s9e\RegexpBuilder\Input\InputInterface;
11
use s9e\RegexpBuilder\Output\OutputInterface;
12
use s9e\RegexpBuilder\Passes\CoalesceOptionalStrings;
13
use s9e\RegexpBuilder\Passes\CoalesceSingleCharacterPrefix;
14
use s9e\RegexpBuilder\Passes\GroupSingleCharacters;
15
use s9e\RegexpBuilder\Passes\MergePrefix;
16
use s9e\RegexpBuilder\Passes\MergeSuffix;
17
use s9e\RegexpBuilder\Passes\PromoteSingleStrings;
18
use s9e\RegexpBuilder\Passes\Recurse;
19
20
class Builder
21
{
22
	/**
23
	* @var InputInterface
24
	*/
25
	protected $input;
26
27
	/**
28
	* @var MetaCharacters
29
	*/
30
	protected $meta;
31
32
	/**
33
	* @var Runner
34
	*/
35
	protected $runner;
36
37
	/**
38
	* @var Serializer
39
	*/
40
	protected $serializer;
41
42
	/**
43
	* @param array $config
44
	*/
45 13
	public function __construct(array $config = [])
46
	{
47
		$config += [
48 13
			'delimiter'     => '/',
49
			'input'         => 'Bytes',
50
			'inputOptions'  => [],
51
			'meta'          => [],
52
			'output'        => 'Bytes',
53
			'outputOptions' => []
54
		];
55
56 13
		$this->setInput($config['input'], $config['inputOptions']);
57 13
		$this->setMeta($config['meta']);
58 13
		$this->setSerializer($config['output'], $config['outputOptions'], $config['delimiter']);
59 13
		$this->setRunner();
60 13
	}
61
62
	/**
63
	* Build and return a regular expression that matches all of the given strings
64
	*
65
	* @param  string[] $strings Literal strings to be matched
66
	* @return string            Regular expression (without delimiters)
67
	*/
68 13
	public function build(array $strings)
69
	{
70 13
		$strings = array_unique($strings);
71 13
		if ($this->isEmpty($strings))
72
		{
73 1
			return '';
74
		}
75
76 12
		$strings = $this->splitStrings($strings);
77 12
		usort($strings, __CLASS__ . '::compareStrings');
78 12
		$strings = $this->meta->replaceMeta($strings);
79 12
		$strings = $this->runner->run($strings);
80
81 12
		return $this->serializer->serializeStrings($strings);
82
	}
83
84
	/**
85
	* Compare two split strings
86
	*
87
	* Will sort strings in ascending order
88
	*
89
	* @param  integer[] $a
90
	* @param  integer[] $b
91
	* @return integer
92
	*/
93 11
	protected function compareStrings(array $a, array $b)
94
	{
95 11
		$i   = -1;
96 11
		$cnt = min(count($a), count($b));
97 11
		while (++$i < $cnt)
98
		{
99 11
			if ($a[$i] !== $b[$i])
100
			{
101 10
				return $a[$i] - $b[$i];
102
			}
103
		}
104
105 2
		return count($a) - count($b);
106
	}
107
108
	/**
109
	* Test whether the list of strings is empty
110
	*
111
	* @param  string[] $strings
112
	* @return bool
113
	*/
114 13
	protected function isEmpty(array $strings)
115
	{
116 13
		return (empty($strings) || $strings === ['']);
117
	}
118
119
	/**
120
	* Set the InputInterface instance in $this->input
121
	*
122
	* @param  string $inputType
123
	* @param  array  $inputOptions
124
	* @return void
125
	*/
126 13
	protected function setInput($inputType, array $inputOptions)
127
	{
128 13
		$className   = __NAMESPACE__ . '\\Input\\' . $inputType;
129 13
		$this->input = new $className($inputOptions);
130 13
	}
131
132
	/**
133
	* Set the MetaCharacters instance in $this->meta
134
	*
135
	* @param  array $map
136
	* @return void
137
	*/
138 13
	protected function setMeta(array $map)
139
	{
140 13
		$this->meta = new MetaCharacters($this->input);
141 13
		foreach ($map as $char => $expr)
142
		{
143 3
			$this->meta->add($char, $expr);
144
		}
145 13
	}
146
147
	/**
148
	* Set the Runner instance $in this->runner
149
	*
150
	* @return void
151
	*/
152 13
	protected function setRunner()
153
	{
154 13
		$this->runner = new Runner;
155 13
		$this->runner->addPass(new MergePrefix);
156 13
		$this->runner->addPass(new GroupSingleCharacters);
157 13
		$this->runner->addPass(new Recurse($this->runner));
158 13
		$this->runner->addPass(new PromoteSingleStrings);
159 13
		$this->runner->addPass(new CoalesceOptionalStrings);
160 13
		$this->runner->addPass(new MergeSuffix);
161 13
		$this->runner->addPass(new CoalesceSingleCharacterPrefix);
162 13
	}
163
164
	/**
165
	* Set the Serializer instance in $this->serializer
166
	*
167
	* @param  string $outputType
168
	* @param  array  $outputOptions
169
	* @param  string $delimiter
170
	* @return void
171
	*/
172 13
	protected function setSerializer($outputType, array $outputOptions, $delimiter)
173
	{
174 13
		$className = __NAMESPACE__ . '\\Output\\' . $outputType;
175 13
		$output    = new $className($outputOptions);
176 13
		$escaper   = new Escaper($delimiter);
177
178 13
		$this->serializer = new Serializer($output, $this->meta, $escaper);
179 13
	}
180
181
	/**
182
	* Split all given strings by character
183
	*
184
	* @param  string[] $strings List of strings
185
	* @return array[]           List of arrays
186
	*/
187 12
	protected function splitStrings(array $strings)
188
	{
189 12
		return array_map([$this->input, 'split'], $strings);
190
	}
191
}