- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
164 lines
6.3 KiB
PHP
164 lines
6.3 KiB
PHP
<?php
|
||
/**
|
||
* Fix all #realfile URLs in the system
|
||
* Processes files in batches to avoid memory issues
|
||
*/
|
||
|
||
$ROOT = '/var/www/fastuser/data/www/crm.clientright.ru/';
|
||
require_once $ROOT . 'config.inc.php';
|
||
|
||
// CLI options
|
||
$opts = getopt('', [
|
||
'batch-size::',
|
||
'dry-run::',
|
||
'start-from::'
|
||
]);
|
||
|
||
$batchSize = isset($opts['batch-size']) ? (int)$opts['batch-size'] : 100;
|
||
$dryRun = isset($opts['dry-run']) ? (int)$opts['dry-run'] !== 0 : true;
|
||
$startFrom = isset($opts['start-from']) ? (int)$opts['start-from'] : 0;
|
||
|
||
// Database connection
|
||
$mysqli = new mysqli($dbconfig['db_server'], $dbconfig['db_username'], $dbconfig['db_password'], $dbconfig['db_name']);
|
||
if ($mysqli->connect_error) {
|
||
die("Connection failed: " . $mysqli->connect_error);
|
||
}
|
||
$mysqli->set_charset("utf8");
|
||
|
||
echo "=== Исправление всех #realfile URL ===\n\n";
|
||
echo "Параметры:\n";
|
||
echo "- Размер батча: $batchSize\n";
|
||
echo "- Режим: " . ($dryRun ? "ТЕСТОВЫЙ" : "РАБОЧИЙ") . "\n";
|
||
echo "- Начать с: $startFrom\n\n";
|
||
|
||
// Создаем директории для логов и бэкапов
|
||
$logDir = $ROOT . 'crm_extensions/file_storage/logs';
|
||
$backupDir = $ROOT . 'crm_extensions/file_storage/backups';
|
||
if (!is_dir($logDir)) mkdir($logDir, 0755, true);
|
||
if (!is_dir($backupDir)) mkdir($backupDir, 0755, true);
|
||
|
||
$logFile = $logDir . '/fix_realfile_urls.log';
|
||
|
||
function logMessage($msg) {
|
||
global $logFile;
|
||
$line = '[' . date('Y-m-d H:i:s') . '] ' . $msg . PHP_EOL;
|
||
file_put_contents($logFile, $line, FILE_APPEND | LOCK_EX);
|
||
echo $line;
|
||
}
|
||
|
||
// Подсчитываем общее количество файлов для обработки
|
||
$countQuery = "SELECT COUNT(*) as total FROM vtiger_notes WHERE filelocationtype = 'E' AND filename LIKE '%s3.twcstorage.ru%' AND filename LIKE '%#realfile%'";
|
||
$countResult = $mysqli->query($countQuery);
|
||
$totalFiles = $countResult->fetch_assoc()['total'];
|
||
|
||
logMessage("Найдено файлов для обработки: $totalFiles");
|
||
|
||
$processed = 0;
|
||
$fixed = 0;
|
||
$errors = 0;
|
||
$skipped = 0;
|
||
|
||
while ($processed < $totalFiles) {
|
||
logMessage("Обработка батча: " . ($processed + 1) . "-" . min($processed + $batchSize, $totalFiles) . " из $totalFiles");
|
||
|
||
// Получаем батч файлов
|
||
$query = "SELECT notesid, title, filename, s3_key, s3_bucket
|
||
FROM vtiger_notes
|
||
WHERE filelocationtype = 'E'
|
||
AND filename LIKE '%s3.twcstorage.ru%'
|
||
AND filename LIKE '%#realfile%'
|
||
ORDER BY notesid DESC
|
||
LIMIT $batchSize OFFSET $processed";
|
||
|
||
$result = $mysqli->query($query);
|
||
|
||
if (!$result || $result->num_rows === 0) {
|
||
logMessage("Больше файлов для обработки нет");
|
||
break;
|
||
}
|
||
|
||
while ($row = $result->fetch_assoc()) {
|
||
$notesid = $row['notesid'];
|
||
$currentFilename = $row['filename'];
|
||
$s3Key = $row['s3_key'];
|
||
$s3Bucket = $row['s3_bucket'];
|
||
|
||
// Проверяем, нужна ли обработка
|
||
if (empty($s3Key) || empty($s3Bucket)) {
|
||
logMessage("Пропуск ID $notesid: отсутствуют S3 данные");
|
||
$skipped++;
|
||
continue;
|
||
}
|
||
|
||
// Создаем правильный URL с правильной кодировкой
|
||
$encodedKey = implode('/', array_map('rawurlencode', explode('/', $s3Key)));
|
||
$correctUrl = "https://s3.twcstorage.ru/$s3Bucket/$encodedKey";
|
||
|
||
// Проверяем, нужно ли обновление
|
||
if ($currentFilename === $correctUrl) {
|
||
logMessage("Пропуск ID $notesid: URL уже правильный");
|
||
$skipped++;
|
||
continue;
|
||
}
|
||
|
||
// Проверяем доступность правильного URL
|
||
$headers = @get_headers($correctUrl, 1);
|
||
if (!$headers || strpos($headers[0], '200') === false) {
|
||
logMessage("Ошибка ID $notesid: файл недоступен даже с правильным URL");
|
||
$errors++;
|
||
continue;
|
||
}
|
||
|
||
if (!$dryRun) {
|
||
// Создаем резервную копию
|
||
$backupFile = $backupDir . '/fix_realfile_backup_' . $notesid . '_' . date('Ymd_His') . '.json';
|
||
$backup = [
|
||
'notesid' => $notesid,
|
||
'title' => $row['title'],
|
||
'original_filename' => $currentFilename,
|
||
'corrected_filename' => $correctUrl,
|
||
's3_key' => $s3Key,
|
||
's3_bucket' => $s3Bucket,
|
||
'timestamp' => date('c')
|
||
];
|
||
file_put_contents($backupFile, json_encode($backup, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||
|
||
// Обновляем URL в базе данных
|
||
$updateQuery = "UPDATE vtiger_notes SET filename = ? WHERE notesid = ?";
|
||
$stmt = $mysqli->prepare($updateQuery);
|
||
$stmt->bind_param('si', $correctUrl, $notesid);
|
||
|
||
if ($stmt->execute()) {
|
||
logMessage("ИСПРАВЛЕНО ID $notesid: {$row['title']}");
|
||
$fixed++;
|
||
} else {
|
||
logMessage("ОШИБКА ID $notesid: " . $stmt->error);
|
||
$errors++;
|
||
}
|
||
$stmt->close();
|
||
} else {
|
||
logMessage("ТЕСТ ID $notesid: {$row['title']} - URL будет исправлен");
|
||
$fixed++;
|
||
}
|
||
}
|
||
|
||
$processed += $batchSize;
|
||
|
||
// Показываем прогресс каждые 500 файлов
|
||
if ($processed % 500 === 0 || $processed >= $totalFiles) {
|
||
$progress = round(($processed / $totalFiles) * 100, 2);
|
||
logMessage("Прогресс: $processed/$totalFiles ($progress%) - Исправлено: $fixed, Ошибок: $errors, Пропущено: $skipped");
|
||
}
|
||
}
|
||
|
||
logMessage("=== ИТОГОВАЯ СТАТИСТИКА ===");
|
||
logMessage("Обработано файлов: $processed");
|
||
logMessage("Исправлено: $fixed");
|
||
logMessage("Ошибок: $errors");
|
||
logMessage("Пропущено: $skipped");
|
||
logMessage("Режим: " . ($dryRun ? "ТЕСТОВЫЙ" : "РАБОЧИЙ"));
|
||
|
||
$mysqli->close();
|
||
echo "\n=== Исправление завершено ===\n";
|
||
?>
|