Completed
Push — master ( c23e1b...1bf822 )
by Sam
03:07
created

Parser::parse()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
c 7
b 0
f 1
dl 0
loc 27
rs 8.5806
cc 4
eloc 13
nc 4
nop 0
1
<?php
2
3
namespace Jalle19\HaPHProxy;
4
5
use Jalle19\HaPHProxy\Exception\FileNotFoundException;
6
use Jalle19\HaPHProxy\Parameter\Parameter;
7
use Jalle19\HaPHProxy\Section\AbstractSection;
8
use Jalle19\HaPHProxy\Section\Factory;
9
10
/**
11
 * Class Parser
12
 * @package Jalle19\HaPHProxy
13
 * @author  Sam Stenvall <[email protected]>
14
 * @license GNU General Public License 2.0+
15
 */
16
class Parser
17
{
18
19
	const MAGIC_COMMENT_PREFIX = '# HAPHPROXY_COMMENT';
20
21
	/**
22
	 * @var string
23
	 */
24
	private $filePath;
25
26
27
	/**
28
	 * Parser constructor.
29
	 *
30
	 * @param string $filePath
31
	 *
32
	 * @throws FileNotFoundException if the specified file could not be found or is not readable
33
	 */
34
	public function __construct($filePath)
35
	{
36
		if (!file_exists($filePath) || !is_readable($filePath)) {
37
			throw new FileNotFoundException($filePath . ' not found or is not readable');
38
		}
39
40
		$this->filePath = $filePath;
41
	}
42
43
44
	/**
45
	 * @return Configuration
46
	 */
47
	public function parse()
48
	{
49
		$configuration  = new Configuration();
50
		$currentSection = null;
51
52
		// Parse the preface
53
		$configuration->setPreface($this->parsePreface());
54
55
		foreach ($this->getNormalizedConfigurationLines() as $line) {
56
			// Check for section changes
57
			$newSection = Factory::makeFactory($line);
58
59
			if ($newSection !== null) {
60
				$currentSection = $newSection;
61
				$configuration->addSection($currentSection);
62
63
				continue;
64
			}
65
66
			// Parse the current section line by line
67
			if ($currentSection !== null) {
68
				$this->parseSectionLine($currentSection, $line);
69
			}
70
		}
71
72
		return $configuration;
73
	}
74
75
76
	/**
77
	 * Reads the configuration and yields one line at a time
78
	 *
79
	 * @return \Generator
80
	 */
81
	private function getConfigurationLines()
82
	{
83
		$handle = fopen($this->filePath, "r");
84
85
		while (($line = fgets($handle)) !== false) {
86
			yield $line;
87
		}
88
	}
89
90
91
	/**
92
	 * @return \Generator
93
	 */
94
	private function getNormalizedConfigurationLines()
95
	{
96
		foreach ($this->getConfigurationLines() as $line) {
97
			$line = $this->normalizeLine($line);
98
99
			if (!empty($line)) {
100
				yield $line;
101
			}
102
		}
103
	}
104
105
106
	/**
107
	 * @param string $line
108
	 *
109
	 * @return string
110
	 */
111
	private function normalizeLine($line)
112
	{
113
		return preg_replace('/\s+/', ' ', trim($line));
114
	}
115
116
117
	/**
118
	 * @param string $line
119
	 *
120
	 * @return bool if the line is a comment
121
	 */
122
	private function isComment($line)
123
	{
124
		return substr($line, 0, 1) === '#';
125
	}
126
127
128
	/**
129
	 * @param string $line
130
	 *
131
	 * @return bool whether the line is a magic comment
132
	 */
133
	private function isMagicComment($line)
134
	{
135
		return substr($line, 0, strlen(self::MAGIC_COMMENT_PREFIX)) === self::MAGIC_COMMENT_PREFIX;
136
	}
137
138
139
	/**
140
	 * @return string
141
	 */
142
	private function parsePreface()
143
	{
144
		$preface = '';
145
146
		foreach ($this->getNormalizedConfigurationLines() as $line) {
147
			if ($this->isComment($line)) {
148
				$preface .= $line . PHP_EOL;
149
			} else {
150
				break;
151
			}
152
		}
153
154
		return $preface;
155
	}
156
157
158
	/**
159
	 * @param AbstractSection $section
160
	 * @param string          $line
161
	 */
162
	private function parseSectionLine($section, $line)
163
	{
164
		// Distinguish between parameters and magic comments
165
		if ($this->isMagicComment($line)) {
166
			$section->addMagicComment($this->parseMagicComment($line));
167
		} else if (!$this->isComment($line)) {
168
			$section->addParameter($this->parseParameter($line));
169
		}
170
	}
171
172
173
	/**
174
	 * @param string $line
175
	 *
176
	 * @return string
177
	 */
178
	private function parseMagicComment($line)
179
	{
180
		return trim(substr($line, strlen(self::MAGIC_COMMENT_PREFIX)));
181
	}
182
183
184
	/**
185
	 * @param string $line
186
	 *
187
	 * @return Parameter
188
	 */
189
	private function parseParameter($line)
190
	{
191
		$words = explode(' ', $line, 2);
192
193
		if (count($words) > 1) {
194
			list($name, $value) = $words;
195
196
			return new Parameter($name, $value);
197
		}
198
199
		list($name) = $words;
200
201
		return new Parameter($name);
202
	}
203
204
}
205