111 lines
3.8 KiB
PHP
111 lines
3.8 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Copyright 2018 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
namespace app\util;
|
|
|
|
use GetOpt\ArgumentException;
|
|
use GetOpt\GetOpt;
|
|
use InvalidArgumentException;
|
|
|
|
/**
|
|
* Wraps `GetOpt` and normalizes arguments parsed by it.
|
|
*
|
|
* @see GetOpt
|
|
*/
|
|
class ArgumentParser
|
|
{
|
|
/**
|
|
* Parses any arguments specified via the command line. For those in the provided argument
|
|
* names that are not passed, provides null values instead.
|
|
*
|
|
* @param array $argumentNames the associative array of argument names to their types
|
|
* @return array the argument names to their values
|
|
*/
|
|
public function parseCommandArguments(array $argumentNames)
|
|
{
|
|
$getOpt = new GetOpt();
|
|
$normalizedOptions = [];
|
|
$numRequiredArguments = 0;
|
|
$getOpt->addOption(['h', 'help', GetOpt::NO_ARGUMENT, 'Show this help and quit']);
|
|
foreach ($argumentNames as $argumentName => $argumentType) {
|
|
$normalizedOptions[$argumentName] = null;
|
|
// Adds an option for an argument using a long option name only.
|
|
$getOpt->addOption(
|
|
[
|
|
null,
|
|
$argumentName,
|
|
$argumentType,
|
|
ArgumentNames::$ARGUMENTS_TO_DESCRIPTIONS[$argumentName]
|
|
]
|
|
);
|
|
|
|
if ($argumentType === GetOpt::REQUIRED_ARGUMENT) {
|
|
$numRequiredArguments++;
|
|
}
|
|
}
|
|
|
|
// Parse arguments and catch exceptions.
|
|
try {
|
|
$getOpt->process();
|
|
} catch (ArgumentException $exception) {
|
|
// When there are any errors regarding arguments, such as invalid argument names, or
|
|
// specifying required arguments but not providing values, 'ArgumentException' will
|
|
// be thrown. Show the help text in these cases.
|
|
echo PHP_EOL . $getOpt->getHelpText();
|
|
throw $exception;
|
|
}
|
|
// Show help text when requested.
|
|
if (!is_null($getOpt->getOption('help'))) {
|
|
$this->printHelpMessageAndExit($getOpt);
|
|
// Help text is printed, so no arguments are passed. The below line is reached only
|
|
// in tests.
|
|
return [];
|
|
}
|
|
|
|
$numPassedRequiredArguments = 0;
|
|
foreach ($getOpt->getOptions() as $optionName => $optionValue) {
|
|
if ($argumentNames[$optionName] === GetOpt::REQUIRED_ARGUMENT) {
|
|
$numPassedRequiredArguments++;
|
|
}
|
|
$normalizedOptions[$optionName] = $optionValue;
|
|
}
|
|
// Don't allow the case when optional arguments are passed, but required arguments are not.
|
|
if (
|
|
count($getOpt->getOptions()) > 0
|
|
&& $numPassedRequiredArguments !== $numRequiredArguments
|
|
) {
|
|
echo PHP_EOL . $getOpt->getHelpText();
|
|
throw new InvalidArgumentException(
|
|
'All required arguments must be specified.' . PHP_EOL
|
|
);
|
|
}
|
|
return $normalizedOptions;
|
|
}
|
|
|
|
/**
|
|
* Print the help message and exit the program.
|
|
*
|
|
* @param GetOpt $getOpt the GetOpt object to print its help text
|
|
*/
|
|
public function printHelpMessageAndExit(GetOpt $getOpt)
|
|
{
|
|
echo PHP_EOL . $getOpt->getHelpText();
|
|
exit;
|
|
}
|
|
}
|