๐Ÿ“š ERP Documentation Viewer

Beautiful, colorful documentation for your ERP system

Manual Backup Controller Documentation

File: /controllers/manualBackup.php

Purpose: Provides on-demand database backup functionality with compression and streaming download capabilities

Last Updated: December 20, 2024

Total Functions: 1 main action + helper functions

Lines of Code: ~206

---

๐Ÿ“‹ Overview

The Manual Backup Controller enables administrators to create immediate database backups that are automatically downloaded. It supports both compressed and uncompressed formats, handles large databases with streaming, and provides cross-platform compatibility for Windows and Unix-based systems.

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Table NamePurposeKey Columns
**programsettings**System configurationprogramsettingsid, reportsPlusHours, partition
---

๐Ÿ”‘ Key Functions

1. Main Backup Process - Database Backup and Download

Location: Lines 59-205

Purpose: Create database backup and stream to user for download

Process Flow:

1. Environment Setup: Configure memory and execution limits

2. Session Validation: Verify database name in session

3. Directory Creation: Ensure backup directory exists

4. Compression Configuration: Load backup settings from JSON

5. Platform Detection: Determine Windows vs Unix execution path

6. Backup Execution: Run mysqldump command

7. File Validation: Verify backup creation and size

8. Stream Download: Send file to user with appropriate headers

9. Cleanup: Remove temporary backup file

System Requirements Setup:

// Optimize for large database backups
set_time_limit(0);                    // No timeout
ini_set('memory_limit', '1024M');     // 1GB memory
ini_set('max_execution_time', 0);     // No execution timeout

// Disable output buffering for streaming
if (ob_get_level()) {
    ob_end_clean();
}

2. find_mysqldump() - Windows Path Detection

Location: Lines 114-131

Purpose: Locate mysqldump.exe on Windows WAMP installations

Function Signature:

function find_mysqldump($baseDirs)

Path Detection Logic:

foreach ($baseDirs as $baseDir) {
    $mysqlPath = $baseDir . '\\bin\\mysql';
    if (!is_dir($mysqlPath)) continue;
    
    $versions = scandir($mysqlPath);
    foreach ($versions as $version) {
        if ($version === '.' || $version === '..') continue;
        
        $dumpPath = $mysqlPath . '\\' . $version . '\\bin\\mysqldump.exe';
        if (file_exists($dumpPath)) {
            return $dumpPath;
        }
    }
}

---

๐Ÿ”„ Workflows

Backup Creation Workflow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: User Requests Manual Backup
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1System Preparation
โ†’ Set unlimited time and memory limits
โ†’ Validate session has database name
โ†’ Load program settings and compression options
โ”‚ โ””โ”€โ†’ Create backup directory if needed โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Platform-Specific Command Generation
โ†’ Detect operating system (Windows/Unix)
โ†’ Find mysqldump executable path
โ†’ Build mysqldump command with compression
โ”‚ โ””โ”€โ†’ Set appropriate output redirection โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Database Backup Execution
โ†’ Execute mysqldump command
โ†’ Verify command execution success
โ†’ Check backup file creation and size
โ”‚ โ””โ”€โ†’ Handle execution errors if any โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4File Streaming and Download
โ†’ Set appropriate download headers
โ†’ Stream file in small chunks (4KB)
โ†’ Monitor connection status
โ†’ Flush output periodically
โ”‚ โ””โ”€โ†’ Handle connection interruptions โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Cleanup and Completion
โ†’ Close file handle
โ†’ Delete temporary backup file
โ†’ Check for any remaining connections
โ”‚ โ””โ”€โ†’ Exit process cleanly โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐Ÿงฎ Technical Implementation

Platform Detection and Command Building

// Cross-platform backup command generation
if (empty($partition) || $partition == "0") {
    // Linux/Unix/macOS
    if ($compressed == 1) {
        $command = "mysqldump --user=$db_user --password=$db_password --host=$host " .
                  "--opt --single-transaction --quick --lock-tables=false $dbname | " .
                  "gzip > $filepath 2>/dev/null";
    } else {
        $command = "mysqldump --user=$db_user --password=$db_password --host=$host " .
                  "--opt --single-transaction --quick --lock-tables=false $dbname > " .
                  "$filepath 2>/dev/null";
    }
    exec($command, $output, $result);
} else {
    // Windows
    $pathToWampMysqldump = find_mysqldump([$partition . ':\\wamp', $partition . ':\\wamp64']);
    
    if ($compressed == 1 && file_exists("C:\gzip\bin\gzip.exe")) {
        $command = "$pathToWampMysqldump --user=$db_user --password=$db_password " .
                  "--host=$host --opt --single-transaction --quick --lock-tables=false " .
                  "$dbname | C:\\gzip\\bin\\gzip.exe > $filepath";
    } else {
        $command = "$pathToWampMysqldump --user=$db_user --password=$db_password " .
                  "--host=$host --opt --single-transaction --quick --lock-tables=false " .
                  "$dbname > $filepath";
    }
    passthru($command);
}

Streaming Download with Keep-Alive

// Stream file to output with connection monitoring
$handle = fopen($filepath, 'rb');
if ($handle) {
    $chunk_size = 4096; // 4KB chunks for better streaming
    $total_sent = 0;
    $file_size = filesize($filepath);
    
    while (!feof($handle)) {
        $chunk = fread($handle, $chunk_size);
        if ($chunk === false) break;
        
        echo $chunk;
        $total_sent += strlen($chunk);
        
        // Flush output every 100KB to prevent timeout
        if ($total_sent % (100 * 1024) < $chunk_size) {
            flush();
            
            // Check connection status
            if (connection_status() != CONNECTION_NORMAL) {
                break;
            }
        }
    }
    fclose($handle);
}

Compression Configuration

// Load compression settings from backupset.json
if (!file_exists('../backupset.json')) {
    $data = array('daily' => 5, 'compressed' => 1);
    $json_data = json_encode($data);
    file_put_contents('../backupset.json', $json_data);
}
$json_data = file_get_contents('../backupset.json');
$data = json_decode($json_data, true);
$compressed = isset($data['compressed']) ? $data['compressed'] : 1;

---

๐Ÿ”’ Security & Performance

Security Features

Performance Optimizations

1. Memory Management: 1GB memory limit for large databases

2. Timeout Handling: Unlimited execution time

3. Streaming: 4KB chunks to prevent memory overflow

4. Compression: Reduces file size by ~70% for text data

5. Connection Monitoring: Handles interrupted downloads

Error Handling

// Validation checks
if (!isset($_SESSION['dbname']) || empty($_SESSION['dbname'])) {
    http_response_code(400);
    die("Database name not found in session. Please login again.");
}

if (!file_exists($filepath) || filesize($filepath) == 0) {
    http_response_code(500);
    die("Backup file was not created or is empty. Please check database permissions.");
}

if ($result !== 0) {
    http_response_code(500);
    die("mysqldump command failed. Please check database connection and permissions.");
}

---

๐Ÿ“Š File Naming Convention

Automatic Filename Generation

if ($compressed == 1) {
    $filename = $dbname . '_' . date("Y-m-d_H-i-s") . '.sql.gz';
} else {
    $filename = $dbname . '_' . date("Y-m-d_H-i-s") . '.sql';
}

// Example outputs:
// myerp_2024-12-20_14-30-25.sql.gz (compressed)
// myerp_2024-12-20_14-30-25.sql (uncompressed)

Directory Structure

/Applications/AMPPS/www/erp19/
โ””โ”€โ”€ db_backups/
    โ””โ”€โ”€ temp__manualBackup/
        โ”œโ”€โ”€ database1_2024-12-20_14-30-25.sql.gz
        โ””โ”€โ”€ database2_2024-12-20_15-45-10.sql

---

๐Ÿงช Testing Scenarios

Test Case 1: Basic Backup Creation

1. Login with valid database session
2. Access manual backup URL
3. Verify backup file downloads
4. Check file integrity and size
5. Test backup restoration

Test Case 2: Compression Testing

1. Enable compression in backupset.json
2. Create backup and verify .gz extension
3. Disable compression and verify .sql extension  
4. Compare file sizes between compressed/uncompressed

Test Case 3: Large Database Handling

1. Test with database > 100MB
2. Monitor memory usage during backup
3. Verify streaming download completion
4. Test connection interruption handling

Test Case 4: Cross-Platform Compatibility

1. Test on Windows WAMP environment
2. Test on Linux/macOS with mysqldump
3. Verify path detection for different WAMP versions
4. Test with different MySQL versions

---

๐Ÿ› Common Issues & Troubleshooting

1. mysqldump Command Not Found

Issue: Command execution fails

Cause: mysqldump not in system PATH or incorrect path detection

Fix:

// Manual path override for Windows
$pathToWampMysqldump = "C:\\wamp64\\bin\\mysql\\mysql8.0.21\\bin\\mysqldump.exe";

// For Linux, ensure mysqldump is installed
sudo apt-get install mysql-client-core-8.0

2. Large Database Timeout

Issue: Backup fails for large databases

Cause: Default timeout limits

Fix: Already implemented in controller:

set_time_limit(0);
ini_set('max_execution_time', 0);

3. Permission Errors

Issue: Cannot create backup directory or files

Cause: Insufficient file system permissions

Fix:

chmod 755 /Applications/AMPPS/www/erp19/db_backups/
chown www-data:www-data /Applications/AMPPS/www/erp19/db_backups/

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur

โ†‘