Files
crm.clientright.ru/crm_extensions/file_storage/analyze_broken_files.php

146 lines
4.1 KiB
PHP

<?php
/**
* Analyze Broken Files - анализирует "битые" записи без S3 метаданных
*/
ini_set('memory_limit', '512M');
set_time_limit(0);
date_default_timezone_set('Europe/Moscow');
$ROOT = '/var/www/fastuser/data/www/crm.clientright.ru/';
require_once $ROOT . 'config.inc.php';
// CLI options
$opts = getopt('', [
'limit::',
'format::',
'check-files::'
]);
$limit = isset($opts['limit']) ? (int)$opts['limit'] : 100;
$format = isset($opts['format']) ? $opts['format'] : 'json';
$checkFiles = isset($opts['check-files']) ? (int)$opts['check-files'] !== 0 : false;
// 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");
// Get records without S3 metadata
$query = "SELECT notesid, filename, filesize, filetype, filelocationtype
FROM vtiger_notes
WHERE (s3_key IS NULL OR s3_key = '')
AND filelocationtype = 'I'
ORDER BY notesid DESC
LIMIT $limit";
$result = $mysqli->query($query);
if (!$result) {
die("Query failed: " . $mysqli->error);
}
$broken_files = [];
$stats = [
'total_checked' => 0,
'files_exist' => 0,
'files_missing' => 0,
'permission_denied' => 0,
'empty_filename' => 0,
'invalid_path' => 0
];
while ($row = $result->fetch_assoc()) {
$stats['total_checked']++;
$file_info = [
'notesid' => $row['notesid'],
'filename' => $row['filename'],
'filesize' => $row['filesize'],
'filetype' => $row['filetype'],
'status' => 'unknown',
'issue' => '',
'full_path' => ''
];
// Check filename
if (empty($row['filename'])) {
$file_info['status'] = 'error';
$file_info['issue'] = 'empty_filename';
$stats['empty_filename']++;
} else {
// Build full path
$filename = $row['filename'];
// Try different path variations
$possible_paths = [
$ROOT . 'storage/' . $filename,
$ROOT . $filename,
$ROOT . 'test/storage/' . $filename,
'/var/www/fastuser/data/www/crm.clientright.ru/storage/' . $filename
];
$file_found = false;
foreach ($possible_paths as $path) {
if ($checkFiles && file_exists($path)) {
$file_info['status'] = 'exists';
$file_info['full_path'] = $path;
$file_info['actual_size'] = filesize($path);
$stats['files_exist']++;
$file_found = true;
break;
}
}
if (!$file_found) {
if ($checkFiles) {
$file_info['status'] = 'missing';
$file_info['issue'] = 'file_not_found';
$file_info['tried_paths'] = $possible_paths;
$stats['files_missing']++;
} else {
$file_info['status'] = 'unchecked';
$file_info['expected_path'] = $possible_paths[0];
}
}
}
$broken_files[] = $file_info;
}
$mysqli->close();
// Output results
$output = [
'timestamp' => date('Y-m-d H:i:s'),
'query_limit' => $limit,
'file_check_enabled' => $checkFiles,
'statistics' => $stats,
'files' => $broken_files
];
if ($format === 'json') {
echo json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} else {
// Simple table format
printf("%-8s %-50s %-10s %-15s %s\n",
"ID", "Filename", "Size", "Status", "Issue");
echo str_repeat("-", 100) . "\n";
foreach ($broken_files as $file) {
printf("%-8s %-50s %-10s %-15s %s\n",
$file['notesid'],
substr($file['filename'], 0, 47) . (strlen($file['filename']) > 47 ? '...' : ''),
$file['filesize'] ?? 'N/A',
$file['status'],
$file['issue']
);
}
echo "\nStatistics:\n";
foreach ($stats as $key => $value) {
echo "$key: $value\n";
}
}