X-Git-Url: http://source.bookstackapp.com/system-cli/blobdiff_plain/0632ad4355078352b430a395e69b10cd790d739a..3992a6b67871ea32c9a2e85fd8824bdd4f2bdeaa:/scripts/Commands/RestoreCommand.php diff --git a/scripts/Commands/RestoreCommand.php b/scripts/Commands/RestoreCommand.php index 1f83045..c181ff8 100644 --- a/scripts/Commands/RestoreCommand.php +++ b/scripts/Commands/RestoreCommand.php @@ -4,6 +4,9 @@ namespace Cli\Commands; use Cli\Services\AppLocator; use Cli\Services\ArtisanRunner; +use Cli\Services\BackupZip; +use Cli\Services\EnvironmentLoader; +use Cli\Services\InteractiveConsole; use Cli\Services\RequirementsValidator; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -26,16 +29,52 @@ class RestoreCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output): int { + $interactions = new InteractiveConsole($this->getHelper('question'), $input, $output); + + $output->writeln("Warning!"); + $output->writeln("- A restore operation will overwrite and remove files & content from an existing instance."); + $output->writeln("- Any existing tables within the configured database will be dropped."); + $output->writeln("- You should only restore into an instance of the same or newer BookStack version."); + $output->writeln("- This command won't handle, restore or address any server configuration."); + $appDir = AppLocator::require($input->getOption('app-directory')); $output->writeln("Checking system requirements..."); RequirementsValidator::validate(); - // TODO - Warn that potentially dangerous, - // warn for same/forward versions only, - // warn this won't handle server-level stuff + $zipPath = realpath($input->getArgument('backup-zip')); + $zip = new BackupZip($zipPath); + $contents = $zip->getContentsOverview(); + + $output->writeln("\nContents found in the backup ZIP:"); + $hasContent = false; + foreach ($contents as $info) { + $output->writeln(($info['exists'] ? '✔ ' : '❌ ') . $info['desc']); + if ($info['exists']) { + $hasContent = true; + } + } + + if (!$hasContent) { + throw new CommandError("Provided ZIP backup [{$zipPath}] does not have any expected restore-able content."); + } + + $output->writeln("The checked elements will be restored into [{$appDir}]."); + $output->writeln("Existing content may be overwritten."); + $output->writeln("Do you want to continue?"); + + if (!$interactions->confirm("Do you want to continue?")) { + $output->writeln("Stopping restore operation."); + return Command::SUCCESS; + } - // TODO - Validate provided backup zip contents - // - Display and prompt to user + $output->writeln("Extracting ZIP into temporary directory..."); + $extractDir = $appDir . DIRECTORY_SEPARATOR . 'restore-temp-' . time(); + if (!mkdir($extractDir)) { + throw new CommandError("Could not create temporary extraction directory at [{$extractDir}]."); + } + $zip->extractInto($extractDir); + + // TODO - Cleanup temp extract dir // TODO - Environment handling // - Restore of old .env @@ -60,4 +99,14 @@ class RestoreCommand extends Command return Command::SUCCESS; } + + protected function restoreEnv(string $extractDir, string $appDir, InteractiveConsole $interactions) + { + $extractEnv = EnvironmentLoader::load($extractDir); + $appEnv = EnvironmentLoader::load($appDir); // TODO - Probably pass in since we'll need the APP_URL later on. + + // TODO - Create mysql runner to take variables to a programrunner instance. + // Then test each, backup existing env, then replace env with old then overwrite + // db options if the new app env options are the valid ones. + } }