214 lines
8.6 KiB
PHP
214 lines
8.6 KiB
PHP
|
|
<?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';
|
|||
|
|
$projectId = 384256;
|
|||
|
|
$s3Bucket = $config['s3']['bucket'];
|
|||
|
|
|
|||
|
|
echo "Перемещение файлов проекта $projectId из temp/ в правильную структуру\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
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
// Подключение к БД
|
|||
|
|
$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]
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// Получаем все файлы из temp/384256/
|
|||
|
|
echo "1. Поиск файлов в temp/$projectId/...\n";
|
|||
|
|
$tempFiles = [];
|
|||
|
|
$objects = $s3Client->listObjectsV2([
|
|||
|
|
'Bucket' => $s3Bucket,
|
|||
|
|
'Prefix' => "temp/$projectId/",
|
|||
|
|
'MaxKeys' => 1000
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
if (isset($objects['Contents'])) {
|
|||
|
|
foreach ($objects['Contents'] as $object) {
|
|||
|
|
$key = $object['Key'];
|
|||
|
|
// Пропускаем папки
|
|||
|
|
if (substr($key, -1) !== '/') {
|
|||
|
|
$tempFiles[] = $key;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo " Найдено файлов в temp/: " . count($tempFiles) . "\n\n";
|
|||
|
|
|
|||
|
|
if (empty($tempFiles)) {
|
|||
|
|
die("Файлы не найдены в temp/$projectId/\n");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Получаем документы проекта из БД
|
|||
|
|
echo "2. Получение документов проекта из БД...\n";
|
|||
|
|
$stmt = $pdo->prepare('
|
|||
|
|
SELECT n.notesid, n.title, n.s3_key, n.filename
|
|||
|
|
FROM vtiger_notes n
|
|||
|
|
INNER JOIN vtiger_crmentity e ON e.crmid = n.notesid
|
|||
|
|
INNER JOIN vtiger_senotesrel snr ON snr.notesid = n.notesid
|
|||
|
|
WHERE snr.crmid = ? AND e.deleted = 0 AND n.filelocationtype = "E"
|
|||
|
|
ORDER BY n.notesid ASC
|
|||
|
|
');
|
|||
|
|
$stmt->execute([$projectId]);
|
|||
|
|
$dbDocs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||
|
|
|
|||
|
|
echo " Найдено документов в БД: " . count($dbDocs) . "\n\n";
|
|||
|
|
|
|||
|
|
// Сопоставляем файлы из temp/ с документами в БД
|
|||
|
|
echo "3. Сопоставление файлов...\n";
|
|||
|
|
$mappings = [];
|
|||
|
|
|
|||
|
|
foreach ($tempFiles as $tempFile) {
|
|||
|
|
$basename = basename($tempFile);
|
|||
|
|
// Извлекаем ID из имени файла (например, 384260 из 384260_8_Dogovor...)
|
|||
|
|
if (preg_match('/^(\d+)_/', $basename, $matches)) {
|
|||
|
|
$fileDocId = $matches[1];
|
|||
|
|
|
|||
|
|
// Ищем соответствующий документ в БД
|
|||
|
|
// Обычно файл с ID 384260 соответствует документу 384259 (ID файла = ID документа + 1)
|
|||
|
|
// Но лучше искать по ближайшему ID
|
|||
|
|
$matchedDoc = null;
|
|||
|
|
foreach ($dbDocs as $doc) {
|
|||
|
|
// Проверяем разные варианты соответствия
|
|||
|
|
if ($doc['notesid'] == $fileDocId - 1 ||
|
|||
|
|
$doc['notesid'] == $fileDocId ||
|
|||
|
|
abs($doc['notesid'] - $fileDocId) <= 2) {
|
|||
|
|
// Дополнительная проверка по названию
|
|||
|
|
$docTitleLower = mb_strtolower($doc['title']);
|
|||
|
|
$fileNameLower = mb_strtolower($basename);
|
|||
|
|
|
|||
|
|
// Проверяем совпадение по ключевым словам
|
|||
|
|
$keywords = ['dogovor', 'podtverzhdenie', 'skrin', 'zayavlenie', '8', '9', '10', '7'];
|
|||
|
|
$foundKeyword = false;
|
|||
|
|
foreach ($keywords as $keyword) {
|
|||
|
|
if (strpos($docTitleLower, $keyword) !== false && strpos($fileNameLower, $keyword) !== false) {
|
|||
|
|
$foundKeyword = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($foundKeyword || abs($doc['notesid'] - $fileDocId) <= 1) {
|
|||
|
|
$matchedDoc = $doc;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($matchedDoc) {
|
|||
|
|
$mappings[] = [
|
|||
|
|
'temp_file' => $tempFile,
|
|||
|
|
'doc_id' => $matchedDoc['notesid'],
|
|||
|
|
'doc_title' => $matchedDoc['title'],
|
|||
|
|
'target_s3_key' => $matchedDoc['s3_key'],
|
|||
|
|
'current_s3_key' => $matchedDoc['s3_key']
|
|||
|
|
];
|
|||
|
|
echo " ✅ {$basename} -> Документ {$matchedDoc['notesid']}: {$matchedDoc['title']}\n";
|
|||
|
|
} else {
|
|||
|
|
echo " ⚠️ {$basename} -> Не найден соответствующий документ (ID файла: $fileDocId)\n";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo "\n Всего сопоставлено: " . count($mappings) . " файлов\n\n";
|
|||
|
|
|
|||
|
|
if (empty($mappings)) {
|
|||
|
|
die("Не удалось сопоставить файлы с документами\n");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Перемещаем файлы
|
|||
|
|
echo "4. Перемещение файлов в S3...\n";
|
|||
|
|
$moved = 0;
|
|||
|
|
$errors = 0;
|
|||
|
|
|
|||
|
|
foreach ($mappings as $mapping) {
|
|||
|
|
$sourceKey = $mapping['temp_file'];
|
|||
|
|
$targetKey = $mapping['target_s3_key'];
|
|||
|
|
$docId = $mapping['doc_id'];
|
|||
|
|
|
|||
|
|
echo " Перемещение: " . basename($sourceKey) . "\n";
|
|||
|
|
echo " Из: $sourceKey\n";
|
|||
|
|
echo " В: $targetKey\n";
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// Проверяем, существует ли целевой путь (если да, пропускаем)
|
|||
|
|
try {
|
|||
|
|
$s3Client->headObject([
|
|||
|
|
'Bucket' => $s3Bucket,
|
|||
|
|
'Key' => $targetKey
|
|||
|
|
]);
|
|||
|
|
echo " ⚠️ Целевой файл уже существует, пропускаем\n\n";
|
|||
|
|
continue;
|
|||
|
|
} catch (\Aws\Exception\AwsException $e) {
|
|||
|
|
if ($e->getAwsErrorCode() != 'NotFound') {
|
|||
|
|
throw $e;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Копируем файл в новое место
|
|||
|
|
$s3Client->copyObject([
|
|||
|
|
'Bucket' => $s3Bucket,
|
|||
|
|
'CopySource' => $s3Bucket . '/' . $sourceKey,
|
|||
|
|
'Key' => $targetKey,
|
|||
|
|
'MetadataDirective' => 'COPY'
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
echo " ✅ Файл скопирован\n";
|
|||
|
|
|
|||
|
|
// Удаляем исходный файл из temp/
|
|||
|
|
$s3Client->deleteObject([
|
|||
|
|
'Bucket' => $s3Bucket,
|
|||
|
|
'Key' => $sourceKey
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
echo " ✅ Исходный файл удален из temp/\n";
|
|||
|
|
|
|||
|
|
// Обновляем filename в БД (если нужно)
|
|||
|
|
$newFilename = "https://s3.twcstorage.ru/{$s3Bucket}/" . rawurlencode($targetKey);
|
|||
|
|
$updateStmt = $pdo->prepare('UPDATE vtiger_notes SET filename = ? WHERE notesid = ?');
|
|||
|
|
$updateStmt->execute([$newFilename, $docId]);
|
|||
|
|
|
|||
|
|
echo " ✅ Путь в БД обновлен\n";
|
|||
|
|
$moved++;
|
|||
|
|
|
|||
|
|
} catch (\Aws\Exception\AwsException $e) {
|
|||
|
|
echo " ❌ Ошибка: " . $e->getMessage() . " (Code: " . $e->getAwsErrorCode() . ")\n";
|
|||
|
|
$errors++;
|
|||
|
|
} catch (Exception $e) {
|
|||
|
|
echo " ❌ Ошибка: " . $e->getMessage() . "\n";
|
|||
|
|
$errors++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo "\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo str_repeat("=", 80) . "\n";
|
|||
|
|
echo "РЕЗУЛЬТАТЫ:\n";
|
|||
|
|
echo " Перемещено файлов: $moved\n";
|
|||
|
|
echo " Ошибок: $errors\n";
|
|||
|
|
|
|||
|
|
} catch (Exception $e) {
|
|||
|
|
echo "КРИТИЧЕСКАЯ ОШИБКА: " . $e->getMessage() . "\n";
|
|||
|
|
echo "Trace: " . $e->getTraceAsString() . "\n";
|
|||
|
|
}
|
|||
|
|
|