Completed
Push — master ( 064b09...94638b )
by Josh
172:30 queued 164:28
created

Builder::compareStrings()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

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