Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ All important changes to this plugin will be documented in this file.

### Fixed
- Fixed a crash when saving LP settings for a worksheet with a deadline, caused by a malformed entry in the MUMIE grade sync response
- The multi-problem selector now uses SSO when the configured problem selector and the selected MUMIE server share the same origin, matching the single-problem selector's behavior

## [v5.0] - 2026-06-02
### Changed
Expand Down
3 changes: 2 additions & 1 deletion classes/class.ilMumieTaskSSOService.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private function getHTMLCode($taskObj, $ssotoken, $hashed_user, $height = 600):
*/
private const LECTURER_SUFFIX = '@lecturer@';

public function getProblemSelectorLaunchForm(string $serverUrl, string $problemLang, string $origin): string
public function getProblemSelectorLaunchForm(string $serverUrl, string $problemLang, string $origin, bool $multiSelect = false): string
{
global $DIC;
$admin_settings = ilMumieTaskAdminSettings::getInstance();
Expand All @@ -159,6 +159,7 @@ public function getProblemSelectorLaunchForm(string $serverUrl, string $problemL
$tpl->setVariable('SERVER_URL', htmlspecialchars($serverUrl));
$tpl->setVariable('PROBLEM_LANG', htmlspecialchars($problemLang));
$tpl->setVariable('ORIGIN', htmlspecialchars($origin));
$tpl->setVariable('MULTI_SELECT', $multiSelect ? 'true' : 'false');

return $tpl->get();
}
Expand Down
23 changes: 23 additions & 0 deletions classes/class.ilObjMumieTaskGUI.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public function launchProblemSelector(): void
(string) ($_GET['serverUrl'] ?? ''),
(string) ($_GET['problemLang'] ?? ''),
(string) ($_GET['origin'] ?? ''),
filter_var($_GET['multiSelect'] ?? false, FILTER_VALIDATE_BOOLEAN),
);
exit;
}
Expand Down Expand Up @@ -257,6 +258,14 @@ public function submitMumieTask()
ilMumieTaskLPStatus::updateGrades($this->object, $force_grade_update);
ilMumieTaskGradeOverrideService::deleteGradeOverridesForTask($this->object);
}

if ($mumieTask->isDummy()) {
// Only multi-select problems were chosen, so this placeholder never became a real task itself.
$this->removeObjectAndRedirectToParent();

return;
}

$tpl->setOnScreenMessage('success', $this->i18N->txt('msg_suc_saved'), true);

$DIC->ctrl()->redirect($this, 'editProperties');
Expand Down Expand Up @@ -459,6 +468,20 @@ public function getStandardCmd(): string
* @throws ilInvalidTreeStructureException
*/
public function cancelDummy(): void
{
$this->removeObjectAndRedirectToParent();
}

/**
* Delete this object and return to the parent container's repository listing.
*
* @throws ilRepositoryException
* @throws ilCtrlException
* @throws ilObjectNotFoundException
* @throws ilDatabaseException
* @throws ilInvalidTreeStructureException
*/
private function removeObjectAndRedirectToParent(): void
{
global $DIC;
$tree = $DIC->repositoryTree();
Expand Down
11 changes: 7 additions & 4 deletions classes/forms/class.ilMumieTaskFormGUI.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,22 @@ public function checkInput(): bool
return $ok;
}

$multi_problems_input = $this->getInput('xmum_multi_problems');

if (null == $task && $is_dummy) {
$ok = false;
$this->problem_display_item->setAlert($this->i18N->globalTxt('required_field'));
if (empty($multi_problems_input)) {
$ok = false;
$this->problem_display_item->setAlert($this->i18N->globalTxt('required_field'));

return $ok;
return $ok;
}
} elseif (null == $task) {
$ok = false;
$this->problem_display_item->setAlert($this->i18N->txt('frm_tsk_problem_not_found'));

return $ok;
}

$multi_problems_input = $this->getInput('xmum_multi_problems');
if (!empty($multi_problems_input) && !ilMumieTaskMultiUploadProcessor::isValid($multi_problems_input)) {
$ok = false;
$this->dropzone_item->setAlert($this->i18N->txt('frm_tsk_problems_not_found'));
Expand Down
2 changes: 1 addition & 1 deletion classes/models/class.ilMumieTaskServerStructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function getCoursebyName($name)
{
foreach ($this->courses as $course) {
foreach ($course->getName() as $translation) {
if ($translation->value == $name) {
if (0 === strcasecmp($translation->value, $name)) {
return $course;
}
}
Expand Down
18 changes: 17 additions & 1 deletion classes/tasks/class.ilMumieTaskMultiUploadProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
class ilMumieTaskMultiUploadProcessor
{
private const MAX_TASKS_PER_UPLOAD = 50;

public static function process(ilObjMumieTask $base_task, string $tasks_json)
{
global $DIC;
Expand All @@ -25,6 +27,10 @@ public static function isValid(string $tasks_json): bool
try {
$task_dtos = self::parseTaskDTOs($tasks_json);

if (0 === count($task_dtos) || count($task_dtos) > self::MAX_TASKS_PER_UPLOAD) {
return false;
}

return !in_array(
false,
array_map(function ($task_dto) {
Expand All @@ -49,14 +55,16 @@ private static function parseTaskDTOs(string $tasks_json): array
private static function generateMumieTask(ilMumieTaskTaskDTO $task_dto, ilObjMumieTask $base_task)
{
$new_task = self::generateEmptyMumieTask($base_task->getParentRef(), $base_task->getType());
$server = ilMumieTaskServer::fromUrl($task_dto->getServer());

$new_task->setTitle($task_dto->getName());
$new_task->setServer($task_dto->getServer());
$new_task->setServer($server->getUrlPrefix());
$new_task->setMumieCourse($task_dto->getCourse());
$new_task->setTaskurl($task_dto->getLink());
$new_task->setLanguage($task_dto->getLanguage());
$new_task->setLaunchcontainer($base_task->getLaunchcontainer());
$new_task->setMumieCoursefile($task_dto->getPathToCoursefile());
$new_task->setWorksheet($task_dto->getWorksheet());
$new_task->setDeadline($base_task->getDeadline());
$new_task->setTimelimit($base_task->getTimelimit());
$new_task->setOnline($base_task->getOnline());
Expand All @@ -78,9 +86,17 @@ private static function generateEmptyMumieTask($parent_ref, $type): ilObjMumieTa

private static function isValidProblem(ilMumieTaskTaskDTO $task_dto): bool
{
if (str_starts_with($task_dto->getLink(), ilObjMumieTask::WORKSHEET_PREFIX)) {
// Worksheets are not part of the course's regular task structure and can't be looked up there.
return true;
}

$server = ilMumieTaskServer::fromUrl($task_dto->getServer());
$server->buildStructure();
$course = $server->getCoursebyName($task_dto->getCourse());
if (null === $course) {
return false;
}
$task = $course->getTaskByLink($task_dto->getLink());

return !is_null($task);
Expand Down
10 changes: 10 additions & 0 deletions classes/tasks/class.ilMumieTaskTaskDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class ilMumieTaskTaskDTO
* @var string
*/
private $link;
/**
* @var object|null
*/
private $worksheet;

public function __construct(string $task_json)
{
Expand All @@ -49,6 +53,7 @@ public function __construct(string $task_json)
$this->path_to_coursefile = $task->path_to_coursefile;
$this->language = $task->language;
$this->link = $task->link;
$this->worksheet = $task->worksheet ?? null;
}

public function getServer(): string
Expand Down Expand Up @@ -83,4 +88,9 @@ public function getLink()
{
return $this->link;
}

public function getWorksheet(): string
{
return null !== $this->worksheet ? json_encode($this->worksheet) : '';
}
}
9 changes: 8 additions & 1 deletion js/ilMumieTaskDropzone.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
})
dropzone.ondrop = (event) => {
dropzone.classList.remove(DRAG_OVER_CLASS);
const taskJsonString = event.dataTransfer.getData("mumie/jsonArray");
applyTasksJson(event.dataTransfer.getData("mumie/jsonArray"));
}

function applyTasksJson(taskJsonString) {
multiProblemInputElem.setAttribute("value", taskJsonString);
problemListController.setData(taskJsonString);
}
Expand Down Expand Up @@ -62,6 +65,10 @@
}
}
})();

window.ilMumieTaskDropzone = {
setData: applyTasksJson,
};
})
}
)(jQuery)
37 changes: 35 additions & 2 deletions js/ilMumieTaskForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,23 @@
if (event.origin !== lmsSelectorUrl) {
return;
}
const importObj = JSON.parse(event.data);
let importObj;
try {
importObj = JSON.parse(event.data);
} catch (error) {
sendFailure(error.message);
return;
}
if (Array.isArray(importObj)) {
try {
window.ilMumieTaskDropzone.setData(JSON.stringify(importObj.map(task => JSON.stringify(task))));
sendSuccess();
window.focus();
} catch (error) {
sendFailure(error.message);
}
return;
}
const worksheet = importObj.worksheet ?? null;
try {
langController.setLanguage(importObj.language);
Expand Down Expand Up @@ -206,11 +222,28 @@

multiProblemSelectorButton.onclick = function(e) {
e.preventDefault();
const selectedServerUrl = serverController.getSelectedServer().url_prefix;
const problemLang = langController.getSelectedLanguage();
const origin = window.location.origin;

if (shouldUseSSO(selectedServerUrl)) {
problemSelectorWindow = window.open(
problemSelectorSsoUrl
+ '&serverUrl=' + encodeURIComponent(selectedServerUrl)
+ '&problemLang=' + problemLang
+ '&origin=' + encodeURIComponent(origin)
+ '&multiSelect=true'
, '_blank',
'toolbar=0,location=0,menubar=0'
);
return;
}

problemSelectorWindow = window.open(
lmsSelectorUrl
+ '/lms-problem-selector?'
+ "serverUrl="
+ encodeURIComponent(serverController.getSelectedServer().url_prefix),
+ encodeURIComponent(selectedServerUrl),
"_blank",
'toolbar=0,location=0,menubar=0'
);
Expand Down
22 changes: 11 additions & 11 deletions lang/ilias_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ properties#:#Einstellungen
mumie_server#:#MUMIE-Server
mumie_server_desc#:#Bitte wählen sie einen MUMIE-Server um eine aktuelle Liste an verfügbaren Kursen und MumieTasks zu erhalten.
mumie_course#:#MUMIE-Kurs
mumie_select_problem#:#Wählen Sie ein MUMIE-Problem
mumie_problem#:#MUMIE-Problem
mumie_problem_desc#:#Ein MUMIE-Problem ist eine benotete Übung auf der MUMIE-Plattform
frm_tsk_problem_not_found#:#Dieses Problem konnte auf dem ausgewählten Server nicht gefunden werden.
mumie_select_problem#:#Wählen Sie ein MUMIE-Problem oder Worksheet
mumie_problem#:#MUMIE-Problem oder Worksheet
mumie_problem_desc#:#Ein MUMIE-Problem oder Worksheet ist eine benotete Übung auf der MUMIE-Plattform
frm_tsk_problem_not_found#:#Dieses Problem oder Worksheet konnte auf dem ausgewählten Server nicht gefunden werden.
launchcontainer#:#Start-Container
launchcontainer_desc#:#Bitte wählen Sie, ob diese Aktivität in einem neuen Browser-Tab geöffnet oder in die Ilias-Umgebung eingebettet werden soll.
window#:#Neues Fenster
Expand Down Expand Up @@ -121,12 +121,12 @@ btn_remove_grade_override#:#Auswahl zurücksetzen
grade_override_desc#:#Neue Abgaben werden automatisch in ILIAS übernommen, sofern die Abgabefrist noch nicht abgelaufen ist. Um eine andere Abgabe für die Bewertung zu verwenden, können Sie auf die entsprechende Schaltfläche in der Tabelle klicken.<br><br>Eine manuell ausgewählte Bewertung wird auch durch zukünftige Abgaben des Studierenden <b>nicht</b> ersetzt werden.
student_name#:#Name
deadline_extension_desc#:#Hier können Sie Studierenden individuelle Fristverlängerungen gewähren. Falls Sie bereits manuell eine andere Bewertung ausgewählt haben, hat diese Fristverlängerung keine Auswirkung.
frm_multi_problem_header#:#Zusätzliche MUMIE-Probleme erzeugen
form_drag_mt_here#:#Ziehe Sie die MUMIE-Problems hierhinein
multi_create_success#:#Es wurden %s weitere MUMIE-Tasks über Drag&Drop erstellt!
mumie_problems#:#MUMIE-Problems
frm_multi_problem_header#:#Zusätzliche MUMIE-Probleme oder Worksheets erzeugen
form_drag_mt_here#:#Ziehe Sie die MUMIE-Problems oder Worksheets hierhinein
multi_create_success#:#Es wurden %s weitere MUMIE-Tasks erstellt!
mumie_problems#:#MUMIE-Problems / Worksheets
open_dnd_prb_selector#:#Mehrfach-Aufgabenauswahl öffnen
dnd_prb_selector_desc#:#Hier klicken, um die Mehrfach-Aufgabenauswahl zu öffnen. Wählen sie einfach die Aufgaben aus, die Sie importieren möchten, und ziehen sie diese in das untere Feld.
frm_tsk_problems_not_found#:#Ein oder mehrere Problems konnten nicht auf dem Server gefunden werden
dnd_prb_selector_desc#:#Hier klicken, um die Mehrfach-Aufgabenauswahl zu öffnen. Wählen Sie einfach die Aufgaben aus, die Sie importieren möchten.
frm_tsk_problems_not_found#:#Ein oder mehrere der ausgewählten Elemente konnten nicht auf dem Server gefunden werden
dropzone_description#:#Sobald Sie auf <b>Speichern</b> klicken, wird Ilias automatisch MUMIE-Tasks für die ausgewählten Aufgaben erstellen. Dabei werden die Einstellungen für <i>Start-Container</i>, <i>online</i> und <i>Abgabefrist</i> von der derzeit ausgewählten MUMIE-Task übernommen.
multi_problem_list_description#:#Sie haben die folgenden MUMIE-Problems ausgewählt
multi_problem_list_description#:#Sie haben die folgenden MUMIE-Problems und Worksheets ausgewählt
28 changes: 14 additions & 14 deletions lang/ilias_en.lang
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ properties#:#Settings
mumie_server#:#MUMIE server
mumie_server_desc#:#Please select a MUMIE server to get an updated list of available tasks and courses.
mumie_course#:#MUMIE course
mumie_select_problem#:#Select a MUMIE Problem
mumie_problem#:#MUMIE problem
mumie_problem_desc#:#A MUMIE problem is a single graded exercise on MUMIE
frm_tsk_problem_not_found#:#This problem doesn't exist in the selected course
mumie_select_problem#:#Select a MUMIE Problem or Worksheet
mumie_problem#:#MUMIE problem or worksheet
mumie_problem_desc#:#A MUMIE problem or worksheet is a single graded exercise on MUMIE
frm_tsk_problem_not_found#:#This problem or worksheet doesn't exist in the selected course
launchcontainer#:#Launch container
launchcontainer_desc#:#Please select whether the activity should be opened in a new browser tab or embedded into the ILIAS environment
window#:#New window
Expand All @@ -60,7 +60,7 @@ frm_sync_lp#:#Grade synchronization
frm_sync_lp_desc#:#Choose whether to automatically load grades from the MUMIE server into ILIAS for this MUMIE Task
frm_privategradepool#:#Share grades with other courses
frm_privategradepool_desc#:#Choose whether to share grades with other ILIAS repositories.
<br>If sharing is enabled, points that were earned for MUMIE problems in other repositories will be automatically synchronized with this repository\'s gradebook.
<br>If sharing is enabled, points that were earned for MUMIE problems or worksheets in other repositories will be automatically synchronized with this repository\'s gradebook.
<br>If not, this repository will neither be able to import nor to export grades.
frm_privategradepool_decided#:#<b>Note:</b><br> This decision was <b>final</b> and affects all other MUMIE Tasks in this course.
frm_privategradepool_undecided#:#<b style="color:red">Warning:</b><br> This decision is <b>final</b> and affects all other MUMIE Tasks in this course.
Expand All @@ -78,7 +78,7 @@ frm_online_info#:#Make this MUMIE Task visible and usable to all users with read
frm_online_disabled_warning#:#This MUMIE Task cannot be set online because a decision is still pending. Please go to grading settings.
frm_online_disabled_worksheet_warning#:#This worksheet cannot be set online until a deadline or time limit is set. Please go to grading settings.
open_prb_selector#:#Open problem selector
open_prb_selector_desc#:#Click here to open a more detailed selection screen. You can filter all problems by category and enter search terms.
open_prb_selector_desc#:#Click here to open a more detailed selection screen. You can filter all problems and worksheets by category and enter search terms.
frm_list_grade#:#Grade
frm_user_overview_list_grade_desc#:#<br><br>By default the newest submission before the deadline is used. If you want to use a different submission, you can click on the corresponding button to overwrite the current grade.
frm_user_overview_list_change_grade#:#Change Grade
Expand Down Expand Up @@ -121,12 +121,12 @@ btn_remove_grade_override#:#Reset selection
grade_override_desc#:#Grades are automatically updated in ILIAS to the latest submitted answer within the deadline. If you want to use a different submission, you can click on the corresponding button to overwrite the current grade.<br><br>A manually selected grade will not be replaced by new submissions.
student_name#:#Name
deadline_extension_desc#:#Here you can grant a deadline extension to the student. If you have already manually selected a grade for them, this setting will not have any effect.
frm_multi_problem_header#:#Create additional MUMIE Problems
form_drag_mt_here#:#Drag MUMIE Problems here
multi_create_success#:#Successfully created %s additional MUMIE Tasks via drag & drop!
mumie_problems#:#MUMIE Problems
frm_multi_problem_header#:#Create additional MUMIE Problems or Worksheets
form_drag_mt_here#:#Drag MUMIE Problems or Worksheets here
multi_create_success#:#Successfully created %s additional MUMIE Tasks!
mumie_problems#:#MUMIE Problems / Worksheets
open_dnd_prb_selector#:#Open multi problem selector
dnd_prb_selector_desc#:#Clicking here will open the multi problem selection screen. Simply choose the problems you want to import and drag them in the field below.<br><br>
frm_tsk_problems_not_found#:#One or more problems could not be found.
dropzone_description#:#Once you click <b>Save</b>, Ilias will automatically create new MUMIE-Tasks for the selected problems. The settings for <i>Launch container</i>, <i>online</i> and <i>Deadline</i> will be copied from this currently opened MUMIE Task.
multi_problem_list_description#:#You have selected the following MUMIE Problems
dnd_prb_selector_desc#:#Clicking here will open the multi problem selection screen. Simply choose the problems or worksheets you want to import.<br><br>
frm_tsk_problems_not_found#:#One or more of the selected items could not be found.
dropzone_description#:#Once you click <b>Save</b>, Ilias will automatically create new MUMIE-Tasks for the selected problems and worksheets. The settings for <i>Launch container</i>, <i>online</i> and <i>Deadline</i> will be copied from this currently opened MUMIE Task.
multi_problem_list_description#:#You have selected the following MUMIE Problems and Worksheets
6 changes: 2 additions & 4 deletions templates/MumieTasks/tpl.file-drop-zone.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<div>
<div class="ui-input-file-input-dropzone">
<div class="" id="xmum-dropzone">
<i class='glyphicon glyphicon-arrow-down'></i> {TXT_DRAG_PROBLEMS_HERE}
</div>
<div class="ui-input-file-input-dropzone" id="xmum-dropzone" hidden>
<i class='glyphicon glyphicon-arrow-down'></i> {TXT_DRAG_PROBLEMS_HERE}
<input hidden name="{POST_VAR}" id="xmum_multi_problems" />
</div>
<div id="xmum_dropzone_description" hidden>
Expand Down
Loading
Loading