From 0146858e9ff3e0f38c13a5b7d5420140b4b86762 Mon Sep 17 00:00:00 2001 From: Ahmet Bora Date: Thu, 22 Feb 2024 20:31:08 +0300 Subject: [PATCH 1/5] New `backup` command --- README.md | 1 + commands/backup.php | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 commands/backup.php diff --git a/README.md b/README.md index 370d8ff..1330674 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ This should print the Kirby CLI version and a list of available commands ## Available core commands ``` +- kirby backup - kirby clean:content - kirby clear:cache - kirby clear:lock diff --git a/commands/backup.php b/commands/backup.php new file mode 100644 index 0000000..4657231 --- /dev/null +++ b/commands/backup.php @@ -0,0 +1,50 @@ + 'Creates backup of application files', + 'args' => [ + 'root' => [ + 'description' => 'Selects the kirby root to be backup' + ] + ], + 'command' => static function (CLI $cli): void { + $root = $cli->argOrPrompt( + 'root', + 'Which root should be backup? (press to backup the entire kirby application)', + false + ); + $root = empty($root) === true ? 'index' : $root; + $targetPath = $cli->kirby()->root($root); + + if ($targetPath === null) { + throw new Exception('Invalid root entered: ' . $root); + } + + $kirbyPath = $cli->kirby()->root('index'); + $backupPath = $kirbyPath . '/backup'; + $backupFile = $backupPath . '/' . date('Y-m-d-His') . '.zip'; + $relativeBackupFile = Str::after($backupFile, $kirbyPath); + $relativeTargetPath = trim(Str::after($targetPath, $kirbyPath), '/'); + + // execution commands list + $commands = [ + // navigates to the target directory to ignore parent folders in zip file + 'cd ' . escapeshellarg($targetPath) . ';', + // set backup file path + 'zip -r ' . escapeshellarg($backupFile), + // set target backup directory + escapeshellarg(empty($relativeTargetPath) === true ? '*' : ('./' . $relativeTargetPath . '/*')), + // exclude backup directory + '-x ' . escapeshellarg('backup/*') + ]; + + exec(implode(' ', $commands)); + + $cli->success('The backup has been created: ' . $relativeBackupFile); + } +]; From 04edf83d305c8db5923d09f76fa5ef8dd9f50744 Mon Sep 17 00:00:00 2001 From: Ahmet Bora Date: Fri, 23 Feb 2024 00:52:37 +0300 Subject: [PATCH 2/5] Some fixes --- commands/backup.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/commands/backup.php b/commands/backup.php index 4657231..100eb97 100644 --- a/commands/backup.php +++ b/commands/backup.php @@ -3,6 +3,7 @@ declare(strict_types = 1); use Kirby\CLI\CLI; +use Kirby\Filesystem\Dir; use Kirby\Toolkit\Str; return [ @@ -27,7 +28,7 @@ $kirbyPath = $cli->kirby()->root('index'); $backupPath = $kirbyPath . '/backup'; - $backupFile = $backupPath . '/' . date('Y-m-d-His') . '.zip'; + $backupFile = $backupPath . '/' . $root . '-' . date('Y-m-d-His') . '.zip'; $relativeBackupFile = Str::after($backupFile, $kirbyPath); $relativeTargetPath = trim(Str::after($targetPath, $kirbyPath), '/'); @@ -35,14 +36,20 @@ $commands = [ // navigates to the target directory to ignore parent folders in zip file 'cd ' . escapeshellarg($targetPath) . ';', - // set backup file path + // sets backup file path 'zip -r ' . escapeshellarg($backupFile), - // set target backup directory - escapeshellarg(empty($relativeTargetPath) === true ? '*' : ('./' . $relativeTargetPath . '/*')), - // exclude backup directory - '-x ' . escapeshellarg('backup/*') + // sets target backup directory + escapeshellarg($root === 'index' ? '*' : ('./' . $relativeTargetPath . '/*')) ]; + // exclude backup directory from the root for only index root + if ($root === 'index') { + $commands[] = '-x ' . escapeshellarg('backup/*'); + } + + // create backup directory before the process + Dir::make($backupPath); + exec(implode(' ', $commands)); $cli->success('The backup has been created: ' . $relativeBackupFile); From 6dec129a559d7f45e3750a2a634a13fafacae85a Mon Sep 17 00:00:00 2001 From: Ahmet Bora Date: Sat, 24 Feb 2024 14:00:27 +0300 Subject: [PATCH 3/5] Switch to php native methods --- commands/backup.php | 68 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/commands/backup.php b/commands/backup.php index 100eb97..5f6b2eb 100644 --- a/commands/backup.php +++ b/commands/backup.php @@ -3,8 +3,6 @@ declare(strict_types = 1); use Kirby\CLI\CLI; -use Kirby\Filesystem\Dir; -use Kirby\Toolkit\Str; return [ 'description' => 'Creates backup of application files', @@ -14,44 +12,60 @@ ] ], 'command' => static function (CLI $cli): void { + if (class_exists('ZipArchive') === false) { + throw new Exception('ZipArchive library could not be found'); + } + $root = $cli->argOrPrompt( 'root', 'Which root should be backup? (press to backup the entire kirby application)', false ); $root = empty($root) === true ? 'index' : $root; - $targetPath = $cli->kirby()->root($root); + $rootPath = $cli->kirby()->root($root); - if ($targetPath === null) { + if ($rootPath === null) { throw new Exception('Invalid root entered: ' . $root); } - $kirbyPath = $cli->kirby()->root('index'); - $backupPath = $kirbyPath . '/backup'; - $backupFile = $backupPath . '/' . $root . '-' . date('Y-m-d-His') . '.zip'; - $relativeBackupFile = Str::after($backupFile, $kirbyPath); - $relativeTargetPath = trim(Str::after($targetPath, $kirbyPath), '/'); - - // execution commands list - $commands = [ - // navigates to the target directory to ignore parent folders in zip file - 'cd ' . escapeshellarg($targetPath) . ';', - // sets backup file path - 'zip -r ' . escapeshellarg($backupFile), - // sets target backup directory - escapeshellarg($root === 'index' ? '*' : ('./' . $relativeTargetPath . '/*')) - ]; - - // exclude backup directory from the root for only index root - if ($root === 'index') { - $commands[] = '-x ' . escapeshellarg('backup/*'); - } + $kirbyPath = $cli->kirby()->root('index'); + $backupPath = $kirbyPath . '/backup'; + $backupFile = $backupPath . '/' . $root . '-' . date('Y-m-d-His') . '.zip'; // create backup directory before the process - Dir::make($backupPath); + mkdir($backupPath); - exec(implode(' ', $commands)); + $zip = new ZipArchive(); + if ($zip->open($backupFile, ZipArchive::CREATE) !== true) { + throw new Exception('Failed to create backup file'); + } + + $files = new RecursiveIteratorIterator( + new RecursiveCallbackFilterIterator( + new RecursiveDirectoryIterator( + $rootPath, + FilesystemIterator::SKIP_DOTS + ), + fn ($file) => $file->isFile() || in_array($file->getBaseName(), ['.git', 'backup']) === false + ) + ); + + foreach ($files as $file) { + // skip directories, will be added automatically + if ($file->isDir() === false) { + // get real and relative path for current file + $filePath = $file->getRealPath(); + $relativePath = substr($filePath, strlen($rootPath) + 1); + + // add current file to archive + $zip->addFile($filePath, $relativePath); + } + } + + if ($zip->close() === false) { + throw new Exception('There was a problem writing the backup file'); + } - $cli->success('The backup has been created: ' . $relativeBackupFile); + $cli->success('The backup has been created: ' . substr($backupFile, strlen($kirbyPath))); } ]; From 1eb9bb645a4863a30832c506a7a858c773a6ccf1 Mon Sep 17 00:00:00 2001 From: Ahmet Bora Date: Sat, 24 Feb 2024 14:03:30 +0300 Subject: [PATCH 4/5] Check backup file existence --- commands/backup.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/commands/backup.php b/commands/backup.php index 5f6b2eb..6f38492 100644 --- a/commands/backup.php +++ b/commands/backup.php @@ -32,6 +32,10 @@ $backupPath = $kirbyPath . '/backup'; $backupFile = $backupPath . '/' . $root . '-' . date('Y-m-d-His') . '.zip'; + if (is_file($backupFile) === true) { + throw new Exception('The backup file exists'); + } + // create backup directory before the process mkdir($backupPath); From 53045bc442b50368d5ea9f3cc62acf986d3c4172 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 27 Feb 2024 12:53:08 +0100 Subject: [PATCH 5/5] Small adjustments --- commands/backup.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/commands/backup.php b/commands/backup.php index 6f38492..409cd0a 100644 --- a/commands/backup.php +++ b/commands/backup.php @@ -3,12 +3,13 @@ declare(strict_types = 1); use Kirby\CLI\CLI; +use Kirby\Filesystem\Dir; return [ 'description' => 'Creates backup of application files', 'args' => [ 'root' => [ - 'description' => 'Selects the kirby root to be backup' + 'description' => 'Selects the kirby root, which should be backuped' ] ], 'command' => static function (CLI $cli): void { @@ -16,18 +17,23 @@ throw new Exception('ZipArchive library could not be found'); } - $root = $cli->argOrPrompt( + $root = $cli->argOrPrompt( 'root', - 'Which root should be backup? (press to backup the entire kirby application)', + 'Which root should be backuped? (press to backup your entire site)', false ); - $root = empty($root) === true ? 'index' : $root; - $rootPath = $cli->kirby()->root($root); + + $root = empty($root) === true ? 'index' : $root; + $rootPath = $cli->kirby()->root($root); if ($rootPath === null) { throw new Exception('Invalid root entered: ' . $root); } + if (is_dir($rootPath) === false) { + throw new Exception('The root does not exist: ' . $root); + } + $kirbyPath = $cli->kirby()->root('index'); $backupPath = $kirbyPath . '/backup'; $backupFile = $backupPath . '/' . $root . '-' . date('Y-m-d-His') . '.zip'; @@ -37,7 +43,7 @@ } // create backup directory before the process - mkdir($backupPath); + Dir::make($backupPath); $zip = new ZipArchive(); if ($zip->open($backupFile, ZipArchive::CREATE) !== true) {