Skip to content
Snippets Groups Projects
Commit c14686ea authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms Committed by Jan-Hendrik Willms
Browse files

make course topic title and description translatable, fixes #401

parent d259140c
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@
class Course_TopicsController extends AuthenticatedController
{
protected $allow_nobody = true;
protected $_autobind = true;
public function before_filter(&$action, &$args)
{
......@@ -13,136 +14,123 @@ class Course_TopicsController extends AuthenticatedController
checkObject();
checkObjectModule("schedule");
Navigation::activateItem('/course/schedule/topics');
PageLayout::setTitle(sprintf('%s - %s', Course::findCurrent()->getFullname(), _("Themen")));
$seminar = new Seminar(Course::findCurrent());
$this->forum_activated = $seminar->getSlotModule('forum');
$this->documents_activated = $seminar->getSlotModule('documents');
if ($action !== 'index' && !$GLOBALS['perm']->have_studip_perm('tutor', Context::getId())) {
throw new AccessDeniedException();
}
$this->setupSidebar($action);
}
public function index_action()
{
if (Request::isPost() && Request::get("edit") && $GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) {
$topic = new CourseTopic(Request::option("issue_id"));
if ($topic['seminar_id'] && ($topic['seminar_id'] !== Context::getId())) {
throw new AccessDeniedException();
}
$this->topics = CourseTopic::findBySeminar_id(Context::getId());
$this->cancelled_dates_locked = LockRules::Check(Context::getId(), 'cancelled_dates');
}
$topic['title'] = Request::get("title");
$topic['description'] = Studip\Markup::purifyHtml(Request::get("description"));
$topic['paper_related'] = (bool) Request::int('paper_related');
if ($topic->isNew()) {
$topic['seminar_id'] = Context::getId();
}
$topic->store();
public function delete_action(CourseTopic $topic)
{
if (!Request::isPost()) {
throw new MethodNotAllowedException();
}
//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 ($topic->seminar_id && ($topic->seminar_id !== Context::getId())) {
throw new AccessDeniedException();
}
if (Request::get("folder")) {
$topic->connectWithDocumentFolder();
}
if ($topic->delete()) {
PageLayout::postSuccess(_('Thema gelöscht.'));
}
// create a connection to the module forum (can be anything)
// will update title and description automagically
if (Request::get("forumthread")) {
$topic->connectWithForumThread();
}
$this->redirect('course/topics');
}
if (Request::option("issue_id") === "new") {
Request::set("open", $topic->getId());
}
PageLayout::postMessage(MessageBox::success(_("Thema gespeichert.")));
$this->redirect("course/topics/index");
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 (Request::isPost() && Request::option("move_down")) {
$topics = CourseTopic::findBySeminar_id(Context::getId());
$mainkey = null;
foreach ($topics as $key => $topic) {
if ($topic->getId() === Request::option("move_down")) {
$mainkey = $key;
}
$topic['priority'] = $key + 1;
}
if ($mainkey !== null && $mainkey < count($topics)) {
$topics[$mainkey]->priority++;
$topics[$mainkey + 1]->priority--;
}
foreach ($topics as $key => $topic) {
$topic->store();
}
if ($topic->seminar_id && ($topic->seminar_id !== Context::getId())) {
throw new AccessDeniedException();
}
if (Request::isPost() && Request::option("move_up")) {
$topics = CourseTopic::findBySeminar_id(Context::getId());
foreach ($topics as $key => $topic) {
if (($topic->getId() === Request::option("move_up")) && $key > 0) {
$topic['priority'] = $key;
$topics[$key - 1]->priority = $key + 1;
$topics[$key - 1]->store();
} else {
$topic['priority'] = $key + 1;
}
$topic->store();
$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();
Navigation::activateItem('/course/schedule/topics');
$this->topics = CourseTopic::findBySeminar_id(Context::getId());
$this->cancelled_dates_locked = LockRules::Check(Context::getId(), 'cancelled_dates');
}
if (Request::bool('folder')) {
$topic->connectWithDocumentFolder();
}
public function delete_action($topic_id)
{
if (!$GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) {
throw new AccessDeniedException();
// create a connection to the module forum (can be anything)
// will update title and description automagically
if (Request::bool('forumthread')) {
$topic->connectWithForumThread();
}
$topic = new CourseTopic($topic_id);
PageLayout::postSuccess(_('Thema gespeichert.'));
$this->redirect($this->indexURL(['open' => $topic->id]));
}
if ($topic['seminar_id'] && ($topic['seminar_id'] !== Context::getId())) {
throw new AccessDeniedException();
public function move_up_action(CourseTopic $topic)
{
if (!Request::isPost()) {
throw new MethodNotAllowedException();
}
$topic->delete();
PageLayout::postSuccess(_('Thema gelöscht.'));
$topic->increasePriority();
$this->redirect('course/topics');
$this->redirect($this->indexURL(['open' => $topic->id]));
}
public function edit_action($topic_id = null)
public function move_down_action(CourseTopic $topic)
{
if (!$GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) {
throw new AccessDeniedException();
if (!Request::isPost()) {
throw new MethodNotAllowedException();
}
$this->topic = new CourseTopic($topic_id);
$this->dates = CourseDate::findBySeminar_id(Context::getId());
if (Request::isXhr()) {
PageLayout::setTitle($topic_id ? sprintf(_('Bearbeiten: %s'), $this->topic['title']) : _("Neues Thema erstellen"));
} else {
Navigation::activateItem('/course/schedule/topics');
}
$topic->decreasePriority();
$this->redirect($this->indexURL(['open' => $topic->id]));
}
public function allow_public_action()
{
if (!$GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) {
throw new AccessDeniedException();
}
$config = CourseConfig::get(Context::getId());
$config->store('COURSE_PUBLIC_TOPICS', !$config->COURSE_PUBLIC_TOPICS);
$this->redirect("course/topics");
......@@ -150,9 +138,6 @@ class Course_TopicsController extends AuthenticatedController
public function copy_action()
{
if (!$GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) {
throw new AccessDeniedException();
}
if (Request::submitted("copy")) {
$prio = 1;
foreach (Course::find(Context::getId())->topics as $topic) {
......@@ -227,9 +212,6 @@ class Course_TopicsController extends AuthenticatedController
public function fetch_topics_action()
{
if (!$GLOBALS['perm']->have_studip_perm("tutor", Request::option("seminar_id"))) {
throw new AccessDeniedException();
}
$this->topics = CourseTopic::findBySeminar_id(Request::option("seminar_id"));
$output = [
'html' => $this->render_template_as_string("course/topics/_topiclist.php")
......@@ -272,8 +254,8 @@ class Course_TopicsController extends AuthenticatedController
if ($GLOBALS['perm']->have_studip_perm('tutor', Context::getId())) {
$options = $sidebar->addWidget(new OptionsWidget());
$options->addCheckbox(
_("Themen öffentlich einsehbar"),
CourseConfig::get(Context::getId())->COURSE_PUBLIC_TOPICS,
_('Themen öffentlich einsehbar'),
(bool) CourseConfig::get(Context::getId())->COURSE_PUBLIC_TOPICS,
$this->url_for('course/topics/allow_public')
);
}
......
<? $date_ids = $topic->dates->pluck("termin_id") ?>
<form action="<?= URLHelper::getLink("dispatch.php/course/topics") ?>" method="post" class="default">
<form action="<?= $controller->store($topic) ?>" method="post" class="default">
<?= CSRFProtection::tokenTag() ?>
<input type="hidden" name="issue_id" value="<?=htmlReady($topic->getId()) ?>">
<input type="hidden" name="open" value="<?=htmlReady($topic->getId()) ?>">
<input type="hidden" name="open" value="<?= htmlReady($topic->getId()) ?>">
<input type="hidden" name="edit" value="1">
<fieldset>
<legend><?= _('Thema bearbeiten') ?></legend>
<label for="topic_title">
<span class="required"><?= _("Titel") ?></span>
<input type="text" name="title" id="topic_title" value="<?= htmlReady($topic['title']) ?>" required>
<label>
<span class="required"><?= _('Titel') ?></span>
<?= I18N::input('title', $topic->title, ['required' => '']) ?>
</label>
<label for="topic_description">
<label>
<?= _("Beschreibung") ?>
<textarea class="add_toolbar wysiwyg size-l" name="description" id="topic_description"><?= wysiwygReady($topic['description']) ?></textarea>
<? if (Request::isAjax()) : ?>
<script>jQuery('.add_toolbar').addToolbar();</script>
<? endif ?>
<?= I18N::textarea('description', $topic->description, [
'class' => 'add_toolbar wysiwyg size-l',
]) ?>
</label>
<? if ($documents_activated) : ?>
<label>
<? $folder = $topic->folders->first() ?>
<? if ($folder) : ?>
<?= Icon::create('accept', 'accept')->asImg(['class' => "text-bottom"]) ?>
<?= _("Dateiordner vorhanden ") ?>
<? else : ?>
<input type="checkbox" name="folder" id="topic_folder">
<?= _("Dateiordner anlegen") ?>
<? endif ?>
</label>
<? if ($documents_activated) : ?>
<label>
<? $folder = $topic->folders->first() ?>
<? if ($folder) : ?>
<?= Icon::create('accept', Icon::ROLE_ACCEPT)->asImg(['class' => 'text-bottom']) ?>
<?= _('Dateiordner vorhanden ') ?>
<? else : ?>
<input type="checkbox" name="folder" id="topic_folder" value="1">
<?= _('Dateiordner anlegen') ?>
<? endif ?>
</label>
<? endif ?>
<? if ($forum_activated) : ?>
<label>
<? if ($topic->forum_thread_url) : ?>
<?= Icon::create('accept', 'accept')->asImg(['class' => "text-bottom"]) ?>
<?= _("Forenthema vorhanden ") ?>
<? else : ?>
<input type="checkbox" name="forumthread" id="topic_forumthread">
<?= _("Forenthema anlegen") ?>
<? endif ?>
</label>
<? if ($forum_activated) : ?>
<label>
<? if ($topic->forum_thread_url) : ?>
<?= Icon::create('accept', Icon::ROLE_ACCEPT)->asImg(['class' => 'text-bottom']) ?>
<?= _('Forenthema vorhanden ') ?>
<? else : ?>
<input type="checkbox" name="forumthread" id="topic_forumthread" value="1">
<?= _('Forenthema anlegen') ?>
<? endif ?>
</label>
<? endif ?>
<h2><?= _("Termine") ?></h2>
<h2><?= _('Termine') ?></h2>
<? foreach ($dates as $date) : ?>
<label>
<input type="checkbox" name="date[<?= $date->getId() ?>]" value="1" class="text-bottom"<?= in_array($date->getId(), $date_ids) ? " checked" : "" ?>>
<?= Icon::create('date', 'info')->asImg(['class' => "text-bottom"]) ?>
<?= (floor($date['date'] / 86400) !== floor($date['end_time'] / 86400)) ? date("d.m.Y, H:i", $date['date'])." - ".date("d.m.Y, H:i", $date['end_time']) : date("d.m.Y, H:i", $date['date'])." - ".date("H:i", $date['end_time']) ?>
<? $localtopics = $date->topics ?>
<? if (count($localtopics)) : ?>
<input type="checkbox" name="date[<?= htmlReady($date->id) ?>]" value="1" class="text-bottom"
<? if (in_array($date->id, $date_ids)) echo 'checked'; ?>>
<?= Icon::create('date', Icon::ROLE_INFO)->asImg(['class' => 'text-bottom']) ?>
<?= floor($date['date'] / 86400) !== floor($date['end_time'] / 86400) ? date("d.m.Y, H:i", $date['date'])." - ".date("d.m.Y, H:i", $date['end_time']) : date("d.m.Y, H:i", $date['date'])." - ".date("H:i", $date['end_time']) ?>
<? if (count($date->topics) > 0) : ?>
(
<? foreach ($localtopics as $key => $localtopic) : ?>
<a href="<?= URLHelper:: getLink("dispatch.php/course/topics/index", ['open' => $localtopic->getId()]) ?>">
<?= Icon::create('topic', 'clickable')->asImg(['class' => "text-bottom"]) ?>
<?= htmlReady($localtopic['title']) ?>
<? foreach ($date->topics as $key => $localtopic) : ?>
<a href="<?= $controller->index(['open' => $localtopic->id]) ?>">
<?= Icon::create('topic')->asImg(['class' => 'text-bottom']) ?>
<?= htmlReady($localtopic->title) ?>
</a>
<? endforeach ?>
)
......@@ -90,5 +89,3 @@
</div>
</footer>
</form>
<br>
......@@ -83,34 +83,36 @@
</table>
<div style="text-align: center;">
<? if ($GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) : ?>
<?= \Studip\LinkButton::createEdit(_('Bearbeiten'),
$controller->url_for('course/topics/edit/' . $topic->getId()), [
'data-dialog' => ''
]) ?>
<?= Studip\LinkButton::create(
_('Löschen'),
$controller->url_for('course/topics/delete/' . $topic->getId()),
['data-confirm' => _('Wirklich löschen?')]
<?= Studip\LinkButton::createEdit(
_('Bearbeiten'),
$controller->editURL($topic),
['data-dialog' => '']
) ?>
<form action="<?= $controller->delete($topic) ?>" method="post" style="display: inline">
<?= Studip\Button::create(
_('Löschen'),
'delete',
['data-confirm' => _('Wirklich löschen?')]
) ?>
</form>
<? if (!$cancelled_dates_locked && $topic->dates->count()) : ?>
<?= \Studip\LinkButton::create(_("Alle Termine ausfallen lassen"), URLHelper::getURL("dispatch.php/course/cancel_dates", ['issue_id' => $topic->getId()]), ['data-dialog' => '']) ?>
<? endif ?>
<span class="button-group">
<? if ($key > 0) : ?>
<form action="<?=$controller->link_for()?>" method="post" style="display: inline;">
<input type="hidden" name="move_up" value="<?= $topic->getId() ?>">
<input type="hidden" name="open" value="<?= $topic->getId() ?>">
<?= \Studip\Button::createMoveUp(_("nach oben verschieben")) ?>
<form action="<?= $controller->move_up($topic) ?>" method="post" style="display: inline;">
<?= Studip\Button::createMoveUp(_('nach oben verschieben')) ?>
</form>
<? endif ?>
<? if ($key < count($topics) - 1) : ?>
<form action="<?=$controller->link_for()?>" method="post" style="display: inline;">
<input type="hidden" name="move_down" value="<?= $topic->getId() ?>">
<input type="hidden" name="open" value="<?= $topic->getId() ?>">
<?= \Studip\Button::createMoveDown(_("nach unten verschieben")) ?>
</form>
<form action="<?=$controller->move_down($topic)?>" method="post" style="display: inline;">
<?= Studip\Button::createMoveDown(_('nach unten verschieben')) ?>
</form>
<? endif ?>
</span>
<? endif ?>
</div>
</div>
......
......@@ -19,57 +19,33 @@
* @property string priority database column
* @property string mkdate database column
* @property string chdate database column
* @property DocumentFolder folder belongs_to DocumentFolder
* @property Folder folder belongs_to DocumentFolder
* @property Course course belongs_to Course
* @property User author belongs_to User
* @property SimpleORMapCollection dates has_and_belongs_to_many CourseDate
*/
class CourseTopic extends SimpleORMap
{
public static function findByTermin_id($termin_id)
{
return self::findBySQL("INNER JOIN themen_termine USING (issue_id)
WHERE themen_termine.termin_id = ?
ORDER BY priority ASC",
[$termin_id]
);
}
public static function findBySeminar_id($seminar_id, $order_by = 'ORDER BY priority')
{
return parent::findBySeminar_id($seminar_id, $order_by);
}
public static function findByTitle($seminar_id, $name)
{
return self::findOneBySQL("seminar_id = ? AND title = ?", [$seminar_id, $name]);
}
public static function getMaxPriority($seminar_id)
{
return DBManager::get()->fetchColumn("SELECT MAX(priority) FROM themen WHERE seminar_id=?", [$seminar_id]);
}
protected static function configure($config = [])
{
$config['db_table'] = 'themen';
$config['has_and_belongs_to_many']['dates'] = [
'class_name' => 'CourseDate',
'class_name' => CourseDate::class,
'thru_table' => 'themen_termine',
'order_by' => 'ORDER BY date',
'on_delete' => 'delete',
'on_store' => 'store'
];
$config['has_many']['folders'] = [
'class_name' => 'Folder',
'class_name' => Folder::class,
'assoc_func' => 'findByTopic_id'
];
$config['belongs_to']['course'] = [
'class_name' => 'Course',
'class_name' => Course::class,
'foreign_key' => 'seminar_id'
];
$config['belongs_to']['author'] = [
'class_name' => 'User',
'class_name' => User::class,
'foreign_key' => 'author_id'
];
......@@ -79,9 +55,36 @@ class CourseTopic extends SimpleORMap
$config['registered_callbacks']['after_store'][] = 'cbUpdateConnectedContentModules';
$config['registered_callbacks']['before_delete'][] = 'cbUnlinkConnectedContentModules';
$config['i18n_fields']['title'] = true;
$config['i18n_fields']['description'] = true;
parent::configure($config);
}
public static function findByTermin_id($termin_id)
{
return self::findBySQL("INNER JOIN themen_termine USING (issue_id)
WHERE themen_termine.termin_id = ?
ORDER BY priority ASC",
[$termin_id]
);
}
public static function findBySeminar_id($seminar_id, $order_by = 'ORDER BY priority')
{
return parent::findBySeminar_id($seminar_id, $order_by);
}
public static function findByTitle($seminar_id, $name)
{
return self::findOneBySQL("seminar_id = ? AND title = ?", [$seminar_id, $name]);
}
public static function getMaxPriority($seminar_id)
{
return DBManager::get()->fetchColumn("SELECT MAX(priority) FROM themen WHERE seminar_id=?", [$seminar_id]);
}
/**
* set or update connection with document folder
*/
......@@ -179,7 +182,7 @@ class CourseTopic extends SimpleORMap
$folders = array_merge($folders, $date->folders->getArrayCopy());
}
foreach ($folders as $folder) {
list($files, $typed_folders) = array_values(FileManager::getFolderFilesRecursive($folder->getTypedFolder(), $user_id));
[$files, $typed_folders] = array_values(FileManager::getFolderFilesRecursive($folder->getTypedFolder(), $user_id));
foreach ($files as $file) {
$all_files[$file->id] = $file;
}
......@@ -187,4 +190,67 @@ class CourseTopic extends SimpleORMap
}
return ['files' => $all_files, 'folders' => $all_folders];
}
/**
* Increases the priority of this topic. Meaning the topic will be sorted further up.
* Be aware that this actually decreases the priority property since lower numbers
* mean higher priority.
*
* @return boolean
*/
public function increasePriority()
{
// Update all the course's topics with a lower priority than this one
$query = "UPDATE `themen`
SET `priority` = `priority` + 1
WHERE `seminar_id` = :course_id
AND `priority` < :current_priority
ORDER BY `priority` DESC
LIMIT 1";
$changed = DBManager::get()->execute($query, [
':course_id' => $this->seminar_id,
':current_priority' => $this->priority,
]);
// If anything has changed, decrease priority. Otherwise the current
// topic is already at top.
if ($changed) {
$this->priority -= 1;
$this->store();
return true;
}
return false;
}
/**
* Decreases the priority of this topic. Meaning the topic will be sorted further down.
* Be aware that this actually increases the priority property since higher numbers
* mean lower priority.
*/
public function decreasePriority()
{
// Update all the course's topics with a higher priority than this one
$query = "UPDATE `themen`
SET `priority` = `priority` - 1
WHERE `seminar_id` = :course_id
AND `priority` > :current_priority
ORDER BY `priority` ASC
LIMIT 1";
$changed = DBManager::get()->execute($query, [
':course_id' => $this->seminar_id,
':current_priority' => $this->priority,
]);
// If anything has changed, increase priority. Otherwise the current
// topic is already at bottom.
if ($changed) {
$this->priority += 1;
$this->store();
return true;
}
return false;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment