feat: Добавлен инструмент генерации документов для AI Ассистента
- Создан API create_document_with_text.php для создания DOCX/XLSX/PPTX с текстом от AI - Поддержка Markdown форматирования (заголовки, жирный, курсив, списки, код) - Установлен PHPWord для красивого форматирования документов - Исправлены пути сохранения (crm2/CRM_Active_Files/... без /crm/ в начале) - Замена пробелов на подчеркивания в именах папок - Создана документация для AI и разработчиков - Добавлены API для работы с шаблонами Nextcloud
This commit is contained in:
@@ -1,97 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* Открытие файла через Nextcloud + OnlyOffice
|
||||
* Для сравнения с прямым OnlyOffice
|
||||
* Открытие файла через Nextcloud (РАБОЧАЯ ВЕРСИЯ v2)
|
||||
* Использует Redis индекс для быстрого получения FileID
|
||||
*/
|
||||
|
||||
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');
|
||||
|
||||
// Отключаем вывод ошибок в браузер
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_errors', 0);
|
||||
|
||||
$fileName = isset($_GET['fileName']) ? $_GET['fileName'] : '';
|
||||
$recordId = isset($_GET['recordId']) ? $_GET['recordId'] : '';
|
||||
// Отключаем buffering
|
||||
if (ob_get_level()) ob_end_clean();
|
||||
|
||||
if (empty($fileName)) {
|
||||
die("❌ fileName не указан");
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-cache, must-revalidate');
|
||||
|
||||
$recordId = isset($_GET['recordId']) ? (int)$_GET['recordId'] : 0;
|
||||
|
||||
if ($recordId <= 0) {
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid recordId']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Извлекаем S3 путь
|
||||
$s3Path = '';
|
||||
if (strpos($fileName, 'http') === 0) {
|
||||
$fileName = urldecode($fileName);
|
||||
$bucketId = 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c';
|
||||
$pos = strpos($fileName, $bucketId . '/');
|
||||
if ($pos !== false) {
|
||||
$s3Path = substr($fileName, $pos + strlen($bucketId) + 1);
|
||||
try {
|
||||
// 1. Получаем filename из БД
|
||||
$db = new mysqli('localhost', 'ci20465_72new', 'EcY979Rn', 'ci20465_72new');
|
||||
|
||||
if ($db->connect_error) {
|
||||
throw new Exception('DB connection failed');
|
||||
}
|
||||
|
||||
$db->set_charset('utf8mb4');
|
||||
|
||||
$stmt = $db->prepare("SELECT filename FROM vtiger_notes WHERE notesid = ?");
|
||||
$stmt->bind_param('i', $recordId);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$row = $result->fetch_assoc();
|
||||
$db->close();
|
||||
|
||||
if (!$row || empty($row['filename'])) {
|
||||
throw new Exception('File not found in DB');
|
||||
}
|
||||
|
||||
$fileName = $row['filename'];
|
||||
|
||||
// 2. Извлекаем S3 путь из URL
|
||||
$bucketId = 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c';
|
||||
$fileName = rawurldecode($fileName);
|
||||
$pos = strpos($fileName, $bucketId . '/');
|
||||
|
||||
if ($pos === false) {
|
||||
throw new Exception('Invalid S3 path in filename');
|
||||
}
|
||||
|
||||
$s3Path = substr($fileName, $pos + strlen($bucketId) + 1);
|
||||
|
||||
// 3. Получаем FileID из Redis
|
||||
$redis = new Redis();
|
||||
if (!$redis->connect('crm.clientright.ru', 6379)) {
|
||||
throw new Exception('Redis connection failed');
|
||||
}
|
||||
|
||||
$redis->auth('CRM_Redis_Pass_2025_Secure!');
|
||||
|
||||
$redisKey = "crm:nc:fileid:" . $s3Path;
|
||||
$cached = $redis->get($redisKey);
|
||||
|
||||
if (!$cached) {
|
||||
$redis->close();
|
||||
throw new Exception('FileID not found in Redis index. Key: ' . substr($redisKey, 0, 100));
|
||||
}
|
||||
|
||||
$data = json_decode($cached, true);
|
||||
$fileId = $data['fileId'] ?? null;
|
||||
|
||||
$redis->close();
|
||||
|
||||
if (!$fileId) {
|
||||
throw new Exception('Invalid FileID data in Redis');
|
||||
}
|
||||
|
||||
// 4. Формируем URL для Nextcloud
|
||||
$nextcloudUrl = 'https://office.clientright.ru:8443';
|
||||
$ncPath = '/crm/' . $s3Path;
|
||||
$dirPath = dirname($ncPath);
|
||||
|
||||
$redirectUrl = $nextcloudUrl . '/apps/files/files/' . $fileId . '?dir=' . urlencode($dirPath) . '&openfile=true';
|
||||
|
||||
// 5. Возвращаем успешный ответ
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'fileId' => $fileId,
|
||||
'redirectUrl' => $redirectUrl,
|
||||
'source' => 'redis',
|
||||
'recordId' => $recordId
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'recordId' => $recordId
|
||||
]);
|
||||
}
|
||||
|
||||
if (empty($s3Path)) {
|
||||
die("❌ Не удалось извлечь путь из URL");
|
||||
}
|
||||
|
||||
// Nextcloud credentials
|
||||
$nextcloudUrl = 'https://office.clientright.ru:8443';
|
||||
$username = 'admin';
|
||||
$password = 'office';
|
||||
|
||||
// Формируем WebDAV путь
|
||||
$ncPath = '/crm/' . $s3Path;
|
||||
$webdavUrl = $nextcloudUrl . '/remote.php/dav/files/' . $username . $ncPath;
|
||||
|
||||
error_log("=== NEXTCLOUD OPEN ===");
|
||||
error_log("S3 Path: " . $s3Path);
|
||||
error_log("Nextcloud WebDAV: " . $webdavUrl);
|
||||
|
||||
// Получаем fileId через PROPFIND
|
||||
$ch = curl_init($webdavUrl);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PROPFIND');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Depth: 0',
|
||||
'Content-Type: application/xml'
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, '<?xml version="1.0"?>
|
||||
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||
<d:prop>
|
||||
<oc:fileid/>
|
||||
</d:prop>
|
||||
</d:propfind>');
|
||||
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
error_log("PROPFIND HTTP код: " . $httpCode);
|
||||
|
||||
if ($httpCode !== 207) {
|
||||
die("❌ Файл не найден в Nextcloud (HTTP $httpCode). Возможно, он не проиндексирован.");
|
||||
}
|
||||
|
||||
// Извлекаем fileId из XML
|
||||
preg_match('/<oc:fileid>(\d+)<\/oc:fileid>/', $response, $matches);
|
||||
if (!isset($matches[1])) {
|
||||
die("❌ Не удалось получить fileId");
|
||||
}
|
||||
|
||||
$fileId = $matches[1];
|
||||
error_log("Получен fileId: " . $fileId);
|
||||
|
||||
// Извлекаем директорию из пути
|
||||
$dirPath = dirname($ncPath);
|
||||
|
||||
// Формируем URL для открытия в Nextcloud
|
||||
// Nextcloud автоматически откроет OnlyOffice для редактирования
|
||||
$redirectUrl = $nextcloudUrl . '/apps/files/files/' . $fileId . '?dir=' . urlencode($dirPath) . '&openfile=true';
|
||||
|
||||
error_log("Redirect to: " . $redirectUrl);
|
||||
|
||||
// Редирект в Nextcloud
|
||||
header('Location: ' . $redirectUrl);
|
||||
exit;
|
||||
?>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user