[core] replace quarter-arsed CLI interface with Symfony Console
This commit is contained in:
parent
f3b292f2ea
commit
ec35cace6a
21 changed files with 983 additions and 911 deletions
|
@ -51,7 +51,8 @@
|
|||
"psr/simple-cache": "^1.0",
|
||||
"sabre/cache": "^2.0.1",
|
||||
"naroga/redis-cache": "dev-master",
|
||||
"aws/aws-sdk-php": "^3.294"
|
||||
"aws/aws-sdk-php": "^3.294",
|
||||
"symfony/console": "6.4.x-dev"
|
||||
},
|
||||
|
||||
"require-dev" : {
|
||||
|
|
1136
composer.lock
generated
1136
composer.lock
generated
File diff suppressed because it is too large
Load diff
64
core/cli_app.php
Normal file
64
core/cli_app.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Input\{ArgvInput,InputOption,InputDefinition,InputInterface};
|
||||
use Symfony\Component\Console\Output\{OutputInterface,ConsoleOutput};
|
||||
|
||||
class CliApp extends \Symfony\Component\Console\Application
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('Shimmie', VERSION);
|
||||
}
|
||||
|
||||
protected function getDefaultInputDefinition(): InputDefinition
|
||||
{
|
||||
$definition = parent::getDefaultInputDefinition();
|
||||
$definition->addOption(new InputOption(
|
||||
'--user',
|
||||
'-u',
|
||||
InputOption::VALUE_NONE,
|
||||
'Log in as the given user'
|
||||
));
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
public function run(InputInterface $input = null, OutputInterface $output = null): int
|
||||
{
|
||||
global $user;
|
||||
|
||||
$input ??= new ArgvInput();
|
||||
$output ??= new ConsoleOutput();
|
||||
|
||||
if ($input->hasParameterOption(['--user', '-u'])) {
|
||||
$user = User::by_name($input->getOption('user'));
|
||||
if (is_null($user)) {
|
||||
die("Unknown user");
|
||||
} else {
|
||||
send_event(new UserLoginEvent($user));
|
||||
}
|
||||
}
|
||||
|
||||
$log_level = SCORE_LOG_WARNING;
|
||||
if (true === $input->hasParameterOption(['--quiet', '-q'], true)) {
|
||||
$log_level = SCORE_LOG_ERROR;
|
||||
} else {
|
||||
if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) {
|
||||
$log_level = SCORE_LOG_DEBUG;
|
||||
} elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) {
|
||||
$log_level = SCORE_LOG_DEBUG;
|
||||
} elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) {
|
||||
$log_level = SCORE_LOG_INFO;
|
||||
}
|
||||
}
|
||||
if (!defined("CLI_LOG_LEVEL")) {
|
||||
define("CLI_LOG_LEVEL", $log_level);
|
||||
}
|
||||
|
||||
return parent::run($input, $output);
|
||||
}
|
||||
}
|
|
@ -200,73 +200,12 @@ class PageRequestEvent extends Event
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sent when index.php is called from the command line
|
||||
*/
|
||||
class CommandEvent extends Event
|
||||
class CliGenEvent extends Event
|
||||
{
|
||||
public string $cmd = "help";
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public array $args = [];
|
||||
|
||||
/**
|
||||
* @param string[] $args
|
||||
*/
|
||||
public function __construct(array $args)
|
||||
{
|
||||
public function __construct(
|
||||
public \Symfony\Component\Console\Application $app
|
||||
) {
|
||||
parent::__construct();
|
||||
global $user;
|
||||
|
||||
$opts = [];
|
||||
$log_level = SCORE_LOG_WARNING;
|
||||
$arg_count = count($args);
|
||||
|
||||
for ($i = 1; $i < $arg_count; $i++) {
|
||||
switch ($args[$i]) {
|
||||
case '-u':
|
||||
$user = User::by_name($args[++$i]);
|
||||
if (is_null($user)) {
|
||||
die("Unknown user");
|
||||
} else {
|
||||
send_event(new UserLoginEvent($user));
|
||||
}
|
||||
break;
|
||||
case '-q':
|
||||
$log_level += 10;
|
||||
break;
|
||||
case '-v':
|
||||
$log_level -= 10;
|
||||
break;
|
||||
default:
|
||||
$opts[] = $args[$i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined("CLI_LOG_LEVEL")) {
|
||||
define("CLI_LOG_LEVEL", $log_level);
|
||||
}
|
||||
|
||||
if (count($opts) > 0) {
|
||||
$this->cmd = $opts[0];
|
||||
$this->args = array_slice($opts, 1);
|
||||
} else {
|
||||
print "\n";
|
||||
print "Usage: php {$args[0]} [flags] [command]\n";
|
||||
print "\n";
|
||||
print "Flags:\n";
|
||||
print "\t-u [username]\n";
|
||||
print "\t\tLog in as the specified user\n";
|
||||
print "\t-q / -v\n";
|
||||
print "\t\tBe quieter / more verbose\n";
|
||||
print "\t\tScale is debug - info - warning - error - critical\n";
|
||||
print "\t\tDefault is to show warnings and above\n";
|
||||
print "\n";
|
||||
print "Currently known commands:\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Sent when the admin page is ready to be added to
|
||||
*/
|
||||
|
@ -65,67 +69,90 @@ class AdminPage extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tget-page <query string>\n";
|
||||
print "\t\teg 'get-page post/list'\n\n";
|
||||
print "\tpost-page <query string> <urlencoded params>\n";
|
||||
print "\t\teg 'post-page ip_ban/delete id=1'\n\n";
|
||||
print "\tget-token\n";
|
||||
print "\t\tget a CSRF auth token\n\n";
|
||||
print "\tregen-thumb <id / hash>\n";
|
||||
print "\t\tregenerate a thumbnail\n\n";
|
||||
print "\tcache [get|set|del] [key] <value>\n";
|
||||
print "\t\teg 'cache get config'\n\n";
|
||||
}
|
||||
if ($event->cmd == "get-page") {
|
||||
global $page;
|
||||
$_SERVER['REQUEST_URI'] = $event->args[0];
|
||||
if (isset($event->args[1])) {
|
||||
parse_str($event->args[1], $_GET);
|
||||
$_SERVER['REQUEST_URI'] .= "?" . $event->args[1];
|
||||
}
|
||||
send_event(new PageRequestEvent("GET", $event->args[0]));
|
||||
$page->display();
|
||||
}
|
||||
if ($event->cmd == "post-page") {
|
||||
global $page;
|
||||
if (isset($event->args[1])) {
|
||||
parse_str($event->args[1], $_POST);
|
||||
}
|
||||
send_event(new PageRequestEvent("POST", $event->args[0]));
|
||||
$page->display();
|
||||
}
|
||||
if ($event->cmd == "get-token") {
|
||||
global $user;
|
||||
print($user->get_auth_token());
|
||||
}
|
||||
if ($event->cmd == "regen-thumb") {
|
||||
$uid = $event->args[0];
|
||||
$image = Image::by_id_or_hash($uid);
|
||||
if ($image) {
|
||||
send_event(new ThumbnailGenerationEvent($image, true));
|
||||
} else {
|
||||
print("No post with ID '$uid'\n");
|
||||
}
|
||||
}
|
||||
if ($event->cmd == "cache") {
|
||||
global $cache;
|
||||
$cmd = $event->args[0];
|
||||
$key = $event->args[1];
|
||||
switch ($cmd) {
|
||||
case "get":
|
||||
var_export($cache->get($key));
|
||||
break;
|
||||
case "set":
|
||||
$cache->set($key, $event->args[2], 60);
|
||||
break;
|
||||
case "del":
|
||||
$cache->delete($key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$event->app->register('page:get')
|
||||
->addArgument('query', InputArgument::REQUIRED)
|
||||
->addArgument('args', InputArgument::OPTIONAL)
|
||||
->setDescription('Get a page, eg /post/list')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $page;
|
||||
$query = $input->getArgument('query');
|
||||
$args = $input->getArgument('args');
|
||||
$_SERVER['REQUEST_URI'] = $query;
|
||||
if (!is_null($args)) {
|
||||
parse_str($args, $_GET);
|
||||
$_SERVER['REQUEST_URI'] .= "?" . $args;
|
||||
}
|
||||
send_event(new PageRequestEvent("GET", $query));
|
||||
$page->display();
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('page:post')
|
||||
->addArgument('query', InputArgument::REQUIRED)
|
||||
->addArgument('args', InputArgument::OPTIONAL)
|
||||
->setDescription('Post a page, eg ip_ban/delete id=1')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $page;
|
||||
$query = $input->getArgument('query');
|
||||
$args = $input->getArgument('args');
|
||||
global $page;
|
||||
if (!is_null($args)) {
|
||||
parse_str($args, $_POST);
|
||||
}
|
||||
send_event(new PageRequestEvent("POST", $query));
|
||||
$page->display();
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('get-token')
|
||||
->setDescription('Get a CSRF token')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $user;
|
||||
$output->writeln($user->get_auth_token());
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('regen-thumb')
|
||||
->addArgument('id_or_hash', InputArgument::REQUIRED)
|
||||
->setDescription("Regenerate a post's thumbnail")
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$uid = $input->getArgument('id_or_hash');
|
||||
$image = Image::by_id_or_hash($uid);
|
||||
if ($image) {
|
||||
send_event(new ThumbnailGenerationEvent($image, true));
|
||||
} else {
|
||||
$output->writeln("No post with ID '$uid'\n");
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('cache:get')
|
||||
->addArgument('key', InputArgument::REQUIRED)
|
||||
->setDescription("Get a cache value")
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $cache;
|
||||
$key = $input->getArgument('key');
|
||||
$output->writeln(var_export($cache->get($key), true));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('cache:set')
|
||||
->addArgument('key', InputArgument::REQUIRED)
|
||||
->addArgument('value', InputArgument::REQUIRED)
|
||||
->setDescription("Set a cache value")
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $cache;
|
||||
$key = $input->getArgument('key');
|
||||
$value = $input->getArgument('value');
|
||||
$cache->set($key, $value, 60);
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('cache:del')
|
||||
->addArgument('key', InputArgument::REQUIRED)
|
||||
->setDescription("Delete a cache value")
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $cache;
|
||||
$key = $input->getArgument('key');
|
||||
$cache->delete($key);
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onAdminBuilding(AdminBuildingEvent $event)
|
||||
|
|
|
@ -23,19 +23,4 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
|
|||
$this->assertEquals(200, $page->code);
|
||||
$this->assertEquals("Admin Tools", $page->title);
|
||||
}
|
||||
|
||||
public function testCommands()
|
||||
{
|
||||
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
|
||||
ob_start();
|
||||
send_event(new CommandEvent(["index.php", "help"]));
|
||||
send_event(new CommandEvent(["index.php", "get-page", "post/list"]));
|
||||
send_event(new CommandEvent(["index.php", "post-page", "post/list", "foo=bar"]));
|
||||
send_event(new CommandEvent(["index.php", "get-token"]));
|
||||
send_event(new CommandEvent(["index.php", "regen-thumb", "42"]));
|
||||
ob_end_clean();
|
||||
|
||||
// don't crash
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class BulkActionException extends SCoreException
|
||||
{
|
||||
}
|
||||
|
@ -97,22 +101,20 @@ class BulkActions extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tbulk-action <action> <query>\n";
|
||||
print "\t\tperform an action on all query results\n\n";
|
||||
}
|
||||
if ($event->cmd == "bulk-action") {
|
||||
if (count($event->args) < 2) {
|
||||
return;
|
||||
}
|
||||
$action = $event->args[0];
|
||||
$query = $event->args[1];
|
||||
$items = $this->yield_search_results($query);
|
||||
log_info("bulk_actions", "Performing $action on {$event->args[1]}");
|
||||
send_event(new BulkActionEvent($event->args[0], $items));
|
||||
}
|
||||
$event->app->register('bulk-action')
|
||||
->addArgument('action', InputArgument::REQUIRED)
|
||||
->addArgument('query', InputArgument::REQUIRED)
|
||||
->setDescription('Perform a bulk action on a given query')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$action = $input->getArgument('action');
|
||||
$query = $input->getArgument('query');
|
||||
$items = $this->yield_search_results($query);
|
||||
log_info("bulk_actions", "Performing $action on $query");
|
||||
send_event(new BulkActionEvent($action, $items));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onBulkAction(BulkActionEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class BulkAddEvent extends Event
|
||||
{
|
||||
public string $dir;
|
||||
|
@ -35,25 +39,23 @@ class BulkAdd extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tbulk-add [directory]\n";
|
||||
print "\t\tImport this directory\n\n";
|
||||
}
|
||||
if ($event->cmd == "bulk-add") {
|
||||
if (count($event->args) == 1) {
|
||||
$bae = send_event(new BulkAddEvent($event->args[0]));
|
||||
$event->app->register('bulk-add')
|
||||
->addArgument('directory', InputArgument::REQUIRED)
|
||||
->setDescription('Import a directory of images')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$dir = $input->getArgument('directory');
|
||||
$bae = send_event(new BulkAddEvent($dir));
|
||||
foreach ($bae->results as $r) {
|
||||
if(is_a($r, UploadError::class)) {
|
||||
print($r->name." failed: ".$r->error."\n");
|
||||
$output->writeln($r->name." failed: ".$r->error);
|
||||
} else {
|
||||
print($r->name." ok\n");
|
||||
$output->writeln($r->name." ok");
|
||||
}
|
||||
}
|
||||
print(implode("\n", $bae->results));
|
||||
}
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onAdminBuilding(AdminBuildingEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class BulkAddCSV extends Extension
|
||||
{
|
||||
/** @var BulkAddCSVTheme */
|
||||
|
@ -21,23 +25,22 @@ class BulkAddCSV extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tbulk-add-csv [/path/to.csv]\n";
|
||||
print "\t\tImport this .csv file (refer to documentation)\n\n";
|
||||
}
|
||||
if ($event->cmd == "bulk-add-csv") {
|
||||
global $user;
|
||||
$event->app->register('bulk-add-csv')
|
||||
->addArgument('path-to-csv', InputArgument::REQUIRED)
|
||||
->setDescription('Import posts from a given CSV file')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $user;
|
||||
if (!$user->can(Permissions::BULK_ADD)) {
|
||||
$output->writeln("Not running as an admin, which can cause problems.");
|
||||
$output->writeln("Please add the parameter: -u admin_username");
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
//Nag until CLI is admin by default
|
||||
if (!$user->can(Permissions::BULK_ADD)) {
|
||||
print "Not running as an admin, which can cause problems.\n";
|
||||
print "Please add the parameter: -u admin_username";
|
||||
} elseif (count($event->args) == 1) {
|
||||
$this->add_csv($event->args[0]);
|
||||
}
|
||||
}
|
||||
$this->add_csv($input->getArgument('path-to-csv'));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onAdminBuilding(AdminBuildingEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ET extends Extension
|
||||
{
|
||||
/** @var ETTheme */
|
||||
|
@ -37,15 +41,14 @@ class ET extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tinfo\n";
|
||||
print "\t\tList a bunch of info\n\n";
|
||||
}
|
||||
if ($event->cmd == "info") {
|
||||
print($this->to_yaml($this->get_info()));
|
||||
}
|
||||
$event->app->register('info')
|
||||
->setDescription('List a bunch of info')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
print($this->to_yaml($this->get_info()));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ExtensionAuthor
|
||||
{
|
||||
public string $name;
|
||||
|
@ -60,15 +64,14 @@ class ExtManager extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tdisable-all-ext\n";
|
||||
print "\t\tdisable all extensions\n\n";
|
||||
}
|
||||
if ($event->cmd == "disable-all-ext") {
|
||||
$this->write_config([]);
|
||||
}
|
||||
$event->app->register('disable-all-ext')
|
||||
->setDescription('Disable all extensions')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$this->write_config([]);
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use GraphQL\GraphQL as GQL;
|
||||
use GraphQL\Server\StandardServer;
|
||||
use GraphQL\Error\DebugFlag;
|
||||
|
@ -173,29 +177,32 @@ class GraphQL extends Extension
|
|||
return ["image_ids" => array_map(fn ($im) => $im->id, $event->images)];
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tgraphql <query string>\n";
|
||||
print "\t\teg 'graphql \"{ post(id: 18) { id, hash } }\"'\n\n";
|
||||
print "\tgraphql-schema\n";
|
||||
print "\t\tdump the schema\n\n";
|
||||
}
|
||||
if ($event->cmd == "graphql") {
|
||||
$t1 = ftime();
|
||||
$schema = $this->get_schema();
|
||||
$t2 = ftime();
|
||||
$debug = DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::RETHROW_INTERNAL_EXCEPTIONS;
|
||||
$body = GQL::executeQuery($schema, $event->args[0])->toArray($debug);
|
||||
$t3 = ftime();
|
||||
$body['stats'] = get_debug_info_arr();
|
||||
$body['stats']['graphql_schema_time'] = round($t2 - $t1, 2);
|
||||
$body['stats']['graphql_execute_time'] = round($t3 - $t2, 2);
|
||||
echo \json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
if ($event->cmd == "graphql-schema") {
|
||||
$schema = $this->get_schema();
|
||||
echo(SchemaPrinter::doPrint($schema));
|
||||
}
|
||||
$event->app->register('graphql:query')
|
||||
->addArgument('query', InputArgument::REQUIRED)
|
||||
->setDescription('Run a GraphQL query')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$query = $input->getArgument('query');
|
||||
$t1 = ftime();
|
||||
$schema = $this->get_schema();
|
||||
$t2 = ftime();
|
||||
$debug = DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::RETHROW_INTERNAL_EXCEPTIONS;
|
||||
$body = GQL::executeQuery($schema, $query)->toArray($debug);
|
||||
$t3 = ftime();
|
||||
$body['stats'] = get_debug_info_arr();
|
||||
$body['stats']['graphql_schema_time'] = round($t2 - $t1, 2);
|
||||
$body['stats']['graphql_execute_time'] = round($t3 - $t2, 2);
|
||||
echo \json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('graphql:schema')
|
||||
->addArgument('query', InputArgument::REQUIRED)
|
||||
->setDescription('Print out the GraphQL schema')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$schema = $this->get_schema();
|
||||
echo(SchemaPrinter::doPrint($schema));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
require_once "config.php";
|
||||
|
||||
/**
|
||||
|
@ -118,17 +122,17 @@ class ImageIO extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tdelete <post id>\n";
|
||||
print "\t\tdelete a specific post\n\n";
|
||||
}
|
||||
if ($event->cmd == "delete") {
|
||||
$post_id = (int)$event->args[0];
|
||||
$image = Image::by_id($post_id);
|
||||
send_event(new ImageDeletionEvent($image));
|
||||
}
|
||||
$event->app->register('delete')
|
||||
->addArgument('id', InputArgument::REQUIRED)
|
||||
->setDescription('Delete a specific post')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$post_id = (int)$input->getArgument('id');
|
||||
$image = Image::by_id($post_id);
|
||||
send_event(new ImageDeletionEvent($image));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onImageAddition(ImageAdditionEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
require_once "config.php";
|
||||
require_once "events.php";
|
||||
|
||||
|
@ -147,20 +151,19 @@ class Index extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
# TODO: --fields a,b,c
|
||||
print "\tsearch <query>\n";
|
||||
print "\t\tsearch the database and print results\n\n";
|
||||
}
|
||||
if ($event->cmd == "search") {
|
||||
$query = count($event->args) > 0 ? Tag::explode($event->args[0]) : [];
|
||||
$items = Search::find_images(limit: 1000, tags: $query);
|
||||
foreach ($items as $item) {
|
||||
print("{$item->hash}\n");
|
||||
}
|
||||
}
|
||||
$event->app->register('search')
|
||||
->addArgument('query', InputArgument::REQUIRED)
|
||||
->setDescription('Search the database and print results')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$query = Tag::explode($input->getArgument('query'));
|
||||
$items = Search::find_images(limit: 1000, tags: $query);
|
||||
foreach ($items as $item) {
|
||||
$output->writeln($item->hash);
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onSearchTermParse(SearchTermParseEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
require_once "config.php";
|
||||
require_once "events.php";
|
||||
require_once "media_engine.php";
|
||||
|
@ -147,22 +151,22 @@ class Media extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tmedia-rescan <id / hash>\n";
|
||||
print "\t\trefresh metadata for a given post\n\n";
|
||||
}
|
||||
if ($event->cmd == "media-rescan") {
|
||||
$uid = $event->args[0];
|
||||
$image = Image::by_id_or_hash($uid);
|
||||
if ($image) {
|
||||
send_event(new MediaCheckPropertiesEvent($image));
|
||||
$image->save_to_db();
|
||||
} else {
|
||||
print("No post with ID '$uid'\n");
|
||||
}
|
||||
}
|
||||
$event->app->register('media-rescan')
|
||||
->addArgument('id_or_hash', InputArgument::REQUIRED)
|
||||
->setDescription('Refresh metadata for a given post')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$uid = $input->getArgument('id_or_hash');
|
||||
$image = Image::by_id_or_hash($uid);
|
||||
if ($image) {
|
||||
send_event(new MediaCheckPropertiesEvent($image));
|
||||
$image->save_to_db();
|
||||
} else {
|
||||
$output->writeln("No post with ID '$uid'");
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use function MicroHTML\{emptyHTML, A};
|
||||
|
||||
if (
|
||||
|
@ -71,15 +76,20 @@ class Rule34 extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
global $cache;
|
||||
if ($event->cmd == "wipe-thumb-cache") {
|
||||
foreach (Search::find_images_iterable(0, null, Tag::explode($event->args[0])) as $image) {
|
||||
print($image->id . "\n");
|
||||
$cache->delete("thumb-block:{$image->id}");
|
||||
}
|
||||
}
|
||||
$event->app->register('wipe-thumb-cache')
|
||||
->addArgument('tags', InputArgument::REQUIRED)
|
||||
->setDescription('Delete cached thumbnails for images matching the given tags')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $cache;
|
||||
$tags = Tag::explode($input->getArgument('tags'));
|
||||
foreach (Search::find_images_iterable(0, null, $tags) as $image) {
|
||||
$output->writeln($image->id);
|
||||
$cache->delete("thumb-block:{$image->id}");
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onSourceSet(SourceSetEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use function MicroHTML\INPUT;
|
||||
|
||||
require_once "config.php";
|
||||
|
@ -37,56 +41,54 @@ class S3 extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
global $database;
|
||||
if ($event->cmd == "help") {
|
||||
print "\ts3-sync <post id>\n";
|
||||
print "\t\tsync a post to s3\n\n";
|
||||
print "\ts3-rm <hash>\n";
|
||||
print "\t\tdelete a leftover file from s3\n\n";
|
||||
}
|
||||
if ($event->cmd == "s3-sync") {
|
||||
if(count($event->args) == 0) {
|
||||
$event->app->register('s3:process')
|
||||
->setDescription('Process the S3 queue')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $database;
|
||||
$count = $database->get_one("SELECT COUNT(*) FROM s3_sync_queue");
|
||||
print("{$count} items in queue\n");
|
||||
$output->writeln("{$count} items in queue");
|
||||
foreach($database->get_all("SELECT * FROM s3_sync_queue ORDER BY time ASC") as $row) {
|
||||
if($row['action'] == "S") {
|
||||
$image = Image::by_hash($row['hash']);
|
||||
print("SYN {$row['hash']} ($image->id)\n");
|
||||
$output->writeln("SYN {$row['hash']} ($image->id)");
|
||||
$this->sync_post($image);
|
||||
} elseif($row['action'] == "D") {
|
||||
print("DEL {$row['hash']}\n");
|
||||
$output->writeln("DEL {$row['hash']}");
|
||||
$this->remove_file($row['hash']);
|
||||
} else {
|
||||
print("??? {$row['hash']} ({$row['action']})\n");
|
||||
$output->writeln("??? {$row['hash']} ({$row['action']})");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (preg_match('/^(\d+)-(\d+)$/', $event->args[0], $matches)) {
|
||||
$start = (int)$matches[1];
|
||||
$end = (int)$matches[2];
|
||||
} else {
|
||||
$start = (int)$event->args[0];
|
||||
$end = $start;
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('s3:sync')
|
||||
->addArgument('start', InputArgument::REQUIRED)
|
||||
->addArgument('end', InputArgument::REQUIRED)
|
||||
->setDescription('Sync a range of images to S3')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$start = (int)$input->getArgument('start');
|
||||
$end = (int)$input->getArgument('end');
|
||||
$output->writeln("Syncing range: $start - $end");
|
||||
foreach(Search::find_images_iterable(tags: ["order=id", "id>=$start", "id<=$end"]) as $image) {
|
||||
if($this->sync_post($image)) {
|
||||
print("{$image->id}: {$image->hash}\n");
|
||||
} else {
|
||||
print("{$image->id}: {$image->hash} (skipped)\n");
|
||||
}
|
||||
ob_flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($event->cmd == "s3-rm") {
|
||||
foreach($event->args as $hash) {
|
||||
print("{$hash}\n");
|
||||
ob_flush();
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('s3:rm')
|
||||
->addArgument('hash', InputArgument::REQUIRED)
|
||||
->setDescription('Delete a leftover file from S3')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$hash = $input->getArgument('hash');
|
||||
$output->writeln("Deleting file: '$hash'");
|
||||
$this->remove_file($hash);
|
||||
}
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onPageRequest(PageRequestEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
require_once "config.php";
|
||||
|
||||
/*
|
||||
|
@ -420,26 +424,26 @@ class Setup extends Extension
|
|||
log_warning("setup", "Cache cleared");
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tconfig [get|set] <args>\n";
|
||||
print "\t\teg 'config get db_version'\n\n";
|
||||
}
|
||||
if ($event->cmd == "config") {
|
||||
global $cache, $config;
|
||||
$cmd = $event->args[0];
|
||||
$key = $event->args[1];
|
||||
switch ($cmd) {
|
||||
case "get":
|
||||
print($config->get_string($key) . "\n");
|
||||
break;
|
||||
case "set":
|
||||
$config->set_string($key, $event->args[2]);
|
||||
break;
|
||||
}
|
||||
$cache->delete("config");
|
||||
}
|
||||
$event->app->register('config:get')
|
||||
->addArgument('key', InputArgument::REQUIRED)
|
||||
->setDescription('Get a config value')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $config;
|
||||
$output->writeln($config->get_string($input->getArgument('key')));
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
$event->app->register('config:set')
|
||||
->addArgument('key', InputArgument::REQUIRED)
|
||||
->addArgument('value', InputArgument::REQUIRED)
|
||||
->setDescription('Set a config value')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
global $cache, $config;
|
||||
$config->set_string($input->getArgument('key'), $input->getArgument('value'));
|
||||
$cache->delete("config");
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
|
||||
|
|
|
@ -4,6 +4,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/*
|
||||
* OwnerSetEvent:
|
||||
* $image_id
|
||||
|
@ -159,19 +163,19 @@ class TagEdit extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
global $database;
|
||||
if ($event->cmd == "help") {
|
||||
print "\ttag-replace <tag> <tag>\n";
|
||||
print "\t\tmass replace tags\n\n";
|
||||
}
|
||||
if ($event->cmd == "tag-replace") {
|
||||
print("Mass editing tags: '{$event->args[0]}' -> '{$event->args[1]}'\n");
|
||||
if(count($event->args) == 2) {
|
||||
$this->mass_tag_edit($event->args[0], $event->args[1], true);
|
||||
}
|
||||
}
|
||||
$event->app->register('tag-replace')
|
||||
->addArgument('old_tag', InputArgument::REQUIRED)
|
||||
->addArgument('new_tag', InputArgument::REQUIRED)
|
||||
->setDescription('Mass edit tags')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$old_tag = $input->getArgument('old_tag');
|
||||
$new_tag = $input->getArgument('new_tag');
|
||||
$output->writeln("Mass editing tags: '$old_tag' -> '$new_tag'");
|
||||
$this->mass_tag_edit($old_tag, $new_tag, true);
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
// public function onPostListBuilding(PostListBuildingEvent $event)
|
||||
|
|
|
@ -4,20 +4,23 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shimmie2;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class Upgrade extends Extension
|
||||
{
|
||||
public function onCommand(CommandEvent $event)
|
||||
public function onCliGen(CliGenEvent $event)
|
||||
{
|
||||
if ($event->cmd == "help") {
|
||||
print "\tdb-upgrade\n";
|
||||
print "\t\tRun DB schema updates, if automatic updates are disabled\n\n";
|
||||
}
|
||||
if ($event->cmd == "db-upgrade") {
|
||||
print("Running DB Upgrade\n");
|
||||
global $database;
|
||||
$database->set_timeout(null); // These updates can take a little bit
|
||||
send_event(new DatabaseUpgradeEvent());
|
||||
}
|
||||
$event->app->register('db-upgrade')
|
||||
->setDescription('Run DB schema updates, if automatic updates are disabled')
|
||||
->setCode(function (InputInterface $input, OutputInterface $output): int {
|
||||
$output->writeln("Running DB Upgrade");
|
||||
global $database;
|
||||
$database->set_timeout(null); // These updates can take a little bit
|
||||
send_event(new DatabaseUpgradeEvent());
|
||||
return Command::SUCCESS;
|
||||
});
|
||||
}
|
||||
|
||||
public function onDatabaseUpgrade(DatabaseUpgradeEvent $event)
|
||||
|
|
|
@ -82,7 +82,9 @@ try {
|
|||
if (PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') {
|
||||
ob_end_flush();
|
||||
ob_implicit_flush(true);
|
||||
send_event(new CommandEvent($argv));
|
||||
$app = new CliApp();
|
||||
send_event(new CliGenEvent($app));
|
||||
$app->run();
|
||||
} else {
|
||||
send_event(new PageRequestEvent($_SERVER['REQUEST_METHOD'], _get_query()));
|
||||
$page->display();
|
||||
|
|
Reference in a new issue