243 lines
9.0 KiB
PHP
243 lines
9.0 KiB
PHP
<?php
|
|
/**
|
|
* 🗄️ INSTALADOR DE BASE DE DATOS - WhatsApp Bot
|
|
* Crea todas las tablas necesarias y corrige inconsistencias
|
|
*/
|
|
|
|
// Headers para mostrar errores
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 1);
|
|
set_time_limit(120); // 2 minutos máximo
|
|
|
|
echo "<!DOCTYPE html><html><head><meta charset='UTF-8'>";
|
|
echo "<title>🗄️ Instalador BD</title>";
|
|
echo "<style>body{font-family:monospace;margin:20px;background:#000;color:#00ff00}";
|
|
echo ".ok{color:#00ff00}.error{color:#ff0040}.warning{color:#ffaa00}";
|
|
echo ".section{background:#111;padding:15px;margin:10px 0;border:1px solid #333}";
|
|
echo "pre{background:#222;padding:10px;color:#ccc;overflow:auto;max-height:200px}";
|
|
echo "</style></head><body>";
|
|
|
|
echo "<h1>🗄️ INSTALADOR DE BASE DE DATOS</h1>";
|
|
|
|
// Cargar configuración
|
|
try {
|
|
require_once 'config/config.php';
|
|
} catch (Exception $e) {
|
|
echo "<div class='error'>❌ Error cargando configuración: " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
exit;
|
|
}
|
|
|
|
// Verificar que existe el archivo schema.sql
|
|
if (!file_exists('database/schema.sql')) {
|
|
echo "<div class='error'>❌ CRÍTICO: database/schema.sql no encontrado</div>";
|
|
exit;
|
|
}
|
|
|
|
// Conectar a la base de datos
|
|
try {
|
|
$dsn = "mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
|
|
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
|
|
]);
|
|
|
|
echo "<div class='ok'>✅ Conectado a la base de datos</div>";
|
|
|
|
} catch (PDOException $e) {
|
|
echo "<div class='error'>❌ Error de conexión: " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
exit;
|
|
}
|
|
|
|
// Leer archivo SQL
|
|
$sql_content = file_get_contents('database/schema.sql');
|
|
if (!$sql_content) {
|
|
echo "<div class='error'>❌ No se pudo leer database/schema.sql</div>";
|
|
exit;
|
|
}
|
|
|
|
echo "<div class='section'>";
|
|
echo "<h2>📋 EJECUTANDO SCHEMA SQL...</h2>";
|
|
|
|
// Separar comandos SQL
|
|
$commands = array_filter(
|
|
array_map('trim', explode(';', $sql_content)),
|
|
function($cmd) {
|
|
return !empty($cmd) && !preg_match('/^\s*--/', $cmd);
|
|
}
|
|
);
|
|
|
|
$success_count = 0;
|
|
$error_count = 0;
|
|
|
|
foreach ($commands as $i => $command) {
|
|
if (empty(trim($command))) continue;
|
|
|
|
// Mostrar progreso cada 5 comandos
|
|
if ($i % 5 === 0) {
|
|
echo "<div class='warning'>Procesando comando " . ($i + 1) . "/" . count($commands) . "...</div>";
|
|
flush();
|
|
}
|
|
|
|
try {
|
|
$pdo->exec($command);
|
|
$success_count++;
|
|
|
|
// Solo mostrar detalles de CREATE TABLE y INSERT importantes
|
|
if (preg_match('/CREATE TABLE (\w+)/', $command, $matches)) {
|
|
echo "<div class='ok'>✅ Tabla '{$matches[1]}' creada</div>";
|
|
} elseif (preg_match('/INSERT INTO (\w+)/', $command, $matches) && $i < 10) {
|
|
echo "<div class='ok'>✅ Datos insertados en '{$matches[1]}'</div>";
|
|
}
|
|
|
|
} catch (PDOException $e) {
|
|
$error_count++;
|
|
|
|
// Si es error de tabla existente, es OK
|
|
if (strpos($e->getMessage(), 'already exists') !== false) {
|
|
if (preg_match('/CREATE TABLE (\w+)/', $command, $matches)) {
|
|
echo "<div class='warning'>⚠️ Tabla '{$matches[1]}' ya existe</div>";
|
|
}
|
|
} else {
|
|
echo "<div class='error'>❌ Error en comando " . ($i + 1) . ": " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
if (strlen($command) < 200) {
|
|
echo "<pre>" . htmlspecialchars($command) . "</pre>";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
echo "<div class='ok'>📊 Comandos exitosos: $success_count</div>";
|
|
echo "<div class='error'>📊 Errores: $error_count</div>";
|
|
|
|
echo "</div>";
|
|
|
|
// Ahora crear tablas adicionales que faltan
|
|
echo "<div class='section'>";
|
|
echo "<h2>🔧 CREANDO TABLAS FALTANTES...</h2>";
|
|
|
|
// Crear tabla 'conversations' como alias de conversations
|
|
try {
|
|
$pdo->exec("
|
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
user_id INT NOT NULL,
|
|
phone_number VARCHAR(20) NOT NULL,
|
|
message_text TEXT,
|
|
direction ENUM('incoming', 'outgoing') NOT NULL,
|
|
message_type ENUM('text', 'image', 'audio', 'video', 'document', 'template') DEFAULT 'text',
|
|
status ENUM('sent', 'delivered', 'read', 'failed') DEFAULT 'sent',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
INDEX idx_phone (phone_number),
|
|
INDEX idx_direction (direction),
|
|
INDEX idx_created (created_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
");
|
|
echo "<div class='ok'>✅ Tabla 'conversations' creada</div>";
|
|
} catch (PDOException $e) {
|
|
if (strpos($e->getMessage(), 'already exists') === false) {
|
|
echo "<div class='error'>❌ Error creando tabla conversations: " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
} else {
|
|
echo "<div class='warning'>⚠️ Tabla 'conversations' ya existe</div>";
|
|
}
|
|
}
|
|
|
|
// Crear tabla 'system_config' como alias de system_config
|
|
try {
|
|
$pdo->exec("
|
|
CREATE TABLE IF NOT EXISTS system_config (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
setting_key VARCHAR(100) UNIQUE NOT NULL,
|
|
setting_value TEXT,
|
|
description TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
");
|
|
echo "<div class='ok'>✅ Tabla 'system_config' creada</div>";
|
|
} catch (PDOException $e) {
|
|
if (strpos($e->getMessage(), 'already exists') === false) {
|
|
echo "<div class='error'>❌ Error creando tabla system_config: " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
} else {
|
|
echo "<div class='warning'>⚠️ Tabla 'system_config' ya existe</div>";
|
|
}
|
|
}
|
|
|
|
echo "</div>";
|
|
|
|
// Copiar datos de system_config a system_config si no existen
|
|
echo "<div class='section'>";
|
|
echo "<h2>📊 SINCRONIZANDO CONFIGURACIÓN...</h2>";
|
|
|
|
try {
|
|
// Copiar datos de system_config a system_config
|
|
$pdo->exec("
|
|
INSERT IGNORE INTO system_config (setting_key, setting_value, description, created_at)
|
|
SELECT config_key, config_value, description, created_at
|
|
FROM system_config
|
|
WHERE config_key IS NOT NULL
|
|
");
|
|
|
|
$affected = $pdo->lastInsertId();
|
|
echo "<div class='ok'>✅ Configuraciones sincronizadas</div>";
|
|
|
|
} catch (PDOException $e) {
|
|
echo "<div class='warning'>⚠️ Error sincronizando: " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
}
|
|
|
|
// Verificar que el SECRET_KEY esté definido
|
|
try {
|
|
if (!defined('SECRET_KEY') || empty(SECRET_KEY)) {
|
|
$secret_key = bin2hex(random_bytes(32));
|
|
$pdo->prepare("INSERT INTO system_config (setting_key, setting_value, description) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)")
|
|
->execute(['SECRET_KEY', $secret_key, 'Clave secreta para encriptación']);
|
|
echo "<div class='ok'>✅ SECRET_KEY generada y guardada</div>";
|
|
echo "<div class='warning'>🔑 IMPORTANTE: Agrega esta línea a config/config.php:</div>";
|
|
echo "<pre>define('SECRET_KEY', '$secret_key');</pre>";
|
|
}
|
|
} catch (Exception $e) {
|
|
echo "<div class='error'>❌ Error generando SECRET_KEY: " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
}
|
|
|
|
echo "</div>";
|
|
|
|
// Verificación final
|
|
echo "<div class='section'>";
|
|
echo "<h2>✅ VERIFICACIÓN FINAL</h2>";
|
|
|
|
$required_tables = ['conversations', 'conversations', 'system_config', 'message_templates', 'users', 'menus'];
|
|
$missing_tables = [];
|
|
|
|
foreach ($required_tables as $table) {
|
|
try {
|
|
$stmt = $pdo->query("SHOW TABLES LIKE '$table'");
|
|
if ($stmt->rowCount() > 0) {
|
|
// Contar registros
|
|
$count_stmt = $pdo->query("SELECT COUNT(*) as count FROM $table");
|
|
$count = $count_stmt->fetch()['count'];
|
|
echo "<div class='ok'>✅ Tabla '$table' existe ($count registros)</div>";
|
|
} else {
|
|
$missing_tables[] = $table;
|
|
}
|
|
} catch (Exception $e) {
|
|
echo "<div class='error'>❌ Error verificando tabla '$table': " . htmlspecialchars($e->getMessage()) . "</div>";
|
|
$missing_tables[] = $table;
|
|
}
|
|
}
|
|
|
|
if (empty($missing_tables)) {
|
|
echo "<div class='ok'>🎉 ¡TODAS LAS TABLAS ESTÁN LISTAS!</div>";
|
|
echo "<div class='ok'>✅ Base de datos completamente configurada</div>";
|
|
echo "<div class='ok'>✅ Sistema debería funcionar ahora</div>";
|
|
|
|
echo "<br><div class='warning'><strong>PRÓXIMO PASO:</strong></div>";
|
|
echo "<div class='warning'>• Probar: <a href='login.php' style='color:#ffaa00'>login.php</a></div>";
|
|
echo "<div class='warning'>• Si funciona, probar: <a href='index.php' style='color:#ffaa00'>index.php</a></div>";
|
|
} else {
|
|
echo "<div class='error'>❌ Faltan tablas: " . implode(', ', $missing_tables) . "</div>";
|
|
echo "<div class='error'>❌ Sistema NO puede funcionar</div>";
|
|
}
|
|
|
|
echo "</div>";
|
|
|
|
echo "</body></html>";
|
|
?>
|