Completed
Push — master ( 091f5a...339d53 )
by Josh
04:50
created

Builder::compareStrings()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 6
cts 7
cp 0.8571
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 2
crap 3.0261
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\CoalesceSingleCharacterPrefix;
13
use s9e\RegexpBuilder\Passes\GroupSingleCharacters;
14
use s9e\RegexpBuilder\Passes\MergePrefix;
15
use s9e\RegexpBuilder\Passes\MergeSuffix;
16
use s9e\RegexpBuilder\Passes\PromoteSingleStrings;
17
use s9e\RegexpBuilder\Passes\Recurse;
18
19
class Builder
20
{
21
	/**
22
	* @var InputInterface
23
	*/
24
	protected $input;
25
26
	/**
27
	* @var Runner
28
	*/
29
	protected $runner;
30
31
	/**
32
	* @var Serializer
33
	*/
34
	protected $serializer;
35
36
	/**
37
	* @param array $config
38
	*/
39 9
	public function __construct(array $config = [])
40
	{
41 9
		$config = $this->getConfig($config);
42
43 9
		$this->input      = $config['input'];
44 9
		$this->runner     = $config['runner'];
45 9
		$this->serializer = new Serializer($config['output'], $config['escaper']);
46 9
	}
47
48
	/**
49
	* Build and return a regular expression that matches all of the given strings
50
	*
51
	* @param  string[] $strings Literal strings to be matched
52
	* @return string            Regular expression (without delimiters)
53
	*/
54 9
	public function build(array $strings)
55
	{
56 9
		$strings = array_unique($strings);
57 9
		if ($strings === [''])
58
		{
59 1
			return '';
60
		}
61
62 8
		$strings = $this->splitStrings($strings);
63 8
		usort($strings, __CLASS__ . '::compareStrings');
64 8
		$strings = $this->runner->run($strings);
65
66 8
		return $this->serializer->serializeStrings($strings);
67
	}
68
69
	/**
70
	* Compare two split strings
71
	*
72
	* Will sort strings in ascending order
73
	*
74
	* @param  integer[] $a
75
	* @param  integer[] $b
76
	* @return integer
77
	*/
78 8
	protected function compareStrings(array $a, array $b)
79
	{
80 8
		$i   = -1;
81 8
		$cnt = min(count($a), count($b));
82 8
		while (++$i < $cnt)
83
		{
84 8
			if ($a[$i] !== $b[$i])
85
			{
86 8
				return $a[$i] - $b[$i];
87
			}
88
		}
89
90
		return count($a) - count($b);
91
	}
92
93
	/**
94
	* Build the full config array based on given input
95
	*
96
	* @param  array $config Sparse config
97
	* @return array         Full config
98
	*/
99 9
	protected function getConfig(array $config)
100
	{
101
		$config += [
102 9
			'delimiter' => '/',
103
			'input'     => 'Bytes',
104
			'output'    => 'Bytes'
105
		];
106 9
		$config['escaper'] = new Escaper($config['delimiter']);
107
108 9
		$className = __NAMESPACE__ . '\\Input\\' . $config['input'];
109 9
		$config['input'] = new $className;
110
111 9
		$className = __NAMESPACE__ . '\\Output\\' . $config['output'];
112 9
		$config['output'] = new $className;
113
114 9
		$config['runner'] = new Runner;
115 9
		$config['runner']->addPass(new MergePrefix);
116 9
		$config['runner']->addPass(new GroupSingleCharacters);
117 9
		$config['runner']->addPass(new Recurse($config['runner']));
118 9
		$config['runner']->addPass(new PromoteSingleStrings);
119 9
		$config['runner']->addPass(new MergeSuffix);
120 9
		$config['runner']->addPass(new CoalesceSingleCharacterPrefix);
121
122 9
		return $config;
123
	}
124
125
	/**
126
	* Split all given strings by character
127
	*
128
	* @param  string[] $strings List of strings
129
	* @return array[]           List of arrays
130
	*/
131 8
	protected function splitStrings(array $strings)
132
	{
133 8
		return array_map([$this->input, 'split'], $strings);
134
	}
135
}