*/ protected static $commands = array(); /** * Current CLI command * @var string|null */ protected static $command = null; /** * Add CLI command * @param string $command The command name * @param callable $handler The command handler * @param string $short_desc Short command description * @param string|null $usage_args Argument usage short message * @param string|array|null $long_desc Long command description * @return bool */ public static function add_command($command, $handler, $short_desc, $usage_args=null, $long_desc=null, $override=false) { if (array_key_exists($command, self :: $commands) && !$override) { Log :: error(I18n::_("The CLI command '%s' already exists."), $command); return False; } if (!is_callable($handler)) { Log :: error(I18n::_("The CLI command '%s' handler is not callable !"), $command); return False; } self :: $commands[$command] = array ( 'handler' => $handler, 'short_desc' => $short_desc, 'usage_args' => $usage_args, 'long_desc' => $long_desc, ); return True; } /** * Show usage message * @param string|false $error Error message to show (optional) * @param array $extra_args Extra arguments to use to compute error message using sprintf * @return void */ public static function usage($error=false, ...$extra_args) { global $argv; // If extra arguments passed, format error message using sprintf if ($extra_args) { $error = call_user_func_array( 'sprintf', array_merge(array($error), $extra_args) ); } if ($error) echo "$error\n\n"; echo(I18n::_("Usage: %s [-h] [-qd] command\n", basename($argv[0]))); echo I18n::_(" -h Show this message\n"); echo I18n::_(" -q / -d Quiet/Debug mode\n"); echo I18n::_(" --trace Trace mode (the most verbose)\n"); echo I18n::_(" command Command to run\n"); echo "\n"; echo I18n::_("Available commands:\n"); foreach (self :: $commands as $command => $info) { if (self :: $command && $command != self :: $command) continue; echo ( " ".str_replace( "\n", "\n ", wordwrap("$command : ".I18n::_($info['short_desc']))) ."\n\n"); echo ( " ".basename($argv[0])." $command ". ($info['usage_args']?I18n::_($info['usage_args']):''). "\n"); if ($info['long_desc']) { if (is_array($info['long_desc'])) { $lines = array(); foreach ($info['long_desc'] as $line) $lines[] = I18n::_($line); $info['long_desc'] = implode("\n", $lines); } else $info['long_desc'] = I18n::_($info['long_desc']); echo "\n ".str_replace("\n", "\n ", wordwrap($info['long_desc']))."\n"; } echo "\n"; } exit(($error?1:0)); } /** * Handle command line arguments * @param array|null $args Command line argurment to handle (optional, default: $argv) * @return void */ public static function handle_args($args=null) { global $argv; $args = is_array($args)?$args:array_slice($argv, 1); $log_level_set = false; self :: $command = null; $command_args = array(); for ($i=0; $i < count($args); $i++) { if (array_key_exists($args[$i], self :: $commands)) { if (!self :: $command) self :: $command = $args[$i]; else self :: usage(I18n::_("Only one command could be executed !")); } else { switch($args[$i]) { case '-h': case '--help': self :: usage(); break; case '-d': case '--debug': Log :: set_level('DEBUG'); $log_level_set = true; break; case '-q': case '--quiet': Log :: set_level('WARNING'); $log_level_set = true; break; case '--trace': Log :: set_level('TRACE'); $log_level_set = true; break; default: if (self :: $command) $command_args[] = $args[$i]; else self :: usage( I18n::_( "Invalid parameter \"%s\".\nNote: Command's parameter/argument must be place ". "after the command." ), $args[$i] ); } } } if (!$log_level_set) Log :: set_level('INFO'); if (!self :: $command) self :: usage(); Log :: debug( "Run %s command %s with argument(s) '%s'.", basename($args[0]), self :: $command, implode("', '", $command_args) ); try { $result = call_user_func(self :: $commands[self :: $command]['handler'], $command_args); exit($result?0:1); } catch(Exception $e) { Log :: exception($e, I18n::_("An exception occured running command %s"), self :: $command); exit(1); } } }