diff options
| author | Murtaza Sultani <sultani@data-quest.de> | 2025-11-20 15:15:16 +0100 |
|---|---|---|
| committer | Murtaza Sultani <sultani@data-quest.de> | 2025-11-20 15:15:16 +0100 |
| commit | 4c10ca495c20c3f2a07841c54fbd1888b2dbac28 (patch) | |
| tree | a8daaaa18b6902098365b625fff48a14688fec51 /lib/models | |
| parent | 091e85611b2bc83d8d760bcd209dcc7306c85dae (diff) | |
Resolve "Zielgruppenspezifische Startseitenwidgets"
Closes #4756
Merge request studip/studip!3696
Diffstat (limited to 'lib/models')
| -rw-r--r-- | lib/models/MassWidget/MassWidget.php | 187 | ||||
| -rw-r--r-- | lib/models/MassWidget/MassWidgetFilter.php | 32 | ||||
| -rw-r--r-- | lib/models/WidgetUser.php | 8 |
3 files changed, 223 insertions, 4 deletions
diff --git a/lib/models/MassWidget/MassWidget.php b/lib/models/MassWidget/MassWidget.php new file mode 100644 index 0000000..f76a951 --- /dev/null +++ b/lib/models/MassWidget/MassWidget.php @@ -0,0 +1,187 @@ +<?php +namespace MassWidget; + +use DBManager; +use JSONArrayObject; +use Plugin; +use Semester; +use SimpleORMap; +use User; +use UserFilter; +use UserFilterRange; +use WidgetUser; + +class MassWidget extends SimpleORMap implements UserFilterRange +{ + protected static function configure($config = []) + { + $config['db_table'] = 'masswidget'; + + $config['serialized_fields']['settings'] = JSONArrayObject::class; + + $config['has_one']['author'] = [ + 'class_name' => User::class, + 'foreign_key' => 'author_id', + 'assoc_foreign_key' => 'user_id' + ]; + $config['has_many']['filters'] = [ + 'class_name' => MassWidgetFilter::class, + 'assoc_foreign_key' => 'masswidget_id', + 'on_store' => 'store', + 'on_delete' => 'delete' + ]; + $config['has_one']['plugin'] = [ + 'class_name' => Plugin::class, + 'foreign_key' => 'plugin_id', + 'assoc_foreign_key' => 'pluginid' + ]; + + parent::configure($config); + } + + public static function getTargets(): array + { + return [ + 'all' => _('alle'), + 'students' => _('Studierende'), + 'employees' => _('Mitarbeitende'), + 'lecturers' => _('Aktive Lehrende'), + 'courses' => _('Veranstaltungen'), + 'usernames' => _('Liste von Nutzernamen'), + ]; + } + + /** + * Gets the real recipient list for this widget. + * @return string[] The list of user IDs that will receive this widget. + */ + public function getTargetUserIds(): array + { + $ids = []; + + switch ($this->target) { + // Everyone studying something or working at an institute. + case 'all': + $students = DBManager::get()->fetchFirst("SELECT DISTINCT `user_id` FROM `user_studiengang`"); + + $employees = DBManager::get()->fetchFirst( + "SELECT DISTINCT `user_id` FROM `user_inst` WHERE `inst_perms` IN (:perms)", + ['perms' => ['autor', 'tutor', 'dozent']] + ); + + $ids = array_unique(array_merge($students, $employees)); + + break; + + // Students are users with at least one studycourse assignment in user_studiengang. + case 'students': + $ids = DBManager::get()->fetchFirst("SELECT DISTINCT `user_id` FROM `user_studiengang`"); + + if (count($this->filters) > 0) { + $filtered = []; + foreach ($this->filters as $filter) { + $f = new UserFilter($filter->filter_id); + $filtered = array_merge($filtered, $f->getUsers()); + } + + $ids = array_unique(array_intersect($ids, $filtered)); + } + + break; + + // Employees are users with at least one institute assignment at 'autor" level or more. + case 'employees': + $ids = DBManager::get()->fetchFirst( + "SELECT DISTINCT `user_id` FROM `user_inst` WHERE `inst_perms` IN (:perms)", + ['perms' => ['autor', 'tutor', 'dozent']] + ); + + if (count($this->filters) > 0) { + $filtered = []; + foreach ($this->filters as $filter) { + $f = new UserFilter($filter->filter_id); + $filtered = array_merge($filtered, $f->getUsers()); + } + + $ids = array_unique(array_intersect($ids, $filtered)); + } + + break; + + // Course members having the specified permission level. + case 'courses': + $courses = array_map( + fn ($course) => $course['id'], + $this->settings['courses']->getArrayCopy() + ); + $permission = $this->settings['perm']; + + $ids = DBManager::get()->fetchFirst( + "SELECT DISTINCT `user_id` FROM `seminar_user` WHERE `Seminar_id` IN (:courses) AND `status` = :perm", + ['courses' => $courses, 'perm' => $permission] + ); + + break; + + // Lecturers of at least one course in the given semester + case 'lecturers': + + $ids = DBManager::get()->fetchFirst( + "SELECT DISTINCT u.`user_id` FROM `seminar_user` u + LEFT JOIN `semester_courses` sc ON (sc.`course_id` = u.`Seminar_id`) + JOIN `seminare` s ON (s.`Seminar_id` = u.`Seminar_id`) + JOIN `sem_types` t ON (t.`id` = s.`status`) + WHERE (sc.`semester_id` = :semester OR sc.`semester_id` IS NULL) + AND t.`class` IN (:categories) + AND u.`status` = 'dozent'", + [ + 'semester' => $this->settings['semester'], + 'categories' => \Config::get()->MASSMAIL_LECTURER_SEM_CATEGORIES + ] + ); + + break; + + case 'usernames': + + $ids = DBManager::get()->fetchFirst( + "SELECT DISTINCT `user_id` FROM `auth_user_md5` WHERE `Username` IN (:usernames)", + ['usernames' => explode("\n", $this->settings['usernames'])] + ); + } + + return DBManager::get()->fetchFirst( + "SELECT DISTINCT `user_id` + FROM `auth_user_md5` + WHERE `visible` != :visible + AND `locked` = :locked + AND `user_id` IN (:ids) + AND `username` NOT IN (:exclude) + ORDER BY `username` + ", + [ + 'visible' => 'never', + 'locked' => 0, + 'ids' => $ids, + 'exclude' => $this->exclude_users ? explode("\n", $this->exclude_users) : [''] + ] + ); + } + + public function deleteUserWidgets(): self + { + $recipientIds = $this->getTargetUserIds(); + + WidgetUser::deleteBySQL( + 'pluginid = :plugin_id AND range_id IN (:user_ids)', + ['plugin_id' => $this->plugin_id, 'user_ids' => $recipientIds] + ); + + return $this; + } + + public function canEditFilter(User $user, UserFilter $filter): bool + { + return $GLOBALS['perm']->have_perm('root'); + } +} diff --git a/lib/models/MassWidget/MassWidgetFilter.php b/lib/models/MassWidget/MassWidgetFilter.php new file mode 100644 index 0000000..32c5dad --- /dev/null +++ b/lib/models/MassWidget/MassWidgetFilter.php @@ -0,0 +1,32 @@ +<?php +namespace MassWidget; +use UserFilter; + +class MassWidgetFilter extends \SimpleORMap +{ + protected static function configure($config = []) + { + $config['db_table'] = 'masswidget_filter'; + + $config['additional_fields']['userfilter']['get'] = function ($entry) { + return new UserFilter($entry->filter_id); + }; + $config['registered_callbacks']['before_delete'][] = 'deleteUserFilter'; + $config['registered_callbacks']['after_store'][] = 'updateUserFilterRange'; + + parent::configure($config); + } + + public function deleteUserFilter(): void + { + $filter = new UserFilter($this->filter_id); + $filter->delete(); + } + + public function updateUserFilterRange(): void + { + $filter = new UserFilter($this->filter_id); + $filter->setRange(MassWidget::class, $this->masswidget_id); + $filter->store(); + } +} diff --git a/lib/models/WidgetUser.php b/lib/models/WidgetUser.php index 84bb0c3..1b2b889 100644 --- a/lib/models/WidgetUser.php +++ b/lib/models/WidgetUser.php @@ -42,8 +42,8 @@ class WidgetUser extends SimpleORMap { if (self::countBySQL('range_id = ?', [$user_id]) === 0) { $stmt = DBManager::get()->prepare( - 'INSERT INTO widget_user (pluginid, position, range_id, col) - SELECT pluginid, position, :user_id, col FROM widget_default WHERE perm = :perm' + 'INSERT INTO widget_user (pluginid, position, range_id, col, chdate) + SELECT pluginid, position, :user_id, col, UNIX_TIMESTAMP() FROM widget_default WHERE perm = :perm' ); $stmt->execute([ 'user_id' => $user_id, @@ -61,7 +61,7 @@ class WidgetUser extends SimpleORMap */ public static function getWidgets($user_id): array { - $widgets = self::findBySQL('range_id = ? ORDER BY position', [$user_id]); + $widgets = self::findBySQL('is_active = 1 AND range_id = ? ORDER BY position', [$user_id]); $result = []; foreach ($widgets as $widget) { @@ -125,6 +125,6 @@ class WidgetUser extends SimpleORMap { self::setInitialWidgets($user_id); - return self::deleteBySQL('pluginid = ? AND range_id = ?', [$plugin_id, $user_id]); + return DBManager::get()->execute("UPDATE widget_user SET is_active = 0 WHERE range_id = ? AND pluginid = ?", [$user_id, $plugin_id]); } } |
