mirror of
https://github.com/php/phd.git
synced 2026-03-24 07:02:07 +01:00
120 lines
3.7 KiB
PHP
120 lines
3.7 KiB
PHP
<?php
|
|
namespace phpdotnet\phd;
|
|
|
|
class Options_Parser
|
|
{
|
|
|
|
private Options_Interface $defaultHandler;
|
|
/** @var array<Options_Interface> */
|
|
private array $packageHandlers = [];
|
|
|
|
public function __construct(
|
|
Options_Interface $defaultHandler,
|
|
Options_Interface ...$packageHandlers
|
|
) {
|
|
$this->defaultHandler = $defaultHandler;
|
|
$this->packageHandlers = $packageHandlers;
|
|
}
|
|
|
|
/**
|
|
* @return array<Options_Interface, string>
|
|
*/
|
|
private function handlerForOption(string $option): array {
|
|
if (method_exists($this->defaultHandler, "option_{$option}")) {
|
|
return [$this->defaultHandler, "option_{$option}"];
|
|
}
|
|
|
|
$opt = explode('-', $option);
|
|
$package = strtolower($opt[0]);
|
|
|
|
if (isset($this->packageHandlers[$package])) {
|
|
if (method_exists($this->packageHandlers[$package], "option_{$opt[1]}")) {
|
|
return [$this->packageHandlers[$package], "option_{$opt[1]}"];
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* @return array<string>
|
|
*/
|
|
private function getLongOptions(): array {
|
|
$defaultOptions = array_keys($this->defaultHandler->optionList());
|
|
$packageOptions = [];
|
|
foreach ($this->packageHandlers as $package => $handler) {
|
|
foreach ($handler->optionList() as $opt) {
|
|
$packageOptions[] = $package . '-' . $opt;
|
|
}
|
|
}
|
|
return array_merge($defaultOptions, $packageOptions);
|
|
}
|
|
|
|
private function getShortOptions(): string {
|
|
$defaultOptions = array_values($this->defaultHandler->optionList());
|
|
$packageOptions = [];
|
|
foreach ($this->packageHandlers as $handler) {
|
|
foreach ($handler->optionList() as $opt) {
|
|
$packageOptions[] = $opt;
|
|
}
|
|
}
|
|
$options = array_merge($defaultOptions, $packageOptions);
|
|
return implode('', array_values($options));
|
|
}
|
|
|
|
/**
|
|
* Checks if all options passed are valid.
|
|
*
|
|
* Fix Bug #54217 - Warn about nonexisting parameters
|
|
*/
|
|
private function validateOptions(): void {
|
|
$argv = $_SERVER['argv'];
|
|
$argc = $_SERVER['argc'];
|
|
|
|
$short = str_split(str_replace(':', '', $this->getShortOptions()));
|
|
$long = [];
|
|
foreach ($this->getLongOptions() as $opt) {
|
|
$long[] = str_replace(':', '', $opt);
|
|
}
|
|
|
|
for ($i=1; $i < $argc; $i++) {
|
|
$checkArgv = explode('=', $argv[$i]);
|
|
if (substr($checkArgv[0], 0, 2) === '--') {
|
|
if (!in_array(substr($checkArgv[0], 2), $long)) {
|
|
throw new \Error('Invalid long option ' . $argv[$i]);
|
|
}
|
|
} elseif (substr($checkArgv[0], 0, 1) === '-') {
|
|
if (!in_array(substr($checkArgv[0], 1), $short)) {
|
|
throw new \Error('Invalid short option ' . $argv[$i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function getopt(): array {
|
|
$this->validateOptions();
|
|
|
|
$args = getopt($this->getShortOptions(), $this->getLongOptions());
|
|
if ($args === false) {
|
|
throw new \Error('Something happend with getopt(), please report a bug');
|
|
}
|
|
|
|
$parsedOptions = [];
|
|
foreach ($args as $k => $v) {
|
|
$handler = $this->handlerForOption($k);
|
|
|
|
if (!is_callable($handler)) {
|
|
throw new \Error("Hmh, something weird has happend, I don't know this option");
|
|
}
|
|
|
|
$retVal = call_user_func($handler, $k, $v);
|
|
if (is_array($retVal)) {
|
|
$parsedOptions = array_merge($parsedOptions, $retVal);
|
|
}
|
|
}
|
|
return $parsedOptions;
|
|
}
|
|
}
|