Select Git revision
Forked from
Uni Osnabrück / Plugins / Vips
285 commits behind, 96 commits ahead of the upstream repository.

Elmar Ludwig authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
api.php 9.84 KiB
<?php
/*
* api.php - Vips plugin for Stud.IP
* Copyright (c) 2021 Elmar Ludwig
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
class ApiController extends StudipController
{
public function assignments_action($course_id)
{
vips_require_status('tutor', $course_id);
$assignments = VipsAssignment::findBySQL('course_id = ? ORDER BY start', [$course_id]);
$data = [];
foreach ($assignments as $assignment) {
if ($assignment->type !== 'exam') {
$data[] = [
'id' => $assignment->id,
'link' => $this->url_for('api/assignment', $assignment->id),
'title' => $assignment->test->title,
'type' => $assignment->type,
'icon' => $assignment->getTypeIcon()->getShape(),
'start' => date('d.m.Y, H:i', strtotime($assignment->start)),
'end' => date('d.m.Y, H:i', strtotime($assignment->end)),
'active' => $assignment->active,
'block' => $assignment->block->name
];
}
}
$this->render_json($data);
}
public function assignment_action($assignment_id)
{
$assignment = VipsAssignment::find($assignment_id);
$user_id = $GLOBALS['user']->id;
$released = $assignment->releaseStatus($user_id);
if (!$assignment || !vips_has_status('autor', $assignment->course_id)) {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf dieses Aufgabenblatt!'));
}
if ($assignment->type === 'exam') {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf dieses Aufgabenblatt!'));
}
if (!$assignment->checkAccess() && $released < 3) {
throw new AccessDeniedException(_vips('Das Aufgabenblatt kann zur Zeit nicht bearbeitet werden.'));
}
// enter user start time the moment he/she first clicks on any exercise
if (!vips_has_status('tutor', $assignment->course_id)) {
$assignment->recordAssignmentAttempt($user_id);
}
$data = [
'id' => $assignment->id,
'title' => $assignment->test->title,
'type' => $assignment->type,
'icon' => $assignment->getTypeIcon()->getShape(),
'start' => date('d.m.Y, H:i', strtotime($assignment->start)),
'end' => date('d.m.Y, H:i', strtotime($assignment->end)),
'active' => $assignment->active,
'block' => $assignment->block->name,
'reset_allowed' => $assignment->isRunning() && $assignment->isResetAllowed(),
'points' => $assignment->test->getTotalPoints(),
'release_status' => $released,
'exercises' => []
];
foreach ($assignment->getExerciseRefs($user_id) as $exercise_ref) {
$template = $this->courseware_template($assignment, $exercise_ref, $released);
$exercise = $exercise_ref->exercise;
$data['exercises'][] = [
'id' => $exercise->id,
'link' => $this->url_for('api/exercise', $assignment_id, $exercise->id),
'type' => $exercise->type,
'title' => $exercise->title,
'template' => $template->render(),
'item_count' => $exercise->itemCount(),
'show_solution' => $template->show_solution
];
}
$this->render_json($data);
}
public function exercise_action($assignment_id, $exercise_id)
{
$assignment = VipsAssignment::find($assignment_id);
$user_id = $GLOBALS['user']->id;
$released = $assignment->releaseStatus($user_id);
check_exercise_assignment($exercise_id, $assignment);
if (!$assignment || !vips_has_status('autor', $assignment->course_id)) {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf dieses Aufgabenblatt!'));
}
if ($assignment->type === 'exam') {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf dieses Aufgabenblatt!'));
}
if (!$assignment->checkAccess() && $released < 3) {
throw new AccessDeniedException(_vips('Das Aufgabenblatt kann zur Zeit nicht bearbeitet werden.'));
}
// enter user start time the moment he/she first clicks on any exercise
if (!vips_has_status('tutor', $assignment->course_id)) {
$assignment->recordAssignmentAttempt($user_id);
}
$exercise_ref = VipsExerciseRef::find([$exercise_id, $assignment->test_id]);
$template = $this->courseware_template($assignment, $exercise_ref, $released);
$exercise = $exercise_ref->exercise;
$data = [
'id' => $exercise->id,
'type' => $exercise->type,
'title' => $exercise->title,
'template' => $template->render(),
'item_count' => $exercise->itemCount(),
'show_solution' => $template->show_solution
];
$this->render_json($data);
}
private function courseware_template($assignment, $exercise_ref, $released)
{
$user_id = $GLOBALS['user']->id;
$exercise = $exercise_ref->exercise;
$solution = $assignment->getSolution($user_id, $exercise->id);
$max_points = $exercise_ref->points;
$reached_points = $solution->points;
$show_solution = false;
if ($assignment->isRunning()) {
// if a solution has been submitted during a selftest
if ($assignment->type === 'selftest' && $solution) {
$max_tries = $assignment->options['max_tries'] ?: 3;
$tries_left = $max_tries - $solution->countTries();
if ($reached_points == $max_points || !$solution->corrected || $solution->corrector_id || $tries_left <= 0) {
$show_solution = true;
}
}
} else {
$show_solution = true;
if (!$solution) {
$solution = new VipsSolution();
$solution->assignment = $assignment;
}
}
if ($show_solution) {
$exercise_template = $exercise->getCorrectionTemplate($solution);
$exercise_template->show_solution = $released == 4;
} else {
$exercise_template = $exercise->getSolveTemplate($solution, $assignment, $user_id);
}
$template = $this->get_template_factory()->open('exercises/courseware_block');
$template->exercise = $exercise;
$template->exercise_template = $exercise_template;
$template->tries_left = $tries_left;
$template->solution = $solution;
$template->max_points = $max_points;
$template->reached_points = $reached_points;
$template->show_solution = $show_solution;
return $template;
}
public function solution_action($assignment_id, $exercise_id)
{
CSRFProtection::verifyUnsafeRequest();
$assignment = VipsAssignment::find($assignment_id);
$block_id = Request::int('block_id');
$user_id = $GLOBALS['user']->id;
check_exercise_assignment($exercise_id, $assignment);
// check access to courseware block
if ($block_id) {
$block = Courseware\Block::find($block_id);
$payload = $block->type->getPayload();
if ($payload['assignment'] != $assignment_id) {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf diesen Block!'));
}
}
if (!$assignment || !vips_has_status('autor', $assignment->course_id)) {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf dieses Aufgabenblatt!'));
}
if ($assignment->type === 'exam') {
throw new AccessDeniedException(_vips('Sie haben keinen Zugriff auf dieses Aufgabenblatt!'));
}
if (!$assignment->checkAccess()) {
throw new AccessDeniedException(_vips('Das Aufgabenblatt kann zur Zeit nicht bearbeitet werden.'));
}
// enter user start time the moment he/she first clicks on any exercise
if (!vips_has_status('tutor', $assignment->course_id)) {
$assignment->recordAssignmentAttempt($user_id);
}
if (Request::isPost()) {
$request = Request::getInstance();
$exercise = Exercise::find($exercise_id);
$solution = $exercise->getSolutionFromRequest($request, $_FILES);
$solution->user_id = $user_id;
$exercise->submitSolutionAction($this, $solution);
if ($solution->isEmpty()) {
$this->set_status(422);
} else {
$assignment->storeSolution($solution);
$this->set_status(201);
}
}
if (Request::isDelete()) {
if ($assignment->isResetAllowed()) {
$assignment->deleteSolution($user_id, $exercise_id);
$this->set_status(204);
} else {
$this->set_status(403);
}
}
// update user progress in Courseware
if ($assignment->type === 'selftest' && $block_id) {
$max_points = $assignment->test->getTotalPoints() ?: 1;
$progress = new Courseware\UserProgress([$user_id, $block_id]);
$progress->grade = $assignment->getUserPoints($user_id) / $max_points;
$progress->store();
}
$this->render_nothing();
}
}