Files
crm.clientright.ru/crm_extensions/file_storage/migrate_all_remaining_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

205 lines
8.1 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
/**
* Миграция ВСЕХ оставшихся файлов проектов (независимо от статуса)
* Перемещает файлы из Documents/documentID/ в Documents/Project/projectName_projectID/
*/
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';
// Загружаем переменные окружения
$envFile = '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/.env';
if (file_exists($envFile)) {
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (strpos($line, '=') !== false && strpos($line, '#') !== 0) {
list($key, $value) = explode('=', $line, 2);
$_ENV[trim($key)] = trim($value);
}
}
}
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
echo "🚀 Миграция ВСЕХ оставшихся файлов проектов...\n\n";
mb_internal_encoding('UTF-8');
try {
$s3Client = new S3Client([
'version' => '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,
]);
$pdo = new PDO("mysql:host={$dbconfig['db_server']};dbname={$dbconfig['db_name']};charset=utf8mb4", $dbconfig['db_username'], $dbconfig['db_password']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec("SET NAMES utf8mb4");
echo "✅ Подключения установлены\n\n";
// Находим ВСЕ файлы проектов в старой структуре (без фильтра по статусу!)
$sql = "
SELECT
n.notesid,
n.title,
n.s3_key,
n.filename,
p.projectid,
p.projectname,
p.projectstatus
FROM vtiger_notes n
INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid
INNER JOIN vtiger_project p ON sr.crmid = p.projectid
WHERE n.filelocationtype = 'E'
AND n.s3_key IS NOT NULL
AND n.s3_key NOT LIKE '%/Project/%'
ORDER BY p.projectid, n.notesid
";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$files = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "📊 Найдено файлов проектов для миграции: " . count($files) . "\n\n";
if (empty($files)) {
echo "Все файлы проектов уже мигрированы!\n";
exit(0);
}
$bucket = $_ENV['S3_BUCKET'];
$migratedCount = 0;
$errorCount = 0;
$currentProjectId = null;
$projectCount = 0;
foreach ($files as $file) {
$notesId = $file['notesid'];
$title = $file['title'];
$currentS3Key = $file['s3_key'];
$projectId = $file['projectid'];
$projectName = $file['projectname'];
$projectStatus = $file['projectstatus'];
// Считаем проекты
if ($currentProjectId !== $projectId) {
$currentProjectId = $projectId;
$projectCount++;
// Выводим прогресс каждые 10 проектов
if ($projectCount % 10 == 0) {
echo "\n📊 Обработано проектов: {$projectCount}\n\n";
}
}
// Компактный вывод
if ($migratedCount % 50 == 0 && $migratedCount > 0) {
echo "📊 Мигрировано файлов: {$migratedCount}, ошибок: {$errorCount}\n";
}
try {
// Правильная нормализация имени проекта (СОХРАНЯЕМ КИРИЛЛИЦУ!)
$normalizedName = preg_replace('/[\/\\:*?"<>|№]/u', '_', $projectName);
$normalizedName = preg_replace('/\s+/', '_', trim($normalizedName));
$normalizedName = preg_replace('/_+/', '_', $normalizedName);
$normalizedName = trim($normalizedName, '_');
if (empty($normalizedName)) {
$normalizedName = "project_{$projectId}";
}
// Правильная нормализация имени файла (СОХРАНЯЕМ КИРИЛЛИЦУ!)
$normalizedTitle = preg_replace('/[\/\\:*?"<>|№]/u', '_', $title);
$normalizedTitle = preg_replace('/\s+/', '_', trim($normalizedTitle));
$normalizedTitle = preg_replace('/_+/', '_', $normalizedTitle);
$normalizedTitle = trim($normalizedTitle, '_');
if (empty($normalizedTitle)) {
$normalizedTitle = "file_{$notesId}";
}
// Получаем расширение файла из РЕАЛЬНОГО s3_key
$extension = pathinfo($currentS3Key, PATHINFO_EXTENSION);
if (empty($extension)) {
$extension = 'pdf';
}
// Формируем новый путь
$targetS3Key = "crm2/CRM_Active_Files/Documents/Project/{$normalizedName}_{$projectId}/{$normalizedTitle}_{$notesId}.{$extension}";
// Проверяем существование текущего файла в S3
$currentS3Key = ltrim($currentS3Key, '/');
try {
$s3Client->headObject([
'Bucket' => $bucket,
'Key' => $currentS3Key
]);
// Копируем файл в новое место
$s3Client->copyObject([
'Bucket' => $bucket,
'CopySource' => $bucket . '/' . $currentS3Key,
'Key' => $targetS3Key
]);
// Проверяем что новый файл существует
$s3Client->headObject([
'Bucket' => $bucket,
'Key' => $targetS3Key
]);
// Удаляем старый файл
$s3Client->deleteObject([
'Bucket' => $bucket,
'Key' => $currentS3Key
]);
// Обновляем записи в БД
$newFilename = 'https://s3.twcstorage.ru/' . $bucket . '/' . $targetS3Key;
$updateSql = "UPDATE vtiger_notes SET s3_key = ?, filename = ? WHERE notesid = ?";
$updateStmt = $pdo->prepare($updateSql);
$updateStmt->execute([$targetS3Key, $newFilename, $notesId]);
$migratedCount++;
} catch (AwsException $e) {
if ($e->getAwsErrorCode() === 'NotFound') {
// Файл не найден в S3 - пропускаем молча
} else {
echo "❌ S3 ошибка для файла {$notesId}: " . $e->getMessage() . "\n";
}
$errorCount++;
}
} catch (Exception $e) {
echo "❌ Ошибка для файла {$notesId}: " . $e->getMessage() . "\n";
$errorCount++;
}
}
echo "\n\n🎉 МИГРАЦИЯ ЗАВЕРШЕНА!\n";
echo "📊 Статистика:\n";
echo " • Проектов обработано: {$projectCount}\n";
echo " • Файлов мигрировано: {$migratedCount}\n";
echo " • Ошибок: {$errorCount}\n";
echo "Всего файлов: " . count($files) . "\n";
if ($errorCount > 0) {
echo "\n⚠️ Ошибки: файлы отсутствуют в S3 или проблемы с доступом\n";
}
} catch (Exception $e) {
echo "❌ КРИТИЧЕСКАЯ ОШИБКА: " . $e->getMessage() . "\n";
exit(1);
}