]> BookStack Code Mirror - system-cli/commitdiff
Split command out to methods, added flags and out path options
authorDan Brown <redacted>
Fri, 3 Mar 2023 17:22:24 +0000 (17:22 +0000)
committerDan Brown <redacted>
Thu, 9 Mar 2023 15:28:12 +0000 (15:28 +0000)
scripts/Commands/BackupCommand.php

index 2b303854a57cdc8e4282e6a55f69c921b905b224..cf2ca35b190487bc2b297cf1cedb3ff5066262cb 100644 (file)
@@ -4,6 +4,7 @@ namespace Cli\Commands;
 
 use Minicli\Command\CommandCall;
 use RecursiveDirectoryIterator;
+use SplFileInfo;
 use Symfony\Component\Process\ExecutableFinder;
 use Symfony\Component\Process\Process;
 use ZipArchive;
@@ -17,14 +18,101 @@ final class BackupCommand
 
     public function handle(CommandCall $input)
     {
-        // TODO - Customizable output file
-        // TODO - Database only command
+        $handleDatabase = !$input->hasFlag('no-database');
+        $handleUploads = !$input->hasFlag('no-uploads');
+        $suggestedOutPath = $input->subcommand ?: '';
+
         // TODO - Validate DB vars
+        // TODO - Backup themes directory, extra flag for no-themes
+        // TODO - Backup the running phar? For easier direct restore...
         // TODO - Error handle each stage
         // TODO - Validate zip (and any other extensions required) are active.
 
-        $zipOutFile = getcwd() . DIRECTORY_SEPARATOR . 'backup.zip';
+        $zipOutFile = $this->buildZipFilePath($suggestedOutPath);
+        $dumpTempFile = $this->createDatabaseDump();
+
+        // Create a new ZIP file
+        $zipTempFile = tempnam(sys_get_temp_dir(), 'bsbackup');
+        $zip = new ZipArchive();
+        $zip->open($zipTempFile, ZipArchive::CREATE);
+        $zip->addFile($this->appDir . DIRECTORY_SEPARATOR . '.env', '.env');
+
+        if ($handleDatabase) {
+            $zip->addFile($dumpTempFile, 'db.sql');
+        }
+
+        if ($handleUploads) {
+            $this->addUploadFoldersToZip($zip);
+        }
+
+        // Close off our zip and move it to the required location
+        $zip->close();
+        rename($zipTempFile, $zipOutFile);
+
+        // Delete our temporary DB dump file
+        unlink($dumpTempFile);
+
+        // Announce end and display errors
+        echo "Finished";
+    }
+
+    /**
+     * Build a full zip path from the given suggestion, which may be empty,
+     * a path to a folder, or a path to a file in relative or absolute form.
+     */
+    protected function buildZipFilePath(string $suggestedOutPath): string
+    {
+        $zipDir = getcwd() ?: $this->appDir;
+        $zipName = "bookstack-backup-" . date('Y-m-d-His') . '.zip';
+
+        if ($suggestedOutPath) {
+            if (is_dir($suggestedOutPath)) {
+                $zipDir = realpath($suggestedOutPath);
+            } else if (is_dir(dirname($suggestedOutPath))) {
+                $zipDir = realpath(dirname($suggestedOutPath));
+                $zipName = basename($suggestedOutPath);
+            } else {
+                // TODO - Handle not found output
+            }
+        }
+
+        $fullPath = $zipDir . DIRECTORY_SEPARATOR . $zipName;
 
+        if (file_exists($fullPath)) {
+            // TODO
+        }
+
+        return $fullPath;
+    }
+
+    /**
+     * Add app-relative upload folders to the provided zip archive.
+     * Will recursively go through all directories to add all files.
+     */
+    protected function addUploadFoldersToZip(ZipArchive $zip): void
+    {
+        $fileDirs = [
+            $this->appDir . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'uploads' => 'public/uploads',
+            $this->appDir . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'uploads' => 'storage/uploads',
+        ];
+
+        foreach ($fileDirs as $fullFileDir => $relativeFileDir) {
+            $dirIter = new RecursiveDirectoryIterator($fullFileDir);
+            $fileIter = new \RecursiveIteratorIterator($dirIter);
+            /** @var SplFileInfo $file */
+            foreach ($fileIter as $file) {
+                if (!$file->isDir()) {
+                    $zip->addFile($file->getPathname(), $relativeFileDir . '/' . $fileIter->getSubPathname());
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a database dump and return the path to the dumped SQL output.
+     */
+    protected function createDatabaseDump(): string
+    {
         $dbHost = ($_SERVER['DB_HOST'] ?? '');
         $dbUser = ($_SERVER['DB_USERNAME'] ?? '');
         $dbPass = ($_SERVER['DB_PASSWORD'] ?? '');
@@ -57,42 +145,7 @@ final class BackupCommand
         }
         fclose($dumpTempFileResource);
 
-
-        // Create a new ZIP file
-        $zipTempFile = tempnam(sys_get_temp_dir(), 'bsbackup');
-        $zip = new ZipArchive();
-        $sep = DIRECTORY_SEPARATOR;
-        $zip->open($zipTempFile, ZipArchive::CREATE);
-        $zip->addFile($this->appDir . $sep . '.env', '.env');
-        $zip->addFile($dumpTempFile, 'db.sql');
-
-        $fileDirs = [
-            $this->appDir . $sep . 'public' . $sep . 'uploads' => 'public/uploads',
-            $this->appDir . $sep . 'storage' . $sep . 'uploads' => 'storage/uploads',
-        ];
-
-        foreach ($fileDirs as $fullFileDir => $relativeFileDir) {
-            $dirIter = new RecursiveDirectoryIterator($fullFileDir);
-            $fileIter = new \RecursiveIteratorIterator($dirIter);
-            /** @var \SplFileInfo $file */
-            foreach ($fileIter as $file) {
-                if (!$file->isDir()) {
-                    $zip->addFile($file->getPathname(), $relativeFileDir . '/' . $fileIter->getSubPathname());
-                }
-            }
-        }
-
-        // Close off our zip and move it to the required location
-        $zip->close();
-        rename($zipTempFile, $zipOutFile);
-
-        // Delete our temporary DB dump file
-        unlink($dumpTempFile);
-
-        // Announce end and display errors
-        echo "Finished";
-        if ($errors) {
-            echo " with the following errors:\n" . $errors;
-        }
+        // TODO - Throw errors if existing
+        return $dumpTempFile;
     }
 }