Skip to content

Commit

Permalink
Merge pull request #14 from dynamiccookies/dev
Browse files Browse the repository at this point in the history
First Pull Request
  • Loading branch information
dynamiccookies authored Jun 21, 2024
2 parents 4fd1448 + 70f09be commit fce575c
Show file tree
Hide file tree
Showing 3 changed files with 392 additions and 2 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
on:
pull_request:
branches:
- main
- dev
types:
- closed
push:
branches:
- dev
workflow_dispatch:
name: 🚀 Deploy website based on branch
jobs:
web-deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true) ||
(github.event_name == 'push' && contains(github.ref, 'refs/heads/dev'))
steps:
- name: 🚚 Get latest code
uses: actions/checkout@v4

- name: 📂 Sync files to PROD
if: contains(github.ref, 'refs/heads/main') || (github.event_name == 'pull_request' && contains(github.base_ref, 'main'))
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PROD_FTP_SERVER }}
username: ${{ secrets.PROD_FTP_USERNAME }}
password: ${{ secrets.PROD_FTP_PASSWORD }}
server-dir: /

- name: 📂 Sync files to DEV
if: contains(github.ref, 'refs/heads/dev')
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.DEV_FTP_SERVER }}
username: ${{ secrets.DEV_FTP_USERNAME }}
password: ${{ secrets.DEV_FTP_PASSWORD }}
server-dir: /
exclude: |
LICENSE
README.md
70 changes: 68 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,68 @@
# Simple-Backup-Utility
Simple PHP backup utility to copy an entire directory into a backup folder.
# Simple Backup Utility
![GitHub](https://img.shields.io/github/license/dynamiccookies/Simple-Backup-Utility?style=for-the-badge "License")
![GitHub file size in bytes](https://img.shields.io/github/size/dynamiccookies/Simple-Backup-Utility/index.php?style=for-the-badge)
![GitHub Release Date](https://img.shields.io/github/release-date/dynamiccookies/Simple-Backup-Utility?style=for-the-badge "Release Date")
![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/dynamiccookies/Simple-Backup-Utility?display_name=tag&include_prereleases&sort=semver&style=for-the-badge "Release Version")
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=0077b6">](https://github.com/SamKirkland/FTP-Deploy-Action)

Simple Backup Utility is a PHP script that allows you to create and manage backups of sibling folders within the same directory.

## Features

- **Backup Creation**: Easily create backups of specific folders.
- **Backup Deletion**: Remove existing backup folders.
- **User-Friendly Interface**: Intuitive web interface for straightforward operation.

## Requirements

- PHP (version 5.6 or higher recommended)
- Web server (e.g., Apache, Nginx)

## Installation

1. Clone the repository or download the ZIP file.
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.

## Usage

### 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.

### Deleting a Backup

1. Click the trash icon next to the Existing Backups entry.


## Folder Structure

The Simple Backup Utility expects the following directory structure:
- Project Directory
- prod
- staging
- test
- dev
- backups
- **index.php** (this script)
- prod_release-v1
- staging_benchmark-tests
- test_data-fixtures
- dev_feature-branch-backup

The script displays all of its parent directory's sibling folders. In this example, prod, staging, test, and dev.

The backup process names the selected directory using the format `<source folder>_<backup-name>` based on the selected directory to backup.

**Note:** The names of all files and folders are arbitrary and can be customized as needed.


## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Support

For any issues, questions, or feature requests, please [open an issue](https://github.com/dynamiccookies/Simple-Backup-Utility/issues).
280 changes: 280 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
<?php
date_default_timezone_set('America/Chicago'); // Set timezone to CST

function backup_folder($source, $destination) {
if (!is_dir($source)) {
return 0;
}
@mkdir($destination, 0777, true);
$files = array_diff(scandir($source), array('.', '..'));
foreach ($files as $file) {
$src = "$source/$file";
$dst = "$destination/$file";
if (is_dir($src)) {
backup_folder($src, $dst);
} else {
copy($src, $dst);
}
}
return count($files);
}

function get_sibling_folders($dir) {
$parent_dir = dirname($dir);
$folders = array_filter(glob($parent_dir . '/*'), 'is_dir');
$sibling_folders = [];
foreach ($folders as $folder) {
$folder_name = basename($folder);
if ($folder_name !== basename($dir)) {
$sibling_folders[] = $folder_name;
}
}
return $sibling_folders;
}

function get_backup_folders($dir) {
$folders = array_filter(glob($dir . '/*'), 'is_dir');
$backup_folders = [];
foreach ($folders as $folder) {
$folder_name = basename($folder);
$created_timestamp = filectime($folder); // Raw timestamp for sorting
$created_date = date('m/d/y h:i:s A', $created_timestamp); // Human-readable format for display

$backup_folders[] = [
'name' => $folder_name,
'created_date' => $created_date,
'created_timestamp' => $created_timestamp // Add timestamp for sorting
];
}
// Sort by created_timestamp in descending order
usort($backup_folders, function($a, $b) {
return $b['created_timestamp'] - $a['created_timestamp'];
});
return $backup_folders;
}

function delete_backup_folder($folder) {
if (!is_dir($folder)) {
return false;
}
$files = array_diff(scandir($folder), array('.', '..'));
foreach ($files as $file) {
$path = "$folder/$file";
is_dir($path) ? delete_backup_folder($path) : unlink($path);
}
return rmdir($folder);
}

$message = '';
$messageColor = "#dc3545";
$current_dir = getcwd(); // Get current directory
$folders = get_sibling_folders($current_dir); // Get sibling folder names excluding current directory

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['delete'])) {
$folder_to_delete = $current_dir . '/' . $_POST['delete'];
if (delete_backup_folder($folder_to_delete)) {
$message = "The folder '{$_POST['delete']}' has been deleted.";
$messageColor = "#28a745";
} else {
$message = "Failed to delete the folder '{$_POST['delete']}'.";
}
} else {
$input_name = preg_replace('/\s+/', '-', trim($_POST['folder_name'])); // Replace spaces with dashes

if (isset($_POST['backup']) && in_array($_POST['backup'], $folders)) {
$source = "../{$_POST['backup']}";
} else {
$message = 'Invalid backup folder selected.';
}

if (empty($message)) {
$folder_name = $_POST['backup'] . '_' . $input_name;
$destination = "../" . basename($current_dir) . "/" . $folder_name;

if (is_dir($destination)) {
$message = "The folder '$folder_name' already exists. Backup cannot be completed.";
} else {
$file_count = backup_folder($source, $destination);
if ($file_count > 0) {
$message = "The folder '$folder_name' has been created with $file_count files.";
$messageColor = "#28a745";
} else {
$message = "Failed to create the folder '$folder_name'.";
}
}
}
}
}

$backup_folders = get_backup_folders($current_dir);

// Array of colors
$colors = [
"blue", "blueviolet", "brown", "cadetblue", "chocolate", "crimson", "darkblue",
"darkcyan", "darkgray", "darkgreen", "darkmagenta", "darkolivegreen", "darkorchid",
"darkred", "darkslateblue", "darkslategray", "darkviolet", "deeppink", "dimgray",
"firebrick", "forestgreen", "gray", "green", "indianred", "magenta", "maroon",
"mediumblue", "mediumvioletred", "midnightblue", "navy", "orangered", "palevioletred",
"peru", "purple", "rebeccapurple", "red", "seagreen", "sienna", "slategray", "steelblue",
"teal", "tomato"
];

// Randomly select a color
$random_color = $colors[array_rand($colors)];
?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Backup Utility</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<style>
body {
background-color: #000;
color: #fff;
font-family: Arial, sans-serif;
text-align: center;
}
.container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
border: 2px solid #fff;
border-radius: 10px;
background-color: <?php echo $random_color; ?>;
}
h1, h2 {
color: #fff;
}
form {
margin-bottom: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
input[type="text"] {
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
width: 75%;
box-sizing: border-box;
margin-bottom: 10px;
text-align: center;
}
.button-container {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
}
.button-container button {
box-shadow: 0 8px 8px 1px rgba(0, 0, 0, .2);
font-weight: bold;
}
button {
padding: 10px 20px;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
background-color: #007bff;
color: #fff;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #0056b3;
}
.message {
background-color: <?php echo "$messageColor"; ?>;
color: #fff;
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table th, table td {
border: 1px solid #fff;
padding: 10px;
color: #000;
}
table th {
background-color: #007bff;
color: #fff;
}
table tr:nth-child(even) {
background-color: #f0f0f0;
}
table tr:nth-child(odd) {
background-color: #e9ecef;
}
table th:nth-child(1), table th:nth-child(2),
table td:nth-child(1), table td:nth-child(2) {
width: 45%;
}
table th:nth-child(3), table td:nth-child(3) {
width: 10%;
}
.divider {
border-top: 1px solid #fff;
margin: 20px 0;
}
.trash-icon {
cursor: pointer;
background: none;
border: none;
color: #dc3545;
font-size: 16px;
}
.trash-icon:hover {
color: #c82333;
}
</style>
</head>
<body>
<div class="container">
<h1>Backup Utility</h1>
<form method="POST">
<input type="text" id="folder_name" name="folder_name" placeholder="Backup Name" required>
<div class="button-container">
<?php foreach ($folders as $folder) : ?>
<button type="submit" name="backup" value="<?php echo $folder; ?>">Backup <?php echo ucfirst($folder); ?></button>
<?php endforeach; ?>
</div>
</form>
<?php if ($message): ?>
<div class="message">
<?php echo htmlspecialchars($message); ?>
</div>
<?php endif; ?>
<div class="divider"></div> <!-- Horizontal divider line -->
<h2>Existing Backups</h2>
<table>
<tr>
<th>Backup</th>
<th>Created Date (CST)</th>
<th>Delete</th>
</tr>
<?php foreach ($backup_folders as $index => $folder): ?>
<tr style="background-color: <?php echo $index % 2 == 0 ? '#e9ecef' : '#f0f0f0'; ?>">
<td><?php echo htmlspecialchars($folder['name']); ?></td>
<td><?php echo htmlspecialchars($folder['created_date']); ?></td>
<td>
<form method="POST" style="display:inline;">
<button type="submit" name="delete" value="<?php echo htmlspecialchars($folder['name']); ?>" class="trash-icon">
<i class="fa fa-trash"></i>
</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
</body>
</html>

0 comments on commit fce575c

Please sign in to comment.