diff --git a/main/exercise/AnswerInOfficeDoc.php b/main/exercise/AnswerInOfficeDoc.php index 52b42419e32..c4537cb4588 100644 --- a/main/exercise/AnswerInOfficeDoc.php +++ b/main/exercise/AnswerInOfficeDoc.php @@ -128,7 +128,7 @@ public function return_header(Exercise $exercise, $counter = null, $score = []): $header .= '
'; if (!empty($this->extra) && 'true' === OnlyofficePlugin::create()->get('enable_onlyoffice_plugin')) { - $fileUrl = api_get_path(WEB_COURSE_PATH).api_get_course_path() . "/exercises/" . $this->extra; + $fileUrl = api_get_course_path() . "/exercises/" . $this->extra; $documentUrl = OnlyofficeTools::getPathToView($fileUrl); $header .= ""; } else { @@ -183,9 +183,9 @@ public function getFileUrl(bool $loadFromDatabase = false): ?string $this->fileName = basename($this->extra); } - $filePath = api_get_path(SYS_COURSE_PATH) . $this->course['path'] . '/exercises/' . $this->extra; - if (is_file($filePath)) { - return str_replace(api_get_path(SYS_COURSE_PATH), api_get_path(WEB_COURSE_PATH), $filePath); + $filePath = $this->course['path'].'/exercises/'.$this->extra; + if (is_file(api_get_path(SYS_COURSE_PATH).$filePath)) { + return $filePath; } return null; diff --git a/main/exercise/exercise.class.php b/main/exercise/exercise.class.php index d18dc7b6088..ffa7100cd7e 100755 --- a/main/exercise/exercise.class.php +++ b/main/exercise/exercise.class.php @@ -6599,11 +6599,9 @@ function ($answerId) use ($objAnswerTmp) { $exercisePath = api_get_path(SYS_COURSE_PATH) . api_get_course_path() . "/exercises/{$courseId}/{$sessionId}/{$this->iid}/{$quesId}/{$userId}/"; $originalFilePath = $objQuestionTmp->getFileUrl(true); - if (!empty($originalFilePath) && file_exists($originalFilePath)) { - $originalExtension = pathinfo($originalFilePath, PATHINFO_EXTENSION); - } else { - $originalExtension = 'docx'; - } + $originalExtension = !empty($originalFilePath) && file_exists($originalFilePath) + ? pathinfo($originalFilePath, PATHINFO_EXTENSION) + : 'docx'; $fileName = "response_" . uniqid() . "." . $originalExtension; $fullFilePath = $exercisePath . $fileName; @@ -6612,7 +6610,11 @@ function ($answerId) use ($objAnswerTmp) { mkdir($exercisePath, 0775, true); } - if (!empty($_FILES['office_file']['tmp_name'])) { + if (!empty($_POST['onlyoffice_file_url'])) { + $onlyofficeFileUrl = $_POST['onlyoffice_file_url']; + file_put_contents($fullFilePath, file_get_contents($onlyofficeFileUrl)); + } + elseif (!empty($_FILES['office_file']['tmp_name'])) { move_uploaded_file($_FILES['office_file']['tmp_name'], $fullFilePath); } else { if (!empty($originalFilePath) && file_exists($originalFilePath)) { diff --git a/main/inc/lib/exercise.lib.php b/main/inc/lib/exercise.lib.php index cf27fba631f..7d3fd578e65 100644 --- a/main/inc/lib/exercise.lib.php +++ b/main/inc/lib/exercise.lib.php @@ -287,7 +287,7 @@ function setRemoveLink(dataContext) { case ANSWER_IN_OFFICE_DOC: if ('true' === OnlyofficePlugin::create()->get('enable_onlyoffice_plugin')) { if (!empty($objQuestionTmp->extra)) { - $fileUrl = api_get_path(WEB_COURSE_PATH) . api_get_course_path() . "/exercises/" . $objQuestionTmp->extra; + $fileUrl = api_get_course_path() . "/exercises/" . $objQuestionTmp->extra; $documentUrl = OnlyofficeTools::getPathToView($fileUrl); echo '
'; diff --git a/plugin/onlyoffice/callback.php b/plugin/onlyoffice/callback.php index a1c60720be3..47b5d5b44cd 100644 --- a/plugin/onlyoffice/callback.php +++ b/plugin/onlyoffice/callback.php @@ -24,7 +24,7 @@ if (isset($_GET['hash']) && !empty($_GET['hash'])) { $callbackResponseArray = []; - @header('Content-Type: application/json; charset==utf-8'); + @header('Content-Type: application/json; charset=utf-8'); @header('X-Robots-Tag: noindex'); @header('X-Content-Type-Options: nosniff'); @@ -69,7 +69,7 @@ switch ($type) { case 'track': - $callbackResponseArray = track(); + $callbackResponseArray = track($type, $docId); exit(json_encode($callbackResponseArray)); case 'download': $callbackResponseArray = download(); @@ -87,7 +87,7 @@ /** * Handle request from the document server with the document status information. */ -function track(): array +function track($type, $docId): array { $result = []; @@ -138,10 +138,14 @@ function track(): array } } - $data['url'] = isset($payload->url) ? $payload->url : null; + $data['url'] = $payload->url ?? null; $data['status'] = $payload->status; } + if (!isset($data['url']) || empty($data['url']) || !in_array($data['status'], [2, 3])) { + return ['status' => 'no_changes']; + } + $docStatus = new CallbackDocStatus($data['status']); $callback = new OnlyofficeCallback(); $callback->setStatus($docStatus); @@ -157,10 +161,35 @@ function track(): array 'groupId' => $groupId, 'sessionId' => $sessionId, 'courseInfo' => $courseInfo, - ]); - $result = $callbackService->processCallback($callback, $docId); + ] + ); + + if ($type === 'exercise') { + return saveExerciseFile($docId, $data['url']); + } + + return $callbackService->processCallback($callback, $docId); +} + +/** + * Save exercise file + */ +function saveExerciseFile($docId, $fileUrl): array +{ + global $courseInfo, $sessionId, $userId; + + $exercisePath = api_get_path(SYS_COURSE_PATH) . api_get_course_path() . "/exercises/{$courseInfo['real_id']}/{$sessionId}/{$docId}/{$userId}/"; + + if (!is_dir($exercisePath)) { + mkdir($exercisePath, 0775, true); + } + + $fileName = "response_" . uniqid() . ".docx"; + $fullFilePath = $exercisePath . $fileName; + + file_put_contents($fullFilePath, file_get_contents($fileUrl)); - return $result; + return ['status' => 'saved', 'file' => $fullFilePath]; } /** diff --git a/plugin/onlyoffice/editor.php b/plugin/onlyoffice/editor.php index 5d16ad385bb..43f8b5382e0 100644 --- a/plugin/onlyoffice/editor.php +++ b/plugin/onlyoffice/editor.php @@ -3,7 +3,7 @@ * (c) Copyright Ascensio System SIA 2024. * * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -21,21 +21,19 @@ $isEnable = 'true' === $plugin->get('enable_onlyoffice_plugin'); if (!$isEnable) { exit("Document server isn't enabled"); - - return; } $appSettings = new OnlyofficeAppsettings($plugin); $documentServerUrl = $appSettings->getDocumentServerUrl(); if (empty($documentServerUrl)) { exit("Document server isn't configured"); - - return; } $config = []; $docApiUrl = $appSettings->getDocumentServerApiUrl(); -$docId = (int) $_GET['docId']; +$docId = isset($_GET['docId']) ? (int) $_GET['docId'] : null; +$docPath = isset($_GET['doc']) ? urldecode($_GET['doc']) : null; + $groupId = isset($_GET['groupId']) && !empty($_GET['groupId']) ? (int) $_GET['groupId'] : (!empty($_GET['gidReq']) ? (int) $_GET['gidReq'] : null); $userId = api_get_user_id(); $userInfo = api_get_user_info($userId); @@ -46,7 +44,41 @@ api_not_allowed(true); } $courseCode = $courseInfo['code']; -$docInfo = DocumentManager::get_document_data_by_id($docId, $courseCode, false, $sessionId); +$docInfo = null; +$fileId = null; +$fileUrl = null; + +if ($docPath) { + $filePath = api_get_path(SYS_COURSE_PATH) . $docPath; + if (!file_exists($filePath)) { + error_log("ERROR: Document not found -> " . $filePath); + die("Error: Document not found."); + } + + $fileId = basename($docPath); + + $docInfo = [ + 'path' => $docPath, + 'title' => basename($docPath), + 'size' => filesize($filePath), + 'forceEdit' => isset($_GET['forceEdit']) ? $_GET['forceEdit'] : false, + ]; + + $fileUrl = api_get_path(WEB_COURSE_PATH) . $docPath; +} +elseif ($docId) { + $docInfo = DocumentManager::get_document_data_by_id($docId, $courseCode, false, $sessionId); + if ($docInfo) { + $fileId = $docId; + $fileUrl = (new OnlyofficeDocumentManager($appSettings, $docInfo))->getFileUrl($docId); + } +} + +if (!$docInfo || !$fileId) { + error_log("ERROR: Document not found."); + die("Error: Document not found."); +} + $langInfo = LangManager::getLangUser(); $jwtManager = new OnlyofficeJwtManager($appSettings); if (isset($_GET['forceEdit']) && (bool) $_GET['forceEdit'] === true) { @@ -55,22 +87,29 @@ $documentManager = new OnlyofficeDocumentManager($appSettings, $docInfo); $extension = $documentManager->getExt($documentManager->getDocInfo('title')); $docType = $documentManager->getDocType($extension); -$key = $documentManager->getDocumentKey($docId, $courseCode); -$fileUrl = $documentManager->getFileUrl($docId); +$fileIdentifier = $docId ? (string) $docId : md5($docPath); +$key = $documentManager->getDocumentKey($fileIdentifier, $courseCode); +$fileUrl = $fileUrl ?? $documentManager->getFileUrl($fileIdentifier); -if (!empty($appSettings->getStorageUrl())) { +if (!empty($appSettings->getStorageUrl()) && !empty($fileUrl)) { $fileUrl = str_replace(api_get_path(WEB_PATH), $appSettings->getStorageUrl(), $fileUrl); } $configService = new OnlyofficeConfigService($appSettings, $jwtManager, $documentManager); $editorsMode = $configService->getEditorsMode(); -$config = $configService->createConfig($docId, $editorsMode, $_SERVER['HTTP_USER_AGENT']); +$config = $configService->createConfig($fileIdentifier, $editorsMode, $_SERVER['HTTP_USER_AGENT']); $config = json_decode(json_encode($config), true); + +if (empty($config)) { + error_log("ERROR: Failed to generate the configuration for OnlyOffice"); + die("Error: Failed to generate the configuration for OnlyOffice."); +} + $isMobileAgent = $configService->isMobileAgent($_SERVER['HTTP_USER_AGENT']); $showHeaders = true; $headerHeight = 'calc(100% - 140px)'; -if (!empty($_GET['nh'])) { +if (!empty($_GET['nh']) || !empty($docPath)) { $showHeaders = false; $headerHeight = '100%'; } @@ -98,11 +137,11 @@ var onRequestSaveAs = function (event) { var url = + "onlyoffice/ajax/saveas.php"; - var folderId = ; + var folderId = ; var saveData = { title: event.data.title, url: event.data.url, - folderId: folderId ? folderId : 0, + folderId: folderId, sessionId: , courseId: , groupId: diff --git a/plugin/onlyoffice/lib/onlyofficeDocumentManager.php b/plugin/onlyoffice/lib/onlyofficeDocumentManager.php index a051dc0efc4..3e0024e93c6 100644 --- a/plugin/onlyoffice/lib/onlyofficeDocumentManager.php +++ b/plugin/onlyoffice/lib/onlyofficeDocumentManager.php @@ -59,7 +59,7 @@ public function getFileUrl(string $fileId) ]; if (!empty($this->getGroupId())) { - $data['groupId'] = $groupId; + $data['groupId'] = $this->getGroupId(); } $jwtManager = new OnlyofficeJwtManager($this->settingsManager); $hashUrl = $jwtManager->getHash($data); @@ -76,8 +76,6 @@ public function getGroupId() public function getCallbackUrl(string $fileId) { - $url = ''; - $data = [ 'type' => 'track', 'courseId' => api_get_course_int_id(), @@ -87,13 +85,17 @@ public function getCallbackUrl(string $fileId) ]; if (!empty($this->getGroupId())) { - $data['groupId'] = $groupId; + $data['groupId'] = $this->getGroupId(); + } + + if (isset($this->docInfo['path']) && str_contains($this->docInfo['path'], 'exercises/')) { + $data['typeExercise'] = 'exercise'; } $jwtManager = new OnlyofficeJwtManager($this->settingsManager); $hashUrl = $jwtManager->getHash($data); - return $url.api_get_path(WEB_PLUGIN_PATH).'onlyoffice/callback.php?hash='.$hashUrl; + return api_get_path(WEB_PLUGIN_PATH) . 'onlyoffice/callback.php?hash=' . $hashUrl; } public function getGobackUrl(string $fileId)