togethere.cloud/public_html/administration/migrate_blobs_to_disk.php

131 lines
4.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
/**
* Skrypt migracji: przenosi istniejące pliki z BLOB (file_data)
* na dysk do katalogu /var/www/togethere.cloud/files/.
*
* Uruchom raz po zastosowaniu file_storage_migration.sql.
* Dostępny tylko z IP serwera lub przez terminal chroń go przed publicznym dostępem!
*
* Uruchomienie z CLI:
* php /var/www/togethere.cloud/public_html/administration/migrate_blobs_to_disk.php
*
* Lub przez przeglądarkę (tylko localhost):
* https://togethere.cloud/administration/migrate_blobs_to_disk.php?token=<MIGRATION_TOKEN>
*/
// Zabezpieczenie token musi być przekazany jako argument CLI lub GET param
define('MIGRATION_TOKEN', getenv('MIGRATION_TOKEN') ?: 'CHANGE_BEFORE_USE');
$isCli = PHP_SAPI === 'cli';
header('Content-Type: text/plain; charset=utf-8');
// ---- Konfiguracja ----
$filesBaseDir = '/var/www/togethere.cloud/files';
$dbHost = 'localhost';
$dbName = 'togethere_cloud';
$dbUser = 'root';
$dbPass = 'HasloDoSQL';
// ---- Połączenie z bazą ----
try {
$pdo = new PDO(
"mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4",
$dbUser,
$dbPass,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
exit('Błąd połączenia z bazą: ' . $e->getMessage());
}
/**
* Przenieś BLOBy z danej tabeli na dysk.
*/
function migrate_table(
PDO $pdo,
string $filesBaseDir,
string $table,
string $subfolder,
string $idColumn,
string $taskIdColumn = ''
): void {
echo "=== Migracja tabeli: $table (subfolder: $subfolder) ===\n";
// Sprawdź czy kolumna file_path istnieje
$cols = $pdo->query("SHOW COLUMNS FROM `$table`")->fetchAll(PDO::FETCH_COLUMN);
if (!in_array('file_path', $cols, true)) {
echo "POMINIĘTO: kolumna file_path nie istnieje uruchom najpierw file_storage_migration.sql\n\n";
return;
}
if (!in_array('file_data', $cols, true)) {
echo "POMINIĘTO: kolumna file_data nie istnieje migracja prawdopodobnie już wykonana\n\n";
return;
}
$targetDir = $filesBaseDir . '/' . ltrim($subfolder, '/');
if (!is_dir($targetDir) && !mkdir($targetDir, 0750, true)) {
echo "BŁĄD: nie można utworzyć katalogu $targetDir\n\n";
return;
}
// Pobierz rekordy z BLOBem i bez file_path
$stmt = $pdo->query(
"SELECT $idColumn AS id, file_name, file_mime, file_data "
. "FROM `$table` "
. "WHERE file_data IS NOT NULL AND file_data <> '' "
. " AND (file_path IS NULL OR file_path = '')"
);
$migrated = 0;
$errors = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$id = (int)$row['id'];
$origName = (string)($row['file_name'] ?? 'plik');
$ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
$safeExts = ['jpg','jpeg','png','gif','webp','pdf','txt','zip','mp4','mp3','wav','doc','docx','xls','xlsx'];
if (!in_array($ext, $safeExts, true)) {
$ext = 'bin';
}
$storedName = bin2hex(random_bytes(16)) . '.' . $ext;
$filePath = $targetDir . '/' . $storedName;
$dbPath = $subfolder . '/' . $storedName;
// Zapisz na dysk
$blob = $row['file_data'];
if (is_resource($blob)) {
$blob = stream_get_contents($blob);
}
if (file_put_contents($filePath, $blob) === false) {
echo " BŁĄD [id=$id]: nie można zapisać pliku $filePath\n";
$errors++;
continue;
}
chmod($filePath, 0640);
// Zaktualizuj rekord w bazie
$upd = $pdo->prepare(
"UPDATE `$table` SET file_path = :fp WHERE $idColumn = :id"
);
$upd->execute([':fp' => $dbPath, ':id' => $id]);
echo " OK [id=$id] $origName -> $dbPath\n";
$migrated++;
}
echo "Zakończono: $migrated przeniesionych, $errors błędów.\n\n";
}
// ---- Uruchom migrację dla każdej tabeli ----
migrate_table($pdo, $filesBaseDir, 'admin_chat_messages', 'admin_chat', 'id');
migrate_table($pdo, $filesBaseDir, 'admin_task_files', 'admin_tasks', 'id');
migrate_table($pdo, $filesBaseDir, 'admin_tasks', 'admin_tasks', 'id');
echo "=== Migracja zakończona. ===\n";
echo "Zweryfikuj dane, a następnie usuń kolumny file_data (patrz file_storage_migration.sql).\n";