175 lines
5.0 KiB
PHP
Executable File
175 lines
5.0 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php
|
|
|
|
require_once __DIR__."/../vendor/autoload.php";
|
|
|
|
$opts = (object)[
|
|
'help' => false,
|
|
'server' => '127.0.0.1:8000',
|
|
'args' => [],
|
|
'json' => false,
|
|
'from' => null,
|
|
'until' => null,
|
|
];
|
|
|
|
function parse_datetime(string $timestamp): ?DateTime {
|
|
if (strtotime($timestamp)) {
|
|
return new DateTime($timestamp);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function parse_options() {
|
|
global $argc,$argv,$opts;
|
|
$o = getopt("hs:f:u:j",["help","server:","from:","until:","json"],$optind);
|
|
foreach ($o as $opt=>$val) {
|
|
switch ($opt) {
|
|
case 'h':
|
|
case 'help':
|
|
$opts->help = true;
|
|
break;
|
|
case 's':
|
|
case 'server':
|
|
$opts->server = $val;
|
|
break;
|
|
case 'f':
|
|
case 'from':
|
|
$opts->from = parse_datetime($val);
|
|
break;
|
|
case 'u':
|
|
case 'until':
|
|
$opts->until = parse_datetime($val);
|
|
break;
|
|
case 'j':
|
|
case 'json':
|
|
$opts->json = true;
|
|
break;
|
|
}
|
|
}
|
|
$opts->args = array_slice($argv,$optind);
|
|
}
|
|
|
|
function print_help() {
|
|
global $argv;
|
|
printf("Syntax:\n %s [options] {action} [args...]\n\n", basename($argv[0]));
|
|
printf("Options:\n");
|
|
printf(" -h,--help Show this help\n");
|
|
printf(" -s,--server SERVER Specify the server (ip:port) to use\n");
|
|
printf(" -f,--from DATETIME Set the validity start timestamp\n");
|
|
printf(" -u,--until DATETIME Set the validity end timestamp\n");
|
|
printf(" -j,--json Assume json encoded values with set\n");
|
|
printf("\nActions:\n");
|
|
printf(" set {collection} {key}={value}*\n Set the keys to value, using the --from and --until values. Multiple\n key-value pairs can be specified. Use --json to pass values as json.\n");
|
|
printf(" get {collection} [{when}]\n Fetch the current values, or the values at {when}.\n");
|
|
printf(" show {collection}\n Show keys and all values, allowing to delete values.\n");
|
|
printf(" delete {collection} {key|id}*\n Delete a key or a value from a collection\n");
|
|
printf(" purge {collection}\n Delete an entire collection\n");
|
|
}
|
|
|
|
function exit_error(string $msg, int $code=1): never {
|
|
fwrite(STDERR, $msg."\n");
|
|
exit($code);
|
|
}
|
|
|
|
parse_options();
|
|
|
|
if ($opts->help) {
|
|
print_help();
|
|
exit(0);
|
|
}
|
|
|
|
$http = new React\Http\Browser();
|
|
|
|
function http_get(string $url, array $headers) {
|
|
global $opts,$http;
|
|
return $http->get("http://{$opts->server}/{$url}", $headers);
|
|
}
|
|
|
|
function http_post(string $url, array $headers, string $body) {
|
|
global $opts,$http;
|
|
return $http->post("http://{$opts->server}/{$url}", $headers, $body);
|
|
}
|
|
|
|
function action_get(object $opts) {
|
|
$collection = array_shift($opts->args);
|
|
if (!$collection) {
|
|
exit_error("Missing collection. Expected: get {collection}");
|
|
}
|
|
http_get($collection, [])->then(
|
|
function ($response) {
|
|
echo $response->getBody()->getContents();
|
|
},
|
|
function ($error) {
|
|
echo $error->getMessage()."\n";
|
|
}
|
|
);
|
|
}
|
|
|
|
function action_show(object $opts) {
|
|
$collection = array_shift($opts->args);
|
|
if (!$collection) {
|
|
exit_error("Missing collection. Expected: get {collection}");
|
|
}
|
|
http_get($collection."/all", [])->then(
|
|
function ($response) {
|
|
echo $response->getBody()->getContents();
|
|
},
|
|
function ($error) {
|
|
echo $error->getMessage()."\n";
|
|
}
|
|
);
|
|
}
|
|
|
|
function action_set(object $opts) {
|
|
$collection = array_shift($opts->args);
|
|
if (!$collection) {
|
|
exit_error("Missing collection. Expected: get {collection}");
|
|
}
|
|
$body = [];
|
|
while ($kvpair = array_shift($opts->args)) {
|
|
$op = [];
|
|
if (!str_contains($kvpair,"=")) {
|
|
exit_error("Invalid key-value pair: {$kvpair}");
|
|
}
|
|
[$key,$value] = explode("=", $kvpair, 2);
|
|
if (ctype_digit($key)) {
|
|
$op['id'] = $key;
|
|
} else {
|
|
$op['key'] = $key;
|
|
}
|
|
$op['value'] = $opts->json ? json_decode($value) : $value;
|
|
if ($opts->from || $opts->until) {
|
|
$vfrom = $opts->from ? [ 'from' => $opts->from->format('Y-m-d H:i:s P') ] : null;
|
|
$vuntil = $opts->until ? [ 'until' => $opts->until->format('Y-m-d H:i:s P') ] : null;
|
|
$op['validity'] = [ ...$vfrom, ...$vuntil ];
|
|
}
|
|
$body[$key] = $op;
|
|
}
|
|
http_post($collection, [ 'content-type'=>'application/json' ], json_encode($body))->then(
|
|
function ($response) {
|
|
echo $response->getBody()->getContents();
|
|
},
|
|
function ($error) {
|
|
echo $error->getMessage()."\n";
|
|
}
|
|
);
|
|
}
|
|
|
|
$action = array_shift($opts->args);
|
|
|
|
switch ($action) {
|
|
|
|
case 'get':
|
|
action_get($opts);
|
|
break;
|
|
|
|
case 'show':
|
|
action_show($opts);
|
|
break;
|
|
|
|
case 'set':
|
|
action_set($opts);
|
|
break;
|
|
}
|
|
|