Completed
Branch CoalesceOptionalStrings (db448d)
by Josh
02:42
created

Builder::setRunner()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
* @package   s9e\RegexpBuilder
5
* @copyright Copyright (c) 2016 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 Runner
29
	*/
30
	protected $runner;
31
32
	/**
33
	* @var Serializer
34
	*/
35
	protected $serializer;
36
37
	/**
38
	* @param array $config
39
	*/
40 9
	public function __construct(array $config = [])
41
	{
42
		$config += [
43 9
			'delimiter' => '/',
44
			'input'     => 'Bytes',
45
			'output'    => 'Bytes'
46
		];
47
48 9
		$this->setInput($config['input']);
49 9
		$this->setSerializer($config['output'], $config['delimiter']);
50 9
		$this->setRunner();
51 9
	}
52
53
	/**
54
	* Build and return a regular expression that matches all of the given strings
55
	*
56
	* @param  string[] $strings Literal strings to be matched
57
	* @return string            Regular expression (without delimiters)
58
	*/
59 9
	public function build(array $strings)
60
	{
61 9
		$strings = array_unique($strings);
62 9
		if ($this->isEmpty($strings))
63
		{
64 1
			return '';
65
		}
66
67 8
		$strings = $this->splitStrings($strings);
68 8
		usort($strings, __CLASS__ . '::compareStrings');
69 8
		$strings = $this->runner->run($strings);
70
71 8
		return $this->serializer->serializeStrings($strings);
72
	}
73
74
	/**
75
	* Compare two split strings
76
	*
77
	* Will sort strings in ascending order
78
	*
79
	* @param  integer[] $a
80
	* @param  integer[] $b
81
	* @return integer
82
	*/
83 8
	protected function compareStrings(array $a, array $b)
84
	{
85 8
		$i   = -1;
86 8
		$cnt = min(count($a), count($b));
87 8
		while (++$i < $cnt)
88
		{
89 8
			if ($a[$i] !== $b[$i])
90
			{
91 8
				return $a[$i] - $b[$i];
92
			}
93
		}
94
95
		return count($a) - count($b);
96
	}
97
98
	/**
99
	* Test whether the list of strings is empty
100
	*
101
	* @param  string[] $strings
102
	* @return bool
103
	*/
104 9
	protected function isEmpty(array $strings)
105
	{
106 9
		return (empty($strings) || $strings === ['']);
107
	}
108
109
	/**
110
	* Set the InputInterface instance in $this->input
111
	*
112
	* @param  string $inputType
113
	* @return void
114
	*/
115 9
	protected function setInput($inputType)
116
	{
117 9
		$className   = __NAMESPACE__ . '\\Input\\' . $inputType;
118 9
		$this->input = new $className;
119 9
	}
120
121
	/**
122
	* Set the Runner instance $in this->runner
123
	*
124
	* @return void
125
	*/
126 9
	protected function setRunner()
127
	{
128 9
		$this->runner = new Runner;
129 9
		$this->runner->addPass(new MergePrefix);
130 9
		$this->runner->addPass(new GroupSingleCharacters);
131 9
		$this->runner->addPass(new Recurse($this->runner));
132 9
		$this->runner->addPass(new PromoteSingleStrings);
133 9
		$this->runner->addPass(new CoalesceOptionalStrings);
134 9
		$this->runner->addPass(new MergeSuffix);
135 9
		$this->runner->addPass(new CoalesceSingleCharacterPrefix);
136 9
	}
137
138
	/**
139
	* Set the Serializer instance in $this->serializer
140
	*
141
	* @param  string $outputType
142
	* @param  string $delimiter
143
	* @return void
144
	*/
145 9
	protected function setSerializer($outputType, $delimiter)
146
	{
147 9
		$className = __NAMESPACE__ . '\\Output\\' . $outputType;
148 9
		$output    = new $className;
149 9
		$escaper   = new Escaper($delimiter);
150
151 9
		$this->serializer = new Serializer($output, $escaper);
152 9
	}
153
154
	/**
155
	* Split all given strings by character
156
	*
157
	* @param  string[] $strings List of strings
158
	* @return array[]           List of arrays
159
	*/
160 8
	protected function splitStrings(array $strings)
161
	{
162 8
		return array_map([$this->input, 'split'], $strings);
163
	}
164
}