'latest', 'region' => 'ru-1', 'endpoint' => 'https://s3.twcstorage.ru', 'credentials' => [ 'key' => $_ENV['S3_ACCESS_KEY'], 'secret' => $_ENV['S3_SECRET_KEY'], ], 'use_path_style_endpoint' => true, ]); echo "✅ S3 клиент инициализирован\n"; // Подключаемся к базе данных $pdo = new PDO("mysql:host={$dbconfig['db_server']};dbname={$dbconfig['db_name']}", $dbconfig['db_username'], $dbconfig['db_password']); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo "✅ Подключение к БД установлено\n\n"; // Находим все файлы контрагентов в старой структуре $sql = " SELECT n.notesid, n.title, n.filename, n.s3_key, a.accountid, a.accountname FROM vtiger_notes n INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid INNER JOIN vtiger_account a ON sr.crmid = a.accountid WHERE n.filelocationtype = 'E' AND n.s3_key IS NOT NULL AND n.s3_key LIKE '%/Documents/%' AND n.s3_key NOT LIKE '%/Project/%' AND n.s3_key NOT LIKE '%/Contacts/%' AND n.s3_key NOT LIKE '%/Accounts/%' ORDER BY a.accountid, n.notesid LIMIT 5 "; $stmt = $pdo->prepare($sql); $stmt->execute(); $files = $stmt->fetchAll(PDO::FETCH_ASSOC); echo "📊 Найдено файлов контрагентов для миграции: " . count($files) . "\n\n"; if (empty($files)) { echo "✅ Все файлы контрагентов уже мигрированы!\n"; exit(0); } $migratedCount = 0; $errorCount = 0; $bucket = $_ENV['S3_BUCKET']; foreach ($files as $file) { $notesId = $file['notesid']; $title = $file['title']; $oldS3Key = $file['s3_key']; $accountId = $file['accountid']; $accountName = $file['accountname']; echo "📁 Контрагент ID: {$accountId}\n"; echo " 📄 Файл ID: {$notesId}\n"; echo " 🔄 Старый путь: {$oldS3Key}\n"; try { // Простая нормализация имени контрагента $normalizedName = preg_replace('/[^a-zA-Zа-яА-Я0-9\s\-_]/u', '', $accountName); $normalizedName = preg_replace('/\s+/', '_', trim($normalizedName)); $normalizedName = preg_replace('/_+/', '_', $normalizedName); $normalizedName = trim($normalizedName, '_'); if (empty($normalizedName)) { $normalizedName = "account_{$accountId}"; } // Простая нормализация имени файла $normalizedTitle = preg_replace('/[^a-zA-Zа-яА-Я0-9\s\-_\.]/u', '', $title); $normalizedTitle = preg_replace('/\s+/', '_', trim($normalizedTitle)); $normalizedTitle = preg_replace('/_+/', '_', $normalizedTitle); $normalizedTitle = trim($normalizedTitle, '_'); if (empty($normalizedTitle)) { $normalizedTitle = "file_{$notesId}"; } // Формируем новый путь $newS3Key = "crm2/CRM_Active_Files/Documents/Accounts/{$normalizedName}_{$accountId}/{$normalizedTitle}_{$notesId}.pdf"; echo " ✅ Новый путь: {$newS3Key}\n"; // Проверяем существование файла в S3 $oldS3Key = ltrim($oldS3Key, '/'); try { $s3Client->headObject([ 'Bucket' => $bucket, 'Key' => $oldS3Key ]); echo " ✅ Файл найден в S3\n"; // Копируем файл в новое место $s3Client->copyObject([ 'Bucket' => $bucket, 'CopySource' => $bucket . '/' . $oldS3Key, 'Key' => $newS3Key ]); echo " ✅ Файл скопирован в новое место\n"; // Проверяем что новый файл существует $s3Client->headObject([ 'Bucket' => $bucket, 'Key' => $newS3Key ]); echo " ✅ Новый файл проверен\n"; // Удаляем старый файл $s3Client->deleteObject([ 'Bucket' => $bucket, 'Key' => $oldS3Key ]); echo " ✅ Старый файл удален\n"; // Обновляем записи в БД $newFilename = 'https://s3.twcstorage.ru/' . $bucket . '/' . $newS3Key; $updateSql = " UPDATE vtiger_notes SET s3_key = ?, filename = ? WHERE notesid = ? "; $updateStmt = $pdo->prepare($updateSql); $updateStmt->execute([$newS3Key, $newFilename, $notesId]); echo " ✅ Записи в БД обновлены\n"; $migratedCount++; } catch (AwsException $e) { if ($e->getAwsErrorCode() === 'NotFound') { echo " ❌ Файл не найден в S3: {$oldS3Key}\n"; } else { echo " ❌ Ошибка S3: " . $e->getMessage() . "\n"; } $errorCount++; } } catch (Exception $e) { echo " ❌ Ошибка: " . $e->getMessage() . "\n"; $errorCount++; } echo "\n"; } echo "🎉 МИГРАЦИЯ ЗАВЕРШЕНА!\n"; echo "📊 Статистика:\n"; echo " • Файлов мигрировано: {$migratedCount}\n"; echo " • Ошибок: {$errorCount}\n"; echo " • Всего файлов: " . count($files) . "\n"; if ($errorCount > 0) { echo "\n⚠️ Некоторые файлы не удалось мигрировать. Возможные причины:\n"; echo " • Файлы отсутствуют в S3\n"; echo " • Проблемы с правами доступа\n"; echo " • Ошибки сети\n"; } } catch (Exception $e) { echo "❌ КРИТИЧЕСКАЯ ОШИБКА: " . $e->getMessage() . "\n"; echo "Стек вызовов:\n" . $e->getTraceAsString() . "\n"; exit(1); }