Files
crm.clientright.ru/crm_extensions/file_storage/migrate_completed_projects.php
Fedor 9245768987 🚀 CRM Files Migration & Real-time Features
 Features:
- Migrated ALL files to new S3 structure (Projects, Contacts, Accounts, HelpDesk, Invoice, etc.)
- Added Nextcloud folder buttons to ALL modules
- Fixed Nextcloud editor integration
- WebSocket server for real-time updates
- Redis Pub/Sub integration
- File path manager for organized storage
- Redis caching for performance (Functions.php)

📁 New Structure:
Documents/Project/ProjectName_ID/file_docID.ext
Documents/Contacts/FirstName_LastName_ID/file_docID.ext
Documents/Accounts/AccountName_ID/file_docID.ext

🔧 Technical:
- FilePathManager for standardized paths
- S3StorageService integration
- WebSocket server (Node.js + Docker)
- Redis cache for getBasicModuleInfo()
- Predis library for Redis connectivity

📝 Scripts:
- Migration scripts for all modules
- Test pages for WebSocket/SSE/Polling
- Documentation (MIGRATION_*.md, REDIS_*.md)

🎯 Result: 15,000+ files migrated successfully!
2025-10-24 19:59:28 +03:00

242 lines
9.3 KiB
PHP
Raw 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
/**
* Миграция ЗАВЕРШЕННЫХ проектов (completed)
* Переносит файлы из старой структуры в новую: Project/название_ID/файл_docID.pdf
*/
// Включаем отображение ошибок
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo "🚀 МИГРАЦИЯ ЗАВЕРШЕННЫХ ПРОЕКТОВ (completed)\n";
echo "============================================\n\n";
// Подключаем конфигурацию
require_once '/var/www/fastuser/data/www/crm.clientright.ru/config.inc.php';
require_once '/var/www/fastuser/data/www/crm.clientright.ru/vendor/autoload.php';
require_once '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/file_storage/FilePathManager.php';
require_once '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/shared/EnvLoader.php';
// Загружаем переменные окружения
EnvLoader::load('/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/.env');
// Создаем PDO подключение напрямую
try {
$pdo = new PDO(
"mysql:host={$dbconfig['db_server']};port=3306;dbname={$dbconfig['db_name']};charset=utf8",
$dbconfig['db_username'],
$dbconfig['db_password'],
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
echo "✅ PDO подключен\n";
} catch (Exception $e) {
die("❌ Ошибка PDO: " . $e->getMessage() . "\n");
}
// S3 конфигурация
$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')
];
try {
echo "🔧 Создаем S3 клиент...\n";
$s3 = new Aws\S3\S3Client($s3Config);
echo "✅ S3 подключен\n";
} catch (Exception $e) {
die("❌ Ошибка S3: " . $e->getMessage() . "\n");
}
echo "🔧 Создаем FilePathManager...\n";
$pathMgr = new FilePathManager();
echo "✅ FilePathManager создан\n";
// Получаем завершенные проекты с файлами
echo "\n📁 ПОИСК ЗАВЕРШЕННЫХ ПРОЕКТОВ С ФАЙЛАМИ:\n";
echo "========================================\n";
$sql = "SELECT DISTINCT p.projectid, p.projectname, p.projectstatus, p.projecttype,
COUNT(n.notesid) as file_count
FROM vtiger_project p
INNER JOIN vtiger_senotesrel sr ON p.projectid = sr.crmid
INNER JOIN vtiger_notes n ON sr.notesid = n.notesid
WHERE n.filelocationtype = 'E' AND n.s3_key IS NOT NULL
AND p.projectstatus = 'completed'
AND n.s3_key NOT LIKE '%/Project/%'
GROUP BY p.projectid, p.projectname, p.projectstatus, p.projecttype
ORDER BY p.projectname";
$result = $pdo->query($sql);
$completedProjects = [];
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$completedProjects[] = $row;
echo "{$row['projectname']}: {$row['file_count']} файлов\n";
}
echo "\n📈 ИТОГО ЗАВЕРШЕННЫХ ПРОЕКТОВ: " . count($completedProjects) . "\n";
// Подсчитываем общее количество файлов
$totalFiles = 0;
foreach ($completedProjects as $project) {
$sql = "SELECT COUNT(*) as count FROM vtiger_notes n
INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid
WHERE sr.crmid = ? AND n.filelocationtype = 'E' AND n.s3_key IS NOT NULL
AND n.s3_key NOT LIKE '%/Project/%'";
$stmt = $pdo->prepare($sql);
$stmt->execute([$project['projectid']]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$totalFiles += $row['count'];
}
echo "📁 ИТОГО ФАЙЛОВ: $totalFiles\n";
// Спрашиваем пользователя
echo "\n❓ ВОПРОС:\n";
echo "===========\n";
echo "Мигрировать завершенные проекты ($totalFiles файлов)? (y/n): ";
$handle = fopen("php://stdin", "r");
$line = fgets($handle);
fclose($handle);
if (trim(strtolower($line)) !== 'y') {
echo "❌ Миграция отменена\n";
exit;
}
// Начинаем миграцию
echo "\n🚀 НАЧИНАЕМ МИГРАЦИЮ ЗАВЕРШЕННЫХ ПРОЕКТОВ:\n";
echo "==========================================\n";
$migratedProjects = 0;
$migratedFiles = 0;
$errors = 0;
foreach ($completedProjects as $project) {
$projectId = $project['projectid'];
$projectName = $project['projectname'];
$projectStatus = $project['projectstatus'];
echo "\n📁 Проект: $projectName (ID: $projectId, Статус: $projectStatus)\n";
// Получаем все файлы проекта которые еще не мигрированы
$sql = "SELECT n.notesid, n.title, n.filename, n.s3_key, n.s3_bucket
FROM vtiger_notes n
INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid
WHERE sr.crmid = ? AND n.filelocationtype = 'E' AND n.s3_key IS NOT NULL
AND n.s3_key NOT LIKE '%/Project/%'";
$stmt = $pdo->prepare($sql);
$stmt->execute([$projectId]);
$files = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$files[] = $row;
}
echo " 📄 Файлов для миграции: " . count($files) . "\n";
$projectMigratedFiles = 0;
$projectErrors = 0;
foreach ($files as $file) {
$documentId = $file['notesid'];
$fileName = $file['filename'];
$oldS3Key = $file['s3_key'];
$title = $file['title'];
// Генерируем новый путь
$newFilePath = $pathMgr->getFilePath('Project', $projectId, $documentId, $fileName, $title, $projectName);
$newS3Key = $newFilePath;
// Проверяем, нужно ли мигрировать
if ($oldS3Key === $newS3Key) {
echo " ✅ Файл уже в новой структуре: $title\n";
$projectMigratedFiles++;
continue;
}
echo " 🔄 Мигрируем: $title\n";
try {
// Проверяем существование старого файла
$oldUrl = "https://s3.twcstorage.ru/{$s3Config['bucket']}/{$oldS3Key}";
$headers = @get_headers($oldUrl);
if (!$headers || strpos($headers[0], '200') === false) {
echo " ⚠️ Файл не найден в S3: $oldUrl\n";
$projectErrors++;
continue;
}
// Скачиваем файл
$fileContent = file_get_contents($oldUrl);
if ($fileContent === false) {
echo "Не удалось скачать файл\n";
$projectErrors++;
continue;
}
// Загружаем в новое место
$uploadResult = $s3->putObject([
'Bucket' => $s3Config['bucket'],
'Key' => $newS3Key,
'Body' => $fileContent,
'ContentType' => mime_content_type('data://text/plain;base64,' . base64_encode($fileContent))
]);
// Обновляем БД (и s3_key и filename с полным URL)
$newFileUrl = "https://s3.twcstorage.ru/{$s3Config['bucket']}/{$newS3Key}";
$updateSql = "UPDATE vtiger_notes SET s3_key = ?, filename = ? WHERE notesid = ?";
$updateStmt = $pdo->prepare($updateSql);
$updateStmt->execute([$newS3Key, $newFileUrl, $documentId]);
// Удаляем старый файл
try {
$s3->deleteObject([
'Bucket' => $s3Config['bucket'],
'Key' => $oldS3Key
]);
echo " ✅ Старый файл удален\n";
} catch (Exception $e) {
echo " ⚠️ Не удалось удалить старый файл: " . $e->getMessage() . "\n";
}
echo " ✅ Файл мигрирован успешно\n";
$projectMigratedFiles++;
} catch (Exception $e) {
echo " ❌ Ошибка миграции: " . $e->getMessage() . "\n";
$projectErrors++;
}
}
echo " 📊 Результат проекта: $projectMigratedFiles файлов мигрировано, $projectErrors ошибок\n";
$migratedProjects++;
$migratedFiles += $projectMigratedFiles;
$errors += $projectErrors;
}
// Итоговая статистика
echo "\n🎉 МИГРАЦИЯ ЗАВЕРШЕННЫХ ПРОЕКТОВ ЗАВЕРШЕНА!\n";
echo "===========================================\n";
echo "📁 Проектов обработано: $migratedProjects\n";
echo "📄 Файлов мигрировано: $migratedFiles\n";
echo "❌ Ошибок: $errors\n";
if ($migratedFiles + $errors > 0) {
echo "✅ Успешность: " . round(($migratedFiles / ($migratedFiles + $errors)) * 100, 2) . "%\n";
}
echo "\n🚀 Все завершенные проекты мигрированы в новую структуру!\n";
?>