Started restore command, extracted artisan command

This commit is contained in:
Dan Brown 2023-03-06 21:39:22 +00:00
parent 6bfbad2393
commit 2894ce275c
No known key found for this signature in database
GPG key ID: 46D9F943C24A2EF9
4 changed files with 103 additions and 24 deletions

View file

@ -0,0 +1,63 @@
<?php
namespace Cli\Commands;
use Cli\Services\AppLocator;
use Cli\Services\ArtisanRunner;
use Cli\Services\RequirementsValidator;
use Symfony\Component\Console\Command\Command;
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 RestoreCommand extends Command
{
protected function configure(): void
{
$this->setName('restore');
$this->addArgument('backup-zip', InputArgument::REQUIRED, 'Path to the ZIP file containing your backup.');
$this->setDescription('Restore data and files from a backup ZIP file.');
$this->addOption('app-directory', null, InputOption::VALUE_OPTIONAL, 'BookStack install directory to restore into', '');
}
/**
* @throws CommandError
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$appDir = AppLocator::require($input->getOption('app-directory'));
$output->writeln("<info>Checking system requirements...</info>");
RequirementsValidator::validate();
// TODO - Warn that potentially dangerous,
// warn for same/forward versions only,
// warn this won't handle server-level stuff
// TODO - Validate provided backup zip contents
// - Display and prompt to user
// TODO - Environment handling
// - Restore of old .env
// - Prompt for correct DB details (Test before serving?)
// - Prompt for correct URL (Allow entry of new?)
// TODO - Restore folders from backup
// TODO - Restore database from backup
$output->writeln("<info>Running database migrations...</info>");
$artisan = (new ArtisanRunner($appDir));
$artisan->run(['migrate', '--force']);
// TODO - Update system URL (via BookStack artisan command) if
// there's been a change from old backup env
$output->writeln("<info>Clearing app caches...</info>");
$artisan->run(['cache:clear']);
$artisan->run(['config:clear']);
$artisan->run(['view:clear']);
return Command::SUCCESS;
}
}

View file

@ -3,8 +3,8 @@
namespace Cli\Commands;
use Cli\Services\AppLocator;
use Cli\Services\ArtisanRunner;
use Cli\Services\ComposerLocator;
use Cli\Services\EnvironmentLoader;
use Cli\Services\ProgramRunner;
use Cli\Services\RequirementsValidator;
use Symfony\Component\Console\Command\Command;
@ -45,12 +45,13 @@ class UpdateCommand extends Command
$this->installComposerDependencies($composer, $appDir);
$output->writeln("<info>Running database migrations...</info>");
$this->runArtisanCommand(['migrate', '--force'], $appDir);
$artisan = (new ArtisanRunner($appDir));
$artisan->run(['migrate', '--force']);
$output->writeln("<info>Clearing app caches...</info>");
$this->runArtisanCommand(['cache:clear'], $appDir);
$this->runArtisanCommand(['config:clear'], $appDir);
$this->runArtisanCommand(['view:clear'], $appDir);
$artisan->run(['cache:clear']);
$artisan->run(['config:clear']);
$artisan->run(['view:clear']);
return Command::SUCCESS;
}
@ -88,22 +89,4 @@ class UpdateCommand extends Command
throw new CommandError("Failed composer install with errors:\n" . $errors);
}
}
protected function runArtisanCommand(array $commandArgs, string $appDir): void
{
$errors = (new ProgramRunner('php', '/usr/bin/php'))
->withTimeout(60)
->withIdleTimeout(5)
->withEnvironment(EnvironmentLoader::load($appDir))
->runCapturingAllOutput([
$appDir . DIRECTORY_SEPARATOR . 'artisan',
'-n', '-q',
...$commandArgs
]);
if ($errors) {
$cmdString = implode(' ', $commandArgs);
throw new CommandError("Failed 'php artisan {$cmdString}' with errors:\n" . $errors);
}
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace Cli\Services;
use Exception;
class ArtisanRunner
{
public function __construct(
protected string $appDir
) {
}
public function run(array $commandArgs)
{
$errors = (new ProgramRunner('php', '/usr/bin/php'))
->withTimeout(60)
->withIdleTimeout(5)
->withEnvironment(EnvironmentLoader::load($this->appDir))
->runCapturingAllOutput([
$this->appDir . DIRECTORY_SEPARATOR . 'artisan',
'-n', '-q',
...$commandArgs
]);
if ($errors) {
$cmdString = implode(' ', $commandArgs);
throw new Exception("Failed 'php artisan {$cmdString}' with errors:\n" . $errors);
}
}
}

View file

@ -7,10 +7,11 @@ if (php_sapi_name() !== 'cli') {
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Console\Application;
use Cli\Commands\BackupCommand;
use Cli\Commands\InitCommand;
use Cli\Commands\RestoreCommand;
use Cli\Commands\UpdateCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Output\ConsoleOutput;
@ -21,6 +22,7 @@ $app->setCatchExceptions(false);
$app->add(new BackupCommand());
$app->add(new UpdateCommand());
$app->add(new InitCommand());
$app->add(new RestoreCommand());
try {
$app->run();