<?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; } }