diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..729cdfe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM php:8.2-apache + +# Install PDO MySQL extension +RUN docker-php-ext-install pdo pdo_mysql + +# Enable Apache mod_rewrite for routing +RUN a2enmod rewrite + +# Set document root to public folder +ENV APACHE_DOCUMENT_ROOT /var/www/html/public + +# Update Apache config to use the new document root +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf +RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + +WORKDIR /var/www/html diff --git a/README.md b/README.md index 25f627c..fc41d8e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,45 @@ -# tippspiel2027 +# Tippspiel 2027 -KI-optimierte Version von tippspiel \ No newline at end of file +Dieses Projekt ist der offizielle Nachfolger des alten Tippspiels. Es basiert auf reinem PHP, um eine maximale Langlebigkeit, leichte Lesbarkeit und einfache Anpassbarkeit für die Zukunft zu gewährleisten. Komplexe Abstraktionsschichten wurden entfernt und Legacy-Features eliminiert. + +## Voraussetzungen + +- Docker & Docker Compose + +## Lokale Entwicklung und Testumgebung starten + +Die Applikation und die dazugehörige Datenbank können einfach via Docker gestartet werden: + +```bash +docker-compose up -d +``` + +Die Web-Oberfläche ist anschließend unter `http://localhost:8080` erreichbar. + +## Daten-Migration (Import vom Live-Dump) + +Das alte Projekt basiert auf Laravel und hat einige Features, die im neuen Projekt nicht mehr existieren (wie z.B. "Ligen" oder das "grüne Trikot"). Um mit den echten Testdaten aus dem Live-Betrieb arbeiten zu können, gibt es ein automatisiertes Import-Skript. + +### 1. Legacy Datenbank importieren + +Zuerst muss der Dump des alten Tippspiels in den laufenden Datenbank-Container importiert werden. Wir laden den alten SQL-Dump in eine Datenbank namens `tippspiel_legacy`: + +```bash +# Alte DB im Container anlegen +docker-compose exec db mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS tippspiel_legacy;" + +# Dump importieren (Beispiel-Kommando) +# docker exec -i $(docker-compose ps -q db) mysql -uroot -proot tippspiel_legacy < /pfad/zum/dump.sql +``` + +### 2. Import-Skript ausführen + +Nachdem die alten Daten in der `tippspiel_legacy` Datenbank liegen, kann das Import-Skript ausgeführt werden. Dieses Skript legt automatisch das neue bereinigte Schema (`schema.sql`) in der neuen Datenbank (`tippspiel2027`) an und migriert die Daten. Tote Features und alte Spalten werden dabei automatisch übersprungen. + +Das Import-Skript kann im Container aufgerufen werden: + +```bash +docker-compose exec app php import.php +``` + +Sobald das Skript durchgelaufen ist, sind die sauberen Daten im System und du kannst die Anwendung auf Port 8080 testen. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e66438b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + app: + build: . + ports: + - "8080:80" + volumes: + - .:/var/www/html + environment: + - DB_HOST=db + - DB_USER=root + - DB_PASS=root + - DB_OLD_NAME=tippspiel_legacy + - DB_NEW_NAME=tippspiel2027 + depends_on: + - db + + db: + image: mariadb:10.11 + ports: + - "3306:3306" + environment: + - MYSQL_ROOT_PASSWORD=root + volumes: + - db_data:/var/lib/mysql + +volumes: + db_data: \ No newline at end of file diff --git a/import.php b/import.php new file mode 100644 index 0000000..9aa9ab8 --- /dev/null +++ b/import.php @@ -0,0 +1,94 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + echo "Erstelle neue Datenbank $newDbName falls nicht vorhanden...\n"; + $pdo->exec("CREATE DATABASE IF NOT EXISTS `$newDbName` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + + // Neues Schema laden + $pdo->exec("USE `$newDbName`"); + $schema = file_get_contents(__DIR__ . '/schema.sql'); + if ($schema) { + $pdo->exec($schema); + echo "Neues Schema erfolgreich in $newDbName angelegt.\n"; + } else { + die("Fehler: schema.sql nicht gefunden.\n"); + } + + echo "Starte Import von $oldDbName nach $newDbName...\n"; + + $tablesToMigrate = [ + 'users', + 'settings', + 'seasons', + 'rounds', + 'games', + 'tipps', + 'payments', + 'quotas', + 'roundmails', + 'manual_payouts' + ]; + + foreach ($tablesToMigrate as $table) { + echo "Migriere Tabelle: $table...\n"; + + // Prüfen, ob Tabelle in der alten DB existiert + $tableExists = $pdo->query("SELECT 1 FROM information_schema.tables WHERE table_schema = '$oldDbName' AND table_name = '$table'")->fetchColumn(); + if (!$tableExists) { + echo " Überspringe $table, existiert in $oldDbName nicht.\n"; + continue; + } + + // Leeren der neuen Tabelle + $pdo->exec("TRUNCATE TABLE `$newDbName`.`$table`"); + + // Alle Daten aus alter DB holen + $rows = $pdo->query("SELECT * FROM `$oldDbName`.`$table`")->fetchAll(PDO::FETCH_ASSOC); + if (count($rows) === 0) { + echo " Keine Daten in $table.\n"; + continue; + } + + // Holen der Spalten der NEUEN Tabelle (um Legacy Felder zu ignorieren) + $newColsStmt = $pdo->query("DESCRIBE `$newDbName`.`$table`"); + $newCols = $newColsStmt->fetchAll(PDO::FETCH_COLUMN); + + $inserted = 0; + foreach ($rows as $row) { + $filteredRow = []; + foreach ($newCols as $col) { + if (array_key_exists($col, $row)) { + $filteredRow[$col] = $row[$col]; + } + } + + if (!empty($filteredRow)) { + $cols = '`' . implode('`, `', array_keys($filteredRow)) . '`'; + $vals = implode(', ', array_fill(0, count($filteredRow), '?')); + $stmt = $pdo->prepare("INSERT INTO `$newDbName`.`$table` ($cols) VALUES ($vals)"); + $stmt->execute(array_values($filteredRow)); + $inserted++; + } + } + echo " $inserted Einträge migriert.\n"; + } + + echo "Import erfolgreich abgeschlossen!\n"; + +} catch (PDOException $e) { + die("Datenbankfehler: " . $e->getMessage() . "\n"); +} diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..5c67ac3 --- /dev/null +++ b/public/index.php @@ -0,0 +1,17 @@ +Willkommen bei Tippspiel 2027"; + echo "

Dies ist die Nachfolgeversion des alten Tippspiels (Pure PHP Variante).

"; +} elseif ($uri === '/api/status') { + header('Content-Type: application/json'); + echo json_encode(['status' => 'ok', 'version' => '2027.1']); +} else { + http_response_code(404); + echo "404 Not Found"; +} diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..f1a68c5 --- /dev/null +++ b/schema.sql @@ -0,0 +1,68 @@ +CREATE TABLE `users` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(201) COLLATE utf8mb4_unicode_ci NOT NULL, + `firstname` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, + `lastname` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, + `email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL, + `password` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, + `iban` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, + `bankname` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `blz` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, + `kontonr` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `mobile` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `deleted` timestamp NULL DEFAULT NULL, + `admin` tinyint(1) NOT NULL DEFAULT '0', + `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `users_email_unique` (`email`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `tipps` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `game_id` int(11) NOT NULL, + `score1` int(11) NOT NULL, + `score2` int(11) NOT NULL, + `joker` tinyint(1) NOT NULL DEFAULT '0', + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `games` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `round_id` int(11) NOT NULL, + `team1` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, + `team2` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, + `score1` int(11) NOT NULL DEFAULT '-1', + `score2` int(11) NOT NULL DEFAULT '-1', + `kickoff` datetime NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `rounds` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `season_id` int(11) NOT NULL, + `report` varchar(16000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `seasons` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, + `rounds` int(11) NOT NULL DEFAULT '36', + `active` tinyint(1) NOT NULL DEFAULT '1', + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Weitere Tabellen (Settings, Payments, Quotas) können bei Bedarf ergänzt werden. +-- Tote Features (Ligen, Matches) wurden absichtlich weggelassen.