Files
crm.clientright.ru/restore_deleted_files.php
Fedor 840acca51a feat(documents): дедупликация documents_meta и исправление field_label
- Исправлен N8N_CODE_PROCESS_UPLOADED_FILES_FIXED.js: использовать uploads_field_labels[0] вместо [grp]
- Создан SQL_CLAIMSAVE_FIXED_NEW_FLOW_DEDUP.sql с дедупликацией documents_meta
- Создан SQL_CLEANUP_DOCUMENTS_META_DUPLICATES.sql для очистки существующих дубликатов
- Создан полный уникальный индекс idx_document_texts_hash_unique на document_texts(file_hash)
- Добавлен SESSION_LOG_2025-11-28_documents_dedup.md с описанием всех изменений

Fixes:
- field_label теперь корректно отображает 'Переписка' вместо 'group-2'
- documents_meta не накапливает дубликаты при повторных сохранениях
- ON CONFLICT (file_hash) теперь работает для document_texts
2025-11-28 18:16:53 +03:00

164 lines
7.8 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
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once '/var/www/fastuser/data/www/crm.clientright.ru/vendor/autoload.php';
require_once '/var/www/fastuser/data/www/crm.clientright.ru/config.inc.php';
$config = require '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/file_storage/config.php';
$docIds = [386869, 394973];
$s3Bucket = $config['s3']['bucket'];
echo "Восстановление удаленных файлов из S3\n";
echo str_repeat("=", 80) . "\n\n";
try {
// Инициализация S3 клиента
$s3Client = new \Aws\S3\S3Client([
'version' => 'latest',
'region' => $config['s3']['region'],
'endpoint' => $config['s3']['endpoint'],
'use_path_style_endpoint' => true,
'credentials' => [
'key' => $config['s3']['key'],
'secret' => $config['s3']['secret'],
],
'suppress_php_deprecation_warning' => true
]);
foreach ($docIds as $docId) {
echo "Восстановление файла для документа $docId:\n";
echo str_repeat("-", 80) . "\n";
// Получаем информацию о документе
$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]
);
$stmt = $pdo->prepare('SELECT notesid, title, s3_key, s3_etag FROM vtiger_notes WHERE notesid = ?');
$stmt->execute([$docId]);
$doc = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$doc) {
echo " Документ не найден в БД\n\n";
continue;
}
$s3Key = $doc['s3_key'];
echo " Название: {$doc['title']}\n";
echo " Путь: $s3Key\n\n";
// Получаем delete markers
try {
$versions = $s3Client->listObjectVersions([
'Bucket' => $s3Bucket,
'Prefix' => $s3Key,
'MaxKeys' => 100
]);
if (isset($versions['DeleteMarkers']) && !empty($versions['DeleteMarkers'])) {
echo " Найдено delete markers: " . count($versions['DeleteMarkers']) . "\n";
// Удаляем все delete markers (самый новый будет удален последним)
// Сортируем по дате удаления (от новых к старым)
usort($versions['DeleteMarkers'], function($a, $b) {
$dateA = isset($a['LastModified']) ? strtotime($a['LastModified']) : 0;
$dateB = isset($b['LastModified']) ? strtotime($b['LastModified']) : 0;
return $dateB - $dateA; // От новых к старым
});
foreach ($versions['DeleteMarkers'] as $marker) {
$versionId = $marker['VersionId'];
$deleteDate = $marker['LastModified'] ?? 'не указана';
echo " Удаление delete marker: VersionId=$versionId (дата удаления: $deleteDate)\n";
try {
$s3Client->deleteObject([
'Bucket' => $s3Bucket,
'Key' => $s3Key,
'VersionId' => $versionId
]);
echo " ✅ Delete marker удален\n";
} catch (\Aws\Exception\AwsException $e) {
echo " ❌ Ошибка при удалении delete marker: " . $e->getMessage() . "\n";
}
}
// Проверяем, восстановился ли файл
echo "\n Проверка восстановления файла...\n";
try {
$headResult = $s3Client->headObject([
'Bucket' => $s3Bucket,
'Key' => $s3Key
]);
echo " ✅ Файл успешно восстановлен!\n";
echo " Размер: " . number_format($headResult['ContentLength'] / 1024, 2) . " KB\n";
echo " ETag: " . (isset($headResult['ETag']) ? trim($headResult['ETag'], '"') : 'не указан') . "\n";
echo " Дата: " . ($headResult['LastModified'] ?? 'не указана') . "\n";
} catch (\Aws\Exception\AwsException $e) {
if ($e->getAwsErrorCode() == 'NotFound') {
echo " ⚠️ Файл все еще не доступен (возможно, нужно восстановить конкретную версию)\n";
// Пробуем восстановить последнюю версию напрямую
if (isset($versions['Versions']) && !empty($versions['Versions'])) {
$latestVersion = $versions['Versions'][0]; // Первая версия - самая новая
$versionId = $latestVersion['VersionId'];
echo " Попытка восстановить версию: VersionId=$versionId\n";
try {
// Копируем версию в текущий объект
$s3Client->copyObject([
'Bucket' => $s3Bucket,
'CopySource' => $s3Bucket . '/' . $s3Key . '?versionId=' . $versionId,
'Key' => $s3Key
]);
echo " ✅ Версия восстановлена\n";
// Проверяем еще раз
$headResult = $s3Client->headObject([
'Bucket' => $s3Bucket,
'Key' => $s3Key
]);
echo " ✅ Файл восстановлен и доступен!\n";
echo " Размер: " . number_format($headResult['ContentLength'] / 1024, 2) . " KB\n";
} catch (\Aws\Exception\AwsException $e) {
echo " ❌ Ошибка при восстановлении версии: " . $e->getMessage() . "\n";
}
}
} else {
echo " ❌ Ошибка при проверке: " . $e->getMessage() . "\n";
}
}
} else {
echo " ❌ Delete markers не найдены\n";
}
} catch (\Aws\Exception\AwsException $e) {
echo " ❌ Ошибка при работе с версиями: " . $e->getMessage() . "\n";
}
echo "\n";
}
echo str_repeat("=", 80) . "\n";
echo "Восстановление завершено!\n";
echo "Проверьте доступность файлов в интерфейсе CRM\n";
} catch (Exception $e) {
echo "ОШИБКА: " . $e->getMessage() . "\n";
echo "Trace: " . $e->getTraceAsString() . "\n";
}