aboutsummaryrefslogtreecommitdiff
path: root/app/controllers/course
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/course')
-rw-r--r--app/controllers/course/forum/admin.php126
-rw-r--r--app/controllers/course/forum/area.php80
-rw-r--r--app/controllers/course/forum/forum_controller.php45
-rw-r--r--app/controllers/course/forum/index.php835
-rw-r--r--app/controllers/course/messenger.php78
5 files changed, 1164 insertions, 0 deletions
diff --git a/app/controllers/course/forum/admin.php b/app/controllers/course/forum/admin.php
new file mode 100644
index 0000000..a7fff71
--- /dev/null
+++ b/app/controllers/course/forum/admin.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * Copyright (C) 2011 - Till Glöggler <tgloeggl@uos.de>
+ *
+ * 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.
+ */
+
+require_once 'forum_controller.php';
+
+class Course_Forum_AdminController extends ForumController
+{
+ /* * * * * * * * * * * * * * * * * * * * */
+ /* * * A D M I N M E T H O D S * * */
+ /* * * * * * * * * * * * * * * * * * * * */
+
+ /**
+ * show the administration page for mass-editing forum-entries
+ */
+ function index_action()
+ {
+ ForumPerm::check('admin', $this->getId());
+ $nav = Navigation::getItem('course/forum2');
+ $nav->setImage(Icon::create('forum', 'info'));
+ Navigation::activateItem('course/forum2/admin');
+
+ $list = ForumEntry::getList('flat', $this->getId());
+
+ // sort by cat
+ $new_list = [];
+ // iterate over all categories and add the belonging areas to them
+ foreach ($categories = ForumCat::getListWithAreas($this->getId(), false) as $category) {
+ if ($category['topic_id']) {
+ $new_list[$category['category_id']][$category['topic_id']] = $list['list'][$category['topic_id']];
+ unset($list['list'][$category['topic_id']]);
+ } else if (ForumPerm::has('add_area', $this->seminar_id)) {
+ $new_list[$category['category_id']] = [];
+ }
+ $this->categories[$category['category_id']] = $category['entry_name'];
+ }
+
+ if (!empty($list['list'])) {
+ // append the remaining entries to the standard category
+ $new_list[$this->getId()] = array_merge((array)$new_list[$this->getId()], $list['list']);
+ }
+
+ $this->list = $new_list;
+
+ }
+
+ /**
+ * show child entries for the passed entry
+ *
+ * @param string $parent_id id of entry to get the childs for
+ */
+ function childs_action($parent_id)
+ {
+ $this->set_layout(null);
+
+ // if the parent-id is a category-id, get all areas for this category
+ if ($cat = ForumCat::get($parent_id)) {
+ ForumPerm::check('admin', $cat['seminar_id']); // check the perms in the categories seminar
+ $this->entries = ForumEntry::parseEntries(ForumCat::getAreas($parent_id));
+ } else {
+ ForumPerm::check('admin', $this->getId(), $parent_id);
+ $entries = ForumEntry::getList('flat', $parent_id);
+ $this->entries = $entries['list'];
+ }
+ }
+
+ /**
+ * move the submitted topics[] to the passed destination
+ *
+ * @param string $destination id of seminar to move topics to
+ */
+ function move_action($destination)
+ {
+ // check if destination is a category_id. if yes, use seminar_id instead
+ if (ForumCat::get($destination)) {
+ $category_id = $destination;
+ $destination = $this->getId();
+ }
+
+ ForumPerm::check('admin', $this->getId(), $destination);
+
+ foreach (Request::getArray('topics') as $topic_id) {
+ // make sure every passed topic_id is checked against the current seminar
+ ForumPerm::check('admin', $this->getId(), $topic_id);
+
+ // if the source is an area and the target a category, just move this area to the category
+ $entry = ForumEntry::getEntry($topic_id);
+ if ($entry['depth'] == 1 && $category_id) {
+ ForumCat::removeArea($topic_id);
+ ForumCat::addArea($category_id, $topic_id);
+ } else {
+ // first step: move the whole topic with all childs
+ ForumEntry::move($topic_id, $destination);
+
+ // if the current topic id is an area, remove it from any categories
+ ForumCat::removeArea($topic_id);
+
+ // second step: move all to deep childs a level up (depth > 3)
+ $data = ForumEntry::getList('depth_to_large', $topic_id);
+ foreach ($data['list'] as $entry) {
+ $path = ForumEntry::getPathToPosting($entry['topic_id']);
+ array_shift($path); // Category
+ array_shift($path); // Area
+
+ $thread = array_shift($path); // Thread
+
+ ForumEntry::move($entry['topic_id'], $thread['id']);
+ }
+
+ // add entry to passed category when moving to the top
+ if ($category_id) {
+ ForumCat::addArea($category_id, $topic_id);
+ }
+ }
+ }
+
+ $this->render_nothing();
+ }
+}
diff --git a/app/controllers/course/forum/area.php b/app/controllers/course/forum/area.php
new file mode 100644
index 0000000..a93860a
--- /dev/null
+++ b/app/controllers/course/forum/area.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * Copyright (C) 2011 - Till Glöggler <tgloeggl@uos.de>
+ *
+ * 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.
+ */
+
+require_once 'forum_controller.php';
+
+class Course_Forum_AreaController extends ForumController
+{
+ function add_action($category_id)
+ {
+ ForumPerm::check('add_area', $this->getId());
+
+ $new_id = md5(uniqid(rand()));
+
+ $name = Request::get('name', _('Kein Titel'));
+ $content = Request::get('content');
+
+ ForumEntry::insert([
+ 'topic_id' => $new_id,
+ 'seminar_id' => $this->getId(),
+ 'user_id' => $GLOBALS['user']->id,
+ 'name' => $name,
+ 'content' => $content,
+ 'author' => get_fullname($GLOBALS['user']->id),
+ 'author_host' => ($GLOBALS['user']->id == 'nobody') ? getenv('REMOTE_ADDR') : ''
+ ], $this->getId());
+
+ ForumCat::addArea($category_id, $new_id);
+
+ if (Request::isXhr()) {
+ $this->set_layout(null);
+ $entries = ForumEntry::parseEntries([ForumEntry::getEntry($new_id)]);
+ $this->entry = array_pop($entries);
+ $this->visitdate = ForumVisit::getLastVisit($this->getId());
+ } else {
+ $this->redirect('course/forum/index/index/');
+ }
+ }
+
+ function edit_action($area_id)
+ {
+ ForumPerm::check('edit_area', $this->getId(), $area_id);
+
+ if (Request::isAjax()) {
+ ForumEntry::update($area_id, Request::get('name'), Request::get('content'));
+ $this->render_json(['content' => ForumEntry::killFormat(ForumEntry::killEdit(Request::get('content')))]);
+ } else {
+ ForumEntry::update($area_id, Request::get('name'), Request::get('content'));
+ $this->flash['messages'] = ['success' => _('Die Änderungen am Bereich wurden gespeichert.')];
+ $this->redirect('course/forum/index/index');
+ }
+
+ }
+
+ function save_order_action()
+ {
+ ForumPerm::check('sort_area', $this->getId());
+
+ foreach (Request::getArray('areas') as $category_id => $areas) {
+ $pos = 0;
+ foreach ($areas as $area_id) {
+ ForumPerm::checkCategoryId($this->getId(), $category_id);
+ ForumPerm::check('sort_area', $this->getId(), $area_id);
+
+ ForumCat::addArea($category_id, $area_id);
+ ForumCat::setAreaPosition($area_id, $pos);
+ $pos++;
+ }
+ }
+
+ $this->render_nothing();
+ }
+}
diff --git a/app/controllers/course/forum/forum_controller.php b/app/controllers/course/forum/forum_controller.php
new file mode 100644
index 0000000..1812be9
--- /dev/null
+++ b/app/controllers/course/forum/forum_controller.php
@@ -0,0 +1,45 @@
+<?php
+
+class ForumController extends StudipController {
+ protected $with_session = true;
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+ /* * * * * H E L P E R F U N C T I O N S * * * * */
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+ function getId()
+ {
+ return ForumHelpers::getSeminarId();
+ }
+
+ /**
+ * Common code for all actions: set default layout and page title.
+ *
+ * @param type $action
+ * @param type $args
+ */
+ function before_filter(&$action, &$args)
+ {
+ $this->validate_args($args, ['option', 'option']);
+
+ parent::before_filter($action, $args);
+
+ $this->flash = Trails_Flash::instance();
+
+ // Set help keyword for Stud.IP's user-documentation and page title
+ PageLayout::setHelpKeyword('Basis.Forum');
+ PageLayout::setTitle(Context::getHeaderLine() .' - '. _('Forum'));
+
+ // the default for displaying timestamps
+ $this->time_format_string = "%a %d. %B %Y, %H:%M";
+ $this->time_format_string_short = "%d.%m.%Y, %H:%M";
+
+ //$this->getId() depends on Context::get()
+ checkObject();
+ ForumVisit::setVisit($this->getId());
+ if (Request::int('page')) {
+ ForumHelpers::setPage(Request::int('page'));
+ }
+
+ $this->seminar_id = $this->getId();
+ }
+}
diff --git a/app/controllers/course/forum/index.php b/app/controllers/course/forum/index.php
new file mode 100644
index 0000000..c3b665e
--- /dev/null
+++ b/app/controllers/course/forum/index.php
@@ -0,0 +1,835 @@
+<?php
+
+/*
+ * Copyright (C) 2011 - Till Glöggler <tgloeggl@uos.de>
+ *
+ * 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.
+ */
+
+require_once 'forum_controller.php';
+
+class Course_Forum_IndexController extends ForumController
+{
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+ /* V I E W - A C T I O N S */
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /**
+ * redirect to correct page (overview or newest entries),
+ * depending on whether there are any entries.
+ */
+ function enter_seminar_action() {
+ if (ForumPerm::has('fav_entry', $this->getId())
+ && ForumVisit::getCount($this->getId(), ForumVisit::getVisit($this->getId())) > 0) {
+ $this->redirect('course/forum/index/newest');
+ } else {
+ $this->redirect('course/forum/index/index');
+ }
+ }
+
+ /**
+ * the main action for the forum. May be called with a topic_id to be displayed
+ * and optionally the page to display
+ *
+ * @param type $topic_id the topic to display, defaults to the main
+ * view of the current seminar
+ * @param type $page the page to be displayed (for thread-view)
+ */
+ function index_action($topic_id = null, $page = null)
+ {
+ $nav = Navigation::getItem('course/forum2');
+ $nav->setImage(Icon::create('forum', 'info'));
+ Navigation::activateItem('course/forum2/index');
+
+ // check, if the root entry is present
+ ForumEntry::checkRootEntry($this->getId());
+
+ /* * * * * * * * * * * * * * * * * * *
+ * V A R I A B L E N F U E L L E N *
+ * * * * * * * * * * * * * * * * * * */
+
+ $this->section = 'index';
+
+ $this->topic_id = $topic_id ? $topic_id : $this->getId();
+ $this->constraint = ForumEntry::getConstraints($this->topic_id);
+
+ // check if there has been submitted an invalid id and use seminar_id in case
+ if (!$this->constraint) {
+ $this->topic_id = $this->getId();
+ $this->constraint = ForumEntry::getConstraints($this->topic_id);
+ }
+
+ $this->highlight_topic = Request::option('highlight_topic', null);
+
+ // set page to which we shall jump
+ if ($page) {
+ ForumHelpers::setPage($page);
+ }
+
+ // we do not crawl deeper than level 2, we show a page chooser instead
+ if ($this->constraint['depth'] > 2) {
+ ForumHelpers::setPage(ForumEntry::getPostingPage($this->topic_id, $this->constraint));
+
+ $path = ForumEntry::getPathToPosting($this->topic_id);
+ array_shift($path);array_shift($path);$path_element = array_shift($path);
+ $this->child_topic = $this->topic_id;
+ $this->topic_id = $path_element['id'];
+ $this->constraint = ForumEntry::getConstraints($this->topic_id);
+ }
+
+ // check if the topic_id matches the currently selected seminar
+ ForumPerm::checkTopicId($this->getId(), $this->topic_id);
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * B E R E I C H E / T H R E A D S / P O S T I N G S L A D E N *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ // load list of areas for use in thread-movement
+ if (ForumPerm::has('move_thread', $this->getId())) {
+ $this->areas = ForumEntry::getList('flat', $this->getId());
+ }
+
+ if ($this->constraint['depth'] > 1) { // POSTINGS
+ $list = ForumEntry::getList('postings', $this->topic_id);
+ if (!empty($list['list'])) {
+ $this->postings = $list['list'];
+ $this->number_of_entries = $list['count'];
+ }
+ } else {
+ if ($this->constraint['depth'] == 0) { // BEREICHE
+ $list = ForumEntry::getList('area', $this->topic_id);
+ } else {
+ $list = ForumEntry::getList('list', $this->topic_id);
+ }
+
+ if ($this->constraint['depth'] == 0) { // BEREICHE
+ $new_list = [];
+ // iterate over all categories and add the belonging areas to them
+ foreach ($categories = ForumCat::getListWithAreas($this->getId(), false) as $category) {
+ if ($category['topic_id']) {
+ $new_list[$category['category_id']][$category['topic_id']] = $list['list'][$category['topic_id']];
+ unset($list['list'][$category['topic_id']]);
+ } else if (ForumPerm::has('add_area', $this->seminar_id)) {
+ $new_list[$category['category_id']] = [];
+ }
+ $this->categories[$category['category_id']] = $category['entry_name'];
+ }
+
+ if (!empty($list['list'])) {
+ // append the remaining entries to the standard category
+ $new_list[$this->getId()] = array_merge((array)$new_list[$this->getId()], $list['list']);
+ }
+
+ // check, if there are any orphaned entries
+ foreach ($new_list as $key1 => $list_item) {
+ foreach ($list_item as $key2 => $contents) {
+ if (empty($contents)) {
+ // remove the orphaned entry from the list and from the database
+ unset($new_list[$key1][$key2]);
+ ForumCat::removeArea($key2);
+ }
+ }
+ }
+
+ $this->list = $new_list;
+
+ } else if ($this->constraint['depth'] == 1) { // THREADS
+ if (!empty($list['list'])) {
+ $this->list = [$list['list']];
+ }
+ }
+ $this->number_of_entries = $list['count'];
+ }
+
+ // set the visit-date and get the stored last_visitdate
+ $this->visitdate = ForumVisit::getLastVisit($this->getId());
+
+ $this->seminar_id = $this->getId();
+
+ // highlight text if passed some words to highlight
+ if (Request::getArray('highlight')) {
+ $this->highlight = Request::optionArray('highlight');
+ }
+
+ if (($this->edit_posting = Request::get('edit_posting', null))
+ && !ForumPerm::hasEditPerms($this->edit_posting)) {
+ $this->edit_posting = null;
+ }
+
+ // trigger a javascript action, like creating an answer or citing a thread
+ if (Request::submitted('answer')) {
+ $this->js = 'answer';
+ } else if (Request::option('cite')) {
+ $this->js = 'cite';
+ $this->cite_id = $topic_id;
+ }
+
+ }
+
+ /**
+ * show newest entries
+ *
+ * @param int $page show entries on submitted page
+ */
+ function newest_action($page = null)
+ {
+ $nav = Navigation::getItem('course/forum2');
+ $nav->setImage(Icon::create('forum', 'info'));
+ Navigation::activateItem('course/forum2/newest');
+
+ // set page to which we shall jump
+ if ($page) {
+ ForumHelpers::setPage($page);
+ }
+
+ $this->section = 'newest';
+ $this->topic_id = $this->getId();
+
+ // set the visitdate of the seminar as the last visitdate
+ $this->visitdate = ForumVisit::getLastVisit($this->getId());
+
+ $list = ForumEntry::getList('newest', $this->topic_id);
+ $this->postings = $list['list'];
+ $this->number_of_entries = $list['count'];
+ $this->show_full_path = true;
+
+ if (empty($this->postings)) {
+ $this->no_entries = true;
+ }
+
+ $this->render_action('index');
+ }
+
+ /**
+ * show all latest entries as flat list
+ *
+ * @param int $page show entries on submitted page
+ */
+ function latest_action($page = null)
+ {
+ $nav = Navigation::getItem('course/forum2');
+ $nav->setImage(Icon::create('forum', 'info'));
+ Navigation::activateItem('course/forum2/latest');
+
+ // set page to which we shall jump
+ if ($page) {
+ ForumHelpers::setPage($page);
+ }
+
+ $this->section = 'latest';
+ $this->topic_id = $this->getId();
+
+ // set the visitdate of the seminar as the last visitdate
+ $this->visitdate = ForumVisit::getLastVisit($this->getId());
+
+ $list = ForumEntry::getList('latest', $this->topic_id);
+ $this->postings = $list['list'];
+ $this->number_of_entries = $list['count'];
+ $this->show_full_path = true;
+
+ if (empty($this->postings)) {
+ $this->no_entries = true;
+ }
+
+ $this->render_action('index');
+ }
+
+ /**
+ * show the current users favorized entries
+ *
+ * @param int $page show entries on submitted page
+ */
+ function favorites_action($page = null)
+ {
+ $nav = Navigation::getItem('course/forum2');
+ $nav->setImage(Icon::create('forum', 'info'));
+ Navigation::activateItem('course/forum2/favorites');
+
+ // set page to which we shall jump
+ if ($page) {
+ ForumHelpers::setPage($page);
+ }
+
+ $this->section = 'favorites';
+ $this->topic_id = $this->getId();
+
+ $list = ForumEntry::getList('favorites', $this->topic_id);
+ $this->postings = $list['list'];
+ $this->number_of_entries = $list['count'];
+ $this->show_full_path = true;
+
+ if (empty($this->postings)) {
+ $this->no_entries = true;
+ }
+
+ // exploit the visitdate for this view
+ $this->visitdate = ForumVisit::getLastVisit($this->getId());
+
+ $this->render_action('index');
+ }
+
+ /**
+ * show search results
+ *
+ * @param int $page show entries on submitted page
+ */
+ function search_action($page = null)
+ {
+ if (Request::submitted('reset-search')) {
+ $this->redirect('index');
+ return;
+ }
+
+ ForumPerm::check('search', $this->getId());
+
+ $nav = Navigation::getItem('course/forum2');
+ $nav->setImage(Icon::create('forum', 'info'));
+ Navigation::activateItem('course/forum2/index');
+
+ // set page to which we shall jump
+ if ($page) {
+ ForumHelpers::setPage($page);
+ }
+
+ $this->section = 'search';
+ $this->topic_id = $this->getId();
+ $this->show_full_path = true;
+
+ // parse filter-options
+ foreach (['search_title', 'search_content', 'search_author'] as $option) {
+ $this->options[$option] = Request::option($option);
+ }
+
+ $this->searchfor = Request::get('searchfor');
+ if (mb_strlen($this->searchfor) < 3) {
+ $this->flash['messages'] = ['error' => _('Ihr Suchbegriff muss mindestens 3 Zeichen lang sein und darf nur Buchstaben und Zahlen enthalten!')];
+ } else {
+ // get search-results
+ $list = ForumEntry::getSearchResults($this->getId(), $this->searchfor, $this->options);
+
+ $this->postings = $list['list'];
+ $this->number_of_entries = $list['count'];
+ $this->highlight = $list['highlight'];
+
+ if (empty($this->postings)) {
+ $this->flash['messages'] = ['info' => _('Es wurden keine Beiträge gefunden, die zu Ihren Suchkriterien passen!')];
+ }
+ }
+
+ // exploit the visitdate for this view
+ $this->visitdate = ForumVisit::getLastVisit($this->getId());
+
+ $this->render_action('index');
+ }
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+ /* * * * P O S T I N G - A C T I O N S * * * */
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /**
+ * this action renders a preview of the submitted text
+ */
+ function preview_action() {
+ if (Request::isXhr()) {
+ $this->set_content_type('text/html; charset=UTF-8');
+ $this->render_text(formatReady(transformBeforeSave(Request::get('posting'))));
+ } else {
+ $this->render_text(
+ ForumEntry::getContentAsHtml(
+ transformBeforeSave(Request::get('posting'))
+ )
+ );
+ }
+ }
+
+ /**
+ * Add a new entry. Has a simple spambot protection and checks
+ * the parent_id to add the entry to, throwing an exception if missing.
+ *
+ * @throws Exception
+ */
+ function add_entry_action()
+ {
+ CSRFProtection::verifyUnsafeRequest();
+ // Schutz vor Spambots - diese füllen meistens alle Felder aus, auch "versteckte".
+ // Ist dieses Feld gefüllt, war das vermutlich kein Mensch
+ if (Request::get('nixda')) {
+ throw new Exception('Access denied!');
+ }
+
+ if (!$parent_id = Request::option('parent')) {
+ throw new Exception('missing seminar_id/topic_id while adding a new entry!');
+ }
+
+ if ($this->seminar_id == $parent_id) {
+ ForumPerm::check('add_area', $this->getId(), $parent_id);
+ } else {
+ ForumPerm::check('add_entry', $this->getId(), $parent_id);
+ }
+
+ $constraints = ForumEntry::getConstraints($parent_id);
+
+ // if we are answering/citing a posting, we want to add it to the thread
+ // (which is the parent of passed posting id)
+ if ($constraints['depth'] == 3) {
+ $parent_id = ForumEntry::getParentTopicId($parent_id);
+ }
+
+ $new_id = md5(uniqid(rand()));
+
+ if ($GLOBALS['user']->id == 'nobody') {
+ $fullname = Request::get('author', 'unbekannt');
+ } else {
+ $fullname = get_fullname($GLOBALS['user']->id);
+ }
+
+ ForumEntry::insert([
+ 'topic_id' => $new_id,
+ 'seminar_id' => $this->getId(),
+ 'user_id' => $GLOBALS['user']->id,
+ 'name' => Request::get('name') ?: '',
+ 'content' => Studip\Markup::purifyHtml(Request::get('content')),
+ 'author' => $fullname,
+ 'author_host' => ($GLOBALS['user']->id == 'nobody') ? getenv('REMOTE_ADDR') : '',
+ 'anonymous' => Config::get()->FORUM_ANONYMOUS_POSTINGS ? Request::get('anonymous') ? : 0 : 0
+ ], $parent_id);
+
+ $this->flash['notify'] = $new_id;
+
+ $this->redirect('course/forum/index/index/' . $new_id .'#'. $new_id);
+ }
+
+ /**
+ * Delete the submitted entry.
+ *
+ * @param string $topic_id the entry to delete
+ */
+ function delete_entry_action($topic_id)
+ {
+ // get the page of the posting to be able to jump there again
+ $page = ForumEntry::getPostingPage($topic_id);
+ URLHelper::addLinkParam('page', $page);
+
+ if (ForumPerm::hasEditPerms($topic_id) || ForumPerm::check('remove_entry', $this->getId(), $topic_id)) {
+ $path = ForumEntry::getPathToPosting($topic_id);
+ $topic = array_pop($path);
+ $parent = array_pop($path);
+
+ if ($topic_id != $this->getId()) {
+ // only delete directly if passed by ajax, otherwise ask for confirmation
+ if (Request::isXhr() || Request::isPost() || Request::get('approve_delete')) {
+ CSRFProtection::verifyUnsafeRequest();
+ ForumEntry::delete($topic_id);
+ $this->flash['messages'] = ['success' => sprintf(_('Der Eintrag %s wurde gelöscht!'), $topic['name'])];
+ } else {
+ $this->flash['messages'] = ['info_html' =>
+ sprintf(_('Sind sie sicher dass Sie den Eintrag %s löschen möchten?'), $topic['name'])
+ . '<br>'. \Studip\LinkButton::createAccept(_('Ja'), $this->url_for('course/forum/index/delete_entry/'. $topic_id .'?approve_delete=1'))
+ . \Studip\LinkButton::createCancel(_('Nein'), $this->url_for('course/forum/index/index/'. ForumEntry::getParentTopicId($topic_id) .'/'. $page))
+ ];
+ }
+ } else {
+ $this->flash['messages'] = ['success' => _('Sie können nicht die gesamte Veranstaltung löschen!')];
+ }
+ }
+
+ if (Request::isXhr()) {
+ $this->render_template('course/forum/messages');
+ $this->flash['messages'] = null;
+ } else {
+ $this->redirect('course/forum/index/index/' . $parent['id'] .'/'. $page);
+ }
+ }
+
+ /**
+ * Update the submitted entry.
+ *
+ * @param string $topic_id id of the entry to update
+ * @throws AccessDeniedException
+ */
+ function update_entry_action($topic_id)
+ {
+ CSRFProtection::verifyUnsafeRequest();
+
+ $name = Request::get('name', _('Kein Titel'));
+ $content = Studip\Markup::purifyHtml(Request::get('content', _('Keine Beschreibung')));
+
+ ForumPerm::check('add_entry', $this->getId(), $topic_id);
+
+ if (ForumPerm::hasEditPerms($topic_id)) {
+ ForumEntry::update($topic_id, $name, $content);
+ } else {
+ throw new AccessDeniedException(_('Sie haben keine Berechtigung, diesen Eintrag zu editieren!'));
+ }
+
+ if (Request::isXhr()) {
+ $this->render_text(json_encode([
+ 'name' => htmlReady($name),
+ 'content' => formatReady($content)
+ ]));
+ } else {
+ $this->redirect('course/forum/index/index/' . $topic_id .'#'. $topic_id);
+ }
+ }
+
+ /**
+ * Move the submitted thread to the submitted parent
+ *
+ * @param string $thread_id the thread to move
+ * @param string $destination the threads new parent
+ */
+ function move_thread_action($thread_id, $destination) {
+ ForumPerm::check('move_thread', $this->getId(), $thread_id);
+ ForumPerm::check('move_thread', $this->getId(), $destination);
+
+ $current_area = ForumEntry::getParentTopicId($thread_id);
+
+ ForumEntry::move($thread_id, $destination);
+
+ $this->redirect('course/forum/index/index/' . $current_area .'/'. ForumHelpers::getPage());
+ }
+
+ /**
+ * Mark the submitted entry as favorite
+ *
+ * @param string $topic_id the entry to mark
+ */
+ function set_favorite_action($topic_id)
+ {
+ ForumPerm::check('fav_entry', $this->getId(), $topic_id);
+
+ ForumFavorite::set($topic_id);
+
+ if (Request::isXhr()) {
+ $this->topic_id = $topic_id;
+ $this->favorite = true;
+ $this->render_template('course/forum/index/_favorite');
+ } else {
+ $this->redirect('course/forum/index/index/' . $topic_id .'#'. $topic_id);
+ }
+ }
+
+ /**
+ * Remove the submtted entry as favorite
+ *
+ * @param string $topic_id the entry to unmark
+ */
+ function unset_favorite_action($topic_id) {
+ ForumPerm::check('fav_entry', $this->getId(), $topic_id);
+
+ ForumFavorite::remove($topic_id);
+
+ if (Request::isXhr()) {
+ $this->topic_id = $topic_id;
+ $this->favorite = false;
+ $this->render_template('course/forum/index/_favorite');
+ } else {
+ $this->redirect('course/forum/index/index/' . $topic_id .'#'. $topic_id);
+ }
+ }
+
+ /**
+ * Jump to page in the entries of the submitted parent-entry
+ * denoted by the submitted context (section)
+ *
+ * @param string $topic_id the parent-topic to goto
+ * @param string $section the type of view (one of index/search)
+ * @param int $page the page to jump to
+ */
+ function goto_page_action($topic_id, $section, $page)
+ {
+ switch ($section) {
+ case 'index':
+ $this->redirect('course/forum/index/index/' . $topic_id .'/'. (int)$page .'#'. $topic_id);
+ break;
+
+ case 'search':
+ $optionlist = [];
+
+ foreach (['search_title', 'search_content', 'search_author'] as $option) {
+ if (Request::option($option)) {
+ $optionlist[] = $option .'='. 1;
+ }
+ }
+
+ $this->redirect('course/forum/index/'. $section .'/'. (int)$page
+ .'/?searchfor='. Request::get('searchfor') .'&'. implode('&', $optionlist));
+ break;
+
+ default:
+ $this->redirect('course/forum/index/'. $section .'/'. (int)$page);
+ break;
+ }
+ }
+
+ /**
+ * Like the submitted topic
+ *
+ * @param string $topic_id the topic to like
+ */
+ function like_action($topic_id)
+ {
+ ForumPerm::check('like_entry', $this->getId(), $topic_id);
+
+ ForumLike::like($topic_id);
+
+ if (Request::isXhr()) {
+ $this->topic_id = $topic_id;
+ $this->render_template('course/forum/index/_like');
+ } else {
+ $this->redirect('course/forum/index/index/' . $topic_id .'#'. $topic_id);
+ }
+ }
+
+ /**
+ * Remove like for the submitted topic
+ *
+ * @param string $topic_id the topic to unlike
+ */
+ function dislike_action($topic_id)
+ {
+ ForumPerm::check('like_entry', $this->getId(), $topic_id);
+
+ ForumLike::dislike($topic_id);
+
+ if (Request::isXhr()) {
+ $this->topic_id = $topic_id;
+ $this->render_template('course/forum/index/_like');
+ } else {
+ $this->redirect('course/forum/index/index/' . $topic_id .'#'. $topic_id);
+ }
+ }
+
+ /**
+ * This action is used to close a thread.
+ *
+ * @param string $topic_id the topic which will be closed
+ * @param string $redirect the topic which will be shown after closing the thread
+ * @param int $page the page number of the topic $redirect
+ */
+ function close_thread_action($topic_id, $redirect, $page = 0)
+ {
+ ForumPerm::check('close_thread', $this->getId(), $topic_id);
+
+ ForumEntry::close($topic_id);
+
+ $success_text = _('Das Thema wurde erfolgreich geschlossen.');
+
+ if (Request::isXhr()) {
+ $this->render_text(MessageBox::success($success_text));
+ } else {
+ $this->flash['messages'] = ['success' => $success_text];
+ $this->redirect('course/forum/index/index/' . $redirect . '/' . $page);
+ }
+ }
+
+ /**
+ * This action is used to open a thread.
+ *
+ * @param string $topic_id the topic which will be opened
+ * @param string $redirect the topic which will be shown after opening the thread
+ * @param int $page the page number of the topic $redirect
+ */
+ function open_thread_action($topic_id, $redirect, $page = 0)
+ {
+ ForumPerm::check('close_thread', $this->getId(), $topic_id);
+
+ ForumEntry::open($topic_id);
+
+ $success_text = _('Das Thema wurde erfolgreich geöffnet.');
+
+ if (Request::isXhr()) {
+ $this->render_text(MessageBox::success($success_text));
+ } else {
+ $this->flash['messages'] = ['success' => $success_text];
+ $this->redirect('course/forum/index/index/' . $redirect . '/' . $page);
+ }
+ }
+
+ /**
+ * This action is used to mark a thread as sticky.
+ *
+ * @param string $topic_id the topic which will be marked as sticky.
+ * @param string $redirect the topic which will be shown afterwards
+ * @param int $page the page number of the topic $redirect
+ */
+ function make_sticky_action($topic_id, $redirect, $page = 0)
+ {
+ ForumPerm::check('make_sticky', $this->getId(), $topic_id);
+
+ ForumEntry::sticky($topic_id);
+
+ $success_text = _('Das Thema wurde erfolgreich in der Themenliste hervorgehoben.');
+
+ if (Request::isXhr()) {
+ $this->render_text(MessageBox::success($success_text));
+ } else {
+ $this->flash['messages'] = ['success' => $success_text];
+ $this->redirect('course/forum/index/index/' . $redirect . '/' . $page);
+ }
+ }
+
+ /**
+ * This action is used to remove the sticky attribute from a topic.
+ *
+ * @param string $topic_id the topic which will be marked as unsticky.
+ * @param string $redirect the topic which will be shown afterwards
+ * @param int $page the page number of the topic $redirect
+ */
+ function make_unsticky_action($topic_id, $redirect, $page = 0)
+ {
+ ForumPerm::check('make_sticky', $this->getId(), $topic_id);
+
+ ForumEntry::unsticky($topic_id);
+
+ $success_text = _('Die Hervorhebung des Themas in der Themenliste wurde entfernt.');
+
+ if (Request::isXhr()) {
+ $this->render_text(MessageBox::success($success_text));
+ } else {
+ $this->flash['messages'] = ['success' => $success_text];
+ $this->redirect('course/forum/index/index/' . $redirect . '/' . $page);
+ }
+ }
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+ /* * * * C O N F I G - A C T I O N S * * * */
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /**
+ * Add submitted category to current course
+ */
+ function add_category_action()
+ {
+ CSRFProtection::verifyUnsafeRequest();
+
+ ForumPerm::check('add_category', $this->getId());
+
+ $category_id = ForumCat::add($this->getId(), Request::get('category'));
+
+ ForumPerm::checkCategoryId($this->getId(), $category_id);
+
+ $this->redirect('course/forum/index#cat_'. $category_id);
+ }
+
+ /*
+ * Remove submitted category from current course
+ */
+ function remove_category_action($category_id)
+ {
+ CSRFProtection::verifyUnsafeRequest();
+
+ ForumPerm::checkCategoryId($this->getId(), $category_id);
+ ForumPerm::check('remove_category', $this->getId());
+
+ $this->flash['messages'] = ['success' => _('Die Kategorie wurde gelöscht!')];
+ ForumCat::remove($category_id, $this->getId());
+
+ if (Request::isXhr()) {
+ $this->render_template('course/forum/messages');
+ } else {
+ $this->redirect('course/forum/index/index');
+ }
+
+ }
+
+ /**
+ * Change the name of the submitted category
+ *
+ * @param string $category_id the category to edit
+ */
+ function edit_category_action($category_id) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ ForumPerm::checkCategoryId($this->getId(), $category_id);
+ ForumPerm::check('edit_category', $this->getId());
+
+ if (Request::isXhr()) {
+ ForumCat::setName($category_id, Request::get('name'));
+ $this->render_nothing();
+ } else {
+ ForumCat::setName($category_id, Request::get('name'));
+ $this->flash['messages'] = ['success' => _('Der Name der Kategorie wurde geändert.')];
+ $this->redirect('course/forum/index/index#cat_' . $category_id);
+ }
+
+ }
+
+ /**
+ * Save the ordering of the categories
+ */
+ function savecats_action()
+ {
+ ForumPerm::check('sort_category', $this->getId());
+
+ $pos = 0;
+ foreach (Request::getArray('categories') as $category_id) {
+ ForumPerm::checkCategoryId($this->getId(), $category_id);
+ ForumCat::setPosition($category_id, $pos);
+ $pos++;
+ }
+
+ $this->render_nothing();
+ }
+
+ /*
+ * Subscribe to the submitted topic and receive mails on new postings
+ *
+ * @param string $topic_id
+ */
+ function abo_action($topic_id)
+ {
+ ForumPerm::check('abo', $this->getId(), $topic_id);
+
+ ForumAbo::add($topic_id);
+ $this->constraint = ForumEntry::getConstraints($topic_id);
+
+ if (Request::isXhr()) {
+ $this->render_template('course/forum/index/_abo_link');
+ } else {
+ switch ($this->constraint['depth']) {
+ case 0: $msg = _('Sie haben das gesamte Forum abonniert!');break;
+ case 1: $msg = _('Sie haben diesen Bereich abonniert.');break;
+ default: $msg = _('Sie haben dieses Thema abonniert');break;
+ }
+ $this->flash['messages'] = ['success' => $msg .' '. _('Sie werden nun über jeden neuen Beitrag informiert.')];
+ $this->redirect('course/forum/index/index/' . $topic_id);
+ }
+ }
+
+ /**
+ * Unsubscribe from the passed topic
+ *
+ * @param string $topic_id
+ */
+ function remove_abo_action($topic_id)
+ {
+ ForumPerm::check('abo', $this->getId(), $topic_id);
+
+ ForumAbo::delete($topic_id);
+
+ if (Request::isXhr()) {
+ $this->constraint = ForumEntry::getConstraints($topic_id);
+ $this->render_template('course/forum/index/_abo_link');
+ } else {
+ $this->flash['messages'] = ['success' => _('Abonnement aufgehoben.')];
+ $this->redirect('course/forum/index/index/' . $topic_id);
+ }
+ }
+
+ /**
+ * Generate a pdf-export for the whole forum or the passed subtree
+ *
+ * @param string $parent_id
+ */
+ function pdfexport_action($parent_id = null)
+ {
+ ForumPerm::check('pdfexport', $this->getId(), $parent_id);
+
+ ForumHelpers::createPDF($this->getId(), $parent_id);
+ }
+}
diff --git a/app/controllers/course/messenger.php b/app/controllers/course/messenger.php
new file mode 100644
index 0000000..0bfd3f5
--- /dev/null
+++ b/app/controllers/course/messenger.php
@@ -0,0 +1,78 @@
+<?php
+class Course_MessengerController extends AuthenticatedController
+{
+ public function before_filter(&$action, &$args)
+ {
+ parent::before_filter($action, $args);
+
+ PageLayout::setBodyElementId('blubber-index');
+ PageLayout::setHelpKeyword("Basis/InteraktionBlubber");
+ }
+
+ public function course_action($thread_id = null)
+ {
+ PageLayout::setTitle(_("Blubber"));
+
+ if (Navigation::hasItem('/course/blubber')) {
+ Navigation::activateItem("/course/blubber");
+ }
+
+ $this->threads = BlubberThread::findByContext(Context::get()->id, true, Context::getType());
+
+ if (!$thread_id) {
+ $thread_id = $GLOBALS['user']->cfg->BLUBBER_DEFAULT_THREAD;
+ }
+ if ($thread_id) {
+ foreach ($this->threads as $thread) {
+ if ($thread->getId() === $thread_id) {
+ $this->thread = $thread;
+ break;
+ }
+ }
+ }
+ if (!$this->thread || Request::get("thread") === "new") {
+ $this->thread = array_pop(array_reverse($this->threads));
+ }
+ $this->thread->markAsRead();
+
+ $this->thread_data = $this->thread->getJSONData();
+
+ if (!Avatar::getAvatar($GLOBALS['user']->id)->is_customized() && !$_SESSION['already_asked_for_avatar']) {
+ $_SESSION['already_asked_for_avatar'] = true;
+ PageLayout::postInfo(sprintf(_("Wollen Sie ein Avatar-Bild nutzen? %sLaden Sie jetzt ein Bild hoch%s."), '<a href="'.URLHelper::getURL("dispatch.php/avatar/update/user/".$GLOBALS['user']->id).'" data-dialog>', '</a>'));
+ }
+ $this->buildSidebar();
+
+ if (Request::isDialog()) {
+ PageLayout::setTitle($this->thread->getName());
+ $this->render_template('blubber/dialog');
+ } else {
+ $this->render_template('blubber/index', $this->layout);
+ }
+ }
+
+ protected function buildSidebar()
+ {
+ $sidebar = Sidebar::Get();
+ $search = new SearchWidget("#");
+ $search->addNeedle(
+ _("Suche nach ..."),
+ "search",
+ true,
+ null,
+ null,
+ null,
+ []
+ );
+ $sidebar->addWidget($search, "blubbersearch");
+
+ $threads_widget = new BlubberThreadsWidget();
+ foreach ($this->threads as $thread) {
+ $threads_widget->addThread($thread);
+ }
+ if ($this->thread) {
+ $threads_widget->setActive($this->thread->getId());
+ }
+ $sidebar->addWidget($threads_widget, "threads");
+ }
+}