Added PDO shell plugin
This commit is contained in:
parent
1125ccb82d
commit
16753e1892
@ -10,6 +10,8 @@ directory you have defined to preload from.
|
||||
- `com.noccy.pdo`: Interact with PDO from the command line. Registers a custom
|
||||
resource type, so database connections can be defined in advance to be available
|
||||
to scripts and more.
|
||||
- `com.noccy.pdo.shell`: An interactive shell for querying PDO resouces. No more
|
||||
forgetting passwords or complex commands to dive into a SQL shell!
|
||||
- `com.noccy.watcher`: A plugin too watch files and invoke scripts or commands when
|
||||
a modification is detected. This can be used to compile scss/less or to generate
|
||||
other resources as files are changed.
|
||||
|
29
plugins/com.noccy.pdo.shell/PdoShellCommand.php
Normal file
29
plugins/com.noccy.pdo.shell/PdoShellCommand.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace SparkPlug\Com\Noccy\Pdo\Shell;
|
||||
|
||||
use Spark\Commands\Command;
|
||||
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 PdoShellCommand extends Command {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName("pdo:shell");
|
||||
$this->setDescription("Launch an interactive PDO shell");
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$shell = new Shell\PdoShell($output);
|
||||
$shell->run();
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
225
plugins/com.noccy.pdo.shell/Shell/PdoShell.php
Normal file
225
plugins/com.noccy.pdo.shell/Shell/PdoShell.php
Normal file
@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
namespace SparkPlug\Com\Noccy\Pdo\Shell\Shell;
|
||||
|
||||
use SparkPlug\Com\Noccy\Pdo\PdoResource;
|
||||
use Spark\Commands\Command;
|
||||
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 PdoShell {
|
||||
|
||||
private OutputInterface $output;
|
||||
|
||||
private string $resource = "db";
|
||||
|
||||
private ?PdoResource $db = null;
|
||||
|
||||
private array $vars = [];
|
||||
|
||||
private bool $running = false;
|
||||
|
||||
private array $options = [];
|
||||
|
||||
private array $defaultOptions = [
|
||||
'output' => 'table',
|
||||
'table.maxwidth' => 40,
|
||||
];
|
||||
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
$this->options = $this->defaultOptions;
|
||||
}
|
||||
|
||||
private function promptForCommand()
|
||||
{
|
||||
$prompt = sprintf("PDO:[%s%s]> ", $this->resource, $this->db?"":"*");
|
||||
$input = readline($prompt);
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
private function parseCommand(string $input): array
|
||||
{
|
||||
$parsed = str_getcsv($input, ' ', '"');
|
||||
$parsed = array_map([$this,"expand"], $parsed);
|
||||
$command = array_shift($parsed);
|
||||
return [
|
||||
strtolower($command),
|
||||
$parsed
|
||||
];
|
||||
}
|
||||
|
||||
private function expand(string $string): string
|
||||
{
|
||||
return $string;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
if ($this->running == true) return;
|
||||
|
||||
$this->running = true;
|
||||
while ($this->running) {
|
||||
|
||||
$input = $this->promptForCommand();
|
||||
if (!trim($input)) {
|
||||
continue;
|
||||
}
|
||||
readline_add_history($input);
|
||||
if (str_starts_with($input, ".")) {
|
||||
[$cmd,$args] = $this->parseCommand($input);
|
||||
$this->handleCommand($cmd, $args);
|
||||
} else {
|
||||
$this->doQuery($input, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function handleCommand(string $command, array $args)
|
||||
{
|
||||
|
||||
switch ($command) {
|
||||
case '.select':
|
||||
$this->doSelectCommand($args);
|
||||
break;
|
||||
case '.set':
|
||||
$this->doSetCommand($args);
|
||||
break;
|
||||
case '.var':
|
||||
$this->doVarCommand($args);
|
||||
break;
|
||||
case '.help':
|
||||
$this->doHelpCommand($args);
|
||||
break;
|
||||
case '.exit':
|
||||
$this->running = false;
|
||||
break;;
|
||||
default:
|
||||
$this->output->writeln("<error>Bad command. Try .help</>");
|
||||
}
|
||||
}
|
||||
|
||||
private function doHelpCommand(array $args)
|
||||
{
|
||||
$cmds = [
|
||||
'.help' => "Show this help",
|
||||
'.select RES' => "Select the database resource to query",
|
||||
'.set [KEY [VALUE]]' => "Set a configuration value",
|
||||
'.var [NAME [VALUE]]' => "Set a variable, or show variable value",
|
||||
'.exit' => "Exit the shell",
|
||||
'SQL' => "Run SQL against the database",
|
||||
];
|
||||
foreach ($cmds as $cmd=>$info) {
|
||||
$this->output->writeln(" <options=bold>{$cmd}</> - <info>{$info}</>");
|
||||
}
|
||||
}
|
||||
|
||||
private function doSetCommand(array $args)
|
||||
{
|
||||
$varname = array_shift($args);
|
||||
$value = array_shift($args);
|
||||
|
||||
if (empty($varname)) {
|
||||
foreach ($this->options as $var=>$value) {
|
||||
$this->output->writeln("<info>{$var}</>: <comment>".var_export($value,true)."</>");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($value !== null) {
|
||||
if (!array_key_exists($varname, $this->options)) {
|
||||
$this->output->writeln("<error>No such option {$varname}</>");
|
||||
return;
|
||||
}
|
||||
$this->options[$varname] = $args;
|
||||
} else {
|
||||
$this->output->writeln(var_export($this->options[$varname]??null,true));
|
||||
}
|
||||
}
|
||||
|
||||
private function doSelectCommand(array $args)
|
||||
{
|
||||
$name = array_shift($args);
|
||||
$res = get_resource($name);
|
||||
if ($res instanceof PdoResource) {
|
||||
$this->db = $res;
|
||||
$this->resource = $name;
|
||||
$this->output->writeln("<fg=green>Seleced {$name}</>");
|
||||
} else {
|
||||
$this->output->writeln("<error>Invalid resource {$name}</>");
|
||||
}
|
||||
}
|
||||
|
||||
private function doVarCommand(array $args)
|
||||
{
|
||||
$varname = array_shift($args);
|
||||
|
||||
if (empty($varname)) {
|
||||
foreach ($this->vars as $var=>$value) {
|
||||
$this->output->writeln("<info>{$var}</>=<comment>".var_export($value,true)."</>");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($args) > 1) {
|
||||
$this->vars[$varname] = $args;
|
||||
} elseif (count($args) > 0) {
|
||||
$this->vars[$varname] = array_shift($args);
|
||||
} else {
|
||||
$this->output->writeln(var_export($this->vars[$varname]??null,true));
|
||||
}
|
||||
}
|
||||
|
||||
private function doQuery(string $query, array $params=[])
|
||||
{
|
||||
if (!$this->db) {
|
||||
$this->output->writeln("<error>No database resource selected</>");
|
||||
return;
|
||||
}
|
||||
$pdo = $this->db->getPDO();
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare($query);
|
||||
$stmt->execute($params);
|
||||
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} catch (\PDOException $e) {
|
||||
$this->output->writeln("<error>{$e->getMessage()}</>");
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($this->options['output']) {
|
||||
case 'table':
|
||||
$this->dumpQueryTable($res);
|
||||
break;
|
||||
case 'vertical':
|
||||
$this->dumpQueryVertical($res);
|
||||
break;
|
||||
default:
|
||||
print_r($res);
|
||||
}
|
||||
}
|
||||
|
||||
private function dumpQueryTable(array $res)
|
||||
{
|
||||
if (count($res) == 0) return;
|
||||
$table = new Table($this->output);
|
||||
$table->setHeaders(array_keys(reset($res)));
|
||||
|
||||
$max = $this->options['table.maxwidth'];
|
||||
|
||||
foreach ($res as $row) {
|
||||
$table->addRow(array_map(function ($v) use ($max) {
|
||||
return strlen($v)>$max ? substr($v, 0, $max)."..." : $v;
|
||||
}, $row));
|
||||
}
|
||||
$table->render();
|
||||
}
|
||||
|
||||
}
|
||||
|
14
plugins/com.noccy.pdo.shell/sparkplug.php
Normal file
14
plugins/com.noccy.pdo.shell/sparkplug.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php // "name":"Interactive PDO Shell", "author":"Noccy"
|
||||
|
||||
namespace SparkPlug\Com\Noccy\Pdo\Shell;
|
||||
|
||||
use SparkPlug;
|
||||
|
||||
class PdoShellPlugin extends SparkPlug {
|
||||
public function load()
|
||||
{
|
||||
register_command(new PdoShellCommand());
|
||||
}
|
||||
}
|
||||
|
||||
register_plugin("com.noccy.pdo.shell", new PdoShellPlugin);
|
Loading…
Reference in New Issue
Block a user