Files
crm.clientright.ru/modules/Documents/actions/NcPrepareEdit.php
Fedor f582cf9c0f fix: Обновлены пути Nextcloud с /crm2/ на /crm/ для нового сервера
Обновленные файлы:
- crm_extensions/nextcloud_editor/js/nextcloud-editor.js (5 путей)
- crm_extensions/file_storage/api/get_edit_urls.php (6 путей)
- modules/Documents/actions/NcPrepareEdit.php (2 пути)
- crm_extensions/file_storage/api/prepare_edit.php (1 путь)
- crm_extensions/file_storage/NextcloudClient.php (1 путь)
- data/CRMEntity.php (nc_path для новых файлов)

Все пути теперь используют /crm/ вместо /crm2/ для соответствия новому External Storage на office.clientright.ru
2025-10-20 17:23:20 +03:00

203 lines
7.3 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
/**
* Action для подготовки файла к редактированию в Nextcloud
*/
class Documents_NcPrepareEdit_Action extends Vtiger_Action_Controller {
public function requiresPermission(\Vtiger_Request $request) {
$permissions = parent::requiresPermission($request);
$permissions[] = array('module_parameter' => 'module', 'action' => 'DetailView', 'record_parameter' => 'record');
return $permissions;
}
public function checkPermission(\Vtiger_Request $request) {
return parent::checkPermission($request);
}
public function process(\Vtiger_Request $request) {
// Устанавливаем заголовки
header('Content-Type: application/json; charset=utf-8');
try {
$recordId = trim($request->get('record'));
$fileName = trim($request->get('fileName'));
if (empty($recordId) || empty($fileName)) {
throw new Exception('record или fileName отсутствуют');
}
// Проверяем поддерживаемые расширения
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
if (!in_array($ext, ['docx', 'xlsx', 'pptx'], true)) {
throw new Exception('Неподдерживаемое расширение: ' . $ext);
}
// Получаем fileId из Nextcloud
$fileId = $this->resolveNcFileId((int)$recordId, $fileName);
$baseUrl = $this->getNcBaseUrl();
$dirPath = $this->getDirPath($recordId);
$urls = [
'collabora_id' => $fileId ? $baseUrl . '/apps/richdocuments/index?fileId=' . rawurlencode((string)$fileId) : null,
'onlyoffice_id' => $fileId ? $baseUrl . '/apps/onlyoffice?fileId=' . rawurlencode((string)$fileId) : null,
'files_manager' => $baseUrl . '/apps/files/?dir=' . rawurlencode($dirPath) . '&openfile=' . rawurlencode($fileName)
];
// Убираем null значения
$urls = array_filter($urls, function($url) {
return $url !== null;
});
echo json_encode([
'success' => true,
'data' => [
'record_id' => $recordId,
'file_name' => $fileName,
'file_id' => $fileId,
'urls' => $urls,
'message' => 'Файл подготовлен к редактированию'
]
], JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage()
], JSON_UNESCAPED_UNICODE);
}
}
/**
* Получение базового URL Nextcloud
*/
private function getNcBaseUrl(): string {
return 'https://office.clientright.ru';
}
/**
* Получение пути к директории
*/
private function getDirPath($recordId): string {
return '/crm/CRM_Active_Files/Documents/' . $recordId;
}
/**
* Получение fileId из Nextcloud через WebDAV
*/
private function resolveNcFileId(int $recordId, string $fileName): ?int {
try {
$config = $this->getNcConfig();
$ncPath = $this->getNcPath($recordId, $fileName);
// 1) PROPFIND для получения метаданных
$meta = $this->webdavPropfind($config, $ncPath);
if ($meta['status'] === 404) {
// Файл не существует - нужно создать
error_log("File not found in Nextcloud: {$ncPath}");
return null;
}
if ($meta['status'] === 200 && isset($meta['fileid'])) {
error_log("Found fileId for {$fileName}: " . $meta['fileid']);
return (int)$meta['fileid'];
}
error_log("Could not get fileId from PROPFIND response");
return null;
} catch (Exception $e) {
error_log('Error resolving fileId: ' . $e->getMessage());
return null;
}
}
/**
* Получение конфигурации Nextcloud
*/
private function getNcConfig(): array {
$configPath = __DIR__ . '/../../../../crm_extensions/file_storage/config.php';
if (!file_exists($configPath)) {
throw new Exception('Nextcloud config not found');
}
$config = require_once $configPath;
return $config['nextcloud'];
}
/**
* Получение пути к файлу в Nextcloud
*/
private function getNcPath(int $recordId, string $fileName): string {
return "/crm/CRM_Active_Files/Documents/{$recordId}/" . rawurlencode($fileName);
}
/**
* WebDAV PROPFIND запрос
*/
private function webdavPropfind(array $config, string $remotePath): array {
$url = $config['base_url'] . '/remote.php/dav/files/' . $config['username'] . $remotePath;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_CUSTOMREQUEST => 'PROPFIND',
CURLOPT_USERPWD => $config['username'] . ':' . $config['password'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
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>
<d:getetag/>
<d:getlastmodified/>
<d:getcontentlength/>
<oc:fileid/>
</d:prop>
</d:propfind>'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new Exception("cURL error: {$error}");
}
$result = ['status' => $httpCode];
if ($httpCode === 207 && $response) {
// Извлекаем данные с помощью регулярных выражений
// Ищем fileid
if (preg_match('/<oc:fileid>(\d+)<\/oc:fileid>/', $response, $matches)) {
$result['fileid'] = $matches[1];
}
// Ищем etag
if (preg_match('/<d:getetag>&quot;([^&]+)&quot;<\/d:getetag>/', $response, $matches)) {
$result['etag'] = $matches[1];
}
// Ищем размер
if (preg_match('/<d:getcontentlength>(\d+)<\/d:getcontentlength>/', $response, $matches)) {
$result['size'] = (int)$matches[1];
}
// Ищем дату модификации
if (preg_match('/<d:getlastmodified>([^<]+)<\/d:getlastmodified>/', $response, $matches)) {
$result['mtime'] = $matches[1];
}
}
return $result;
}
}
?>