storageLocationRepo->findAllByType(Entity\StorageLocation::TYPE_BACKUP); foreach ($storageLocations as $storageLocation) { /** @var StorageAttributes $file */ foreach ($storageLocation->getFilesystem()->listContents('', true) as $file) { if ($file->isDir()) { continue; } /** @var FileAttributes $file */ $filename = $file->path(); $backups[] = [ 'path' => $filename, 'basename' => basename($filename), 'pathEncoded' => base64_encode($storageLocation->getId() . '|' . $filename), 'timestamp' => $file->lastModified(), 'size' => $file->fileSize(), 'storageLocationId' => $storageLocation->getId(), ]; } } uasort( $backups, static function ($a, $b) { return $b['timestamp'] <=> $a['timestamp']; } ); $settings = $this->settingsRepo->readSettings(); return $request->getView()->renderToResponse( $response, 'admin/backups/index', [ 'backups' => $backups, 'is_enabled' => $settings->getBackupEnabled(), 'last_run' => $settings->getBackupLastRun(), 'last_result' => $settings->getBackupLastResult(), 'last_output' => $settings->getBackupLastOutput(), 'csrf' => $request->getCsrf()->generate($this->csrfNamespace), ] ); } public function configureAction( ServerRequest $request, Response $response, FactoryInterface $factory ): ResponseInterface { $settingsForm = $factory->make(BackupSettingsForm::class); if (false !== $settingsForm->process($request)) { $request->getFlash()->addMessage(__('Changes saved.'), Flash::SUCCESS); return $response->withRedirect((string)$request->getRouter()->fromHere('admin:backups:index')); } return $request->getView()->renderToResponse( $response, 'system/form_page', [ 'form' => $settingsForm, 'render_mode' => 'edit', 'title' => __('Configure Backups'), ] ); } public function runAction( ServerRequest $request, Response $response, Config $config ): ResponseInterface { $runForm = new Form( $config->get( 'forms/backup_run', [ 'storageLocations' => $this->storageLocationRepo->fetchSelectByType( Entity\StorageLocation::TYPE_BACKUP, true ), ] ) ); // Handle submission. if ($runForm->isValid($request)) { $data = $runForm->getValues(); $tempFile = File::generateTempPath('backup.log'); $storageLocationId = (int)$data['storage_location']; if ($storageLocationId <= 0) { $storageLocationId = null; } $message = new BackupMessage(); $message->storageLocationId = $storageLocationId; $message->path = $data['path']; $message->excludeMedia = $data['exclude_media']; $message->outputPath = $tempFile; $this->messageBus->dispatch($message); return $request->getView()->renderToResponse( $response, 'admin/backups/run', [ 'title' => __('Run Manual Backup'), 'path' => $data['path'], 'outputLog' => basename($tempFile), ] ); } return $request->getView()->renderToResponse( $response, 'system/form_page', [ 'form' => $runForm, 'render_mode' => 'edit', 'title' => __('Run Manual Backup'), ] ); } public function logAction( ServerRequest $request, Response $response, string $path ): ResponseInterface { $logPath = File::validateTempPath($path); return $this->view($request, $response, $logPath, true); } public function downloadAction( ServerRequest $request, Response $response, string $path ): ResponseInterface { [$path, $fs] = $this->getFile($path); /** @var ExtendedFilesystemInterface $fs */ return $response ->withNoCache() ->streamFilesystemFile($fs, $path); } public function deleteAction( ServerRequest $request, Response $response, string $path, string $csrf ): ResponseInterface { $request->getCsrf()->verify($csrf, $this->csrfNamespace); [$path, $fs] = $this->getFile($path); /** @var ExtendedFilesystemInterface $fs */ $fs->delete($path); $request->getFlash()->addMessage('' . __('Backup deleted.') . '', Flash::SUCCESS); return $response->withRedirect((string)$request->getRouter()->named('admin:backups:index')); } /** * @param string $rawPath * * @return array{0: string, 1: ExtendedFilesystemInterface} */ protected function getFile(string $rawPath): array { $pathStr = base64_decode($rawPath); [$storageLocationId, $path] = explode('|', $pathStr); $storageLocation = $this->storageLocationRepo->findByType( Entity\StorageLocation::TYPE_BACKUP, (int)$storageLocationId ); if (!($storageLocation instanceof Entity\StorageLocation)) { throw new InvalidArgumentException('Invalid storage location.'); } $fs = $storageLocation->getFilesystem(); if (!$fs->fileExists($path)) { throw new NotFoundException(__('Backup not found.')); } return [$path, $fs]; } }