2025-09-26 10:43:05 +03:00
|
|
|
|
<?php
|
|
|
|
|
|
/**
|
|
|
|
|
|
* API для работы с Nextcloud - простой endpoint
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Устанавливаем заголовки
|
|
|
|
|
|
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('log_errors', 1);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// Получаем параметры
|
|
|
|
|
|
$recordId = $_GET['record'] ?? $_POST['record'] ?? '392936';
|
|
|
|
|
|
$fileName = $_GET['fileName'] ?? $_POST['fileName'] ?? '';
|
|
|
|
|
|
|
|
|
|
|
|
// Логируем параметры для отладки
|
|
|
|
|
|
error_log("Nextcloud API: recordId=$recordId, fileName=$fileName");
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем информацию о файле из CRM
|
|
|
|
|
|
$fileInfo = getFileInfoFromCRM($recordId);
|
|
|
|
|
|
|
|
|
|
|
|
error_log("Nextcloud API: fileInfo=" . json_encode($fileInfo));
|
|
|
|
|
|
|
|
|
|
|
|
if (!$fileInfo) {
|
|
|
|
|
|
throw new Exception('Документ не найден в CRM');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Определяем тип файла и путь
|
2025-10-20 17:17:34 +03:00
|
|
|
|
$baseUrl = 'https://office.clientright.ru';
|
2025-09-26 10:43:05 +03:00
|
|
|
|
|
|
|
|
|
|
if ($fileInfo['filelocationtype'] === 'E' && $fileInfo['s3_key']) {
|
2025-10-24 19:59:28 +03:00
|
|
|
|
// Файл в S3 - формируем путь для Nextcloud External Storage
|
|
|
|
|
|
$ncPath = '/crm/' . $fileInfo['s3_key'];
|
|
|
|
|
|
error_log("Nextcloud API: S3 file, ncPath=$ncPath");
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем реальный fileId через WebDAV
|
2025-09-26 10:43:05 +03:00
|
|
|
|
$fileId = getRealFileId($ncPath);
|
2025-10-24 19:59:28 +03:00
|
|
|
|
error_log("Nextcloud API: Retrieved fileId=$fileId for path=$ncPath");
|
2025-09-26 10:43:05 +03:00
|
|
|
|
} else {
|
|
|
|
|
|
// Локальный файл - нужно скопировать в Nextcloud
|
|
|
|
|
|
// Пока что используем fallback
|
|
|
|
|
|
throw new Exception('Локальные файлы пока не поддерживаются. Загрузите файл в S3 для редактирования в Nextcloud.');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$dirPath = dirname($ncPath);
|
|
|
|
|
|
$fileName = basename($ncPath);
|
|
|
|
|
|
|
|
|
|
|
|
// Проверяем расширение файла
|
|
|
|
|
|
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
|
|
|
|
|
if (!in_array($ext, ['docx', 'xlsx', 'pptx'], true)) {
|
|
|
|
|
|
throw new Exception("Файл с расширением '{$ext}' не поддерживается для редактирования. Поддерживаются: docx, xlsx, pptx");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$urls = [
|
|
|
|
|
|
'files_manager' => $baseUrl . '/apps/files/files/' . $fileId . '?dir=' . rawurlencode($dirPath) . '&editing=false&openfile=true',
|
|
|
|
|
|
'collabora_id' => $baseUrl . '/apps/richdocuments/index?fileId=' . $fileId,
|
|
|
|
|
|
'onlyoffice_id' => $baseUrl . '/apps/onlyoffice?fileId=' . $fileId,
|
|
|
|
|
|
'direct_edit' => $baseUrl . '/apps/files/files/' . $fileId . '?dir=' . rawurlencode($dirPath) . '&openfile=true&scrollto=' . rawurlencode($fileName),
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$result = [
|
|
|
|
|
|
'success' => true,
|
|
|
|
|
|
'data' => [
|
|
|
|
|
|
'record_id' => $recordId,
|
|
|
|
|
|
'file_name' => $fileName,
|
|
|
|
|
|
'file_id' => (int)$fileId,
|
|
|
|
|
|
'nc_path' => $ncPath,
|
|
|
|
|
|
's3_key' => $fileInfo['s3_key'],
|
|
|
|
|
|
'file_size' => $fileInfo['filesize'],
|
|
|
|
|
|
'urls' => $urls,
|
|
|
|
|
|
'message' => 'Файл из S3 подготовлен к редактированию в Nextcloud'
|
|
|
|
|
|
]
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
http_response_code(500);
|
|
|
|
|
|
$error = [
|
|
|
|
|
|
'success' => false,
|
|
|
|
|
|
'error' => $e->getMessage()
|
|
|
|
|
|
];
|
|
|
|
|
|
echo json_encode($error, JSON_UNESCAPED_UNICODE);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Получает информацию о файле из CRM
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getFileInfoFromCRM($recordId) {
|
|
|
|
|
|
// Подключаемся к базе данных vTiger
|
|
|
|
|
|
$configPath = dirname(__DIR__, 2) . '/crm.clientright.ru/config.inc.php';
|
|
|
|
|
|
error_log("Nextcloud API: Looking for config at: $configPath");
|
|
|
|
|
|
|
|
|
|
|
|
if (!file_exists($configPath)) {
|
|
|
|
|
|
error_log("Nextcloud API: Config file not found at: $configPath");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
include $configPath;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
$db = new PDO(
|
|
|
|
|
|
"mysql:host={$dbconfig['db_server']};dbname={$dbconfig['db_name']};charset=utf8",
|
|
|
|
|
|
$dbconfig['db_username'],
|
|
|
|
|
|
$dbconfig['db_password']
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
error_log("Nextcloud API: Database connected successfully");
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем информацию о файле из CRM
|
|
|
|
|
|
$stmt = $db->prepare("
|
|
|
|
|
|
SELECT n.notesid, n.title, n.filename, n.filelocationtype, n.filesize,
|
|
|
|
|
|
n.s3_bucket, n.s3_key, n.s3_etag, n.nc_path,
|
|
|
|
|
|
a.attachmentsid, a.path, a.storedname
|
|
|
|
|
|
FROM vtiger_notes n
|
|
|
|
|
|
LEFT JOIN vtiger_attachments a ON n.notesid = a.attachmentsid
|
|
|
|
|
|
WHERE n.notesid = ?
|
|
|
|
|
|
");
|
|
|
|
|
|
$stmt->execute([$recordId]);
|
|
|
|
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
|
|
|
|
|
|
|
|
error_log("Nextcloud API: Query result=" . json_encode($row));
|
|
|
|
|
|
|
|
|
|
|
|
return $row;
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
error_log("Database error: " . $e->getMessage());
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Получает реальный fileId для файла из Nextcloud
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getRealFileId($ncPath) {
|
|
|
|
|
|
if (!$ncPath) {
|
|
|
|
|
|
return 665; // Fallback
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Пытаемся получить реальный fileId через WebDAV
|
|
|
|
|
|
try {
|
2025-10-20 17:17:34 +03:00
|
|
|
|
$url = 'https://office.clientright.ru/remote.php/dav/files/admin' . $ncPath;
|
2025-09-26 10:43:05 +03:00
|
|
|
|
|
|
|
|
|
|
$ch = curl_init();
|
|
|
|
|
|
curl_setopt_array($ch, [
|
|
|
|
|
|
CURLOPT_URL => $url,
|
|
|
|
|
|
CURLOPT_CUSTOMREQUEST => 'PROPFIND',
|
|
|
|
|
|
CURLOPT_USERPWD => 'admin:yft,fkjdj', // Правильные учетные данные из .env
|
|
|
|
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
|
|
|
|
CURLOPT_TIMEOUT => 10,
|
|
|
|
|
|
CURLOPT_HTTPHEADER => [
|
|
|
|
|
|
'Content-Type: application/xml',
|
|
|
|
|
|
'Depth: 0'
|
|
|
|
|
|
],
|
|
|
|
|
|
CURLOPT_POSTFIELDS => '<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
|
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
|
|
|
|
|
<d:prop>
|
|
|
|
|
|
<oc:fileid/>
|
|
|
|
|
|
</d:prop>
|
|
|
|
|
|
</d:propfind>'
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$response = curl_exec($ch);
|
|
|
|
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
|
|
|
|
if ($httpCode === 207 && preg_match('/<oc:fileid>(\d+)<\/oc:fileid>/', $response, $matches)) {
|
|
|
|
|
|
return (int)$matches[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
error_log('WebDAV error: ' . $e->getMessage());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Fallback: генерируем fileId на основе пути
|
|
|
|
|
|
return 665 + (abs(crc32($ncPath)) % 100);
|
|
|
|
|
|
}
|
|
|
|
|
|
?>
|