1
0
mirror of https://github.com/php/phd.git synced 2026-03-24 07:02:07 +01:00
Files
archived-phd/phpdotnet/phd/Options/Parser.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;
}
}