# 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
- [x] On-demand database backup creation
- [x] Automatic file compression (optional)
- [x] Cross-platform mysqldump execution
- [x] Streaming download for large files
- [x] Temporary file cleanup
- [x] Error handling and validation
- [x] Session-based database selection
- [x] Memory and timeout optimization

### Related Controllers
- [backupController.md](backupController.md) - Scheduled backup management
- [programsettingsController.md](programsettingsController.md) - System configuration

---

## 🗄️ Database Tables

| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **programsettings** | System configuration | programsettingsid, 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**:
```php
// 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**:
```php
function find_mysqldump($baseDirs)
```

**Path Detection Logic**:
```php
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               │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. System Preparation                                     │
│     ├─→ Set unlimited time and memory limits               │
│     ├─→ Validate session has database name                 │
│     ├─→ Load program settings and compression options      │
│     └─→ Create backup directory if needed                  │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Platform-Specific Command Generation                  │
│     ├─→ Detect operating system (Windows/Unix)            │
│     ├─→ Find mysqldump executable path                    │
│     ├─→ Build mysqldump command with compression          │
│     └─→ Set appropriate output redirection                │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Database Backup Execution                              │
│     ├─→ Execute mysqldump command                         │
│     ├─→ Verify command execution success                  │
│     ├─→ Check backup file creation and size               │
│     └─→ Handle execution errors if any                    │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. File Streaming and Download                           │
│     ├─→ Set appropriate download headers                  │
│     ├─→ Stream file in small chunks (4KB)                 │
│     ├─→ Monitor connection status                         │
│     ├─→ Flush output periodically                        │
│     └─→ Handle connection interruptions                   │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  5. Cleanup and Completion                                 │
│     ├─→ Close file handle                                  │
│     ├─→ Delete temporary backup file                      │
│     ├─→ Check for any remaining connections               │
│     └─→ Exit process cleanly                              │
└─────────────────────────────────────────────────────────────┘
```

---

## 🧮 Technical Implementation

### Platform Detection and Command Building
```php
// 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
```php
// 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
```php
// 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
- **Session Validation**: Requires valid database session
- **Path Traversal Protection**: Uses absolute paths only
- **Error Suppression**: Prevents password exposure in error messages
- **File Cleanup**: Removes temporary files after download

### 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
```php
// 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
```php
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**:
```php
// 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:
```php
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**:
```bash
chmod 755 /Applications/AMPPS/www/erp19/db_backups/
chown www-data:www-data /Applications/AMPPS/www/erp19/db_backups/
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [backupController.md](backupController.md) - Scheduled backup system
- [programsettingsController.md](programsettingsController.md) - System settings

---

**Documented By**: AI Assistant  
**Review Status**: ✅ Complete  
**Next Review**: When major changes occur