Added plugins and build tools
This commit is contained in:
		
							
								
								
									
										4
									
								
								plugins/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								plugins/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# Plugins
 | 
			
		||||
 | 
			
		||||
Install by copying or symlinking into your `.spark/plugins` directory, or whatever
 | 
			
		||||
directory you have defined to preload from.
 | 
			
		||||
							
								
								
									
										24
									
								
								plugins/com.noccy.docker/DockerBuildCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plugins/com.noccy.docker/DockerBuildCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerBuildCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("docker:build")
 | 
			
		||||
            ->setDescription("Build an image");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $config = read_config("docker.json");
 | 
			
		||||
        print_r($config);
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								plugins/com.noccy.docker/DockerCompose/Service.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								plugins/com.noccy.docker/DockerCompose/Service.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker\DockerCompose;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Service
 | 
			
		||||
{
 | 
			
		||||
    private array $service;
 | 
			
		||||
 | 
			
		||||
    private array $environment = [];
 | 
			
		||||
 | 
			
		||||
    private Stack|null $stack;
 | 
			
		||||
 | 
			
		||||
    public function __construct(array $service, ?Stack $stack)
 | 
			
		||||
    {
 | 
			
		||||
        $this->service = $service;
 | 
			
		||||
        $this->stack = $stack;
 | 
			
		||||
 | 
			
		||||
        foreach ($this->service['environment']??[] as $k=>$v) {
 | 
			
		||||
            if (is_numeric($k)) {
 | 
			
		||||
                [$k, $v] = explode("=", $v, 2);
 | 
			
		||||
            }
 | 
			
		||||
            $this->environment[$k] = $v;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getImage():?String
 | 
			
		||||
    {
 | 
			
		||||
        return $this->service['image']??null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getEnvironment(): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->environment;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								plugins/com.noccy.docker/DockerCompose/Stack.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								plugins/com.noccy.docker/DockerCompose/Stack.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker\DockerCompose;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Yaml\Yaml;
 | 
			
		||||
 | 
			
		||||
class Stack 
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    private array $compose;
 | 
			
		||||
 | 
			
		||||
    private string $version;
 | 
			
		||||
 | 
			
		||||
    private array $services;
 | 
			
		||||
 | 
			
		||||
    public function __construct(string $filename)
 | 
			
		||||
    {
 | 
			
		||||
        $this->compose = Yaml::parseFile($filename);
 | 
			
		||||
 | 
			
		||||
        $this->version = $this->compose['version']??null;
 | 
			
		||||
        $this->enumServices();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function enumServices()
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->compose['services'] as $service=>$config) {
 | 
			
		||||
            $this->services[$service] = new Service($config, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getServiceNames(): array
 | 
			
		||||
    {
 | 
			
		||||
        return array_keys($this->services);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getService(string $name): ?Service
 | 
			
		||||
    {
 | 
			
		||||
        return $this->services[$name] ?? null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										85
									
								
								plugins/com.noccy.docker/DockerDbExportCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								plugins/com.noccy.docker/DockerDbExportCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\Input;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Input\InputOption;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerDbExportCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("docker:db:export")
 | 
			
		||||
            ->setDescription("Export a database")
 | 
			
		||||
            ->addOption("mysql", null, InputOption::VALUE_NONE, "Export from a MySQL database")
 | 
			
		||||
            ->addOption("dsn", null, InputOption::VALUE_REQUIRED, "Database DSN")
 | 
			
		||||
            ->addOption("service", null, InputOption::VALUE_REQUIRED, "Service name in stack")
 | 
			
		||||
            ->addOption("database", null, InputOption::VALUE_REQUIRED, "Database name")
 | 
			
		||||
            ->addOption("output", "o", InputOption::VALUE_REQUIRED, "Output to file instead of stdout")
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $docker = get_plugin("com.noccy.docker");
 | 
			
		||||
 | 
			
		||||
        $service = $input->getOption("service");
 | 
			
		||||
        $dsn = $input->getOption("dsn");
 | 
			
		||||
        if ($service) {
 | 
			
		||||
            $stack = $docker->getComposeStack();
 | 
			
		||||
            if ($input->getOption("mysql")) {
 | 
			
		||||
                $dbtype = 'mysql';
 | 
			
		||||
            } else {
 | 
			
		||||
                $services = $stack->getServiceNames();
 | 
			
		||||
                if (!in_array($service, $services)) {
 | 
			
		||||
                    $output->writeln("<error>Invalid service {$service}. Valid are ".join(", ", $services)."</>");
 | 
			
		||||
                    return Command::INVALID;
 | 
			
		||||
                }
 | 
			
		||||
                $image = $stack->getService($service)->getImage();
 | 
			
		||||
                if (preg_match('/(mysql|mariadb)/i', $image)) {
 | 
			
		||||
                    $dbtype = 'mysql';
 | 
			
		||||
                    $env = $stack->getService($service)->getEnvironment();
 | 
			
		||||
                    $database = $env['MYSQL_DATABASE']??null;
 | 
			
		||||
                    if ($dbpass = $env['MYSQL_ROOT_PASSWORD']??null) {
 | 
			
		||||
                        $dbuser = 'root';
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $dbuser = $env['MYSQL_USER']??null;
 | 
			
		||||
                        $dbpass = $env['MYSQL_PASSWORD']??null;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    $output->writeln("<error>Unable to determine database type from service</>");
 | 
			
		||||
                    return Command::INVALID;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $database = $database ?? $input->getOption("database");
 | 
			
		||||
            if (empty($database)) {
 | 
			
		||||
                $output->writeln("<error>No --database specified</>");
 | 
			
		||||
                return Command::INVALID;
 | 
			
		||||
            }
 | 
			
		||||
            switch ($dbtype) {
 | 
			
		||||
                case 'mysql':
 | 
			
		||||
                    $cmd = sprintf("mysqldump -u%s -p%s %s", $dbuser, $dbpass, $database);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            $this->exportFromService($service, $cmd, $output);
 | 
			
		||||
        } elseif ($dsn) {
 | 
			
		||||
            $url = parse_url($dsn);
 | 
			
		||||
            if (empty($url)) {
 | 
			
		||||
                $output->writeln("<error>Bad database DSN {$dsn}. Should look like mysql://user:pass@host:port/database</>");
 | 
			
		||||
                return Command::INVALID;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function exportFromService(string $service, string $command, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $cmd = sprintf("docker-compose exec -T %s %s", $service, $command);
 | 
			
		||||
        passthru($cmd);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								plugins/com.noccy.docker/DockerDownCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plugins/com.noccy.docker/DockerDownCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerDownCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("docker:down")
 | 
			
		||||
            ->setDescription("Stop a stack or container");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $config = read_config("docker.json");
 | 
			
		||||
        print_r($config);
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								plugins/com.noccy.docker/DockerExecCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plugins/com.noccy.docker/DockerExecCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerExecCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("docker:exec")
 | 
			
		||||
            ->setDescription("Execute scripts in a docker container");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $config = read_config("docker.json");
 | 
			
		||||
        print_r($config);
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								plugins/com.noccy.docker/DockerStatusCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								plugins/com.noccy.docker/DockerStatusCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Helper\Table;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerStatusCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    const BULLET="\u{25cf}";
 | 
			
		||||
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("docker:status")
 | 
			
		||||
            ->setDescription("Show docker status");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        exec("docker-compose ps -q", $ids, $ret);
 | 
			
		||||
        if (count($ids) === 0) return Command::SUCCESS;
 | 
			
		||||
 | 
			
		||||
        exec("docker inspect ".join(" ",$ids), $out, $ret);
 | 
			
		||||
        $json = json_decode(join("", $out));
 | 
			
		||||
 | 
			
		||||
        $stack = get_plugin('com.noccy.docker')->getComposeStack();
 | 
			
		||||
 | 
			
		||||
        $table = new Table($output);
 | 
			
		||||
        $table->setStyle("box");
 | 
			
		||||
        $table->setHeaders([ "Name", "Status", "Image", "Ports" ]);
 | 
			
		||||
        foreach ($json as $container) {
 | 
			
		||||
            $startedTs = preg_replace('/(\.([0-9]+)Z)$/', '+0100', $container->State->StartedAt);
 | 
			
		||||
            $s = date_parse($startedTs);
 | 
			
		||||
            $started = mktime($s['hour'], $s['minute'], $s['second'], $s['month'], $s['day'], $s['year']) + 3600;
 | 
			
		||||
            if ($container->State->Dead) {
 | 
			
		||||
                $status = "<fg=red>".self::BULLET."</> ".$container->State->Status;
 | 
			
		||||
            } elseif ($container->State->Restarting) {
 | 
			
		||||
                $status = "<fg=yellow>".self::BULLET."</> ".$container->State->Status;
 | 
			
		||||
            } elseif ($container->State->Running) {
 | 
			
		||||
                $elapsed = time() - $started;
 | 
			
		||||
                if ($elapsed > 60) {
 | 
			
		||||
                    $em = floor($elapsed / 60);
 | 
			
		||||
                    $es = $elapsed - ($em * 60);
 | 
			
		||||
                    if ($em>60)  {
 | 
			
		||||
                        $eh = floor($em / 60);
 | 
			
		||||
                        $em = $em - ($eh * 60);
 | 
			
		||||
                        $elapsed = sprintf("%dh%dm%ds", $eh, $em, $es);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $elapsed = sprintf("%dm%ds", $em, $es);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    $elapsed = sprintf("%ds", $elapsed);
 | 
			
		||||
                }
 | 
			
		||||
                $status = "<fg=green>".self::BULLET."</> ".$container->State->Status." (<fg=green>{$elapsed}</>)";
 | 
			
		||||
            } else {
 | 
			
		||||
                $status = "<fg=red>".self::BULLET."</> ".$container->State->Status;
 | 
			
		||||
            }
 | 
			
		||||
            $ports = $container->Config->ExposedPorts??[];
 | 
			
		||||
            $ports = array_keys((array)$ports);
 | 
			
		||||
            $table->addRow([ $container->Name, $status, $container->Config->Image, join(", ", $ports) ]);
 | 
			
		||||
        }
 | 
			
		||||
        $table->render();
 | 
			
		||||
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								plugins/com.noccy.docker/DockerUpCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								plugins/com.noccy.docker/DockerUpCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerUpCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("docker:up")
 | 
			
		||||
            ->setDescription("Start a stack or container");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $config = read_config("docker.json");
 | 
			
		||||
        print_r($config);
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								plugins/com.noccy.docker/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								plugins/com.noccy.docker/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
<?php // "name":"Docker plugin for SparkPlug", "author":"Noccy"
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Docker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use SparkPlug\Com\Noccy\Docker\DockerCompose\Stack;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class DockerPlug extends SparkPlug
 | 
			
		||||
{
 | 
			
		||||
    private array $compose = [];
 | 
			
		||||
 | 
			
		||||
    private Stack $composeStack;
 | 
			
		||||
 | 
			
		||||
    public function load()
 | 
			
		||||
    {
 | 
			
		||||
        $config = read_config("docker.json");
 | 
			
		||||
        $docker = $config['docker']??[];
 | 
			
		||||
 | 
			
		||||
        $hasCompose = array_key_exists('compose', $docker);
 | 
			
		||||
        $hasBuild = array_key_exists('build', $docker);
 | 
			
		||||
 | 
			
		||||
        if ($hasCompose) {
 | 
			
		||||
            $this->compose = $docker['compose'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($hasCompose || $hasBuild) {
 | 
			
		||||
            register_command(new DockerUpCommand);
 | 
			
		||||
            register_command(new DockerDownCommand);
 | 
			
		||||
            register_command(new DockerStatusCommand);
 | 
			
		||||
        }
 | 
			
		||||
        if ($hasBuild) {
 | 
			
		||||
            register_command(new DockerBuildCommand);
 | 
			
		||||
            register_command(new DockerExecCommand);
 | 
			
		||||
        }
 | 
			
		||||
        register_command(new DockerDbExportCommand);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getComposeStack(): ?Stack
 | 
			
		||||
    {
 | 
			
		||||
        $base = $this->getProjectDirectory();
 | 
			
		||||
        if (empty($this->composeStack)) {
 | 
			
		||||
            $composeFile = $base . "/" . ($this->compose['file']??'docker-compose.yml');
 | 
			
		||||
            $this->composeStack = new Stack($composeFile);
 | 
			
		||||
        }
 | 
			
		||||
        return $this->composeStack;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//if (file_exists(get_environment()->getConfigDirectory()."/maker.json")) {
 | 
			
		||||
register_plugin("com.noccy.docker", new DockerPlug());
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										73
									
								
								plugins/com.noccy.git/GitIgnoreCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								plugins/com.noccy.git/GitIgnoreCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Git;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
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 GitIgnoreCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setName("git:ignore")
 | 
			
		||||
            ->setDescription("List, add or remove paths from gits ignorelists")
 | 
			
		||||
            ->addOption("local","l",InputOption::VALUE_NONE,"Use the local ignore rather than .gitignore")
 | 
			
		||||
            ->addOption("add","a",InputOption::VALUE_NONE,"Add a pattern")
 | 
			
		||||
            ->addOption("remove","r",InputOption::VALUE_NONE,"Attempt to remove a pattern")
 | 
			
		||||
            ->addArgument("pattern", InputArgument::OPTIONAL, "Pattern to add or remove")
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $local = $input->getOption("local");
 | 
			
		||||
        $root = $this->getEnvironment()->getProjectDirectory();
 | 
			
		||||
        $file = $root . (!$local ? "/.gitignore" : "/.git/info/exclude");
 | 
			
		||||
        $pattern = $input->getArgument("pattern");
 | 
			
		||||
 | 
			
		||||
        if (empty($pattern)) {
 | 
			
		||||
            if (file_exists($file)) {
 | 
			
		||||
                $ignores = file($file, FILE_IGNORE_NEW_LINES);
 | 
			
		||||
                foreach ($ignores as $ignore) {
 | 
			
		||||
                    if (str_starts_with(trim($ignore),'#')) {
 | 
			
		||||
                        $output->writeln("<fg=green>".$ignore."</>");
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $output->writeln("<fg=white>".$ignore."</>");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return Command::SUCCESS;
 | 
			
		||||
            }
 | 
			
		||||
            $output->writeln("<info>Empty list</>");
 | 
			
		||||
            return Command::SUCCESS;
 | 
			
		||||
        } elseif ($input->getOption("add") && $pattern) {
 | 
			
		||||
            if (file_exists($file)) {
 | 
			
		||||
                $ignores = file($file, FILE_IGNORE_NEW_LINES);
 | 
			
		||||
            } else {
 | 
			
		||||
                $ignores = [];
 | 
			
		||||
            }
 | 
			
		||||
            array_push($ignores, $pattern);
 | 
			
		||||
            file_put_contents($file, join("\n", $ignores));
 | 
			
		||||
            $output->writeln("<info>Updated {$file}</>");
 | 
			
		||||
            return Command::SUCCESS;
 | 
			
		||||
        } elseif ($input->getOption("remove") && $pattern) {
 | 
			
		||||
            if (file_exists($file)) {
 | 
			
		||||
                $ignores = file($file, FILE_IGNORE_NEW_LINES);
 | 
			
		||||
                $ignores = array_filter($ignores, function ($v) use ($pattern) { 
 | 
			
		||||
                    return $v != $pattern; 
 | 
			
		||||
                });
 | 
			
		||||
                $output->writeln("<info>Updated {$file}</>");
 | 
			
		||||
                file_put_contents($file, join("\n", $ignores));
 | 
			
		||||
                return Command::SUCCESS;
 | 
			
		||||
            }
 | 
			
		||||
            $output->writeln("<info>Not updating non-existing file {$file}</>");
 | 
			
		||||
            return Command::SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $output->writeln("<error>Expected no pattern, --add pattern or --remove pattern</>");
 | 
			
		||||
        return Command::INVALID;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								plugins/com.noccy.git/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								plugins/com.noccy.git/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
<?php // "name":"Git plugin for SparkPlug", "author":"Noccy"
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Git;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class GitPlug extends SparkPlug
 | 
			
		||||
{
 | 
			
		||||
    public function load()
 | 
			
		||||
    {
 | 
			
		||||
        $root = $this->getProjectDirectory();
 | 
			
		||||
        if (!file_exists($root."/.git")) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        register_command(new GitIgnoreCommand());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//if (file_exists(get_environment()->getConfigDirectory()."/maker.json")) {
 | 
			
		||||
register_plugin("com.noccy.git", new GitPlug());
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										42
									
								
								plugins/com.noccy.maker/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								plugins/com.noccy.maker/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
<?php // "name":"Build stuff from stuff", "author":"Noccy"
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Maker;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
class MakerPlug extends SparkPlug
 | 
			
		||||
{
 | 
			
		||||
    public function load()
 | 
			
		||||
    {
 | 
			
		||||
        $config = json_decode(file_get_contents(get_environment()->getConfigDirectory()."/maker.json"), true);
 | 
			
		||||
        foreach ($config as $rule=>$info) {
 | 
			
		||||
            if (str_starts_with($rule, '@')) {
 | 
			
		||||
                $rule = substr($rule, 1);
 | 
			
		||||
                register_command(new class($rule) extends Command {
 | 
			
		||||
                    private $rule;
 | 
			
		||||
                    public function __construct($rule)
 | 
			
		||||
                    {
 | 
			
		||||
                        $this->rule = $rule;
 | 
			
		||||
                        parent::__construct();
 | 
			
		||||
                    }
 | 
			
		||||
                    protected function configure()
 | 
			
		||||
                    {
 | 
			
		||||
                        $this->setName("make:{$this->rule}");
 | 
			
		||||
                        $this->setDescription("Run the {$this->rule} maker task");
 | 
			
		||||
                    }
 | 
			
		||||
                    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
                    {
 | 
			
		||||
                        
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (file_exists(get_environment()->getConfigDirectory()."/maker.json")) {
 | 
			
		||||
    register_plugin("com.noccy.maker", new MakerPlug());
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								plugins/com.noccy.pdo/PdoExecCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								plugins/com.noccy.pdo/PdoExecCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Pdo;
 | 
			
		||||
 | 
			
		||||
use Spark\Commands\Command;
 | 
			
		||||
use Symfony\Component\Console\Helper\Table;
 | 
			
		||||
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 PdoExecCommand extends Command {
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $source = $input->getOption("res");
 | 
			
		||||
        $sourcePdo = get_resource($source)->getPDO();
 | 
			
		||||
        if (!$sourcePdo) {
 | 
			
		||||
            $output->writeln("<error>Invalid resource: {$source}</>");
 | 
			
		||||
            return Command::INVALID;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $query = $input->getArgument('query');
 | 
			
		||||
 | 
			
		||||
        $stmt = $sourcePdo->prepare($query);
 | 
			
		||||
        $stmt->execute();
 | 
			
		||||
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
    protected function configure() {
 | 
			
		||||
        $this->setName("pdo:exec");
 | 
			
		||||
        $this->setDescription("Run a query without returning data");
 | 
			
		||||
        $this->addOption("res", "r", InputOption::VALUE_REQUIRED, "Resource to query", "db");
 | 
			
		||||
        $this->addArgument("query", InputArgument::REQUIRED, "SQL query to execute");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										85
									
								
								plugins/com.noccy.pdo/PdoQueryCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								plugins/com.noccy.pdo/PdoQueryCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Pdo;
 | 
			
		||||
 | 
			
		||||
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 PdoQueryCommand extends Command {
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $source = $input->getOption("res");
 | 
			
		||||
        $sourcePdo = get_resource($source)->getPDO();
 | 
			
		||||
        if (!$sourcePdo) {
 | 
			
		||||
            $output->writeln("<error>Invalid resource: {$source}</>");
 | 
			
		||||
            return Command::INVALID;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $box = $input->getOption('box');
 | 
			
		||||
        $query = $input->getArgument('query');
 | 
			
		||||
        $vert = $input->getOption("vertical");
 | 
			
		||||
        $unserialize = $input->getOption("unserialize");
 | 
			
		||||
 | 
			
		||||
        $stmt = $sourcePdo->query($query);
 | 
			
		||||
        $stmt->execute();
 | 
			
		||||
 | 
			
		||||
        $table = new Table($output);
 | 
			
		||||
        $table->setStyle($box?"box":"compact");
 | 
			
		||||
        $hasColumns = false;
 | 
			
		||||
        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
 | 
			
		||||
            if (!$hasColumns) {
 | 
			
		||||
                if ($vert) {
 | 
			
		||||
                    $table->setHeaders([ "Field", "VarType", "Value" ]);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $table->setHeaders(array_keys($row));
 | 
			
		||||
                }
 | 
			
		||||
                $hasColumns = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                if ($vert) {
 | 
			
		||||
                    if ($box) {
 | 
			
		||||
                        $table->addRow(new TableSeparator());
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $table->addRow(["","","-----"]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if ($vert) {
 | 
			
		||||
                foreach ($row as $k=>$v) {
 | 
			
		||||
                    $vv = $v;
 | 
			
		||||
                    if ($unserialize) {
 | 
			
		||||
                        $j = @json_decode($v);
 | 
			
		||||
                        $p = @unserialize($v);
 | 
			
		||||
                        if ($j) {
 | 
			
		||||
                            $v = $j;
 | 
			
		||||
                            $vv = json_encode($v, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 | 
			
		||||
                        } elseif ($p) {
 | 
			
		||||
                            $v = $p;
 | 
			
		||||
                            $vv = json_encode($p, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    $table->addRow([ $k, gettype($v), $vv ]);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                $table->addRow($row);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $table->render();
 | 
			
		||||
 | 
			
		||||
        return Command::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
    protected function configure() {
 | 
			
		||||
        $this->setName("pdo:query");
 | 
			
		||||
        $this->setDescription("Run a query against a defined PDO connection");
 | 
			
		||||
        $this->addOption("res", "r", InputOption::VALUE_REQUIRED, "Resource to query", "db");
 | 
			
		||||
        $this->addOption("vertical", "l", InputOption::VALUE_NONE, "Print result as rows instead of columns");
 | 
			
		||||
        $this->addOption("box", null, InputOption::VALUE_NONE, "Use boxed table");
 | 
			
		||||
        $this->addOption("unserialize", "u", InputOption::VALUE_NONE, "Attempt to unserialize serialized data");
 | 
			
		||||
        $this->addArgument("query", InputArgument::REQUIRED, "SQL query to execute");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										59
									
								
								plugins/com.noccy.pdo/PdoResource.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								plugins/com.noccy.pdo/PdoResource.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Pdo;
 | 
			
		||||
 | 
			
		||||
use Spark\Resource\ResourceType;
 | 
			
		||||
use PDO;
 | 
			
		||||
 | 
			
		||||
class PdoResource extends ResourceType
 | 
			
		||||
{
 | 
			
		||||
    private PDO|null $pdo = null;
 | 
			
		||||
 | 
			
		||||
    private array $options;
 | 
			
		||||
 | 
			
		||||
    public function __construct(array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $this->options = $options;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createFromURI(string $uri)
 | 
			
		||||
    {
 | 
			
		||||
        $uris = parse_url($uri);
 | 
			
		||||
        $username = $uris['user']??null;
 | 
			
		||||
        $password = $uris['pass']??null;
 | 
			
		||||
        
 | 
			
		||||
        switch ($uris['scheme']??null) {
 | 
			
		||||
            case 'mysql':
 | 
			
		||||
                $database = ltrim($uris['path']??null, '/');
 | 
			
		||||
                $dsn = sprintf("mysql:host=%s;port=%d;dbname=%s", $uris['host']??'127.0.0.1', $uris['port']??3306, $database);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'sqlite':
 | 
			
		||||
                $database = $uris['path']??':memory:';
 | 
			
		||||
                $dsn = sprintf("sqlite:%s", $database);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                fprintf(STDERR, "error: Unable to create PDO resource from URI, invalid type %s\n", $uris['scheme']??null);
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->pdo = new \PDO($dsn, $username, $password);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getPDO(): ?PDO
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->pdo) {
 | 
			
		||||
            $this->createFromURI($this->options['uri']);
 | 
			
		||||
        }
 | 
			
		||||
        return $this->pdo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function info()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->options['uri'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createTable(string $name, array $columns, bool $ifNotExists=false)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								plugins/com.noccy.pdo/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								plugins/com.noccy.pdo/sparkplug.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
<?php // "name":"Access databases through PDO", "author":"Noccy"
 | 
			
		||||
 | 
			
		||||
namespace SparkPlug\Com\Noccy\Pdo;
 | 
			
		||||
 | 
			
		||||
use SparkPlug;
 | 
			
		||||
 | 
			
		||||
class PdoPlugin extends SparkPlug {
 | 
			
		||||
    public function load()
 | 
			
		||||
    {
 | 
			
		||||
        register_command(new PdoQueryCommand());
 | 
			
		||||
        register_command(new PdoExecCommand());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
register_plugin("com.noccy.pdo", new PdoPlugin);
 | 
			
		||||
register_resource_type("pdo", PdoResource::class);
 | 
			
		||||
		Reference in New Issue
	
	Block a user