From 8648400838328b24038d619af9e18c067bdac696 Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sat, 6 Jul 2024 18:29:11 -0500 Subject: [PATCH 1/7] Replaced folder buttons with checkboxes #11 - Replaced the individual backup folder buttons with checkboxes and one Backup Selected Folders button. - This fixes the issue where buttons were going offscreen, and it adds the ability to backup multiple folders at the same time. Close #11 --- index.php | 138 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 57 deletions(-) diff --git a/index.php b/index.php index e1b3f27..2bf3574 100644 --- a/index.php +++ b/index.php @@ -195,39 +195,37 @@ function get_sibling_folders($dir) { // Check if a backup action is requested } elseif (isset($_POST['backup'])) { - - // Check if a valid backup folder is selected - if (in_array($_POST['backup'], $folders)) { - // Define the source path for backup - $source = "../{$_POST['backup']}"; + + // Check if any folders are selected for backup + if (!isset($_POST['backup_folders']) || empty($_POST['backup_folders'])) { + $message = 'No folders selected for backup.'; } else { - // Set error message for invalid backup folder selection - $message = 'Invalid backup folder selected.'; - } - - // Proceed if no error message is set - if (empty($message)) { - - // Define the destination folder name and path - $folder_name = $_POST['backup'] . '_' . preg_replace('/\s+/', '-', trim($_POST['folder_name'])); - $destination = "../" . basename($current_dir) . "/" . $folder_name; - - // Check if the destination folder already exists - if (is_dir($destination)) { - // Set error message if the destination folder already exists - $message = "The folder '$folder_name' already exists. Backup cannot be completed."; - } else { - // Perform the backup operation - $file_count = backup_folder($source, $destination); - - // Check if files are successfully backed up - if ($file_count > 0) { - // Set success message if backup operation is successful - $message = "The folder '$folder_name' has been created with $file_count files."; - $messageColor = "#28a745"; // Green color for success message + // Loop through selected folders and initiate backup + foreach ($_POST['backup_folders'] as $selected_folder) { + // Define the source path for backup + $source = "../" . $selected_folder; + + // Define the destination folder name and path + $folder_name = $selected_folder . '_' . preg_replace('/\s+/', '-', trim($_POST['folder_name'])); + $destination = "../" . basename($current_dir) . "/" . $folder_name; + + // Check if the destination folder already exists + if (is_dir($destination)) { + // Set error message if the destination folder already exists + $message .= "The folder '$folder_name' already exists. Backup cannot be completed.
"; } else { - // Set error message if backup operation fails - $message = "Failed to create the folder '$folder_name'."; + // Perform the backup operation + $file_count = backup_folder($source, $destination); + + // Check if files are successfully backed up + if ($file_count > 0) { + // Set success message if backup operation is successful + $message .= "The folder '$folder_name' has been created with $file_count files.
"; + $messageColor = "#28a745"; // Green color for success message + } else { + // Set error message if backup operation fails + $message .= "Failed to create the folder '$folder_name'.
"; + } } } } @@ -284,7 +282,7 @@ function get_sibling_folders($dir) { gap: 10px; margin-bottom: 20px; } - .button-container button, .message { + button.backup, .message { box-shadow: 0 8px 8px 1px rgba(0, 0, 0, .2); font-weight: bold; } @@ -335,6 +333,16 @@ function get_sibling_folders($dir) { table th:nth-child(3), table td:nth-child(3) { width: 10%; } + .checkbox-columns { + display: flex; + gap: 20px; + text-align: left; + } + .checkbox-column label { + display: block; + white-space: nowrap; + margin-bottom: 5px; + } .divider { border-top: 1px solid #fff; margin: 20px 0; @@ -372,6 +380,7 @@ function confirmDelete(folderName, formId) { } } + // Function to trigger update from GitHub repository's latest release function triggerUpdate() { const form = document.createElement('form'); form.method = 'post'; @@ -395,19 +404,35 @@ function triggerUpdate() {
-
- - - +
"; + for ($j = 0; $j < $folders_per_column; $j++) { + $folder_index = $j * $columns + $i; + if ($folder_index < $total_folders) { + $folder = $folders[$folder_index]; + echo "\n\t\t\t\t\t" . '
'; + } + } + echo "\n\t\t\t\t
"; + } + ?> +
+
- -
- -
- + $message"; ?>
@@ -423,26 +448,25 @@ function triggerUpdate() { $folder): ?> - - - - - -
- - -
- - + foreach ($backup_folders as $index => $folder): + ?> + + + +
+ + +
+ + + - +
- From 4e563d58484570d108949c4c0612f8c6ef17c07c Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sat, 6 Jul 2024 18:31:59 -0500 Subject: [PATCH 2/7] Removed unnecessary `$destination` variable #23 Discovered the `$destination` variable wasn't actually needed. `$folder_name` worked in its place. Close #23 --- index.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 2bf3574..5cb73cb 100644 --- a/index.php +++ b/index.php @@ -207,15 +207,14 @@ function get_sibling_folders($dir) { // Define the destination folder name and path $folder_name = $selected_folder . '_' . preg_replace('/\s+/', '-', trim($_POST['folder_name'])); - $destination = "../" . basename($current_dir) . "/" . $folder_name; // Check if the destination folder already exists - if (is_dir($destination)) { + if (is_dir($folder_name)) { // Set error message if the destination folder already exists $message .= "The folder '$folder_name' already exists. Backup cannot be completed.
"; } else { // Perform the backup operation - $file_count = backup_folder($source, $destination); + $file_count = backup_folder($source, $folder_name); // Check if files are successfully backed up if ($file_count > 0) { From d30547427b1ebb1ebc04155e026230210525e01f Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sun, 7 Jul 2024 16:07:16 -0500 Subject: [PATCH 3/7] Added $green variable for $messageColor - Replaced hardcoded green hex color with `$green` variable and set it at the top of the script with the other variables - Also removed unnecessary spaces on empty lines --- index.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/index.php b/index.php index 5cb73cb..e1386a2 100644 --- a/index.php +++ b/index.php @@ -12,6 +12,7 @@ $apiUrl = 'https://api.github.com/repos/dynamiccookies/Simple-Backup-Utility/releases'; $current_dir = getcwd(); // Get current directory $folders = get_sibling_folders($current_dir); // Get sibling folder names excluding current directory +$green = '#28a745'; $latestVersion = get_latest_release_tag($apiUrl); $message = ''; $messageColor = "#dc3545"; @@ -66,7 +67,7 @@ function compare_versions($currentVersion, $latestVersion) { // Remove 'v' prefix for comparison $currentVersionClean = ltrim($currentVersion, 'v'); $latestVersionClean = ltrim($latestVersion, 'v'); - + // Compare versions and switch on the result switch (version_compare($currentVersionClean, $latestVersionClean)) { case -1: @@ -170,12 +171,12 @@ function get_sibling_folders($dir) { if (isset($_POST['delete'])) { // Construct the path to the folder to delete $folder_to_delete = $current_dir . '/' . $_POST['delete']; - + // Attempt to delete the folder if (delete_backup_folder($folder_to_delete)) { // Set success message if deletion is successful $message = "The folder '{$_POST['delete']}' has been deleted."; - $messageColor = "#28a745"; // Green color for success message + $messageColor = $green; } else { // Set error message if deletion fails $message = "Failed to delete the folder '{$_POST['delete']}'."; @@ -195,7 +196,7 @@ function get_sibling_folders($dir) { // Check if a backup action is requested } elseif (isset($_POST['backup'])) { - + // Check if any folders are selected for backup if (!isset($_POST['backup_folders']) || empty($_POST['backup_folders'])) { $message = 'No folders selected for backup.'; @@ -204,10 +205,10 @@ function get_sibling_folders($dir) { foreach ($_POST['backup_folders'] as $selected_folder) { // Define the source path for backup $source = "../" . $selected_folder; - + // Define the destination folder name and path $folder_name = $selected_folder . '_' . preg_replace('/\s+/', '-', trim($_POST['folder_name'])); - + // Check if the destination folder already exists if (is_dir($folder_name)) { // Set error message if the destination folder already exists @@ -215,12 +216,12 @@ function get_sibling_folders($dir) { } else { // Perform the backup operation $file_count = backup_folder($source, $folder_name); - + // Check if files are successfully backed up if ($file_count > 0) { // Set success message if backup operation is successful $message .= "The folder '$folder_name' has been created with $file_count files.
"; - $messageColor = "#28a745"; // Green color for success message + $messageColor = $green; } else { // Set error message if backup operation fails $message .= "Failed to create the folder '$folder_name'.
"; @@ -407,7 +408,7 @@ function triggerUpdate() { $total_folders = count($folders); $max_columns = 4; // Maximum number of columns $columns = min($max_columns, max(1, ceil($total_folders / 2))); // Adjust columns dynamically based on folder count - + // Calculate number of folders per column $folders_per_column = ceil($total_folders / $columns); for ($i = 0; $i < $columns; $i++) { From 46c4a17e87a0e64d978aa0fed7c1374a87182216 Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sun, 7 Jul 2024 16:15:06 -0500 Subject: [PATCH 4/7] Fix #21 & #27 Backup message and count issues The count wasn't including the parent folder, so empty folders returned 0, which showed the 'Failed to create' message. - Updated the `backup_folder()` function to count the parent folder - Updated the success message to subtract the parent folder from the count total since it is called out by name in the message - Updated the success message to clarify the count total is for files & folders - Updated the fail message to explain the folder name is not a valid directory, as that's the only way the `$file_count` should return as 0 Close #21 Close #27 --- index.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/index.php b/index.php index e1386a2..8c29c3c 100644 --- a/index.php +++ b/index.php @@ -43,17 +43,20 @@ function backup_folder($source, $destination) { return 0; } @mkdir($destination, 0777, true); + $count = 1; $files = array_diff(scandir($source), array('.', '..')); + foreach ($files as $file) { $src = "$source/$file"; $dst = "$destination/$file"; if (is_dir($src)) { - backup_folder($src, $dst); + $count += backup_folder($src, $dst); } else { copy($src, $dst); + $count ++; } } - return count($files); + return $count; } /** @@ -220,11 +223,11 @@ function get_sibling_folders($dir) { // Check if files are successfully backed up if ($file_count > 0) { // Set success message if backup operation is successful - $message .= "The folder '$folder_name' has been created with $file_count files.
"; + $message .= "The folder '$folder_name' has been created with " . ($file_count - 1) . " files/folders.
"; $messageColor = $green; } else { // Set error message if backup operation fails - $message .= "Failed to create the folder '$folder_name'.
"; + $message .= "ERROR: '$folder_name' is not a valid directory!
"; } } } From 3f94394dd44098e9da44c62b10a67d5b48d5a2af Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sun, 7 Jul 2024 16:53:32 -0500 Subject: [PATCH 5/7] Add new features to README #28 - Added new update and multi-backup features to the README file - Replaced 'ZIP file' with 'latest release' and added link to latest release page - Updated the issues link to point directly to the new issue form - Added clarifications under 'Folder Structure' section - Updated 'Creating a Backup' instructions after changing functionality for #11 - Added 'Updating to Latest Version' instructions for #15 Close #28 --- README.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 292370e..903bade 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,10 @@ Simple Backup Utility is a PHP script that allows you to create and manage backu ## Features - **Backup Creation**: Easily create backups of specific folders. +- **Multiple Folder Backup**: Select and backup multiple folders simultaneously. - **Backup Deletion**: Remove existing backup folders. - **User-Friendly Interface**: Intuitive web interface for straightforward operation. +- **Easy Update**: Built-in update feature for seamless updates to the latest version. ## Requirements @@ -20,7 +22,7 @@ Simple Backup Utility is a PHP script that allows you to create and manage backu ## Installation -1. Clone the repository or download the ZIP file. +1. Clone the repository or download the [latest release](https://github.com/dynamiccookies/Simple-Backup-Utility/releases/latest). 2. Place the script (`index.php`) in the directory where you want to manage backups. 3. Ensure the directory has appropriate permissions for creating and deleting files and folders. @@ -29,17 +31,24 @@ Simple Backup Utility is a PHP script that allows you to create and manage backu ### Creating a Backup 1. Access the script via a web browser after installation. -2. Enter a name for your backup in the "Backup Name" field. -3. Click the "Backup" button for the environment folder you want to backup. +2. Enter a name for your backup(s) in the "Backup Name" field. +3. Place a checkmark next to each of the folders you'd like to backup. +4. Click the "Backup Selected Folders" button. ### Deleting a Backup 1. Click the trash icon next to the Existing Backups entry. +### Updating to Latest Version + +Only available if you see the New Version Available message in the bottom right corner of the screen. + +1. Click the (Update Now) link in the New Version Available message. +2. When the page reloads, the new version number should be shown. ## Folder Structure -The Simple Backup Utility expects the following directory structure: +The Simple Backup Utility expects the following parent/child directory structure: - Project Directory - prod - staging @@ -56,7 +65,7 @@ The script displays all of its parent directory's sibling folders. In this examp The backup process names the selected directory using the format `_` based on the selected directory to backup. -**Note:** The names of all files and folders are arbitrary and can be customized as needed. +**Note:** The names of all files and folders are arbitrary and can be customized as needed, including `index.php`. ## License @@ -65,4 +74,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Support -For any issues, questions, or feature requests, please [open an issue](https://github.com/dynamiccookies/Simple-Backup-Utility/issues). +For any issues, questions, or feature requests, please [open an issue](https://github.com/dynamiccookies/Simple-Backup-Utility/issues/new). From a999b38ad757806ebcf9fcabaf04f91ff725436c Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sun, 7 Jul 2024 17:07:00 -0500 Subject: [PATCH 6/7] Hide Existing Backups when none exist #19 - Added check for empty backup folders array - If array is empty, show 'No Backups Found' message, otherwise, show table of backups Close #19 --- index.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index 8c29c3c..d3ccce6 100644 --- a/index.php +++ b/index.php @@ -440,6 +440,14 @@ function triggerUpdate() {
+ No Backups Found'; + } else { + ?> +

Existing Backups

@@ -450,7 +458,6 @@ function triggerUpdate() { Delete $folder): ?> @@ -467,6 +474,7 @@ function triggerUpdate() { + From 54dace796f69cbd96c557f8f402646cf6aad9ac0 Mon Sep 17 00:00:00 2001 From: Chad Davis Date: Sun, 7 Jul 2024 17:11:04 -0500 Subject: [PATCH 7/7] Increment version to v0.3.0 --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index d3ccce6..5e5a433 100644 --- a/index.php +++ b/index.php @@ -4,7 +4,7 @@ // * Define constant for the current version // **************************************************************************************** date_default_timezone_set('America/Chicago'); -define('CURRENT_VERSION', 'v0.2.1'); +define('CURRENT_VERSION', 'v0.3.0'); // **************************************************************************************** // * Define variables for API URL, directories, and other data