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
haszi e6e6847d7b Refactor Options Parser and default Options Handler (#110)
* Refactor Options Parser and default Options Handler

Refactor default Options Handler to accept dependencies through its constructor.
Refactor default Options Handler to return an array of options instead of directly setting options in Config and declare array return types.
Refactor method in Options Parser to return an array of options and declare its return type as array.
Inject all necessary dependencies in render.php.
Refactor two methods in default Options Handler by using match expressions.

* Minor refactor of files used in tests

Inlcude Config with require_once instead of require in Autloader.
Define __INSTALLDIR__ only if it is not defined yet in render.php.
Include Autoloader and functions.php with require_once instead of require.
Remove unnecessary __PHPDIR__ constant, correct path for __INSTALLDIR__ and use that constant in setup.php.

* Remove var_dump from Options Parser

* Fix inconsistent option flags in default Option Handler

* Add default Options Handler tests

---------

Co-authored-by: haszi <haszika80@gmail.com>
2024-03-17 18:29:43 +00:00

120 lines
3.8 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)) {
trigger_error('Invalid long option ' . $argv[$i], E_USER_ERROR);
}
} elseif (substr($checkArgv[0], 0, 1) === '-') {
if (!in_array(substr($checkArgv[0], 1), $short)) {
trigger_error('Invalid short option ' . $argv[$i], E_USER_ERROR);
}
}
}
}
/**
* @return array<string, mixed>
*/
public function getopt(): array {
$this->validateOptions();
$args = getopt($this->getShortOptions(), $this->getLongOptions());
if ($args === false) {
trigger_error("Something happend with getopt(), please report a bug", E_USER_ERROR);
}
$parsedOptions = [];
foreach ($args as $k => $v) {
$handler = $this->handlerForOption($k);
if (!is_callable($handler)) {
trigger_error("Hmh, something weird has happend, I don't know this option", E_USER_ERROR);
}
$retVal = call_user_func($handler, $k, $v);
if (is_array($retVal)) {
$parsedOptions = array_merge($parsedOptions, $retVal);
}
}
return $parsedOptions;
}
}