- */
class CertificateTestTemplateDeleteActionTest extends TestCase
{
- public function testDelete(): void
+ public function testDeletionIsDelegatedToWrappedAction(): void
{
- $delete_action = $this->getMockBuilder(\ilCertificateDeleteAction::class)
- ->getMock();
-
+ $delete_action = $this->createMock(\ilCertificateDeleteAction::class);
$delete_action
->expects($this->once())
->method('delete');
- $object_helper = $this->getMockBuilder(\ilCertificateObjectHelper::class)
- ->getMock();
-
- $object = $this->getMockBuilder(\ilObjTest::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $object_helper->method('getInstanceByObjId')
- ->willReturn($object);
-
$action = new CertificateTestTemplateDeleteAction(
$delete_action
);
diff --git a/components/ILIAS/Test/tests/ExportImport/ExportFixedQuestionSetTest.php b/components/ILIAS/Test/tests/ExportImport/ExportFixedQuestionSetTest.php
index cd87aeac6e75..7266ca3cab9d 100755
--- a/components/ILIAS/Test/tests/ExportImport/ExportFixedQuestionSetTest.php
+++ b/components/ILIAS/Test/tests/ExportImport/ExportFixedQuestionSetTest.php
@@ -39,7 +39,7 @@ protected function setUp(): void
$this->addGlobal_resourceStorage();
$this->testObj = new ExportFixedQuestionSet(
- $this->createMock(\ILIAS\Language\Language::class),
+ $this->createMock(\ilLanguage::class),
$this->createMock(\ilDBInterface::class),
$this->createMock(\ilBenchmark::class),
$this->createMock(\ILIAS\Test\Logging\TestLogger::class),
@@ -48,7 +48,8 @@ protected function setUp(): void
$this->createMock(\ILIAS\TestQuestionPool\Questions\GeneralQuestionPropertiesRepository::class),
$this->createMock(\ILIAS\FileDelivery\Services::class),
$this->createMock(\ilObjTest::class),
- $DIC['resource_storage']
+ $DIC['resource_storage'],
+ $DIC['ilUser']
);
}
diff --git a/components/ILIAS/Test/tests/ExportImport/ExportRandomQuestionSetTest.php b/components/ILIAS/Test/tests/ExportImport/ExportRandomQuestionSetTest.php
index 6c10d8527cf0..acb3bbbaffd8 100755
--- a/components/ILIAS/Test/tests/ExportImport/ExportRandomQuestionSetTest.php
+++ b/components/ILIAS/Test/tests/ExportImport/ExportRandomQuestionSetTest.php
@@ -38,7 +38,7 @@ protected function setUp(): void
$this->addGlobal_resourceStorage();
$this->testObj = new ExportRandomQuestionSet(
- $this->createMock(\ILIAS\Language\Language::class),
+ $this->createMock(\ilLanguage::class),
$this->createMock(\ilDBInterface::class),
$this->createmOck(\ilBenchmark::class),
$this->createMock(\ILIAS\Test\Logging\TestLogger::class),
@@ -47,7 +47,8 @@ protected function setUp(): void
$this->createMock(\ILIAS\TestQuestionPool\Questions\GeneralQuestionPropertiesRepository::class),
$this->createMock(\ILIAS\FileDelivery\Services::class),
$this->getTestObjMock(),
- $DIC['resource_storage']
+ $DIC['resource_storage'],
+ $DIC['ilUser']
);
}
diff --git a/components/ILIAS/Test/tests/Scoring/Settings/ScoreSettingsTest.php b/components/ILIAS/Test/tests/Scoring/Settings/ScoreSettingsTest.php
index 88132d15e0fb..c43aa12e1d76 100755
--- a/components/ILIAS/Test/tests/Scoring/Settings/ScoreSettingsTest.php
+++ b/components/ILIAS/Test/tests/Scoring/Settings/ScoreSettingsTest.php
@@ -291,7 +291,7 @@ public function testScoreSettingsSectionSummary(): void
$i1_1_4_1 = $this->getFormWrappedHtml(
'date-time-field-input',
- 'tst_reporting_date*',
+ 'tst_reporting_daterequired_field*',
'
',
@@ -303,7 +303,7 @@ public function testScoreSettingsSectionSummary(): void
$i1_1_4 = $this->getFormWrappedHtml(
'group-field-input',
- 'tst_results_access_date*',
+ 'tst_results_access_daterequired_field*',
$i1_1_4_1,
'tst_results_access_date_desc',
'id_5',
@@ -313,7 +313,7 @@ public function testScoreSettingsSectionSummary(): void
$i1_1 = $this->getFormWrappedHtml(
'switchable-group-field-input',
- 'tst_results_access_setting*',
+ 'tst_results_access_settingrequired_field*',
$i1_1_1 . $i1_1_2 . $i1_1_3 . $i1_1_4,
null,
null,
@@ -441,7 +441,7 @@ public function testScoreSettingsSectionGamification(): void
$fields = $this->getFormWrappedHtml(
'radio-field-input',
- 'tst_highscore_mode*',
+ 'tst_highscore_moderequired_field*',
'
tst_highscore_own_table_description
@@ -460,7 +460,7 @@ public function testScoreSettingsSectionGamification(): void
);
$fields .= $this->getFormWrappedHtml(
'numeric-field-input',
- 'tst_highscore_top_num
*',
+ 'tst_highscore_top_num
required_field*',
'
',
'tst_highscore_top_num_description',
'id_3',
diff --git a/components/ILIAS/Test/tests/Settings/MainSettings/SettingsFinishingTest.php b/components/ILIAS/Test/tests/Settings/MainSettings/SettingsFinishingTest.php
index a7e5401b4168..ecfae3c19ff2 100644
--- a/components/ILIAS/Test/tests/Settings/MainSettings/SettingsFinishingTest.php
+++ b/components/ILIAS/Test/tests/Settings/MainSettings/SettingsFinishingTest.php
@@ -49,18 +49,6 @@ public function testGetAndWithConcludingRemarksEnabled(bool $io): void
$this->assertEquals($io, $settings_finishing->getConcludingRemarksEnabled());
}
- #[\PHPUnit\Framework\Attributes\DataProvider('getAndWithConcludingRemarksTextDataProvider')]
- public function testGetAndWithConcludingRemarksText(?string $io): void
- {
- $settings_finishing = new SettingsFinishing(
- false,
- false,
- $io
- );
-
- $this->assertEquals($io, $settings_finishing->getConcludingRemarksText());
- }
-
public static function getAndWithConcludingRemarksTextDataProvider(): array
{
return [
diff --git a/components/ILIAS/Test/tests/Settings/MainSettings/SettingsIntroductionTest.php b/components/ILIAS/Test/tests/Settings/MainSettings/SettingsIntroductionTest.php
index 16c5d4f5c21c..addfce942cd7 100644
--- a/components/ILIAS/Test/tests/Settings/MainSettings/SettingsIntroductionTest.php
+++ b/components/ILIAS/Test/tests/Settings/MainSettings/SettingsIntroductionTest.php
@@ -39,15 +39,6 @@ public static function getAndWithIntroductionEnabledDataProvider(): array
];
}
- #[\PHPUnit\Framework\Attributes\DataProvider('getAndWithIntroductionTextDataProvider')]
- public function testGetAndWithIntroductionText(string $io): void
- {
- $settings_introduction = (new SettingsIntroduction())->withIntroductionText($io);
-
- $this->assertInstanceOf(SettingsIntroduction::class, $settings_introduction);
- $this->assertEquals($io, $settings_introduction->getIntroductionText());
- }
-
public static function getAndWithIntroductionTextDataProvider(): array
{
return [
diff --git a/components/ILIAS/Test/tests/ilTestResultsToXMLTest.php b/components/ILIAS/Test/tests/ilTestResultsToXMLTest.php
index 7dc6c6ecd4cf..9cb7405aab4f 100755
--- a/components/ILIAS/Test/tests/ilTestResultsToXMLTest.php
+++ b/components/ILIAS/Test/tests/ilTestResultsToXMLTest.php
@@ -32,11 +32,12 @@ protected function setUp(): void
parent::setUp();
$this->testObj = new ilTestResultsToXML(
- 0,
+ $this->createMock(ilObjTest::class),
$DIC['ilDB'],
$DIC['resource_storage'],
- '',
- false
+ $DIC['ilUser'],
+ $DIC['lng'],
+ ''
);
}
diff --git a/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIItem.php b/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIItem.php
index c18ab199ac1a..b953b2ef3fad 100755
--- a/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIItem.php
+++ b/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIItem.php
@@ -94,6 +94,9 @@ class ilQTIItem
protected ?string $iliasSourceNic = null;
protected array $response = [];
+ private array $unit_categories = [];
+ private array $units = [];
+
public function setIdent(string $a_ident): void
{
$this->ident = $a_ident;
@@ -284,6 +287,64 @@ public function determineQuestionType(): ?string
return $this->questiontype;
}
+ public function addUnitCategory(string $label, array $unit_category): void
+ {
+ $this->unit_categories[$label] = $unit_category;
+ }
+
+ public function getUnitCategories(): array
+ {
+ return $this->unit_categories;
+ }
+
+ /**
+ * @return assFormulaQuestionUnitCategory[]
+ */
+ public function getUnitCategoryObjets(): array
+ {
+ $unit_categories = [];
+ foreach ($this->getUnitCategories() as $key => $unit_category) {
+ $formula_question_unit_category = new assFormulaQuestionUnitCategory();
+ $formula_question_unit_category->setCategory($key);
+ $formula_question_unit_category->setId((int) $unit_category['id']);
+ $formula_question_unit_category->setQuestionFi((int) $unit_category['question_fi']);
+ $unit_categories[$key] = $formula_question_unit_category;
+ }
+
+ return $unit_categories;
+ }
+
+ public function addUnit(string $label, array $unit): void
+ {
+ $this->units[$label] = $unit;
+ }
+
+ public function getUnits(): array
+ {
+ return $this->units;
+ }
+
+ /**
+ * @return assFormulaQuestionUnit[]
+ */
+ public function getUnitObjects(): array
+ {
+ $units = [];
+ foreach ($this->getUnits() as $key => $unit) {
+ $formula_question_unit = new assFormulaQuestionUnit();
+ $formula_question_unit->setUnit($key);
+ $formula_question_unit->setId((int) $unit['id']);
+ $formula_question_unit->setSequence((int) $unit['sequence']);
+ $formula_question_unit->setFactor((float) $unit['factor']);
+ $formula_question_unit->setBaseUnit((int) $unit['base_unit']);
+ $formula_question_unit->setBaseunitTitle($unit['base_unit_title']);
+ $formula_question_unit->setCategory((int) $unit['category']);
+ $units[$key] = $formula_question_unit;
+ }
+
+ return $units;
+ }
+
public function setAuthor(string $a_author): void
{
$this->author = $a_author;
diff --git a/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIParser.php b/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIParser.php
index 119aac226649..8ce58906eade 100755
--- a/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIParser.php
+++ b/components/ILIAS/TestQuestionPool/classes/QTI/class.ilQTIParser.php
@@ -188,13 +188,16 @@ class ilQTIParser extends ilSaxParser
protected QuestionFiles $questionfiles;
+ private array $attributes = [];
+
public function __construct(
private readonly string $importdir,
?string $a_xml_file,
int $a_mode = self::IL_MO_PARSE_QTI,
int $a_qpl_id = 0,
array $import_idents = [],
- private array $mappings = []
+ private array $mappings = [],
+ bool $throw_errors = false
) {
/** @var ILIAS\DI\Container $DIC */
global $DIC;
@@ -211,6 +214,7 @@ public function __construct(
}
$this->depth = $this->createParserStorage();
+ $this->setThrowException($throw_errors);
}
public function isIgnoreItemsEnabled(): bool
@@ -330,6 +334,9 @@ public function handlerParseBeginTag($a_xml_parser, string $a_name, array $a_att
case "qtimetadatafield":
$this->metadata = ["label" => "", "entry" => ""];
break;
+ case "fieldentry":
+ $this->attributes = $a_attribs;
+ break;
case "flow":
$this->flow++;
break;
@@ -623,6 +630,19 @@ public function handlerParseEndTag($a_xml_parser, string $a_name): void
$this->assessment->addQtiMetadata($this->metadata);
}
$this->metadata = ["label" => "", "entry" => ""];
+ break;
+ case "fieldentry":
+ $label = $this->metadata["label"];
+ if ($label === "unit_categories") {
+ $this->item?->addUnitCategory($this->metadata["entry"], $this->attributes);
+ break;
+ }
+
+ if ($label === "units") {
+ $this->item?->addUnit($this->metadata["entry"], $this->attributes);
+ break;
+ }
+
break;
case "flow":
$this->flow--;
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assClozeTest.php b/components/ILIAS/TestQuestionPool/classes/class.assClozeTest.php
index 4e74cfa497a3..fa6520069c81 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assClozeTest.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assClozeTest.php
@@ -311,24 +311,24 @@ protected function saveClozeTextGapRecordToDb(
$this->db->manipulateF(
'INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, gap_size) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)',
[
- 'integer',
- 'integer',
- 'integer',
- 'text',
- 'float',
- 'integer',
- 'text',
- 'integer'
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_FLOAT,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_INTEGER
],
[
$next_id,
$this->getId(),
$key,
- strlen($item->getAnswertext()) ? $item->getAnswertext() : '',
+ $item->getAnswertext(),
$item->getPoints(),
$item->getOrder(),
$gap->getType(),
- (int) $gap->getGapSize()
+ $gap->getGapSize()
]
);
}
@@ -342,24 +342,24 @@ protected function saveClozeSelectGapRecordToDb(
$this->db->manipulateF(
'INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, shuffle) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)',
[
- 'integer',
- 'integer',
- 'integer',
- 'text',
- 'float',
- 'integer',
- 'text',
- 'text'
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_FLOAT,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_TEXT
],
[
$next_id,
$this->getId(),
$key,
- strlen($item->getAnswertext()) ? $item->getAnswertext() : '',
+ $item->getAnswertext(),
$item->getPoints(),
$item->getOrder(),
$gap->getType(),
- ($gap->getShuffle()) ? '1' : '0'
+ $gap->getShuffle() ? '1' : '0'
]
);
}
@@ -375,32 +375,32 @@ protected function saveClozeNumericGapRecordToDb(
$this->db->manipulateF(
'INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, lowerlimit, upperlimit, gap_size) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)',
[
- 'integer',
- 'integer',
- 'integer',
- 'text',
- 'float',
- 'integer',
- 'text',
- 'text',
- 'text',
- 'integer'
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_FLOAT,
+ ilDBConstants::T_INTEGER,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_TEXT,
+ ilDBConstants::T_INTEGER
],
[
$next_id,
$this->getId(),
$key,
- strlen($item->getAnswertext()) ? $item->getAnswertext() : '',
+ $item->getAnswertext(),
$item->getPoints(),
$item->getOrder(),
$gap->getType(),
- ($eval->e($item->getLowerBound()) !== false && strlen(
- $item->getLowerBound()
- ) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
- ($eval->e($item->getUpperBound()) !== false && strlen(
- $item->getUpperBound()
- ) > 0) ? $item->getUpperBound() : $item->getAnswertext(),
- (int) $gap->getGapSize()
+ ($eval->e($item->getLowerBound()) !== false && ($item->getLowerBound() ?? '') !== '')
+ ? $item->getLowerBound()
+ : $item->getAnswertext(),
+ ($eval->e($item->getUpperBound()) !== false && ($item->getUpperBound() ?? '') !== '')
+ ? $item->getUpperBound()
+ : $item->getAnswertext(),
+ $gap->getGapSize()
]
);
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assErrorTextGUI.php b/components/ILIAS/TestQuestionPool/classes/class.assErrorTextGUI.php
index c8994f6222bd..4fa6450c0f7b 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assErrorTextGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assErrorTextGUI.php
@@ -237,7 +237,7 @@ public function getSolutionOutput(
bool $show_question_text = true,
bool $show_inline_feedback = true
): string {
- $user_solutions = $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass);
+ $user_solutions = $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass, true);
return $this->renderSolutionOutput(
$user_solutions,
$active_id,
@@ -273,7 +273,7 @@ public function renderSolutionOutput(
$selections = [
'user' => $user_solutions ?
$user_solutions :
- $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass)
+ $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass, true)
];
$selections['best'] = $this->object->getBestSelection();
@@ -355,7 +355,7 @@ public function getTestOutput(
bool $show_specific_inline_feedback = false
): string {
$selections = [
- 'user' => $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass)
+ 'user' => $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass, false)
];
return $this->outQuestionPage(
@@ -393,15 +393,20 @@ private function generateQuestionOutput($selections, $show_question_only): strin
return $this->getILIASPage($questionoutput);
}
- private function getUsersSolutionFromPreviewOrDatabase(int $active_id = 0, ?int $pass = null): array
- {
+ private function getUsersSolutionFromPreviewOrDatabase(
+ int $active_id = 0,
+ ?int $pass = null,
+ bool $only_authorized = false
+ ): array {
if (is_object($this->getPreviewSession())) {
return (array) $this->getPreviewSession()->getParticipantsSolution();
}
if ($active_id > 0) {
$selections = [];
- $solutions = $this->object->getSolutionValues($active_id, $pass ?? 0, true);
+ $solutions = $only_authorized
+ ? $this->object->getSolutionValues($active_id, $pass ?? 0, true)
+ : $this->object->getUserSolutionPreferingIntermediate($active_id, $pass);
foreach ($solutions as $solution) {
$selections[] = $solution['value1'];
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assFileUploadGUI.php b/components/ILIAS/TestQuestionPool/classes/class.assFileUploadGUI.php
index 57d7e2401bbd..c8aa531e24f3 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assFileUploadGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assFileUploadGUI.php
@@ -176,10 +176,7 @@ public function getSolutionOutput(
// get the solution of the user for the active pass or from the last pass if allowed
$template = new ilTemplate("tpl.il_as_qpl_fileupload_output_solution.html", true, true, "components/ILIAS/TestQuestionPool");
- $solutionvalue = "";
if (($active_id > 0) && (!$show_correct_solution)) {
- $solutions = $this->object->getSolutionValues($active_id, $pass);
-
$files = ($show_manual_scoring) ? $this->object->getUploadedFilesForWeb($active_id, $pass) : $this->object->getUploadedFiles($active_id, $pass);
$table_gui = new assFileUploadFileTableGUI($this, 'gotoquestion');
$table_gui->setTitle(
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestion.php b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestion.php
index faa83bc2488e..f47d721ccda8 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestion.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestion.php
@@ -127,6 +127,9 @@ public function addResultUnit(
$this->resultunits[$result->getResult()][$unit->getId()] = $unit;
}
+ /**
+ * @return assFormulaQuestionUnit[]
+ */
public function getResultUnits(assFormulaQuestionResult $result): array
{
if (!isset($this->resultunits[$result->getResult()])) {
@@ -327,7 +330,7 @@ public function substituteVariables(array $userdata, bool $graphicalOutput = fal
$text = $this->getQuestion();
foreach ($this->fetchAllVariables($this->getQuestion()) as $varObj) {
- if (isset($userdata[$varObj->getVariable()]) && strlen($userdata[$varObj->getVariable()])) {
+ if (isset($userdata[$varObj->getVariable()]) && $userdata[$varObj->getVariable()] !== '') {
$varObj->setValue($userdata[$varObj->getVariable()]);
}
@@ -335,7 +338,7 @@ public function substituteVariables(array $userdata, bool $graphicalOutput = fal
$val = '';
if ($varObj->getValue() !== null) {
- $val = (strlen($varObj->getValue()) > 8) ? strtoupper(sprintf("%e", $varObj->getValue())) : $varObj->getValue();
+ $val = (strlen((string) $varObj->getValue()) > 8) ? strtoupper(sprintf("%e", $varObj->getValue())) : $varObj->getValue();
}
$text = preg_replace('/\$' . substr($varObj->getVariable(), 1) . '(?![0-9]+)/', $val . ' ' . $unit . '\1', $text);
@@ -387,13 +390,11 @@ public function substituteVariables(array $userdata, bool $graphicalOutput = fal
if (is_array($userdata)) {
foreach ($result_units as $unit) {
if (isset($userdata[$result]["unit"]) && $userdata[$result]["unit"] == $unit->getId()) {
- $units = $unit->getUnit();
+ $units = $unit->getSanitizedUnit();
}
}
- } else {
- if ($resObj->getUnit()) {
- $units = $resObj->getUnit()->getUnit();
- }
+ } elseif ($resObj->getUnit()) {
+ $units = $resObj->getUnit()->getSanitizedUnit();
}
} else {
$units = '
';
}
@@ -450,7 +451,7 @@ public function substituteVariables(array $userdata, bool $graphicalOutput = fal
$user_value = '';
if (is_array($userdata) && is_array($userdata[$result])) {
if (isset($userdata[$result]["unit"]) && $userdata[$result]["unit"] > 0) {
- $resunit = $this->getUnitrepository()->getUnit($userdata[$result]["unit"]);
+ $resunit = $this->getUnitrepository()->getUnit((int) $userdata[$result]["unit"]);
}
if (isset($userdata[$result]["value"])) {
@@ -847,7 +848,11 @@ public function calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSes
$points = 0;
foreach ($this->getResults() as $result) {
- $unit_id = $user_solution[$result->getResult() . '_unit'] ?? null;
+ $result_unit = "{$result->getResult()}_unit";
+ $unit_id = isset($user_solution[$result_unit]) && is_numeric($user_solution[$result_unit])
+ ? (int) $user_solution[$result_unit]
+ : null;
+
$points += $result->getReachedPoints(
$this->getVariables(),
$this->getResults(),
@@ -888,7 +893,7 @@ public function saveWorkingData(
function () use ($answer, $active_id, $pass, $authorized) {
foreach ($answer as $key => $value) {
$matches = null;
- if (preg_match('/^result_(\$r\d+)$/', $key, $matches) !== false) {
+ if (preg_match('/^result_(\$r\d+)$/', $key, $matches) !== false && $matches !== []) {
$queryResult = "SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND authorized = %s AND " . $this->db->like('value1', 'clob', $matches[1]);
if ($this->getStep() !== null) {
@@ -1092,30 +1097,27 @@ public function getBestSolution(array $solutions): array
if (!array_key_exists($matches[1], $user_solution)) {
$user_solution[$matches[1]] = [];
}
- $user_solution[$matches[1]]['unit'] = $solution_value['value2'];
+ $user_solution[$matches[1]]['unit'] = (int) $solution_value['value2'];
}
}
foreach ($this->getResults() as $result) {
$resVal = $result->calculateFormula($this->getVariables(), $this->getResults(), $this->getId(), false);
- if (is_object($result->getUnit())) {
- $user_solution[$result->getResult()]['unit'] = $result->getUnit()->getId();
+ $unit = $result->getUnit();
+ if ($unit instanceof assFormulaQuestionUnit) {
+ $user_solution[$result->getResult()]['unit'] = $unit->getId();
$user_solution[$result->getResult()]['value'] = $resVal;
- } elseif ($result->getUnit() === null) {
+ } elseif ($unit === null) {
$unit_factor = 1;
// there is no fix result_unit, any "available unit" is accepted
- $available_units = $result->getAvailableResultUnits(parent::getId());
+ $available_units = $result->getAvailableResultUnits($this->getId());
$result_name = $result->getResult();
- $check_unit = false;
- if (array_key_exists($result_name, $available_units) &&
- $available_units[$result_name] !== null) {
- $check_unit = in_array($user_solution[$result_name]['unit'] ?? null, $available_units[$result_name]);
- }
-
- if ($check_unit == true) {
- //get unit-factor
+ if (
+ isset($available_units[$result_name])
+ && in_array($user_solution[$result_name]['unit'] ?? null, $available_units[$result_name])
+ ) {
$unit_factor = assFormulaQuestionUnit::lookupUnitFactor($user_solution[$result_name]['unit']);
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionGUI.php b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionGUI.php
index bc0ffdd27698..d56216e7f4ad 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionGUI.php
@@ -612,16 +612,13 @@ public function editQuestion(
$custom_errors = true;
}
- $int_precision = $form->getItemByPostVar('intprecision_' . $variable->getVariable());
- if (!$variable->isIntPrecisionValid($int_precision?->getValue(), $min_range_value, $max_range_value)) {
- $int_precision?->setAlert($this->lng->txt('err_divider_too_big_specific'));
- $custom_errors = true;
- continue;
- }
-
$decimal_spots = $form->getItemByPostVar('precision_' . $variable->getVariable());
+ $int_precision = $form->getItemByPostVar('intprecision_' . $variable->getVariable());
if ($decimal_spots instanceof ilFormPropertyGUI && $decimal_spots->getValue() === 0) {
- $int_precision?->setAlert($this->lng->txt('err_division'));
+ $txt = !$variable->isIntPrecisionValid($int_precision?->getValue(), $min_range_value, $max_range_value)
+ ? 'err_divider_too_big_specific'
+ : 'err_division';
+ $int_precision?->setAlert($this->lng->txt($txt));
$custom_errors = true;
}
}
@@ -982,7 +979,7 @@ public function getTestOutput(
if (!array_key_exists($matches[1], $user_solution)) {
$user_solution[$matches[1]] = [];
}
- $user_solution[$matches[1]][['unit']] = $solution_value['value2'];
+ $user_solution[$matches[1]]['unit'] = $solution_value['value2'];
}
if (preg_match('/^(\$r\d+)/', $solution_value['value1'], $matches) && !isset($user_solution[$matches[1]]['result_type'])) {
$user_solution[$matches[1]]['result_type'] = assFormulaQuestionResult::getResultTypeByQstId($this->object->getId(), $solution_value['value1']);
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnit.php b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnit.php
index 0fff97ff7458..959c8362192a 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnit.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnit.php
@@ -40,7 +40,7 @@ public function initFormArray(array $data): void
$this->factor = (float) $data['factor'];
$this->baseunit = (int) $data['baseunit_fi'];
$this->baseunit_title = $data['baseunit_title'] ?? null;
- $this->category = (int) $data['category'];
+ $this->category = (int) $data['category_fi'];
$this->sequence = (int) $data['sequence'];
}
@@ -64,6 +64,11 @@ public function getUnit(): string
return $this->unit;
}
+ public function getSanitizedUnit(): string
+ {
+ return htmlspecialchars($this->getUnit(), ENT_QUOTES | ENT_SUBSTITUTE, 'utf-8');
+ }
+
public function setSequence(int $sequence): void
{
$this->sequence = $sequence;
@@ -108,6 +113,11 @@ public function getBaseunitTitle(): ?string
return $this->baseunit_title;
}
+ public function getSanitizedBaseunitTitle(): ?string
+ {
+ return $this->sanitizeString($this->getBaseunitTitle() ?? '');
+ }
+
public function setCategory(int $category): void
{
$this->category = $category;
@@ -122,14 +132,11 @@ public function getDisplayString(): string
{
global $DIC;
- $lng = $DIC->language();
-
$unit = $this->getUnit();
- if (strcmp('-qpl_qst_formulaquestion_' . $unit . '-', $lng->txt('qpl_qst_formulaquestion_' . $unit)) !== 0) {
- $unit = $lng->txt('qpl_qst_formulaquestion_' . $unit);
- }
-
- return $unit;
+ $txt = $DIC->language()->txt("qpl_qst_formulaquestion_{$unit}");
+ return strcmp("-qpl_qst_formulaquestion_{$unit}-", $txt) !== 0
+ ? $this->sanitizeString($txt)
+ : $this->getSanitizedUnit();
}
public static function lookupUnitFactor(int $a_unit_id): float
@@ -147,4 +154,9 @@ public static function lookupUnitFactor(int $a_unit_id): float
return (float) $row['factor'];
}
+
+ private function sanitizeString(string $string): string
+ {
+ return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'utf-8');
+ }
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnitCategory.php b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnitCategory.php
index 254ab0886d81..963c0d7637e5 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnitCategory.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assFormulaQuestionUnitCategory.php
@@ -56,6 +56,11 @@ public function getCategory(): string
return $this->category;
}
+ public function getSanitizedCategory(): string
+ {
+ return $this->sanitizeString($this->getCategory());
+ }
+
public function setQuestionFi(int $question_fi): void
{
$this->question_fi = $question_fi;
@@ -70,13 +75,15 @@ public function getDisplayString(): string
{
global $DIC;
- $lng = $DIC->language();
-
$category = $this->getCategory();
- if (strcmp('-qpl_qst_formulaquestion_' . $category . '-', $lng->txt('qpl_qst_formulaquestion_' . $category)) !== 0) {
- $category = $lng->txt('qpl_qst_formulaquestion_' . $category);
- }
+ $txt = $DIC->language()->txt("qpl_qst_formulaquestion_{$category}");
+ return strcmp("-qpl_qst_formulaquestion_{$category}-", $txt) !== 0
+ ? $this->sanitizeString($txt)
+ : $this->getSanitizedCategory();
+ }
- return $category;
+ private function sanitizeString(string $string): string
+ {
+ return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'utf-8');
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assOrderingQuestionGUI.php b/components/ILIAS/TestQuestionPool/classes/class.assOrderingQuestionGUI.php
index 54e55ae42d2a..2605757d2f4f 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assOrderingQuestionGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assOrderingQuestionGUI.php
@@ -257,7 +257,6 @@ public function populateAnswerSpecificFormPart(ilPropertyFormGUI $form): ilPrope
$form->addItem($header);
$orderingElementInput = $this->object->buildOrderingElementInputGui();
- $orderingElementInput->setStylingDisabled($this->isRenderPurposePrintPdf());
$this->object->initOrderingElementAuthoringProperties($orderingElementInput);
$list = $this->object->getOrderingElementList();
@@ -397,7 +396,6 @@ protected function buildNestingForm()
$form->addItem($header);
$orderingElementInput = $this->object->buildNestedOrderingElementInputGui();
- $orderingElementInput->setStylingDisabled($this->isRenderPurposePrintPdf());
$this->object->initOrderingElementAuthoringProperties($orderingElementInput);
diff --git a/components/ILIAS/TestQuestionPool/classes/class.assQuestionGUI.php b/components/ILIAS/TestQuestionPool/classes/class.assQuestionGUI.php
index 264f8d30348b..10eccce369b9 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.assQuestionGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.assQuestionGUI.php
@@ -1102,7 +1102,7 @@ public function suggestedsolution(bool $save = false): void
$options = $this->getTypeOptions();
$solution_type = $this->ctrl->getCmd() === 'cancelSuggestedSolution'
- ? $solution->getType()
+ ? $solution?->getType()
: $this->request_data_collector->string('solutiontype');
if ($solution_type === SuggestedSolution::TYPE_FILE
&& ($solution === null || $solution->getType() !== SuggestedSolution::TYPE_FILE)
@@ -1603,12 +1603,16 @@ protected function getAdditionalEditQuestionCommands(): array
protected function addTab_QuestionFeedback(ilTabsGUI $tabs): void
{
- $tabCommands = self::getCommandsFromClassConstants(ilAssQuestionFeedbackEditingGUI::class);
-
$this->ctrl->setParameterByClass(ilAssQuestionFeedbackEditingGUI::class, 'q_id', $this->object->getId());
- $tabLink = $this->ctrl->getLinkTargetByClass(ilAssQuestionFeedbackEditingGUI::class, ilAssQuestionFeedbackEditingGUI::CMD_SHOW);
- $tabs->addTarget('feedback', $tabLink, $tabCommands, $this->ctrl->getCmdClass(), '');
+ $tabs->addTab(
+ 'feedback',
+ $this->lng->txt('tst_feedback'),
+ $this->ctrl->getLinkTargetByClass(
+ ilAssQuestionFeedbackEditingGUI::class,
+ ilAssQuestionFeedbackEditingGUI::CMD_SHOW
+ )
+ );
}
protected function addTab_Question(ilTabsGUI $tabs_gui): void
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssFileUploadUploadsExporter.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssFileUploadUploadsExporter.php
index 65929f97361c..0eee94544d66 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssFileUploadUploadsExporter.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssFileUploadUploadsExporter.php
@@ -212,10 +212,9 @@ private function collectUploadedFiles(array $solution_data, ilTestParticipantDat
$dir .= $this->getPassSubDirName($file['pass']) . '/';
// IRSS Version
- if ($file['value2'] === 'rid') {
- $revision = $this->irss->manage()->getCurrentRevision(
- $rid = $this->irss->manage()->find($file['value1'])
- );
+ if ($file['value2'] === 'rid'
+ && ($rid = $this->irss->manage()->find($file['value1'])) !== null) {
+ $revision = $this->irss->manage()->getCurrentRevision($rid);
$streams[$dir . $revision->getTitle()] = $this->irss->consume()->stream($rid)->getStream();
continue;
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionFeedbackEditingGUI.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionFeedbackEditingGUI.php
index 0f11796add46..77ed7bf43230 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionFeedbackEditingGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionFeedbackEditingGUI.php
@@ -166,10 +166,6 @@ private function isSyncAfterSaveRequired(): bool
return false;
}
- if ($this->question_obj->isAdditionalContentEditingModePageObject()) {
- return false;
- }
-
if (!$this->question_gui->needsSyncQuery()) {
return false;
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionList.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionList.php
index 3e2ffeb6959e..31c6edfb9bae 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionList.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionList.php
@@ -671,7 +671,7 @@ private function isActiveQuestionType(array $questionData): bool
->isActive();
}
- public function getDataArrayForQuestionId(int $questionId)
+ public function getDataArrayForQuestionId(int $questionId): array
{
return $this->questions[$questionId];
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php
index 7dc7b4f836f2..3bad9658c401 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php
@@ -16,100 +16,55 @@
*
*********************************************************************/
-/**
- * @author Björn Heyser
- * @version $Id$
- *
- * @package components\ILIAS/Test
- */
+declare(strict_types=1);
+
class ilAssQuestionSkillAssignmentList
{
- /**
- * @var ilDBInterface
- */
- private $db;
+ private ?int $parent_obj_id = null;
- /**
- * @var integer
- */
- private $parentObjId;
+ private array $assignments = [];
- /**
- * @var array
- */
- private $assignments;
+ private array $num_assigns_by_skill = [];
- /**
- * @var array
- */
- private $numAssignsBySkill;
+ private array $max_points_by_skill = [];
- /**
- * @var array
- */
- private $maxPointsBySkill;
+ private ?int $question_id_filter = null;
- /**
- * @var integer
- */
- private $questionIdFilter;
-
- public function __construct(ilDBInterface $db)
- {
- $this->db = $db;
-
- $this->parentObjId = null;
- $this->assignments = [];
- $this->numAssignsBySkill = [];
- $this->maxPointsBySkill = [];
- $this->questionIdFilter = null;
+ public function __construct(
+ private readonly ilDBInterface $db
+ ) {
}
- /**
- * @param int $parentObjId
- */
- public function setParentObjId($parentObjId): void
+ public function setParentObjId(?int $parent_obj_id): void
{
- $this->parentObjId = $parentObjId;
+ $this->parent_obj_id = $parent_obj_id;
}
- /**
- * @return int
- */
public function getParentObjId(): ?int
{
- return $this->parentObjId;
+ return $this->parent_obj_id;
}
- /**
- * @return int
- */
public function getQuestionIdFilter(): ?int
{
- return $this->questionIdFilter;
+ return $this->question_id_filter;
}
- /**
- * @param int $questionIdFilter
- */
- public function setQuestionIdFilter($questionIdFilter): void
+ public function setQuestionIdFilter(?int $question_id_filter): void
{
- $this->questionIdFilter = $questionIdFilter;
+ $this->question_id_filter = $question_id_filter;
}
public function reset(): void
{
$this->assignments = [];
- $this->numAssignsBySkill = [];
- $this->maxPointsBySkill = [];
+ $this->num_assigns_by_skill = [];
+ $this->max_points_by_skill = [];
}
public function addAssignment(ilAssQuestionSkillAssignment $assignment): void
{
- if (!isset($this->assignments[$assignment->getQuestionId()])) {
- $this->assignments[$assignment->getQuestionId()] = [];
- }
-
+ $this->assignments[$assignment->getQuestionId()] ??= [];
$this->assignments[$assignment->getQuestionId()][] = $assignment;
}
@@ -117,22 +72,16 @@ private function incrementNumAssignsBySkill(ilAssQuestionSkillAssignment $assign
{
$key = $this->buildSkillKey($assignment->getSkillBaseId(), $assignment->getSkillTrefId());
- if (!isset($this->numAssignsBySkill[$key])) {
- $this->numAssignsBySkill[$key] = 0;
- }
-
- $this->numAssignsBySkill[$key]++;
+ $this->num_assigns_by_skill[$key] ??= 0;
+ $this->num_assigns_by_skill[$key]++;
}
private function incrementMaxPointsBySkill(ilAssQuestionSkillAssignment $assignment): void
{
$key = $this->buildSkillKey($assignment->getSkillBaseId(), $assignment->getSkillTrefId());
- if (!isset($this->maxPointsBySkill[$key])) {
- $this->maxPointsBySkill[$key] = 0;
- }
-
- $this->maxPointsBySkill[$key] += $assignment->getMaxSkillPoints();
+ $this->max_points_by_skill[$key] ??= 0;
+ $this->max_points_by_skill[$key] += $assignment->getMaxSkillPoints();
}
public function loadFromDb(): void
@@ -149,7 +98,7 @@ public function loadFromDb(): void
$assignment = $this->buildSkillQuestionAssignmentByArray($row);
if ($assignment->hasEvalModeBySolution()) {
- $assignment->loadComparisonExpressions(); // db query
+ $assignment->loadComparisonExpressions();
}
$this->addAssignment($assignment);
@@ -160,22 +109,16 @@ public function loadFromDb(): void
private function getWhereConditions(): string
{
- $conditions = [
- 'obj_fi = ' . $this->db->quote($this->getParentObjId(), 'integer')
- ];
+ $conditions = ["obj_fi = {$this->db->quote($this->getParentObjId(), ilDBConstants::T_INTEGER)}"];
if ($this->getQuestionIdFilter()) {
- $conditions[] = 'question_fi = ' . $this->db->quote($this->getQuestionIdFilter(), 'integer');
+ $conditions[] = "question_fi = {$this->db->quote($this->getQuestionIdFilter(), ilDBConstants::T_INTEGER)}";
}
return implode(' AND ', $conditions);
}
- /**
- * @param array $data
- * @return ilAssQuestionSkillAssignment
- */
- private function buildSkillQuestionAssignmentByArray($data): ilAssQuestionSkillAssignment
+ private function buildSkillQuestionAssignmentByArray(array $data): ilAssQuestionSkillAssignment
{
$assignment = new ilAssQuestionSkillAssignment($this->db);
@@ -189,45 +132,40 @@ private function buildSkillQuestionAssignmentByArray($data): ilAssQuestionSkillA
return $assignment;
}
- private function buildSkillKey($skillBaseId, $skillTrefId): string
+ private function buildSkillKey(int $skill_base_id, int $skill_tref_id): string
{
- return $skillBaseId . ':' . $skillTrefId;
+ return "{$skill_base_id}:{$skill_tref_id}";
}
public function loadAdditionalSkillData(): void
{
- foreach ($this->assignments as $assignmentsByQuestion) {
- foreach ($assignmentsByQuestion as $assignment) {
+ foreach ($this->assignments as $assignments_by_question) {
+ foreach ($assignments_by_question as $assignment) {
$assignment->loadAdditionalSkillData();
}
}
}
/**
- * @param $questionId
- * @return array of ilAssQuestionSkillAssignment
+ * @return ilAssQuestionSkillAssignment[]
*/
- public function getAssignmentsByQuestionId($questionId): array
+ public function getAssignmentsByQuestionId(int $question_id): array
{
- if (!isset($this->assignments[$questionId])) {
- return [];
- }
-
- return $this->assignments[$questionId];
+ return $this->assignments[$question_id] ?? [];
}
- public function isAssignedToQuestionId($skillBaseId, $skillTrefId, $questionId): bool
+ public function isAssignedToQuestionId(int $skill_base_id, int $skill_tref_id, int $question_id): bool
{
- if (!isset($this->assignments[$questionId])) {
+ if (!isset($this->assignments[$question_id])) {
return false;
}
- foreach ($this->assignments[$questionId] as $assignment) {
- if ($assignment->getSkillBaseId() != $skillBaseId) {
+ foreach ($this->assignments[$question_id] as $assignment) {
+ if ($assignment->getSkillBaseId() !== $skill_base_id) {
continue;
}
- if ($assignment->getSkillTrefId() != $skillTrefId) {
+ if ($assignment->getSkillTrefId() !== $skill_tref_id) {
continue;
}
@@ -241,40 +179,38 @@ public function getUniqueAssignedSkills(): array
{
$skills = [];
- foreach ($this->assignments as $assignmentsByQuestion) {
- foreach ($assignmentsByQuestion as $assignment) {
+ foreach ($this->assignments as $assignments_by_question) {
+ foreach ($assignments_by_question as $assignment) {
$key = $this->buildSkillKey($assignment->getSkillBaseId(), $assignment->getSkillTrefId());
- if (!isset($skills[$key])) {
- $skills[$key] = [
- 'skill' => new ilBasicSkill($assignment->getSkillBaseId()),
- 'skill_base_id' => $assignment->getSkillBaseId(),
- 'skill_tref_id' => $assignment->getSkillTrefId(),
- 'skill_title' => $assignment->getSkillTitle(),
- 'skill_path' => $assignment->getSkillPath(),
- 'num_assigns' => $this->getNumAssignsBySkill(
- $assignment->getSkillBaseId(),
- $assignment->getSkillTrefId()
- ),
- 'max_points' => $this->getMaxPointsBySkill(
- $assignment->getSkillBaseId(),
- $assignment->getSkillTrefId()
- )
- ];
- }
+ $skills[$key] ??= [
+ 'skill' => new ilBasicSkill($assignment->getSkillBaseId()),
+ 'skill_base_id' => $assignment->getSkillBaseId(),
+ 'skill_tref_id' => $assignment->getSkillTrefId(),
+ 'skill_title' => $assignment->getSkillTitle(),
+ 'skill_path' => $assignment->getSkillPath(),
+ 'num_assigns' => $this->getNumAssignsBySkill(
+ $assignment->getSkillBaseId(),
+ $assignment->getSkillTrefId()
+ ),
+ 'max_points' => $this->getMaxPointsBySkill(
+ $assignment->getSkillBaseId(),
+ $assignment->getSkillTrefId()
+ )
+ ];
}
}
return $skills;
}
- public function isAssignedSkill($skillBaseId, $skillTrefId): bool
+ public function isAssignedSkill(int $skill_base_id, int $skill_tref_id): bool
{
foreach ($this->getUniqueAssignedSkills() as $assignedSkill) {
- if ($assignedSkill['skill_base_id'] != $skillBaseId) {
+ if ($assignedSkill['skill_base_id'] !== $skill_base_id) {
continue;
}
- if ($assignedSkill['skill_tref_id'] == $skillTrefId) {
+ if ($assignedSkill['skill_tref_id'] === $skill_tref_id) {
return true;
}
}
@@ -282,20 +218,22 @@ public function isAssignedSkill($skillBaseId, $skillTrefId): bool
return false;
}
- public function getNumAssignsBySkill($skillBaseId, $skillTrefId)
+ public function getNumAssignsBySkill(int $skill_base_id, int $skill_tref_id)
{
- return $this->numAssignsBySkill[$this->buildSkillKey($skillBaseId, $skillTrefId)] ?? null;
+ return $this->num_assigns_by_skill[$this->buildSkillKey($skill_base_id, $skill_tref_id)] ?? null;
}
- public function getMaxPointsBySkill($skillBaseId, $skillTrefId)
+ public function getMaxPointsBySkill(int $skill_base_id, int $skill_tref_id)
{
- return $this->maxPointsBySkill[$this->buildSkillKey($skillBaseId, $skillTrefId)] ?? null;
+ return $this->max_points_by_skill[$this->buildSkillKey($skill_base_id, $skill_tref_id)] ?? null;
}
public function hasSkillsAssignedLowerThanBarrier(): bool
{
- $global_barrier = (new ilObjTestFolder())->getGlobalSettingsRepository()
- ->getGlobalSettings()->getSkillTriggeringNumberOfAnswers();
+ $global_barrier = (new ilObjTestFolder())
+ ->getGlobalSettingsRepository()
+ ->getGlobalSettings()
+ ->getSkillTriggeringNumberOfAnswers();
foreach ($this->getUniqueAssignedSkills() as $skill_data) {
if ($skill_data['num_assigns'] < $global_barrier) {
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentsGUI.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentsGUI.php
index 72fae798974c..8608c25d0a5b 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentsGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentsGUI.php
@@ -165,6 +165,8 @@ public function executeCommand(): void
$this->ctrl->redirect($this, self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
}
+ $this->keepAssignmentParameters();
+
if (in_array($command, [self::CMD_EDIT_SKILL_QUEST_ASSIGNS])) {
$this->modifyTabs();
}
@@ -276,6 +278,7 @@ private function saveSkillPointsCmd(): void
private function updateSkillQuestionAssignmentsCmd(): void
{
+ $this->keepAssignmentParameters();
$question_id = $this->request_data_collector->getQuestionId();
if ($this->isTestQuestion($question_id)) {
@@ -339,12 +342,12 @@ private function updateSkillQuestionAssignmentsCmd(): void
}
}
- $this->ctrl->redirect($this, self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
+ $this->editSkillQuestionAssignmentCmd();
}
private function showSkillSelectionCmd(): void
{
- $this->ctrl->saveParameter($this, 'q_id');
+ $this->keepAssignmentParameters();
$question_id = $this->request_data_collector->getQuestionId();
$assignmentList = new ilAssQuestionSkillAssignmentList($this->db);
@@ -390,8 +393,8 @@ private function showSkillQuestionAssignmentPropertiesFormCmd(
$question_id = $this->request_data_collector->getQuestionId();
$question_gui ??= assQuestionGUI::_getQuestionGUI('', $question_id);
- $row_id_parameter = $this->request_data_collector->strArray(EditSkillsOfQuestionTableActions::FULL_ROW_ID_PARAMETER);
- [1 => $skill_base_id, 2 => $skill_tref_id] = explode('_', $row_id_parameter[0]);
+ $row_id_parameter = $this->request_data_collector->getRowIdParameter(EditSkillsOfQuestionTableActions::FULL_ROW_ID_PARAMETER);
+ [1 => $skill_base_id, 2 => $skill_tref_id] = explode('_', $row_id_parameter);
$assignment ??= $this->buildQuestionSkillAssignment($question_id, (int) $skill_base_id, (int) $skill_tref_id);
$form ??= $this->buildSkillQuestionAssignmentPropertiesForm($question_gui->getObject(), $assignment);
@@ -406,7 +409,7 @@ private function saveSkillQuestionAssignmentPropertiesFormCmd(): void
if ($this->isTestQuestion($question_id)) {
$question_gui = assQuestionGUI::_getQuestionGUI('', $question_id);
- $row_id_parameter = $this->request_data_collector->string(EditSkillsOfQuestionTableActions::FULL_ROW_ID_PARAMETER);
+ $row_id_parameter = $this->request_data_collector->getRowIdParameter(EditSkillsOfQuestionTableActions::FULL_ROW_ID_PARAMETER);
[1 => $skill_base_id, 2 => $skill_tref_id] = explode('_', $row_id_parameter);
$assignment = $this->buildQuestionSkillAssignment($question_id, (int) $skill_base_id, (int) $skill_tref_id);
@@ -461,7 +464,7 @@ private function saveSkillQuestionAssignmentPropertiesFormCmd(): void
}
}
- $this->ctrl->redirect($this, self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
+ $this->ctrl->redirect($this, self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
}
private function buildSkillQuestionAssignmentPropertiesForm(
@@ -521,6 +524,8 @@ private function editSkillQuestionAssignmentCmd(): void
$assignment_list->loadFromDb();
$assignment_list->loadAdditionalSkillData();
+ $this->keepAssignmentParameters();
+
$edit_uri = $this->data_factory->uri(
ILIAS_HTTP_PATH . '/' . $this->ctrl->getLinkTargetByClass(
self::class,
@@ -528,6 +533,11 @@ private function editSkillQuestionAssignmentCmd(): void
)
);
+ $this->ctrl->setParameterByClass(
+ ilAssQuestionSkillAssignmentsGUI::class,
+ 'q_id',
+ $this->request_data_collector->getQuestionId()
+ );
$this->toolbar->addComponent(
$this->ui_factory->button()->standard(
$this->lng->txt('tst_manage_competence_select_skills'),
@@ -535,8 +545,9 @@ private function editSkillQuestionAssignmentCmd(): void
[ilAssQuestionSkillAssignmentsGUI::class],
self::CMD_SHOW_SKILL_SELECT
)
- )
+ )->withUnavailableAction(!$this->isAssignmentEditingEnabled())
);
+ $this->ctrl->setParameterByClass(ilAssQuestionSkillAssignmentsGUI::class, 'q_id', null);
$components = (new EditSkillsOfQuestionTable(
$this->request_data_collector,
@@ -545,14 +556,20 @@ private function editSkillQuestionAssignmentCmd(): void
$this->lng,
(new EditSkillsOfQuestionTableActions(
$this->tpl,
- [EditSkillsOfQuestionTableEditAction::ACTION_ID => new EditSkillsOfQuestionTableEditAction($this->ui_factory, $this->lng)]
+ [
+ EditSkillsOfQuestionTableEditAction::ACTION_ID => new EditSkillsOfQuestionTableEditAction(
+ $this->ui_factory,
+ $this->lng,
+ $this->isAssignmentEditingEnabled()
+ )
+ ]
))
))->getComponents(new URLBuilder($edit_uri));
$this->tpl->setContent($this->ui_renderer->render($components));
}
- private function isSyncOriginalPossibleAndAllowed($questionId): bool
+ private function isSyncOriginalPossibleAndAllowed(int $questionId): bool
{
$questionData = $this->question_list->getDataArrayForQuestionId($questionId);
@@ -583,7 +600,7 @@ private function showSyncOriginalConfirmationCmd(): void
$confirmation->setFormAction($this->ctrl->getFormAction($this));
$confirmation->addHiddenItem('q_id', $this->request_data_collector->getQuestionId());
$confirmation->setConfirm($this->lng->txt('yes'), self::CMD_SYNC_ORIGINAL);
- $confirmation->setCancel($this->lng->txt('no'), self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
+ $confirmation->setCancel($this->lng->txt('no'), self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
$this->tpl->setContent($this->ctrl->getHTML($confirmation));
}
@@ -604,7 +621,7 @@ private function syncOriginalCmd(): void
$this->tpl->setOnScreenMessage('success', $this->lng->txt('qpl_qst_skl_assign_synced_to_orig'), true);
}
- $this->ctrl->redirect($this, self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
+ $this->ctrl->redirect($this, self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
}
private function buildSkillQuestionAssignmentList(): ilAssQuestionSkillAssignmentList
@@ -775,11 +792,12 @@ private function handleAssignmentConfigurationHintMessage(): void
}
}
- private function getSkillSelectorHeader($questionId): string
+ private function getSkillSelectorHeader(int $questionId): string
{
- $questionData = $this->question_list->getDataArrayForQuestionId($questionId);
-
- return sprintf($this->lng->txt('qpl_qst_skl_selection_for_question_header'), $questionData['title']);
+ return sprintf(
+ $this->lng->txt('qpl_qst_skl_selection_for_question_header'),
+ $this->question_list->getDataArrayForQuestionId($questionId)['title']
+ );
}
private function sortAlphabetically($array)
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpression.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpression.php
index 97afbce9810c..3ba6845f11ae 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpression.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpression.php
@@ -16,195 +16,107 @@
*
*********************************************************************/
-/**
- * @author Björn Heyser
- * @version $Id$
- *
- * @package components\ILIAS/TestQuestionPool
- */
+declare(strict_types=1);
+
class ilAssQuestionSolutionComparisonExpression
{
- /**
- * @var ilDBInterface
- */
- protected $db;
-
- /**
- * @var integer
- */
- private $questionId;
-
- /**
- * @var integer
- */
- private $skillBaseId;
-
- /**
- * @var integer
- */
- private $skillTrefId;
-
- /**
- * @var integer
- */
- private $orderIndex;
-
- /**
- * @var string
- */
- private $expression;
-
- /**
- * @var integer
- */
- private $points;
-
- /**
- * Constructor
- */
- public function __construct()
- {
- $this->questionId = null;
- $this->skillBaseId = null;
- $this->skillTrefId = null;
- $this->orderIndex = null;
- $this->expression = null;
- $this->points = null;
- }
+ protected ilDBInterface $db;
+
+ private ?int $question_id = null;
+
+ private ?int $skill_base_id = null;
+
+ private ?int $skill_tref_id = null;
+
+ private ?int $order_index = null;
+
+ private ?string $expression = null;
+
+ private ?int $points = null;
public function save(): void
{
$this->db->replace(
'qpl_qst_skl_sol_expr',
[
- 'question_fi' => ['integer', $this->getQuestionId()],
- 'skill_base_fi' => ['integer', $this->getSkillBaseId()],
- 'skill_tref_fi' => ['integer', $this->getSkillTrefId()],
- 'order_index' => ['integer', $this->getOrderIndex()]
+ 'question_fi' => [ilDBConstants::T_INTEGER, $this->getQuestionId()],
+ 'skill_base_fi' => [ilDBConstants::T_INTEGER, $this->getSkillBaseId()],
+ 'skill_tref_fi' => [ilDBConstants::T_INTEGER, $this->getSkillTrefId()],
+ 'order_index' => [ilDBConstants::T_INTEGER, $this->getOrderIndex()]
],
[
- 'expression' => ['text', $this->getExpression()],
- 'points' => ['integer', $this->getPoints()]
+ 'expression' => [ilDBConstants::T_TEXT, $this->getExpression()],
+ 'points' => [ilDBConstants::T_INTEGER, $this->getPoints()]
]
);
}
- /**
- * @return ilDBInterface
- */
- public function getDb(): ilDBInterface
- {
- return $this->db;
- }
-
- /**
- * @param ilDBInterface $db
- */
- public function setDb($db): void
+ public function setDb(ilDBInterface $db): void
{
$this->db = $db;
}
- /**
- * @return int
- */
public function getQuestionId(): ?int
{
- return $this->questionId;
+ return $this->question_id;
}
- /**
- * @param int $questionId
- */
- public function setQuestionId($questionId): void
+ public function setQuestionId(?int $question_id): void
{
- $this->questionId = $questionId;
+ $this->question_id = $question_id;
}
- /**
- * @return int
- */
public function getSkillBaseId(): ?int
{
- return $this->skillBaseId;
+ return $this->skill_base_id;
}
- /**
- * @param int $skillBaseId
- */
- public function setSkillBaseId($skillBaseId): void
+ public function setSkillBaseId(?int $skill_base_id): void
{
- $this->skillBaseId = $skillBaseId;
+ $this->skill_base_id = $skill_base_id;
}
- /**
- * @return int
- */
public function getSkillTrefId(): ?int
{
- return $this->skillTrefId;
+ return $this->skill_tref_id;
}
- /**
- * @param int $skillTrefId
- */
- public function setSkillTrefId($skillTrefId): void
+ public function setSkillTrefId(?int $skill_tref_id): void
{
- $this->skillTrefId = $skillTrefId;
+ $this->skill_tref_id = $skill_tref_id;
}
- /**
- * @return int
- */
public function getOrderIndex(): ?int
{
- return $this->orderIndex;
+ return $this->order_index;
}
- /**
- * @param int $orderIndex
- */
- public function setOrderIndex($orderIndex): void
+ public function setOrderIndex(?int $order_index): void
{
- $this->orderIndex = $orderIndex;
+ $this->order_index = $order_index;
}
- /**
- * @return string
- */
public function getExpression(): ?string
{
return $this->expression;
}
- /**
- * @param string $expression
- */
- public function setExpression($expression): void
+ public function setExpression(?string $expression): void
{
$this->expression = $expression;
}
- /**
- * @return int
- */
public function getPoints(): ?int
{
return $this->points;
}
- /**
- * @param int $points
- */
- public function setPoints($points): void
+ public function setPoints(?int $points): void
{
$this->points = $points;
}
- /**
- * @param array $data
- */
- public function initInstanceFromArray($data): void
+ public function initInstanceFromArray(array $data): void
{
$this->setQuestionId($data['question_fi']);
$this->setSkillBaseId($data['skill_base_fi']);
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpressionList.php b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpressionList.php
index 8929d6ffd290..bede1c958e5a 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpressionList.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilAssQuestionSolutionComparisonExpressionList.php
@@ -16,64 +16,28 @@
*
*********************************************************************/
-/**
- * @author Björn Heyser
- * @version $Id$
- *
- * @package components\ILIAS/Test
- */
+declare(strict_types=1);
+
class ilAssQuestionSolutionComparisonExpressionList
{
- /**
- * @var ilDBInterface
- */
- protected $db;
-
- /**
- * @var integer
- */
- private $questionId;
-
- /**
- * @var integer
- */
- private $skillBaseId;
-
- /**
- * @var integer
- */
- private $skillTrefId;
-
- /**
- * @var array
- */
- private $expressions;
-
- /**
- * @param ilDBInterface $db
- */
- public function __construct(ilDBInterface $db)
- {
- $this->db = $db;
+ private ?int $question_id = null;
- $this->questionId = null;
- $this->skillBaseId = null;
- $this->skillTrefId = null;
+ private ?int $skill_base_id = null;
- $this->expressions = [];
+ private ?int $skill_tref_id = null;
+
+ private array $expressions = [];
+
+ public function __construct(
+ protected readonly ilDBInterface $db
+ ) {
}
public function load(): void
{
- $query = "
- SELECT *
- FROM qpl_qst_skl_sol_expr
- WHERE question_fi = %s AND skill_base_fi = %s AND skill_tref_fi = %s
- ";
-
$res = $this->db->queryF(
- $query,
- ['integer', 'integer', 'integer'],
+ 'SELECT * FROM qpl_qst_skl_sol_expr WHERE question_fi = %s AND skill_base_fi = %s AND skill_tref_fi = %s',
+ [ilDBConstants::T_INTEGER, ilDBConstants::T_INTEGER, ilDBConstants::T_INTEGER],
[$this->getQuestionId(), $this->getSkillBaseId(), $this->getSkillTrefId()]
);
@@ -90,9 +54,8 @@ public function save(): void
{
$this->delete();
- foreach ($this->expressions as $orderIndex => $expression) {
- /* @var ilAssQuestionSolutionComparisonExpression $expression */
-
+ /* @var ilAssQuestionSolutionComparisonExpression $expression */
+ foreach ($this->expressions as $expression) {
$expression->setQuestionId($this->getQuestionId());
$expression->save();
}
@@ -100,14 +63,9 @@ public function save(): void
public function delete(): void
{
- $query = "
- DELETE FROM qpl_qst_skl_sol_expr
- WHERE question_fi = %s AND skill_base_fi = %s AND skill_tref_fi = %s
- ";
-
$this->db->manipulateF(
- $query,
- ['integer', 'integer', 'integer'],
+ 'DELETE FROM qpl_qst_skl_sol_expr WHERE question_fi = %s AND skill_base_fi = %s AND skill_tref_fi = %s',
+ [ilDBConstants::T_INTEGER, ilDBConstants::T_INTEGER, ilDBConstants::T_INTEGER],
[$this->getQuestionId(), $this->getSkillBaseId(), $this->getSkillTrefId()]
);
}
@@ -132,51 +90,33 @@ public function reset(): void
$this->expressions = [];
}
- /**
- * @return int
- */
public function getQuestionId(): ?int
{
- return $this->questionId;
+ return $this->question_id;
}
- /**
- * @param int $questionId
- */
- public function setQuestionId($questionId): void
+ public function setQuestionId(?int $question_id): void
{
- $this->questionId = $questionId;
+ $this->question_id = $question_id;
}
- /**
- * @return int
- */
public function getSkillBaseId(): ?int
{
- return $this->skillBaseId;
+ return $this->skill_base_id;
}
- /**
- * @param int $skillBaseId
- */
- public function setSkillBaseId($skillBaseId): void
+ public function setSkillBaseId(?int $skill_base_id): void
{
- $this->skillBaseId = $skillBaseId;
+ $this->skill_base_id = $skill_base_id;
}
- /**
- * @return int
- */
public function getSkillTrefId(): ?int
{
- return $this->skillTrefId;
+ return $this->skill_tref_id;
}
- /**
- * @param int $skillTrefId
- */
- public function setSkillTrefId($skillTrefId): void
+ public function setSkillTrefId(?int $skill_tref_id): void
{
- $this->skillTrefId = $skillTrefId;
+ $this->skill_tref_id = $skill_tref_id;
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilBulkEditQuestionsGUI.php b/components/ILIAS/TestQuestionPool/classes/class.ilBulkEditQuestionsGUI.php
index 4178685ae116..58c4856b3367 100644
--- a/components/ILIAS/TestQuestionPool/classes/class.ilBulkEditQuestionsGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilBulkEditQuestionsGUI.php
@@ -25,7 +25,6 @@
use Psr\Http\Message\ServerRequestInterface;
use ILIAS\HTTP\Wrapper\RequestWrapper;
use ILIAS\UI\Component\Input\Container\Form;
-use ILIAS\UI\Component\MessageBox\MessageBox;
/**
* @ilCtrl_Calls ilBulkEditQuestionsGUI: ilFormPropertyDispatchGUI
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilLocalUnitConfigurationGUI.php b/components/ILIAS/TestQuestionPool/classes/class.ilLocalUnitConfigurationGUI.php
index 61aae9cfa45e..5333b2657708 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilLocalUnitConfigurationGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilLocalUnitConfigurationGUI.php
@@ -143,7 +143,9 @@ protected function confirmImportGlobalCategory(): void
protected function confirmImportGlobalCategories(array $category_ids): void
{
// @todo: Confirmation Currently not implemented, so forward to import
- $this->importGlobalCategories($category_ids);
+ $category_ids === []
+ ? $this->showGlobalUnitCategories()
+ : $this->importGlobalCategories($category_ids);
}
protected function importGlobalCategories(array $category_ids): void
@@ -171,9 +173,9 @@ protected function importGlobalCategories(array $category_ids): void
if ($i) {
$this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
+ $this->ctrl->setParameter($this, 'question_fi', $this->request->getQuestionId());
}
- $this->ctrl->setParameter($this, 'question_fi', 0);
$this->ctrl->redirect($this, 'showLocalUnitCategories');
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilObjQuestionPoolGUI.php b/components/ILIAS/TestQuestionPool/classes/class.ilObjQuestionPoolGUI.php
index 1ebb0b2481ab..98195c86b9e0 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilObjQuestionPoolGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilObjQuestionPoolGUI.php
@@ -882,7 +882,6 @@ private function importQuestionPoolWithValidManifest(
array $selected_questions,
string $file_to_import
): void {
-
ilSession::set('qpl_import_selected_questions', $selected_questions);
$imp = new ilImport($this->request_data_collector->getRefId());
$map = $imp->getMapping();
@@ -1307,8 +1306,10 @@ public function editQuestionForTestObject(): void
protected function importQuestionsFile(string $path_to_uploaded_file_in_temp_dir): void
{
if (!$this->temp_file_system->hasDir($path_to_uploaded_file_in_temp_dir)
- || ($files = $this->temp_file_system->listContents($path_to_uploaded_file_in_temp_dir)) === []) {
- $this->tpl->setOnScreenMessage('failure', $this->lng->txt('obj_import_file_error'));
+ || ($files = $this->temp_file_system->listContents($path_to_uploaded_file_in_temp_dir)) === []
+ || mb_stripos($files[0]->getPath(), 'tst') !== false) {
+ $this->tpl->setOnScreenMessage('failure', $this->lng->txt('obj_import_file_error'), true);
+ $this->ctrl->redirectByClass(self::class, self::DEFAULT_CMD);
}
$file_to_import = $this->import_temp_directory . DIRECTORY_SEPARATOR . $files[0]->getPath();
diff --git a/components/ILIAS/TestQuestionPool/classes/class.ilUnitConfigurationGUI.php b/components/ILIAS/TestQuestionPool/classes/class.ilUnitConfigurationGUI.php
index 6fc930e7cd1c..2fdc9bc9fa5c 100755
--- a/components/ILIAS/TestQuestionPool/classes/class.ilUnitConfigurationGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/class.ilUnitConfigurationGUI.php
@@ -80,15 +80,10 @@ public function executeCommand(): void
{
$cmd = $this->ctrl->getCmd($this->getDefaultCommand());
$this->checkPermissions($cmd);
- switch ($cmd) {
- case 'confirmImportGlobalCategories':
- $category_ids = $this->request->raw('category_ids');
- $this->$cmd($category_ids);
- break;
- default:
- $this->$cmd();
- break;
- }
+ match ($cmd) {
+ 'confirmImportGlobalCategories' => $this->$cmd($this->request->getUnitCategoryIds()),
+ default => $this->$cmd(),
+ };
$this->handleSubtabs();
}
@@ -482,8 +477,8 @@ protected function showUnitsOfCategory(): void
/** @var assFormulaQuestionUnit $unit */
$data[] = [
'unit_id' => $unit->getId(),
- 'unit' => $unit->getUnit(),
- 'baseunit' => $unit->getBaseunitTitle(),
+ 'unit' => $unit->getSanitizedUnit(),
+ 'baseunit' => $unit->getSanitizedBaseunitTitle(),
'baseunit_id' => $unit->getBaseUnit(),
'factor' => $unit->getFactor(),
'sequence' => $unit->getSequence(),
diff --git a/components/ILIAS/TestQuestionPool/classes/export/qti12/class.assFormulaQuestionExport.php b/components/ILIAS/TestQuestionPool/classes/export/qti12/class.assFormulaQuestionExport.php
index 97bb8528607a..75746c4f8761 100755
--- a/components/ILIAS/TestQuestionPool/classes/export/qti12/class.assFormulaQuestionExport.php
+++ b/components/ILIAS/TestQuestionPool/classes/export/qti12/class.assFormulaQuestionExport.php
@@ -66,6 +66,53 @@ public function toXML($a_include_header = true, $a_include_binary = true, $a_shu
$a_xml_writer->xmlElement("fieldlabel", null, "points");
$a_xml_writer->xmlElement("fieldentry", null, $this->object->getPoints());
$a_xml_writer->xmlEndTag("qtimetadatafield");
+
+ /** @var assFormulaQuestion $object */
+ $object = $this->object;
+ $unit_repository = $object->getUnitRepository();
+
+ $question_id = $this->object->getId();
+ $unit_categories = array_filter(
+ $unit_repository->getAllUnitCategories(),
+ static fn(object $object): bool => $object->getQuestionFi() === $question_id,
+ );
+
+ $a_xml_writer->xmlStartTag("qtimetadatafield");
+ $a_xml_writer->xmlElement("fieldlabel", null, "unit_categories");
+ /** @var assFormulaQuestionUnitCategory $unit_category */
+ foreach ($unit_categories as $unit_category) {
+ $a_xml_writer->xmlElement(
+ "fieldentry",
+ ["id" => $unit_category->getId(), "question_fi" => $unit_category->getQuestionFi()],
+ $unit_category->getCategory()
+ );
+ }
+ $a_xml_writer->xmlEndTag("qtimetadatafield");
+
+ $categorized_units = array_filter(
+ $unit_repository->getCategorizedUnits(),
+ static fn(object $object): bool => $object instanceof assFormulaQuestionUnit,
+ );
+
+ $a_xml_writer->xmlStartTag("qtimetadatafield");
+ $a_xml_writer->xmlElement("fieldlabel", null, "units");
+ /** @var assFormulaQuestionUnit $categorized_unit */
+ foreach ($categorized_units as $categorized_unit) {
+ $a_xml_writer->xmlElement(
+ "fieldentry",
+ [
+ "id" => $categorized_unit->getId(),
+ "sequence" => $categorized_unit->getSequence(),
+ "factor" => $categorized_unit->getFactor(),
+ "base_unit" => $categorized_unit->getBaseUnit(),
+ "base_unit_title" => $categorized_unit->getBaseunitTitle(),
+ "category" => $categorized_unit->getCategory()
+ ],
+ $categorized_unit->getUnit()
+ );
+ }
+ $a_xml_writer->xmlEndTag("qtimetadatafield");
+
foreach ($this->object->getVariables() as $variable) {
$var = [
"precision" => $variable->getPrecision(),
diff --git a/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php b/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php
index 55b64245b31f..904101ec42f9 100755
--- a/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php
+++ b/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php
@@ -651,10 +651,10 @@ private function cloneSpecificFeedbackSetting(
);
}
- protected function cloneSpecificFeedback(int $originalQuestionId, int $duplicateQuestionId): void
+ protected function cloneSpecificFeedback(int $original_question_id, int $duplicate_question_id): void
{
- $this->cloneSpecificFeedbackSetting($originalQuestionId, $duplicateQuestionId);
- parent::cloneSpecificFeedback($originalQuestionId, $duplicateQuestionId);
+ $this->cloneSpecificFeedbackSetting($original_question_id, $duplicate_question_id);
+ parent::cloneSpecificFeedback($original_question_id, $duplicate_question_id);
}
/**
diff --git a/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php b/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php
index caf120520d6c..27dd46e480ca 100755
--- a/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php
+++ b/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php
@@ -239,31 +239,28 @@ public function deleteSpecificAnswerFeedbacks(int $question_id, bool $is_additio
protected function cloneSpecificFeedback(int $source_question_id, int $target_question_id): void
{
- // delete specific feedback of the original
- $this->db->manipulateF(
- "DELETE FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s",
- ['integer'],
- [$source_question_id]
+ $this->deleteFeedbackOfOriginalQuestion(
+ $this->getSpecificFeedbackTableName(),
+ $target_question_id,
+ $this->getSpecificAnswerFeedbackPageObjectType()
);
- // get specific feedback of the actual question
$res = $this->db->queryF(
"SELECT * FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s",
- ['integer'],
- [$target_question_id]
+ [ilDBConstants::T_INTEGER],
+ [$source_question_id]
);
- // save specific feedback to the original
while ($row = $this->db->fetchAssoc($res)) {
$next_id = $this->db->nextId($this->getSpecificFeedbackTableName());
$this->db->insert($this->getSpecificFeedbackTableName(), [
- 'feedback_id' => ['integer', $next_id],
- 'question_fi' => ['integer', $source_question_id],
- 'question' => ['integer', $row['question']],
- 'answer' => ['integer', $row['answer']],
- 'feedback' => ['text', $row['feedback']],
- 'tstamp' => ['integer', time()]
+ 'feedback_id' => [ilDBConstants::T_INTEGER, $next_id],
+ 'question_fi' => [ilDBConstants::T_INTEGER, $target_question_id],
+ 'question' => [ilDBConstants::T_INTEGER, $row['question']],
+ 'answer' => [ilDBConstants::T_INTEGER, $row['answer']],
+ 'feedback' => [ilDBConstants::T_TEXT, $row['feedback']],
+ 'tstamp' => [ilDBConstants::T_INTEGER, time()]
]);
if ($this->questionOBJ->isAdditionalContentEditingModePageObject()) {
diff --git a/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php b/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php
index a478b101d99e..dbb491956c0d 100755
--- a/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php
+++ b/components/ILIAS/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php
@@ -433,50 +433,80 @@ private function duplicateGenericFeedback(int $originalQuestionId, int $duplicat
* duplicates the SPECIFIC feedback relating to the given original question id
* and saves it for the given duplicate question id
*/
- abstract protected function cloneSpecificFeedback(int $originalQuestionId, int $duplicateQuestionId): void;
+ abstract protected function cloneSpecificFeedback(int $source_question_id, int $target_question_id): void;
/**
* syncs the feedback from a duplicated question back to the original question
*/
- final public function cloneFeedback(int $originalQuestionId, int $duplicateQuestionId): void
+ final public function cloneFeedback(int $original_question_id, int $duplicate_question_id): void
{
- $this->cloneGenericFeedback($originalQuestionId, $duplicateQuestionId);
- $this->cloneSpecificFeedback($originalQuestionId, $duplicateQuestionId);
+ $this->cloneGenericFeedback($original_question_id, $duplicate_question_id);
+ $this->cloneSpecificFeedback($duplicate_question_id, $original_question_id);
}
/**
* syncs the GENERIC feedback from a duplicated question back to the original question
*/
- private function cloneGenericFeedback(int $originalQuestionId, int $duplicateQuestionId): void
+ private function cloneGenericFeedback(int $original_question_id, int $duplicate_question_id): void
{
- // delete generic feedback of the original question
- $this->db->manipulateF(
- "DELETE FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s",
- ['integer'],
- [$originalQuestionId]
+ $this->deleteFeedbackOfOriginalQuestion(
+ $this->getGenericFeedbackTableName(),
+ $original_question_id,
+ $this->getGenericFeedbackPageObjectType()
);
// get generic feedback of the actual (duplicated) question
$result = $this->db->queryF(
"SELECT * FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s",
- ['integer'],
- [$duplicateQuestionId]
+ [ilDBConstants::T_INTEGER],
+ [$duplicate_question_id]
);
// save generic feedback to the original question
while ($row = $this->db->fetchAssoc($result)) {
- $nextId = $this->db->nextId($this->getGenericFeedbackTableName());
+ $next_id = $this->db->nextId($this->getGenericFeedbackTableName());
$this->db->insert($this->getGenericFeedbackTableName(), [
- 'feedback_id' => ['integer', $nextId],
- 'question_fi' => ['integer', $originalQuestionId],
- 'correctness' => ['text', $row['correctness']],
- 'feedback' => ['clob', $row['feedback']],
- 'tstamp' => ['integer', time()]
+ 'feedback_id' => [ilDBConstants::T_INTEGER, $next_id],
+ 'question_fi' => [ilDBConstants::T_INTEGER, $original_question_id],
+ 'correctness' => [ilDBConstants::T_TEXT, $row['correctness']],
+ 'feedback' => [ilDBConstants::T_CLOB, $row['feedback']],
+ 'tstamp' => [ilDBConstants::T_INTEGER, time()]
]);
+
+ if ($this->questionOBJ->isAdditionalContentEditingModePageObject()) {
+ $page_object_type = $this->getGenericFeedbackPageObjectType();
+ $this->clonePageObject($page_object_type, $row['feedback_id'], $next_id, $original_question_id);
+ }
}
}
+ protected function deleteFeedbackOfOriginalQuestion(
+ string $table_name,
+ int $original_question_id,
+ string $page_object_type
+ ): void {
+ if ($this->questionOBJ->isAdditionalContentEditingModePageObject()) {
+ $original_result = $this->db->queryF(
+ "SELECT feedback_id FROM {$table_name} WHERE question_fi = %s",
+ [ilDBConstants::T_INTEGER],
+ [$original_question_id]
+ );
+ while ($original_row = $this->db->fetchAssoc($original_result)) {
+ $this->ensurePageObjectDeleted(
+ $page_object_type,
+ (int) $original_row['feedback_id']
+ );
+ }
+ }
+
+ $this->db->manipulateF(
+ "DELETE FROM {$table_name} WHERE question_fi = %s",
+ [ilDBConstants::T_INTEGER],
+ [$original_question_id]
+ );
+ }
+
/**
* returns the SPECIFIC answer feedback ID for a given question id and answer index.
*/
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php
index f52443a7676c..1201c315c605 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php
@@ -41,6 +41,10 @@ public function setHidePointsEnabled(bool $hide_points_enabled): void
public function setValue($a_value): void
{
foreach ($this->forms_helper->transformPoints($a_value) as $index => $value) {
+ if ($value === null) {
+ return;
+ }
+
$this->values[$index]->setPoints($value);
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php
index 7640660ffb31..2f99be071e89 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php
@@ -29,6 +29,10 @@ class ilAssClozeTestCombinationVariantsInputGUI extends ilAnswerWizardInputGUI
public function setValue($a_value): void
{
foreach ($this->forms_helper->transformPoints($a_value) as $index => $value) {
+ if ($value === null) {
+ return;
+ }
+
$this->values[$index]['points'] = $value;
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php
index 03818987220d..818bbdc7a985 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php
@@ -29,6 +29,10 @@ class ilAssErrorTextCorrectionsInputGUI extends ilErrorTextWizardInputGUI
public function setValue($a_value): void
{
foreach ($this->forms_helper->transformPoints($a_value) as $index => $points) {
+ if ($points === null) {
+ return;
+ }
+
$this->values[$index] = $this->values[$index]->withPoints($points);
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMatchingPairCorrectionsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMatchingPairCorrectionsInputGUI.php
index 088647b5593c..96101dee3e93 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMatchingPairCorrectionsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMatchingPairCorrectionsInputGUI.php
@@ -40,6 +40,10 @@ public function setThumbsWebPathWithPrefix(string $path_including_prefix): void
public function setValue($a_value): void
{
foreach ($this->forms_helper->transformPoints($a_value) as $index => $value) {
+ if ($value === null) {
+ return;
+ }
+
$this->pairs[$index] = $this->pairs[$index]->withPoints($value);
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMultipleChoiceCorrectionsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMultipleChoiceCorrectionsInputGUI.php
index 7cf09bf39f3f..0658c7ed0cc7 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMultipleChoiceCorrectionsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssMultipleChoiceCorrectionsInputGUI.php
@@ -37,6 +37,10 @@ public function setValue($a_value): void
$points_unchecked = $this->forms_helper->transformPoints($a_value, 'points_unchecked');
foreach ($this->values as $index => $value) {
+ if ($value === null) {
+ return;
+ }
+
$this->values[$index]->setPoints($points[$index] ?? 0.0);
$this->values[$index]->setPointsUnchecked($points_unchecked[$index] ?? 0.0);
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssNestedOrderingElementsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssNestedOrderingElementsInputGUI.php
index dbd0f215cff7..06a676b89e9f 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssNestedOrderingElementsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssNestedOrderingElementsInputGUI.php
@@ -41,7 +41,6 @@ class ilAssNestedOrderingElementsInputGUI extends ilIdentifiedMultiValuesInputGU
private ?ilAssOrderingElementList $correctness_true_element_list = null;
private bool $interaction_enabled = true;
private bool $nesting_enabled = true;
- private bool $styling_disabled = false;
private ?ilTemplate $list_tpl = null;
private UIFactory $ui_factory;
@@ -70,11 +69,6 @@ public function setNestingEnabled(bool $nesting_enabled): void
$this->nesting_enabled = $nesting_enabled;
}
- public function setStylingDisabled(bool $styling_disabled): void
- {
- $this->styling_disabled = $styling_disabled;
- }
-
private function getGlobalTpl()
{
return isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['tpl'] : $GLOBALS['tpl'];
@@ -383,10 +377,6 @@ function (string $c, array $v) use ($sort_closure): string {
public function render(string $a_mode = ''): string
{
- if (!$this->styling_disabled) {
- $this->getGlobalTpl()->addCss('assets/css/content.css');
- }
-
if ($this->interaction_enabled) {
$this->initializePlayerJS();
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssOrderingImagesInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssOrderingImagesInputGUI.php
index cf043bca8aad..a947f6ccbcfa 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssOrderingImagesInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssOrderingImagesInputGUI.php
@@ -1,4 +1,5 @@
addFormValuesManipulator($converter);
}
- /**
- * FOR COMPATIBILITY ONLY
- *
- * @param $stylingDisabled
- */
- public function setStylingDisabled($stylingDisabled): void
- {
- }
-
- /**
- * FOR COMPATIBILITY ONLY
- *
- * @return bool
- */
- public function getStylingDisabled(): bool
- {
- return false;
- }
-
/**
* @param ilAssOrderingElementList $elementList
*/
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssQuestionSkillAssignmentPropertyFormGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssQuestionSkillAssignmentPropertyFormGUI.php
index ec211720763a..f7692ccc7e7d 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssQuestionSkillAssignmentPropertyFormGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssQuestionSkillAssignmentPropertyFormGUI.php
@@ -96,12 +96,12 @@ public function build(): void
);
$this->addCommandButton(
- ilAssQuestionSkillAssignmentsGUI::CMD_SHOW_SKILL_QUEST_ASSIGNS,
+ ilAssQuestionSkillAssignmentsGUI::CMD_EDIT_SKILL_QUEST_ASSIGNS,
$this->lng->txt('cancel')
);
} else {
$this->addCommandButton(
- ilAssQuestionSkillAssignmentsGUI::CMD_SHOW_SKILL_QUEST_ASSIGNS,
+ ilAssQuestionSkillAssignmentsGUI::CMD_EDIT_SKILL_QUEST_ASSIGNS,
$this->lng->txt('back')
);
}
@@ -208,6 +208,7 @@ private function buildResultSkillPointsInputField(): ilNumberInputGUI
$questResultSkillPoints->setMinValue(1);
$questResultSkillPoints->allowDecimals(false);
$questResultSkillPoints->setValue((string) $this->assignment->getSkillPoints());
+
if (!$this->isManipulationEnabled()) {
$questResultSkillPoints->setDisabled(true);
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssSingleChoiceCorrectionsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssSingleChoiceCorrectionsInputGUI.php
index 43c53c19bf6f..fe86752c779c 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssSingleChoiceCorrectionsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilAssSingleChoiceCorrectionsInputGUI.php
@@ -34,6 +34,10 @@ class ilAssSingleChoiceCorrectionsInputGUI extends ilSingleChoiceWizardInputGUI
public function setValue($a_value): void
{
foreach ($this->forms_helper->transformPoints($a_value) as $index => $value) {
+ if ($value === null) {
+ return;
+ }
+
$this->values[$index]->setPoints($value);
}
}
diff --git a/components/ILIAS/TestQuestionPool/classes/forms/class.ilImagemapCorrectionsInputGUI.php b/components/ILIAS/TestQuestionPool/classes/forms/class.ilImagemapCorrectionsInputGUI.php
index fff4252e1621..ae4fc191c87a 100755
--- a/components/ILIAS/TestQuestionPool/classes/forms/class.ilImagemapCorrectionsInputGUI.php
+++ b/components/ILIAS/TestQuestionPool/classes/forms/class.ilImagemapCorrectionsInputGUI.php
@@ -37,6 +37,10 @@ public function setAreasByArray($a_areas): void
$points_unchecked = $this->forms_helper->transformPoints($a_areas, 'points_unchecked');
foreach (array_keys($this->areas) as $index) {
+ if ($points[$index] === null) {
+ return;
+ }
+
$points_unchecked[$index] = $this->getPointsUncheckedFieldEnabled() && isset($points_unchecked[$index])
? $points_unchecked[$index] : 0.0;
diff --git a/components/ILIAS/TestQuestionPool/classes/ilTestLegacyFormsHelper.php b/components/ILIAS/TestQuestionPool/classes/ilTestLegacyFormsHelper.php
index e0f3236f61a5..ef851f7d9962 100644
--- a/components/ILIAS/TestQuestionPool/classes/ilTestLegacyFormsHelper.php
+++ b/components/ILIAS/TestQuestionPool/classes/ilTestLegacyFormsHelper.php
@@ -85,7 +85,7 @@ public function transformArray($data, string $key, Transformation $transformatio
}
return $this->refinery->byTrying([
- $this->refinery->kindlyTo()->listOf($transformation),
+ $this->refinery->kindlyTo()->dictOf($transformation),
$this->refinery->always([])
])->transform($data[$key]);
}
diff --git a/components/ILIAS/TestQuestionPool/classes/import/qti12/class.assFormulaQuestionImport.php b/components/ILIAS/TestQuestionPool/classes/import/qti12/class.assFormulaQuestionImport.php
index abdc136edeb9..5fb30a0a6003 100755
--- a/components/ILIAS/TestQuestionPool/classes/import/qti12/class.assFormulaQuestionImport.php
+++ b/components/ILIAS/TestQuestionPool/classes/import/qti12/class.assFormulaQuestionImport.php
@@ -84,6 +84,9 @@ public function fromXML(
$this->fetchAdditionalContentEditingModeInformation($item)
);
$this->object->saveToDb();
+
+ $this->importUnitsAndUnitCategories($item);
+
// handle the import of media objects in XHTML code
$questiontext = $this->object->getQuestion();
$feedbacksgeneric = $this->getFeedbackGeneric($item);
@@ -124,4 +127,79 @@ public function fromXML(
);
return $import_mapping;
}
+
+ private function importUnitsAndUnitCategories(ilQTIItem $item): void
+ {
+ /** @var ilUnitConfigurationRepository $unit_repository */
+ $unit_repository = $this->object->getUnitrepository();
+ foreach ($item->getUnitCategoryObjets() as $unit_category) {
+ $old_category_id = $unit_category->getId();
+
+ $unit_category->setQuestionFi($this->object->getId());
+ $unit_repository->saveNewUnitCategory($unit_category);
+
+ $units = [];
+ $base_unit_map = [];
+
+ foreach ($item->getUnitObjects() as $unit) {
+ if ($unit->getCategory() !== $old_category_id) {
+ continue;
+ }
+
+ $old_unit_id = $unit->getId();
+ $old_base_unit_id = $unit->getBaseUnit();
+ $old_unit_factor = $unit->getFactor();
+ $old_sequence = $unit->getSequence();
+
+ $unit->setCategory($unit_category->getId());
+ $unit->setFactor($old_unit_factor);
+ $unit->setSequence($old_sequence);
+
+ $unit_repository->createNewUnit($unit);
+ $unit->setBaseUnit($old_base_unit_id);
+
+ $units[] = $unit;
+ $base_unit_map[$old_unit_id] = $unit->getId();
+
+ $this->mapAssignedVariableUnits($unit, $old_unit_id);
+ $this->mapAssignedResultUnits($unit, $old_unit_id);
+ }
+
+ foreach ($units as $unit) {
+ $unit->setBaseUnit($base_unit_map[$unit->getBaseUnit()] ?? 0);
+ $unit_repository->saveUnit($unit);
+ }
+ }
+ }
+
+ private function mapAssignedVariableUnits(assFormulaQuestionUnit $unit, int $old_unit_id): void
+ {
+ /** @var assFormulaQuestionVariable $variable */
+ foreach ($this->object->getVariables() as $variable) {
+ $variable_unit = $variable->getUnit();
+ if ($variable_unit instanceof assFormulaQuestionUnit && $variable_unit->getId() === $old_unit_id) {
+ $variable_unit->setId($unit->getId());
+ }
+ }
+ }
+
+ private function mapAssignedResultUnits(assFormulaQuestionUnit $unit, int $old_unit_id): void
+ {
+ /** @var assFormulaQuestionResult $result */
+ foreach ($this->object->getResults() as $result) {
+ $result_unit = $result->getUnit();
+ if ($result_unit instanceof assFormulaQuestionUnit && $result_unit->getId() === $old_unit_id) {
+ $result_unit->setId($unit->getId());
+ }
+ }
+
+ /** @var assFormulaQuestionUnit[] $result */
+ foreach ($this->object->getAllResultUnits() as $result) {
+ foreach ($result as $result_unit) {
+ if ($result_unit instanceof assFormulaQuestionUnit && $result_unit->getId() === $old_unit_id) {
+ $result_unit->setId($unit->getId());
+ }
+ }
+ }
+ }
}
diff --git a/components/ILIAS/TestQuestionPool/resources/js/dist/longMenuQuestion.js b/components/ILIAS/TestQuestionPool/resources/js/dist/longMenuQuestion.js
index f49a3ab413cf..b9a7feb6d01b 100644
--- a/components/ILIAS/TestQuestionPool/resources/js/dist/longMenuQuestion.js
+++ b/components/ILIAS/TestQuestionPool/resources/js/dist/longMenuQuestion.js
@@ -382,7 +382,7 @@ var longMenuQuestion = (function () {
pro.redrawAnswerList = function(question_id)
{
pro.checkAnswersArray(question_id);
- const answer_options_element = document.querySelector('#ilGapModal .modal_answer_options');
+ const answer_options_element = document.querySelector(`#${pub.gap_modal_id} .modal_answer_options`);
answer_options_element.innerHTML = '';
if (pro.inputFieldsStillPossible(question_id))
diff --git a/components/ILIAS/TestQuestionPool/resources/js/dist/question_handling.js b/components/ILIAS/TestQuestionPool/resources/js/dist/question_handling.js
index 0204171c678f..511b9ae98838 100755
--- a/components/ILIAS/TestQuestionPool/resources/js/dist/question_handling.js
+++ b/components/ILIAS/TestQuestionPool/resources/js/dist/question_handling.js
@@ -48,7 +48,8 @@ ilias.questions.enhancedQuestionTypes = [
];
ilias.questions.questionTypesSupportingPartialScoring = [
- "assKprimChoice"
+ "assKprimChoice",
+ "assClozeTest"
];
ilias.questions.init = function() {
@@ -56,16 +57,14 @@ ilias.questions.init = function() {
};
ilias.questions.refresh_lang = function() {
-
jQuery(".ilc_qinput_ClozeGapSelect").each(function(){
- $(this).prepend("");
-
- $(this).val("");
+ if (!$(this).prop("disabled")) {
+ $(this).prepend(``);
+ $(this).val("");
+ }
});
jQuery("input[value='TXT_SUBMIT_ANSWERS']").val(ilias.questions.txt.submit_answers);
-
};
ilias.questions.shuffleAll = function() {
@@ -98,13 +97,14 @@ ilias.questions.swapper = function(a)
}
};
-ilias.questions.initAnswer = function(a_id, tries, passed) {
+ilias.questions.initAnswer = function(a_id, tries, passed, scored_points = null) {
if (!answers[a_id]) { // to keep answers[a_id].areas intact if initialized before
answers[a_id] = {};
}
answers[a_id].tries = tries;
answers[a_id].wrong = 0;
answers[a_id].passed = passed;
+ answers[a_id].scored_points = scored_points;
answers[a_id].answer = new Array();
answers[a_id].interactionId=null;
if (tries > 0 && (answers[a_id].tries >= questions[a_id].nr_of_tries || passed)) {
@@ -535,77 +535,99 @@ ilias.questions.assTextSubset = function(a_id) {
ilias.questions.assClozeTest = function(a_id) {
- answers[a_id].wrong = 0;
- answers[a_id].passed = true;
- answers[a_id].choice = [];
+ let value_found;
+ let a_node;
+ answers[a_id].wrong = 0;
+ answers[a_id].passed = true;
+ answers[a_id].isBestSolution = true;
+ answers[a_id].choice = [];
+
+ const gaps = questions[a_id].gaps;
+ for (let i = 0; i < gaps.length; i++) {
+ const gap = gaps[i];
+ const type = gap.type;
+
+ if (type !== 1) {
+ a_node = jQuery(`input#${a_id}_${i}`).get(0);
+ value_found = false;
+ }
- for (var i=0;i= 0) {
- answers[a_id].choice.push(questions[a_id].gaps[i].item[selected].order);
- }
- }
- else
- {
- var a_node = jQuery('input#'+a_id+"_"+i).get(0);
- var value_found = false;
+ let j;
+ const items = gap.item;
+ const max_points = Math.max(...items.map(item => item.points));
+ let points = 0;
+ switch (type) {
+ case 0:
+ for (j = 0; j < items.length; j++) {
+ if (items[j].value !== a_node.value) {
+ continue;
+ }
+
+ value_found = true;
+ if (items[j].points <= 0) {
+ answers[a_id].passed = false;
+ answers[a_id].wrong++;
+ answers[a_id].answer[i] = false;
+ continue;
+ }
+
+ answers[a_id].answer[i] = true;
+ points = items[j].points;
+ }
+ break
+ case 1:
+ a_node = jQuery(`select#${a_id}_${i}`).get(0);
+ const selected = a_node.options[a_node.selectedIndex].id;
+
+ if (parseInt(selected) < 0 || items[selected].points <= 0) {
+ answers[a_id].passed = false;
+ answers[a_id].wrong++;
+ answers[a_id].answer[i] = false;
+ } else {
+ answers[a_id].answer[i] = true;
+ points = items[selected].points;
+ }
- // text
- if (type==0) {
- for(var j=0;j= val) {
- value_found=true;
- if (questions[a_id].gaps[i].item[j].points <= 0) {
- answers[a_id].passed = false;
- answers[a_id].wrong++;
- answers[a_id].answer[i]=false;
- } else {
- answers[a_id].answer[i]=true;
- }
- }
- }
+ if (parseInt(selected) >= 0) {
+ answers[a_id].choice.push(items[selected].order);
+ }
+ break;
+ case 2:
+ for (let j = 0; j < items.length; j++) {
+ a_node.value = a_node.value.replace(',', '.');
+ const lb = parseFloat(items[j].lowerbound);
+ const ub = parseFloat(items[j].upperbound);
+ const val = parseFloat(a_node.value);
+
+ if (!isNaN(a_node.value) && lb <= val && ub >= val) {
+ value_found = true;
+ if (items[j].points <= 0) {
+ answers[a_id].passed = false;
+ answers[a_id].wrong++;
+ answers[a_id].answer[i] = false;
+ } else {
+ answers[a_id].answer[i] = true;
+ points = items[j].points;
+ }
+ }
+ }
+ break;
+ }
- }
+ if (type !== 1) {
+ answers[a_id].choice.push(a_node.value);
+ if (value_found === false) {
+ answers[a_id].passed = false;
+ answers[a_id].wrong++;
+ answers[a_id].answer[i] = false;
+ }
+ }
- answers[a_id].choice.push(a_node.value);
- if (value_found==false) {answers[a_id].passed = false; answers[a_id].wrong++; answers[a_id].answer[i]=false;}
- }
- }
- ilias.questions.showFeedback(a_id);
+ if (points !== max_points) {
+ answers[a_id].isBestSolution = false;
+ }
+ }
+ ilias.questions.showFeedback(a_id);
};
ilias.questions.initClozeTest = function(a_id) {
@@ -832,11 +854,20 @@ ilias.questions.showFeedback = function(a_id) {
answers[a_id].wrong ;
}
- if(jQuery.inArray(questions[a_id].type, ilias.questions.questionTypesSupportingPartialScoring) == -1)
- {
+ if (jQuery.inArray(questions[a_id].type, ilias.questions.questionTypesSupportingPartialScoring) === -1) {
answers[a_id].isBestSolution = answers[a_id].passed;
}
+ if (questions[a_id].type === "assClozeTest" && answers[a_id].isBestSolution === undefined) {
+ let total_max_points = 0;
+ const gaps = questions[a_id].gaps;
+ for (let i = 0; i < gaps.length; i++) {
+ total_max_points += Math.max(...gaps[i].item.map(item => item.points));
+ }
+
+ answers[a_id].isBestSolution = total_max_points === answers[a_id].scored_points;
+ }
+
jQuery('#feedback'+a_id).removeClass("ilc_qfeedw_FeedbackWrong");
jQuery('#feedback'+a_id).removeClass("ilc_qfeedr_FeedbackRight");
@@ -848,7 +879,7 @@ ilias.questions.showFeedback = function(a_id) {
if (answers[a_id].passed===true) {
jQuery('#feedback'+a_id).addClass("ilc_qfeedr_FeedbackRight");
- if( answers[a_id].isBestSolution ) {
+ if (answers[a_id].isBestSolution) {
if (ilias.questions.default_feedback) {
fbtext = '' + ilias.questions.txt.all_answers_correct + '
';
}
@@ -857,15 +888,15 @@ ilias.questions.showFeedback = function(a_id) {
fbtext += questions[a_id].feedback['allcorrect'];
}
- if( jQuery.inArray(questions[a_id].type, ilias.questions.enhancedQuestionTypes) == -1 ) {
+ if (jQuery.inArray(questions[a_id].type, ilias.questions.enhancedQuestionTypes) === -1) {
ilias.questions.showCorrectAnswers(a_id);
}
} else {
if (ilias.questions.default_feedback) {
fbtext = '' + ilias.questions.txt.enough_answers_correct + '
'
+ txt_wrong_answers + '
' + ilias.questions.txt.correct_answers_shown;
- } else if (questions[a_id].feedback['allcorrect']) {
- fbtext += questions[a_id].feedback['allcorrect'];
+ } else if (questions[a_id].feedback['onenotcorrect']) {
+ fbtext += questions[a_id].feedback['onenotcorrect'];
}
ilias.questions.showCorrectAnswers(a_id);
@@ -1154,36 +1185,34 @@ ilias.questions.showCorrectAnswers =function(a_id) {
break;
//end assMatchingQuestion
- case 'assClozeTest':
- for (var i=0;i=1)
- {
- cid=j;
- }
- }
- //jQuery('select#'+a_id+"_"+i+" option[id="+cid+"]").attr("selected","selected");
- jQuery('select#'+a_id+"_"+i+" option[id="+cid+"]").prop('selected', true);
- jQuery('select#'+a_id+"_"+i).prop("disabled",true);
- }
- if (type==0 || type==2) {
- var cvalue;
- //look for correct solution
- for (var j=0;j 0)
- {
- cvalue = questions[a_id].gaps[i].item[j].value;
- }
- }
- jQuery('input#'+a_id+"_"+i).val(cvalue);
- jQuery('input#'+a_id+"_"+i).prop("disabled",true);
- }
+ case 'assClozeTest':
+ for (let i = 0; i < questions[a_id].gaps.length; i++) {
+ const gap = questions[a_id].gaps[i];
+ const type = gap.type;
+ const items = gap.item;
+ const maxPoints = Math.max(...items.map(item => item.points));
+ const input = jQuery(`input#${a_id}_${i}`);
+ const select = jQuery(`select#${a_id}_${i}`);
+ let best_values;
+
+ switch (type) {
+ case 0:
+ best_values = items.filter(item => item.points === maxPoints).map(item => item.value);
+ input.val(best_values.join(' / '));
+ input.prop('disabled', true);
+ break;
+ case 1:
+ best_values = items.filter(item => item.points === maxPoints).map(item => item.value);
+ const option = jQuery(`select#${a_id}_${i} option[id="1"]`);
+ option.prop('selected', true);
+ option.text(best_values.join(' / '));
+ select.prop('disabled', true);
+ break;
+ case 2:
+ const best_value = items.find(item => item.points === maxPoints).value;
+ input.val(best_value);
+ input.prop('disabled', true);
+ }
}
break;
//end assClozeTest
diff --git a/components/ILIAS/TestQuestionPool/src/Questions/GeneralQuestionPropertiesRepository.php b/components/ILIAS/TestQuestionPool/src/Questions/GeneralQuestionPropertiesRepository.php
index 614beb9b99ad..8b31bfdcafe5 100755
--- a/components/ILIAS/TestQuestionPool/src/Questions/GeneralQuestionPropertiesRepository.php
+++ b/components/ILIAS/TestQuestionPool/src/Questions/GeneralQuestionPropertiesRepository.php
@@ -363,7 +363,7 @@ private function getForWhereClause(string $where): array
$questions = [];
while ($db_record = $this->db->fetchObject($query_result)) {
- if (!$this->isQuestionTypeAvailable($db_record->plugin_name)) {
+ if (!$this->isQuestionTypeAvailable((bool) $db_record->is_plugin, $db_record->type_tag)) {
continue;
}
$questions[$db_record->question_id] = $this
@@ -372,12 +372,9 @@ private function getForWhereClause(string $where): array
return $questions;
}
- /*
- * $param array $question_data
- */
- private function isQuestionTypeAvailable(?string $plugin_name): bool
+ private function isQuestionTypeAvailable(bool $is_plugin, string $question_type): bool
{
- if ($plugin_name === null) {
+ if ($is_plugin === false) {
return true;
}
@@ -386,10 +383,10 @@ private function isQuestionTypeAvailable(?string $plugin_name): bool
'TestQuestionPool'
)->getPluginSlotById('qst');
- if (!$plugin_slot->hasPluginName($plugin_name)) {
+ if (!$plugin_slot->hasPluginName($question_type)) {
return false;
}
- return $plugin_slot->getPluginByName($plugin_name)->isActive();
+ return $plugin_slot->getPluginByName($question_type)->isActive();
}
}
diff --git a/components/ILIAS/TestQuestionPool/src/Questions/Presentation/QuestionTable.php b/components/ILIAS/TestQuestionPool/src/Questions/Presentation/QuestionTable.php
index 8a8db51d96ac..a7018262d284 100755
--- a/components/ILIAS/TestQuestionPool/src/Questions/Presentation/QuestionTable.php
+++ b/components/ILIAS/TestQuestionPool/src/Questions/Presentation/QuestionTable.php
@@ -63,7 +63,7 @@ public function getTable(): Table\Data
return $this->ui_factory->table()->data(
$this,
$this->lng->txt('questions'),
- $this->getColums(),
+ $this->getColumns()
)
->withActions($this->getActions())
->withId('qpt' . $this->parent_obj_id . '_' . $this->request_ref_id);
@@ -136,7 +136,7 @@ public function getFilter(\ilUIService $ui_service, string $action): Filter
$active = array_fill(0, count($filter_inputs), true);
$filter = $ui_service->filter()->standard(
- 'question_table_filter_id',
+ "question_table_filter_{$this->request_ref_id}",
$action,
$filter_inputs,
$active,
@@ -147,7 +147,7 @@ public function getFilter(\ilUIService $ui_service, string $action): Filter
}
- public function getColums(): array
+ public function getColumns(): array
{
$f = $this->ui_factory->table()->column();
$df = $this->data_factory->dateFormat();
@@ -162,7 +162,7 @@ public function getColums(): array
'author' => $f->text($this->lng->txt('author'))->withIsOptional(true, true),
'lifecycle' => $f->text($this->lng->txt('qst_lifecycle'))->withIsOptional(true, true),
'taxonomies' => $f->text($this->lng->txt('qpl_settings_subtab_taxonomies'))->withIsOptional(true, true),
- 'feedback' => $f->boolean($this->lng->txt('feedback'), $icon_yes, $icon_no)->withIsOptional(true, true),
+ 'feedback' => $f->boolean($this->lng->txt('tst_feedback'), $icon_yes, $icon_no)->withIsOptional(true, true),
'created' => $f->date(
$this->lng->txt('create_date'),
$this->current_user->getDateTimeFormat()
@@ -330,27 +330,27 @@ protected function getActions(): array
{
$write_access = $this->rbac->checkAccess('write', $this->request_ref_id);
return array_merge(
- $this->buildAction('copy', 'standard'),
- $write_access ? $this->buildAction('move', 'standard') : [],
- $write_access ? $this->buildAction('delete', 'standard') : [],
- $this->buildAction('export', 'multi'),
- $this->buildAction('preview', 'single'),
- $this->buildAction('statistics', 'single'),
- $write_access ? $this->buildAction('edit_question', 'single') : [],
- $write_access ? $this->buildAction('edit_page', 'single') : [],
- $write_access ? $this->buildAction('feedback', 'single') : [],
- $write_access ? $this->buildAction(\ilBulkEditQuestionsGUI::CMD_EDITTAUTHOR, 'multi') : [],
- $write_access ? $this->buildAction(\ilBulkEditQuestionsGUI::CMD_EDITLIFECYCLE, 'multi') : [],
- $write_access ? $this->buildAction(\ilBulkEditQuestionsGUI::CMD_EDITTAXONOMIES, 'multi') : [],
- $this->showCommentAction() ? $this->buildAction('comments', 'single', true) : []
+ $this->buildAction('copy', 'copy', 'standard'),
+ $write_access ? $this->buildAction('move', 'move', 'standard') : [],
+ $write_access ? $this->buildAction('delete', 'delete', 'standard') : [],
+ $this->buildAction('export', 'export', 'multi'),
+ $this->buildAction('preview', 'preview', 'single'),
+ $this->buildAction('statistics', 'statistics', 'single'),
+ $write_access ? $this->buildAction('edit_question', 'edit_question', 'single') : [],
+ $write_access ? $this->buildAction('edit_page', 'edit_page', 'single') : [],
+ $write_access ? $this->buildAction('feedback', 'tst_feedback', 'single') : [],
+ $write_access ? $this->buildAction(\ilBulkEditQuestionsGUI::CMD_EDITTAUTHOR, 'bulkedit_author', 'multi') : [],
+ $write_access ? $this->buildAction(\ilBulkEditQuestionsGUI::CMD_EDITLIFECYCLE, 'bulkedit_lifecycle', 'multi') : [],
+ $write_access ? $this->buildAction(\ilBulkEditQuestionsGUI::CMD_EDITTAXONOMIES, 'bulkedit_taxonomies', 'multi') : [],
+ $this->showCommentAction() ? $this->buildAction('comments', 'comments', 'single', true) : []
);
}
- protected function buildAction(string $act, string $type, bool $async = false): array
+ protected function buildAction(string $act, string $lng_var, string $type, bool $async = false): array
{
$action = $this->ui_factory->table()->action()
->$type(
- $this->lng->txt($act),
+ $this->lng->txt($lng_var),
$this->url_builder->withParameter($this->action_parameter_token, $act),
$this->row_id_token
);
diff --git a/components/ILIAS/TestQuestionPool/src/RequestDataCollector.php b/components/ILIAS/TestQuestionPool/src/RequestDataCollector.php
index 26801bb7042b..dd4a08784419 100755
--- a/components/ILIAS/TestQuestionPool/src/RequestDataCollector.php
+++ b/components/ILIAS/TestQuestionPool/src/RequestDataCollector.php
@@ -245,6 +245,15 @@ public function rawArray(string $key): array
return $this->retrieveArray($key, 1, $this->refinery->identity());
}
+ public function getRowIdParameter(string $key): string|int
+ {
+ return $this->get($key, $this->refinery->byTrying([
+ $this->refinery->kindlyTo()->int(),
+ $this->refinery->kindlyTo()->string(),
+ $this->refinery->custom()->transformation(fn(array $v): string|int => $v[0])
+ ]));
+ }
+
/**
* @return array|string
*/
diff --git a/components/ILIAS/TestQuestionPool/src/RequestDataCollectorInterface.php b/components/ILIAS/TestQuestionPool/src/RequestDataCollectorInterface.php
index ebecb6fa70ac..c92e13064b95 100644
--- a/components/ILIAS/TestQuestionPool/src/RequestDataCollectorInterface.php
+++ b/components/ILIAS/TestQuestionPool/src/RequestDataCollectorInterface.php
@@ -54,4 +54,6 @@ public function getPostKeys(): array;
* @return array|string
*/
public function getMultiSelectionIds(string $key): array|string;
+
+ public function getRowIdParameter(string $key): string|int;
}
diff --git a/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTable.php b/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTable.php
index 28422fd4d64e..a09a11b9c688 100644
--- a/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTable.php
+++ b/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTable.php
@@ -22,7 +22,7 @@
use ILIAS\Data\Order;
use ILIAS\Data\Range;
-use ILIAS\TestQuestionPool\RequestDataCollector;
+use ILIAS\TestQuestionPool\RequestDataCollectorInterface;
use ILIAS\UI\Component\Table\DataRetrieval;
use ILIAS\UI\Component\Table\DataRowBuilder;
use ILIAS\UI\Factory as UIFactory;
@@ -33,7 +33,7 @@ class EditSkillsOfQuestionTable implements DataRetrieval
public const string ID = 'ska';
public function __construct(
- private readonly RequestDataCollector $pool_request,
+ private readonly RequestDataCollectorInterface $pool_request,
private readonly \ilAssQuestionSkillAssignmentList $assignment_list,
private readonly UIFactory $ui_factory,
private readonly \ilLanguage $lng,
@@ -46,7 +46,7 @@ public function __construct(
*/
public function getComponents(URLBuilder $url_builder): array
{
- $question = \assQuestionGUI::_getQuestionGUI('', $this->pool_request->getQuestionId())->getObject();
+ $question = \assQuestion::instantiateQuestion($this->pool_request->getQuestionId());
return [
$this->ui_factory->table()->data(
$this,
@@ -80,7 +80,7 @@ public function getRows(
'eval_mode' => $this->lng->txt($record->hasEvalModeBySolution()
? 'qpl_skill_point_eval_mode_solution_compare'
: 'qpl_skill_point_eval_mode_quest_result'),
- 'points' => $record->getSkillPoints(),
+ 'points' => $record->getMaxSkillPoints(),
]
),
$record
diff --git a/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTableEditAction.php b/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTableEditAction.php
index 8e130d00ffd7..8c2865822e32 100644
--- a/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTableEditAction.php
+++ b/components/ILIAS/TestQuestionPool/src/Skills/EditSkillsOfQuestionTableEditAction.php
@@ -31,7 +31,8 @@ class EditSkillsOfQuestionTableEditAction implements EditSkillsOfQuestionTableAc
public function __construct(
private readonly UIFactory $ui_factory,
- private readonly \ilLanguage $lng
+ private readonly \ilLanguage $lng,
+ private readonly bool $assignment_editing_enabled
) {
}
@@ -52,7 +53,7 @@ public function getTableAction(
URLBuilderToken $action_type_token
): Action {
return $this->ui_factory->table()->action()->single(
- $this->lng->txt('tst_edit_competence_assign'),
+ $this->lng->txt($this->assignment_editing_enabled ? 'tst_edit_competence_assign' : 'tst_view_competence_assign'),
$url_builder
->withParameter($action_token, self::ACTION_ID)
->withParameter($action_type_token, EditSkillsOfQuestionTableActions::SHOW_ACTION),
diff --git a/components/ILIAS/TestQuestionPool/src/Skills/SkillUsagesTable.php b/components/ILIAS/TestQuestionPool/src/Skills/SkillUsagesTable.php
index bde874700acf..a01274ebf0b5 100644
--- a/components/ILIAS/TestQuestionPool/src/Skills/SkillUsagesTable.php
+++ b/components/ILIAS/TestQuestionPool/src/Skills/SkillUsagesTable.php
@@ -51,6 +51,7 @@ public function getColumns(): array
return [
'skill_title' => $column_factory->text($this->lng->txt('qpl_qst_skl_usg_skill_col')),
+ 'skill_path' => $column_factory->text($this->lng->txt('tst_competence_tree')),
'num_assigns' => $column_factory->number($this->lng->txt('qpl_qst_skl_usg_numq_col')),
'max_points' => $column_factory->number($this->lng->txt('qpl_qst_skl_usg_sklpnt_col'))
];
diff --git a/components/ILIAS/TestQuestionPool/src/Skills/SkillsByQuestionOverviewTable.php b/components/ILIAS/TestQuestionPool/src/Skills/SkillsByQuestionOverviewTable.php
index d0d90e1604af..d6c233baabf5 100644
--- a/components/ILIAS/TestQuestionPool/src/Skills/SkillsByQuestionOverviewTable.php
+++ b/components/ILIAS/TestQuestionPool/src/Skills/SkillsByQuestionOverviewTable.php
@@ -68,7 +68,7 @@ private function mapRow(PresentationRow $row, SkillAssignments $record, URI $edi
: 'qpl_skill_point_eval_mode_quest_result'
)
)
- ->withProperty($this->lng->txt('tst_comp_points'), (string) $skill_assignment->getSkillPoints());
+ ->withProperty($this->lng->txt('tst_comp_points'), (string) $skill_assignment->getMaxSkillPoints());
}
$row = $row
diff --git a/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_mr_output_solution.html b/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_mr_output_solution.html
index 026b30ff8794..93f8c4240e3e 100755
--- a/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_mr_output_solution.html
+++ b/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_mr_output_solution.html
@@ -5,7 +5,7 @@
-

+
@@ -35,4 +35,4 @@
-
\ No newline at end of file
+
diff --git a/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_sr_output_solution.html b/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_sr_output_solution.html
index 6480d19741d7..24d3e5af75d9 100755
--- a/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_sr_output_solution.html
+++ b/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_mc_sr_output_solution.html
@@ -5,7 +5,7 @@
-

+
@@ -31,4 +31,4 @@
-
\ No newline at end of file
+
diff --git a/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_text_question_output_solution.html b/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_text_question_output_solution.html
index 56dfd8176783..e0c3c29e5976 100755
--- a/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_text_question_output_solution.html
+++ b/components/ILIAS/TestQuestionPool/templates/default/tpl.il_as_qpl_text_question_output_solution.html
@@ -7,7 +7,7 @@
-
{DIV_ESSAY}
+
{DIV_ESSAY}
{TA_ESSAY}
diff --git a/components/ILIAS/Tracking/classes/Setup/ProgressBlockUpdateSteps11.php b/components/ILIAS/Tracking/classes/Setup/ProgressBlockUpdateSteps11.php
index 282c3d1181f8..e5afef749a2d 100644
--- a/components/ILIAS/Tracking/classes/Setup/ProgressBlockUpdateSteps11.php
+++ b/components/ILIAS/Tracking/classes/Setup/ProgressBlockUpdateSteps11.php
@@ -57,4 +57,27 @@ public function step_1(): void
]);
$this->db->addPrimaryKey('ut_progress_block', ['obj_id']);
}
+
+ /**
+ * Fix column types in progress block table
+ */
+ public function step_2(): void
+ {
+ if (
+ !$this->db->tableExists('ut_progress_block') ||
+ !$this->db->tableColumnExists('ut_progress_block', 'obj_id')
+ ) {
+ return;
+ }
+ $this->db->modifyTableColumn(
+ 'ut_progress_block',
+ 'obj_id',
+ [
+ 'type' => ilDBConstants::T_INTEGER,
+ 'length' => 4,
+ 'default' => 0,
+ 'notnull' => true
+ ]
+ );
+ }
}
diff --git a/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php b/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php
index 4cdbcafa6542..80894e93a3c9 100644
--- a/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php
+++ b/components/ILIAS/Tracking/classes/class.ilLPProgressBlockGUI.php
@@ -43,6 +43,7 @@ public function __construct()
$this->setBlockId('lpprogress_' . $this->ctrl->getContextObjId());
$this->setTitle($this->lng->txt('trac_progress_block_title'));
$this->setPresentation(self::PRES_SEC_LEG);
+ $this->setActions();
}
public function getBlockType(): string
@@ -81,4 +82,29 @@ protected function getLegacyContent(): string
$mode_and_status
]);
}
+
+ protected function setActions(): void
+ {
+ $read_only_allowed = true;
+ if ($this->supportsMembers($this->requested_ref_id)) {
+ $read_only_allowed = ilParticipants::_isParticipant($this->requested_ref_id, $this->user->getId());
+ }
+ if (!ilLearningProgressAccess::checkAccess($this->requested_ref_id, $read_only_allowed)) {
+ return;
+ }
+ $this->ctrl->setParameterByClass(ilLearningProgressGUI::class, 'ref_id', $this->requested_ref_id);
+ $link = $this->ctrl->getLinkTargetByClass(ilLearningProgressGUI::class);
+ $this->ctrl->clearParameterByClass(ilLearningProgressGUI::class, 'ref_id');
+ $this->addBlockCommand($link, $this->lng->txt('trac_progress_block_details'));
+ }
+
+ protected function supportsMembers(int $ref_id): bool
+ {
+ try {
+ ilParticipants::getInstance($ref_id);
+ return true;
+ } catch (Exception) {
+ return false;
+ }
+ }
}
diff --git a/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php b/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php
index f31d186c119a..9f34b1d7bf49 100755
--- a/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php
+++ b/components/ILIAS/Tracking/classes/class.ilLPTableBaseGUI.php
@@ -32,7 +32,7 @@
*/
class ilLPTableBaseGUI extends ilTable2GUI
{
- public const HIT_LIMIT = 5000;
+ public const int HIT_LIMIT = 5000;
protected RefineryFactory $refinery;
protected HttpService $http;
@@ -190,20 +190,6 @@ public function executeCommand(): bool
$obj->writeToSession();
}
- if ($this->requested_tmpl_create !== "") {
- $this->ctrl->setParameter(
- $this->parent_obj,
- "tbltplcrt",
- $this->requested_tmpl_create
- );
- }
- if ($this->requested_tmpl_delete !== "") {
- $this->ctrl->setParameter(
- $this->parent_obj,
- "tbltpldel",
- $this->requested_tmpl_delete
- );
- }
$this->ctrl->redirect($this->parent_obj, $this->parent_cmd);
} else {
// e.g. repository selector
@@ -656,7 +642,6 @@ public function getCurrentFilter(bool $as_query = false): array
$item = $this->getFilterItemByPostVar($id);
switch ($id) {
case "title":
- case "country":
case "gender":
case "city":
case "language":
@@ -671,7 +656,7 @@ public function getCurrentFilter(bool $as_query = false): array
case "zipcode":
case "email":
case "matriculation":
- case "sel_country":
+ case "country":
case "query":
case "type":
case "area":
@@ -1029,11 +1014,10 @@ protected function getSelectableUserColumns(
): array {
$cols = $privacy_fields = array();
- $this->profile->skipGroup(AvailableSections::Interests);
if ($a_in_course === 1) {
- $ufs = $this->profile->getVisibleFields(Context::Course);
+ $ufs = $this->profile->getVisibleFields(Context::Course, null, [AvailableSections::Interests]);
} elseif ($a_in_group === 1) {
- $ufs = $this->profile->getVisibleFields(Context::Group);
+ $ufs = $this->profile->getVisibleFields(Context::Group, null, [AvailableSections::Interests]);
} else {
$ufs = $this->profile->getFields();
}
@@ -1138,6 +1122,9 @@ protected function getSelectableUserColumns(
)) {
// other user profile fields
foreach ($ufs as $fd) {
+ if ($fd->isCustom()) {
+ continue;
+ }
$f = $fd->getIdentifier();
if (!isset($cols[$f]) && $f !== "username" && !$fd->hiddenInLists()) {
$cols[$f] = array(
diff --git a/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php b/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php
index f27eaaf6f893..1debd834d1de 100755
--- a/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php
+++ b/components/ILIAS/Tracking/classes/class.ilLearningProgressBaseGUI.php
@@ -514,7 +514,7 @@ public function __appendLPDetails(
}
$info->addProperty(
- $this->lng->txt('trac_visits'),
+ $this->lng->txt('trac_visits_nr'),
(string) ($progress['visits'] ?? "")
);
diff --git a/components/ILIAS/Tracking/classes/class.ilTrQuery.php b/components/ILIAS/Tracking/classes/class.ilTrQuery.php
index 2109df97b16e..e09cb6114565 100755
--- a/components/ILIAS/Tracking/classes/class.ilTrQuery.php
+++ b/components/ILIAS/Tracking/classes/class.ilTrQuery.php
@@ -185,24 +185,24 @@ public static function getSCOsStatusForUser(
foreach ($a_sco_ids as $sco_id) {
// #9719 - can have in_progress AND failed/completed
if (in_array($a_user_id, $status_info["failed"][$sco_id])) {
- $status = ilLPStatus::LP_STATUS_FAILED;
+ $status = ilLPStatus::LP_STATUS_FAILED_NUM;
} elseif (in_array(
$a_user_id,
$status_info["completed"][$sco_id]
)) {
- $status = ilLPStatus::LP_STATUS_COMPLETED;
+ $status = ilLPStatus::LP_STATUS_COMPLETED_NUM;
} elseif (in_array(
$a_user_id,
$status_info["in_progress"][$sco_id]
)) {
- $status = ilLPStatus::LP_STATUS_IN_PROGRESS;
+ $status = ilLPStatus::LP_STATUS_IN_PROGRESS_NUM;
} else {
- $status = ilLPStatus::LP_STATUS_NOT_ATTEMPTED;
+ $status = ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM;
}
$items[$sco_id] = array(
"title" => $status_info["scos_title"][$sco_id],
- "status" => (int) $status,
+ "status" => $status,
"type" => "sahs",
"score" => (int) ($scores[$sco_id] ?? 0)
);
@@ -880,9 +880,8 @@ protected static function getSummaryDataForObject(
}
if ($valid) {
- $result["country"] = self::getSummaryPercentages("country", $query);
- $result["sel_country"] = self::getSummaryPercentages(
- "sel_country",
+ $result["country"] = self::getSummaryPercentages(
+ "country",
$query
);
$result["city"] = self::getSummaryPercentages("city", $query);
@@ -1131,7 +1130,6 @@ protected static function buildFilters(
case "street":
case "email":
case "matriculation":
- case "country":
case "city":
case "title":
$where[] = $ilDB->like(
@@ -1143,7 +1141,7 @@ protected static function buildFilters(
case "gender":
case "zipcode":
- case "sel_country":
+ case "country":
$where[] = "usr_data." . $id . " = " . $ilDB->quote(
$value,
"text"
diff --git a/components/ILIAS/Tracking/classes/object_statistics/class.ilLPObjectStatisticsAdminTableGUI.php b/components/ILIAS/Tracking/classes/object_statistics/class.ilLPObjectStatisticsAdminTableGUI.php
index 85992d1ecf4a..afdb1d2e1560 100755
--- a/components/ILIAS/Tracking/classes/object_statistics/class.ilLPObjectStatisticsAdminTableGUI.php
+++ b/components/ILIAS/Tracking/classes/object_statistics/class.ilLPObjectStatisticsAdminTableGUI.php
@@ -77,6 +77,11 @@ public function getItems(): void
$this->setData($data);
}
+ public function numericOrdering(string $a_field): bool
+ {
+ return $a_field === "count";
+ }
+
/**
* Fill table row
*/
diff --git a/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrMatrixTableGUI.php b/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrMatrixTableGUI.php
index bd066b7fcc8d..608526e15b60 100755
--- a/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrMatrixTableGUI.php
+++ b/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrMatrixTableGUI.php
@@ -705,7 +705,7 @@ protected function fillRowExcel(
case (substr($c, 0, 4) == "obj_"):
$obj_id = substr($c, 4);
$val = ilLearningProgressBaseGUI::_getStatusText(
- (int) $a_set[$c]
+ (int) ($a_set[$c] ?? ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM)
);
$a_excel->setCell($a_row, $cnt, $val);
@@ -723,7 +723,7 @@ protected function fillRowExcel(
case (substr($c, 0, 7) == "objsco_"):
case (substr($c, 0, 7) == "objsub_"):
$val = ilLearningProgressBaseGUI::_getStatusText(
- (int) $a_set[$c]
+ (int) ($a_set[$c] ?? ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM)
);
$a_excel->setCell($a_row, $cnt, $val);
break;
@@ -789,7 +789,7 @@ protected function fillRowCSV(ilCSVWriter $a_csv, array $a_set): void
case (substr($c, 0, 4) == "obj_"):
$obj_id = substr($c, 4);
$val = ilLearningProgressBaseGUI::_getStatusText(
- (int) $a_set[$c]
+ (int) ($a_set[$c] ?? ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM)
);
$a_csv->addColumn($val);
@@ -806,7 +806,7 @@ protected function fillRowCSV(ilCSVWriter $a_csv, array $a_set): void
case (substr($c, 0, 7) == "objsco_"):
case (substr($c, 0, 7) == "objsub_"):
$val = ilLearningProgressBaseGUI::_getStatusText(
- (int) $a_set[$c]
+ (int) ($a_set[$c] ?? ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM)
);
$a_csv->addColumn($val);
break;
diff --git a/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrObjectUsersPropsTableGUI.php b/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrObjectUsersPropsTableGUI.php
index 56ba89d466d3..0531e014a4aa 100755
--- a/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrObjectUsersPropsTableGUI.php
+++ b/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrObjectUsersPropsTableGUI.php
@@ -258,7 +258,6 @@ public function initFilter(): void
case "street":
case "zipcode":
case "city":
- case "country":
case "email":
case "matriculation":
case "login":
@@ -326,9 +325,9 @@ public function initFilter(): void
$this->filter["gender"] = $item->getValue();
break;
- case "sel_country":
+ case "country":
$item = $this->addFilterItemByMetaType(
- "sel_country",
+ "country",
ilTable2GUI::FILTER_SELECT,
true,
$meta["txt"]
@@ -343,7 +342,7 @@ public function initFilter(): void
array("" => $this->lng->txt("trac_all")) + $options
);
- $this->filter["sel_country"] = $item->getValue();
+ $this->filter["country"] = $item->getValue();
break;
case "status":
diff --git a/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrSummaryTableGUI.php b/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrSummaryTableGUI.php
index 764400d0cdde..e0dd3486de70 100755
--- a/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrSummaryTableGUI.php
+++ b/components/ILIAS/Tracking/classes/repository_statistics/class.ilTrSummaryTableGUI.php
@@ -93,7 +93,7 @@ public function __construct(
$labels = $this->getSelectableColumns();
foreach ($this->getSelectedColumns() as $c) {
// see bug #35119; these column list percentage lists and are not sortable
- if (in_array($c, ["status", "mark", "language", "country", "gender", "city", "sel_country"])) {
+ if (in_array($c, ["status", "mark", "language", "gender", "city", "country"])) {
$this->addColumn($labels[$c]["txt"]);
} else {
$this->addColumn($labels[$c]["txt"], $c);
@@ -184,7 +184,7 @@ public function getSelectableColumns(): array
$all[] = "mark";
}
- $privacy = array("gender", "city", "country", "sel_country");
+ $privacy = array("gender", "city", "country");
foreach ($privacy as $field) {
if (
($this->is_in_course && $this->setting->get("usr_settings_course_export_" . $field)) ||
@@ -386,18 +386,10 @@ public function initFilter(): void
$this->filter["city"] = $item->getValue();
}
+
if ($this->setting->get("usr_settings_course_export_country")) {
$item = $this->addFilterItemByMetaType(
"country",
- ilTable2GUI::FILTER_TEXT,
- true
- );
- $this->filter["country"] = $item->getValue();
- }
-
- if ($this->setting->get("usr_settings_course_export_sel_country")) {
- $item = $this->addFilterItemByMetaType(
- "sel_country",
ilTable2GUI::FILTER_SELECT,
true
);
@@ -407,7 +399,7 @@ public function initFilter(): void
)
) + $this->getSelCountryCodes()
);
- $this->filter["sel_country"] = $item->getValue();
+ $this->filter["country"] = $item->getValue();
}
$item = $this->addFilterItemByMetaType(
@@ -573,10 +565,6 @@ public function getItems(int $a_object_id, int $a_ref_id): void
// percentages
$users_no = $result["user_total"];
- $data["set"][$idx]["country"] = $this->getItemsPercentages(
- $result["country"],
- $users_no
- );
$data["set"][$idx]["gender"] = $this->getItemsPercentages(
$result["gender"],
$users_no,
@@ -590,8 +578,8 @@ public function getItems(int $a_object_id, int $a_ref_id): void
$result["city"],
$users_no
);
- $data["set"][$idx]["sel_country"] = $this->getItemsPercentages(
- $result["sel_country"],
+ $data["set"][$idx]["country"] = $this->getItemsPercentages(
+ $result["country"],
$users_no,
$this->getSelCountryCodes()
);
@@ -830,13 +818,12 @@ protected function fillRow(array $a_set): void
foreach ($this->getSelectedColumns() as $c) {
switch ($c) {
- case "country":
case "gender":
case "city":
case "language":
case "status":
case "mark":
- case "sel_country":
+ case "country":
$this->renderPercentages($c, $a_set[$c]);
break;
@@ -960,13 +947,13 @@ protected function isArrayColumn(string $a_name): bool
{
if (in_array(
$a_name,
- array("country",
+ array(
"gender",
"city",
"language",
"status",
"mark",
- 'sel_country'
+ 'country'
)
)) {
return true;
diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php
index 5e26a7c0b6ba..f8d991e89de1 100755
--- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php
+++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusTestPassed.php
@@ -19,6 +19,7 @@
declare(strict_types=0);
use ILIAS\Test\Results\Data\Repository;
+use ILIAS\Test\Participants\ParticipantRepository;
use ILIAS\Test\TestDIC;
/**
@@ -71,9 +72,27 @@ private static function getUserIdsByResultArrayStatus(
public static function _getStatusInfo(int $a_obj_id): array
{
- /** @var Repository $test_result_repository */
- $test_result_repository = TestDIC::dic()['results.data.repository'];
- $status_info['results'] = $test_result_repository->getPassedParticipants($a_obj_id);
+ /** @var ParticipantRepository $participant_repository */
+ $participant_repository = TestDIC::dic()['participant.repository'];
+ $test_id = ilObjTestAccess::_getTestIDFromObjectID($a_obj_id);
+
+ $lp_status = new self($a_obj_id);
+ $results = [];
+
+ foreach ($participant_repository->getParticipants($test_id) as $participant) {
+ $user_id = $participant->getUserId();
+ $status = $lp_status->determineStatus($a_obj_id, $user_id);
+
+ $results[] = [
+ 'user_id' => $user_id,
+ 'passed' => ($status === self::LP_STATUS_COMPLETED_NUM),
+ 'failed' => ($status === self::LP_STATUS_FAILED_NUM),
+ 'in_progress' => ($status === self::LP_STATUS_IN_PROGRESS_NUM),
+ 'not_attempted' => ($status === self::LP_STATUS_NOT_ATTEMPTED_NUM)
+ ];
+ }
+
+ $status_info['results'] = $results;
return $status_info;
}
diff --git a/components/ILIAS/Tracking/templates/default/tpl.trac_summary_row.html b/components/ILIAS/Tracking/templates/default/tpl.trac_summary_row.html
index 2198871f71cd..68df0f7ceaff 100755
--- a/components/ILIAS/Tracking/templates/default/tpl.trac_summary_row.html
+++ b/components/ILIAS/Tracking/templates/default/tpl.trac_summary_row.html
@@ -6,7 +6,7 @@
- {COLL_PATH}
+ {COLL_PATH}
@@ -85,17 +85,6 @@
-
-
-
-
-
- - {CAPTION}: {ABSOLUTE} ({PERCENTAGE}%)
-
-
-
- |
-
@@ -123,7 +112,7 @@
|
{PATH_ITEM} {TXT_DETAILS}
-
+
|
diff --git a/components/ILIAS/Tree/classes/class.ilPathGUI.php b/components/ILIAS/Tree/classes/class.ilPathGUI.php
index f932b4874749..0c1dec308807 100755
--- a/components/ILIAS/Tree/classes/class.ilPathGUI.php
+++ b/components/ILIAS/Tree/classes/class.ilPathGUI.php
@@ -33,6 +33,7 @@ class ilPathGUI
protected ilCtrlInterface $ctrl;
protected ilObjectDefinition $objectDefinition;
protected \ILIAS\Refinery\Factory $refinery;
+ private ilAccessHandler $access;
/**
* Constructor
@@ -48,6 +49,7 @@ public function __construct()
$this->ctrl = $DIC['ilCtrl'];
$this->objectDefinition = $DIC['objDefinition'];
$this->refinery = $DIC->refinery();
+ $this->access = $DIC->access();
}
/**
@@ -194,7 +196,9 @@ protected function getHTML(): string
$tpl->parseCurrentBlock();
}
- if (!$this->tree->isDeleted($ref_id)) {
+ if (!$this->tree->isDeleted($ref_id) &&
+ ($this->access->checkAccess('visible', '', (int) $ref_id)
+ || $this->access->checkAccess('read', '', (int) $ref_id))) {
$tpl->setCurrentBlock('locator_item');
$tpl->setVariable('LINK_ITEM', $this->buildLink($ref_id, $type));
$tpl->setVariable('ITEM', $title);
diff --git a/components/ILIAS/UI/resources/images/object/marked.svg b/components/ILIAS/UI/resources/images/object/marked.svg
old mode 100755
new mode 100644
index 937bb5e52949..b710f36ebbea
--- a/components/ILIAS/UI/resources/images/object/marked.svg
+++ b/components/ILIAS/UI/resources/images/object/marked.svg
@@ -1,21 +1,26 @@
-
-
-
-
+
+
\ No newline at end of file
diff --git a/components/ILIAS/UI/resources/images/object/marked_.svg b/components/ILIAS/UI/resources/images/object/marked_.svg
old mode 100755
new mode 100644
index 6c9911af60a3..2fb126c455d6
--- a/components/ILIAS/UI/resources/images/object/marked_.svg
+++ b/components/ILIAS/UI/resources/images/object/marked_.svg
@@ -1,7 +1,26 @@
-
-
-
-
+
+
\ No newline at end of file
diff --git a/components/ILIAS/UI/resources/images/standard/icon_attach.svg b/components/ILIAS/UI/resources/images/standard/icon_attach.svg
new file mode 100644
index 000000000000..24b39134104d
--- /dev/null
+++ b/components/ILIAS/UI/resources/images/standard/icon_attach.svg
@@ -0,0 +1,26 @@
+
+
\ No newline at end of file
diff --git a/components/ILIAS/UI/resources/images/standard/icon_drafts.svg b/components/ILIAS/UI/resources/images/standard/icon_drafts.svg
old mode 100755
new mode 100644
index c6a6a11532c6..2c980d720d30
--- a/components/ILIAS/UI/resources/images/standard/icon_drafts.svg
+++ b/components/ILIAS/UI/resources/images/standard/icon_drafts.svg
@@ -1,22 +1,26 @@
-
-
-
+
+
\ No newline at end of file
diff --git a/components/ILIAS/UI/resources/images/standard/icon_mailr.svg b/components/ILIAS/UI/resources/images/standard/icon_mailr.svg
index 93d113f8d1d3..0de7634f686d 100644
--- a/components/ILIAS/UI/resources/images/standard/icon_mailr.svg
+++ b/components/ILIAS/UI/resources/images/standard/icon_mailr.svg
@@ -1 +1,26 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/components/ILIAS/UI/resources/images/standard/icon_outbox.svg b/components/ILIAS/UI/resources/images/standard/icon_outbox.svg
index 17dcc1bfeb85..ffd890fea748 100644
--- a/components/ILIAS/UI/resources/images/standard/icon_outbox.svg
+++ b/components/ILIAS/UI/resources/images/standard/icon_outbox.svg
@@ -1,6 +1,6 @@
- |