webman_ad/app/util/ArgumentParser.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;
}
}