321 lines
12 KiB
PHP
321 lines
12 KiB
PHP
<?php
|
||
/**
|
||
* Детальный анализ "битых" файлов
|
||
*
|
||
* Анализирует файлы, которые есть в БД, но физически отсутствуют
|
||
* Проверяет зависимости, категоризирует и дает рекомендации
|
||
*/
|
||
|
||
require_once '/var/www/fastuser/data/www/crm.clientright.ru/config.inc.php';
|
||
$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 "=== ДЕТАЛЬНЫЙ АНАЛИЗ БИТЫХ ФАЙЛОВ ===\n";
|
||
echo "Дата анализа: " . date('Y-m-d H:i:s') . "\n\n";
|
||
|
||
// Получаем все "битые" файлы
|
||
$query = "SELECT notesid, filename, filesize, filetype, filelocationtype
|
||
FROM vtiger_notes
|
||
WHERE filelocationtype = 'I'
|
||
AND (s3_key IS NULL OR s3_key = '')
|
||
ORDER BY notesid ASC";
|
||
|
||
$result = $mysqli->query($query);
|
||
$totalBroken = $result->num_rows;
|
||
|
||
echo "Всего битых файлов: $totalBroken\n";
|
||
echo "==========================================\n\n";
|
||
|
||
// Анализируем по категориям
|
||
$categories = [
|
||
'empty_filename' => [],
|
||
'zero_size' => [],
|
||
'duplicate_names' => [],
|
||
'file_15_series' => [],
|
||
'evidence_files' => [],
|
||
'old_files' => [],
|
||
'pdf_files' => [],
|
||
'image_files' => [],
|
||
'other' => []
|
||
];
|
||
|
||
$filenameCounts = [];
|
||
$fileTypes = [];
|
||
$sizeRanges = [
|
||
'0 bytes' => 0,
|
||
'1-1KB' => 0,
|
||
'1-10KB' => 0,
|
||
'10-100KB' => 0,
|
||
'100KB-1MB' => 0,
|
||
'1MB+' => 0
|
||
];
|
||
|
||
$idRanges = [
|
||
'1-1000' => 0,
|
||
'1000-10000' => 0,
|
||
'10000-50000' => 0,
|
||
'50000-100000' => 0,
|
||
'100000+' => 0
|
||
];
|
||
|
||
while ($row = $result->fetch_assoc()) {
|
||
$notesid = $row['notesid'];
|
||
$filename = $row['filename'];
|
||
$filesize = $row['filesize'];
|
||
$filetype = $row['filetype'];
|
||
|
||
// Подсчет по размерам
|
||
if ($filesize == 0) {
|
||
$sizeRanges['0 bytes']++;
|
||
} elseif ($filesize < 1024) {
|
||
$sizeRanges['1-1KB']++;
|
||
} elseif ($filesize < 10240) {
|
||
$sizeRanges['1-10KB']++;
|
||
} elseif ($filesize < 102400) {
|
||
$sizeRanges['10-100KB']++;
|
||
} elseif ($filesize < 1048576) {
|
||
$sizeRanges['100KB-1MB']++;
|
||
} else {
|
||
$sizeRanges['1MB+']++;
|
||
}
|
||
|
||
// Подсчет по ID диапазонам
|
||
if ($notesid <= 1000) {
|
||
$idRanges['1-1000']++;
|
||
} elseif ($notesid <= 10000) {
|
||
$idRanges['1000-10000']++;
|
||
} elseif ($notesid <= 50000) {
|
||
$idRanges['10000-50000']++;
|
||
} elseif ($notesid <= 100000) {
|
||
$idRanges['50000-100000']++;
|
||
} else {
|
||
$idRanges['100000+']++;
|
||
}
|
||
|
||
// Подсчет типов файлов
|
||
$fileTypes[$filetype] = ($fileTypes[$filetype] ?? 0) + 1;
|
||
|
||
// Подсчет имен файлов
|
||
$filenameCounts[$filename] = ($filenameCounts[$filename] ?? 0) + 1;
|
||
|
||
// Категоризация
|
||
if (empty($filename) || $filename == '') {
|
||
$categories['empty_filename'][] = $row;
|
||
} elseif ($filesize == 0) {
|
||
$categories['zero_size'][] = $row;
|
||
} elseif (strpos($filename, 'file_15_') === 0) {
|
||
$categories['file_15_series'][] = $row;
|
||
} elseif (strpos($filename, 'доказательство') !== false || strpos($filename, 'evidence') !== false) {
|
||
$categories['evidence_files'][] = $row;
|
||
} elseif (strpos($filename, '7777777') !== false) {
|
||
$categories['old_files'][] = $row;
|
||
} elseif (strtolower(pathinfo($filename, PATHINFO_EXTENSION)) == 'pdf') {
|
||
$categories['pdf_files'][] = $row;
|
||
} elseif (in_array(strtolower(pathinfo($filename, PATHINFO_EXTENSION)), ['jpg', 'jpeg', 'png', 'gif'])) {
|
||
$categories['image_files'][] = $row;
|
||
} else {
|
||
$categories['other'][] = $row;
|
||
}
|
||
}
|
||
|
||
// Выводим статистику по размерам
|
||
echo "РАСПРЕДЕЛЕНИЕ ПО РАЗМЕРАМ:\n";
|
||
foreach ($sizeRanges as $range => $count) {
|
||
if ($count > 0) {
|
||
$percentage = round(($count / $totalBroken) * 100, 1);
|
||
echo " $range: $count файлов ($percentage%)\n";
|
||
}
|
||
}
|
||
echo "\n";
|
||
|
||
// Выводим статистику по ID диапазонам
|
||
echo "РАСПРЕДЕЛЕНИЕ ПО ID ДИАПАЗОНАМ:\n";
|
||
foreach ($idRanges as $range => $count) {
|
||
if ($count > 0) {
|
||
$percentage = round(($count / $totalBroken) * 100, 1);
|
||
echo " ID $range: $count файлов ($percentage%)\n";
|
||
}
|
||
}
|
||
echo "\n";
|
||
|
||
// Выводим статистику по типам файлов
|
||
echo "РАСПРЕДЕЛЕНИЕ ПО ТИПАМ ФАЙЛОВ:\n";
|
||
arsort($fileTypes);
|
||
foreach ($fileTypes as $type => $count) {
|
||
$percentage = round(($count / $totalBroken) * 100, 1);
|
||
echo " $type: $count файлов ($percentage%)\n";
|
||
}
|
||
echo "\n";
|
||
|
||
// Выводим дубликаты имен
|
||
echo "ДУБЛИКАТЫ ИМЕН ФАЙЛОВ (топ-10):\n";
|
||
$duplicates = array_filter($filenameCounts, function($count) { return $count > 1; });
|
||
arsort($duplicates);
|
||
$duplicateCount = 0;
|
||
foreach ($duplicates as $filename => $count) {
|
||
if ($duplicateCount >= 10) break;
|
||
echo " '$filename': $count раз\n";
|
||
$duplicateCount++;
|
||
}
|
||
if (count($duplicates) > 10) {
|
||
echo " ... и еще " . (count($duplicates) - 10) . " дубликатов\n";
|
||
}
|
||
echo "\n";
|
||
|
||
// Выводим категории
|
||
echo "КАТЕГОРИИ ФАЙЛОВ:\n";
|
||
foreach ($categories as $category => $files) {
|
||
if (count($files) > 0) {
|
||
$percentage = round((count($files) / $totalBroken) * 100, 1);
|
||
echo " $category: " . count($files) . " файлов ($percentage%)\n";
|
||
|
||
// Показываем примеры для каждой категории
|
||
if (count($files) <= 5) {
|
||
foreach ($files as $file) {
|
||
echo " - ID: {$file['notesid']}, File: {$file['filename']}, Size: {$file['filesize']}\n";
|
||
}
|
||
} else {
|
||
echo " Примеры:\n";
|
||
for ($i = 0; $i < 3; $i++) {
|
||
$file = $files[$i];
|
||
echo " - ID: {$file['notesid']}, File: {$file['filename']}, Size: {$file['filesize']}\n";
|
||
}
|
||
echo " ... и еще " . (count($files) - 3) . " файлов\n";
|
||
}
|
||
echo "\n";
|
||
}
|
||
}
|
||
|
||
// Проверяем зависимости
|
||
echo "ПРОВЕРКА ЗАВИСИМОСТЕЙ:\n";
|
||
|
||
// Проверяем vtiger_attachments
|
||
$attachmentQuery = "SELECT COUNT(*) as count FROM vtiger_attachments WHERE notesid IN (
|
||
SELECT notesid FROM vtiger_notes
|
||
WHERE filelocationtype = 'I'
|
||
AND (s3_key IS NULL OR s3_key = '')
|
||
)";
|
||
$attachmentResult = $mysqli->query($attachmentQuery);
|
||
$attachmentCount = $attachmentResult->fetch_assoc()['count'];
|
||
echo " Записи в vtiger_attachments: $attachmentCount\n";
|
||
|
||
// Проверяем vtiger_crmentity
|
||
$crmentityQuery = "SELECT COUNT(*) as count FROM vtiger_crmentity WHERE crmid IN (
|
||
SELECT notesid FROM vtiger_notes
|
||
WHERE filelocationtype = 'I'
|
||
AND (s3_key IS NULL OR s3_key = '')
|
||
)";
|
||
$crmentityResult = $mysqli->query($crmentityQuery);
|
||
$crmentityCount = $crmentityResult->fetch_assoc()['count'];
|
||
echo " Записи в vtiger_crmentity: $crmentityCount\n";
|
||
|
||
// Проверяем связи с другими модулями
|
||
$relationsQuery = "SELECT COUNT(*) as count FROM vtiger_crmentityrel WHERE crmid IN (
|
||
SELECT notesid FROM vtiger_notes
|
||
WHERE filelocationtype = 'I'
|
||
AND (s3_key IS NULL OR s3_key = '')
|
||
)";
|
||
$relationsResult = $mysqli->query($relationsQuery);
|
||
$relationsCount = $relationsResult->fetch_assoc()['count'];
|
||
echo " Связи в vtiger_crmentityrel: $relationsCount\n";
|
||
|
||
// Проверяем vtiger_seattachmentsrel
|
||
$seattachmentsQuery = "SELECT COUNT(*) as count FROM vtiger_seattachmentsrel WHERE attachmentsid IN (
|
||
SELECT notesid FROM vtiger_notes
|
||
WHERE filelocationtype = 'I'
|
||
AND (s3_key IS NULL OR s3_key = '')
|
||
)";
|
||
$seattachmentsResult = $mysqli->query($seattachmentsQuery);
|
||
$seattachmentsCount = $seattachmentsResult->fetch_assoc()['count'];
|
||
echo " Связи в vtiger_seattachmentsrel: $seattachmentsCount\n";
|
||
|
||
echo "\n";
|
||
|
||
// Анализ безопасности удаления
|
||
echo "=== АНАЛИЗ БЕЗОПАСНОСТИ УДАЛЕНИЯ ===\n";
|
||
|
||
$safeToDelete = 0;
|
||
$needsCheck = 0;
|
||
|
||
// Файлы с пустыми именами - безопасно удалять
|
||
if (count($categories['empty_filename']) > 0) {
|
||
$safeToDelete += count($categories['empty_filename']);
|
||
echo "✅ БЕЗОПАСНО УДАЛИТЬ: " . count($categories['empty_filename']) . " файлов с пустыми именами\n";
|
||
}
|
||
|
||
// Файлы размером 0 байт - безопасно удалять
|
||
if (count($categories['zero_size']) > 0) {
|
||
$safeToDelete += count($categories['zero_size']);
|
||
echo "✅ БЕЗОПАСНО УДАЛИТЬ: " . count($categories['zero_size']) . " файлов размером 0 байт\n";
|
||
}
|
||
|
||
// Старые тестовые файлы - безопасно удалять
|
||
if (count($categories['file_15_series']) > 0) {
|
||
$safeToDelete += count($categories['file_15_series']);
|
||
echo "✅ БЕЗОПАСНО УДАЛИТЬ: " . count($categories['file_15_series']) . " старых тестовых файлов (file_15_*)\n";
|
||
}
|
||
|
||
// Файлы без зависимостей
|
||
if ($attachmentCount == 0 && $crmentityCount == 0 && $relationsCount == 0 && $seattachmentsCount == 0) {
|
||
echo "✅ БЕЗОПАСНО УДАЛИТЬ: Все файлы не имеют зависимостей в других таблицах\n";
|
||
$safeToDelete = $totalBroken;
|
||
} else {
|
||
echo "⚠️ ТРЕБУЕТ ПРОВЕРКИ: " . ($attachmentCount + $crmentityCount + $relationsCount + $seattachmentsCount) . " файлов имеют зависимости\n";
|
||
$needsCheck = $totalBroken - $safeToDelete;
|
||
}
|
||
|
||
echo "\n";
|
||
|
||
// Рекомендации
|
||
echo "=== РЕКОМЕНДАЦИИ ===\n";
|
||
|
||
if ($safeToDelete > 0) {
|
||
echo "🗑️ МОЖНО УДАЛИТЬ БЕЗОПАСНО: $safeToDelete файлов\n";
|
||
echo " - Файлы с пустыми именами\n";
|
||
echo " - Файлы размером 0 байт\n";
|
||
echo " - Старые тестовые файлы\n";
|
||
}
|
||
|
||
if ($needsCheck > 0) {
|
||
echo "🔍 ТРЕБУЕТ ПРОВЕРКИ: $needsCheck файлов\n";
|
||
echo " - Проверить зависимости в других таблицах\n";
|
||
echo " - Возможно, архивировать вместо удаления\n";
|
||
}
|
||
|
||
if (count($duplicates) > 0) {
|
||
echo "🔄 ДУБЛИКАТЫ: " . count($duplicates) . " файлов с одинаковыми именами\n";
|
||
echo " - Проверить, какие из них реально нужны\n";
|
||
}
|
||
|
||
echo "\n";
|
||
|
||
// SQL команды для очистки
|
||
echo "=== SQL КОМАНДЫ ДЛЯ ОЧИСТКИ ===\n";
|
||
|
||
if ($safeToDelete > 0) {
|
||
echo "-- Безопасное удаление файлов с пустыми именами\n";
|
||
echo "DELETE FROM vtiger_notes WHERE filelocationtype = 'I' AND (s3_key IS NULL OR s3_key = '') AND (filename IS NULL OR filename = '');\n\n";
|
||
|
||
echo "-- Безопасное удаление файлов размером 0 байт\n";
|
||
echo "DELETE FROM vtiger_notes WHERE filelocationtype = 'I' AND (s3_key IS NULL OR s3_key = '') AND filesize = 0;\n\n";
|
||
|
||
echo "-- Безопасное удаление старых тестовых файлов\n";
|
||
echo "DELETE FROM vtiger_notes WHERE filelocationtype = 'I' AND (s3_key IS NULL OR s3_key = '') AND filename LIKE 'file_15_%';\n\n";
|
||
}
|
||
|
||
if ($attachmentCount == 0 && $crmentityCount == 0 && $relationsCount == 0 && $seattachmentsCount == 0) {
|
||
echo "-- Удаление всех битых файлов (если нет зависимостей)\n";
|
||
echo "DELETE FROM vtiger_notes WHERE filelocationtype = 'I' AND (s3_key IS NULL OR s3_key = '');\n\n";
|
||
}
|
||
|
||
echo "=== АНАЛИЗ ЗАВЕРШЕН ===\n";
|
||
echo "Всего проанализировано: $totalBroken файлов\n";
|
||
echo "Безопасно удалить: $safeToDelete файлов\n";
|
||
echo "Требует проверки: $needsCheck файлов\n";
|
||
|
||
$mysqli->close();
|
||
?>
|