2026-06-02 14:58:21 -05:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/**
|
2026-06-11 12:24:27 -05:00
|
|
|
* @package MokoSuiteBackup
|
|
|
|
|
* @subpackage com_mokosuitebackup
|
2026-06-02 14:58:21 -05:00
|
|
|
* @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
|
|
|
|
|
*
|
|
|
|
|
* Imports a SQL dump file created by DatabaseDumper.
|
|
|
|
|
* Handles #__ prefix replacement, multi-statement execution,
|
|
|
|
|
* and DROP TABLE before CREATE TABLE for clean restores.
|
|
|
|
|
*/
|
|
|
|
|
|
2026-06-11 12:24:27 -05:00
|
|
|
namespace Joomla\Component\MokoSuiteBackup\Administrator\Engine;
|
2026-06-02 14:58:21 -05:00
|
|
|
|
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
|
|
|
|
|
|
use Joomla\CMS\Factory;
|
|
|
|
|
|
|
|
|
|
class DatabaseImporter
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Import a SQL dump file into the database.
|
|
|
|
|
*
|
|
|
|
|
* @param string $sqlFile Absolute path to the SQL dump file
|
|
|
|
|
*
|
|
|
|
|
* @return int Number of statements executed
|
|
|
|
|
*
|
|
|
|
|
* @throws \RuntimeException On import failure
|
|
|
|
|
*/
|
|
|
|
|
public function import(string $sqlFile): int
|
|
|
|
|
{
|
|
|
|
|
if (!is_file($sqlFile) || !is_readable($sqlFile)) {
|
|
|
|
|
throw new \RuntimeException('SQL file not readable: ' . $sqlFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$db = Factory::getDbo();
|
|
|
|
|
$prefix = $db->getPrefix();
|
|
|
|
|
|
|
|
|
|
$handle = fopen($sqlFile, 'r');
|
|
|
|
|
|
|
|
|
|
if ($handle === false) {
|
|
|
|
|
throw new \RuntimeException('Cannot open SQL file: ' . $sqlFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$statementsExecuted = 0;
|
|
|
|
|
$currentStatement = '';
|
|
|
|
|
$inMultiLineComment = false;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
while (($line = fgets($handle)) !== false) {
|
|
|
|
|
$trimmed = trim($line);
|
|
|
|
|
|
|
|
|
|
// Skip empty lines
|
|
|
|
|
if ($trimmed === '') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skip single-line comments
|
|
|
|
|
if (str_starts_with($trimmed, '--') || str_starts_with($trimmed, '#')) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle multi-line comments
|
|
|
|
|
if (str_starts_with($trimmed, '/*')) {
|
|
|
|
|
$inMultiLineComment = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($inMultiLineComment) {
|
|
|
|
|
if (str_contains($trimmed, '*/')) {
|
|
|
|
|
$inMultiLineComment = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Accumulate the statement
|
|
|
|
|
$currentStatement .= $line;
|
|
|
|
|
|
|
|
|
|
// Check if statement is complete (ends with semicolon)
|
|
|
|
|
if (str_ends_with($trimmed, ';')) {
|
|
|
|
|
$statement = trim($currentStatement);
|
|
|
|
|
$currentStatement = '';
|
|
|
|
|
|
|
|
|
|
if (empty($statement)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-18 10:42:05 -05:00
|
|
|
// Replace abstract #__ prefix with the current site's prefix
|
|
|
|
|
$statement = str_replace('#__', $prefix, $statement);
|
2026-06-02 14:58:21 -05:00
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$db->setQuery($statement);
|
|
|
|
|
$db->execute();
|
|
|
|
|
$statementsExecuted++;
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
// Log but don't abort — some statements may fail on
|
|
|
|
|
// different MySQL versions (e.g. charset differences)
|
|
|
|
|
// but the overall restore should continue.
|
2026-06-11 12:24:27 -05:00
|
|
|
error_log('MokoSuiteBackup SQL import warning: ' . $e->getMessage());
|
2026-06-02 14:58:21 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Execute any remaining statement without trailing semicolon
|
|
|
|
|
$remaining = trim($currentStatement);
|
|
|
|
|
|
|
|
|
|
if (!empty($remaining)) {
|
|
|
|
|
try {
|
|
|
|
|
$db->setQuery($remaining);
|
|
|
|
|
$db->execute();
|
|
|
|
|
$statementsExecuted++;
|
|
|
|
|
} catch (\Exception $e) {
|
2026-06-11 12:24:27 -05:00
|
|
|
error_log('MokoSuiteBackup SQL import warning (final): ' . $e->getMessage());
|
2026-06-02 14:58:21 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
fclose($handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $statementsExecuted;
|
|
|
|
|
}
|
|
|
|
|
}
|