Skip to content
Snippets Groups Projects
Commit 3d3eaee5 authored by André Noack's avatar André Noack
Browse files

Resolve #3344 "Testergebnisse aus ILIAS in das Stud.IP Gradebook importieren"

Closes #3344

Merge request studip/studip!2271
parent e45e4fed
No related branches found
No related tags found
No related merge requests found
Showing
with 559 additions and 21 deletions
......@@ -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;
}
}
......@@ -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;
}
}
......@@ -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);
}
}
<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) { ?>
......
......@@ -42,13 +42,6 @@
</tr>
<? } ?>
</tbody>
<? } else { ?>
<tbody>
<tr>
<td colspan="2">
<?= \MessageBox::info(_('Es sind keine manuellen Leistungen definiert.')) ?>
</td>
</tbody>
<? } ?>
......
<?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>
<?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
......@@ -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>
<? } ?>
<? } ?>
......
<?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>
......@@ -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) ?>
......
<?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();
}
}
<?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';
}
}
}
......@@ -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);
}
}
}
......@@ -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;
}
}
......@@ -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;
}
}
......@@ -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')
);
}
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment