studip_module = checkObjectModule('CoursewareModule', true); object_set_visit_module($this->studip_module->getPluginId()); $this->last_visitdate = object_get_visit(Context::getId(), $this->studip_module->getPluginId()); } public function index_action() { /** @var array $last */ $last = UserConfig::get($GLOBALS['user']->id)->getValue('COURSEWARE_LAST_ELEMENT'); if (isset($last[Context::getId()])) { $this->entry_element_id = $last[Context::getId()]; /** @var ?StructuralElement $struct */ $struct = StructuralElement::findOneBySQL("id = ? AND range_id = ? AND range_type = 'course'", [ $this->entry_element_id, Context::getId(), ]); } // load courseware for course if (!$this->entry_element_id || !$struct || !$struct->canRead($GLOBALS['user'])) { $course = Course::find(Context::getId()); if (!$course->courseware) { // create initial courseware dataset StructuralElement::createEmptyCourseware(Context::getId(), 'course'); } $this->entry_element_id = $course->courseware->id; } $last[Context::getId()] = $this->entry_element_id; UserConfig::get($GLOBALS['user']->id)->store('COURSEWARE_LAST_ELEMENT', $last); Navigation::activateItem('course/courseware/content'); $this->setIndexSidebar(); $this->licenses = array(); $sorm_licenses = License::findBySQL("1 ORDER BY name ASC"); foreach($sorm_licenses as $license) { array_push($this->licenses, $license->toArray()); } $this->licenses = json_encode($this->licenses); } public function dashboard_action(): void { global $perm, $user; $course_progress = $perm->have_studip_perm('dozent', Context::getId(), $user->id); $this->courseware_progress_data = $this->getProgressData($course_progress); $this->courseware_chapter_counter = $this->getChapterCounter($this->courseware_progress_data); Navigation::activateItem('course/courseware/dashboard'); } public function manager_action(): void { $courseId = Context::getId(); $element = StructuralElement::getCoursewareCourse($courseId); $instance = new Instance($element); if (!$GLOBALS['perm']->have_studip_perm($instance->getEditingPermissionLevel(), $courseId)) { $this->redirect('course/courseware/index'); } else { Navigation::activateItem('course/courseware/manager'); } } private function setIndexSidebar(): void { $sidebar = Sidebar::Get(); $actions = new TemplateWidget( _('Aktionen'), $this->get_template_factory()->open('course/courseware/action_widget') ); $sidebar->addWidget($actions)->addLayoutCSSClass('courseware-action-widget'); $views = new TemplateWidget( _('Ansichten'), $this->get_template_factory()->open('course/courseware/view_widget') ); $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget'); } private function getProgressData(bool $course_progress = false): array { $data = []; $cid = Context::getId(); $course = Course::find($cid); $course_members = $course->getMembersWithStatus('autor'); $course_member_ids = array_column($course_members, 'user_id'); $elements = StructuralElement::findBySQL('range_id = ?', [$cid]); if ($course_progress) { $cw_user_progresses = UserProgress::findBySQL('user_id IN (?)', [$course_member_ids]); } else { $cw_user_progresses = UserProgress::findBySQL('user_id = ?', [ $GLOBALS['user']->id, ]); } foreach ($elements as $element) { $el = [ 'id' => $element->id, 'name' => $element->title, 'parent_id' => $element->parent->id, 'parent_name' => $element->parent->title, 'children' => $this->getChildren($element->children), ]; $el['progress'] = $this->getProgress($course, $element, $course_progress, $cw_user_progresses, $course_member_ids); array_push($data, $el); } //update children progress foreach ($data as &$element) { if (count($element['children'])) { foreach ($element['children'] as &$child) { foreach ($data as $el) { if ($el['id'] == $child['id']) { $child['progress'] = $el['progress']; } } } } } return $data; } private function getChildren($children): array { $data = []; foreach ($children as $child) { $el = [ 'id' => $child->id, 'name' => $child->title, ]; array_push($data, $el); } return $data; } private function getProgress(Course $course, StructuralElement $element, bool $course_progress = false, array $cw_user_progresses, array $course_member_ids): array { $descendants = $element->findDescendants(\User::findCurrent()); $count = count($descendants); $progress = 0; $own_progress = 0; foreach ($descendants as $el) { $block = $this->getBlocks($el->id, $course_progress, $cw_user_progresses, $course, $course_member_ids); if ($block['counter'] > 0) { $progress += $block['progress'] / $block['counter']; } else { $progress += 1; } } $own_blocks = $this->getBlocks($element->id, $course_progress, $cw_user_progresses, $course, $course_member_ids); if ($own_blocks['counter'] > 0) { $own_progress = $own_blocks['progress'] / $own_blocks['counter']; } else { $own_progress = 1; } $count = count($descendants); if ($count > 0) { $progress = ($progress + $own_progress) / ($count + 1); } else { $progress = $own_progress; } return ['total' => round($progress, 2) * 100, 'current' => round($own_progress, 2) * 100]; } private function getBlocks(string $element_id, bool $course_progress = false, array $cw_user_progresses, Course $course, array $course_member_ids): array { $containers = Courseware\Container::findBySQL('structural_element_id = ?', [intval($element_id)]); $blocks = []; $blocks['counter'] = 0; $blocks['progress'] = 0; $users_counter = count($course->getMembersWithStatus('autor')); foreach ($containers as $container) { $counter = $container->countBlocks(); $blocks['counter'] += $counter; if ($counter > 0) { $blks = Courseware\Block::findBySQL('container_id = ?', [$container->id]); foreach ($blks as $item) { if ($course_progress) { if ($users_counter > 0) { $progresses = array_filter($cw_user_progresses, function($progress) use ($item) { if ($progress->block_id === $item->id) { return true; } }); $users_progress = 0; foreach ($progresses as $prog) { if (in_array($prog->user_id, $course_member_ids)) { $users_progress += $prog->grade; } } $blocks['progress'] += $users_progress / $users_counter; } } else { $uid = $GLOBALS['user']->id; $progresses = array_filter($cw_user_progresses, function($progress) use ($item, $uid) { if ($progress->block_id === $item->id && $progress->user_id === $uid) { return true; } }); $progress = reset($progresses); if ($progress !== null) { $blocks['progress'] += intval($progress->grade); } } } } } return $blocks; } private function getChapterCounter(array $chapters): array { $finished = 0; $started = 0; $ahead = 0; foreach ($chapters as $chapter) { if ($chapter['parent_id'] != null) { if ($chapter['progress']['current'] == 0) { $ahead += 1; } if ($chapter['progress']['current'] > 0 && $chapter['progress']['current'] < 100) { $started += 1; } if ($chapter['progress']['current'] == 100) { $finished += 1; } } } return [ 'started' => $started, 'finished' => $finished, 'ahead' => $ahead, ]; } }