Files
crm.clientright.ru/crm_extensions/file_storage/api/prepare_edit_v2.php
Fedor 9245768987 🚀 CRM Files Migration & Real-time Features
 Features:
- Migrated ALL files to new S3 structure (Projects, Contacts, Accounts, HelpDesk, Invoice, etc.)
- Added Nextcloud folder buttons to ALL modules
- Fixed Nextcloud editor integration
- WebSocket server for real-time updates
- Redis Pub/Sub integration
- File path manager for organized storage
- Redis caching for performance (Functions.php)

📁 New Structure:
Documents/Project/ProjectName_ID/file_docID.ext
Documents/Contacts/FirstName_LastName_ID/file_docID.ext
Documents/Accounts/AccountName_ID/file_docID.ext

🔧 Technical:
- FilePathManager for standardized paths
- S3StorageService integration
- WebSocket server (Node.js + Docker)
- Redis cache for getBasicModuleInfo()
- Predis library for Redis connectivity

📝 Scripts:
- Migration scripts for all modules
- Test pages for WebSocket/SSE/Polling
- Documentation (MIGRATION_*.md, REDIS_*.md)

🎯 Result: 15,000+ files migrated successfully!
2025-10-24 19:59:28 +03:00

209 lines
8.1 KiB
PHP
Raw 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
/**
* API v2 для подготовки файла к редактированию в Nextcloud
* Использует новую структуру файлов с FilePathManager
*/
// Подключаем конфигурацию
require_once '/var/www/fastuser/data/www/crm.clientright.ru/config.inc.php';
require_once '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/file_storage/FilePathManager.php';
require_once '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/shared/EnvLoader.php';
// Загружаем переменные окружения
EnvLoader::load('/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/.env');
// Устанавливаем заголовки для JSON
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// Включаем отображение ошибок для отладки
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Обрабатываем OPTIONS запросы
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
try {
// Логируем запрос для отладки
error_log("Nextcloud API v2 called with: " . json_encode($_GET));
// Получаем параметры
$recordId = $_GET['recordId'] ?? $_POST['recordId'] ?? null;
$fileName = $_GET['fileName'] ?? $_POST['fileName'] ?? null;
$module = $_GET['module'] ?? $_POST['module'] ?? 'Project';
// Декодируем URL-кодированное имя файла
if ($fileName) {
$fileName = urldecode($fileName);
}
error_log("Parsed parameters: recordId=$recordId, fileName=$fileName, module=$module");
if (!$recordId || !$fileName) {
throw new Exception('Необходимы параметры recordId и fileName');
}
// Инициализируем FilePathManager
$pathMgr = new FilePathManager();
// Получаем информацию о файле из CRM
error_log("API: Calling getFileInfoFromCRM with recordId=$recordId, fileName=$fileName, module=$module");
$fileInfo = getFileInfoFromCRM($recordId, $fileName, $module);
error_log("API: getFileInfoFromCRM returned: " . json_encode($fileInfo));
if (!$fileInfo) {
// Добавляем отладочную информацию
$debugInfo = "recordId=$recordId, fileName=$fileName, module=$module";
throw new Exception("Файл не найден в CRM для записи $recordId. Debug: $debugInfo");
}
// Получаем правильный путь через FilePathManager
$recordName = $pathMgr->getRecordName($module, $recordId);
$filePath = $pathMgr->getFilePath($module, $recordId, $fileInfo['documentId'], $fileName, $fileInfo['title'], $recordName);
error_log("Generated file path: $filePath");
// Формируем URL для Nextcloud (используем внешнее хранилище S3)
$nextcloudPath = '/crm/' . $filePath;
error_log("Nextcloud path: $nextcloudPath");
// Создаём прямую ссылку для редактирования (Nextcloud сам найдет файл по пути)
$editResult = createDirectEditLink($nextcloudPath, $recordId, $fileName, $fileInfo['documentId']);
// Возвращаем результат
echo json_encode([
'success' => true,
'data' => [
'record_id' => $recordId,
'document_id' => $fileInfo['documentId'],
'file_name' => $fileName,
'file_id' => $fileInfo['documentId'],
'file_path' => $filePath,
'nextcloud_path' => $nextcloudPath,
'edit_url' => $editResult['edit_url'],
'share_url' => $editResult['share_url'] ?? null,
'message' => 'Файл подготовлен к редактированию'
]
]);
} catch (Exception $e) {
error_log("API v2 Error: " . $e->getMessage());
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}
/**
* Получает информацию о файле из CRM
*/
function getFileInfoFromCRM($recordId, $fileName, $module) {
try {
// Используем PDO для подключения к БД
$dsn = 'mysql:host=localhost;dbname=ci20465_72new;charset=utf8';
$pdo = new PDO($dsn, 'ci20465_72new', 'CRM_DB_Pass_2025_Secure!');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Ищем файл в базе данных по documentId (извлекаем из fileName)
$documentId = null;
if (preg_match('/_(\d+)\.pdf$/', $fileName, $matches)) {
$documentId = (int)$matches[1];
}
if (!$documentId) {
error_log("ERROR: Could not extract documentId from fileName: $fileName");
return null;
}
error_log("Extracted documentId=$documentId from fileName=$fileName");
$sql = "SELECT n.notesid, n.title, n.filename, n.s3_key, n.s3_bucket
FROM vtiger_notes n
INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid
WHERE sr.crmid = ? AND n.notesid = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$recordId, $documentId]);
error_log("Searching for recordId=$recordId, documentId=$documentId");
if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
error_log("Found file: " . json_encode($row));
return [
'documentId' => $row['notesid'],
'title' => $row['title'],
'filename' => $row['filename'],
's3_key' => $row['s3_key'],
's3_bucket' => $row['s3_bucket']
];
}
error_log("No file found for recordId=$recordId, documentId=$documentId");
return null;
} catch (Exception $e) {
error_log("Error getting file info from CRM: " . $e->getMessage());
return null;
}
}
/**
* Проверяет существование файла в S3
*/
function checkFileInS3($filePath) {
try {
// Используем S3 клиент для проверки
require_once __DIR__ . '/../S3Client.php';
$s3Config = [
'version' => 'latest',
'region' => 'ru-1',
'endpoint' => 'https://s3.twcstorage.ru',
'bucket' => 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c',
'use_path_style_endpoint' => true,
'key' => EnvLoader::getRequired('S3_ACCESS_KEY'),
'secret' => EnvLoader::getRequired('S3_SECRET_KEY')
];
$s3Client = new S3Client($s3Config);
return $s3Client->fileExists($filePath);
} catch (Exception $e) {
error_log("Error checking S3 file: " . $e->getMessage());
return false;
}
}
/**
* Создаёт прямую ссылку для редактирования
*/
function createDirectEditLink($nextcloudPath, $recordId, $fileName, $documentId) {
$baseUrl = 'https://office.clientright.ru:8443';
// Кодируем путь правильно для Nextcloud
$pathParts = explode('/', $nextcloudPath);
$encodedParts = array_map('rawurlencode', $pathParts);
$encodedPath = implode('/', $encodedParts);
// Извлекаем директорию (без имени файла)
$dir = dirname($nextcloudPath);
$encodedDir = str_replace(basename($nextcloudPath), '', $encodedPath);
$encodedDir = rtrim($encodedDir, '/');
// URL для открытия файла в Nextcloud Files (он сам найдет fileId по пути)
$filesUrl = "$baseUrl/apps/files/?dir=" . rawurlencode($dir) . "&openfile=" . rawurlencode(basename($nextcloudPath));
return [
'edit_url' => $filesUrl,
'share_url' => $filesUrl
];
}