2020-04-18 00:51:33 +02:00
|
|
|
<?php
|
|
|
|
|
2023-01-29 17:36:21 +01:00
|
|
|
use EesyPHP\Check;
|
2023-01-29 23:35:17 +01:00
|
|
|
use EesyPHP\I18n;
|
2023-01-29 17:36:21 +01:00
|
|
|
use EesyPHP\Log;
|
|
|
|
|
2020-04-18 00:51:33 +02:00
|
|
|
$cli_commands=array();
|
2022-04-24 17:43:44 +02:00
|
|
|
function add_cli_command($command, $handler, $short_desc, $usage_args=false, $long_desc=false,
|
|
|
|
$override=false) {
|
|
|
|
global $cli_commands;
|
|
|
|
if (array_key_exists($command, $cli_commands) && !$override) {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: error(_("The CLI command '%s' already exists."), $command);
|
2022-04-24 17:43:44 +02:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_callable($handler)) {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: error(_("The CLI command '%s' handler is not callable !"), $command);
|
2022-04-24 17:43:44 +02:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
$cli_commands[$command] = array (
|
|
|
|
'handler' => $handler,
|
|
|
|
'short_desc' => $short_desc,
|
|
|
|
'usage_args' => $usage_args,
|
|
|
|
'long_desc' => $long_desc,
|
|
|
|
);
|
|
|
|
return True;
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2022-04-24 17:43:44 +02:00
|
|
|
*************************************************************************************************
|
2020-04-18 00:51:33 +02:00
|
|
|
* /!\ Code after this message will only be execute on CLI context /!\
|
2022-04-24 17:43:44 +02:00
|
|
|
*************************************************************************************************
|
2020-04-18 00:51:33 +02:00
|
|
|
*/
|
|
|
|
if (php_sapi_name() != "cli")
|
2022-04-24 17:43:44 +02:00
|
|
|
return true;
|
2020-11-18 18:33:39 +01:00
|
|
|
|
|
|
|
// Store current CLI command
|
|
|
|
$cli_command = null;
|
2020-04-18 00:51:33 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* CLI Helpers
|
|
|
|
**/
|
|
|
|
|
|
|
|
function usage($error=false) {
|
2022-04-24 17:43:44 +02:00
|
|
|
global $cli_commands, $cli_command, $argv;
|
|
|
|
|
2022-04-24 18:20:44 +02:00
|
|
|
// 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))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-24 17:43:44 +02:00
|
|
|
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));
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function handle_cli_args() {
|
2022-04-24 17:43:44 +02:00
|
|
|
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(
|
2022-04-24 18:20:44 +02:00
|
|
|
_(
|
|
|
|
"Invalid parameter \"%s\".\nNote: Command's parameter/argument must be place ".
|
|
|
|
"after the command."
|
|
|
|
), $argv[$i]
|
2022-04-24 17:43:44 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$cli_command)
|
|
|
|
usage();
|
|
|
|
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: debug(
|
|
|
|
"Run %s command %s with argument(s) '%s'.",
|
2022-04-24 18:20:44 +02:00
|
|
|
basename($argv[0]), $cli_command, implode("', '", $command_args)
|
2022-04-24 17:43:44 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
try {
|
|
|
|
$result = call_user_func($cli_commands[$cli_command]['handler'], $command_args);
|
|
|
|
|
|
|
|
exit($result?0:1);
|
|
|
|
}
|
|
|
|
catch(Exception $e) {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: exception($e, _("An exception occured running command %s"), $cli_command);
|
2022-04-24 17:43:44 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function print_item_info($item) {
|
2022-04-24 17:43:44 +02:00
|
|
|
printf(_("Item #%s:\n"), $item['id']);
|
|
|
|
printf("\t"._("ID: %s")."\n", $item['id']);
|
|
|
|
printf("\t"._("Name: '%s'")."\n", $item['name']);
|
|
|
|
printf("\t"._("Date: %s")."\n", format_time($item['date']));
|
|
|
|
printf(
|
|
|
|
"\t"._("Description: %s")."\n",
|
|
|
|
($item['description']?"'".$item['description']."'":_("Not set"))
|
|
|
|
);
|
|
|
|
printf("\t"._("Status: %s")."\n", $item['status']);
|
|
|
|
return true;
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Common CLI commands
|
|
|
|
**/
|
|
|
|
|
|
|
|
$orderbys = array('id', 'name', 'date', 'status', 'description');
|
|
|
|
function cli_list($command_args) {
|
2022-04-24 17:43:44 +02:00
|
|
|
global $orderbys;
|
|
|
|
$params = array(
|
|
|
|
'order' => $orderbys[0],
|
|
|
|
'order_direction' => 'ASC',
|
|
|
|
'all' => true,
|
|
|
|
);
|
|
|
|
$patterns = array();
|
|
|
|
for($i=0; $i < count($command_args); $i++) {
|
|
|
|
switch($command_args[$i]) {
|
|
|
|
case '-o':
|
|
|
|
case '--orderby':
|
|
|
|
$i++;
|
|
|
|
if(!in_array($command_args[$i], $orderbys))
|
|
|
|
usage('Invalid --orderby clause');
|
|
|
|
$params['order'] = $command_args[$i];
|
|
|
|
break;
|
|
|
|
case '-r':
|
|
|
|
case '--reverse':
|
|
|
|
$params['order_direction'] = 'DESC';
|
|
|
|
break;
|
|
|
|
case '-s':
|
|
|
|
case '--status':
|
|
|
|
$i++;
|
|
|
|
if(!check_status($command_args[$i]))
|
|
|
|
usage('Invalid -s/--status clause');
|
|
|
|
$params['status'] = $command_args[$i];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$patterns[] = $command_args[$i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!empty($patterns))
|
|
|
|
$params['pattern'] = implode(' ', $patterns);
|
|
|
|
|
|
|
|
$items = search_items($params);
|
|
|
|
if (!is_array($items)) {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: error("Invalid DB info return.\n");
|
2022-04-24 17:43:44 +02:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($items['count'] == 0){
|
|
|
|
echo _("No item.\n");
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
|
|
|
$tbl = new Console_Table();
|
|
|
|
$tbl->setHeaders(
|
|
|
|
array(
|
|
|
|
'ID',
|
|
|
|
'Name',
|
|
|
|
'Date',
|
|
|
|
'Status',
|
|
|
|
'Description',
|
|
|
|
)
|
|
|
|
);
|
|
|
|
foreach($items['items'] as $info) {
|
|
|
|
$tbl->addRow(
|
|
|
|
array(
|
|
|
|
$info['id'],
|
|
|
|
$info['name'],
|
|
|
|
format_time($info['date']),
|
|
|
|
$info['status'],
|
|
|
|
($info['description']?$info['description']:''),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
echo $tbl->getTable();
|
|
|
|
echo "\n".sprintf(_("%d item(s)"), $items['count'])."\n";
|
|
|
|
return True;
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
add_cli_command(
|
2022-04-24 17:43:44 +02:00
|
|
|
'list',
|
|
|
|
'cli_list',
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("List/search items"),
|
|
|
|
I18n :: ___("[patterns]"),
|
2022-04-24 17:43:44 +02:00
|
|
|
array(
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("-o|--orderby Ordering list criterion. Possible values:"),
|
2022-04-24 17:43:44 +02:00
|
|
|
" - ".implode("\n - ", $orderbys),
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("-r|--reverse Reverse order"),
|
|
|
|
I18n :: ___("-s|--status Filter on status. Possible values:"),
|
2022-04-24 17:43:44 +02:00
|
|
|
" - ".implode("\n - ", array_keys($status_list)),
|
|
|
|
)
|
2020-04-18 00:51:33 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
function cli_show($command_args) {
|
2023-01-29 17:36:21 +01:00
|
|
|
if (count($command_args) != 1 || !Check :: id($command_args[0]))
|
2022-04-24 17:43:44 +02:00
|
|
|
usage(_('You must provide a valid ID.'));
|
2020-04-18 00:51:33 +02:00
|
|
|
|
|
|
|
$item_id = $command_args[0];
|
2022-04-24 17:43:44 +02:00
|
|
|
$item = get_item($item_id);
|
2020-04-18 00:51:33 +02:00
|
|
|
|
2022-04-24 17:43:44 +02:00
|
|
|
if (!$item)
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: fatal(_("Item #%s not found."), $item_id);
|
2020-04-18 00:51:33 +02:00
|
|
|
|
2022-04-24 17:43:44 +02:00
|
|
|
print_item_info($item);
|
|
|
|
return True;
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
add_cli_command(
|
2022-04-24 17:43:44 +02:00
|
|
|
'show',
|
|
|
|
'cli_show',
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("Show item"),
|
|
|
|
I18n :: ___("[ID]")
|
2020-04-18 00:51:33 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
function cli_delete($command_args) {
|
2022-04-24 17:43:44 +02:00
|
|
|
if (count($command_args) != 1)
|
|
|
|
usage(_('You must provide item ID.'));
|
|
|
|
|
|
|
|
// Check URI
|
2023-01-29 17:36:21 +01:00
|
|
|
if (!Check :: id($command_args[0]))
|
|
|
|
Log :: fatal(_("Invalid item ID"));
|
2022-04-24 17:43:44 +02:00
|
|
|
|
|
|
|
// Check exist
|
|
|
|
$item_id = $command_args[0];
|
|
|
|
$item = get_item($item_id);
|
|
|
|
if (!$item)
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: fatal(_("Item #%s not found."), $item_id);
|
2022-04-24 17:43:44 +02:00
|
|
|
|
|
|
|
print_item_info($item);
|
|
|
|
|
|
|
|
// Sure ?
|
|
|
|
echo _("Are you sure you want to delete this item? Type 'yes' to continue: ");
|
|
|
|
$handle = fopen ("php://stdin","r");
|
|
|
|
$line = fgets($handle);
|
|
|
|
if(trim($line) != 'yes'){
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: warning(_("User cancel"));
|
2022-04-24 17:43:44 +02:00
|
|
|
exit;
|
|
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
|
|
|
|
if (!delete_item($item['id']))
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: fatal(_("An error occured deleting item #%d."), $item_id);
|
2022-04-24 17:43:44 +02:00
|
|
|
|
|
|
|
return True;
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
add_cli_command(
|
2022-04-24 17:43:44 +02:00
|
|
|
'delete',
|
|
|
|
'cli_delete',
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("Delete item"),
|
|
|
|
I18n :: ___("[item ID]")
|
2020-04-18 00:51:33 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
function cli_export($command_args) {
|
2022-04-24 17:43:44 +02:00
|
|
|
$fd = fopen((count($command_args) >= 1?$command_args[0]:'php://output'), 'w');
|
|
|
|
export_items($fd);
|
|
|
|
fclose($fd);
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: info("Items export to '".(count($command_args) >= 1?$command_args[0]:'STDOUT')."'.");
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
add_cli_command(
|
2022-04-24 17:43:44 +02:00
|
|
|
'export',
|
|
|
|
'cli_export',
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("Export items (as CSV)"),
|
|
|
|
I18n :: ___("[output file path]")
|
2020-04-18 00:51:33 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
function cli_restore($command_args) {
|
2022-04-24 17:43:44 +02:00
|
|
|
$fd = fopen((count($command_args) >= 1?$command_args[0]:'php://stdin'), 'r');
|
|
|
|
restore_items($fd);
|
|
|
|
fclose($fd);
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: info(
|
|
|
|
"Items restored from '%s'",
|
2022-04-24 17:43:44 +02:00
|
|
|
(count($command_args) >= 1?$command_args[0]:'STDIN')
|
2023-01-29 11:51:41 +01:00
|
|
|
);
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
add_cli_command(
|
2022-04-24 17:43:44 +02:00
|
|
|
'restore',
|
|
|
|
'cli_restore',
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("Restore items (from CSV)"),
|
|
|
|
I18n :: ___("[input file path]")
|
2020-04-18 00:51:33 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
function cli_cron($command_args) {
|
2022-04-24 17:43:44 +02:00
|
|
|
global $item_max_age;
|
|
|
|
if (!isset($item_max_age))
|
|
|
|
$item_max_age = 30;
|
|
|
|
|
|
|
|
$just_try = false;
|
|
|
|
for($i=0; $i < count($command_args); $i++) {
|
|
|
|
switch($command_args[$i]) {
|
|
|
|
case '-m':
|
|
|
|
case '--max-age':
|
|
|
|
$i++;
|
2023-01-29 17:36:21 +01:00
|
|
|
if(!Check :: id($command_args[$i]))
|
2022-04-24 17:43:44 +02:00
|
|
|
usage('Invalid -m|--max-age clause');
|
|
|
|
$item_max_age = $command_args[$i];
|
|
|
|
break;
|
|
|
|
case '-j':
|
|
|
|
case '--just-try':
|
|
|
|
$just_try = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage('Invalid parameter '.$command_args[$i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_int($item_max_age) || $item_max_age <= 0)
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: fatal(
|
2022-04-24 17:43:44 +02:00
|
|
|
'Invalid $item_max_age value set in configuration: it\'s must be a positive integer.');
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: debug("cli_cron(): item max age = $item_max_age day(s)");
|
2022-04-24 17:43:44 +02:00
|
|
|
|
|
|
|
$limit = time() - ($item_max_age * 86400);
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: debug("Handle items expiration with creation date limit ".format_time($limit).".");
|
2022-04-24 17:43:44 +02:00
|
|
|
|
|
|
|
$items = search_items(array('all' => true));
|
|
|
|
$error = false;
|
|
|
|
foreach($items['items'] as $item) {
|
|
|
|
if ($item['date'] < $limit) {
|
|
|
|
if ($just_try) {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: debug('Just-try mode: do not really delete item #%s (%s, creation date: %s)',
|
2022-04-24 17:43:44 +02:00
|
|
|
$item['id'], $item['name'], format_time($item['date'])
|
2022-04-24 18:20:44 +02:00
|
|
|
);
|
2022-04-24 17:43:44 +02:00
|
|
|
}
|
|
|
|
else if (delete_item($item['id'])) {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: info('Item #%s (%s) deleted (creation date: %s)',
|
2022-04-24 18:20:44 +02:00
|
|
|
$item['id'], $item['name'], format_time($item['date'])
|
|
|
|
);
|
2022-04-24 17:43:44 +02:00
|
|
|
}
|
|
|
|
else {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: error('Fail to delete item "%s" (%s, creation date: %s)',
|
2022-04-24 17:43:44 +02:00
|
|
|
$item['id'], $item['name'], format_time($item['date'])
|
2022-04-24 18:20:44 +02:00
|
|
|
);
|
2022-04-24 17:43:44 +02:00
|
|
|
$error = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2023-01-29 17:36:21 +01:00
|
|
|
Log :: debug('Item "%s" (%s) still valid (creation date: %s)',
|
2022-04-24 17:43:44 +02:00
|
|
|
$item['id'], $item['name'], format_time($item['date'])
|
2022-04-24 18:20:44 +02:00
|
|
|
);
|
2022-04-24 17:43:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
exit($error?1:0);
|
2020-04-18 00:51:33 +02:00
|
|
|
}
|
|
|
|
add_cli_command(
|
2022-04-24 17:43:44 +02:00
|
|
|
'cron',
|
|
|
|
'cli_cron',
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("Cron to handle item expiration"),
|
2022-04-24 17:43:44 +02:00
|
|
|
false,
|
|
|
|
array (
|
2023-01-29 23:35:17 +01:00
|
|
|
I18n :: ___("-j/--just-try Just-try mode : do not really removed expired item(s)"),
|
|
|
|
I18n :: ___("-m/--max-age Item expiration limit (in days, optional)"),
|
2022-04-24 17:43:44 +02:00
|
|
|
)
|
2020-04-18 00:51:33 +02:00
|
|
|
);
|
2023-01-29 11:51:41 +01:00
|
|
|
|
|
|
|
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|