. */ namespace SP\Modules\Cli\Commands; use Exception; use Psr\Log\LoggerInterface; use RuntimeException; use SP\Core\Bootstrap\Path; use SP\Core\Bootstrap\PathsContext; use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Export\Ports\BackupFileService; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\StyleInterface; use Symfony\Component\Console\Style\SymfonyStyle; use function SP\__; use function SP\__u; /** * Class BackupCommand * * @package SP\Modules\Cli\Commands */ final class BackupCommand extends CommandBase { /** * @var string[] */ public static array $envVarsMapping = [ 'path' => 'BACKUP_PATH' ]; /** * @var string */ protected static $defaultName = 'sp:backup'; public function __construct( private readonly BackupFileService $fileBackupService, LoggerInterface $logger, ConfigFileService $config, private readonly PathsContext $pathsContext ) { parent::__construct($logger, $config); } protected function configure(): void { $this->setDescription(__('Backup actions')) ->setHelp(__('This command performs a file based backup from sysPass database and application')) ->addOption( 'path', null, InputOption::VALUE_OPTIONAL, __('Path where to store the backup files'), $this->pathsContext[Path::BACKUP] ); } protected function execute( InputInterface $input, OutputInterface $output ): int { $style = new SymfonyStyle($input, $output); try { $this->checkInstalled(); $path = $this->getPath($input, $style); $this->logger->info(sprintf(__u('Backup path set to: %s'), $path)); $this->fileBackupService->doBackup($path, $this->pathsContext[Path::APP]); $this->logger->info(__u('Application and database backup completed successfully')); $style->success(__('Application and database backup completed successfully')); return self::SUCCESS; } catch (Exception $e) { $this->logger->error($e->getTraceAsString()); $this->logger->error($e->getMessage()); $style->error(__($e->getMessage())); } return self::FAILURE; } private function checkInstalled(): void { if (!defined('TEST_ROOT') && !$this->configData->isInstalled() ) { throw new RuntimeException(__u('sysPass is not installed')); } } private function getPath( InputInterface $input, StyleInterface $style ): string { $path = self::getEnvVarOrOption('path', $input); if (empty($path)) { $this->logger->debug(__u('Ask for path')); return $style->ask( __('Please enter the path where to store the backup files'), $this->pathsContext[Path::BACKUP] ); } return $path; } }