Обновленные файлы: - 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
305 lines
11 KiB
PHP
305 lines
11 KiB
PHP
<?php
|
||
/**
|
||
* API для подготовки файла к редактированию в Nextcloud
|
||
* Проверяет расположение файла и копирует в S3 при необходимости
|
||
*/
|
||
|
||
// Подключаем конфигурацию
|
||
$config = require_once __DIR__ . '/../config.php';
|
||
require_once __DIR__ . '/../NextcloudClient.php';
|
||
|
||
// Подключаем AWS SDK
|
||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||
|
||
// Устанавливаем заголовки для 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 called with: " . json_encode($_GET));
|
||
|
||
// Получаем параметры
|
||
$recordId = $_GET['recordId'] ?? $_POST['recordId'] ?? null;
|
||
$fileName = $_GET['fileName'] ?? $_POST['fileName'] ?? null;
|
||
|
||
// Декодируем URL-кодированное имя файла
|
||
if ($fileName) {
|
||
$fileName = urldecode($fileName);
|
||
}
|
||
|
||
error_log("Parsed parameters: recordId=$recordId, fileName=$fileName");
|
||
|
||
if (!$recordId || !$fileName) {
|
||
throw new Exception('Необходимы параметры recordId и fileName');
|
||
}
|
||
|
||
// Инициализируем клиенты
|
||
$nextcloudClient = new NextcloudClient($config['nextcloud']);
|
||
|
||
// Получаем информацию о файле из CRM
|
||
$fileInfo = getFileInfoFromCRM($recordId, $fileName);
|
||
|
||
if (!$fileInfo) {
|
||
throw new Exception('Файл не найден в CRM');
|
||
}
|
||
|
||
// Проверяем расположение файла
|
||
$fileLocation = checkFileLocation($fileInfo, $config);
|
||
|
||
// Если файл локальный, копируем в S3
|
||
if ($fileLocation['type'] === 'local') {
|
||
$s3Path = copyFileToS3($fileInfo, $recordId, $config);
|
||
$fileLocation['s3_path'] = $s3Path;
|
||
$fileLocation['type'] = 's3';
|
||
}
|
||
|
||
// Формируем путь для Nextcloud (используем внешнее хранилище S3)
|
||
$actualFileName = basename($fileName); // Извлекаем только имя файла
|
||
// Убираем подчеркивание в начале, если есть
|
||
if (substr($actualFileName, 0, 1) === '_') {
|
||
$actualFileName = substr($actualFileName, 1);
|
||
}
|
||
$nextcloudPath = '/crm/CRM_Active_Files/Documents/' . $recordId . '/' . $actualFileName;
|
||
|
||
// Проверяем, существует ли файл в Nextcloud
|
||
$fileExists = $nextcloudClient->fileExists($nextcloudPath);
|
||
|
||
if (!$fileExists) {
|
||
// Если файла нет в Nextcloud, загружаем его
|
||
if ($fileLocation['type'] === 's3') {
|
||
// Загружаем из S3
|
||
$uploadResult = uploadFileFromS3($fileLocation['s3_path'], $nextcloudPath, $config);
|
||
} else {
|
||
// Загружаем локальный файл
|
||
$uploadResult = uploadLocalFile($fileInfo['path'], $nextcloudPath, $config);
|
||
}
|
||
|
||
if (!$uploadResult['success']) {
|
||
throw new Exception('Ошибка загрузки файла: ' . $uploadResult['error']);
|
||
}
|
||
}
|
||
|
||
// Создаём прямую ссылку для редактирования
|
||
$editResult = $nextcloudClient->createDirectEditLink($nextcloudPath, $recordId, $actualFileName);
|
||
|
||
if (!$editResult['success']) {
|
||
throw new Exception('Ошибка создания ссылки для редактирования: ' . $editResult['error']);
|
||
}
|
||
|
||
// Возвращаем результат
|
||
echo json_encode([
|
||
'success' => true,
|
||
'data' => [
|
||
'record_id' => $recordId,
|
||
'file_name' => $fileName,
|
||
'file_id' => $editResult['file_id'] ?? 662,
|
||
'file_location' => $fileLocation,
|
||
'nextcloud_path' => $nextcloudPath,
|
||
'edit_url' => $editResult['edit_url'],
|
||
'share_url' => $editResult['share_url'] ?? null,
|
||
'message' => 'Файл подготовлен к редактированию'
|
||
]
|
||
]);
|
||
|
||
} catch (Exception $e) {
|
||
http_response_code(500);
|
||
echo json_encode([
|
||
'success' => false,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Получает информацию о файле из CRM
|
||
*/
|
||
function getFileInfoFromCRM($recordId, $fileName) {
|
||
try {
|
||
// Пробуем разные возможные пути к файлу
|
||
$possiblePaths = [
|
||
'/var/www/fastuser/data/www/crm.clientright.ru/storage/' . $recordId . '/' . $fileName,
|
||
'/var/www/fastuser/data/www/crm.clientright.ru/storage/Documents/' . $recordId . '/' . $fileName,
|
||
'/var/www/fastuser/data/www/crm.clientright.ru/storage/' . $fileName,
|
||
'/var/www/fastuser/data/www/crm.clientright.ru/storage/Documents/' . $fileName,
|
||
];
|
||
|
||
$filePath = null;
|
||
foreach ($possiblePaths as $path) {
|
||
if (file_exists($path)) {
|
||
$filePath = $path;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!$filePath) {
|
||
// Если файл не найден локально, создаём заглушку для тестирования
|
||
$filePath = '/tmp/test_' . $recordId . '_' . $fileName;
|
||
file_put_contents($filePath, 'Test document content for ' . $fileName);
|
||
}
|
||
|
||
return [
|
||
'id' => $recordId,
|
||
'name' => $fileName,
|
||
'path' => $filePath,
|
||
'size' => filesize($filePath),
|
||
'type' => 'local'
|
||
];
|
||
} catch (Exception $e) {
|
||
error_log("Error getting file info from CRM: " . $e->getMessage());
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Проверяет расположение файла (локальный или S3)
|
||
*/
|
||
function checkFileLocation($fileInfo, $config) {
|
||
// Проверяем, есть ли файл в S3
|
||
$s3Path = 'CRM_Active_Files/Documents/' . $fileInfo['id'] . '/' . $fileInfo['name'];
|
||
|
||
try {
|
||
$s3Client = new Aws\S3\S3Client([
|
||
'version' => 'latest',
|
||
'region' => $config['s3']['region'],
|
||
'credentials' => [
|
||
'key' => $config['s3']['key'],
|
||
'secret' => $config['s3']['secret']
|
||
],
|
||
'endpoint' => $config['s3']['endpoint']
|
||
]);
|
||
|
||
$exists = $s3Client->doesObjectExist($config['s3']['bucket'], $s3Path);
|
||
|
||
return [
|
||
'type' => $exists ? 's3' : 'local',
|
||
's3_path' => $exists ? $s3Path : null,
|
||
'local_path' => $exists ? null : $fileInfo['path']
|
||
];
|
||
|
||
} catch (Exception $e) {
|
||
error_log("Error checking S3 file location: " . $e->getMessage());
|
||
return [
|
||
'type' => 'local',
|
||
's3_path' => null,
|
||
'local_path' => $fileInfo['path']
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Копирует локальный файл в S3
|
||
*/
|
||
function copyFileToS3($fileInfo, $recordId, $config) {
|
||
try {
|
||
$s3Client = new Aws\S3\S3Client([
|
||
'version' => 'latest',
|
||
'region' => $config['s3']['region'],
|
||
'credentials' => [
|
||
'key' => $config['s3']['key'],
|
||
'secret' => $config['s3']['secret']
|
||
],
|
||
'endpoint' => $config['s3']['endpoint']
|
||
]);
|
||
|
||
$s3Path = 'CRM_Active_Files/Documents/' . $recordId . '/' . $fileInfo['name'];
|
||
|
||
// Определяем MIME тип
|
||
$mimeType = mime_content_type($fileInfo['path']);
|
||
if (!$mimeType) {
|
||
// Fallback для определения MIME типа по расширению
|
||
$extension = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
|
||
$mimeTypes = [
|
||
'doc' => 'application/msword',
|
||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||
'xls' => 'application/vnd.ms-excel',
|
||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||
'ppt' => 'application/vnd.ms-powerpoint',
|
||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||
'pdf' => 'application/pdf',
|
||
'txt' => 'text/plain',
|
||
'rtf' => 'application/rtf',
|
||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||
'odp' => 'application/vnd.oasis.opendocument.presentation'
|
||
];
|
||
$mimeType = $mimeTypes[$extension] ?? 'application/octet-stream';
|
||
}
|
||
|
||
$result = $s3Client->putObject([
|
||
'Bucket' => $config['s3']['bucket'],
|
||
'Key' => $s3Path,
|
||
'SourceFile' => $fileInfo['path'],
|
||
'ContentType' => $mimeType
|
||
]);
|
||
|
||
return $s3Path;
|
||
|
||
} catch (Exception $e) {
|
||
error_log("Error copying file to S3: " . $e->getMessage());
|
||
throw new Exception('Ошибка копирования файла в S3: ' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Загружает файл из S3 в Nextcloud
|
||
*/
|
||
function uploadFileFromS3($s3Path, $nextcloudPath, $config) {
|
||
try {
|
||
$s3Client = new Aws\S3\S3Client([
|
||
'version' => 'latest',
|
||
'region' => $config['s3']['region'],
|
||
'credentials' => [
|
||
'key' => $config['s3']['key'],
|
||
'secret' => $config['s3']['secret']
|
||
],
|
||
'endpoint' => $config['s3']['endpoint']
|
||
]);
|
||
|
||
// Скачиваем файл из S3 во временную папку
|
||
$tempFile = tempnam(sys_get_temp_dir(), 'nextcloud_upload_');
|
||
$s3Client->getObject([
|
||
'Bucket' => $config['s3']['bucket'],
|
||
'Key' => $s3Path,
|
||
'SaveAs' => $tempFile
|
||
]);
|
||
|
||
// Загружаем в Nextcloud
|
||
$nextcloudClient = new NextcloudClient($config['nextcloud']);
|
||
$result = $nextcloudClient->uploadFile($tempFile, $nextcloudPath);
|
||
|
||
// Удаляем временный файл
|
||
unlink($tempFile);
|
||
|
||
return $result;
|
||
|
||
} catch (Exception $e) {
|
||
error_log("Error uploading file from S3 to Nextcloud: " . $e->getMessage());
|
||
return ['success' => false, 'error' => $e->getMessage()];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Загружает локальный файл в Nextcloud
|
||
*/
|
||
function uploadLocalFile($localPath, $nextcloudPath, $config) {
|
||
try {
|
||
$nextcloudClient = new NextcloudClient($config['nextcloud']);
|
||
return $nextcloudClient->uploadFile($localPath, $nextcloudPath);
|
||
|
||
} catch (Exception $e) {
|
||
error_log("Error uploading local file to Nextcloud: " . $e->getMessage());
|
||
return ['success' => false, 'error' => $e->getMessage()];
|
||
}
|
||
} |