Add find, query and set slot commands

This commit is contained in:
Chris 2025-03-13 17:36:38 +01:00
parent c4877471f8
commit dda2a7b4ae
8 changed files with 269 additions and 6 deletions

View File

@ -27,5 +27,8 @@
}, },
"bin": [ "bin": [
"bin/slotcli" "bin/slotcli"
] ],
"require-dev": {
"phpstan/phpstan": "^2.1"
}
} }

70
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "c7b8d782317f7c0945290d495e1b425e", "content-hash": "9dc3a3ca30d0b0d1698b2e4e26577e67",
"packages": [ "packages": [
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
@ -594,13 +594,14 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "../slotdb-client-php", "url": "../slotdb-client-php",
"reference": "3b929684f9ceb58ea1e23328b12c2c3333e092a0" "reference": "43d5db56cfc22486b00415079664b5fbc2392b4e"
}, },
"require": { "require": {
"psr/http-client": "^1.0" "psr/http-client": "^1.0"
}, },
"require-dev": { "require-dev": {
"guzzlehttp/guzzle": "^7.9" "guzzlehttp/guzzle": "^7.9",
"phpstan/phpstan": "^2.1"
}, },
"default-branch": true, "default-branch": true,
"type": "library", "type": "library",
@ -619,7 +620,7 @@
} }
], ],
"description": "SlotDB PHP Client", "description": "SlotDB PHP Client",
"time": "2025-03-10T15:43:56+00:00" "time": "2025-03-13T16:14:01+00:00"
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
@ -1270,7 +1271,66 @@
"time": "2024-11-13T13:31:26+00:00" "time": "2024-11-13T13:31:26+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [
{
"name": "phpstan/phpstan",
"version": "2.1.8",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "f9adff3b87c03b12cc7e46a30a524648e497758f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/f9adff3b87c03b12cc7e46a30a524648e497758f",
"reference": "f9adff3b87c03b12cc7e46a30a524648e497758f",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"bin": [
"phpstan",
"phpstan.phar"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"keywords": [
"dev",
"static analysis"
],
"support": {
"docs": "https://phpstan.org/user-guide/getting-started",
"forum": "https://github.com/phpstan/phpstan/discussions",
"issues": "https://github.com/phpstan/phpstan/issues",
"security": "https://github.com/phpstan/phpstan/security/policy",
"source": "https://github.com/phpstan/phpstan-src"
},
"funding": [
{
"url": "https://github.com/ondrejmirtes",
"type": "github"
},
{
"url": "https://github.com/phpstan",
"type": "github"
}
],
"time": "2025-03-09T09:30:48+00:00"
}
],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": { "stability-flags": {

6
phpstan.neon Normal file
View File

@ -0,0 +1,6 @@
parameters:
level: 5
# Paths to include in the analysis
paths:
- src

View File

@ -2,13 +2,24 @@
namespace SlotDb\Cli; namespace SlotDb\Cli;
use GuzzleHttp\Client;
use SlotDb\Client\SlotDbClient;
class Application extends \Symfony\Component\Console\Application class Application extends \Symfony\Component\Console\Application
{ {
public function __construct() public function __construct()
{ {
parent::__construct("slotcli", "0.0.0"); parent::__construct("slotcli", "0.0.0");
$psr = new Client();
$client = new SlotDbClient($psr);
$this->add(new Command\ImportCommand()); $this->add(new Command\ImportCommand());
$this->add(new Command\ExportCommand()); $this->add(new Command\ExportCommand());
$this->add(new Command\Slot\SlotQueryCommand($client));
$this->add(new Command\Slot\SlotFindCommand($client));
$this->add(new Command\Slot\SlotSetCommand($client));
} }
} }

View File

@ -2,9 +2,14 @@
namespace SlotDb\Cli\Command; namespace SlotDb\Cli\Command;
use SlotDb\Cli\Application;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
abstract class BaseCommand extends Command abstract class BaseCommand extends Command
{ {
public function getApplication(): Application
{
return parent::getApplication(); // @phpstan-ignore return.type
}
} }

View File

@ -0,0 +1,67 @@
<?php
namespace SlotDb\Cli\Command\Slot;
use SlotDb\Client\SlotDbClient;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name:"slot:find", aliases:[ "find" ], description:"Find all slots, or slots matching conditions")]
class SlotFindCommand extends Command
{
public function __construct(
private readonly SlotDbClient $client
)
{
parent::__construct();
}
protected function configure()
{
$this
->addArgument("where", InputArgument::IS_ARRAY, "Conditions that are ANDed")
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$wheres = $input->getArgument("where");
$whereConds = [];
foreach ($wheres as $where) {
if (preg_match('<^(.+?)(=|\<=|\>=|\<|\>)(.+?)$>', $where, $match)) {
$c = $match[2];
if ($c == '=') $c = '';
$whereConds[$match[1]] = sprintf("%s%s", $c, $match[3]);
}
}
$slots = $this->client->findSlots($whereConds);
$keys = [];
foreach ($slots as $slot) {
$keys = array_merge($keys, array_keys($slot));
}
$keys = array_unique($keys);
$table = new Table($output);
$table->setHeaders($keys);
$table->setStyle('box');
foreach ($slots as $slot) {
$row = [];
foreach ($keys as $key) {
$row[] = isset($slot[$key]) ? json_encode($slot[$key]) : null;
}
$table->addRow($row);
}
$table->render();
return self::SUCCESS;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace SlotDb\Cli\Command\Slot;
use SlotDb\Client\SlotDbClient;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name:"slot:query", aliases:[ "query" ], description:"Query a slot and its properties")]
class SlotQueryCommand extends Command
{
public function __construct(
private readonly SlotDbClient $client
)
{
parent::__construct();
}
protected function configure()
{
$this
->addArgument("slot", InputArgument::REQUIRED, "Slot ID")
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$slotId = $input->getArgument("slot");
$slot = $this->client->querySlot($slotId);
$len = 2 + max(array_map(mb_strlen(...), array_keys($slot)));
foreach ($slot as $k=>$v) {
$output->writeln(
sprintf(
str_starts_with($k,"_")
? "<fg=green>%{$len}s</>: <fg=gray>%s</>"
: "<fg=green;options=bold>%{$len}s</>: <fg=yellow>%s</>",
$k, json_encode($v)
)
);
}
return self::SUCCESS;
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace SlotDb\Cli\Command\Slot;
use SlotDb\Client\SlotDbClient;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name:"slot:set", aliases:[ "set" ], description:"Update the properties on a slot")]
class SlotSetCommand extends Command
{
public function __construct(
private readonly SlotDbClient $client
)
{
parent::__construct();
}
protected function configure()
{
$this
->addArgument("slot", InputArgument::REQUIRED, "Slot ID")
->addArgument("update", InputArgument::IS_ARRAY, "key=value pairs to update")
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$slotId = $input->getArgument("slot");
$updates = $input->getArgument("update");
$props = [];
foreach ($updates as $update) {
if (str_contains($update, "=")) {
[$k,$v] = explode("=", $update, 2);
$v = json_decode($v) ?? $v;
$props[$k] = $v;
} else {
$props[$update] = null;
}
}
$slot = $this->client->updateSlot($slotId, $props);
$len = 2 + max(array_map(mb_strlen(...), array_keys($slot)));
foreach ($slot as $k=>$v) {
$output->writeln(
sprintf(
str_starts_with($k,"_")
? "<fg=green>%{$len}s</>: <fg=gray>%s</>"
: "<fg=green;options=bold>%{$len}s</>: <fg=yellow>%s</>",
$k, json_encode($v)
)
);
}
return self::SUCCESS;
}
}