Skip to content

[BUG] Falscher Observer UND falscher Nutzer bei Moodle-Quiz-Abgaben #496

Description

@ralferlebach

Problem

Der Abschluss eines Moodle-Quizversuchs führt nicht zuverlässig dazu, dass die zugehörige Lernpfad-Node neu ausgewertet und als abgeschlossen verbucht wird.

In db/events.php ist folgender Observer registriert:

[
    'eventname' => '\mod_quiz\event\attempt_finished',
    'callback' => 'local_adele_observer::quiz_attempt_finished',
],

Das Moodle-Quizmodul löst bei einer regulären Abgabe jedoch das Event

\mod_quiz\event\attempt_submitted

aus. Dieses Event enthält den Eigentümer des Versuchs in relateduserid. Beim ebenfalls beobachteten Event attempt_reviewed bezeichnet userid dagegen die Person, die den Versuch betrachtet, und relateduserid den Eigentümer des Versuchs.

Ursache

Es liegen zwei zusammenwirkende Fehler vor.

1. Falscher Eventname

db/events.php registriert:

\mod_quiz\event\attempt_finished

Im Plugin existiert zwar eine eigene Klasse

\local_adele\event\attempt_finished

registriert ist jedoch eine vermeintliche Klasse im Namespace mod_quiz. Dadurch wird bei einer regulären Quizabgabe kein passender Observer aufgerufen.

2. Falsche Benutzer-ID

In classes/learning_path_update.php wird der Lernpfad über

$event->userid

geladen:

$records = $userpathrelation->get_learning_paths(
    $event->userid,
    null,
    '"quizid":"' . $event->other['quizid'] . '"'
);

Bei fremden Aktionen, beispielsweise wenn ein Lehrender den Versuch eines Studierenden betrachtet, bezeichnet userid den Lehrenden und relateduserid den Studierenden.

Lösung

Eventregistrierung korrigieren

- 'eventname' => '\mod_quiz\event\attempt_finished',
+ 'eventname' => '\mod_quiz\event\attempt_submitted',

Betroffenen Benutzer korrekt ermitteln

public static function quiz_finished(
    \mod_quiz\event\attempt_submitted $event
): void {
    $userid = (int) $event->relateduserid;
    $quizid = (int) $event->other['quizid'];

    self::recompute_quiz_paths($userid, $quizid);
}

Die eigentliche Neuberechnung sollte in einer eventunabhängigen Methode gekapselt werden:

private static function recompute_quiz_paths(
    int $userid,
    int $quizid
): void {
    // Betroffene aktive Lernpfade ermitteln und einmal neu berechnen.
}

attempt_reviewed sollte nicht als fachlicher Änderungstrigger verwendet werden, da das reine Anzeigen eines Versuchs keinen Bewertungszustand ändert.

Manuelles Testverfahren

Vorbereitung

  1. Einen Hostkurs mit einem Adele-Lernpfad anlegen.
  2. Eine Node mit einem Moodle-Quiz verknüpfen.
  3. Als Abschlusskriterium beispielsweise mindestens 5 von 10 Quizpunkten konfigurieren.
  4. Einen Studierenden in den Hostkurs einschreiben.
  5. Sicherstellen, dass für den Studierenden ein aktiver Datensatz in local_adele_path_user existiert.
  6. Die Node zunächst als nicht abgeschlossen prüfen.

Testschritte

  1. Als Studierender das Quiz mit mindestens 5 Punkten abschließen und abgeben.
  2. Den Lernpfad nicht erneut öffnen.
  3. Als Administrator den Datensatz in local_adele_path_user kontrollieren.
  4. Prüfen, ob die Node nach der Quizabgabe automatisch als abgeschlossen gespeichert wurde.
  5. Als Lehrender die Ergebnisansicht des Studierenden öffnen.
  6. Den Datensatz erneut prüfen.
  7. Abschließend als Studierender den Hostkurs beziehungsweise die Lernpfadansicht öffnen.

Aktuelles Ist-Verhalten

  • Die reguläre Quizabgabe löst keine Aktualisierung aus, weil attempt_finished nicht ausgelöst wird.
  • Das Öffnen des Versuchs durch den Lehrenden löst zwar attempt_reviewed aus, die Verarbeitung sucht aber nach dem Lernpfad des Lehrenden.
  • Erst das spätere Öffnen des Hostkurses kann über course_viewed eine Neuberechnung auslösen.
  • Die Node wird dadurch verspätet oder gar nicht aktualisiert.

Erwartetes Soll-Verhalten

Unmittelbar nach der Quizabgabe wird der Lernpfad des Studierenden neu berechnet. Die Node erhält ohne zusätzlichen Seitenaufruf den fachlich korrekten Status.

Automatisierte Tests

  • PHPUnit-Test für attempt_submitted.
  • Unterschiedliche Werte für userid und relateduserid.
  • Sicherstellen, dass ausschließlich der Lernpfad aus relateduserid aktualisiert wird.
  • Sicherstellen, dass attempt_reviewed keine unnötige Neuberechnung auslöst.
  • Behat-Test für den vollständigen Ablauf Quizabgabe → Node-Abschluss.

Akzeptanzkriterien

  • attempt_submitted ist als Observer registriert.
  • Der Studierende wird über relateduserid ermittelt.
  • Eine Quizabgabe aktualisiert den Lernpfad ohne zusätzlichen Seitenaufruf.
  • Fremde Reviews aktualisieren nicht den Lernpfad des Lehrenden.
  • Pro betroffenem Lernpfad wird maximal eine Neuberechnung ausgelöst.
  • PHPUnit- und Behat-Regressionstests sind vorhanden.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions