Builder::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 11
c 2
b 0
f 0
dl 0
loc 15
ccs 6
cts 6
cp 1
rs 9.9
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
/**
4
* @package   s9e\RegexpBuilder
5
* @copyright Copyright (c) 2016-2022 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 17
	public function __construct(array $config = [])
46
	{
47
		$config += [
48 17
			'delimiter'     => '/',
49
			'input'         => 'Bytes',
50
			'inputOptions'  => [],
51
			'meta'          => [],
52
			'output'        => 'Bytes',
53
			'outputOptions' => []
54
		];
55
56 17
		$this->setInput($config['input'], $config['inputOptions']);
57 17
		$this->setMeta($config['meta']);
58 17
		$this->setSerializer($config['output'], $config['outputOptions'], $config['delimiter']);
59 17
		$this->setRunner();
60 17
	}
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 17
	public function build(array $strings): string
69
	{
70 17
		$strings = array_unique($strings);
71 17
		sort($strings);
72 17
		if ($this->isEmpty($strings))
73
		{
74 1
			return '';
75
		}
76
77 16
		$strings = $this->splitStrings($strings);
78 16
		$strings = $this->meta->replaceMeta($strings);
79 16
		$strings = $this->runner->run($strings);
80
81 16
		return $this->serializer->serializeStrings($strings);
82
	}
83
84
	/**
85
	* Test whether the list of strings is empty
86
	*
87
	* @param  string[] $strings
88
	* @return bool
89
	*/
90 17
	protected function isEmpty(array $strings): bool
91
	{
92 17
		return (empty($strings) || $strings === ['']);
93
	}
94
95
	/**
96
	* Set the InputInterface instance in $this->input
97
	*
98
	* @param  string $inputType
99
	* @param  array  $inputOptions
100
	* @return void
101
	*/
102 17
	protected function setInput(string $inputType, array $inputOptions): void
103
	{
104 17
		$className   = __NAMESPACE__ . '\\Input\\' . $inputType;
105 17
		$this->input = new $className($inputOptions);
106 17
	}
107
108
	/**
109
	* Set the MetaCharacters instance in $this->meta
110
	*
111
	* @param  array $map
112
	* @return void
113
	*/
114 17
	protected function setMeta(array $map): void
115
	{
116 17
		$this->meta = new MetaCharacters($this->input);
117 17
		foreach ($map as $char => $expr)
118
		{
119 5
			$this->meta->add($char, $expr);
120
		}
121 17
	}
122
123
	/**
124
	* Set the Runner instance $in this->runner
125
	*
126
	* @return void
127
	*/
128 17
	protected function setRunner(): void
129
	{
130 17
		$this->runner = new Runner;
131 17
		$this->runner->addPass(new MergePrefix);
132 17
		$this->runner->addPass(new GroupSingleCharacters);
133 17
		$this->runner->addPass(new Recurse($this->runner));
134 17
		$this->runner->addPass(new PromoteSingleStrings);
135 17
		$this->runner->addPass(new CoalesceOptionalStrings);
136 17
		$this->runner->addPass(new MergeSuffix);
137 17
		$this->runner->addPass(new CoalesceSingleCharacterPrefix);
138 17
	}
139
140
	/**
141
	* Set the Serializer instance in $this->serializer
142
	*
143
	* @param  string $outputType
144
	* @param  array  $outputOptions
145
	* @param  string $delimiter
146
	* @return void
147
	*/
148 17
	protected function setSerializer(string $outputType, array $outputOptions, string $delimiter): void
149
	{
150 17
		$className = __NAMESPACE__ . '\\Output\\' . $outputType;
151 17
		$output    = new $className($outputOptions);
152 17
		$escaper   = new Escaper($delimiter);
153
154 17
		$this->serializer = new Serializer($output, $this->meta, $escaper);
155 17
	}
156
157
	/**
158
	* Split all given strings by character
159
	*
160
	* @param  string[] $strings List of strings
161
	* @return array[]           List of arrays
162
	*/
163 16
	protected function splitStrings(array $strings): array
164
	{
165 16
		return array_map([$this->input, 'split'], $strings);
166
	}
167
}