Skip to content
Snippets Groups Projects
Commit 50202028 authored by Sebastian Biller's avatar Sebastian Biller Committed by André Noack
Browse files

fixes #410

parent 653cfb58
No related branches found
No related tags found
No related merge requests found
...@@ -53,6 +53,23 @@ class NewsController extends StudipController ...@@ -53,6 +53,23 @@ class NewsController extends StudipController
'icon' => 'person', 'icon' => 'person',
], ],
]; ];
$this->priorities = [
0 => '0 (' . _('normal') . ')',
1 => '1 (' . _('sehr niedrig') . ')',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
9 => '9',
10 => '10 (' . _('sehr hoch') . ')',
];
$this->roles = NewsRoles::getAvailableRoles();
$this->rolesStats = RolePersistence::getStatistics();
} }
/** /**
...@@ -166,6 +183,7 @@ class NewsController extends StudipController ...@@ -166,6 +183,7 @@ class NewsController extends StudipController
'news_basic' => true, 'news_basic' => true,
'news_comments' => false, 'news_comments' => false,
'news_areas' => false, 'news_areas' => false,
'news_visibility' => false,
]; ];
if ($context_range) { if ($context_range) {
...@@ -197,6 +215,15 @@ class NewsController extends StudipController ...@@ -197,6 +215,15 @@ class NewsController extends StudipController
if (!$news->havePermission('edit') && !$news->isNew()) { if (!$news->havePermission('edit') && !$news->isNew()) {
throw new AccessDeniedException(); throw new AccessDeniedException();
} }
if(!$news->isNew()){
$this->assigned = NewsRoles::getRoles($id);
if ($this->assigned){
$this->news_isvisible['news_visibility'] = true;
}
$this->roles = NewsRoles::getAvailableRoles($id);
}
// if form sent, get news data by post vars // if form sent, get news data by post vars
if (Request::get('news_isvisible')) { if (Request::get('news_isvisible')) {
// visible categories, selected areas, topic, and body are utf8 encoded when sent via ajax // visible categories, selected areas, topic, and body are utf8 encoded when sent via ajax
...@@ -216,6 +243,13 @@ class NewsController extends StudipController ...@@ -216,6 +243,13 @@ class NewsController extends StudipController
? $this->getTimeStamp(Request::get('news_enddate'), 'end') - $news->date ? $this->getTimeStamp(Request::get('news_enddate'), 'end') - $news->date
: ''; : '';
$news->allow_comments = Request::bool('news_allow_comments', false); $news->allow_comments = Request::bool('news_allow_comments', false);
$news->prio = Request::int('news_prio', 0);
$assignedroles = Request::intArray('assignedroles',false);
$this->assigned = NewsRoles::load($assignedroles);
if ($this->assigned){
$this->news_isvisible['news_visibility'] = true;
}
} elseif ($id) { } elseif ($id) {
// if news id given check for valid id and load ranges // if news id given check for valid id and load ranges
if ($news->isNew()) { if ($news->isNew()) {
...@@ -439,6 +473,10 @@ class NewsController extends StudipController ...@@ -439,6 +473,10 @@ class NewsController extends StudipController
$news->store(); $news->store();
if ($GLOBALS['perm']->have_perm('admin')) {
NewsRoles::update($news->id, $assignedroles);
}
PageLayout::postSuccess(_('Die Ankündigung wurde gespeichert.')); PageLayout::postSuccess(_('Die Ankündigung wurde gespeichert.'));
if (!Request::isXhr() && !$id) { if (!Request::isXhr() && !$id) {
// in fallback mode redirect to edit page with proper news id // in fallback mode redirect to edit page with proper news id
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
<input type="hidden" name="news_basic_js" value=""> <input type="hidden" name="news_basic_js" value="">
<input type="hidden" name="news_comments_js" value=""> <input type="hidden" name="news_comments_js" value="">
<input type="hidden" name="news_areas_js" value=""> <input type="hidden" name="news_areas_js" value="">
<input type="hidden" name="news_visibility_js" value="">
<input type="hidden" name="news_isvisible" value="<?=htmlReady(json_encode($news_isvisible))?>"> <input type="hidden" name="news_isvisible" value="<?=htmlReady(json_encode($news_isvisible))?>">
<input type="hidden" name="news_selectable_areas" value="<?=htmlReady(json_encode($area_options_selectable))?>"> <input type="hidden" name="news_selectable_areas" value="<?=htmlReady(json_encode($area_options_selectable))?>">
<input type="hidden" name="news_selected_areas" value="<?=htmlReady(json_encode($area_options_selected))?>"> <input type="hidden" name="news_selected_areas" value="<?=htmlReady(json_encode($area_options_selected))?>">
...@@ -256,6 +257,50 @@ ...@@ -256,6 +257,50 @@
</div> </div>
</fieldset> </fieldset>
<fieldset <?= $news_isvisible['news_visibility'] ? '' : 'class="collapsed"' ?>>
<legend class="news_visibility_header" id="news_visibility">
<?= _('Sichtbarkeitseinstellungen') ?>
</legend>
<? if ($anker == 'news_visibility') : ?>
<a name='anker'></a>
<? endif ?>
<label>
<?= _('Priorität') ?>
<select name="news_prio">
<? foreach ($priorities as $key => $label) : ?>
<option value ="<?= $key ?>"<?= $news->prio == $key ? ' selected' : '' ?>><?= $label ?></option>
<? endforeach ?>
</select>
</label>
<? if ($GLOBALS['perm']->have_perm('admin')) : ?>
<label>
<?= _('Sichtbarkeit') ?>
<select id="assignedroles" name="assignedroles[]" multiple>
<? if ($assigned) : ?>
<? foreach ($assigned as $assignedrole) : ?>
<option value="<?= $assignedrole->getRoleid() ?>" selected>
<?= htmlReady($assignedrole->getRolename()) ?>
<? if ($assignedrole->getSystemtype()) : ?>[<?= _('Systemrolle') ?>]<? endif ?>
(<?= $rolesStats[$assignedrole->getRoleid()]['explicit'] + $rolesStats[$assignedrole->getRoleid()]['implicit'] ?>)
</option>
<? endforeach ?>
<? endif ?>
<? foreach ($roles as $role) : ?>
<option value="<?= $role->getRoleid() ?>">
<?= htmlReady($role->getRolename()) ?>
<? if ($role->getSystemtype()) : ?>[<?= _('Systemrolle') ?>]<? endif ?>
(<?= $rolesStats[$role->getRoleid()]['explicit'] + $rolesStats[$role->getRoleid()]['implicit'] ?>)
</option>
<? endforeach ?>
</select>
</label>
<? endif ?>
</fieldset>
<footer data-dialog-button> <footer data-dialog-button>
<? if ($news->isNew()) : ?> <? if ($news->isNew()) : ?>
<?= Button::createAccept(_('Ankündigung erstellen'), 'save_news') ?> <?= Button::createAccept(_('Ankündigung erstellen'), 'save_news') ?>
...@@ -280,4 +325,9 @@ ...@@ -280,4 +325,9 @@
event.preventDefault(); event.preventDefault();
} }
}); });
<? if ($GLOBALS['perm']->have_perm('admin')) : ?>
$("#assignedroles").select2({
width: '100%'
});
<? endif ?>
</script> </script>
<?php
class tic410 extends Migration
{
public function description()
{
return "create NewsRoles table";
}
public function up()
{
$db = DBManager::get();
$query = 'CREATE TABLE IF NOT EXISTS `news_roles` (
`news_id` CHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`roleid` int(10) NOT NULL,
PRIMARY KEY (`news_id`, `roleid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;';
$db->exec($query);
$query = 'ALTER TABLE `news` ADD COLUMN `prio` tinyint(2) NOT NULL DEFAULT 0 AFTER `allow_comments`';
$db->exec($query);
$query = "INSERT IGNORE INTO `config` (`field`, `value`, `type`, `range`, `mkdate`, `chdate`, `description`)
VALUES (:name, :value, :type, :range, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), :description)";
$statement = DBManager::get()->prepare($query);
$statement->execute([
':name' => 'NEWS_ONLY_SYSTEM_ROLES',
':description' => 'Über diese Option wird die Auswahl der rollenspezifischen Ankündigungen auf Systemrollen begrenzt',
':range' => 'global',
':type' => 'boolean',
':value' => '1'
]);
}
public function down()
{
$db = DBManager::get();
$db->exec('DROP TABLE IF EXISTS `news_roles`');
$db->exec('ALTER TABLE `news` DROP COLUMN `prio`');
}
}
<?php
/**
* NewsRoles.class.php - model class for the news roles
*
* 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.
*
* @author Sebastian Biller <s.biller@tu-braunschweig.de>
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Stud.IP
* @package admin
* @since 5.1
*
* @property string news_id database column
* @property int roleid database column
*/
class NewsRoles extends SimpleORMap
{
protected static function configure($config = [])
{
$config['db_table'] = 'news_roles';
$config['belongs_to']['news_ranges'] = [
'class_name' => StudipNews::class,
'foreign_key' => 'news_id',
];
parent::configure($config);
}
public static function checkUserAccess($news_id, $user_id = null)
{
$user_id = $user_id ?: (isset($GLOBALS['user']) ? $GLOBALS['user']->id : null);
$news_roles = self::getRoles($news_id);
if (!$news_roles) {
return true;
}
if (!$user_id) {
return false;
}
$user_roles = RolePersistence::getAssignedRoles($user_id, true);
foreach ($news_roles as $news_role) {
foreach ($user_roles as $user_role) {
if ($news_role->getRoleid() === $user_role->getRoleid()) {
return true;
}
}
}
return false;
}
public static function getRoles($news_id)
{
$news_roles = self::findBynews_id($news_id);
$news_role_ids = [];
foreach ($news_roles as $news_role) {
$news_role_ids[] = $news_role['roleid'];
}
$only_system_roles = Config::get()->NEWS_ONLY_SYSTEM_ROLES;
$roles = RolePersistence::getAllRoles();
$re = [];
foreach ($news_role_ids as $role_id) {
if (isset($roles[$role_id])) {
if ($only_system_roles && !$roles[$role_id]->getSystemtype()) {
continue;
}
$re[$role_id] = $roles[$role_id];
}
}
return $re;
}
public static function getAvailableRoles($news_id = null)
{
$news_role_ids = [];
if ($news_id) {
$news_roles = self::findBynews_id($news_id);
foreach ($news_roles as $news_role) {
$news_role_ids[] = $news_role['roleid'];
}
}
$only_system_roles = Config::get()->NEWS_ONLY_SYSTEM_ROLES;
$roles = RolePersistence::getAllRoles();
$rolesStats = RolePersistence::getStatistics();
$re = [];
foreach ($roles as $key => $role) {
if (!in_array($key, $news_role_ids)) {
if ($only_system_roles && !$role->getSystemtype()) {
continue;
}
if ($rolesStats[$role->getRoleid()]['explicit'] + $rolesStats[$role->getRoleid()]['implicit'] == 0) {
continue;
}
$re[$key] = $role;
}
}
return $re;
}
public static function update($news_id, $new_roles)
{
self::deleteBynews_id($news_id);
if ($new_roles) {
foreach ($new_roles as $new_role) {
$NewsRoles = new self();
$NewsRoles->news_id = $news_id;
$NewsRoles->roleid = $new_role;
$NewsRoles->store();
}
}
}
public static function load($new_roles)
{
$roles = RolePersistence::getAllRoles();
return array_filter(array_map(
function ($role_id) use ($roles) {
if (!isset($roles[$role_id])) {
return false;
}
return [$role_id, $roles[$role_id]];
},
$new_roles
));
}
}
...@@ -36,6 +36,7 @@ require_once 'lib/object.inc.php'; ...@@ -36,6 +36,7 @@ require_once 'lib/object.inc.php';
* @property string user_id database column * @property string user_id database column
* @property string expire database column * @property string expire database column
* @property string allow_comments database column * @property string allow_comments database column
* @property int prio database column
* @property string chdate database column * @property string chdate database column
* @property string chdate_uid database column * @property string chdate_uid database column
* @property string mkdate database column * @property string mkdate database column
...@@ -64,6 +65,11 @@ class StudipNews extends SimpleORMap implements PrivacyObject ...@@ -64,6 +65,11 @@ class StudipNews extends SimpleORMap implements PrivacyObject
'class_name' => 'User', 'class_name' => 'User',
'foreign_key' => 'user_id', 'foreign_key' => 'user_id',
]; ];
$config['has_many']['news_roles'] = [
'class_name' => NewsRoles::class,
'assoc_foreign_key' => 'news_id',
'on_delete' => 'delete'
];
$config['i18n_fields']['topic'] = true; $config['i18n_fields']['topic'] = true;
$config['i18n_fields']['body'] = true; $config['i18n_fields']['body'] = true;
...@@ -96,25 +102,33 @@ class StudipNews extends SimpleORMap implements PrivacyObject ...@@ -96,25 +102,33 @@ class StudipNews extends SimpleORMap implements PrivacyObject
INNER JOIN news USING (news_id) INNER JOIN news USING (news_id)
WHERE range_id = ? {$clause} "; WHERE range_id = ? {$clause} ";
if (Config::get()->SORT_NEWS_BY_CHDATE) { if (Config::get()->SORT_NEWS_BY_CHDATE) {
$query .= "ORDER BY chdate DESC, date DESC, topic ASC"; $query .= "ORDER BY prio DESC, chdate DESC, date DESC, topic ASC";
} else { } else {
$query .= "ORDER BY date DESC, chdate DESC, topic ASC"; $query .= "ORDER BY prio DESC, date DESC, chdate DESC, topic ASC";
} }
$statement = DBManager::get()->prepare($query); $statement = DBManager::get()->prepare($query);
$statement->execute([$range_id]); $statement->execute([$range_id]);
$ret = $statement->fetchGrouped(PDO::FETCH_ASSOC); $ret = $statement->fetchGrouped(PDO::FETCH_ASSOC);
if (!(isset($GLOBALS['perm']) && $GLOBALS['perm']->have_perm('root'))) {
if (!(User::find($range_id) && $GLOBALS['user']->id == $range_id)) {
foreach ($ret as $news_id => $news) {
if (!NewsRoles::checkUserAccess($news_id)) {
unset($ret[$news_id]);
}
}
}
}
return $as_objects ? static::GetNewsObjects($ret) : $ret; return $as_objects ? static::GetNewsObjects($ret) : $ret;
} }
public static function CountUnread($range_id = 'studip', $user_id = false) public static function CountUnread($range_id = 'studip', $user_id = false)
{ {
$query = "SELECT SUM(nw.chdate > IFNULL(b.visitdate, :threshold) AND nw.user_id != :user_id) $query = "SELECT nw.news_id as idx, nw.chdate > IFNULL(b.visitdate, :threshold) AS active
FROM news_range a FROM news_range a
LEFT JOIN news nw ON (a.news_id = nw.news_id AND UNIX_TIMESTAMP() BETWEEN date AND date + expire) LEFT JOIN news nw ON (a.news_id = nw.news_id AND UNIX_TIMESTAMP() BETWEEN date AND date + expire)
LEFT JOIN object_user_visits b ON (b.object_id = nw.news_id AND b.user_id = :user_id AND b.plugin_id = :plugin_id) LEFT JOIN object_user_visits b ON (b.object_id = nw.news_id AND b.user_id = :user_id AND b.plugin_id = :plugin_id)
WHERE a.range_id = :range_id WHERE a.range_id = :range_id AND nw.user_id != :user_id";
GROUP BY a.range_id";
$statement = DBManager::get()->prepare($query); $statement = DBManager::get()->prepare($query);
$statement->bindValue(':threshold', object_get_visit_threshold()); $statement->bindValue(':threshold', object_get_visit_threshold());
$statement->bindValue(':user_id', $user_id ?: $GLOBALS['user']->id); $statement->bindValue(':user_id', $user_id ?: $GLOBALS['user']->id);
...@@ -122,7 +136,13 @@ class StudipNews extends SimpleORMap implements PrivacyObject ...@@ -122,7 +136,13 @@ class StudipNews extends SimpleORMap implements PrivacyObject
$plugin_id = object_type_to_id('news'); $plugin_id = object_type_to_id('news');
$statement->bindValue(':plugin_id', $plugin_id); $statement->bindValue(':plugin_id', $plugin_id);
$statement->execute(); $statement->execute();
return (int) $statement->fetchColumn(); $ret = $statement->fetchGrouped(PDO::FETCH_ASSOC);
foreach ($ret as $news_id => $news) {
if (!NewsRoles::checkUserAccess($news_id, $user_id) && !$GLOBALS['perm']->have_perm('root') || !$news['active']) {
unset($ret[$news_id]);
}
}
return (int) count($ret);
} }
public static function GetNewsByAuthor($user_id, $as_objects = false) public static function GetNewsByAuthor($user_id, $as_objects = false)
...@@ -131,13 +151,22 @@ class StudipNews extends SimpleORMap implements PrivacyObject ...@@ -131,13 +151,22 @@ class StudipNews extends SimpleORMap implements PrivacyObject
FROM news FROM news
WHERE user_id = ? "; WHERE user_id = ? ";
if (Config::get()->SORT_NEWS_BY_CHDATE) { if (Config::get()->SORT_NEWS_BY_CHDATE) {
$query .= "ORDER BY chdate DESC, date DESC"; $query .= "ORDER BY prio DESC, chdate DESC, date DESC";
} else { } else {
$query .= "ORDER BY date DESC, chdate DESC"; $query .= "ORDER BY prio DESC, date DESC, chdate DESC";
} }
$statement = DBManager::get()->prepare($query); $statement = DBManager::get()->prepare($query);
$statement->execute([$user_id]); $statement->execute([$user_id]);
$ret = $statement->fetchGrouped(PDO::FETCH_ASSOC); $ret = $statement->fetchGrouped(PDO::FETCH_ASSOC);
if (!(isset($GLOBALS['perm']) && $GLOBALS['perm']->have_perm('root'))) {
if ($GLOBALS['user']->id != $user_id) {
foreach ($ret as $news_id => $news) {
if (!NewsRoles::checkUserAccess($news_id)) {
unset($ret[$news_id]);
}
}
}
}
return $as_objects ? static::GetNewsObjects($ret) : $ret; return $as_objects ? static::GetNewsObjects($ret) : $ret;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment