Files
crm.clientright.ru/crm_extensions/file_storage/migrate_project_final.php

209 lines
7.6 KiB
PHP
Raw Normal View History

<?php
/**
* ФИНАЛЬНАЯ МИГРАЦИЯ PROJECT: documentID/файл.pdf Project/название_ID/файл_docID.pdf
*
* Использует реальные S3 ключи из БД для перемещения файлов в новую структуру
*/
// Прямое подключение к БД через PDO
$dbConfig = [
'host' => 'localhost',
'dbname' => 'ci20465_72new',
'user' => 'ci20465_72new',
'pass' => 'EcY979Rn'
];
try {
$pdo = new PDO(
"mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset=utf8",
$dbConfig['user'],
$dbConfig['pass']
);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "✅ Подключено к БД\n\n";
} catch (PDOException $e) {
die("❌ Ошибка подключения к БД: " . $e->getMessage() . "\n");
}
// Параметры
$projectId = isset($argv[1]) ? (int)$argv[1] : null;
$dryRun = in_array('--dry-run', $argv);
if (!$projectId) {
echo "❌ Укажите ID проекта!\n";
echo "Использование: php migrate_project_final.php PROJECT_ID [--dry-run]\n";
echo "\nПример: php migrate_project_final.php 699 --dry-run\n";
exit(1);
}
echo "🔄 ФИНАЛЬНАЯ МИГРАЦИЯ PROJECT\n";
echo "==========================================\n";
if ($dryRun) {
echo "⚠️ РЕЖИМ DRY-RUN - НИЧЕГО НЕ БУДЕТ ИЗМЕНЕНО\n";
}
echo "\n";
// Подключаем зависимости
require_once(__DIR__ . '/FilePathManager.php');
require_once(__DIR__ . '/S3Client.php');
$pathMgr = new FilePathManager();
// S3 конфигурация - используем ключи из .env
require_once(__DIR__ . '/../shared/EnvLoader.php');
EnvLoader::load(__DIR__ . '/../.env');
$s3Config = [
'version' => 'latest',
'region' => 'ru-1',
'endpoint' => 'https://s3.twcstorage.ru',
'bucket' => 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c',
'use_path_style_endpoint' => true,
'key' => EnvLoader::getRequired('S3_ACCESS_KEY'),
'secret' => EnvLoader::getRequired('S3_SECRET_KEY')
];
$s3 = new S3Client($s3Config);
// Получаем проект
$stmt = $pdo->prepare("SELECT projectname FROM vtiger_project WHERE projectid = ?");
$stmt->execute([$projectId]);
$project = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$project) {
echo "❌ Проект не найден!\n";
exit(1);
}
$projectName = $project['projectname'];
echo "📁 Проект: $projectName (ID: $projectId)\n\n";
// Получаем файлы проекта с S3 ключами
$stmt = $pdo->prepare("
SELECT n.notesid, n.title, n.s3_key, n.s3_bucket, n.filename
FROM vtiger_notes n
INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid
WHERE sr.crmid = ?
AND n.s3_key IS NOT NULL
AND n.s3_bucket IS NOT NULL
AND n.s3_key LIKE 'crm2/CRM_Active_Files/Documents/%'
");
$stmt->execute([$projectId]);
$files = $stmt->fetchAll(PDO::FETCH_ASSOC);
$totalFiles = count($files);
echo "📊 Найдено файлов с S3 ключами: $totalFiles\n\n";
if ($totalFiles == 0) {
echo "✅ Нет файлов для миграции!\n";
exit(0);
}
$stats = ['processed' => 0, 'migrated' => 0, 'errors' => 0];
foreach ($files as $file) {
$stats['processed']++;
$notesId = $file['notesid'];
$documentTitle = $file['title'] ?: null;
$oldS3Key = $file['s3_key'];
$s3Bucket = $file['s3_bucket'];
$oldFilename = $file['filename'];
echo "[$stats[processed]/$totalFiles] Документ: " . ($documentTitle ?: $notesId) . " (ID: $notesId)\n";
// Извлекаем старое имя файла из S3 ключа
$oldFileName = basename($oldS3Key);
// Генерируем новый путь через FilePathManager
$newFullPath = $pathMgr->getFilePath('Project', $projectId, $notesId, $oldFileName, $documentTitle, $projectName);
$newS3Key = $newFullPath;
// Новый filename для БД
$newFilename = "https://s3.twcstorage.ru/$s3Bucket/" . rawurlencode($newS3Key);
echo " Старый S3: $oldS3Key\n";
echo " Новый S3: $newS3Key\n";
echo " Новый URL: " . substr($newFilename, 0, 80) . "...\n";
if (!$dryRun) {
try {
// Проверяем старый файл через URL
$oldUrl = "https://s3.twcstorage.ru/$s3Bucket/" . rawurlencode($oldS3Key);
$headers = @get_headers($oldUrl, 1);
if (!$headers || strpos($headers[0], '200') === false) {
echo " ⚠️ Старый файл не найден в S3 (URL: " . substr($oldUrl, 0, 80) . "...)\n\n";
$stats['errors']++;
continue;
}
// Проверяем новый файл
if ($s3->fileExists($newS3Key)) {
echo " ⚠️ Целевой файл уже существует\n\n";
$stats['errors']++;
continue;
}
// Скачиваем во временный файл
$tempFile = $s3->downloadToTemp($oldS3Key);
if (!$tempFile) {
throw new Exception("Не удалось скачать файл");
}
echo " ✅ Скачан во временный файл\n";
// Загружаем в новое место
if (!$s3->uploadFile($tempFile, $newS3Key)) {
throw new Exception("Не удалось загрузить файл");
}
echo " ✅ Загружен в новое место\n";
// Удаляем временный файл
@unlink($tempFile);
// Удаляем старый файл в S3
$s3->deleteObject($oldS3Key);
echo " ✅ Старый файл удален\n";
// Обновляем БД
$updateStmt = $pdo->prepare("UPDATE vtiger_notes SET s3_key = ?, filename = ? WHERE notesid = ?");
$updateStmt->execute([$newS3Key, $newFilename, $notesId]);
echo " ✅ БД обновлена\n";
$stats['migrated']++;
echo " ✅ УСПЕШНО!\n\n";
} catch (Exception $e) {
echo " ❌ ОШИБКА: " . $e->getMessage() . "\n\n";
$stats['errors']++;
}
} else {
echo " [DRY-RUN] Будет выполнено:\n";
echo " - Скачать: $oldS3Key\n";
echo " - Загрузить: $newS3Key\n";
echo " - Удалить: $oldS3Key\n";
echo " - Обновить БД: s3_key='$newS3Key', filename='$newFilename'\n\n";
$stats['migrated']++;
}
usleep(100000); // 0.1 сек пауза
}
// Итоги
echo "\n==========================================\n";
echo "📊 СТАТИСТИКА:\n";
echo "==========================================\n";
echo "Обработано: $stats[processed]\n";
echo "Мигрировано: $stats[migrated]\n";
echo "Ошибок: $stats[errors]\n";
echo "\n";
if ($dryRun) {
echo "⚠️ Это был DRY-RUN. Запустите без --dry-run для реальной миграции.\n";
} else if ($stats['errors'] == 0) {
echo "✅ МИГРАЦИЯ ЗАВЕРШЕНА УСПЕШНО!\n";
echo "\n📁 Структура: crm/crm2/CRM_Active_Files/Documents/Project/$projectName" . "_$projectIdайл_docID.ext\n";
} else {
echo "⚠️ Миграция завершена с ошибками.\n";
}
?>