aboutsummaryrefslogtreecommitdiff
path: root/lib/models
diff options
context:
space:
mode:
authorMurtaza Sultani <sultani@data-quest.de>2025-11-20 15:15:16 +0100
committerMurtaza Sultani <sultani@data-quest.de>2025-11-20 15:15:16 +0100
commit4c10ca495c20c3f2a07841c54fbd1888b2dbac28 (patch)
treea8daaaa18b6902098365b625fff48a14688fec51 /lib/models
parent091e85611b2bc83d8d760bcd209dcc7306c85dae (diff)
Resolve "Zielgruppenspezifische Startseitenwidgets"
Closes #4756 Merge request studip/studip!3696
Diffstat (limited to 'lib/models')
-rw-r--r--lib/models/MassWidget/MassWidget.php187
-rw-r--r--lib/models/MassWidget/MassWidgetFilter.php32
-rw-r--r--lib/models/WidgetUser.php8
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]);
}
}