--- /dev/null
+<?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;
+ }
+}
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;
$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;
}
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);
- }
- }
}
--- /dev/null
+<?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);
+ }
+ }
+}
\ No newline at end of file
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;
$app->add(new BackupCommand());
$app->add(new UpdateCommand());
$app->add(new InitCommand());
+$app->add(new RestoreCommand());
try {
$app->run();