Files
MokoSuiteBackup/source/packages/com_mokosuitebackup/src/Engine/FileRestorer.php
T

125 lines
2.9 KiB
PHP
Raw Normal View History

<?php
/**
* @package MokoSuiteBackup
* @subpackage com_mokosuitebackup
* @author Moko Consulting <hello@mokoconsulting.tech>
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*
* Restores files from a staging directory to the Joomla root.
* Skips database.sql and sensitive files that should not be overwritten.
*/
namespace Joomla\Component\MokoSuiteBackup\Administrator\Engine;
defined('_JEXEC') or die;
class FileRestorer
{
private string $sourceDir;
private string $targetDir;
/**
* Files that should never be overwritten during restore.
* configuration.php is rebuilt from .bak + user input by RestoreEngine.
*/
private const SKIP_FILES = [
'configuration.php',
'configuration.php.bak',
'.htaccess',
'web.config',
];
/**
* Files that are backup artifacts, not part of the site.
*/
private const EXCLUDE_FILES = [
'database.sql',
];
public function __construct(string $sourceDir, string $targetDir)
{
$this->sourceDir = rtrim($sourceDir, '/\\');
$this->targetDir = rtrim($targetDir, '/\\');
}
/**
* Copy files from staging to target, preserving directory structure.
*
* @return int Number of files restored
*/
public function restore(): int
{
$count = 0;
$this->restoreDirectory('', $count);
return $count;
}
private function restoreDirectory(string $relativePath, int &$count): void
{
$sourcePath = $this->sourceDir . ($relativePath ? '/' . $relativePath : '');
if (!is_dir($sourcePath)) {
return;
}
$handle = opendir($sourcePath);
if ($handle === false) {
return;
}
while (($entry = readdir($handle)) !== false) {
if ($entry === '.' || $entry === '..') {
continue;
}
$entryRelative = $relativePath ? $relativePath . '/' . $entry : $entry;
$entrySource = $sourcePath . '/' . $entry;
$entryTarget = $this->targetDir . '/' . $entryRelative;
if (is_dir($entrySource)) {
// Create target directory if it doesn't exist
if (!is_dir($entryTarget)) {
mkdir($entryTarget, 0755, true);
}
$this->restoreDirectory($entryRelative, $count);
} elseif (is_file($entrySource)) {
// Skip excluded files
if (in_array($entry, self::EXCLUDE_FILES, true)) {
continue;
}
// Skip protected files (only at root level)
if ($relativePath === '' && in_array($entry, self::SKIP_FILES, true)) {
continue;
}
// Ensure parent directory exists
$parentDir = dirname($entryTarget);
if (!is_dir($parentDir)) {
mkdir($parentDir, 0755, true);
}
// Copy file, preserving permissions
if (copy($entrySource, $entryTarget)) {
// Try to match original permissions
$perms = fileperms($entrySource);
if ($perms !== false) {
@chmod($entryTarget, $perms);
}
$count++;
}
}
}
closedir($handle);
}
}