*/
- public static function _getInProgress($scorm_item_id, int $a_obj_id, ?array $a_blocked_user_ids = null): array
+ public static function _getInProgress(array|int $scorm_item_id, int $a_obj_id, ?array $a_blocked_user_ids = null): array
{
global $DIC;
$ilDB = $DIC->database();
@@ -622,10 +618,7 @@ public static function checkIfAllowed(int $packageId, int $userId, int $hash): v
array($packageId, $userId, date('Y-m-d H:i:s'))
);
$rowtmp = $ilDB->fetchAssoc($res);
- if ($rowtmp['hash'] == $hash) {
- //ok - do nothing
- // die("allowed");
- } else {
+ if (! ($rowtmp && $rowtmp['hash'] == $hash)) {
//output used by api
die("not allowed");
}
diff --git a/Modules/ScormAicc/classes/SCORM/class.ilSCORMExplorer.php b/Modules/ScormAicc/classes/SCORM/class.ilSCORMExplorer.php
index fea0d832a77d..08e1e4d1be3a 100755
--- a/Modules/ScormAicc/classes/SCORM/class.ilSCORMExplorer.php
+++ b/Modules/ScormAicc/classes/SCORM/class.ilSCORMExplorer.php
@@ -92,9 +92,8 @@ public function setOutput($a_parent_id, int $a_depth = 1, int $a_obj_id = 0, $a_
}
/**
- * recursive creating of outputs
- * @return mixed[]
- */
+ * recursive creating of outputs
+ */
protected function createOutputArray(int $a_parent_id, array $options = array()): array
{
global $ilErr;
diff --git a/Modules/ScormAicc/classes/SCORM/class.ilSCORMObject.php b/Modules/ScormAicc/classes/SCORM/class.ilSCORMObject.php
index 2f45ee952d48..9894261653dd 100755
--- a/Modules/ScormAicc/classes/SCORM/class.ilSCORMObject.php
+++ b/Modules/ScormAicc/classes/SCORM/class.ilSCORMObject.php
@@ -180,10 +180,7 @@ public function delete(): void
);
}
- /**
- * @return ilSCORMItem|ilSCORMManifest|ilSCORMOrganization|ilSCORMOrganizations|ilSCORMResource|ilSCORMResources
- */
- public static function &_getInstance(int $a_id, int $a_slm_id)
+ public static function &_getInstance(int $a_id, int $a_slm_id): ilSCORMItem|ilSCORMManifest|ilSCORMOrganization|ilSCORMOrganizations|ilSCORMResource|ilSCORMResources
{
global $DIC;
$ilDB = $DIC->database();
diff --git a/Modules/ScormAicc/classes/SCORM/class.ilSCORMObjectGUI.php b/Modules/ScormAicc/classes/SCORM/class.ilSCORMObjectGUI.php
index 4c48fde53807..85f952c7b593 100755
--- a/Modules/ScormAicc/classes/SCORM/class.ilSCORMObjectGUI.php
+++ b/Modules/ScormAicc/classes/SCORM/class.ilSCORMObjectGUI.php
@@ -27,10 +27,7 @@
*/
class ilSCORMObjectGUI
{
- /**
- * @var ilSCORMManifest|ilSCORMItem|ilSCORMOrganization|ilSCORMOrganizations
- */
- public $sc_object;
+ public ilSCORMManifest|ilSCORMItem|ilSCORMOrganization|ilSCORMOrganizations $sc_object;
public ilGlobalTemplate $tpl;
public ilLanguage $lng;
@@ -47,10 +44,7 @@ public function __construct(int $a_id = 0)
$this->lng = $lng;
}
- /**
- * @return ilSCORMItemGUI|ilSCORMManifestGUI|ilSCORMOrganizationGUI|ilSCORMOrganizationsGUI|ilSCORMResourceGUI|ilSCORMResourcesGUI
- */
- public function &getInstance(int $a_id)
+ public function &getInstance(int $a_id): ilSCORMItemGUI|ilSCORMManifestGUI|ilSCORMOrganizationGUI|ilSCORMOrganizationsGUI|ilSCORMResourceGUI|ilSCORMResourcesGUI
{
$object = new ilSCORMObject($a_id);
switch ($object->getType()) {
diff --git a/Modules/ScormAicc/classes/SCORM/class.ilSCORMPackageParser.php b/Modules/ScormAicc/classes/SCORM/class.ilSCORMPackageParser.php
index c6ef01a35f7b..203772ddbc47 100755
--- a/Modules/ScormAicc/classes/SCORM/class.ilSCORMPackageParser.php
+++ b/Modules/ScormAicc/classes/SCORM/class.ilSCORMPackageParser.php
@@ -165,15 +165,19 @@ public function getCurrentParent(): int
* @param array $a_attribs
* @return void
*/
- public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
+ public function handlerBeginTag(XMLParser $a_xml_parser, string $a_name, array $a_attribs): void
{
//echo "
handlerBeginTag:".$a_name;
switch ($a_name) {
case "manifest":
+ $mVersion = "";
+ if (isset($a_attribs["version"])) {
+ $mVersion = $a_attribs["version"];
+ }
$manifest = new ilSCORMManifest();
$manifest->setSLMId($this->slm_object->getId());
$manifest->setImportId($a_attribs["identifier"]);
- $manifest->setVersion($a_attribs["version"]);
+ $manifest->setVersion($mVersion);
if (isset($a_attribs["xml:base"])) {
$manifest->setXmlBase($a_attribs["xml:base"]);
}
@@ -274,6 +278,7 @@ public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs)
$dependency->setIdentifierRef($a_attribs["identifierref"]);
$this->current_resource->addDependency($dependency);
break;
+
}
$this->beginElement($a_name);
}
@@ -284,7 +289,7 @@ public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs)
* @param string $a_name
* @return void
*/
- public function handlerEndTag($a_xml_parser, string $a_name): void
+ public function handlerEndTag(XMLParser $a_xml_parser, string $a_name): void
{
//echo "
handlerEndTag:".$a_name;
@@ -310,6 +315,7 @@ public function handlerEndTag($a_xml_parser, string $a_name): void
$this->current_resource->update();
array_pop($this->parent_stack);
break;
+
}
$this->endElement($a_name);
}
@@ -320,7 +326,7 @@ public function handlerEndTag($a_xml_parser, string $a_name): void
* @param string|null $a_data
* @return void
*/
- public function handlerCharacterData($a_xml_parser, ?string $a_data): void
+ public function handlerCharacterData(XMLParser $a_xml_parser, ?string $a_data): void
{
//echo "
handlerCharacterData:".$this->getCurrentElement().":".$a_data;
// DELETE WHITESPACES AND NEWLINES OF CHARACTER DATA
@@ -364,6 +370,7 @@ public function handlerCharacterData($a_xml_parser, ?string $a_data): void
case "adlcp:masteryscore":
$this->item_stack[count($this->item_stack) - 1]->setMasteryScore($a_data);
break;
+
}
}
}
diff --git a/Modules/ScormAicc/classes/SCORM/class.ilSCORMPresentationGUI.php b/Modules/ScormAicc/classes/SCORM/class.ilSCORMPresentationGUI.php
index d8a56ba6d794..a210963317cb 100755
--- a/Modules/ScormAicc/classes/SCORM/class.ilSCORMPresentationGUI.php
+++ b/Modules/ScormAicc/classes/SCORM/class.ilSCORMPresentationGUI.php
@@ -510,10 +510,8 @@ public function downloadCertificate(): void
$certificateLogger = $DIC->logger()->root();
$ilUserCertificateRepository = new ilUserCertificateRepository();
- $pdfGenerator = new ilPdfGenerator($ilUserCertificateRepository, $certificateLogger);
-
+ $pdfGenerator = new ilPdfGenerator($ilUserCertificateRepository);
$pdfAction = new ilCertificatePdfAction(
- $certificateLogger,
$pdfGenerator,
new ilCertificateUtilHelper(),
$this->lng->txt('error_creating_certificate_pdf')
diff --git a/Modules/ScormAicc/classes/SCORM/class.ilSCORMResource.php b/Modules/ScormAicc/classes/SCORM/class.ilSCORMResource.php
index 0a9fc6663024..ccc5e2a5951d 100755
--- a/Modules/ScormAicc/classes/SCORM/class.ilSCORMResource.php
+++ b/Modules/ScormAicc/classes/SCORM/class.ilSCORMResource.php
@@ -102,9 +102,6 @@ public function addFile(ilSCORMResourceFile $a_file_obj): void
$this->files[] = &$a_file_obj;
}
- /**
- * @return mixed[]
- */
public function &getFiles(): array
{
return $this->files;
@@ -115,9 +112,6 @@ public function addDependency(ilSCORMResourceDependency $a_dependency): void
$this->dependencies[] = &$a_dependency;
}
- /**
- * @return mixed[]
- */
public function &getDependencies(): array
{
return $this->dependencies;
diff --git a/Modules/ScormAicc/classes/Verification/class.ilObjSCORMVerificationGUI.php b/Modules/ScormAicc/classes/Verification/class.ilObjSCORMVerificationGUI.php
index 6b1153ce153a..3a223008db77 100644
--- a/Modules/ScormAicc/classes/Verification/class.ilObjSCORMVerificationGUI.php
+++ b/Modules/ScormAicc/classes/Verification/class.ilObjSCORMVerificationGUI.php
@@ -172,11 +172,7 @@ public static function _goto(string $a_target): void
$DIC->ctrl->redirectByClass(ilSharedResourceGUI::class);
}
- /**
- * @param mixed $default
- * @return mixed
- */
- protected function getRequestValue(string $key, $default = null)
+ protected function getRequestValue(string $key, mixed $default = null): mixed
{
if (isset($this->request->getQueryParams()[$key])) {
return $this->request->getQueryParams()[$key];
diff --git a/Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php b/Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php
index 12b2241bdd9f..62c946d54f4a 100755
--- a/Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php
+++ b/Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php
@@ -70,13 +70,17 @@ class ilObjSAHSLearningModule extends ilObject
protected string $api_adapter = 'API';
+ protected \ILIAS\DI\UIServices $ui;
+
/**
* Constructor
- * @param integer reference_id or object_id
- * @param boolean treat the id as reference_id (true) or object_id (false)
+ * @param integer $a_id reference_id or object_id
+ * @param boolean $a_call_by_reference treat the id as reference_id (true) or object_id (false)
*/
public function __construct(int $a_id = 0, bool $a_call_by_reference = true)
{
+ global $DIC;
+ $this->ui = $DIC->ui();
$this->type = "sahs";
parent::__construct($a_id, $a_call_by_reference);
}
@@ -1350,7 +1354,7 @@ public function getApiStudentName(): string
/**
* get button for view
*/
- public function getViewButton(): ilLinkButton
+ public function getViewButton(): \ILIAS\UI\Component\Button\Primary
{
$setUrl = "ilias.php?baseClass=ilSAHSPresentationGUI&ref_id=" . $this->getRefID();
// $setUrl = $this->getLinkTargetByClass("ilsahspresentationgui", "")."&ref_id=".$this->getRefID();
@@ -1365,11 +1369,17 @@ public function getViewButton(): ilLinkButton
$setUrl = "javascript:void(0); onclick=startSAHS('" . $setUrl . "','ilContObj" . $this->getId() . "'," . $om . "," . $width . "," . $height . ");";
$setTarget = "";
}
- $button = ilLinkButton::getInstance();
- $button->setCaption("view");
- $button->setPrimary(true);
- $button->setUrl($setUrl);
- $button->setTarget($setTarget);
+ //todo $setTarget ?
+ $button = $this->ui->factory()->button()->primary(
+ $this->lng->txt("view"),
+ $setUrl
+ );
+
+ // $button = ilLinkButton::getInstance();
+ // $button->setCaption("view");
+ // $button->setPrimary(true);
+ // $button->setUrl($setUrl);
+ // $button->setTarget($setTarget);
return $button;
}
}
diff --git a/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleAccess.php b/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleAccess.php
index d2ec0597fc70..a3844509b21a 100644
--- a/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleAccess.php
+++ b/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleAccess.php
@@ -100,7 +100,7 @@ public static function _checkGoto(string $target): bool
/**
* Returns the number of bytes used on the harddisk by the learning module
* with the specified object id.
- * @param int object id of a file object.
+ * @param int $a_id object id of a file object.
*/
public static function _lookupDiskUsage(int $a_id): int
{
diff --git a/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleGUI.php b/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleGUI.php
index a44fe1e83684..11e5b5355d9b 100755
--- a/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleGUI.php
+++ b/Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleGUI.php
@@ -184,7 +184,7 @@ protected function infoScreen(): void
protected function infoScreenForward(): void
{
if (!$this->checkPermissionBool("visible") && !$this->checkPermissionBool("read")) {
- $this->error->raiseError($this->lng->txt("msg_no_perm_read"));
+ $this->error->raiseError($this->lng->txt("msg_no_perm_read"), $this->error->MESSAGE);
}
$info = new ilInfoScreenGUI($this);
@@ -866,10 +866,9 @@ public function setSettingsSubTabs(): void
}
/**
- * @return mixed
* @throws ilCtrlException
*/
- public function export()
+ public function export(): mixed
{
$GLOBALS['DIC']->tabs()->setTabActive('export');
$exp_gui = new ilExportGUI($this);
diff --git a/Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php b/Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php
index ca3f5b5e2a0d..08ccaaac4cfa 100755
--- a/Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php
+++ b/Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php
@@ -30,8 +30,8 @@ class ilObjSCORMLearningModule extends ilObjSAHSLearningModule
{
/**
* Constructor
- * @param integer reference_id or object_id
- * @param boolean treat the id as reference_id (true) or object_id (false)
+ * @param integer $a_id reference_id or object_id
+ * @param boolean $a_call_by_reference treat the id as reference_id (true) or object_id (false)
*/
public function __construct(int $a_id = 0, bool $a_call_by_reference = true)
{
diff --git a/Modules/ScormAicc/classes/class.ilObjSCORMLearningModuleGUI.php b/Modules/ScormAicc/classes/class.ilObjSCORMLearningModuleGUI.php
index 25491b70602a..5f05bbc296bc 100755
--- a/Modules/ScormAicc/classes/class.ilObjSCORMLearningModuleGUI.php
+++ b/Modules/ScormAicc/classes/class.ilObjSCORMLearningModuleGUI.php
@@ -341,7 +341,7 @@ public function getPropertiesFormValues(): void
{
$values = array();
$values["Fobject_title"] = $this->object->getTitle();
- $values["Fobject_description"] = $this->object->getDescription();
+ $values["Fobject_description"] = $this->object->getLongDescription();
if (!$this->object->getOfflineStatus()) {
$values["cobj_online"] = true;
}
@@ -531,6 +531,7 @@ public function newModuleVersionUpload(): void
//do testing for converted versions as well as earlier ILIAS version messed up utf8 conversion
if (strcmp($new_manifest, $old_manifest) == 0 || strcmp(utf8_encode($new_manifest), $old_manifest) == 0 ||
strcmp($reload_manifest, $old_manifest) == 0 || strcmp(utf8_encode($reload_manifest), $old_manifest) == 0) {
+
//get exisiting module version
$module_version = $this->object->getModuleVersion() + 1;
diff --git a/Modules/ScormAicc/classes/class.ilSCORMTrackingItems.php b/Modules/ScormAicc/classes/class.ilSCORMTrackingItems.php
index 6a5c411d5822..e34d92372ff4 100644
--- a/Modules/ScormAicc/classes/class.ilSCORMTrackingItems.php
+++ b/Modules/ScormAicc/classes/class.ilSCORMTrackingItems.php
@@ -240,9 +240,6 @@ public function scoTitlesForExportSelected(int $obj_id): array
return $scoTitles;
}
- /**
- * @return mixed[]
- */
public function markedLearningStatusForExportSelected(array $a_scos, int $obj_id): array
{
global $DIC;
@@ -378,9 +375,6 @@ public function exportSelectedCore(
return $returnData;
}
- /**
- * @return mixed[]
- */
public function getScormTrackingValue(int $obj_id, array $a_user, array $a_sco, array $a_empty, string $lvalue): array
{
global $DIC;
@@ -926,10 +920,7 @@ public function exportSelectedSuccessRows(
return $returnData;
}
- /**
- * @return float|string
- */
- public function SCORMTimeToSeconds(string $a_time)
+ public function SCORMTimeToSeconds(string $a_time): float|string
{
if ($a_time == "") {
return "";
diff --git a/Modules/ScormAicc/classes/class.ilSCORMTrackingItemsTableGUI.php b/Modules/ScormAicc/classes/class.ilSCORMTrackingItemsTableGUI.php
index f77f14a8f219..53bd532a6dda 100644
--- a/Modules/ScormAicc/classes/class.ilSCORMTrackingItemsTableGUI.php
+++ b/Modules/ScormAicc/classes/class.ilSCORMTrackingItemsTableGUI.php
@@ -36,8 +36,6 @@ class ilSCORMTrackingItemsTableGUI extends ilTable2GUI
/**
* @throws ilCtrlException
- * @param mixed[] $a_userSelected
- * @param mixed[] $a_scosSelected
*/
public function __construct(int $a_obj_id, ?object $a_parent_obj, string $a_parent_cmd, array $a_userSelected, array $a_scosSelected, string $a_report)
{
@@ -199,11 +197,7 @@ public function getItems(): void
$this->setData($tr_data);
}
- /**
- * @param string|float|int|null $value
- * @return string|float|int|null
- */
- protected function parseValue(string $id, $value, string $type)
+ protected function parseValue(string $id, string|float|int|null $value, string $type): string|float|int|null
{
global $DIC;
$lng = $DIC->language();
diff --git a/Modules/ScormAicc/classes/class.ilScormAiccDataSet.php b/Modules/ScormAicc/classes/class.ilScormAiccDataSet.php
index 98ec59bbea53..42dd8cafa2df 100755
--- a/Modules/ScormAicc/classes/class.ilScormAiccDataSet.php
+++ b/Modules/ScormAicc/classes/class.ilScormAiccDataSet.php
@@ -76,9 +76,6 @@ public function __construct()
}
}
- /**
- * @return mixed[]
- */
protected function getDependencies(
string $a_entity,
string $a_version,
diff --git a/Modules/ScormAicc/module.xml b/Modules/ScormAicc/module.xml
index cc42170a9ee8..2d8bf3459eac 100644
--- a/Modules/ScormAicc/module.xml
+++ b/Modules/ScormAicc/module.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/Modules/StudyProgramme/classes/ilStudyProgrammeUserTableRow.php b/Modules/StudyProgramme/classes/ilStudyProgrammeUserTableRow.php
index 023b0665ac59..8524b1a5bd74 100644
--- a/Modules/StudyProgramme/classes/ilStudyProgrammeUserTableRow.php
+++ b/Modules/StudyProgramme/classes/ilStudyProgrammeUserTableRow.php
@@ -26,7 +26,7 @@ class ilStudyProgrammeUserTableRow
protected PRGProgressId $id;
protected int $ass_id;
protected int $usr_id;
- protected int $pgs_id;
+ protected int $node_id;
protected bool $is_root_progress;
protected int $status_raw;
protected bool $active_raw;
diff --git a/Modules/Test/classes/MainSettings/class.ilObjTestSettingsMainGUI.php b/Modules/Test/classes/MainSettings/class.ilObjTestSettingsMainGUI.php
index 853f25fe9861..a72035e52c10 100644
--- a/Modules/Test/classes/MainSettings/class.ilObjTestSettingsMainGUI.php
+++ b/Modules/Test/classes/MainSettings/class.ilObjTestSettingsMainGUI.php
@@ -649,8 +649,9 @@ private function getParticipantsFunctionalitySettingsForStorage(array $section):
->withUsePreviousAnswerAllowed($section['use_previous_answers'])
->withSuspendTestAllowed($section['allow_suspend_test'])
->withPostponedQuestionsMoveToEnd($section['postponed_questions_behaviour'])
- ->withQuestionListMode($section['enable_question_list'])
- ->withQuestionMarkingEnabled($section['enable_question_marking']);
+ ->withUsrPassOverviewMode($section['usr_pass_overview'])
+ ->withQuestionMarkingEnabled($section['enable_question_marking'])
+ ->withQuestionListEnabled($section['enable_question_list']);
}
private function getFinishingSettingsForStorage(array $section): ilObjTestSettingsFinishing
diff --git a/Modules/Test/classes/MainSettings/ilObjTestMainSettingsDatabaseRepository.php b/Modules/Test/classes/MainSettings/ilObjTestMainSettingsDatabaseRepository.php
index 3459c54c5388..4b21ab705d1d 100644
--- a/Modules/Test/classes/MainSettings/ilObjTestMainSettingsDatabaseRepository.php
+++ b/Modules/Test/classes/MainSettings/ilObjTestMainSettingsDatabaseRepository.php
@@ -84,8 +84,9 @@ protected function doSelect(string $where_part): ilObjTestMainSettings
. 'use_previous_answers,' . PHP_EOL
. 'show_cancel,' . PHP_EOL
. 'sequence_settings,' . PHP_EOL
- . 'show_summary,' . PHP_EOL
+ . 'usr_pass_overview_mode,' . PHP_EOL
. 'show_marker,' . PHP_EOL
+ . 'show_questionlist,' . PHP_EOL
. 'enable_examview,' . PHP_EOL
. 'showfinalstatement,' . PHP_EOL
. 'finalstatement,' . PHP_EOL
@@ -167,8 +168,9 @@ protected function doSelect(string $where_part): ilObjTestMainSettings
(bool) $row['use_previous_answers'],
(bool) $row['show_cancel'],
(bool) $row['sequence_settings'],
- $row['show_summary'],
- (bool) $row['show_marker']
+ $row['usr_pass_overview_mode'],
+ (bool) $row['show_marker'],
+ (bool) $row['show_questionlist']
),
new ilObjTestSettingsFinishing(
$test_id,
diff --git a/Modules/Test/classes/MainSettings/ilObjTestSettingsParticipantFunctionality.php b/Modules/Test/classes/MainSettings/ilObjTestSettingsParticipantFunctionality.php
index cbe308710d3e..460d6c1fd7d0 100644
--- a/Modules/Test/classes/MainSettings/ilObjTestSettingsParticipantFunctionality.php
+++ b/Modules/Test/classes/MainSettings/ilObjTestSettingsParticipantFunctionality.php
@@ -30,8 +30,9 @@ public function __construct(
protected bool $use_previous_answers_allowed = false,
protected bool $suspend_test_allowed = false,
protected bool $postponed_questions_move_to_end = false,
- protected int $question_list_mode = 0,
- protected bool $question_marking_enabled = false
+ protected int $usrpass_overview_mode = 0,
+ protected bool $question_marking_enabled = false,
+ protected bool $question_list_enabled = false
) {
parent::__construct($test_id);
}
@@ -69,7 +70,12 @@ public function toForm(
)->withValue($this->getPostponedQuestionsMoveToEnd() ? '1' : '0')
->withAdditionalTransformation($refinery->kindlyTo()->bool());
- $inputs['enable_question_list'] = $this->getInputEnableQuestionList(
+ $inputs['enable_question_list'] = $f->checkbox(
+ $lng->txt('tst_enable_questionlist'),
+ $lng->txt('tst_enable_questionlist_description')
+ )->withValue($this->getQuestionListEnabled());
+
+ $inputs['usr_pass_overview'] = $this->getInputUsrPassOverview(
$lng,
$f,
$refinery
@@ -83,7 +89,7 @@ public function toForm(
return $f->section($inputs, $lng->txt('tst_sequence_properties'));
}
- private function getInputEnableQuestionList(
+ private function getInputUsrPassOverview(
\ilLanguage $lng,
FieldFactory $f,
Refinery $refinery
@@ -94,46 +100,46 @@ static function (?array $vs): int {
return 0;
}
- $question_list_mode = 1;
+ $usrpass_overview_mode = 1;
if ($vs['show_at_beginning'] === true) {
- $question_list_mode += 2;
+ $usrpass_overview_mode += 2;
}
if ($vs['show_at_end'] === true) {
- $question_list_mode += 4;
+ $usrpass_overview_mode += 4;
}
if ($vs['show_description'] === true) {
- $question_list_mode += 8;
+ $usrpass_overview_mode += 8;
}
- return $question_list_mode;
+ return $usrpass_overview_mode;
}
);
- $sub_inputs_question_list['show_at_beginning'] = $f->checkbox(
+ $sub_inputs_usrpass_questionlist['show_at_beginning'] = $f->checkbox(
$lng->txt('tst_list_of_questions_start')
);
- $sub_inputs_question_list['show_at_end'] = $f->checkbox(
+ $sub_inputs_usrpass_questionlist['show_at_end'] = $f->checkbox(
$lng->txt('tst_list_of_questions_end')
);
- $sub_inputs_question_list['show_description'] = $f->checkbox(
+ $sub_inputs_usrpass_questionlist['show_description'] = $f->checkbox(
$lng->txt('tst_list_of_questions_with_description')
);
- $enable_question_list = $f->optionalGroup(
- $sub_inputs_question_list,
+ $enable_usrpass_questionlist = $f->optionalGroup(
+ $sub_inputs_usrpass_questionlist,
$lng->txt('tst_show_summary'),
$lng->txt('tst_show_summary_description')
)->withValue(null)
->withAdditionalTransformation($trafo);
- if ($this->getQuestionListEnabled() === false) {
- return $enable_question_list;
+ if ($this->getUsrPassOverviewEnabled() === false) {
+ return $enable_usrpass_questionlist;
}
- return $enable_question_list->withValue(
+ return $enable_usrpass_questionlist->withValue(
[
'show_at_beginning' => $this->getShownQuestionListAtBeginning(),
'show_at_end' => $this->getShownQuestionListAtEnd(),
@@ -148,8 +154,9 @@ public function toStorage(): array
'use_previous_answers' => ['integer', (int) $this->getUsePreviousAnswerAllowed()],
'show_cancel' => ['integer', (int) $this->getSuspendTestAllowed()],
'sequence_settings' => ['integer', (int) $this->getPostponedQuestionsMoveToEnd()],
- 'show_summary' => ['integer', $this->getQuestionListMode()],
- 'show_marker' => ['integer', (int) $this->getQuestionMarkingEnabled()]
+ 'usr_pass_overview_mode' => ['integer', $this->getUsrPassOverviewMode()],
+ 'show_marker' => ['integer', (int) $this->getQuestionMarkingEnabled()],
+ 'show_questionlist' => ['integer', $this->getQuestionListEnabled()]
];
}
@@ -186,13 +193,24 @@ public function withPostponedQuestionsMoveToEnd(bool $postponed_questions_move_t
return $clone;
}
- public function getQuestionListMode(): int
+ public function getQuestionListEnabled(): bool
{
- return $this->question_list_mode;
+ return $this->question_list_enabled;
}
- public function getQuestionListEnabled(): bool
+ public function withQuestionListEnabled(bool $question_list_enabled): self
+ {
+ $clone = clone $this;
+ $clone->question_list_enabled = $question_list_enabled;
+ return $clone;
+ }
+
+ public function getUsrPassOverviewMode(): int
+ {
+ return $this->usrpass_overview_mode;
+ }
+ public function getUsrPassOverviewEnabled(): bool
{
- if (($this->question_list_mode & 1) > 0) {
+ if (($this->usrpass_overview_mode & 1) > 0) {
return true;
}
@@ -200,7 +218,7 @@ public function getQuestionListEnabled(): bool
}
public function getShownQuestionListAtBeginning(): bool
{
- if (($this->question_list_mode & 2) > 0) {
+ if (($this->usrpass_overview_mode & 2) > 0) {
return true;
}
@@ -208,7 +226,7 @@ public function getShownQuestionListAtBeginning(): bool
}
public function getShownQuestionListAtEnd(): bool
{
- if (($this->question_list_mode & 4) > 0) {
+ if (($this->usrpass_overview_mode & 4) > 0) {
return true;
}
@@ -216,16 +234,16 @@ public function getShownQuestionListAtEnd(): bool
}
public function getShowDescriptionInQuestionList(): bool
{
- if (($this->question_list_mode & 8) > 0) {
+ if (($this->usrpass_overview_mode & 8) > 0) {
return true;
}
return false;
}
- public function withQuestionListMode(int $question_list_mode): self
+ public function withUsrPassOverviewMode(int $usrpass_overview_mode): self
{
$clone = clone $this;
- $clone->question_list_mode = $question_list_mode;
+ $clone->usrpass_overview_mode = $usrpass_overview_mode;
return $clone;
}
diff --git a/Modules/Test/classes/Results/class.ilQuestionResult.php b/Modules/Test/classes/Results/class.ilQuestionResult.php
new file mode 100644
index 000000000000..1de0a45ad2ad
--- /dev/null
+++ b/Modules/Test/classes/Results/class.ilQuestionResult.php
@@ -0,0 +1,104 @@
+id;
+ }
+ public function getType(): string
+ {
+ return $this->type;
+ }
+ public function getTitle(): string
+ {
+ return $this->title;
+ }
+ public function getUserAnswer(): string
+ {
+ return $this->usr_solution;
+ }
+ public function getBestSolution(): string
+ {
+ return $this->best_solution;
+ }
+ public function getQuestionScore(): float
+ {
+ return $this->question_score;
+ }
+ public function getUserScore(): float
+ {
+ return $this->usr_score;
+ }
+ public function getUserScorePercent(): float
+ {
+ return 100 / $this->getQuestionScore() * $this->getUserScore();
+ }
+ public function getCorrect(): int
+ {
+ if ($this->getUserScore() === 0.0) {
+ return self::CORRECT_NONE;
+ }
+ if ($this->getUserScore() === $this->getQuestionScore()) {
+ return self::CORRECT_FULL;
+ }
+ return self::CORRECT_PARTIAL;
+ }
+ public function getFeedback(): string
+ {
+ return $this->feedback;
+ }
+ public function isWorkedThrough(): bool
+ {
+ return $this->workedthrough;
+ }
+ public function isAnswered(): bool
+ {
+ return $this->answered;
+ }
+ public function getContentForRecapitulation(): ?string
+ {
+ return $this->content_for_recapitulation;
+ }
+}
diff --git a/Modules/Test/classes/Results/class.ilTestPassResult.php b/Modules/Test/classes/Results/class.ilTestPassResult.php
new file mode 100644
index 000000000000..8183a25d9168
--- /dev/null
+++ b/Modules/Test/classes/Results/class.ilTestPassResult.php
@@ -0,0 +1,60 @@
+settings;
+ }
+
+ public function getActiveId(): int
+ {
+ return $this->active_id;
+ }
+
+ public function getPass(): int
+ {
+ return $this->pass_id;
+ }
+
+ /**
+ * @return ilQuestionResult[];
+ */
+ public function getQuestionResults(): array
+ {
+ return $this->question_results;
+ }
+}
diff --git a/Modules/Test/classes/Results/class.ilTestPassResultsSettings.php b/Modules/Test/classes/Results/class.ilTestPassResultsSettings.php
new file mode 100644
index 000000000000..ee38a967a432
--- /dev/null
+++ b/Modules/Test/classes/Results/class.ilTestPassResultsSettings.php
@@ -0,0 +1,66 @@
+show_hidden_questions;
+ }
+
+ public function getShowOptionalQuestions(): bool
+ {
+ return $this->show_optional_questions;
+ }
+
+ public function getShowBestSolution(): bool
+ {
+ return $this->show_best_solution;
+ }
+
+ public function getShowFeedback(): bool
+ {
+ return $this->show_feedback;
+ }
+
+ public function getQuestionTextOnly(): bool
+ {
+ return $this->question_text_only;
+ }
+
+ public function getShowRecapitulation(): bool
+ {
+ return $this->show_recapitulation;
+ }
+}
diff --git a/Modules/Test/classes/Results/class.ilTestPassResultsTable.php b/Modules/Test/classes/Results/class.ilTestPassResultsTable.php
new file mode 100644
index 000000000000..589e1ad03225
--- /dev/null
+++ b/Modules/Test/classes/Results/class.ilTestPassResultsTable.php
@@ -0,0 +1,246 @@
+getViewControlsParameter();
+ $results = $this->applyControls($mode, $sortation, $test_results->getQuestionResults());
+ $target = new URLBuilder($data_factory->uri($http->request()->getUri()->__toString()));
+
+ $this->table = $ui_factory->table()->presentation(
+ $title,
+ $this->getViewControls($ui_factory, $lng, $target, $mode, $sortation),
+ $this->getMapping()
+ )
+ ->withEnvironment([
+ self::ENV => $test_results->getSettings(),
+ self::LNG => $lng
+ ])
+ ->withData($results);
+ }
+
+ public function render(): string
+ {
+ return $this->ui_renderer->render($this->table);
+ }
+
+ /**
+ * @param ilQuestionResult[] $question_results
+ */
+ protected function applyControls(
+ string $mode,
+ string $sortation,
+ array $question_results
+ ) {
+ switch($mode) {
+ case self::MODE_OPT_CORRECT:
+ $filter = static fn($qr) => $qr->getCorrect() === ilQuestionResult::CORRECT_FULL;
+ break;
+ case self::MODE_OPT_INCORRECT:
+ $filter = static fn($qr) => $qr->getCorrect() !== ilQuestionResult::CORRECT_FULL;
+ break;
+ case self::MODE_OPT_ALL:
+ default:
+ $filter = static fn($qr) => true;
+ }
+ $question_results = array_filter($question_results, $filter);
+
+ if ($sortation === self::SORT_OPT_POSSIBLESCORE) {
+ usort(
+ $question_results,
+ static fn(ilQuestionResult $a, ilQuestionResult $b) => $a->getQuestionScore() <=> $b->getQuestionScore()
+ );
+ $question_results = array_reverse($question_results);
+ }
+ return $question_results;
+ }
+
+ protected function getViewControlsParameter(): array
+ {
+ $request = $this->http->wrapper()->query();
+ $pre = implode(URLBuilder::SEPARATOR, self::URL_NAMESPACE) . URLBuilder::SEPARATOR;
+
+ $mode = $request->has($pre . self::PARAM_MODE) ?
+ $request->retrieve($pre . self::PARAM_MODE, $this->refinery->kindlyTo()->string()) : self::MODE_OPT_ALL;
+
+ $sortation = $request->has($pre . self::PARAM_SORT) ?
+ $request->retrieve($pre . self::PARAM_SORT, $this->refinery->kindlyTo()->string()) : self::SORT_OPT_ORDEROFAPPEARANCE;
+
+ return [$mode, $sortation];
+ }
+
+ /**
+ * return \ILIAS\UI\ViewControl\ViewControl[]
+ */
+ protected function getViewControls(
+ UIFactory $ui_factory,
+ ilLanguage $lng,
+ URLBuilder $target,
+ string $mode,
+ string $sortation
+ ): array {
+ $builder = $target->acquireParameter(self::URL_NAMESPACE, self::PARAM_MODE);
+ [$target, $token] = $builder;
+
+ $modes = [
+ $lng->txt('resulttable_all') => $target->withParameter($token, self::MODE_OPT_ALL)->buildURI()->__toString(),
+ $lng->txt('resulttable_correct') => $target->withParameter($token, self::MODE_OPT_CORRECT)->buildURI()->__toString(),
+ $lng->txt('resulttable_incorrect') => $target->withParameter($token, self::MODE_OPT_INCORRECT)->buildURI()->__toString(),
+ ];
+ $check = [self::MODE_OPT_ALL, self::MODE_OPT_CORRECT, self::MODE_OPT_INCORRECT];
+ $active = array_search($mode, $check);
+
+ $vc_mode = $ui_factory->viewControl()->mode($modes, $lng->txt('ta_resulttable_vc_mode_aria'))
+ ->withActive(array_keys($modes)[$active]);
+
+ $options = [
+ self::SORT_OPT_ORDEROFAPPEARANCE => $lng->txt('resulttable_vc_sort_iooa'),
+ self::SORT_OPT_POSSIBLESCORE => $lng->txt('resulttable_vc_sort_posscore')
+ ];
+
+ $pre = implode(URLBuilder::SEPARATOR, self::URL_NAMESPACE) . URLBuilder::SEPARATOR;
+ $vc_sort = $ui_factory->viewControl()->sortation($options)->withTargetURL(
+ $target->buildURI()->__toString(),
+ $pre . self::PARAM_SORT
+ )
+ ->withLabel($options[$sortation]);
+
+ return [
+ $vc_mode,
+ $vc_sort
+ ];
+ }
+
+ protected function getMapping(): \Closure
+ {
+ return function ($row, $question, $ui_factory, $environment) {
+ $env = $environment[self::ENV];
+ $lng = $environment[self::LNG];
+
+ $title = sprintf(
+ '%s [ID: %s]',
+ $question->getTitle(),
+ (string)$question->getId()
+ );
+
+ $important_fields = [
+ $lng->txt('question_id') => (string)$question->getId(),
+ $lng->txt('question_type') => $question->getType(),
+ $lng->txt('points') => sprintf(
+ '%s/%s (%s%%)',
+ (string)$question->getUserScore(),
+ (string)$question->getQuestionScore(),
+ (string)$question->getUserScorePercent()
+ )
+ ];
+ $stats = $ui_factory->listing()->characteristicValue()->text($important_fields);
+ $user_answer = $question->getUserAnswer();
+ $best_solution = $env->getShowBestSolution() ? $question->getBestSolution() : '';
+
+
+ $feedback = $ui_factory->listing()->descriptive([
+ $lng->txt('tst_feedback') => $question->getFeedback()
+ ]);
+
+ $contents = [];
+
+ $contents[] = $stats;
+ if ($env->getShowFeedback()) {
+ $contents[] = $feedback;
+ }
+
+ if ($recap = $question->getContentForRecapitulation()) {
+ $contents[] = $ui_factory->listing()->descriptive([
+ $lng->txt('suggested_solution') => $recap
+ ]);
+ }
+
+
+ $answers = $ui_factory->layout()->alignment()->horizontal()->evenlyDistributed(
+ $ui_factory->listing()->descriptive([$lng->txt('tst_header_participant') => $user_answer]),
+ $ui_factory->listing()->descriptive([$lng->txt('tst_header_solution') => $best_solution])
+ );
+ $contents[] = $answers;
+
+ $content = $ui_factory->layout()->alignment()->vertical(...$contents);
+
+ switch($question->getCorrect()) {
+ case ilQuestionResult::CORRECT_FULL:
+ $icon_name = 'icon_ok.svg';
+ $label = $lng->txt("answer_is_right");
+ break;
+ case ilQuestionResult::CORRECT_PARTIAL:
+ $icon_name = 'icon_mostly_ok.svg';
+ $label = $lng->txt("answer_is_not_correct_but_positive");
+ break;
+ case ilQuestionResult::CORRECT_NONE:
+ $icon_name = 'icon_not_ok.svg';
+ $label = $lng->txt("answer_is_wrong");
+ break;
+ }
+ $path = ilUtil::getImagePath('standard/' . $icon_name);
+ $correct_icon = $ui_factory->symbol()->icon()->custom(
+ $path,
+ $label
+ );
+
+ return $row
+ ->withHeadline($title)
+ ->withLeadingSymbol($correct_icon)
+ ->withImportantFields($important_fields)
+ ->withContent($content);
+ };
+ }
+}
diff --git a/Modules/Test/classes/Results/class.ilTestResultsFactory.php b/Modules/Test/classes/Results/class.ilTestResultsFactory.php
new file mode 100644
index 000000000000..8378ed0fbc0b
--- /dev/null
+++ b/Modules/Test/classes/Results/class.ilTestResultsFactory.php
@@ -0,0 +1,192 @@
+getPassResultsSettings($test_obj, $is_user_output);
+ return $this->buildPassResults(
+ $settings,
+ $test_obj,
+ $active_id,
+ $pass_id,
+ $is_user_output
+ );
+ }
+
+ protected function buildPassResults(
+ ilTestPassResultsSettings $settings,
+ ilObjTest $test_obj,
+ int $active_id,
+ int $pass_id,
+ bool $is_user_output
+ ): ilTestPassResult {
+ $question_results = [];
+
+ $results = $test_obj->getTestResult(
+ $active_id,
+ $pass_id,
+ false, //$ordered_sequence
+ $settings->getShowHiddenQuestions(),
+ $settings->getShowOptionalQuestions()
+ );
+
+ // params of getSolutionOutput
+ $graphical_output = false;
+ $result_output = false;
+ $show_question_only = $settings->getQuestionTextOnly();
+ $show_feedback = false; //general
+ $show_correct_solution = false;
+ $show_manual_scoring = false;
+ $show_question_text = true;
+ $show_inline_feedback = true;
+
+ foreach ($results as $idx => $qresult) {
+ if (!is_numeric($idx)) {
+ continue;
+ }
+
+ $qid = $qresult['qid'];
+ $type = $qresult['type'];
+ $title = $qresult['title'];
+ $question_score = $qresult['max'];
+ $usr_score = $qresult['reached'];
+ $workedthrough = (bool)$qresult['workedthrough'];
+ $answered = (bool)$qresult['answered'];
+
+ $question_gui = $test_obj->createQuestionGUI("", $qid);
+ $shuffle_trafo = $this->shuffler->getAnswerShuffleFor($qid, $active_id, $pass_id);
+ $question_gui->object->setShuffler($shuffle_trafo);
+
+ $graphical_output = true;
+ $show_correct_solution = false;
+ $show_inline_feedback = $settings->getShowFeedback();
+ $usr_solution = $question_gui->getSolutionOutput(
+ $active_id,
+ $pass_id,
+ $graphical_output,
+ $result_output,
+ $show_question_only,
+ $show_feedback,
+ $show_correct_solution,
+ $show_manual_scoring,
+ $show_question_text,
+ $show_inline_feedback
+ );
+
+ $graphical_output = false;
+ $show_correct_solution = true;
+ $show_inline_feedback = false;
+ $best_solution = $question_gui->getSolutionOutput(
+ $active_id,
+ $pass_id,
+ $graphical_output,
+ $result_output,
+ $show_question_only,
+ $show_feedback,
+ $show_correct_solution,
+ $show_manual_scoring,
+ $show_question_text,
+ $show_inline_feedback
+ );
+
+ if ($show_question_only) {
+ $usr_solution = $this->ui_renderer->render($this->ui_factory->legacy('' . $usr_solution . '
'));
+ $best_solution = $this->ui_renderer->render($this->ui_factory->legacy('' . $best_solution . '
'));
+ }
+
+ $feedback = $question_gui->getGenericFeedbackOutput($active_id, $pass_id);
+
+ $recapitulation = null;
+ if ($is_user_output && $settings->getShowRecapitulation()) {
+ $recapitulation = $question_gui->object->getSuggestedSolutionOutput();
+ }
+
+ $question_results[] = new ilQuestionResult(
+ $qid,
+ $type,
+ $title,
+ $question_score,
+ $usr_score,
+ $usr_solution,
+ $best_solution,
+ $feedback,
+ $workedthrough,
+ $answered,
+ $recapitulation
+ );
+ }
+
+ return new ilTestPassResult(
+ $settings,
+ $active_id,
+ $pass_id,
+ $question_results
+ );
+ }
+
+ protected function getPassResultsSettings(
+ ilObjTest $test_obj,
+ bool $is_user_output
+ ): ilTestPassResultsSettings {
+ $settings = $test_obj->getScoreSettings();
+ $settings_summary = $settings->getResultSummarySettings();
+ $settings_result = $settings->getResultDetailsSettings();
+
+ $show_hidden_questions = false;
+ $show_optional_questions = true;
+ $show_best_solution = $is_user_output ?
+ $settings_result->getShowSolutionListComparison() :
+ (bool)ilSession::get('tst_results_show_best_solutions');
+ $show_feedback = $settings_result->getShowSolutionFeedback();
+ $show_question_text_only = $settings_result->getShowSolutionAnswersOnly();
+ $show_content_for_recapitulation = $settings_result->getShowSolutionSuggested();
+
+ return new ilTestPassResultsSettings(
+ $show_hidden_questions,
+ $show_optional_questions,
+ $show_best_solution,
+ $show_feedback,
+ $show_question_text_only,
+ $show_content_for_recapitulation
+ );
+ }
+}
diff --git a/Modules/Test/classes/Results/class.ilTestResultsPresentationFactory.php b/Modules/Test/classes/Results/class.ilTestResultsPresentationFactory.php
new file mode 100644
index 000000000000..286437be7d99
--- /dev/null
+++ b/Modules/Test/classes/Results/class.ilTestResultsPresentationFactory.php
@@ -0,0 +1,58 @@
+ui_factory,
+ $this->ui_renderer,
+ $this->refinery,
+ $this->http,
+ $this->data_factory,
+ $this->lng,
+ $pass_results,
+ $title
+ );
+ }
+}
diff --git a/Modules/Test/classes/ScoreReporting/class.ilObjTestScoreSettingsDatabaseRepository.php b/Modules/Test/classes/ScoreReporting/class.ilObjTestScoreSettingsDatabaseRepository.php
index 74ed43602466..5779ae49ba9d 100644
--- a/Modules/Test/classes/ScoreReporting/class.ilObjTestScoreSettingsDatabaseRepository.php
+++ b/Modules/Test/classes/ScoreReporting/class.ilObjTestScoreSettingsDatabaseRepository.php
@@ -98,7 +98,6 @@ protected function doSelect(string $where_part): ilObjTestScoreSettings
//->withShowPassDetails derived from results_presentation with bit RESULTPRES_BIT_PASS_DETAILS
(new ilObjTestSettingsResultDetails($test_id))
->withResultsPresentation((int)$row['results_presentation'])
- ->withPrintBestSolutionWithResult((bool) $row['print_bs_with_res'])
->withShowExamIdInTestResults((bool) $row['examid_in_test_res'])
->withExportSettings((int) $row['exportsettings'])
->withTaxonomyFilterIds($tax_filter_ids),
diff --git a/Modules/Test/classes/ScoreReporting/ilObjTestSettingsResultDetails.php b/Modules/Test/classes/ScoreReporting/ilObjTestSettingsResultDetails.php
index a91fef9c7a8d..33936d68cd84 100644
--- a/Modules/Test/classes/ScoreReporting/ilObjTestSettingsResultDetails.php
+++ b/Modules/Test/classes/ScoreReporting/ilObjTestSettingsResultDetails.php
@@ -52,45 +52,6 @@ public function toForm(
Refinery $refinery,
array $environment = null
): FormInput {
- $bool_with_optional_addition = $refinery->custom()->transformation(
- function ($v) {
- if (!$v) {
- return [false, false]; //[enabled, show_best_solution]
- }
- return [true, array_shift($v)];
- }
- );
-
- $optgroup_lists = $f->optionalGroup(
- [
- $f->checkbox(
- $lng->txt('tst_results_print_best_solution'),
- $lng->txt('tst_results_print_best_solution_info')
- )->withValue($this->getShowSolutionListComparison())
- ],
- $lng->txt('tst_show_solution_details'),
- $lng->txt('tst_show_solution_details_desc')
- )->withAdditionalTransformation($bool_with_optional_addition);
-
- if (!$this->getShowSolutionListOwnAnswers()) {
- $optgroup_lists = $optgroup_lists->withValue(null);
- }
-
- $optgroup_singlepage = $f->optionalGroup(
- [
- $f->checkbox(
- $lng->txt('tst_results_print_best_solution_singlepage'),
- $lng->txt('tst_results_print_best_solution_singlepage_info')
- )->withValue($this->getPrintBestSolutionWithResult())
- ],
- $lng->txt('tst_show_solution_details_singlepage'),
- $lng->txt('tst_show_solution_details_singlepage_desc')
- )->withAdditionalTransformation($bool_with_optional_addition);
- if (!$this->getShowSolutionDetails()) {
- $optgroup_singlepage = $optgroup_singlepage->withValue(null);
- }
-
-
$taxonomy_options = $environment['taxonomy_options'];
$taxonomy_ids = $f->multiselect(
$lng->txt('tst_results_tax_filters'),
@@ -99,9 +60,11 @@ function ($v) {
);
$fields = [
- 'solution_details' => $optgroup_lists,
- 'solution_details_singlepage' => $optgroup_singlepage,
-
+ 'solution_best_solution' =>
+ $f->checkbox(
+ $lng->txt('tst_results_print_best_solution'),
+ $lng->txt('tst_results_print_best_solution_info')
+ )->withValue($this->getShowSolutionListComparison()),
'solution_feedback' => $f->checkbox(
$lng->txt('tst_show_solution_feedback'),
$lng->txt('tst_show_solution_feedback_desc')
@@ -138,13 +101,8 @@ function ($v) {
->withAdditionalTransformation(
$refinery->custom()->transformation(
function ($v) {
- list($solution_list_details, $solution_list_best_solution) = $v['solution_details'];
- list($solution_sp_details, $solution_sp_best_solution) = $v['solution_details_singlepage'];
return (clone $this)
- ->withShowSolutionListOwnAnswers($solution_list_details)
- ->withShowSolutionListComparison($solution_list_best_solution)
- ->withShowSolutionDetails($solution_sp_details)
- ->withPrintBestSolutionWithResult($solution_sp_best_solution)
+ ->withShowSolutionListComparison($v['solution_best_solution'])
->withShowSolutionFeedback($v['solution_feedback'])
->withShowSolutionSuggested($v['solution_suggested'])
->withShowSolutionPrintview($v['solution_printview'])
@@ -160,7 +118,6 @@ function ($v) {
public function toStorage(): array
{
return [
- 'print_bs_with_res' => ['integer', (int) $this->getPrintBestSolutionWithResult()],
'results_presentation' => ['integer', $this->getResultsPresentation()],
'examid_in_test_res' => ['integer', (int) $this->getShowExamIdInTestResults()],
'exportsettings' => ['integer', (int) $this->getExportSettings()],
@@ -169,18 +126,6 @@ public function toStorage(): array
];
}
-
- public function getPrintBestSolutionWithResult(): bool
- {
- return $this->print_bs_with_res;
- }
- public function withPrintBestSolutionWithResult(bool $print_bs_with_res): self
- {
- $clone = clone $this;
- $clone->print_bs_with_res = $print_bs_with_res;
- return $clone;
- }
-
public function getResultsPresentation(): int
{
return $this->results_presentation;
@@ -232,15 +177,6 @@ public function withShowPassDetails(bool $flag): self
return $this->modifyResultPresentation(self::RESULTPRES_BIT_PASS_DETAILS, $flag);
}
- public function getShowSolutionDetails(): bool
- {
- return $this->compareResultPresentation(self::RESULTPRES_BIT_SOLUTION_DETAILS);
- }
- public function withShowSolutionDetails(bool $flag): self
- {
- return $this->modifyResultPresentation(self::RESULTPRES_BIT_SOLUTION_DETAILS, $flag);
- }
-
public function getShowSolutionPrintview(): bool
{
return $this->compareResultPresentation(self::RESULTPRES_BIT_SOLUTION_PRINTVIEW);
@@ -295,15 +231,6 @@ public function withShowSolutionListComparison(bool $flag): self
return $this->modifyResultPresentation(self::RESULTPRES_BIT_SOLUTION_LISTCOMPARE, $flag);
}
- public function getShowSolutionListOwnAnswers(): bool
- {
- return $this->compareResultPresentation(self::RESULTPRES_BIT_SOLUTION_LISTOWNANSWERS);
- }
- public function withShowSolutionListOwnAnswers(bool $flag): self
- {
- return $this->modifyResultPresentation(self::RESULTPRES_BIT_SOLUTION_LISTOWNANSWERS, $flag);
- }
-
public function getExportSettings(): int
{
return $this->exportsettings;
diff --git a/Modules/Test/classes/Screen/class.ilTestPlayerLayoutProvider.php b/Modules/Test/classes/Screen/class.ilTestPlayerLayoutProvider.php
index 5fe0046113bb..9bd737bef0f4 100644
--- a/Modules/Test/classes/Screen/class.ilTestPlayerLayoutProvider.php
+++ b/Modules/Test/classes/Screen/class.ilTestPlayerLayoutProvider.php
@@ -22,6 +22,7 @@
use ILIAS\GlobalScreen\Scope\Layout\Factory\LogoModification;
use ILIAS\GlobalScreen\Scope\Layout\Factory\MainBarModification;
use ILIAS\GlobalScreen\Scope\Layout\Factory\MetaBarModification;
+use ILIAS\GlobalScreen\Scope\Layout\Factory\TitleModification;
use ILIAS\GlobalScreen\Scope\Layout\Factory\ShortTitleModification;
use ILIAS\GlobalScreen\Scope\Layout\Factory\ViewTitleModification;
use ILIAS\GlobalScreen\Scope\Layout\Provider\AbstractModificationProvider;
@@ -44,58 +45,66 @@
class ilTestPlayerLayoutProvider extends AbstractModificationProvider implements ModificationProvider
{
public const TEST_PLAYER_KIOSK_MODE_ENABLED = 'test_player_kiosk_mode_enabled';
- public const TEST_PLAYER_TITLE = 'test_player_kiosk_mode_title';
- public const TEST_PLAYER_SHORT_TITLE = 'test_player_kiosk_mode_instance_name';
+ public const TEST_PLAYER_TITLE = 'test_player_title';
+ public const TEST_PLAYER_VIEW_TITLE = 'test_player_view_title';
+ public const TEST_PLAYER_SHORT_TITLE = 'test_player_instance_name';
+ public const TEST_PLAYER_QUESTIONLIST = 'test_player_questionlist';
+ private const MODIFICATION_PRIORITY = 5; //slightly above "low"
public function isInterestedInContexts(): ContextCollection
{
return $this->context_collection->repository();
}
- public function getLogoModification(CalledContexts $called_contexts): ?LogoModification
+ public function getMainBarModification(CalledContexts $called_contexts): ?MainBarModification
{
- if ($this->isKioskModeEnabled($called_contexts)) {
- $logo = $this->globalScreen()->layout()->factory()->logo();
-
- $logo = $logo->withModification(function (?Image $current): ?Image {
- return null;
- });
+ $mainbar = $this->globalScreen()->layout()->factory()->mainbar();
+ $additionalData = $called_contexts->current()->getAdditionalData();
+ $has_question_list = $additionalData->exists(self::TEST_PLAYER_QUESTIONLIST);
+ $is_kiosk_mode = $this->isKioskModeEnabled($called_contexts);
- return $logo->withHighPriority();
+ if (! $is_kiosk_mode && ! $has_question_list) {
+ return null;
}
- return null;
- }
-
- public function getResponsiveLogoModification(CalledContexts $called_contexts): ?LogoModification
- {
- if ($this->isKioskModeEnabled($called_contexts)) {
- $logo = $this->globalScreen()->layout()->factory()->logo();
+ if ($is_kiosk_mode && ! $has_question_list) {
+ $mainbar_modification = static fn(?MainBar $mainbar): ?MainBar => null;
+ }
- $logo = $logo->withModification(function (?Image $current): ?Image {
- return null;
- });
+ if ($has_question_list) {
+ $f = $this->dic->ui()->factory();
+ $r = $this->dic->ui()->renderer();
+ $lng = $this->dic->language();
+ $question_listing = $called_contexts->current()->getAdditionalData()->get(self::TEST_PLAYER_QUESTIONLIST);
- return $logo->withHighPriority();
- }
+ $mainbar_modification = static function (?MainBar $mainbar) use ($f, $r, $lng, $question_listing, $is_kiosk_mode): ?MainBar {
+ if ($is_kiosk_mode) {
+ $mainbar = $mainbar->withClearedEntries();
+ }
- return null;
- }
+ $icon = $f->symbol()->icon()->standard('tst', $lng->txt("more"));
+ $tools_button = $f->button()->bulky($icon, $lng->txt("tools"), "#")
+ ->withEngagedState(true);
- public function getMainBarModification(CalledContexts $called_contexts): ?MainBarModification
- {
- if ($this->isKioskModeEnabled($called_contexts)) {
- $mainBar = $this->globalScreen()->layout()->factory()->mainbar();
+ $question_listing = $f->legacy($r->render($question_listing));
- $mainBar = $mainBar->withModification(function (?MainBar $current): ?MainBar {
- return null;
- });
+ $label = $lng->txt('mainbar_button_label_questionlist');
+ $entry = $f->maincontrols()->slate()->legacy(
+ $label,
+ $f->symbol()->icon()->standard("tst", $label),
+ $question_listing
+ );
- return $mainBar->withHighPriority();
+ return $mainbar
+ ->withToolsButton($tools_button)
+ ->withAdditionalToolEntry('questionlist', $entry);
+ };
}
- return null;
+ return $mainbar
+ ->withModification($mainbar_modification)
+ ->withPriority(self::MODIFICATION_PRIORITY);
}
public function getMetaBarModification(CalledContexts $called_contexts): ?MetaBarModification
@@ -107,7 +116,8 @@ public function getMetaBarModification(CalledContexts $called_contexts): ?MetaBa
return null;
});
- return $metaBar->withHighPriority();
+ return $metaBar
+ ->withPriority(self::MODIFICATION_PRIORITY);
}
return null;
@@ -122,7 +132,8 @@ public function getFooterModification(CalledContexts $called_contexts): ?FooterM
return null;
});
- return $footer->withHighPriority();
+ return $footer
+ ->withPriority(self::MODIFICATION_PRIORITY);
}
return null;
@@ -149,7 +160,7 @@ function (?string $content) use ($title): ?string {
return $title;
}
)
- ->withHighPriority();
+ ->withPriority(self::MODIFICATION_PRIORITY);
}
return null;
}
@@ -157,6 +168,26 @@ function (?string $content) use ($title): ?string {
public function getViewTitleModification(CalledContexts $called_contexts): ?ViewTitleModification
{
if ($this->isKioskModeEnabled($called_contexts)) {
+ $title = $called_contexts->current()->getAdditionalData()->get(self::TEST_PLAYER_VIEW_TITLE);
+ if (is_null($title)) {
+ $title = '';
+ }
+ return $this->globalScreen()->layout()->factory()->view_title()
+ ->withModification(
+ function (?string $content) use ($title): ?string {
+ return $title;
+ }
+ )
+ ->withPriority(self::MODIFICATION_PRIORITY);
+ }
+ return null;
+ }
+
+ public function getTitleModification(CalledContexts $called_contexts): ?TitleModification
+ {
+ $additionalData = $called_contexts->current()->getAdditionalData();
+ $has_title = $additionalData->exists(self::TEST_PLAYER_TITLE);
+ if ($has_title) {
$title = $called_contexts->current()->getAdditionalData()->get(self::TEST_PLAYER_TITLE);
if ($title == null) {
$title = '';
@@ -167,7 +198,7 @@ function (?string $content) use ($title): ?string {
return $title;
}
)
- ->withHighPriority();
+ ->withPriority(self::MODIFICATION_PRIORITY);
}
return null;
}
diff --git a/Modules/Test/classes/Setup/class.ilTest9DBUpdateSteps.php b/Modules/Test/classes/Setup/class.ilTest9DBUpdateSteps.php
index b201a7c954c8..64dba27c03ea 100644
--- a/Modules/Test/classes/Setup/class.ilTest9DBUpdateSteps.php
+++ b/Modules/Test/classes/Setup/class.ilTest9DBUpdateSteps.php
@@ -180,6 +180,20 @@ public function step_8(): void
}
public function step_9(): void
+ {
+ if (!$this->db->tableColumnExists('tst_tests', 'show_questionlist')) {
+ $this->db->addTableColumn(
+ 'tst_tests',
+ 'show_questionlist',
+ [
+ 'type' => 'integer',
+ 'length' => 1
+ ]
+ );
+ }
+ }
+
+ public function step_10(): void
{
if ($this->db->tableColumnExists('tst_tests', 'sign_submission')) {
$this->db->dropTableColumn(
@@ -188,4 +202,29 @@ public function step_9(): void
);
}
}
+
+ public function step_11(): void
+ {
+ if ($this->db->tableColumnExists('tst_tests', 'show_summary')) {
+ $this->db->renameTableColumn(
+ 'tst_tests',
+ 'show_summary',
+ 'usr_pass_overview_mode'
+ );
+ }
+ }
+
+ public function step_12(): void
+ {
+ if (!$this->db->tableColumnExists('tst_tests', 'show_questionlist')) {
+ $this->db->addTableColumn(
+ 'tst_tests',
+ 'show_questionlist',
+ [
+ 'type' => 'integer',
+ 'length' => 1
+ ]
+ );
+ }
+ }
}
diff --git a/Modules/Test/classes/Setup/class.ilTestSetupAgent.php b/Modules/Test/classes/Setup/class.ilTestSetupAgent.php
index 1f15f3403def..138c095d7862 100644
--- a/Modules/Test/classes/Setup/class.ilTestSetupAgent.php
+++ b/Modules/Test/classes/Setup/class.ilTestSetupAgent.php
@@ -26,6 +26,7 @@
use ILIAS\Refinery\Transformation;
use ILIAS\Test\Setup\ilManScoringSettingsToOwnDbTableMigration;
use ILIAS\Test\Setup\ilRemoveDynamicTestsAndCorrespondingDataMigration;
+use ILIAS\Test\Setup\ilSeparateQuestionListSettingMigration;
class ilTestSetupAgent extends NullAgent
{
@@ -65,7 +66,8 @@ public function getMigrations(): array
{
return [
new ilManScoringSettingsToOwnDbTableMigration(),
- new ilRemoveDynamicTestsAndCorrespondingDataMigration()
+ new ilRemoveDynamicTestsAndCorrespondingDataMigration(),
+ new ilSeparateQuestionListSettingMigration()
];
}
}
diff --git a/Modules/Test/classes/Setup/ilSeparateQuestionListSettingMigration.php b/Modules/Test/classes/Setup/ilSeparateQuestionListSettingMigration.php
new file mode 100644
index 000000000000..e4fefec87d1c
--- /dev/null
+++ b/Modules/Test/classes/Setup/ilSeparateQuestionListSettingMigration.php
@@ -0,0 +1,87 @@
+db = $environment->getResource(Setup\Environment::RESOURCE_DATABASE);
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function step(Environment $environment): void
+ {
+ $this->db->manipulate(
+ 'UPDATE tst_tests SET show_questionlist = 1 WHERE usr_pass_overview_mode > 0'
+ );
+
+ $this->db->manipulate(
+ 'UPDATE tst_tests SET show_questionlist = 0 WHERE usr_pass_overview_mode = 0'
+ );
+ }
+
+ public function getRemainingAmountOfSteps(): int
+ {
+ $result = $this->db->query(
+ "SELECT count(*) as cnt FROM tst_tests WHERE show_questionlist is NULL"
+ );
+ $row = $this->db->fetchAssoc($result);
+
+ return (int) $row['cnt'] ?? 0;
+ }
+}
diff --git a/Modules/Test/classes/Skills/class.TestSkillDBRepository.php b/Modules/Test/classes/Skills/class.TestSkillDBRepository.php
new file mode 100644
index 000000000000..5a88c21b8a17
--- /dev/null
+++ b/Modules/Test/classes/Skills/class.TestSkillDBRepository.php
@@ -0,0 +1,48 @@
+
+ */
+class TestSkillDBRepository
+{
+ protected \ilDBInterface $db;
+
+ public function __construct(
+ \ilDBInterface $db = null
+ ) {
+ global $DIC;
+
+ $this->db = ($db) ?: $DIC->database();
+ }
+
+ public function removeForSkill(int $skill_node_id, bool $is_reference): void
+ {
+ if (!$is_reference) {
+ $this->db->manipulate("DELETE FROM tst_skl_thresholds " .
+ " WHERE skill_base_fi = " . $this->db->quote($skill_node_id, "integer"));
+ } else {
+ $this->db->manipulate("DELETE FROM tst_skl_thresholds " .
+ " WHERE skill_tref_fi = " . $this->db->quote($skill_node_id, "integer"));
+ }
+ }
+}
diff --git a/Modules/Test/classes/class.ilObjTest.php b/Modules/Test/classes/class.ilObjTest.php
index b8905978bb1e..c071dea0d3b0 100755
--- a/Modules/Test/classes/class.ilObjTest.php
+++ b/Modules/Test/classes/class.ilObjTest.php
@@ -134,8 +134,10 @@ public function __construct(int $id = 0, bool $a_call_by_reference = true)
$this->component_repository = $DIC['component.repository'];
$this->component_factory = $DIC['component.factory'];
$this->filesystem_web = $DIC->filesystem()->web();
- $this->testManScoringDoneHelper = new TestManScoringDoneHelper();
- $this->participant_access_filter = new ilTestParticipantAccessFilterFactory($DIC['ilAccess']);
+
+ $local_dic = $this->getLocalDIC();
+ $this->participant_access_filter = $local_dic['participantAccessFilterFactory'];
+ $this->testManScoringDoneHelper = $local_dic['manScoringDoneHelper'];
$this->mark_schema = new ASS_MarkSchema($DIC['ilDB'], $DIC['lng'], $DIC['ilUser']->getId());
$this->mark_schema->createSimpleSchema(
@@ -166,6 +168,11 @@ public function __construct(int $id = 0, bool $a_call_by_reference = true)
);
}
+ public function getLocalDIC(): ILIAS\DI\Container
+ {
+ return ilTestDIC::dic();
+ }
+
/**
* returns the object title prepared to be used as a filename
*/
@@ -3435,9 +3442,13 @@ public function fromXML(ilQTIAssessment $assessment)
case 'pass_deletion_allowed':
$result_summary_settings = $result_summary_settings->withPassDeletionAllowed((bool) $metadata["entry"]);
break;
- case "show_summary":
- $participant_functionality_settings = $participant_functionality_settings->withQuestionListMode((int) $metadata["entry"]);
+ case "usr_pass_overview_mode":
+ $participant_functionality_settings = $participant_functionality_settings->withUsrPassOverviewMode((int) $metadata["entry"]);
break;
+ case "question_list":
+ $participant_functionality_settings = $participant_functionality_settings->withQuestionListEnabled((bool) $metadata["entry"]);
+ break;
+
case "reporting_date":
$result_summary_settings = $result_summary_settings->withReportingDate(
$metadata['ReportingDate'] !== null ?
@@ -3861,8 +3872,8 @@ public function toXML(): string
// solution details
$a_xml_writer->xmlStartTag("qtimetadatafield");
- $a_xml_writer->xmlElement("fieldlabel", null, "show_summary");
- $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $main_settings->getParticipantFunctionalitySettings()->getQuestionListMode()));
+ $a_xml_writer->xmlElement("fieldlabel", null, "usr_pass_overview_mode");
+ $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $main_settings->getParticipantFunctionalitySettings()->getUsrPassOverviewMode()));
$a_xml_writer->xmlEndTag("qtimetadatafield");
// solution details
@@ -3871,10 +3882,6 @@ public function toXML(): string
$a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getScoreReporting()));
$a_xml_writer->xmlEndTag("qtimetadatafield");
- $a_xml_writer->xmlStartTag("qtimetadatafield");
- $a_xml_writer->xmlElement("fieldlabel", null, "solution_details");
- $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getShowSolutionDetails());
- $a_xml_writer->xmlEndTag("qtimetadatafield");
$a_xml_writer->xmlStartTag("qtimetadatafield");
$a_xml_writer->xmlElement("fieldlabel", null, "print_bs_with_res");
$a_xml_writer->xmlElement("fieldentry", null, (int) $this->getShowSolutionDetails() ? (int) $this->isBestSolutionPrintedWithResult() : 0);
@@ -5871,7 +5878,7 @@ public function getShuffleQuestions(): bool
*/
public function getListOfQuestionsSettings()
{
- return $this->getMainSettings()->getParticipantFunctionalitySettings()->getQuestionListMode();
+ return $this->getMainSettings()->getParticipantFunctionalitySettings()->getUsrPassOverviewMode();
}
public function getListOfQuestions(): bool
@@ -5879,6 +5886,11 @@ public function getListOfQuestions(): bool
return $this->getMainSettings()->getParticipantFunctionalitySettings()->getQuestionListEnabled();
}
+ public function getUsrPassOverviewEnabled(): bool
+ {
+ return $this->getMainSettings()->getParticipantFunctionalitySettings()->getUsrPassOverviewEnabled();
+ }
+
public function getListOfQuestionsStart(): bool
{
return $this->getMainSettings()->getParticipantFunctionalitySettings()->getShownQuestionListAtBeginning();
@@ -5902,14 +5914,6 @@ public function getShowPassDetails(): bool
return $this->getScoreSettings()->getResultDetailsSettings()->getShowPassDetails();
}
- /**
- * Returns if the solution details should be presented to the user or not
- */
- public function getShowSolutionDetails(): bool
- {
- return $this->getScoreSettings()->getResultDetailsSettings()->getShowSolutionDetails();
- }
-
/**
* Returns if the solution printview should be presented to the user or not
*/
@@ -6362,7 +6366,7 @@ public function addDefaults($a_name)
'use_previous_answers' => (int) $main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed(),
'ShowCancel' => (int) $main_settings->getParticipantFunctionalitySettings()->getSuspendTestAllowed(),
'SequenceSettings' => (int) $main_settings->getParticipantFunctionalitySettings()->getPostponedQuestionsMoveToEnd(),
- 'ListOfQuestionsSettings' => $main_settings->getParticipantFunctionalitySettings()->getQuestionListMode(),
+ 'ListOfQuestionsSettings' => $main_settings->getParticipantFunctionalitySettings()->getUsrPassOverviewMode(),
'ShowMarker' => (int) $main_settings->getParticipantFunctionalitySettings()->getQuestionMarkingEnabled(),
'enable_examview' => $main_settings->getFinishingSettings()->getShowAnswerOverview(),
@@ -6486,7 +6490,7 @@ public function applyDefaults($test_defaults): bool
->withUsePreviousAnswerAllowed((bool) $testsettings['use_previous_answers'])
->withSuspendTestAllowed((bool) $testsettings['ShowCancel'])
->withPostponedQuestionsMoveToEnd((bool) $testsettings['SequenceSettings'])
- ->withQuestionListMode($testsettings['ListOfQuestionsSettings'])
+ ->withUsrPassOverviewMode($testsettings['ListOfQuestionsSettings'])
->withQuestionMarkingEnabled((bool) $testsettings['ShowMarker'])
)
->withFinishingSettings(
diff --git a/Modules/Test/classes/class.ilObjTestGUI.php b/Modules/Test/classes/class.ilObjTestGUI.php
index a73574dd64de..c23501cb1a7e 100755
--- a/Modules/Test/classes/class.ilObjTestGUI.php
+++ b/Modules/Test/classes/class.ilObjTestGUI.php
@@ -121,6 +121,7 @@ public function __construct($refId = null)
$this->questioninfo = $DIC->testQuestionPool()->questionInfo();
$this->type = 'tst';
$this->testrequest = $DIC->test()->internal()->request();
+
$ref_id = 0;
if ($this->testrequest->hasRefId() && is_numeric($this->testrequest->getRefId())) {
$ref_id = $this->testrequest->getRefId();
@@ -1445,7 +1446,7 @@ public function importVerifiedFileObject()
if (is_file(ilSession::get("tst_import_dir") . '/' . ilSession::get("tst_import_subdir") . "/manifest.xml")) {
$newObj->saveToDb();
- ilSession::set('tst_import_idents', $_POST['ident']);
+ ilSession::set('tst_import_idents', $_POST['ident'] ?? '');
ilSession::set('tst_import_qst_parent', $questionParentObjId);
$fileName = ilSession::get('tst_import_subdir') . '.zip';
diff --git a/Services/Object/classes/Setup/class.Agent.php b/Modules/Test/classes/class.ilTestAppEventListener.php
similarity index 50%
rename from Services/Object/classes/Setup/class.Agent.php
rename to Modules/Test/classes/class.ilTestAppEventListener.php
index 26a3f045df4d..bcc48e91ee30 100644
--- a/Services/Object/classes/Setup/class.Agent.php
+++ b/Modules/Test/classes/class.ilTestAppEventListener.php
@@ -16,24 +16,24 @@
*
*********************************************************************/
-namespace ILIAS\Object\Setup;
+declare(strict_types=1);
-use ILIAS\Setup;
-use ILIAS\Setup\Objective;
-use ILIAS\Setup\Metrics;
+use ILIAS\Test\Skills\TestSkillDBRepository;
/**
- * @author Alexander Killing
+ * @author Thomas Famula
*/
-class Agent extends Setup\Agent\NullAgent
+class ilTestAppEventListener implements ilAppEventListener
{
- public function getUpdateObjective(Setup\Config $config = null): Setup\Objective
+ /**
+ * @inheritDoc
+ */
+ public static function handleEvent(string $a_component, string $a_event, array $a_parameter): void
{
- return new \ilDatabaseUpdateStepsExecutedObjective(new ilObjectDBUpdateSteps());
- }
+ $test_skill_repo = new TestSkillDBRepository();
- public function getStatusObjective(Metrics\Storage $storage): Objective
- {
- return new \ilDatabaseUpdateStepsMetricsCollectedObjective($storage, new ilObjectDBUpdateSteps());
+ if ($a_component === "Services/Skill" && $a_event === "deleteSkill") {
+ $test_skill_repo->removeForSkill($a_parameter["node_id"], $a_parameter["is_reference"]);
+ }
}
}
diff --git a/Modules/Test/classes/class.ilTestDIC.php b/Modules/Test/classes/class.ilTestDIC.php
new file mode 100644
index 000000000000..1673e4a99fa4
--- /dev/null
+++ b/Modules/Test/classes/class.ilTestDIC.php
@@ -0,0 +1,75 @@
+
+ new ilTestShuffler($dic['refinery']);
+
+ $dic['factory.results'] = static fn($c): ilTestResultsFactory =>
+ new ilTestResultsFactory(
+ $c['shuffler'],
+ $dic['ui.factory'],
+ $dic['ui.renderer']
+ );
+
+ $dic['factory.results_presentation'] = static fn($c): ilTestResultsPresentationFactory =>
+ new ilTestResultsPresentationFactory(
+ $dic['ui.factory'],
+ $dic['ui.renderer'],
+ $dic['refinery'],
+ new ILIAS\Data\Factory(),
+ $dic['http'],
+ $dic['lng']
+ );
+
+
+ $dic['participantAccessFilterFactory'] = static fn($c): ilTestParticipantAccessFilterFactory =>
+ new ilTestParticipantAccessFilterFactory($dic['ilAccess']);
+
+ $dic['manScoringDoneHelper'] = static fn($c): TestManScoringDoneHelper =>
+ new TestManScoringDoneHelper();
+
+ $dic['request.internal'] = static fn($c): InternalRequestService =>
+ new InternalRequestService($dic['http'], $dic['refinery']);
+
+ return $dic;
+ }
+}
diff --git a/Modules/Test/classes/class.ilTestEvaluationGUI.php b/Modules/Test/classes/class.ilTestEvaluationGUI.php
index c211d77fe3e8..28f0b957c166 100644
--- a/Modules/Test/classes/class.ilTestEvaluationGUI.php
+++ b/Modules/Test/classes/class.ilTestEvaluationGUI.php
@@ -48,8 +48,6 @@ class ilTestEvaluationGUI extends ilTestServiceGUI
protected ilTestAccess $testAccess;
protected ilTestProcessLockerFactory $processLockerFactory;
- protected ilTestParticipantAccessFilterFactory $participant_access_filter;
-
/**
* ilTestEvaluationGUI constructor
*
@@ -64,6 +62,7 @@ public function __construct(ilObjTest $object)
global $DIC;
$this->participant_access_filter = new ilTestParticipantAccessFilterFactory($this->access);
$this->ui = $DIC->ui();
+
$this->processLockerFactory = new ilTestProcessLockerFactory(
new ilSetting('assessment'),
$this->db
@@ -331,6 +330,7 @@ public function outEvaluation()
}
$this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
+
if ($this->object->getShowSolutionAnswersOnly()) {
$this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
}
@@ -863,47 +863,6 @@ public function outParticipantsPassDetails()
);
}
- $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache);
-
- $objectivesList = null;
-
- if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
- $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
- $testSequence->loadFromDb();
- $testSequence->loadQuestions();
-
- $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession);
-
- $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence);
- $objectivesList->loadObjectivesTitles();
-
- $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId());
- $testResultHeaderLabelBuilder->setUserId($testSession->getUserId());
- $testResultHeaderLabelBuilder->setTestObjId($this->object->getId());
- $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId());
- $testResultHeaderLabelBuilder->initObjectiveOrientedMode();
- }
-
- $result_array = $this->getFilteredTestResult($active_id, $pass, false, !$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired());
-
- $overviewTableGUI = $this->getPassDetailsOverviewTableGUI(
- $result_array,
- $active_id,
- $pass,
- $this,
- "outParticipantsPassDetails",
- '',
- true,
- $objectivesList
- );
- $overviewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
- $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, false);
- $user_id = $this->object->_getUserIdFromActiveId($active_id);
-
- $template = new ilTemplate("tpl.il_as_tst_pass_details_overview_participants.html", true, true, "Modules/Test");
-
- $toolbar = $this->buildUserTestResultsToolbarGUI();
-
if ($this->testrequest->isset('show_best_solutions')) {
ilSession::set('tst_results_show_best_solutions', true);
} elseif ($this->testrequest->isset('hide_best_solutions')) {
@@ -912,6 +871,18 @@ public function outParticipantsPassDetails()
ilSession::clear('tst_results_show_best_solutions');
}
+ $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
+ if ($this->object->getShowSolutionAnswersOnly()) {
+ $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
+ }
+
+ $template = new ilTemplate("tpl.il_as_tst_pass_details_overview_participants.html", true, true, "Modules/Test");
+
+ $this->populateExamId($template, $active_id, (int) $pass);
+ $this->populatePassFinishDate($template, ilObjTest::lookupLastTestPassAccess($active_id, $pass));
+
+
+ $toolbar = $this->buildUserTestResultsToolbarGUI();
if (ilSession::get('tst_results_show_best_solutions')) {
$this->ctrl->setParameter($this, 'hide_best_solutions', '1');
$toolbar->setHideBestSolutionsLinkTarget($this->ctrl->getLinkTarget($this, 'outParticipantsPassDetails'));
@@ -934,37 +905,31 @@ public function outParticipantsPassDetails()
$template->parseCurrentBlock();
}
- $list_of_answers = $this->getPassListOfAnswers($result_array, $active_id, $pass, ilSession::get('tst_results_show_best_solutions'), false, false, false, true, $objectivesList, $testResultHeaderLabelBuilder);
- $template->setVariable("LIST_OF_ANSWERS", $list_of_answers);
- $template->setVariable("PASS_DETAILS", $this->ctrl->getHTML($overviewTableGUI));
-
- $data = $this->object->getCompleteEvaluationData();
- $result = $data->getParticipant($active_id)->getReached() . " " . strtolower($this->lng->txt("of")) . " " . $data->getParticipant($active_id)->getMaxpoints() . " (" . sprintf("%2.2f", $data->getParticipant($active_id)->getReachedPointsInPercent()) . " %" . ")";
- $template->setCurrentBlock('total_score');
- $template->setVariable("TOTAL_RESULT_TEXT", $this->lng->txt('tst_stat_result_resultspoints'));
- $template->setVariable("TOTAL_RESULT", $result);
- $template->parseCurrentBlock();
-
- if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
- $template->setVariable("USER_DATA", $user_data);
-
- $uname = $this->object->userLookupFullName($user_id);
- $template->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name_pass"), $pass + 1, $uname));
+ $title = sprintf(
+ $this->lng->txt("tst_result_user_name_pass"),
+ $pass + 1,
+ ilObjUser::_lookupFullname($this->object->_getUserIdFromActiveId($active_id))
+ );
- $template->setVariable("TEXT_RESULTS", $testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
- }
+ $pass_results = $this->results_factory->getPassResultsFor(
+ $this->object,
+ $active_id,
+ $pass,
+ false
+ );
- $template->setVariable("FORMACTION", $this->ctrl->getFormAction($this));
+ $table = $this->results_presentation_factory->getPassResultsPresentationTable(
+ $pass_results,
+ $title
+ );
- $this->populateExamId($template, $active_id, $pass);
- $this->populatePassFinishDate($template, ilObjTest::lookupLastTestPassAccess($active_id, $pass));
+ $this->tpl->addCss(ilObjStyleSheet::getContentStylePath(0));
- $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
- if ($this->object->getShowSolutionAnswersOnly()) {
- $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
- }
-
- $this->tpl->setVariable("ADM_CONTENT", $template->get());
+ $this->tpl->setVariable(
+ "ADM_CONTENT",
+ $template->get()
+ . $table->render()
+ );
}
public function outParticipantsResultsOverview()
@@ -1149,14 +1114,10 @@ public function outUserPassDetails(): void
$result_array = $this->getFilteredTestResult($active_id, $pass, $considerHiddenQuestions, $considerOptionalQuestions);
$command_solution_details = "";
- if ($this->object->getShowSolutionDetails()) {
+ if ($this->object->getShowSolutionListComparison()) {
$command_solution_details = "outCorrectSolution";
}
- //$questionAnchorNav = $this->object->canShowSolutionPrintview();
- $questionAnchorNav =
- $this->object->getShowSolutionListOwnAnswers();
-
$tpl = new ilTemplate('tpl.il_as_tst_pass_details_overview_participants.html', true, true, "Modules/Test");
$toolbar = $this->buildUserTestResultsToolbarGUI();
@@ -1191,19 +1152,6 @@ public function outUserPassDetails(): void
$gradingMessageBuilder->sendMessage();
}
- $overviewTableGUI = $this->getPassDetailsOverviewTableGUI(
- $result_array,
- $active_id,
- $pass,
- $this,
- "outUserPassDetails",
- $command_solution_details,
- $questionAnchorNav,
- $objectivesList
- );
- $overviewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
- $tpl->setVariable("PASS_DETAILS", $this->ctrl->getHTML($overviewTableGUI));
-
$data = $this->object->getCompleteEvaluationData();
$percent = $data->getParticipant($active_id)->getPass($pass)->getReachedPoints() / $data->getParticipant($active_id)->getPass($pass)->getMaxPoints() * 100;
$result = $data->getParticipant($active_id)->getPass($pass)->getReachedPoints() . " " . strtolower($this->lng->txt("of")) . " " . $data->getParticipant($active_id)->getPass($pass)->getMaxPoints() . " (" . sprintf("%2.2f", $percent) . " %" . ")";
@@ -1212,36 +1160,9 @@ public function outUserPassDetails(): void
$tpl->setVariable("TOTAL_RESULT", $result);
$tpl->parseCurrentBlock();
- if ($this->object->getShowSolutionListOwnAnswers()) {
- $list_of_answers = $this->getPassListOfAnswers(
- $result_array,
- $active_id,
- $pass,
- $this->object->getShowSolutionListComparison(),
- false,
- false,
- false,
- true,
- $objectivesList,
- $testResultHeaderLabelBuilder
- );
- $tpl->setVariable("LIST_OF_ANSWERS", $list_of_answers);
- }
-
$tpl->setVariable("TEXT_RESULTS", $testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
$tpl->setVariable("FORMACTION", $this->ctrl->getFormAction($this));
- $uname = $this->object->userLookupFullName($user_id, true);
- $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, true);
- if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
- if ($this->object->getAnonymity()) {
- $tpl->setVariable("TEXT_HEADING", $this->lng->txt("tst_result_pass"));
- } else {
- $tpl->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name_pass"), $pass + 1, $uname));
- $tpl->setVariable("USER_DATA", $user_data);
- }
- }
-
$this->populateExamId($tpl, $active_id, (int) $pass);
$this->populatePassFinishDate($tpl, ilObjTest::lookupLastTestPassAccess($active_id, $pass));
@@ -1250,7 +1171,31 @@ public function outUserPassDetails(): void
$this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
}
- $this->tpl->setContent($tpl->get());
+ $title = sprintf(
+ $this->lng->txt("tst_result_user_name_pass"),
+ $pass + 1,
+ ilObjUser::_lookupFullname($this->object->_getUserIdFromActiveId($active_id))
+ );
+
+ $pass_results = $this->results_factory->getPassResultsFor(
+ $this->object,
+ $active_id,
+ $pass,
+ true
+ );
+
+ $table = $this->results_presentation_factory->getPassResultsPresentationTable(
+ $pass_results,
+ $title
+ );
+
+ $tpl->setVariable("LIST_OF_ANSWERS", $table->render());
+
+ $this->tpl->addCss(ilObjStyleSheet::getContentStylePath(0));
+
+ $this->tpl->setContent(
+ $tpl->get()
+ );
}
public function outUserResultsOverview()
diff --git a/Modules/Test/classes/class.ilTestNavigationToolbarGUI.php b/Modules/Test/classes/class.ilTestNavigationToolbarGUI.php
index 17a6bd9cdd3d..2ea7bf415e02 100644
--- a/Modules/Test/classes/class.ilTestNavigationToolbarGUI.php
+++ b/Modules/Test/classes/class.ilTestNavigationToolbarGUI.php
@@ -28,71 +28,21 @@
*/
class ilTestNavigationToolbarGUI extends ilToolbarGUI
{
- /**
- * @var ilCtrl
- */
- protected $ctrl;
-
- /**
- * @var ilTestPlayerAbstractGUI
- */
- protected $playerGUI;
-
- /**
- * @var bool
- */
- private $suspendTestButtonEnabled = false;
-
- /**
- * @var bool
- */
- private $questionListButtonEnabled = false;
-
- /**
- * @var bool
- */
- private $questionTreeButtonEnabled = false;
-
+ private bool $suspendTestButtonEnabled = false;
private bool $questionTreeVisible = false;
-
- /**
- * @var bool
- */
- private $questionSelectionButtonEnabled = false;
-
- /**
- * @var bool
- */
- private $finishTestButtonEnabled = false;
-
- /**
- * @var string
- */
- private $finishTestCommand = '';
-
- /**
- * @var bool
- */
- private $finishTestButtonPrimary = false;
-
- /**
- * @var bool
- */
- private $disabledStateEnabled = false;
+ private bool $questionSelectionButtonEnabled = false;
+ private bool $finishTestButtonEnabled = false;
+ private string $finishTestCommand = '';
+ private bool $finishTestButtonPrimary = false;
+ private bool $disabledStateEnabled = false;
private bool $user_has_attempts_left = true;
protected ?Interruptive $finish_test_modal = null;
+ protected bool $user_pass_overview_button_enabled = false;
- /**
- * @param ilCtrl $ctrl
- * @param ilLanguage $lng
- * @param ilTestPlayerAbstractGUI $playerGUI
- */
- public function __construct(ilCtrl $ctrl, ilLanguage $lng, ilTestPlayerAbstractGUI $playerGUI)
- {
- $this->ctrl = $ctrl;
- $this->lng = $lng;
- $this->playerGUI = $playerGUI;
-
+ public function __construct(
+ protected ilCtrl $ctrl,
+ protected ilTestPlayerAbstractGUI $playerGUI
+ ) {
parent::__construct();
}
@@ -125,33 +75,17 @@ public function setSuspendTestButtonEnabled($suspendTestButtonEnabled)
/**
* @return boolean
*/
- public function isQuestionListButtonEnabled(): bool
+ public function isUserPassOverviewEnabled(): bool
{
- return $this->questionListButtonEnabled;
+ return $this->user_pass_overview_button_enabled;
}
/**
* @param boolean $questionListButtonEnabled
*/
- public function setQuestionListButtonEnabled($questionListButtonEnabled)
- {
- $this->questionListButtonEnabled = $questionListButtonEnabled;
- }
-
- /**
- * @return boolean
- */
- public function isQuestionTreeButtonEnabled(): bool
- {
- return $this->questionTreeButtonEnabled;
- }
-
- /**
- * @param boolean $questionTreeButtonEnabled
- */
- public function setQuestionTreeButtonEnabled($questionTreeButtonEnabled)
+ public function setUserPassOverviewEnabled(bool $user_pass_overview_button_enabled)
{
- $this->questionTreeButtonEnabled = $questionTreeButtonEnabled;
+ $this->user_pass_overview_button_enabled = $user_pass_overview_button_enabled;
}
/**
@@ -249,12 +183,8 @@ public function setDisabledStateEnabled($disabledStateEnabled)
public function build()
{
- if ($this->isQuestionTreeButtonEnabled()) {
- $this->addQuestionTreeButton();
- }
-
- if ($this->isQuestionListButtonEnabled()) {
- $this->addQuestionListButton();
+ if ($this->isUserPassOverviewEnabled()) {
+ $this->addPassOverviewButton();
}
if ($this->isQuestionSelectionButtonEnabled()) {
@@ -287,7 +217,7 @@ private function addSuspendTestButton()
$this->addComponent($button);
}
- private function addQuestionListButton()
+ private function addPassOverviewButton()
{
$button = $this->ui->factory()->button()->standard(
$this->lng->txt('question_summary_btn'),
@@ -305,21 +235,6 @@ private function addQuestionSelectionButton()
$this->addComponent($button);
}
- private function addQuestionTreeButton()
- {
- if ($this->isQuestionTreeVisible()) {
- $btn_cap = $this->lng->txt('tst_hide_side_list');
- } else {
- $btn_cap = $this->lng->txt('tst_show_side_list');
- }
-
- $button = $this->ui->factory()->button()->standard(
- $btn_cap,
- $this->ctrl->getLinkTarget($this->playerGUI, ilTestPlayerCommands::TOGGLE_SIDE_LIST)
- );
- $this->addComponent($button);
- }
-
private function addFinishTestButton(): void
{
if ($this->userHasAttemptsLeft()) {
diff --git a/Modules/Test/classes/class.ilTestOutputGUI.php b/Modules/Test/classes/class.ilTestOutputGUI.php
index 7eedd80e3e87..49ba06b4e3e8 100755
--- a/Modules/Test/classes/class.ilTestOutputGUI.php
+++ b/Modules/Test/classes/class.ilTestOutputGUI.php
@@ -55,23 +55,6 @@ public function executeCommand()
$this->initAssessmentSettings();
- $this->global_screen->tool()->context()->current()->addAdditionalData(
- ilTestPlayerLayoutProvider::TEST_PLAYER_KIOSK_MODE_ENABLED,
- $this->object->getKioskMode()
- );
- $this->global_screen->tool()->context()->current()->addAdditionalData(
- ilTestPlayerLayoutProvider::TEST_PLAYER_TITLE,
- $this->object->getTitle()
- );
- $instance_name = $this->settings->get('short_inst_name') ?? '';
- if (trim($instance_name) === '') {
- $instance_name = 'ILIAS';
- }
- $this->global_screen->tool()->context()->current()->addAdditionalData(
- ilTestPlayerLayoutProvider::TEST_PLAYER_SHORT_TITLE,
- $instance_name
- );
-
$testSessionFactory = new ilTestSessionFactory($this->object, $this->db, $this->user);
$this->test_session = $testSessionFactory->getSession($this->testrequest->int('active_id'));
@@ -92,6 +75,29 @@ public function executeCommand()
$this->handlePasswordProtectionRedirect();
+
+ $instance_name = $this->settings->get('short_inst_name') ?? '';
+ if (trim($instance_name) === '') {
+ $instance_name = 'ILIAS';
+ }
+ $this->global_screen->tool()->context()->current()->addAdditionalData(
+ ilTestPlayerLayoutProvider::TEST_PLAYER_SHORT_TITLE,
+ $instance_name
+ );
+ $this->global_screen->tool()->context()->current()->addAdditionalData(
+ ilTestPlayerLayoutProvider::TEST_PLAYER_KIOSK_MODE_ENABLED,
+ $this->object->getKioskMode()
+ );
+ $this->global_screen->tool()->context()->current()->addAdditionalData(
+ ilTestPlayerLayoutProvider::TEST_PLAYER_VIEW_TITLE,
+ $this->object->getTitle()
+ );
+ $this->global_screen->tool()->context()->current()->addAdditionalData(
+ ilTestPlayerLayoutProvider::TEST_PLAYER_TITLE,
+ $this->getTestPlayerTitle()
+ );
+
+
$cmd = $this->getCommand($cmd);
switch ($next_class) {
@@ -948,4 +954,29 @@ protected function handlePrimaryButton(ilTestNavigationToolbarGUI $navigationToo
return $isNextPrimary;
}
+
+ protected function getTestPlayerTitle(): string
+ {
+ $test_title = $this->object->getShowKioskModeTitle() ? $this->object->getTitle() : '';
+ $user_name = $this->object->getShowKioskModeParticipant() ? $this->user->getFullname() : '';
+ $exam_id = '';
+ if ($this->object->isShowExamIdInTestPassEnabled()) {
+ $exam_id = $this->lng->txt("exam_id")
+ . ' '
+ . ilObjTest::buildExamId(
+ $this->test_session->getActiveId(),
+ $this->test_session->getPass(),
+ $this->object->getId()
+ );
+ }
+
+ $layout = $this->ui_factory->layout()->alignment()->vertical(
+ $this->ui_factory->legacy($test_title),
+ $this->ui_factory->layout()->alignment()->horizontal()->dynamicallyDistributed(
+ $this->ui_factory->legacy($user_name),
+ $this->ui_factory->legacy($exam_id)
+ )
+ );
+ return $this->ui_renderer->render($layout);
+ }
}
diff --git a/Modules/Test/classes/class.ilTestPasswordChecker.php b/Modules/Test/classes/class.ilTestPasswordChecker.php
index 82a1e7f56269..0eb9d772b1a1 100644
--- a/Modules/Test/classes/class.ilTestPasswordChecker.php
+++ b/Modules/Test/classes/class.ilTestPasswordChecker.php
@@ -56,19 +56,11 @@ public function __construct(ilRbacSystem $rbacsystem, ilObjUser $user, ilObjTest
public function isPasswordProtectionPageRedirectRequired(): bool
{
- if (!$this->isTestPasswordEnabled()) {
- return false;
- }
-
- if ($this->isPrivilegedParticipant()) {
- return false;
- }
-
- if ($this->isUserEnteredPasswordCorrect()) {
- return false;
- }
-
- return true;
+ return (
+ $this->isTestPasswordEnabled()
+ && !$this->isPrivilegedParticipant()
+ && !$this->isUserEnteredPasswordCorrect()
+ );
}
protected function isTestPasswordEnabled(): bool
diff --git a/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php b/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php
index 3e44a4c5c161..b8f97de33f0f 100755
--- a/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php
+++ b/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php
@@ -44,6 +44,7 @@ abstract class ilTestPlayerAbstractGUI extends ilTestServiceGUI
public bool $maxProcessingTimeReached;
public bool $endingTimeReached;
+ public int $ref_id;
protected ilTestPasswordChecker $passwordChecker;
protected ilTestProcessLocker $processLocker;
@@ -612,13 +613,6 @@ protected function submitIntermediateSolutionCmd()
$this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
}
- public function toggleSideListCmd(): void
- {
- $show_side_list = $this->user->getPref('side_list_of_questions');
- $this->user->writePref('side_list_of_questions', (string) !$show_side_list);
- $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
- }
-
protected function markQuestionAndSaveIntermediateCmd(): void
{
$this->handleIntermediateSubmit();
@@ -812,45 +806,6 @@ public function showFinalStatementCmd()
$this->tpl->setVariable($this->getContentBlockName(), $template->get());
}
- public function getKioskHead(): string
- {
- /**
- * this is an abomination for release_8 + release_9!
- * @todo Implement proper "kiosk-handling" for ILIAS 10.
- */
- $this->tpl->addCSS('Modules/Test/templates/default/test_kiosk_header.css');
- //end of hack
-
- $template = new ilTemplate('tpl.il_as_tst_kiosk_head.html', true, true, 'Modules/Test');
- if ($this->object->getShowKioskModeTitle()) {
- $template->setCurrentBlock("kiosk_show_title");
- $template->setVariable("TEST_TITLE", $this->object->getTitle());
- $template->parseCurrentBlock();
- }
- if ($this->object->getShowKioskModeParticipant()) {
- $template->setCurrentBlock("kiosk_show_participant");
- $template->setVariable("PARTICIPANT_NAME_TXT", $this->lng->txt("login_as"));
- $template->setVariable("PARTICIPANT_NAME", $this->user->getFullname());
- $template->setVariable("PARTICIPANT_LOGIN", $this->user->getLogin());
- $template->setVariable("PARTICIPANT_MATRICULATION", $this->user->getMatriculation());
- $template->setVariable("PARTICIPANT_EMAIL", $this->user->getEmail());
- $template->parseCurrentBlock();
- }
- if ($this->object->isShowExamIdInTestPassEnabled()) {
- $exam_id = ilObjTest::buildExamId(
- $this->test_session->getActiveId(),
- $this->test_session->getPass(),
- $this->object->getId()
- );
-
- $template->setCurrentBlock("kiosk_show_exam_id");
- $template->setVariable("EXAM_ID_TXT", $this->lng->txt("exam_id"));
- $template->setVariable("EXAM_ID", $exam_id);
- $template->parseCurrentBlock();
- }
- return $template->get();
- }
-
protected function prepareTestPage($presentationMode, $sequenceElement, $questionId)
{
$this->navigation_history->addItem(
@@ -879,12 +834,9 @@ protected function prepareTestPage($presentationMode, $sequenceElement, $questio
return;
}
- if ($this->object->getKioskMode()) {
- $this->populateKioskHead();
- }
-
$this->tpl->setVariable("TEST_ID", (string) $this->object->getTestId());
$this->tpl->setVariable("LOGIN", $this->user->getLogin());
+
$this->tpl->setVariable("SEQ_ID", $sequenceElement);
$this->tpl->setVariable("QUEST_ID", $questionId);
@@ -1282,21 +1234,48 @@ public function checkWorkingTimeCmd(): void
protected function showSideList($current_sequence_element): void
{
- $side_list_active = $this->user->getPref('side_list_of_questions');
+ $questionSummaryData = $this->service->getQuestionSummaryData($this->testSequence, false);
+ $questions = [];
+ $active = 0;
- if (!$side_list_active) {
- return;
+ foreach ($questionSummaryData as $idx => $row) {
+ $title = ilLegacyFormElementsUtil::prepareFormOutput($row['title']);
+ if (strlen($row['description'])) {
+ $description = " title=\"" . htmlspecialchars($row['description']) . "\" ";
+ } else {
+ $description = "";
+ }
+
+ if (!$row['disabled']) {
+ $this->ctrl->setParameter($this, 'pmode', '');
+ $this->ctrl->setParameter($this, 'sequence', $row['sequence']);
+ $action = $this->ctrl->getLinkTarget($this, ilTestPlayerCommands::SHOW_QUESTION);
+ $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
+ $this->ctrl->setParameter($this, 'sequence', $this->getCurrentSequenceElement($current_sequence_element));
+ }
+
+ $status = ILIAS\UI\Component\Listing\Workflow\Step::NOT_STARTED;
+
+ if ($row['worked_through'] || $row['isAnswered']) {
+ $status = ILIAS\UI\Component\Listing\Workflow\Step::IN_PROGRESS;
+ }
+
+ $questions[] = $this->ui_factory->listing()->workflow()
+ ->step($title, $description, $action)
+ ->withStatus($status);
+ $active = $row['sequence'] == $current_sequence_element ? $idx : $active;
}
- $question_summary_data = $this->service->getQuestionSummaryData($this->testSequence, false);
+ $question_listing = $this->ui_factory->listing()->workflow()->linear(
+ $this->lng->txt('mainbar_button_label_questionlist'),
+ $questions
+ )->withActive($active);
+
- $question_side_list_gui = new ilTestQuestionSideListGUI($this->ctrl, $this->lng);
- $question_side_list_gui->setTargetGUI($this);
- $question_side_list_gui->setQuestionSummaryData($question_summary_data);
- $question_side_list_gui->setCurrentSequenceElement($current_sequence_element);
- $question_side_list_gui->setCurrentPresentationMode(ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
- $question_side_list_gui->setDisabled(false);
- $this->tpl->setVariable('LIST_OF_QUESTIONS', $question_side_list_gui->getHTML());
+ $this->global_screen->tool()->context()->current()->addAdditionalData(
+ ilTestPlayerLayoutProvider::TEST_PLAYER_QUESTIONLIST,
+ $question_listing
+ );
}
abstract protected function isQuestionSummaryFinishTestButtonRequired();
@@ -1327,16 +1306,6 @@ public function outQuestionSummaryCmd(
$this->tpl->setOnScreenMessage('failure', $this->lng->txt('not_all_obligations_answered'));
}
- if ($this->object->getKioskMode() && $fullpage) {
- $head = $this->getKioskHead();
- if (strlen($head)) {
- $this->tpl->setCurrentBlock("kiosk_options");
- $this->tpl->setVariable("KIOSK_HEAD", $head);
- $this->tpl->parseCurrentBlock();
- }
- }
-
-
$active_id = $this->test_session->getActiveId();
$questionSummaryData = $this->service->getQuestionSummaryData($this->testSequence, $obligationsFilter);
@@ -1583,10 +1552,6 @@ protected function prepareSummaryPage()
'tpl.il_as_tst_question_summary.html',
'Modules/Test'
);
-
- if ($this->object->getKioskMode()) {
- $this->populateKioskHead();
- }
}
protected function initTestPageTemplate()
@@ -1617,17 +1582,6 @@ protected function initTestPageTemplate()
);
}
- protected function populateKioskHead()
- {
- $head = $this->getKioskHead();
-
- if (strlen($head)) {
- $this->tpl->setCurrentBlock("kiosk_options");
- $this->tpl->setVariable("KIOSK_HEAD", $head);
- $this->tpl->parseCurrentBlock();
- }
- }
-
protected function handlePasswordProtectionRedirect()
{
/**
@@ -1769,20 +1723,20 @@ protected function populateHelperGuiContent($helperGui)
protected function getTestNavigationToolbarGUI(): ilTestNavigationToolbarGUI
{
- $navigation_toolbar = new ilTestNavigationToolbarGUI($this->ctrl, $this->lng, $this);
-
+ $navigation_toolbar = new ilTestNavigationToolbarGUI($this->ctrl, $this);
$navigation_toolbar->setSuspendTestButtonEnabled($this->object->getShowCancel());
- $navigation_toolbar->setQuestionTreeButtonEnabled($this->object->getListOfQuestions());
- $navigation_toolbar->setQuestionTreeVisible((bool) $this->user->getPref('side_list_of_questions'));
- $navigation_toolbar->setQuestionListButtonEnabled($this->object->getListOfQuestions());
+ $navigation_toolbar->setUserPassOverviewEnabled($this->object->getUsrPassOverviewEnabled());
$navigation_toolbar->setFinishTestCommand($this->getFinishTestCommand());
-
return $navigation_toolbar;
}
protected function buildReadOnlyStateQuestionNavigationGUI($questionId): ilTestQuestionNavigationGUI
{
- $navigationGUI = new ilTestQuestionNavigationGUI($this->lng);
+ $navigationGUI = new ilTestQuestionNavigationGUI(
+ $this->lng,
+ $this->ui_factory,
+ $this->ui_renderer
+ );
if (!$this->isParticipantsAnswerFixed($questionId)) {
$navigationGUI->setEditSolutionCommand(ilTestPlayerCommands::EDIT_SOLUTION);
@@ -1812,7 +1766,11 @@ protected function buildReadOnlyStateQuestionNavigationGUI($questionId): ilTestQ
protected function buildEditableStateQuestionNavigationGUI($questionId): ilTestQuestionNavigationGUI
{
- $navigationGUI = new ilTestQuestionNavigationGUI($this->lng);
+ $navigationGUI = new ilTestQuestionNavigationGUI(
+ $this->lng,
+ $this->ui_factory,
+ $this->ui_renderer
+ );
if ($this->object->isForceInstantFeedbackEnabled()) {
$navigationGUI->setSubmitSolutionCommand(ilTestPlayerCommands::SUBMIT_SOLUTION);
@@ -2210,7 +2168,7 @@ protected function getQuestionGuiInstance($question_id, $fromCache = true): obje
$question_gui->setPresentationContext(assQuestionGUI::PRESENTATION_CONTEXT_TEST);
$question_gui->object->setObligationsToBeConsidered($this->object->areObligationsEnabled());
$question_gui->populateJavascriptFilesRequiredForWorkForm($tpl);
- $question_gui->object->setShuffler($this->buildQuestionAnswerShuffler(
+ $question_gui->object->setShuffler($this->shuffler->getAnswerShuffleFor(
$question_id,
$this->test_session->getActiveId(),
$this->test_session->getPass()
@@ -2233,9 +2191,7 @@ protected function getQuestionInstance(int $question_id, bool $from_cache = true
if ($from_cache && isset($this->cachedQuestionObjects[$question_id])) {
return $this->cachedQuestionObjects[$question_id];
}
-
$question = assQuestion::instantiateQuestion($question_id);
-
$ass_settings = new ilSetting('assessment');
$process_locker_factory = new ilAssQuestionProcessLockerFactory($ass_settings, $this->db);
@@ -2308,12 +2264,28 @@ protected function populateDiscardSolutionModal()
$tpl->setVariable('CONFIRMATION_TEXT', $this->lng->txt('discard_answer_confirmation'));
- $button = $this->ui_factory->button()->standard($this->lng->txt('discard_answer'), '#');
+ $button = $this->ui_factory->button()->standard($this->lng->txt('discard_answer'), '#')
+ ->withAdditionalOnLoadCode(
+ fn($id) => "document.getElementById('$id').addEventListener(
+ 'click',
+ (event)=>{
+ event.target.name = 'cmd[discardSolution]';
+ event.target.form.requestSubmit(event.target);
+ }
+ )"
+ );
+
$tpl->setCurrentBlock('buttons');
$tpl->setVariable('BUTTON', $this->ui_renderer->render($button));
$tpl->parseCurrentBlock();
- $button = $this->ui_factory->button()->primary($this->lng->txt('cancel'), '#');
+ $button = $this->ui_factory->button()->primary($this->lng->txt('cancel'), '#')
+ ->withAdditionalOnLoadCode(
+ fn($id) => "document.getElementById('$id').addEventListener(
+ 'click',
+ ()=>$('#tst_discard_solution_modal').modal('hide')
+ );"
+ );
$tpl->setCurrentBlock('buttons');
$tpl->setVariable('BUTTON', $this->ui_renderer->render($button));
$tpl->parseCurrentBlock();
diff --git a/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php b/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php
index 34b7b25b8911..ff560c47625e 100644
--- a/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php
+++ b/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php
@@ -18,6 +18,8 @@
declare(strict_types=1);
+use ILIAS\UI\Factory as UIFactory;
+use ILIAS\UI\Renderer as UIRenderer;
use ILIAS\UI\Component\Button\Button;
/**
@@ -33,11 +35,6 @@ class ilTestQuestionNavigationGUI
public const CSS_CLASS_SUBMIT_BUTTONS = 'ilc_qsubmit_Submit';
private \ILIAS\DI\UIServices $ui;
- /**
- * @var ilLanguage
- */
- protected $lng;
-
/**
* @var string
*/
@@ -120,11 +117,13 @@ class ilTestQuestionNavigationGUI
/**
* @param ilLanguage $lng
*/
- public function __construct(ilLanguage $lng)
- {
- $this->lng = $lng;
- global $DIC;
- $this->ui = $DIC->ui();
+
+
+ public function __construct(
+ protected ilLanguage $lng,
+ protected UIFactory $ui_factory,
+ protected UIRenderer $ui_renderer
+ ) {
}
/**
@@ -371,110 +370,57 @@ public function setAnythingRendered()
$this->anythingRendered = true;
}
- // fau: testNav - generate question actions menu
- /**
- * Get the HTML of an actions menu below the title
- * @return string
- */
public function getActionsHTML(): string
{
$tpl = $this->getTemplate('actions');
-
- $actions = new ilGroupedListGUI();
- $actions->setAsDropDown(true, true);
+ $actions = [];
if ($this->getQuestionMarkLinkTarget()) {
- $actions->addEntry(
- $this->getQuestionMarkActionLabel(),
- $this->getQuestionMarkLinkTarget(),
- '',
- '',
- 'ilTestQuestionAction',
- 'tst_mark_question_action'
- );
- $actions->addSeparator();
- }
-
- if ($this->getRevertChangesLinkTarget()) {
- $actions->addEntry(
- $this->lng->txt('tst_revert_changes'),
- $this->getRevertChangesLinkTarget(),
- '',
- '',
- 'ilTestQuestionAction ilTestRevertChangesAction',
- 'tst_revert_changes_action'
- );
- } else {
- $actions->addEntry(
- $this->lng->txt('tst_revert_changes'),
- '#',
- '',
- '',
- 'ilTestQuestionAction ilTestRevertChangesAction disabled',
- 'tst_revert_changes_action'
- );
- }
-
- if ($this->isDiscardSolutionButtonEnabled()) {
- $actions->addEntry(
- $this->lng->txt('discard_answer'),
- '#',
- '',
- '',
- 'ilTestQuestionAction ilTestDiscardSolutionAction',
- 'tst_discard_solution_action'
+ $this->renderActionsIcon(
+ $tpl,
+ $this->getQuestionMarkIconSource(),
+ $this->getQuestionMarkIconLabel(),
+ 'ilTestMarkQuestionIcon'
);
- } else {
- $actions->addEntry(
- $this->lng->txt('discard_answer'),
- '#',
- '',
- '',
- 'ilTestQuestionAction ilTestDiscardSolutionAction disabled',
- 'tst_discard_solution_action'
+ $actions[] = $this->ui_factory->button()->shy(
+ $this->getQuestionMarkActionLabel(),
+ $this->getQuestionMarkLinkTarget()
);
}
if ($this->getSkipQuestionLinkTarget()) {
- $actions->addEntry(
- $this->lng->txt('postpone_question'),
- $this->getSkipQuestionLinkTarget(),
- '',
- '',
- 'ilTestQuestionAction',
- 'tst_skip_question_action'
- );
- } elseif (self::SHOW_DISABLED_COMMANDS) {
- $actions->addEntry(
+ $actions[] = $this->ui_factory->button()->shy(
$this->lng->txt('postpone_question'),
- '#',
- '',
- '',
- 'ilTestQuestionAction disabled',
- 'tst_skip_question_action'
+ $this->getSkipQuestionLinkTarget()
);
}
- if ($this->getQuestionMarkLinkTarget()) {
- $this->renderActionsIcon(
- $tpl,
- $this->getQuestionMarkIconSource(),
- $this->getQuestionMarkIconLabel(),
- 'ilTestMarkQuestionIcon'
- );
+ if ($actions !== []) {
+ $actions[] = $this->ui_factory->divider()->horizontal();
}
- $list = new ilAdvancedSelectionListGUI();
- $list->setSelectionHeaderClass('btn-primary');
- $list->setId('QuestionActions');
- $list->setListTitle($this->lng->txt("actions"));
- $list->setStyle(1);
- $list->setGroupedList($actions);
- $tpl->setVariable('ACTION_MENU', $list->getHTML());
+ $actions[] = $this->ui_factory->button()->shy(
+ $this->lng->txt('tst_revert_changes'),
+ $this->getRevertChangesLinkTarget()
+ )->withUnavailableAction(!$this->getRevertChangesLinkTarget());
+
+ $actions[] = $this->ui_factory->button()->shy(
+ $this->lng->txt('discard_answer'),
+ '#'
+ )
+ ->withUnavailableAction(!$this->isDiscardSolutionButtonEnabled())
+ ->withAdditionalOnLoadCode(
+ fn($id) => "document.getElementById('$id').addEventListener(
+ 'click',
+ ()=>$('#tst_discard_solution_modal').modal('show')
+ )"
+ );
+
+ $list = $this->ui_factory->dropdown()->standard($actions)->withLabel($this->lng->txt("actions"));
+ $tpl->setVariable('ACTION_MENU', $this->ui_renderer->render($list));
return $tpl->get();
}
- // fau.
/**
@@ -498,7 +444,7 @@ public function getHTML(): string
// fau: testNav - skip question (postpone) is moved to the actions menu.
if ($this->getInstantFeedbackCommand()) {
- $this->renderSubmitButton(
+ $this->renderInstantFeedbackButton(
$tpl,
$this->getInstantFeedbackCommand(),
$this->getCheckButtonLabel(),
@@ -642,7 +588,7 @@ private function parseButtonsBlock(ilTemplate $tpl)
private function renderButtonInstance(ilTemplate $tpl, Button $button)
{
$tpl->setCurrentBlock("button_instance");
- $tpl->setVariable("BUTTON_INSTANCE", $this->ui->renderer()->render($button));
+ $tpl->setVariable("BUTTON_INSTANCE", $this->ui_renderer->render($button));
$tpl->parseCurrentBlock();
$this->parseButtonsBlock($tpl);
@@ -655,19 +601,47 @@ private function renderButtonInstance(ilTemplate $tpl, Button $button)
* @param $label
* @param bool|false $primary
*/
- private function renderSubmitButton(ilTemplate $tpl, $command, $label, $primary = false)
- {
- if ($primary) {
- $this->renderButtonInstance(
- $tpl,
- $this->ui->factory()->button()->primary($label, $command)
- );
- } else {
+ private function renderSubmitButton(
+ ilTemplate $tpl,
+ string $command,
+ string $label
+ ): void {
+ $this->renderButtonInstance(
+ $tpl,
+ $this->ui_factory->button()->standard($label, $command)
+ );
+ }
+
+ private function renderInstantFeedbackButton(
+ ilTemplate $tpl,
+ string $command,
+ string $label,
+ bool $is_primary
+ ): void {
+ $on_load_code = $this->getOnLoadCode($command);
+ if ($is_primary) {
$this->renderButtonInstance(
$tpl,
- $this->ui->factory()->button()->standard($label, $command)
+ $this->ui_factory->button()->primary($label, '')->withAdditionalOnLoadCode($on_load_code)
);
+ return;
}
+
+ $this->renderButtonInstance(
+ $tpl,
+ $this->ui_factory->button()->standard($label, '')->withAdditionalOnLoadCode($on_load_code)
+ );
+ }
+
+ private function getOnLoadCode(string $command): Closure
+ {
+ return static function ($id) use ($command): string {
+ return "document.getElementById('$id').addEventListener('click', "
+ . '(e) => {'
+ . " e.target.setAttribute('name', 'cmd[$command]');"
+ . ' e.target.form.requestSubmit(e.target);'
+ . '});';
+ };
}
/**
diff --git a/Modules/Test/classes/class.ilTestQuestionSideListGUI.php b/Modules/Test/classes/class.ilTestQuestionSideListGUI.php
deleted file mode 100644
index 74273e2f24ff..000000000000
--- a/Modules/Test/classes/class.ilTestQuestionSideListGUI.php
+++ /dev/null
@@ -1,271 +0,0 @@
-
- * @version $Id$
- *
- * @package Modules/Test
- */
-class ilTestQuestionSideListGUI
-{
- /**
- * @var ilCtrl
- */
- protected $ctrl;
-
- /**
- * @var ilLanguage
- */
- protected $lng;
-
- /**
- * @var ilTestPlayerAbstractGUI
- */
- private $targetGUI;
-
- /**
- * @var array
- */
- private $questionSummaryData;
-
- /**
- * @var integer
- */
- private $currentSequenceElement;
-
- /**
- * @var string
- */
- private $currentPresentationMode;
-
- /**
- * @var bool
- */
- private $disabled;
-
- /**
- * @param ilCtrl $ctrl
- * @param ilLanguage $lng
- */
- public function __construct(ilCtrl $ctrl, ilLanguage $lng)
- {
- $this->ctrl = $ctrl;
- $this->lng = $lng;
-
- $this->questionSummaryData = array();
- $this->currentSequenceElement = null;
- $this->disabled = false;
- }
-
- /**
- * @return ilTestPlayerAbstractGUI
- */
- public function getTargetGUI(): ilTestPlayerAbstractGUI
- {
- return $this->targetGUI;
- }
-
- /**
- * @param ilTestPlayerAbstractGUI $targetGUI
- */
- public function setTargetGUI($targetGUI)
- {
- $this->targetGUI = $targetGUI;
- }
-
- /**
- * @return array
- */
- public function getQuestionSummaryData(): array
- {
- return $this->questionSummaryData;
- }
-
- /**
- * @param array $questionSummaryData
- */
- public function setQuestionSummaryData($questionSummaryData)
- {
- $this->questionSummaryData = $questionSummaryData;
- }
-
- /**
- * @return int
- */
- public function getCurrentSequenceElement(): ?int
- {
- return $this->currentSequenceElement;
- }
-
- /**
- * @param int $currentSequenceElement
- */
- public function setCurrentSequenceElement($currentSequenceElement)
- {
- $this->currentSequenceElement = $currentSequenceElement;
- }
-
- /**
- * @return string
- */
- public function getCurrentPresentationMode(): string
- {
- return $this->currentPresentationMode;
- }
-
- /**
- * @param string $currentPresentationMode
- */
- public function setCurrentPresentationMode($currentPresentationMode)
- {
- $this->currentPresentationMode = $currentPresentationMode;
- }
-
- /**
- * @return boolean
- */
- public function isDisabled(): bool
- {
- return $this->disabled;
- }
-
- /**
- * @param boolean $disabled
- */
- public function setDisabled($disabled)
- {
- $this->disabled = $disabled;
- }
-
- /**
- * @return ilPanelGUI
- */
- private function buildPanel(): ilPanelGUI
- {
- $panel = ilPanelGUI::getInstance();
- $panel->setHeadingStyle(ilPanelGUI::HEADING_STYLE_SUBHEADING);
- $panel->setPanelStyle(ilPanelGUI::PANEL_STYLE_SECONDARY);
- $panel->setHeading($this->lng->txt('list_of_questions'));
- return $panel;
- }
-
- /**
- * @return string
- */
- private function renderList(): string
- {
- $tpl = new ilTemplate('tpl.il_as_tst_list_of_questions_short.html', true, true, 'Modules/Test');
-
- foreach ($this->getQuestionSummaryData() as $row) {
- $title = ilLegacyFormElementsUtil::prepareFormOutput($row['title']);
-
- if (strlen($row['description'])) {
- $description = " title=\"" . htmlspecialchars($row['description']) . "\" ";
- } else {
- $description = "";
- }
-
- $active = ($row['sequence'] == $this->getCurrentSequenceElement()) ? ' active' : '';
-
- $class = (
- $row['worked_through'] ? 'answered' . $active : 'unanswered' . $active
- );
-
- $headerclass = ($row['sequence'] == $this->getCurrentSequenceElement()) ? 'bold' : '';
-
- if ($row['marked']) {
- $tpl->setCurrentBlock("mark_icon");
- $tpl->setVariable("ICON_SRC", ilUtil::getImagePath('object/marked.svg'));
- $tpl->setVariable("ICON_TEXT", $this->lng->txt('tst_question_marked'));
- $tpl->setVariable("ICON_CLASS", 'ilTestMarkQuestionIcon');
- $tpl->parseCurrentBlock();
- }
-
- if ($this->isDisabled() || $row['disabled']) {
- $tpl->setCurrentBlock('disabled_entry');
- $tpl->setVariable('CLASS', $class);
- $tpl->setVariable('HEADERCLASS', $headerclass);
- $tpl->setVariable('ITEM', $title);
- $tpl->setVariable('DESCRIPTION', $description);
- $tpl->parseCurrentBlock();
- } else {
- // fau: testNav - show mark icon in side list
- // fau.
- $tpl->setCurrentBlock('linked_entry');
- $tpl->setVariable('HREF', $this->buildLink($row['sequence']));
- $tpl->setVariable('NEXTCMD', ilTestPlayerCommands::SHOW_QUESTION);
- $tpl->setVariable('NEXTSEQ', $row['sequence']);
- $tpl->setVariable('HEADERCLASS', $headerclass);
- $tpl->setVariable('CLASS', $class);
- $tpl->setVariable('ITEM', $title);
- $tpl->setVariable("DESCRIPTION", $description);
- $tpl->parseCurrentBlock();
- }
-
- $tpl->setCurrentBlock('item');
- }
-
- return $tpl->get();
- }
-
- /**
- * @return string
- */
- public function getHTML(): string
- {
- $panel = $this->buildPanel();
- $panel->setBody($this->renderList());
- return $panel->getHTML();
- }
-
- /**
- * @param $row
- * @return string
- */
- private function buildLink($sequenceElement): string
- {
- $this->ctrl->setParameter(
- $this->getTargetGUI(),
- 'pmode',
- ''
- );
-
- $this->ctrl->setParameter(
- $this->getTargetGUI(),
- 'sequence',
- $sequenceElement
- );
-
- $href = $this->ctrl->getLinkTarget($this->getTargetGUI(), ilTestPlayerCommands::SHOW_QUESTION);
-
- $this->ctrl->setParameter(
- $this->getTargetGUI(),
- 'pmode',
- $this->getCurrentPresentationMode()
- );
- $this->ctrl->setParameter(
- $this->getTargetGUI(),
- 'sequence',
- $this->getCurrentSequenceElement()
- );
- return $href;
- }
-}
diff --git a/Modules/Test/classes/class.ilTestRandomQuestionSetConfigGUI.php b/Modules/Test/classes/class.ilTestRandomQuestionSetConfigGUI.php
index 0d6fbbd7db51..71ea800bb033 100644
--- a/Modules/Test/classes/class.ilTestRandomQuestionSetConfigGUI.php
+++ b/Modules/Test/classes/class.ilTestRandomQuestionSetConfigGUI.php
@@ -752,20 +752,20 @@ private function getSourcePoolDefinitionByAvailableQuestionPoolId($poolId): ilTe
*/
protected function fetchPoolIdsParameter(): array
{
- $poolIds = [];
+ $pool_ids = [];
if ($this->testrequest->isset('derive_pool_ids') && is_array($this->testrequest->raw('derive_pool_ids'))) {
- $poolIds = [];
+ $pool_ids = [];
- foreach ($this->testrequest->raw('derive_pool_ids') as $poolId) {
- $poolIds[] = (int) $poolId;
+ foreach ($this->testrequest->raw('derive_pool_ids') as $pool_id) {
+ $pool_ids[] = (int) $pool_id;
}
} elseif ($this->testrequest->isset('derive_pool_ids') && preg_match('/^\d+(\:\d+)*$/', $this->testrequest->raw('derive_pool_ids'))) {
- $poolIds = explode(':', $this->testrequest->raw('derive_pool_ids'));
+ $pool_ids = explode(':', $this->testrequest->raw('derive_pool_ids'));
} elseif ($this->testrequest->isset('derive_pool_id') && (int) $this->testrequest->raw('derive_pool_id')) {
- $poolIds = [(int) $this->testrequest->raw('derive_pool_id')];
+ $pool_ids = [(int) $this->testrequest->raw('derive_pool_id')];
}
- return $poolIds;
+ return $pool_ids;
}
protected function fetchTargetRefParameter(): ?int
@@ -799,29 +799,34 @@ private function selectPoolDerivationTargetCmd(): void
private function deriveNewPoolsCmd(): void
{
- $poolIds = $this->fetchPoolIdsParameter();
- $targetRef = $this->fetchTargetRefParameter();
+ $pool_ids = $this->fetchPoolIdsParameter();
+ $target_ref = $this->fetchTargetRefParameter();
+ if (!$this->access->checkAccess('write', '', $target_ref)) {
+ $this->tpl->setOnScreenMessage('failure', $this->lng->txt("no_permission"), true);
+ $this->ctrl->setParameterByClass(ilObjTestGUI::class, 'ref_id', $this->test_obj->getRefId());
+ $this->ctrl->redirectByClass(ilObjTestGUI::class);
+ }
- if (count($poolIds)) {
- foreach ($poolIds as $poolId) {
- $lostPool = $this->sourcePoolDefinitionList->getLostPool($poolId);
+ if ($pool_ids !== []) {
+ foreach ($pool_ids as $pool_id) {
+ $lost_pool = $this->sourcePoolDefinitionList->getLostPool($pool_id);
$deriver = new ilTestRandomQuestionSetPoolDeriver($this->db, $this->component_repository, $this->test_obj);
$deriver->setSourcePoolDefinitionList($this->sourcePoolDefinitionList);
- $deriver->setTargetContainerRef($targetRef);
+ $deriver->setTargetContainerRef($target_ref);
$deriver->setOwnerId($this->user->getId());
- $newPool = $deriver->derive($lostPool);
+ $new_pool = $deriver->derive($lost_pool);
- $srcPoolDefinition = $this->sourcePoolDefinitionList->getDefinitionBySourcePoolId($newPool->getId());
- $srcPoolDefinition->setPoolTitle($newPool->getTitle());
- $srcPoolDefinition->setPoolPath($this->questionSetConfig->getQuestionPoolPathString($newPool->getId()));
- $srcPoolDefinition->setPoolRefId($this->questionSetConfig->getFirstQuestionPoolRefIdByObjId($newPool->getId()));
+ $srcPoolDefinition = $this->sourcePoolDefinitionList->getDefinitionBySourcePoolId($new_pool->getId());
+ $srcPoolDefinition->setPoolTitle($new_pool->getTitle());
+ $srcPoolDefinition->setPoolPath($this->questionSetConfig->getQuestionPoolPathString($new_pool->getId()));
+ $srcPoolDefinition->setPoolRefId($this->questionSetConfig->getFirstQuestionPoolRefIdByObjId($new_pool->getId()));
$srcPoolDefinition->saveToDb();
ilTestRandomQuestionSetStagingPoolQuestionList::updateSourceQuestionPoolId(
$this->test_obj->getTestId(),
- $lostPool->getId(),
- $newPool->getId()
+ $lost_pool->getId(),
+ $new_pool->getId()
);
}
diff --git a/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinition.php b/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinition.php
index ee38fc4d1dda..aae7d17819ee 100644
--- a/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinition.php
+++ b/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinition.php
@@ -451,16 +451,10 @@ private function updateDbRecord($testId)
'pool_title' => array('text', $this->getPoolTitle()),
'pool_path' => array('text', $this->getPoolPath()),
'pool_quest_count' => array('integer', $this->getPoolQuestionCount()),
- // fau: taxFilter/typeFilter - use new db fields
- #'origin_tax_fi' => array('integer', $this->getOriginalFilterTaxId()),
- #'origin_node_fi' => array('integer', $this->getOriginalFilterTaxNodeId()),
- #'mapped_tax_fi' => array('integer', $this->getMappedFilterTaxId()),
- #'mapped_node_fi' => array('integer', $this->getMappedFilterTaxNodeId()),
'origin_tax_filter' => array('text', $this->getOriginalTaxonomyFilterForDbValue()),
'mapped_tax_filter' => array('text', $this->getMappedTaxonomyFilterForDbValue()),
'type_filter' => array('text', $this->getTypeFilterForDbValue()),
'lifecycle_filter' => array('text', $this->getLifecycleFilterForDbValue()),
- // fau.
'quest_amount' => array('integer', $this->getQuestionAmount()),
'sequence_pos' => array('integer', $this->getSequencePosition())
],
@@ -485,16 +479,10 @@ private function insertDbRecord(int $test_id): void
'pool_title' => array('text', $this->getPoolTitle()),
'pool_path' => array('text', $this->getPoolPath()),
'pool_quest_count' => array('integer', $this->getPoolQuestionCount()),
- // fau: taxFilter/typeFilter - use new db fields
- #'origin_tax_fi' => array('integer', $this->getOriginalFilterTaxId()),
- #'origin_node_fi' => array('integer', $this->getOriginalFilterTaxNodeId()),
- #'mapped_tax_fi' => array('integer', $this->getMappedFilterTaxId()),
- #'mapped_node_fi' => array('integer', $this->getMappedFilterTaxNodeId()),
'origin_tax_filter' => array('text', $this->getOriginalTaxonomyFilterForDbValue()),
'mapped_tax_filter' => array('text', $this->getMappedTaxonomyFilterForDbValue()),
'type_filter' => array('text', $this->getTypeFilterForDbValue()),
'lifecycle_filter' => array('text', $this->getLifecycleFilterForDbValue()),
- // fau.
'quest_amount' => array('integer', $this->getQuestionAmount()),
'sequence_pos' => array('integer', $this->getSequencePosition())
]);
diff --git a/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php b/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php
index c63f78671044..73cbc59a5b5b 100644
--- a/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php
+++ b/Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php
@@ -176,24 +176,24 @@ public function loadDefinitions()
$trashedPools[$trashedPool->getId()] = $trashedPool;
}
- if (!$this->isLostPool($row['pool_id'])) {
- if (!$row['pool_id']) {
- $lostPool = new ilTestRandomQuestionSetNonAvailablePool();
- $lostPool->assignDbRow($row);
+ if (!$this->isLostPool($row['pool_id'])
+ && !$row['pool_id']) {
+ $lostPool = new ilTestRandomQuestionSetNonAvailablePool();
+ $lostPool->assignDbRow($row);
- $lostPool->setUnavailabilityStatus(
- ilTestRandomQuestionSetNonAvailablePool::UNAVAILABILITY_STATUS_LOST
- );
+ $lostPool->setUnavailabilityStatus(
+ ilTestRandomQuestionSetNonAvailablePool::UNAVAILABILITY_STATUS_LOST
+ );
- $this->addLostPool($lostPool);
+ $this->addLostPool($lostPool);
- if (isset($trashedPools[$lostPool->getId()])) {
- unset($trashedPools[$lostPool->getId()]);
- }
+ if (isset($trashedPools[$lostPool->getId()])) {
+ unset($trashedPools[$lostPool->getId()]);
}
}
- if ($sourcePoolDefinition->getPoolTitle() !== $row['actual_pool_title']) {
+ if (isset($row['actual_pool_title'])
+ && $sourcePoolDefinition->getPoolTitle() !== $row['actual_pool_title']) {
$sourcePoolDefinition->setPoolTitle($row['actual_pool_title']);
$sourcePoolDefinition->saveToDb();
}
diff --git a/Modules/Test/classes/class.ilTestServiceGUI.php b/Modules/Test/classes/class.ilTestServiceGUI.php
index bbe7f8f4616f..3dc21286e285 100755
--- a/Modules/Test/classes/class.ilTestServiceGUI.php
+++ b/Modules/Test/classes/class.ilTestServiceGUI.php
@@ -24,7 +24,6 @@
use ILIAS\GlobalScreen\Services as GlobalScreenServices;
use ILIAS\Refinery\Factory as Refinery;
use ILIAS\Refinery\Transformation;
-use ILIAS\Refinery\Random\Seed\GivenSeed;
use ILIAS\Test\InternalRequestService;
use ILIAS\HTTP\Wrapper\ArrayBasedRequestWrapper;
use ILIAS\DI\LoggingServices;
@@ -78,6 +77,9 @@ class ilTestServiceGUI
protected UIFactory $ui_factory;
protected UIRenderer $ui_renderer;
protected SkillService $skills_service;
+ protected ilTestShuffler $shuffler;
+ protected ilTestResultsFactory $results_factory;
+ protected ilTestResultsPresentationFactory $results_presentation_factory;
protected ILIAS $ilias;
protected ilSetting $settings;
@@ -140,19 +142,26 @@ public function __construct(
$this->rbac_system = $DIC['rbacsystem'];
$this->obj_cache = $DIC['ilObjDataCache'];
$this->skills_service = $DIC->skills();
- $this->participant_access_filter = new ilTestParticipantAccessFilterFactory($DIC['ilAccess']);
$this->post_wrapper = $DIC->http()->wrapper()->post();
- $this->testrequest = $DIC->test()->internal()->request();
+
$this->questioninfo = $DIC->testQuestionPool()->questionInfo();
$this->service = new ilTestService($this->object, $this->db, $this->questioninfo);
- $this->lng->loadLanguageModule('cert');
+ $this->lng->loadLanguageModule('cert');
$this->ref_id = $this->object->getRefId();
- $this->testrequest = $DIC->test()->internal()->request();
$this->testSessionFactory = new ilTestSessionFactory($this->object, $this->db, $this->user);
$this->testSequenceFactory = new ilTestSequenceFactory($this->object, $this->db, $this->questioninfo);
-
$this->objective_oriented_container = null;
+
+ $this->ui_factory = $DIC['ui.factory'];
+ $this->ui_renderer = $DIC['ui.renderer'];
+
+ $local_dic = $object->getLocalDIC();
+ $this->testrequest = $local_dic['request.internal'];
+ $this->participant_access_filter = $local_dic['participantAccessFilterFactory'];
+ $this->shuffler = $local_dic['shuffler'];
+ $this->results_factory = $local_dic['factory.results'];
+ $this->results_presentation_factory = $local_dic['factory.results_presentation'];
}
public function setParticipantData(ilTestParticipantData $participantData): void
@@ -358,7 +367,8 @@ public function getPassListOfAnswers(
&& is_numeric($question_id)) {
$maintemplate->setCurrentBlock("printview_question");
$question_gui = $this->object->createQuestionGUI("", $question_id);
- $question_gui->object->setShuffler($this->buildQuestionAnswerShuffler(
+
+ $question_gui->object->setShuffler($this->shuffler->getAnswerShuffleFor(
(int) $question_id,
(int) $active_id,
(int) $pass
@@ -435,33 +445,6 @@ public function getPassListOfAnswers(
return $maintemplate->get();
}
- protected function buildQuestionAnswerShuffler(
- int $question_id,
- int $active_id,
- int $pass_id
- ): Transformation {
- $fixedSeed = $this->buildFixedShufflerSeed($question_id, $pass_id, $active_id);
-
- return $this->refinery->random()->shuffleArray(new GivenSeed($fixedSeed));
- }
-
- protected function buildFixedShufflerSeed(int $question_id, int $pass_id, int $active_id): int
- {
- $seed = ($question_id + $pass_id) * $active_id;
-
- if (is_float($seed) && is_float($seed = $active_id + $pass_id)) {
- $seed = $active_id;
- }
-
- $div = ceil((10 ** (ilTestPlayerAbstractGUI::FIXED_SHUFFLER_SEED_MIN_LENGTH - 1)) / $seed);
-
- if ($div > 1) {
- $seed = $seed * ($div + $seed % 10);
- }
-
- return (int) $seed;
- }
-
/**
* Returns the list of answers of a users test pass and offers a scoring option
*
@@ -675,7 +658,11 @@ public function getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $ac
$invited_user = array_pop($this->object->getInvitedUsers($user_id));
$title_client = '';
- if (isset($invited_user['clientip']) && $invited_user["clientip"] !== '') {
+ if (is_array($invited_user)
+ && array_key_exists('clientip', $invited_user)
+ && is_string($invited_user['clientip'])
+ && trim($invited_user['clientip']) !== ''
+ ) {
$template->setCurrentBlock("client_ip");
$template->setVariable("TXT_CLIENT_IP", $this->lng->txt("client_ip"));
$template->setVariable("VALUE_CLIENT_IP", $invited_user["clientip"]);
diff --git a/Modules/Test/classes/class.ilTestShuffler.php b/Modules/Test/classes/class.ilTestShuffler.php
new file mode 100644
index 000000000000..d0fef441d634
--- /dev/null
+++ b/Modules/Test/classes/class.ilTestShuffler.php
@@ -0,0 +1,60 @@
+buildFixedShufflerSeed($question_id, $pass_id, $active_id);
+ return $this->refinery->random()->shuffleArray(new GivenSeed($fixedSeed));
+ }
+
+ protected function buildFixedShufflerSeed(int $question_id, int $pass_id, int $active_id): int
+ {
+ $seed = ($question_id + $pass_id) * $active_id;
+ if (is_float($seed) && is_float($seed = $active_id + $pass_id)) {
+ $seed = $active_id;
+ }
+
+ $div = ceil((10 ** (self::FIXED_SHUFFLER_SEED_MIN_LENGTH - 1)) / $seed);
+ if ($div > 1) {
+ $seed = $seed * ($div + $seed % 10);
+ }
+ return (int) $seed;
+ }
+}
diff --git a/Modules/Test/classes/tables/class.ilTestPassOverviewTableGUI.php b/Modules/Test/classes/tables/class.ilTestPassOverviewTableGUI.php
index 275f828c46f8..a63f35c386d3 100644
--- a/Modules/Test/classes/tables/class.ilTestPassOverviewTableGUI.php
+++ b/Modules/Test/classes/tables/class.ilTestPassOverviewTableGUI.php
@@ -18,13 +18,16 @@
declare(strict_types=1);
+use ILIAS\UI\Factory as UIFactory;
+use ILIAS\UI\Renderer as UIRenderer;
+
/**
* Class ilTestPassOverviewTableGUI
*/
class ilTestPassOverviewTableGUI extends ilTable2GUI
{
- private \ILIAS\UI\Factory $ui_factory;
- private \ILIAS\UI\Renderer $ui_renderer;
+ private UIFactory $ui_factory;
+ private UIRenderer $ui_renderer;
protected bool $resultPresentationEnabled = false;
protected bool $pdfPresentationEnabled = false;
@@ -266,12 +269,12 @@ private function buildActionsHtml($actions, $pass): string
}
$this->ctrl->setParameter($this->parent_obj, 'pass', $pass);
- $actions = [];
+ $action_links = [];
if (count($actions) > 1) {
foreach ($actions as $cmd => $label) {
- $actions[] = $this->ui_factory->link()->standard($label, $this->ctrl->getLinkTarget($this->parent_obj, $cmd));
+ $action_links[] = $this->ui_factory->link()->standard($label, $this->ctrl->getLinkTarget($this->parent_obj, $cmd));
}
- $dropdown = $this->ui_factory->dropdown()->standard($actions)->withLabel($this->lng->txt('actions'));
+ $dropdown = $this->ui_factory->dropdown()->standard($action_links)->withLabel($this->lng->txt('actions'));
$html = $this->ui_renderer->render($dropdown);
} else {
$cmd = key($actions);
diff --git a/Modules/Test/classes/toolbars/class.ilTestResultsToolbarGUI.php b/Modules/Test/classes/toolbars/class.ilTestResultsToolbarGUI.php
index 7ce95036e3a6..5c63aa43375b 100644
--- a/Modules/Test/classes/toolbars/class.ilTestResultsToolbarGUI.php
+++ b/Modules/Test/classes/toolbars/class.ilTestResultsToolbarGUI.php
@@ -45,7 +45,9 @@ public function build(): void
{
$this->setId('tst_results_toolbar');
- $this->addButton($this->lng->txt('print'), 'javascript:window.print();');
+ $print_button = $this->ui->factory()->button()->standard($this->lng->txt('print'), '')
+ ->withOnLoadCode(fn($id) => "$('#$id').on('click', ()=>{window.print();})");
+ $this->addComponent($print_button);
if ($this->getCertificateLinkTarget() !== null
&& $this->getCertificateLinkTarget() !== '') {
diff --git a/Modules/Test/module.xml b/Modules/Test/module.xml
index 8341dc429c54..f8a37e633b9f 100644
--- a/Modules/Test/module.xml
+++ b/Modules/Test/module.xml
@@ -47,4 +47,7 @@
+
+
+
diff --git a/Modules/Test/templates/default/tpl.il_as_tst_kiosk_head.html b/Modules/Test/templates/default/tpl.il_as_tst_kiosk_head.html
deleted file mode 100644
index 39abcfbf3b4e..000000000000
--- a/Modules/Test/templates/default/tpl.il_as_tst_kiosk_head.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-{TEST_TITLE}
-
-
-
-
-{PARTICIPANT_NAME}
-
-
-
-{EXAM_ID_TXT} {EXAM_ID}
-
-
-
\ No newline at end of file
diff --git a/Modules/Test/templates/default/tpl.il_as_tst_pass_details_overview_participants.html b/Modules/Test/templates/default/tpl.il_as_tst_pass_details_overview_participants.html
index d195f3c6ac2a..1a3108aa34d9 100755
--- a/Modules/Test/templates/default/tpl.il_as_tst_pass_details_overview_participants.html
+++ b/Modules/Test/templates/default/tpl.il_as_tst_pass_details_overview_participants.html
@@ -12,9 +12,10 @@ {TEXT_HEADING}
{TOTAL_RESULT_TEXT}: {TOTAL_RESULT}
-
+
{LIST_OF_ANSWERS}
+
{SIGNATURE}
diff --git a/Modules/Test/test/ScoreSettingsTest.php b/Modules/Test/test/ScoreSettingsTest.php
index 2d69c04a93b2..8bb2d5f274eb 100644
--- a/Modules/Test/test/ScoreSettingsTest.php
+++ b/Modules/Test/test/ScoreSettingsTest.php
@@ -76,13 +76,10 @@ public function testScoreSettingsSummary(): void
public function testScoreSettingsDetails(): void
{
$s = new ilObjTestSettingsResultDetails(-666);
- $this->assertTrue($s->withPrintBestSolutionWithResult(true)->getPrintBestSolutionWithResult());
$this->assertEquals(192, $s->withResultsPresentation(192)->getResultsPresentation(192));
$this->assertTrue($s->withShowExamIdInTestResults(true)->getShowExamIdInTestResults());
$this->assertTrue($s->withShowPassDetails(true)->getShowPassDetails());
$this->assertFalse($s->withShowPassDetails(false)->getShowPassDetails());
- $this->assertTrue($s->withShowSolutionDetails(true)->getShowSolutionDetails());
- $this->assertFalse($s->withShowSolutionDetails(false)->getShowSolutionDetails());
$this->assertTrue($s->withShowSolutionPrintview(true)->getShowSolutionPrintview());
$this->assertFalse($s->withShowSolutionPrintview(false)->getShowSolutionPrintview());
$this->assertTrue($s->withShowSolutionFeedback(true)->getShowSolutionFeedback());
@@ -367,77 +364,55 @@ public function testScoreSettingsSectionDetails(): void
$expected = <<
-