getFullName(), _("Themen"))); $course = Course::findCurrent(); $this->forum_activated = $course->isToolActive(CoreForum::class); $this->documents_activated = $course->isToolActive(CoreDocuments::class); if ( !in_array($action, ['index', 'details']) && !User::findCurrent()->hasPermissionLevel('tutor', Context::get()) ) { throw new AccessDeniedException(); } $this->setupSidebar($action); } public function index_action() { $this->topics = CourseTopic::findBySeminar_id(Context::getId()); $this->topic_links = $this->createLinksForTopics($this->topics); $this->cancelled_dates_locked = LockRules::Check(Context::getId(), 'cancelled_dates'); } public function delete_action(CourseTopic $topic) { CSRFProtection::verifyUnsafeRequest(); if ($topic->seminar_id && ($topic->seminar_id !== Context::getId())) { throw new AccessDeniedException(); } if ($topic->delete()) { PageLayout::postSuccess(_('Thema gelöscht.')); } $this->redirect('course/topics'); } public function edit_action(?CourseTopic $topic = null) { PageLayout::setTitle($topic->isNew() ? _('Neues Thema erstellen') : sprintf(_('Bearbeiten: %s'), $topic->title)); $this->dates = CourseDate::findBySeminar_id(Context::getId()); } public function store_action(?CourseTopic $topic = null) { if (!Request::isPost()) { throw new MethodNotAllowedException(); } if ($topic->seminar_id && ($topic->seminar_id !== Context::getId())) { throw new AccessDeniedException(); } $topic->title = Request::i18n("title"); $topic->description = Request::i18n('description', null, function ($string) { return Studip\Markup::purifyHtml($string); }); $topic->paper_related = Request::bool('paper_related', false); if ($topic->isNew()) { $topic->seminar_id = Context::getId(); } $topic->store(); //change dates for this topic $former_date_ids = $topic->dates->pluck('termin_id'); $new_date_ids = array_keys(Request::getArray('date')); foreach (array_diff($former_date_ids, $new_date_ids) as $delete_termin_id) { $topic->dates->unsetByPk($delete_termin_id); } foreach (array_diff($new_date_ids, $former_date_ids) as $add_termin_id) { $date = CourseDate::find($add_termin_id); if ($date) { $topic->dates[] = $date; } } $topic->store(); if (Request::bool('folder')) { $topic->connectWithDocumentFolder(); } if (Request::bool('forumthread')) { $topic->connectWithForumThread(); } PageLayout::postSuccess(_('Thema gespeichert.')); $this->redirect($this->indexURL()); } public function swap_action(CourseTopic $a, CourseTopic $b) { if (!Request::isPost()) { throw new MethodNotAllowedException(); } if ( $a->seminar_id !== Context::getId() || $b->seminar_id !== Context::getId() ) { throw new Exception(_('Eines oder mehrere Themen gehören nicht zur ausgewählten Veranstaltung.')); } [$a->priority, $b->priority] = [$b->priority, $a->priority]; $a->store(); $b->store(); $this->redirect($this->indexURL()); } public function allow_public_action() { $config = CourseConfig::get(Context::getId()); $config->store('COURSE_PUBLIC_TOPICS', !$config->COURSE_PUBLIC_TOPICS); $this->redirect("course/topics"); } public function copy_action() { if (Request::submitted("copy")) { $prio = 1; foreach (Course::find(Context::getId())->topics as $topic) { $prio = max($prio, $topic['priority']); } foreach (Request::getArray("topic") as $topic_id => $value) { $topic = new CourseTopic($topic_id); $topic = clone $topic; $topic['seminar_id'] = Context::getId(); $topic['priority'] = $prio; $prio++; $topic->setId($topic->getNewId()); $topic->setNew(true); $topic->store(); NotificationCenter::postNotification('TopicDidCopy', $topic_id, $topic->id); } PageLayout::postMessage(MessageBox::success(sprintf(_("%s Themen kopiert."), count(Request::getArray("topic"))))); $this->redirect("course/topics"); } $semester_sql = " CONCAT('(',IFNULL(GROUP_CONCAT(DISTINCT semester_data.name ORDER BY semester_data.beginn SEPARATOR '-'),'" . _('unbegrenzt') . "'),')')"; if ($GLOBALS['perm']->have_perm("root")) { $this->courseSearch = new SQLSearch(" SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, $semester_sql, '(', COUNT(issue_id), ')') FROM seminare LEFT JOIN semester_courses ON (seminare.Seminar_id = semester_courses.course_id) LEFT JOIN semester_data ON (semester_data.semester_id = semester_courses.semester_id) INNER JOIN themen ON themen.seminar_id = seminare.Seminar_id WHERE seminare.VeranstaltungsNummer LIKE :input OR seminare.name LIKE :input GROUP BY seminare.Seminar_id ORDER BY semester_data.beginn DESC, seminare.VeranstaltungsNummer ASC, seminare.name ASC ", _("Veranstaltung suchen"), "seminar_id" ); } elseif ($GLOBALS['perm']->have_perm("admin")) { $this->courseSearch = new SQLSearch(" SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, $semester_sql, '(', COUNT(issue_id), ')') FROM seminare INNER JOIN seminar_inst ON (seminare.Seminar_id = seminar_inst.seminar_id) INNER JOIN user_inst ON (user_inst.Institut_id = seminar_inst.institut_id) LEFT JOIN semester_courses ON (seminare.Seminar_id = semester_courses.course_id) LEFT JOIN semester_data ON (semester_data.semester_id = semester_courses.semester_id) INNER JOIN themen ON themen.seminar_id = seminare.Seminar_id WHERE seminare.VeranstaltungsNummer LIKE :input OR seminare.name LIKE :input AND user_inst.user_id = ".DBManager::get()->quote($GLOBALS['user']->id)." AND user_inst.inst_perms = 'admin' GROUP BY seminare.Seminar_id ORDER BY semester_data.beginn DESC, seminare.VeranstaltungsNummer ASC, seminare.name ASC ", _("Veranstaltung suchen"), "seminar_id" ); } else { $this->courseSearch = new SQLSearch(" SELECT seminare.Seminar_id, CONCAT_WS(' ', seminare.VeranstaltungsNummer, seminare.name, $semester_sql, '(', COUNT(issue_id), ')') FROM seminare INNER JOIN seminar_user ON (seminare.Seminar_id = seminar_user.Seminar_id) LEFT JOIN semester_courses ON (seminare.Seminar_id = semester_courses.course_id) LEFT JOIN semester_data ON (semester_data.semester_id = semester_courses.semester_id) INNER JOIN themen ON themen.seminar_id = seminare.Seminar_id WHERE seminare.VeranstaltungsNummer LIKE :input OR seminare.name LIKE :input AND seminar_user.status IN ('tutor', 'dozent') AND seminar_user.user_id = ".DBManager::get()->quote($GLOBALS['user']->id)." GROUP BY seminare.Seminar_id ORDER BY semester_data.beginn DESC, seminare.VeranstaltungsNummer ASC, seminare.name ASC ", _("Veranstaltung suchen"), "seminar_id" ); } PageLayout::setTitle(_("Themen aus Veranstaltung kopieren")); } public function fetch_topics_action() { $this->topics = CourseTopic::findBySeminar_id(Request::option("seminar_id")); $output = [ 'html' => $this->render_template_as_string("course/topics/_topiclist.php") ]; $this->render_json($output); } public function bulk_action(string $action): void { CSRFProtection::verifyUnsafeRequest(); $topic_ids = Request::optionArray('topics'); [$callback, $success, $failure] = match ($action) { 'ftopic' => [ fn(CourseTopic $topic) => $topic->connectWithForumThread(), _('Forumsthemen erfolgreich angelegt.'), _('Fehler beim Anlegen von Forumsthemen zu:'), ], 'folder' => [ fn(CourseTopic $topic) => $topic->connectWithDocumentFolder(), _('Ordner erfolgreich angelegt.'), _('Fehler beim Anlegen von Ordnern zu:'), ], 'delete' => [ fn(CourseTopic $topic) => $topic->delete(), _('Erfolgreich gelöscht.'), _('Fehler beim Löschen von:'), ], default => throw new InvalidArgumentException('Unknown action'), }; $errors = []; CourseTopic::findEachMany( function (CourseTopic $topic) use ($callback, &$errors) { if (!$callback($topic)) { $errors[] = $topic->title; } }, $topic_ids ); if (count($errors) === 0) { PageLayout::postSuccess($success); } else { PageLayout::postError( $failure, array_map('htmlReady', $errors) ); } $this->redirect($this->indexURL()); } public function details_action(CourseTopic $topic) { PageLayout::setTitle(sprintf(_('Details: %s'), htmlReady($topic->title))); $this->render_template('course/topics/details'); } private function setupSidebar($action) { $sidebar = Sidebar::get(); $actions = $sidebar->addWidget(new ActionsWidget()); if ($GLOBALS['perm']->have_studip_perm('tutor', Context::getId())) { $actions->addLink( _('Neues Thema erstellen'), $this->url_for('course/topics/edit'), Icon::create('add') )->asDialog(); $actions->addLink( _('Themen aus Veranstaltung kopieren'), $this->url_for('course/topics/copy'), Icon::create('clipboard') )->asDialog(); } if ($GLOBALS['perm']->have_studip_perm('tutor', Context::getId())) { $options = $sidebar->addWidget(new OptionsWidget()); $options->addCheckbox( _('Themen öffentlich einsehbar'), (bool) CourseConfig::get(Context::getId())->COURSE_PUBLIC_TOPICS, $this->url_for('course/topics/allow_public') ); } } private function createLinksForTopics(array $topics): array { $links = array_combine( array_column($topics, 'id'), array_fill(0, count($topics), ['previous' => null, 'next' => null]) ); $last = null; foreach ($topics as $topic) { if ($last !== null) { $links[$topic->id]['previous'] = $last; } $last = $topic; } $next = null; foreach (array_reverse($topics) as $topic) { if ($next !== null) { $links[$topic->id]['next'] = $next; } $next = $topic; } return $links; } public function getActionMenu(CourseTopic $topic): ActionMenu { $actions = ActionMenu::get(); $actions->setContext(htmlReady($topic->title)); if (User::findCurrent()->hasPermissionLevel('tutor', Context::get())) { $actions->addLink( $this->editURL($topic), _('Bearbeiten'), Icon::create('edit'), ['data-dialog' => ''] ); $actions->addButton( 'delete', _('Löschen'), Icon::create('trash'), [ 'formaction' => $this->delete($topic), 'data-confirm' => _('Das Thema wirklich löschen?'), ] ); if (!$this->cancelled_dates_locked && count($topic->dates) > 0) { $actions->addLink( URLHelper::getURL( 'dispatch.php/course/cancel_dates', ['issue_id' => $topic->id] ), _('Alle Termine ausfallen lassen'), Icon::create('date'), ['data-dialog' => ''] ); } } return $actions; } }