injectableFactory = $injectableFactory; $this->metadata = $metadata; } /** * @param array $argv * * @return int<0, 255> Exit-status. */ public function run(array $argv): int { $command = $this->getCommandNameFromArgv($argv); $params = $this->createParamsFromArgv($argv); if ( $command === null && ( $params->hasFlag(self::DEFAULT_COMMAND_FLAG) || count($params->getFlagList()) === 0 && count($params->getOptions()) === 0 && count($params->getArgumentList()) === 0 ) ) { $command = self::DEFAULT_COMMAND; } if ($command === null) { throw new CommandNotSpecified("Command name is not specified."); } $io = new IO(); $commandObj = $this->createCommand($command); if (!$commandObj instanceof Command) { // for backward compatibility assert(method_exists($commandObj, 'run')); $commandObj->run($params->getOptions(), $params->getFlagList(), $params->getArgumentList()); return 0; } $commandObj->run($params, $io); return $io->getExitStatus(); } /** * @param array $argv */ private function getCommandNameFromArgv(array $argv): ?string { $command = isset($argv[1]) ? trim($argv[1]) : null; if ($command === null && count($argv) < 2) { return null; } if (!$command || !ctype_alpha($command[0])) { return null; } return ucfirst(Util::hyphenToCamelCase($command)); } private function createCommand(string $command): object { $className = $this->getClassName($command); return $this->injectableFactory->create($className); } /** * @return class-string */ private function getClassName(string $command): string { /** @var ?class-string $className */ $className = $this->metadata->get(['app', 'consoleCommands', lcfirst($command), 'className']); if ($className) { return $className; } $className = 'Espo\\Core\\Console\\Commands\\' . $command; if (!class_exists($className)) { throw new CommandNotFound("Command '" . Util::camelCaseToHyphen($command) ."' does not exist."); } /** @var class-string */ return $className; } /** * @param array $argv */ private function createParamsFromArgv(array $argv): Params { return Params::fromArgs(array_slice($argv, 1)); } }