Skip to content

Commit 3914978

Browse files
committed
1 parent 7a5a771 commit 3914978

1 file changed

Lines changed: 145 additions & 0 deletions

File tree

server/GetOptionsx.php

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
class GetOptions {
4+
5+
private array $config = [];
6+
7+
public function __construct(
8+
string $projectRootName,
9+
string $iniName,
10+
array $expected = ['-i', '-logfile', '-address', '-console'],
11+
array $boolFlags = ['-console'],
12+
?string $startDir = null,
13+
?array $argv = null
14+
) {
15+
if ($iniName === '') {
16+
throw new InvalidArgumentException('iniName must not be empty');
17+
}
18+
19+
if (!in_array('-i', $expected, true)) {
20+
$expected[] = '-i';
21+
}
22+
23+
$startDir = $startDir ?? $this->detectStartDir();
24+
$projectRoot = $this->findProjectRoot($projectRootName, $startDir);
25+
$configDir = $projectRoot . '/config';
26+
27+
$argv = $argv ?? ($_SERVER['argv'] ?? []);
28+
$cliOptions = $this->parseArgv($argv, $expected, $boolFlags);
29+
30+
$iniArg = $cliOptions['i'] ?? $iniName;
31+
$iniFile = $this->resolveIniPath($iniArg, $configDir);
32+
33+
if (!file_exists($iniFile)) {
34+
throw new RuntimeException("Config file not found: $iniFile");
35+
}
36+
37+
$ini = parse_ini_file($iniFile, false, INI_SCANNER_TYPED);
38+
if ($ini === false) {
39+
throw new RuntimeException("Failed to parse ini file: $iniFile");
40+
}
41+
42+
$this->config = array_replace($ini, $cliOptions);
43+
$this->config['_projectRoot'] = $projectRoot;
44+
$this->config['_configDir'] = $configDir;
45+
$this->config['_iniFile'] = $iniFile;
46+
}
47+
48+
public function getConfig(): array {
49+
return $this->config;
50+
}
51+
52+
public function get(string $key, mixed $default = null): mixed {
53+
return $this->config[$key] ?? $default;
54+
}
55+
56+
private function detectStartDir(): string {
57+
if (!empty($_SERVER['SCRIPT_FILENAME'])) {
58+
return dirname(realpath($_SERVER['SCRIPT_FILENAME']) ?: $_SERVER['SCRIPT_FILENAME']);
59+
}
60+
if (!empty($_SERVER['argv'][0])) {
61+
$script = $_SERVER['argv'][0];
62+
return dirname(realpath($script) ?: $script);
63+
}
64+
return getcwd() ?: __DIR__;
65+
}
66+
67+
private function findProjectRoot(string $name, string $startDir): string {
68+
$dir = $startDir;
69+
70+
for ($i = 0; $i < 20; $i++) {
71+
if (basename($dir) === $name) {
72+
return $dir;
73+
}
74+
$parent = dirname($dir);
75+
if ($parent === $dir) {
76+
break;
77+
}
78+
$dir = $parent;
79+
}
80+
81+
throw new RuntimeException(
82+
"Project root '$name' not found above: $startDir"
83+
);
84+
}
85+
86+
/**
87+
* - absoluter Pfad -> unverändert
88+
* - reiner Dateiname -> $configDir/<name>
89+
* - relativer Pfad mit Slash -> $configDir/<path>
90+
*/
91+
private function resolveIniPath(string $path, string $configDir): string {
92+
if ($this->isAbsolutePath($path)) {
93+
return $path;
94+
}
95+
return $configDir . '/' . ltrim($path, '/\\');
96+
}
97+
98+
private function isAbsolutePath(string $path): bool {
99+
if ($path === '') {
100+
return false;
101+
}
102+
if ($path[0] === '/' || $path[0] === '\\') {
103+
return true;
104+
}
105+
if (strlen($path) >= 3 && ctype_alpha($path[0]) && $path[1] === ':') {
106+
return true;
107+
}
108+
return false;
109+
}
110+
111+
private function parseArgv(array $argv, array $expect, array $boolFlags): array {
112+
$out = [];
113+
$argc = count($argv);
114+
115+
for ($i = 1; $i < $argc; $i++) {
116+
$arg = $argv[$i];
117+
118+
if (!in_array($arg, $expect, true)) {
119+
fwrite(STDERR, "Unknown option ignored: $arg\n");
120+
continue;
121+
}
122+
123+
$key = ltrim($arg, '-');
124+
125+
if (in_array($arg, $boolFlags, true)) {
126+
$out[$key] = true;
127+
continue;
128+
}
129+
130+
if ($i + 1 >= $argc) {
131+
throw new RuntimeException("Missing value for option: $arg");
132+
}
133+
134+
$next = $argv[$i + 1];
135+
if ($next === '' || str_starts_with($next, '-')) {
136+
throw new RuntimeException("Missing value for option: $arg");
137+
}
138+
139+
$i++;
140+
$out[$key] = $next;
141+
}
142+
143+
return $out;
144+
}
145+
}

0 commit comments

Comments
 (0)