aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/course/gradebook/lecturers.php164
-rw-r--r--app/controllers/course/gradebook/students.php23
-rw-r--r--app/controllers/course/gradebook/template_helpers.php19
-rw-r--r--app/views/course/gradebook/lecturers/custom_definitions.php21
-rw-r--r--app/views/course/gradebook/lecturers/edit_custom_definitions.php7
-rw-r--r--app/views/course/gradebook/lecturers/edit_ilias_definition.php26
-rw-r--r--app/views/course/gradebook/lecturers/edit_ilias_definitions.php75
-rw-r--r--app/views/course/gradebook/lecturers/index.php14
-rw-r--r--app/views/course/gradebook/lecturers/new_ilias_definition.php32
-rw-r--r--app/views/course/gradebook/students/index.php21
-rw-r--r--db/migrations/5.5.15_step3344_ilias_results.php32
-rw-r--r--lib/cronjobs/import_ilias_testresults.php51
-rw-r--r--lib/ilias_interface/ConnectedIlias.class.php15
-rw-r--r--lib/ilias_interface/IliasObjectConnections.class.php37
-rw-r--r--lib/ilias_interface/IliasSoap.class.php37
-rw-r--r--lib/modules/GradebookModule.class.php6
16 files changed, 559 insertions, 21 deletions
diff --git a/app/controllers/course/gradebook/lecturers.php b/app/controllers/course/gradebook/lecturers.php
index 2e98856..2cba5f3 100644
--- a/app/controllers/course/gradebook/lecturers.php
+++ b/app/controllers/course/gradebook/lecturers.php
@@ -43,6 +43,7 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
$this->groupedInstances = $this->groupedInstances($course);
$this->sumOfWeights = $this->getSumOfWeights($gradingDefinitions);
$this->totalSums = $this->sumOfWeights ? $this->getTotalSums($gradingDefinitions) : 0;
+ $this->totalPassed = $this->getTotalPassed($gradingDefinitions);
}
/**
@@ -71,6 +72,7 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
$categoryName = Definition::CUSTOM_DEFINITIONS_CATEGORY === $category ? _('Manuell eingetragen') : $category;
foreach ($this->groupedDefinitions[$category] as $definition) {
$headerLine[] = $categoryName.': '.$definition->name;
+ $headerLine[] = _('bestanden') . '(' . $categoryName.': '.$definition->name . ')';
}
}
$studentLines = [];
@@ -81,6 +83,9 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
$studentLine[] = isset($this->groupedInstances[$user->user_id][$definition->id])
? $this->groupedInstances[$user->user_id][$definition->id]->rawgrade
: 0;
+ $studentLine[] = isset($this->groupedInstances[$user->user_id][$definition->id])
+ ? $this->groupedInstances[$user->user_id][$definition->id]->passed
+ : 0;
}
}
$studentLines[] = $studentLine;
@@ -166,6 +171,8 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
)->pluck('id');
$grades = \Request::getArray('grades');
+ $passed = \Request::getArray('passed');
+ $feedback = \Request::getArray('feedback');
foreach ($grades as $studentId => $studentGrades) {
if (!in_array($studentId, $studentIds)) {
continue;
@@ -177,6 +184,8 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
$instance = new Instance([$definitionId, $studentId]);
$instance->rawgrade = ((int) $strGrade) / 100.0;
+ $instance->passed = $passed[$studentId][$definitionId] ?? 0;
+ $instance->feedback = $feedback[$studentId][$definitionId] ?? '';
$instance->store();
}
}
@@ -195,6 +204,9 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
$gradingDefinitions = Definition::findByCourse($course);
$this->groupedDefinitions = $this->getGroupedDefinitions($gradingDefinitions);
$this->customDefinitions = $this->groupedDefinitions[Definition::CUSTOM_DEFINITIONS_CATEGORY] ?? [];
+ if (!count($this->customDefinitions )) {
+ PageLayout::postInfo(_('Es sind keine manuellen Leistungen definiert.'));
+ }
}
/**
@@ -294,6 +306,131 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
$this->redirect('course/gradebook/lecturers/edit_custom_definitions');
}
+ public function edit_ilias_definitions_action()
+ {
+ if (Navigation::hasItem('/course/gradebook/edit_ilias_definitions')) {
+ Navigation::activateItem('/course/gradebook/edit_ilias_definitions');
+ }
+
+ $course = \Context::get();
+ $gradingDefinitions = Definition::findByCourse($course);
+ $this->groupedDefinitions = $this->getGroupedDefinitions($gradingDefinitions);
+ $this->customDefinitions = $this->groupedDefinitions['ILIAS'] ?? [];
+ $this->setupIliasSidebar(count($this->customDefinitions));
+ if (!count($this->customDefinitions )) {
+ PageLayout::postInfo(_('Es sind keine ILIAS-Tests als Leistungen definiert.'));
+ }
+ }
+
+ public function new_ilias_definition_action()
+ {
+ $this->ilias_modules = [];
+ $course = Course::findCurrent();
+ $already_defined = new SimpleCollection(Definition::findBySQL("course_id = ? AND category='ILIAS'", [$course->id]));
+ foreach (Config::get()->ILIAS_INTERFACE_SETTINGS as $ilias_index => $ilias_config) {
+ if ($ilias_config['is_active']) {
+ $ilias = new ConnectedIlias($ilias_index);
+ $this->ilias_modules[$ilias_index] = array_filter(
+ DBManager::get()->fetchFirst(
+ "SELECT module_id FROM object_contentmodules WHERE object_id=? AND system_type=? AND module_type='tst'", [$course->id, $ilias_index],
+ function ($module_id) use ($ilias, $already_defined) {
+ $item = $ilias->index . '-' . $module_id;
+ if (!$already_defined->findOneBy('item', $item)) {
+ return $ilias->getModule($module_id);
+ }
+ return null;
+ }
+ )
+ );
+ }
+ }
+ }
+
+ public function delete_ilias_definition_action($definitionId)
+ {
+ CSRFProtection::verifyUnsafeRequest();
+ if (!$definition = Definition::findOneBySQL(
+ 'id = ? AND course_id = ?',
+ [$definitionId, \Context::getId()]
+ )
+ ) {
+ \PageLayout::postError(_('Die Leistung konnte nicht gelöscht werden.'));
+ } else {
+ if (Definition::deleteBySQL('id = ?', [$definition->id])) {
+ \PageLayout::postSuccess(_('Die Leistung wurde gelöscht.'));
+ } else {
+ \PageLayout::postError(_('Die Leistung konnte nicht gelöscht werden.'));
+ }
+ }
+
+ $this->redirect('course/gradebook/lecturers/edit_ilias_definitions');
+ }
+
+ public function create_ilias_definition_action()
+ {
+ CSRFProtection::verifyUnsafeRequest();
+ $ilias_module = Request::get('ilias_module');
+ $module_import = Request::int('result') + Request::int('passed');
+ if (!$module_import) {
+ $module_import = 3;
+ }
+ if ($ilias_module) {
+ [$index, $module_id] = explode('-', $ilias_module);
+ $ilias = new ConnectedIlias($index);
+ $module = $ilias->getModule($module_id);
+ if ($module) {
+ $definition = Definition::create(
+ [
+ 'course_id' => \Context::getId(),
+ 'item' => $ilias_module . '-' . $module_import,
+ 'name' => $module->getTitle(),
+ 'tool' => 'ILIAS',
+ 'category' => 'ILIAS',
+ 'position' => 0,
+ 'weight' => 0.0,
+ ]
+ );
+
+ if (!$definition) {
+ \PageLayout::postError(_('Die Leistung konnte nicht definiert werden.'));
+ } else {
+ \PageLayout::postSuccess(_('Die Leistung wurde erfolgreich definiert.'));
+ }
+ }
+ }
+ $this->redirect('course/gradebook/lecturers/edit_ilias_definitions');
+ }
+
+ public function edit_ilias_definition_action($definition_id)
+ {
+ $this->definition = Definition::find($definition_id);
+ if ($this->definition && Request::submitted('test_name')) {
+ CSRFProtection::verifyUnsafeRequest();
+ $module_import = Request::int('result') + Request::int('passed');
+ [$index, $module_id] = explode('-', $this->definition->item );
+ $this->definition->name = Request::get('test_name');
+ $this->definition->item = $index . '-' . $module_id . '-' . $module_import;
+ if ($this->definition->store()) {
+ \PageLayout::postSuccess(_('Die Leistung wurde erfolgreich aktualisiert.'));
+ }
+
+ $this->redirect('course/gradebook/lecturers/edit_ilias_definitions');
+ }
+ }
+
+ public function import_ilias_results_action()
+ {
+ $num = IliasObjectConnections::importIliasResultsForCourse(Course::findCurrent());
+ PageLayout::postInfo(sprintf(
+ ngettext(
+ '%s Resultat wurde importiert.',
+ '%s Resultate wurden importiert.',
+ $num),
+ $num)
+ );
+ $this->redirect('course/gradebook/lecturers/edit_ilias_definitions');
+ }
+
public function getInstanceForUser(Definition $definition, \CourseMember $user)
{
if (!isset($this->groupedInstances[$user->user_id])) {
@@ -342,4 +479,31 @@ class Course_Gradebook_LecturersController extends AuthenticatedController
return $totalSums;
}
+
+ private function getTotalPassed($gradingDefinitions)
+ {
+ $gradingDefinitions = \SimpleCollection::createFromArray($gradingDefinitions);
+ $totalPassed = [];
+ foreach ($this->students as $student) {
+ if (!isset($totalPassed[$student->user_id])) {
+ $totalPassed[$student->user_id] = 0;
+ }
+
+ if (!isset($this->groupedInstances[$student->user_id])) {
+ continue;
+ }
+
+ foreach ($this->groupedInstances[$student->user_id] as $definitionId => $instance) {
+ if ($gradingDefinitions->findOneBy('id', $definitionId)) {
+ $totalPassed[$student->user_id] += $instance->passed;
+ }
+ }
+ }
+ $count = $gradingDefinitions->count();
+ $totalPassed = array_map(
+ function($p) use ($count) {
+ return $p == $count ? $p : 0;
+ }, $totalPassed);
+ return $totalPassed;
+ }
}
diff --git a/app/controllers/course/gradebook/students.php b/app/controllers/course/gradebook/students.php
index 81a1f7f..b00c22d 100644
--- a/app/controllers/course/gradebook/students.php
+++ b/app/controllers/course/gradebook/students.php
@@ -45,6 +45,8 @@ class Course_Gradebook_StudentsController extends AuthenticatedController
$this->sumOfWeights = $this->getSumOfWeights($this->gradingDefinitions);
$this->subtotals = $this->getSubtotalGrades();
$this->total = $this->getTotalGrade();
+ $this->subpassed = $this->getSubpassed();
+ $this->passed = array_sum($this->subpassed);
}
/**
@@ -75,6 +77,7 @@ class Course_Gradebook_StudentsController extends AuthenticatedController
$definition->name,
$definition->tool,
$instance ? $instance->rawgrade : 0,
+ $instance ? $instance->passed : 0,
$instance ? $instance->feedback : null,
];
}
@@ -85,6 +88,7 @@ class Course_Gradebook_StudentsController extends AuthenticatedController
_('Leistung'),
_('Werkzeug'),
_('Fortschritt'),
+ _('Bestanden'),
_('Feedback'),
];
$data = array_merge([$headerLine], $lines);
@@ -139,4 +143,23 @@ class Course_Gradebook_StudentsController extends AuthenticatedController
return $sumOfWeights ? $sumOfWeightedGrades / $sumOfWeights : 0;
}
+
+ private function getSubpassed()
+ {
+ $subpassed = [];
+
+ foreach ($this->groupedDefinitions as $category => $definitions) {
+ $passed = 0;
+
+ foreach ($definitions as $definition) {
+ if (isset($this->groupedInstances[$definition->id])) {
+ $instance = $this->groupedInstances[$definition->id];
+ $passed += $instance->passed;
+ }
+ }
+ $subpassed[$category] = $passed == count($definitions) ? $passed : 0;
+ }
+
+ return $subpassed;
+ }
}
diff --git a/app/controllers/course/gradebook/template_helpers.php b/app/controllers/course/gradebook/template_helpers.php
index b77822e..3cbd8b4 100644
--- a/app/controllers/course/gradebook/template_helpers.php
+++ b/app/controllers/course/gradebook/template_helpers.php
@@ -87,4 +87,23 @@ trait GradebookTemplateHelpers
\PageLayout::setTitle(Context::getHeaderLine().' - Gradebook');
\PageLayout::setHelpKeyword("Basis.Gradebook");
}
+
+ protected function setupIliasSidebar($num_definitions = 0)
+ {
+ $ilias = new \LinksWidget();
+ $ilias->setTitle(_('ILIAS'));
+ $ilias->addLink(
+ _('Test als Leistung hinzufügen'),
+ $this->url_for('course/gradebook/lecturers/new_ilias_definition'),
+ Icon::create('learnmodule+add')
+ )->asDialog();
+ if ($num_definitions) {
+ $ilias->addLink(
+ _('Ergebnisse aus ILIAS importieren'),
+ $this->url_for('course/gradebook/lecturers/import_ilias_results'),
+ Icon::create('refresh')
+ );
+ }
+ \Sidebar::Get()->addWidget($ilias);
+ }
}
diff --git a/app/views/course/gradebook/lecturers/custom_definitions.php b/app/views/course/gradebook/lecturers/custom_definitions.php
index 864aa0d..6b90698 100644
--- a/app/views/course/gradebook/lecturers/custom_definitions.php
+++ b/app/views/course/gradebook/lecturers/custom_definitions.php
@@ -1,14 +1,14 @@
<form class="default" action="<?= $controller->link_for('course/gradebook/lecturers/store_grades') ?>" method="POST">
<?= CSRFProtection::tokenTag()?>
<div style="overflow-x:auto;">
- <table class="default gradebook-lecturer-custom-definitions">
+ <table class="default gradebook-lecturer-custom-definitions sortable-table" data-sortlist="[[0, 0]]">
<caption>
<?= _('Noten manuell erfassen') ?>
</caption>
<thead>
- <tr class="tablesorter-ignoreRow">
- <th><?= _('Name') ?></th>
+ <tr class="sortable">
+ <th data-sort="text"><?= _('Name') ?></th>
<? if (count($customDefinitions)) { ?>
<? foreach ($customDefinitions as $definition) { ?>
<th>
@@ -35,13 +35,26 @@
<td class="gradebook-grade-input">
<? $instance = $controller->getInstanceForUser($definition, $student) ?>
<? $rawgrade = $instance ? $instance->rawgrade : 0 ?>
+ <? $passed = $instance ? $instance->passed : 0 ?>
+ <? $feedback = $instance ? $instance->feedback : '' ?>
<label class="undecorated">
<input type="number"
name="grades[<?= htmlReady($student->user_id) ?>][<?= htmlReady($definition->id) ?>]"
value="<?= $controller->formatAsPercent($rawgrade) ?>"
min="0"> %
</label>
-
+ <label>
+ <?=_('Bestanden')?>
+ <input type="checkbox"
+ name="passed[<?= htmlReady($student->user_id) ?>][<?= htmlReady($definition->id) ?>]"
+ value="1"
+ <?= $passed ? 'checked' : ''?>>
+ </label>
+ <label>
+ <input type="text"
+ name="feedback[<?= htmlReady($student->user_id) ?>][<?= htmlReady($definition->id) ?>]"
+ value="<?=htmlReady($feedback)?>" placeholder="<?=_('Feedback')?>">
+ </label>
</td>
<? } ?>
<? } elseif ($index === 0) { ?>
diff --git a/app/views/course/gradebook/lecturers/edit_custom_definitions.php b/app/views/course/gradebook/lecturers/edit_custom_definitions.php
index dbb3454..1901204 100644
--- a/app/views/course/gradebook/lecturers/edit_custom_definitions.php
+++ b/app/views/course/gradebook/lecturers/edit_custom_definitions.php
@@ -42,13 +42,6 @@
</tr>
<? } ?>
</tbody>
- <? } else { ?>
- <tbody>
- <tr>
- <td colspan="2">
- <?= \MessageBox::info(_('Es sind keine manuellen Leistungen definiert.')) ?>
- </td>
- </tbody>
<? } ?>
diff --git a/app/views/course/gradebook/lecturers/edit_ilias_definition.php b/app/views/course/gradebook/lecturers/edit_ilias_definition.php
new file mode 100644
index 0000000..3638907
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/edit_ilias_definition.php
@@ -0,0 +1,26 @@
+<?php
+/** @var StudipController $controller */
+/** @var \Grading\Definition $definition */
+?>
+<form class="default" action="<?=$controller->link_for('course/gradebook/lecturers/edit_ilias_definition/' . $definition->id) ?>" method="POST">
+ <?= CSRFProtection::tokenTag()?>
+ <fieldset>
+ <label>
+ <?= _('Name der Leistung') ?>
+ <input type="text" value="<?=htmlReady($definition->name)?>" name="test_name">
+ </label>
+ <label>
+ <?=_('Prozentwert übertragen')?>
+ <input type="checkbox" value="1" <?=substr($definition->item, -1) & 1 ? 'checked' : ''?> name="result">
+ </label>
+ <label>
+ <?=_('Bestanden/nicht bestanden übertragen')?>
+ <input type="checkbox" value="2" <?=substr($definition->item, -1) & 2 ? 'checked' : ''?> name="passed">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::createAccept(_('Speichern')) ?>
+ <?= \Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/gradebook/lecturers/edit_ilias_definitions')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/gradebook/lecturers/edit_ilias_definitions.php b/app/views/course/gradebook/lecturers/edit_ilias_definitions.php
new file mode 100644
index 0000000..1fd7a17
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/edit_ilias_definitions.php
@@ -0,0 +1,75 @@
+<?php
+/** @var Grading\Definition[] $customDefinitions */
+/** @var StudipController $controller */
+?>
+<table class="default">
+ <caption>
+ <?= _('ILIAS Leistungen definieren') ?>
+ </caption>
+
+ <thead>
+ <tr class="tablesorter-ignoreRow">
+ <th><?= _('Name') ?></th>
+ <th><?= _('ID') ?></th>
+ <th><?= _('Prozentwert') ?></th>
+ <th><?= _('Bestanden') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+
+ <? if (count($customDefinitions)) { ?>
+ <tbody>
+ <? foreach ($customDefinitions as $definition) { ?>
+ <tr>
+ <td>
+ <?= htmlReady($definition->name) ?>
+ </td>
+ <td>
+ <?= htmlReady($definition->item) ?>
+ </td>
+ <td>
+ <?= substr($definition->item, -1) & 1 ? 'x' : '' ?>
+ </td>
+ <td>
+ <?= substr($definition->item, -1) & 2 ? 'x' : '' ?>
+ <td class="actions">
+ <?=
+ \ActionMenu::get()
+ ->addLink(
+ $controller->url_for(
+ 'course/gradebook/lecturers/edit_ilias_definition',
+ $definition->id
+ ),
+ _('Ändern'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=fit']
+ )
+ ->addLink(
+ $controller->url_for(
+ 'course/gradebook/lecturers/delete_ilias_definition',
+ $definition->id
+ ),
+ _('Löschen'),
+ Icon::create('trash'),
+ ['onclick' => "return STUDIP.Dialog.confirmAsPost('" . _('Wollen Sie die Leistungsdefinition wirklich löschen?') . "', this.href);"]
+ ) ?>
+ </td>
+ </tr>
+ <? } ?>
+ </tbody>
+ <? } ?>
+
+
+ <tfoot class="gradebook-lecturer-custom-definitions-actions">
+ <tr>
+ <td colspan="5">
+ <?= \Studip\LinkButton::createAdd(
+ count($customDefinitions) ? _('Weiteren Test als Leistung definieren') : _('Test als Leistung definieren'),
+ $controller->url_for('course/gradebook/lecturers/new_ilias_definition'),
+ ['data-dialog' => 'size=fit']
+ ) ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+<?php
diff --git a/app/views/course/gradebook/lecturers/index.php b/app/views/course/gradebook/lecturers/index.php
index 62ebfcc..7e5523c 100644
--- a/app/views/course/gradebook/lecturers/index.php
+++ b/app/views/course/gradebook/lecturers/index.php
@@ -45,17 +45,21 @@
<?= $studentName ?>
</a>
</td>
- <? $totalSum = isset($totalSums[$student->user_id]) ? $totalSums[$student->user_id] : 0 ?>
- <td data-sort-value="<?= $totalSum?>">
- <?= $controller->formatAsPercent($totalSum) ?> %
+ <? $totalSum = $totalSums[$student->user_id] ?? 0 ?>
+ <? $totalPassed = $totalPassed[$student->user_id] ?? 0 ?>
+ <td data-sort-value="<?= $totalSum + $totalPassed?>">
+ <?= $totalSum > 0 ? $controller->formatAsPercent($totalSum) . ' %' : ''?>
+ <?= $totalPassed ? _('bestanden') : ''?>
</td>
<? foreach ($categories as $category) { ?>
<? foreach ($groupedDefinitions[$category] as $definition) { ?>
<? $instance = $controller->getInstanceForUser($definition, $student) ?>
<? $rawgrade = $instance ? $instance->rawgrade : 0 ?>
- <td data-sort-value="<? $rawgrade ?>">
- <?= $controller->formatAsPercent($rawgrade) ?> %
+ <? $passed = $instance ? $instance->passed : 0 ?>
+ <td data-sort-value="<?= $rawgrade + $passed ?>">
+ <?= $rawgrade > 0 ? $controller->formatAsPercent($rawgrade) . ' %' : ''?>
+ <?= $passed ? _('bestanden') : ''?>
</td>
<? } ?>
<? } ?>
diff --git a/app/views/course/gradebook/lecturers/new_ilias_definition.php b/app/views/course/gradebook/lecturers/new_ilias_definition.php
new file mode 100644
index 0000000..7a65c79
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/new_ilias_definition.php
@@ -0,0 +1,32 @@
+<?php
+/** @var StudipController $controller */
+/** @var array $ilias_modules */
+?>
+<form class="default" action="<?=$controller->link_for('course/gradebook/lecturers/create_ilias_definition') ?>" method="POST">
+ <?= CSRFProtection::tokenTag()?>
+ <fieldset>
+ <label>
+ <?= _('Bitte wählen Sie einen Test aus') ?>
+ <select name="ilias_module">
+ <? foreach ($ilias_modules as $key => $modules) : ?>
+ <? foreach ($modules as $module) : ?>
+ <option value="<?=$key . '-' . $module->getId()?>"><?=htmlReady($module->getTitle())?></option>
+ <? endforeach;?>
+ <? endforeach;?>
+ </select>
+ </label>
+ <label>
+ <?=_('Prozentwert übertragen')?>
+ <input type="checkbox" value="1" checked name="result">
+ </label>
+ <label>
+ <?=_('Bestanden/nicht bestanden übertragen')?>
+ <input type="checkbox" value="2" checked name="passed">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::createAccept(_('Speichern')) ?>
+ <?= \Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/gradebook/lecturers/edit_ilias_definitions')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/gradebook/students/index.php b/app/views/course/gradebook/students/index.php
index fb39eed..572067a 100644
--- a/app/views/course/gradebook/students/index.php
+++ b/app/views/course/gradebook/students/index.php
@@ -10,16 +10,25 @@
<article class="gradebook-student">
<header>
<h1><?= _("Gesamt") ?></h1>
- <?= $this->render_partial("course/gradebook/_progress", ['value' => $controller->formatAsPercent($total)])?>
+ <? if ($total > 0) : ?>
+ <?= $this->render_partial("course/gradebook/_progress", ['value' => $controller->formatAsPercent($total)])?>
+ <? endif ?>
+ <? if ($passed) : ?>
+ <div><?= _('bestanden')?></div>
+ <? endif ?>
</header>
<? foreach ($categories as $category) { ?>
<section class="gradebook-student-category">
<header>
<h2><?= $controller->formatCategory($category) ?></h2>
- <?= $this->render_partial("course/gradebook/_progress", ['value' => $controller->formatAsPercent($subtotals[$category])])?>
</header>
-
+ <? if ($subtotals[$category] > 0) : ?>
+ <?= $this->render_partial("course/gradebook/_progress", ['value' => $controller->formatAsPercent($subtotals[$category])])?>
+ <? endif ?>
+ <? if ($subpassed[$category]) : ?>
+ <div><?= _('bestanden')?></div>
+ <? endif ?>
<table class="default">
<colgroup>
<col width="200px" />
@@ -43,11 +52,15 @@
$instance = $groupedInstances[$definition->id] ?? null;
$grade = $controller->formatAsPercent($instance ? $instance->rawgrade : 0);
$feedback = $instance ? $instance->feedback : '';
+ $passed = $instance ? $instance->passed : 0;
?>
<tr>
<td>
<span class="gradebook-definition-name"><?= htmlReady($definition->name) ?></span>
- <?= $this->render_partial("course/gradebook/_progress", ['value' => (int) $grade])?>
+ <? if ($grade > 0) : ?>
+ <?= $this->render_partial("course/gradebook/_progress", ['value' => (int) $grade])?>
+ <? endif ?>
+ <div><?= $passed ? _('bestanden') : '' ?></div>
</td>
<td>
<?= htmlReady($definition->tool) ?>
diff --git a/db/migrations/5.5.15_step3344_ilias_results.php b/db/migrations/5.5.15_step3344_ilias_results.php
new file mode 100644
index 0000000..20bb33a
--- /dev/null
+++ b/db/migrations/5.5.15_step3344_ilias_results.php
@@ -0,0 +1,32 @@
+<?php
+require_once 'lib/cronjobs/import_ilias_testresults.php';
+final class Step3344IliasResults extends Migration
+{
+
+ use DatabaseMigrationTrait;
+
+ public function description()
+ {
+ return 'adds column passed to table `grading_instances`, add cronjob';
+ }
+
+ protected function up()
+ {
+ if (!$this->columnExists('grading_instances', 'passed')) {
+ DBManager::get()->exec("ALTER TABLE `grading_instances` ADD
+ `passed` TINYINT NOT NULL DEFAULT 0 AFTER `feedback`");
+
+ }
+ ImportIliasTestresults::register()->schedulePeriodic(45, 1);
+ }
+
+ protected function down()
+ {
+ if ($this->columnExists('grading_instances', 'passed')) {
+ DBManager::get()->exec("ALTER TABLE `grading_instances` DROP
+ `passed`");
+ }
+ ImportIliasTestresults::unregister();
+ }
+
+}
diff --git a/lib/cronjobs/import_ilias_testresults.php b/lib/cronjobs/import_ilias_testresults.php
new file mode 100644
index 0000000..c8c1225
--- /dev/null
+++ b/lib/cronjobs/import_ilias_testresults.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * ImportIliasTestresults
+ *
+ * @author André Noack <noack@data-quest.de>, Suchi & Berg GmbH <info@data-quest.de>
+ */
+
+class ImportIliasTestresults extends CronJob
+{
+ public static function getName()
+ {
+ return _('Testergebnisse aus ILIAS importieren');
+ }
+
+ public static function getDescription()
+ {
+ return _('Importiert Testergebnisse in das Gradebook');
+ }
+
+ public static function getParameters()
+ {
+ return [
+ 'verbose' => [
+ 'type' => 'boolean',
+ 'default' => false,
+ 'status' => 'optional',
+ 'description' => _('Sollen Ausgaben erzeugt werden (sind später im Log des Cronjobs sichtbar)'),
+ ]
+ ];
+ }
+
+ public function execute($last_result, $parameters = [])
+ {
+ $verbose = $parameters['verbose'];
+ $db = DBManager::get();
+ if (Config::get()->ILIAS_INTERFACE_ENABLE) {
+ $courses = $db->fetchFirst("SELECT DISTINCT course_id FROM grading_definitions WHERE tool='ILIAS'");
+ foreach ($courses as $course_id) {
+ $course = Course::find($course_id);
+ if ($course && $course->isToolActive('IliasInterfaceModule')) {
+ $num = IliasObjectConnections::importIliasResultsForCourse($course);
+ if ($verbose) {
+ echo 'Veranstaltung: ' . $course->name . ' '. $course->id . ': ' . $num . ' Ergebnisse übertragen.' . "\n";
+ }
+ }
+ }
+ } else {
+ echo 'ILIAS_INTERFACE is not enabled';
+ }
+ }
+}
diff --git a/lib/ilias_interface/ConnectedIlias.class.php b/lib/ilias_interface/ConnectedIlias.class.php
index dff41c8..6b82783 100644
--- a/lib/ilias_interface/ConnectedIlias.class.php
+++ b/lib/ilias_interface/ConnectedIlias.class.php
@@ -1346,4 +1346,19 @@ class ConnectedIlias
public function deleteConnectedModules($object_id){
return IliasObjectConnections::DeleteAllConnections($object_id, $this->index);
}
+
+ /**
+ * @param string $ilias_user_id
+ * @return IliasUser|void
+ */
+ public function getConnectedUser(string $ilias_user_id)
+ {
+ $user_id = DBManager::get()->fetchColumn(
+ "SELECT studip_user_id FROM auth_extern WHERE external_user_id = ? AND external_user_system_type = ?",
+ [$ilias_user_id, $this->index]
+ );
+ if ($user_id) {
+ return new IliasUser($this->index, $this->ilias_config['version'], $user_id);
+ }
+ }
}
diff --git a/lib/ilias_interface/IliasObjectConnections.class.php b/lib/ilias_interface/IliasObjectConnections.class.php
index 87468e9..0c6a8a9 100644
--- a/lib/ilias_interface/IliasObjectConnections.class.php
+++ b/lib/ilias_interface/IliasObjectConnections.class.php
@@ -135,7 +135,7 @@ class IliasObjectConnections
return false;
}
}
-
+
/**
* get module-id
*
@@ -273,4 +273,39 @@ class IliasObjectConnections
$statement->execute([$object_id, $cms_type]);
return $statement->rowCount();
}
+
+ /**
+ * @param Course $course
+ * @return int
+ */
+ public static function importIliasResultsForCourse(Course $course): int
+ {
+ $connected_ilias = [];
+ $students = new SimpleCollection($course->getMembersWithStatus('autor'));
+ $num = 0;
+ foreach (Grading\Definition::findBySQL("course_id = ? AND tool='ILIAS'", [$course->id]) as $definition) {
+ [$index, $module_id, $import_type] = explode('-', $definition->item);
+ if (!isset($connected_ilias[$index])) {
+ $connected_ilias[$index] = new ConnectedIlias($index);
+ }
+ $test_result = $connected_ilias[$index]->soap_client->getTestResults($module_id);
+ foreach ($test_result as $result) {
+ $ilias_user = $connected_ilias[$index]->getConnectedUser($result['user_id']);
+ if ($ilias_user) {
+ $member = $students->findOneBy('user_id', $ilias_user->getStudipId());
+ if ($member) {
+ $grade = Grading\Instance::import([
+ 'definition_id' => $definition->id,
+ 'user_id' => $member->user_id,
+ 'rawgrade' => $import_type & 1 && $result['maximum_points'] ? $result['received_points'] / $result['maximum_points'] : 0,
+ 'passed' => $import_type & 2 ? $result['passed'] : 0
+ ]
+ );
+ $num += $grade->store();
+ }
+ }
+ }
+ }
+ return $num;
+ }
}
diff --git a/lib/ilias_interface/IliasSoap.class.php b/lib/ilias_interface/IliasSoap.class.php
index d5647f4..37d7c62 100644
--- a/lib/ilias_interface/IliasSoap.class.php
+++ b/lib/ilias_interface/IliasSoap.class.php
@@ -1672,4 +1672,41 @@ class IliasSoap extends StudipSoapClient
}
return false;
}
+
+ /**
+ * @param string $ref_id
+ * @param bool $sum_only
+ * @return array|false
+ * @throws Exception
+ */
+ public function getTestResults($ref_id, $sum_only = true)
+ {
+ $param = [
+ 'sid' => $this->getSID(),
+ 'ref_id' => $ref_id,
+ 'sum_only' => $sum_only
+ ];
+ $result = $this->call('getTestResults', $param);
+ if ($result !== false) {
+ $columns = [];
+ $data = [];
+ $xml = simplexml_load_string($result);
+ foreach ($xml->colspecs->colspec as $colspec) {
+ $columns[] = (string)$colspec['name'];
+ }
+ foreach ($xml->rows->row as $row) {
+ $data_row = [];
+ $i = 0;
+ foreach ($row->column as $column) {
+ $data_row[$columns[$i++]] = (string)$column;
+ }
+ if (isset($data_row['user_id'])) {
+
+ }
+ $data[] = $data_row;
+ }
+ return $data;
+ }
+ return false;
+ }
}
diff --git a/lib/modules/GradebookModule.class.php b/lib/modules/GradebookModule.class.php
index 6c000a7..0423622 100644
--- a/lib/modules/GradebookModule.class.php
+++ b/lib/modules/GradebookModule.class.php
@@ -112,6 +112,12 @@ class GradebookModule extends CorePlugin implements SystemPlugin, StudipModule
'custom_definitions',
new Navigation(_('Noten manuell erfassen'), 'dispatch.php/course/gradebook/lecturers/custom_definitions')
);
+ if (Config::get()->ILIAS_INTERFACE_ENABLE && $cid && Course::findCurrent()->isToolActive('IliasInterfaceModule')) {
+ $navigation->addSubNavigation(
+ 'edit_ilias_definitions',
+ new Navigation(_('ILIAS-Test als Leistung definieren'), 'dispatch.php/course/gradebook/lecturers/edit_ilias_definitions')
+ );
+ }
}
/**