diff options
| author | Rasmus Fuhse <fuhse@data-quest.de> | 2025-12-19 12:20:47 +0000 |
|---|---|---|
| committer | Rasmus Fuhse <fuhse@data-quest.de> | 2025-12-19 12:20:47 +0000 |
| commit | 680de640261a0b9005a6b3c084506d6abf51b433 (patch) | |
| tree | 3527474ecb01e621b4bbbf338f29ce6888ae1380 /lib | |
| parent | 47fd6fe31f93c06f816d4bb27e8fdb6c013af606 (diff) | |
Resolve "Widget Aktiver Prozesse"
Closes #5675
Merge request studip/studip!4299
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/classes/Processes/ProcessProvider.php | 13 | ||||
| -rw-r--r-- | lib/classes/Processes/Questionnaires.php | 86 | ||||
| -rw-r--r-- | lib/classes/Processes/TimedFolders.php | 42 | ||||
| -rw-r--r-- | lib/classes/RunningProcess.php | 37 | ||||
| -rw-r--r-- | lib/modules/RunningProcessesWidget.php | 26 | ||||
| -rw-r--r-- | lib/plugins/core/RunningProcessPlugin.php | 11 |
6 files changed, 215 insertions, 0 deletions
diff --git a/lib/classes/Processes/ProcessProvider.php b/lib/classes/Processes/ProcessProvider.php new file mode 100644 index 0000000..fcce4bd --- /dev/null +++ b/lib/classes/Processes/ProcessProvider.php @@ -0,0 +1,13 @@ +<?php +namespace Studip\Processes; + +interface ProcessProvider +{ + + /** + * Returns an array of RunningProcess objects for the given user. + * + * @return array : RunningProcess[] + */ + public static function getProcesses(\User $user): array; +} diff --git a/lib/classes/Processes/Questionnaires.php b/lib/classes/Processes/Questionnaires.php new file mode 100644 index 0000000..2354c95 --- /dev/null +++ b/lib/classes/Processes/Questionnaires.php @@ -0,0 +1,86 @@ +<?php + +namespace Studip\Processes; + +class Questionnaires implements ProcessProvider +{ + /** + * Retrieves all active questionnaires accessible to the given user. + * + * This method fetches questionnaires that: + * - Are currently active (within start and stop dates) + * - Are visible + * - Are assigned to courses, institutes, or status groups where the user is a member + * - Are either unanswered or still editable by the user + * + * For each qualifying questionnaire, it creates a RunningProcess object containing: + * - Context information (course/institute/status group) + * - Questionnaire details (title, URL) + * - Time constraints (start and end dates) + * - Response statistics (number of answers / total possible respondents) + * + * @return array : RunningProcess[] + */ + public static function getProcesses(\User $user) : array + { + $statement = \DBManager::get()->prepare(" + SELECT `questionnaires`.* + FROM `questionnaires` + INNER JOIN `questionnaire_assignments` USING (`questionnaire_id`) + LEFT JOIN `seminar_user` ON (`seminar_user`.`Seminar_id` = `questionnaire_assignments`.`range_id` AND `questionnaire_assignments`.`range_type` = 'course') + LEFT JOIN `user_inst` ON (`user_inst`.`Institut_id` = `questionnaire_assignments`.`range_id` AND `questionnaire_assignments`.`range_type` = 'institute') + LEFT JOIN `statusgruppe_user` ON (`statusgruppe_user`.`statusgruppe_id` = `questionnaire_assignments`.`range_id` AND `questionnaire_assignments`.`range_type` = 'statusgruppe') + LEFT JOIN `statusgruppen` ON (`statusgruppen`.`statusgruppe_id` = `questionnaire_assignments`.`range_id` AND `questionnaire_assignments`.`range_type` = 'statusgruppe') + LEFT JOIN `seminar_user` AS `teacher` ON (`teacher`.`Seminar_id` = `statusgruppen`.`range_id` AND `questionnaire_assignments`.`range_type` = 'statusgruppe' AND `teacher`.`status` IN ('tutor', 'dozent')) + WHERE `questionnaires`.`startdate` <= UNIX_TIMESTAMP() + AND `questionnaires`.`stopdate` >= UNIX_TIMESTAMP() + AND `questionnaires`.`visible` = 1 + AND (`seminar_user`.`user_id` = :user_id OR `teacher`.`user_id` = :user_id OR `user_inst`.`user_id` = :user_id OR `statusgruppe_user`.`user_id` = :user_id) + GROUP BY `questionnaires`.`questionnaire_id` + "); + $statement->execute(['user_id' => $user->id]); + $questionnaires = $statement->fetchAll(\PDO::FETCH_ASSOC); + $result = []; + + foreach ($questionnaires as $questionnaire_data) { + $questionnaire = \Questionnaire::buildExisting($questionnaire_data); + if ($questionnaire->isViewable() && (!$questionnaire->isAnswered() || $questionnaire->isEditable())) { + foreach ($questionnaire->assignments as $assignment) { + if ($questionnaire->isAnswerable() || $questionnaire->isEditable()) { + + $answers = $questionnaire->countAnswers(); + if ($assignment->range_type === 'course') { + $allPersons = \CourseMember::countBySQL("`Seminar_id` = ?", [$assignment->range_id]); + $range_id = $assignment->range_id; + } elseif($assignment->range_type === 'institute') { + $allPersons = \InstituteMember::countBySQL("`Institut_id` = ?", [$assignment->range_id]); + $range_id = $assignment->range_id; + } elseif($assignment->range_type === 'statusgruppe') { + $allPersons = \StatusgruppeUser::countBySQL("`statusgruppe_id` = ?", [$assignment->range_id]); + $statusgroup = \Statusgruppen::find($assignment->range_id); + if ($statusgroup) { + $range_id = $statusgroup->range_id; + } + } + + $result[] = new \RunningProcess( + $range_id, + \Icon::create("vote"), + _('Fragebogen'), + $questionnaire->isEditable() + ? \URLHelper::getURL('dispatch.php/questionnaire/evaluate/'.$questionnaire->id) + : \URLHelper::getURL('dispatch.php/questionnaire/answer/'.$questionnaire->id), + $questionnaire->startdate, + $questionnaire->stopdate, + true, + $questionnaire->title, + $questionnaire->isEditable() ? $answers.'/'.$allPersons : '', + $questionnaire->isEditable() ? sprintf(_('Rücklaufquote: %s'), $answers.'/'.$allPersons) : '' + ); + } + } + } + } + return $result; + } +} diff --git a/lib/classes/Processes/TimedFolders.php b/lib/classes/Processes/TimedFolders.php new file mode 100644 index 0000000..1460183 --- /dev/null +++ b/lib/classes/Processes/TimedFolders.php @@ -0,0 +1,42 @@ +<?php + +namespace Studip\Processes; + +class TimedFolders implements ProcessProvider +{ + /** + * Retrieves an array of timed folder processes that are visible, active, and linked to the given user. + * The method fetches folders of type "TimedFolder" for which the user has access, + * processes each folder to check its visibility and end time, and compiles them into a list + * of ongoing processes with relevant details such as folder name, start time, end time, and file information. + * + * @return array : RunningProcess[] + */ + public static function getProcesses(\User $user) : array + { + $folders = \Folder::findBySQL("LEFT JOIN `seminar_user` ON (`seminar_user`.`Seminar_id` = `folders`.`range_id` AND `folders`.`range_type` = 'course') + LEFT JOIN `user_inst` ON (`user_inst`.`Institut_id` = `folders`.`range_id` AND `folders`.`range_type` = 'institute') + WHERE `folders`.`folder_type` = 'TimedFolder' + AND (`seminar_user`.`user_id` = :user_id OR `user_inst`.`user_id` = :user_id) + ", ['user_id' => $user->id]); + $result = []; + foreach ($folders as $folder) { + $folderType = $folder->getTypedFolder(); + if ($folderType->isVisible($user->id) && ($folderType->end_time > 0)) { + $files = $folderType->getFiles(); + $result[] = new \RunningProcess( + $folder->range_id, + $folderType->getIcon(), + _('Zeitgesteuerter Ordner'), + \URLHelper::getURL('dispatch.php/course/files/index/'.$folder->id, ['cid' => $folder->range_id]), + $folderType->start_time, + $folderType->end_time, + false, + $folder->name, + $folderType->isReadable($user->id) && (count($files) > 0) ? sprintf(ngettext('%d Datei', '%d Dateien', count($files)), count($files)) : '' + ); + } + } + return $result; + } +} diff --git a/lib/classes/RunningProcess.php b/lib/classes/RunningProcess.php new file mode 100644 index 0000000..ca71068 --- /dev/null +++ b/lib/classes/RunningProcess.php @@ -0,0 +1,37 @@ +<?php + +class RunningProcess +{ + public readonly string $id; + public function __construct( + public readonly string $context_id, + public readonly Icon $icon, + public readonly string $type, + public readonly string $url, + public readonly int $begin, + public readonly int $end, + public readonly bool $dialog = false, + public readonly string $title = '', + public readonly string $additionalShortInfo = '', + public readonly string $additionalInfoTitleTag = '' + ) { + $this->id = uniqid(); + } + + public function toArray() + { + return [ + 'id' => $this->id, + 'context_id' => $this->context_id, + 'icon' => $this->icon->asImagePath(), + 'type' => $this->type, + 'url' => $this->url, + 'begin' => $this->begin, + 'end' => $this->end, + 'dialog' => $this->dialog, + 'title' => $this->title, + 'additionalShortInfo' => $this->additionalShortInfo, + 'additionalInfoTitleTag' => $this->additionalInfoTitleTag + ]; + } +} diff --git a/lib/modules/RunningProcessesWidget.php b/lib/modules/RunningProcessesWidget.php new file mode 100644 index 0000000..54a4bd4 --- /dev/null +++ b/lib/modules/RunningProcessesWidget.php @@ -0,0 +1,26 @@ +<?php + +class RunningProcessesWidget extends CorePlugin implements PortalPlugin +{ + public function getPluginName() + { + return _('Meine Prozesse'); + } + + public function getMetadata() + { + return [ + 'description' => _('Dieses Widget zeigt offene Prozesse, wie unbearbeitete Fragebögen oder zeitgesteuerte Dateiordner, aus Ihren Veranstaltungen oder Einrichtungen an.') + ]; + } + + function getPortalTemplate() + { + $controller = app(\Trails\Dispatcher::class)->load_controller('running_processes'); + $response = $controller->relayWithRedirect('running_processes/widget'); + $template = $GLOBALS['template_factory']->open('shared/string'); + $template->content = $response->body; + + return $template; + } +} diff --git a/lib/plugins/core/RunningProcessPlugin.php b/lib/plugins/core/RunningProcessPlugin.php new file mode 100644 index 0000000..e64e75c --- /dev/null +++ b/lib/plugins/core/RunningProcessPlugin.php @@ -0,0 +1,11 @@ +<?php + +interface RunningProcessPlugin +{ + /** + * Returns an array of RunningProcess objects, that should be displayed in the running processes widget.. + * + * @return array : [RunningProcess, RunningProcess, ...] + */ + public function getRunningProcesses() : array; +} |
