Skip to content

Commit

Permalink
Exercise: Improved OnlyOffice integration and URL handling - refs BT#…
Browse files Browse the repository at this point in the history
…22370
  • Loading branch information
christianbeeznest committed Mar 9, 2025
1 parent 6bc5b60 commit 4d82256
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 37 deletions.
8 changes: 4 additions & 4 deletions main/exercise/AnswerInOfficeDoc.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public function return_header(Exercise $exercise, $counter = null, $score = []):
$header .= '<div class="question-container">';

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 .= "<iframe src='{$documentUrl}' width='800' height='600'></iframe>";
} else {
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 8 additions & 6 deletions main/exercise/exercise.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion main/inc/lib/exercise.lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 '<div class="office-doc-container">';
Expand Down
43 changes: 36 additions & 7 deletions plugin/onlyoffice/callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -69,7 +69,7 @@

switch ($type) {
case 'track':
$callbackResponseArray = track();
$callbackResponseArray = track($type, $docId);
exit(json_encode($callbackResponseArray));
case 'download':
$callbackResponseArray = download();
Expand All @@ -87,7 +87,7 @@
/**
* Handle request from the document server with the document status information.
*/
function track(): array
function track($type, $docId): array
{
$result = [];

Expand Down Expand Up @@ -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);
Expand All @@ -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];
}

/**
Expand Down
67 changes: 53 additions & 14 deletions plugin/onlyoffice/editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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) {
Expand All @@ -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%';
}
Expand Down Expand Up @@ -98,11 +137,11 @@

var onRequestSaveAs = function (event) {
var url = <?php echo json_encode(api_get_path(WEB_PLUGIN_PATH)); ?> + "onlyoffice/ajax/saveas.php";
var folderId = <?php echo json_encode($docInfo['parent_id']); ?>;
var folderId = <?php echo json_encode($docInfo['parent_id'] ?? 0); ?>;
var saveData = {
title: event.data.title,
url: event.data.url,
folderId: folderId ? folderId : 0,
folderId: folderId,
sessionId: <?php echo json_encode($sessionId); ?>,
courseId: <?php echo json_encode($courseId); ?>,
groupId: <?php echo json_encode($groupId); ?>
Expand Down
12 changes: 7 additions & 5 deletions plugin/onlyoffice/lib/onlyofficeDocumentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -76,8 +76,6 @@ public function getGroupId()

public function getCallbackUrl(string $fileId)
{
$url = '';

$data = [
'type' => 'track',
'courseId' => api_get_course_int_id(),
Expand All @@ -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)
Expand Down

0 comments on commit 4d82256

Please sign in to comment.