Various fixes
* Fixed the init command not being registered * pdoshell: Improved configuration handling
This commit is contained in:
parent
7c4ca953f6
commit
7e04b6c001
@ -29,23 +29,46 @@ class PdoShell {
|
|||||||
|
|
||||||
private ?array $lastQuery = null;
|
private ?array $lastQuery = null;
|
||||||
|
|
||||||
|
private ShellState $state;
|
||||||
|
|
||||||
#[EnumSetting('output', [ 'table', 'vertical', 'dump' ])]
|
#[EnumSetting('output', [ 'table', 'vertical', 'dump' ])]
|
||||||
#[EnumSetting('table.style', [ 'box', 'compact', 'borderless' ])]
|
#[EnumSetting('table.style', [ 'box', 'compact', 'borderless' ])]
|
||||||
private array $defaultOptions = [
|
private array $defaultOptions = [
|
||||||
'output' => 'table',
|
'output' => 'table',
|
||||||
'table.maxwidth' => 40,
|
'table.maxwidth' => 40,
|
||||||
'table.style' => 'box',
|
'table.style' => 'box',
|
||||||
|
'capture' => false,
|
||||||
|
'syntax' => 'none',
|
||||||
|
];
|
||||||
|
private array $validOptions = [
|
||||||
|
'output' => [ 'table', 'vertical', 'dump' ],
|
||||||
|
'table.maxwidth' => 'int',
|
||||||
|
'table.style' => [ 'box', 'compact', 'borderless' ],
|
||||||
|
'capture' => 'bool',
|
||||||
|
'syntax' => [ 'none', 'mysql', 'sqlite' ]
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(OutputInterface $output)
|
public function __construct(OutputInterface $output)
|
||||||
{
|
{
|
||||||
$this->output = $output;
|
$this->output = $output;
|
||||||
|
$this->state = new ShellState();
|
||||||
$this->options = $this->defaultOptions;
|
$this->options = $this->defaultOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getState(): ShellState
|
||||||
|
{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
private function promptForCommand()
|
private function promptForCommand()
|
||||||
{
|
{
|
||||||
$prompt = sprintf("PDO:[%s%s]> ", $this->resource, $this->db?"":"?");
|
$info = $this->resource . ($this->db?"":"?");
|
||||||
|
|
||||||
|
if ($this->getOption('capture')) {
|
||||||
|
$info .= '][#' . $this->vars['capture_index'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$prompt = sprintf("PDO:[%s]> ", $info);
|
||||||
$input = readline($prompt);
|
$input = readline($prompt);
|
||||||
|
|
||||||
return $input;
|
return $input;
|
||||||
@ -62,6 +85,11 @@ class PdoShell {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getOption(string $name): mixed
|
||||||
|
{
|
||||||
|
return $this->options[$name] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
private function expand(string $string): string
|
private function expand(string $string): string
|
||||||
{
|
{
|
||||||
return $string;
|
return $string;
|
||||||
@ -125,6 +153,10 @@ class PdoShell {
|
|||||||
case '.help':
|
case '.help':
|
||||||
$this->doHelpCommand($args);
|
$this->doHelpCommand($args);
|
||||||
break;
|
break;
|
||||||
|
case '.capture':
|
||||||
|
$this->doSetCommand(['capture', 1]);
|
||||||
|
$this->doVarCommand(['capture_index', 0]);
|
||||||
|
break;
|
||||||
|
|
||||||
case '.quit':
|
case '.quit':
|
||||||
case '.exit':
|
case '.exit':
|
||||||
@ -211,7 +243,14 @@ class PdoShell {
|
|||||||
|
|
||||||
if (empty($varname)) {
|
if (empty($varname)) {
|
||||||
foreach ($this->options as $var=>$value) {
|
foreach ($this->options as $var=>$value) {
|
||||||
$this->output->writeln("<info>{$var}</>: <comment>".var_export($value,true)."</>");
|
if (!array_key_exists($var, $this->validOptions)) {
|
||||||
|
$info = "";
|
||||||
|
} elseif (is_array($this->validOptions[$var])) {
|
||||||
|
$info = "[<fg=cyan>".join("</>,<fg=cyan>", $this->validOptions[$var])."</>]";
|
||||||
|
} else {
|
||||||
|
$info = "<<fg=magenta>".$this->validOptions[$var]."</>>";
|
||||||
|
}
|
||||||
|
$this->output->writeln("<info>{$var}</>: <comment>".var_export($value,true)."</> ".$info);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -221,6 +260,33 @@ class PdoShell {
|
|||||||
$this->output->writeln("<error>No such option {$varname}</>");
|
$this->output->writeln("<error>No such option {$varname}</>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (array_key_exists($varname, $this->validOptions)) {
|
||||||
|
$v = $this->validOptions[$varname];
|
||||||
|
if (is_array($v)) {
|
||||||
|
if (!in_array($value, $v)) {
|
||||||
|
$this->output->writeln("<error>Bad value for {$varname}</> Valid values: ".join(", ",$v)."</>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} elseif (is_string($v)) {
|
||||||
|
switch ($v) {
|
||||||
|
case 'int':
|
||||||
|
if (!ctype_digit($value)) {
|
||||||
|
$this->output->writeln("<error>Bad value for {$varname}</> Expected integer</>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'bool':
|
||||||
|
$true = in_array($value, [ 1, "true", "yes", "on" ]);
|
||||||
|
$false = in_array($value, [ 0, "false", "no", "off" ]);
|
||||||
|
if (!$true && !$false) {
|
||||||
|
$this->output->writeln("<error>Bad value for {$varname}</> Expected boolean</>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$value = $true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
$this->options[$varname] = $value;
|
$this->options[$varname] = $value;
|
||||||
} else {
|
} else {
|
||||||
$this->output->writeln(var_export($this->options[$varname]??null,true));
|
$this->output->writeln(var_export($this->options[$varname]??null,true));
|
||||||
@ -368,4 +434,4 @@ class EnumSetting
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
138
plugins/com.noccy.pdo.shell/Shell/ShellState.php
Normal file
138
plugins/com.noccy.pdo.shell/Shell/ShellState.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SparkPlug\Com\Noccy\Pdo\Shell\Shell;
|
||||||
|
|
||||||
|
use Attribute;
|
||||||
|
use SparkPlug\Com\Noccy\Pdo\PdoResource;
|
||||||
|
use Spark\Commands\Command;
|
||||||
|
use Spark\SparkApplication;
|
||||||
|
use Symfony\Component\Console\Helper\Table;
|
||||||
|
use Symfony\Component\Console\Helper\TableSeparator;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class ShellState
|
||||||
|
{
|
||||||
|
|
||||||
|
private array $vars = [];
|
||||||
|
|
||||||
|
private array $options = [];
|
||||||
|
|
||||||
|
private SessionStorage $sessionStorage;
|
||||||
|
|
||||||
|
private PersistentStorage $persistentStorage;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->sessionStorage = new SessionStorage();
|
||||||
|
|
||||||
|
$this->persistentStorage = new PersistentStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSessionStorage(): SessionStorage
|
||||||
|
{
|
||||||
|
return $this->sessionStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPersistentStorage(): PersistentStorage
|
||||||
|
{
|
||||||
|
return $this->persistentStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(string $varname, $value)
|
||||||
|
{
|
||||||
|
$this->vars[$varname] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $varname, $default=null): mixed
|
||||||
|
{
|
||||||
|
return $this->vars[$varname] ?? $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expand(string $input): string
|
||||||
|
{
|
||||||
|
$expanded = preg_replace_callback('/(%\{(.+?)\})/', function ($m) {
|
||||||
|
$k = $m[1];
|
||||||
|
if (str_contains($k, ':')) {
|
||||||
|
[$type, $k] = explode(":", $k, 2);
|
||||||
|
} else {
|
||||||
|
$type = "var";
|
||||||
|
}
|
||||||
|
switch ($type) {
|
||||||
|
case 'var':
|
||||||
|
return $this->get($k, null);
|
||||||
|
case 'env':
|
||||||
|
return getenv($k);
|
||||||
|
}
|
||||||
|
}, $input);
|
||||||
|
return $expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionStorage implements StorageInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $data = [];
|
||||||
|
|
||||||
|
public function set(string $k, $value)
|
||||||
|
{
|
||||||
|
$this->data[$k] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $k, $default=null): mixed
|
||||||
|
{
|
||||||
|
return $this->data[$k] ?? $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function has(string $k): bool
|
||||||
|
{
|
||||||
|
return array_key_exists($k, $this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(string $k): void
|
||||||
|
{
|
||||||
|
unset($this->data[$k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class PersistentStorage implements StorageInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $data = [];
|
||||||
|
|
||||||
|
public function set(string $k, $value)
|
||||||
|
{
|
||||||
|
$this->data[$k] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $k, $default=null): mixed
|
||||||
|
{
|
||||||
|
return $this->data[$k] ?? $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function has(string $k): bool
|
||||||
|
{
|
||||||
|
return array_key_exists($k, $this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(string $k): void
|
||||||
|
{
|
||||||
|
unset($this->data[$k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StorageInterface
|
||||||
|
{
|
||||||
|
public function set(string $k, $value);
|
||||||
|
|
||||||
|
public function get(string $k, $default=null): mixed;
|
||||||
|
|
||||||
|
public function has(string $k): bool;
|
||||||
|
|
||||||
|
public function delete(string $k): void;
|
||||||
|
}
|
@ -48,7 +48,9 @@ class SparkApplication extends Application
|
|||||||
if (getenv("SPARK_PLUGINS")) {
|
if (getenv("SPARK_PLUGINS")) {
|
||||||
$this->add(new Commands\PluginsCommand());
|
$this->add(new Commands\PluginsCommand());
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!is_dir(getcwd()."/.spark")) {
|
||||||
$this->add(new Commands\InitCommand());
|
$this->add(new Commands\InitCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user