diff --git a/bin/eesyphp b/bin/eesyphp index cea5a5a..211a8ed 100755 --- a/bin/eesyphp +++ b/bin/eesyphp @@ -1,8 +1,7 @@ #!/usr/bin/php $handler, - 'short_desc' => $short_desc, - 'usage_args' => $usage_args, - 'long_desc' => $long_desc, - ); - return True; -} - /* ************************************************************************************************* * /!\ Code after this message will only be execute on CLI context /!\ @@ -35,126 +13,11 @@ function add_cli_command($command, $handler, $short_desc, $usage_args=false, $lo if (php_sapi_name() != "cli") return true; -// Store current CLI command -$cli_command = null; /** * CLI Helpers **/ -function usage($error=false) { - global $cli_commands, $cli_command, $argv; - - // If more than 1 arguments passed, format error message using sprintf - if (func_num_args() > 1) { - $error = call_user_func_array( - 'sprintf', - array_merge(array($error), array_slice(func_get_args(), 1)) - ); - } - - if ($error) - echo "$error\n\n"; - printf(_("Usage: %s [-h] [-qd] command\n"), basename($argv[0])); - echo _(" -h Show this message\n"); - echo _(" -q / -d Quiet/Debug mode\n"); - echo _(" --trace Trace mode (the most verbose)\n"); - echo _(" command Command to run\n"); - echo "\n"; - echo _("Available commands:\n"); - - foreach ($cli_commands as $command => $info) { - if ($cli_command && $command != $cli_command) - continue; - echo ( - " ".str_replace( - "\n", "\n ", - wordwrap("$command : "._($info['short_desc']))) - ."\n\n"); - echo ( - " ".basename($argv[0])." $command ". - ($info['usage_args']?_($info['usage_args']):''). - "\n"); - if ($info['long_desc']) { - if (is_array($info['long_desc'])) { - $lines = array(); - foreach ($info['long_desc'] as $line) - $lines[] = _($line); - $info['long_desc'] = implode("\n", $lines); - } - else - $info['long_desc'] = _($info['long_desc']); - - echo "\n ".str_replace("\n", "\n ", wordwrap($info['long_desc']))."\n"; - } - echo "\n"; - } - - exit(($error?1:0)); -} - -function handle_cli_args() { - global $log_level, $cli_commands, $cli_command, $argv; - $log_level = 'INFO'; - $cli_command = false; - $command_args = array(); - for ($i=1; $i < count($argv); $i++) { - if (array_key_exists($argv[$i], $cli_commands)) { - if (!$cli_command) - $cli_command = $argv[$i]; - else - usage(_("Only one command could be executed !")); - } - else { - switch($argv[$i]) { - case '-h': - case '--help': - usage(); - break; - case '-d': - case '--debug': - $log_level = 'DEBUG'; - break; - case '-q': - case '--quiet': - $log_level = 'WARNING'; - break; - case '--trace': - $log_level = 'TRACE'; - break; - default: - if ($cli_command) - $command_args[] = $argv[$i]; - else - usage( - _( - "Invalid parameter \"%s\".\nNote: Command's parameter/argument must be place ". - "after the command." - ), $argv[$i] - ); - } - } - } - - if (!$cli_command) - usage(); - - Log :: debug( - "Run %s command %s with argument(s) '%s'.", - basename($argv[0]), $cli_command, implode("', '", $command_args) - ); - - try { - $result = call_user_func($cli_commands[$cli_command]['handler'], $command_args); - - exit($result?0:1); - } - catch(Exception $e) { - Log :: exception($e, _("An exception occured running command %s"), $cli_command); - exit(1); - } -} - function print_item_info($item) { printf(_("Item #%s:\n"), $item['id']); printf("\t"._("ID: %s")."\n", $item['id']); @@ -188,7 +51,7 @@ function cli_list($command_args) { case '--orderby': $i++; if(!in_array($command_args[$i], $orderbys)) - usage('Invalid --orderby clause'); + Cli :: usage('Invalid --orderby clause'); $params['order'] = $command_args[$i]; break; case '-r': @@ -199,7 +62,7 @@ function cli_list($command_args) { case '--status': $i++; if(!check_status($command_args[$i])) - usage('Invalid -s/--status clause'); + Cli :: usage('Invalid -s/--status clause'); $params['status'] = $command_args[$i]; break; default: @@ -246,7 +109,7 @@ function cli_list($command_args) { echo "\n".sprintf(_("%d item(s)"), $items['count'])."\n"; return True; } -add_cli_command( +Cli :: add_command( 'list', 'cli_list', I18n :: ___("List/search items"), @@ -262,7 +125,7 @@ add_cli_command( function cli_show($command_args) { if (count($command_args) != 1 || !Check :: id($command_args[0])) - usage(_('You must provide a valid ID.')); + Cli :: usage(_('You must provide a valid ID.')); $item_id = $command_args[0]; $item = get_item($item_id); @@ -273,7 +136,7 @@ function cli_show($command_args) { print_item_info($item); return True; } -add_cli_command( +Cli :: add_command( 'show', 'cli_show', I18n :: ___("Show item"), @@ -282,7 +145,7 @@ add_cli_command( function cli_delete($command_args) { if (count($command_args) != 1) - usage(_('You must provide item ID.')); + Cli :: usage(_('You must provide item ID.')); // Check URI if (!Check :: id($command_args[0])) @@ -311,7 +174,7 @@ function cli_delete($command_args) { return True; } -add_cli_command( +Cli :: add_command( 'delete', 'cli_delete', I18n :: ___("Delete item"), @@ -324,7 +187,7 @@ function cli_export($command_args) { fclose($fd); Log :: info("Items export to '".(count($command_args) >= 1?$command_args[0]:'STDOUT')."'."); } -add_cli_command( +Cli :: add_command( 'export', 'cli_export', I18n :: ___("Export items (as CSV)"), @@ -340,7 +203,7 @@ function cli_restore($command_args) { (count($command_args) >= 1?$command_args[0]:'STDIN') ); } -add_cli_command( +Cli :: add_command( 'restore', 'cli_restore', I18n :: ___("Restore items (from CSV)"), @@ -359,7 +222,7 @@ function cli_cron($command_args) { case '--max-age': $i++; if(!Check :: id($command_args[$i])) - usage('Invalid -m|--max-age clause'); + Cli :: usage('Invalid -m|--max-age clause'); $item_max_age = $command_args[$i]; break; case '-j': @@ -367,7 +230,7 @@ function cli_cron($command_args) { $just_try = true; break; default: - usage('Invalid parameter '.$command_args[$i]); + Cli :: usage('Invalid parameter '.$command_args[$i]); } } @@ -408,11 +271,11 @@ function cli_cron($command_args) { } exit($error?1:0); } -add_cli_command( +Cli :: add_command( 'cron', 'cli_cron', I18n :: ___("Cron to handle item expiration"), - false, + null, array ( I18n :: ___("-j/--just-try Just-try mode : do not really removed expired item(s)"), I18n :: ___("-m/--max-age Item expiration limit (in days, optional)"), diff --git a/phpstan.neon b/phpstan.neon index 3340bfc..58a3784 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,7 +4,7 @@ parameters: - src - includes - public_html - - bin + - bin/eesyphp excludePaths: - includes/config.local.php ignoreErrors: diff --git a/src/Cli.php b/src/Cli.php new file mode 100644 index 0000000..d862481 --- /dev/null +++ b/src/Cli.php @@ -0,0 +1,185 @@ + + */ + 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(_("The CLI command '%s' already exists."), $command); + return False; + } + + if (!is_callable($handler)) { + Log :: error(_("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"; + printf(_("Usage: %s [-h] [-qd] command\n"), basename($argv[0])); + echo _(" -h Show this message\n"); + echo _(" -q / -d Quiet/Debug mode\n"); + echo _(" --trace Trace mode (the most verbose)\n"); + echo _(" command Command to run\n"); + echo "\n"; + echo _("Available commands:\n"); + + foreach (self :: $commands as $command => $info) { + if (self :: $command && $command != self :: $command) + continue; + echo ( + " ".str_replace( + "\n", "\n ", + wordwrap("$command : "._($info['short_desc']))) + ."\n\n"); + echo ( + " ".basename($argv[0])." $command ". + ($info['usage_args']?_($info['usage_args']):''). + "\n"); + if ($info['long_desc']) { + if (is_array($info['long_desc'])) { + $lines = array(); + foreach ($info['long_desc'] as $line) + $lines[] = _($line); + $info['long_desc'] = implode("\n", $lines); + } + else + $info['long_desc'] = _($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(_("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( + _( + "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, _("An exception occured running command %s"), self :: $command); + exit(1); + } + } + +} diff --git a/src/I18n.php b/src/I18n.php index 5976d87..c7f7871 100644 --- a/src/I18n.php +++ b/src/I18n.php @@ -2,6 +2,7 @@ namespace EesyPHP; +use EesyPHP\Cli; use EesyPHP\Log; use Locale; @@ -114,7 +115,7 @@ class I18n { } if (php_sapi_name() == 'cli') { - add_cli_command( + Cli :: add_command( 'extract_messages', array('\\EesyPHP\\I18n', 'cli_extract_messages'), self :: ___("Extract messages that need to be translated"), @@ -122,7 +123,7 @@ class I18n { self :: ___("This command could be used to generate/update lang/messages.pot file.") ); - add_cli_command( + Cli :: add_command( 'update_messages', array('\\EesyPHP\\I18n', 'cli_update_messages'), self :: ___("Update messages in translation PO lang files"), @@ -130,7 +131,7 @@ class I18n { self :: ___("This command could be used to init/update PO files in lang/*/LC_MESSAGES directories.") ); - add_cli_command( + Cli :: add_command( 'compile_messages', array('\\EesyPHP\\I18n', 'cli_compile_messages'), self :: ___( diff --git a/src/Log.php b/src/Log.php index accb968..a383756 100644 --- a/src/Log.php +++ b/src/Log.php @@ -66,19 +66,8 @@ class Log { public static function init($filepath, $level=null, $php_errors_levels=null) { self :: $filepath = $filepath; - // Set default log level (if not defined or invalid) - if (is_null($level)) { - self :: $level = self :: $default_level; - } - elseif (!array_key_exists($level, self :: $levels)) { - self :: $level = self :: $default_level; - self :: warning( - "Invalid log level value found in configuration (%s). ". - "Set as default (%s).", $level, self :: $default_level); - } - else { - self :: $level = $level; - } + // Set log level + self :: set_level($level); // Log PHP errors if (!is_null($php_errors_levels)) @@ -258,6 +247,27 @@ class Log { return True; } + /** + * Set current log level + * @param string $level The new log level to set + * @return void + */ + public static function set_level($level=null) { + // Set default log level (if not defined or invalid) + if (is_null($level)) { + self :: $level = self :: $default_level; + } + elseif (!array_key_exists($level, self :: $levels)) { + self :: $level = self :: $default_level; + self :: warning( + "Invalid log level value found in configuration (%s). ". + "Set as default (%s).", $level, self :: $default_level); + } + else { + self :: $level = $level; + } + } + /* ******************************************************************************* * Handle exception logging