/** * Validates arguments against the schema. * * @param Args $args The arguments that were returned from {@link Cli::parseRaw()}. * @return Args|null */ public function validate(Args $args) { $isValid = true; $command = $args->getCommand(); $valid = new Args($command); $schema = $this->getSchema($command); ksort($schema); $meta = $schema[Cli::META]; unset($schema[Cli::META]); $opts = $args->getOpts(); $missing = []; // Check to see if the command is correct. if ($command && !$this->hasCommand($command) && $this->hasCommand()) { echo $this->red("Invalid command: {$command}." . PHP_EOL); $isValid = false; } // Add the args. $valid->setArgs($args->getArgs()); foreach ($schema as $key => $definition) { // No Parameter (default) $required = Cli::val('required', $definition, false); $type = Cli::val('type', $definition, 'string'); $value = null; if (isset($opts[$key])) { // Check for --key. $value = $opts[$key]; if ($this->validateType($value, $type)) { $valid->setOpt($key, $value); } else { echo $this->red("The value of --{$key} is not a valid {$type}." . PHP_EOL); $isValid = false; } unset($opts[$key]); } elseif (isset($definition['short']) && isset($opts[$definition['short']])) { // Check for -s. $value = $opts[$definition['short']]; if ($this->validateType($value, $type)) { $valid->setOpt($key, $value); } else { echo $this->red("The value of --{$key} (-{$definition['short']}) is not a valid {$type}." . PHP_EOL); $isValid = false; } unset($opts[$definition['short']]); } elseif (isset($opts['no-' . $key])) { // Check for --no-key. $value = $opts['no-' . $key]; if ($type !== 'boolean') { echo $this->red("Cannont apply the --no- prefix on the non boolean --{$key}." . PHP_EOL); $isValid = false; } elseif ($this->validateType($value, $type)) { $valid->setOpt($key, !$value); } else { echo $this->red("The value of --no-{$key} is not a valid {$type}." . PHP_EOL); $isValid = false; } unset($opts['no-' . $key]); } elseif ($definition['required']) { // The key was not supplied. Is it required? $missing[$key] = true; } elseif ($type === 'boolean') { // The value os not required, but can maybe be coerced into a type. $valid->setOpt($key, false); } } if (count($missing)) { $isValid = false; foreach ($missing as $key => $v) { echo $this->red("Missing required option: {$key}" . PHP_EOL); } } if (count($opts)) { $isValid = false; foreach ($opts as $key => $v) { echo $this->red("Invalid option: {$key}" . PHP_EOL); } } if ($isValid) { return $valid; } else { echo PHP_EOL; return null; } }