* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 * @category Stud.IP * @since 3.0 */ class Admission_CoursesetController extends AuthenticatedController { /** * Things to do before every page load. */ public function before_filter(&$action, &$args) { parent::before_filter($action, $args); PageLayout::setTitle(_('Anmeldesets')); // Get only own courses if user doesn't have permission to edit institute-wide coursesets. $this->onlyOwnCourses = true; if ($GLOBALS['perm']->have_perm('admin') || ($GLOBALS['perm']->have_perm('dozent') && Config::get()->ALLOW_DOZENT_COURSESET_ADMIN)) { // We have access to institute-wide course sets, so all courses may be assigned. $this->onlyOwnCourses = false; Navigation::activateItem('/browse/coursesets/sets'); } else { throw new AccessDeniedException(); } $views = new ActionsWidget(); $views->addLink( _('Anmeldeset anlegen'), $this->configureURL(), Icon::create('add') )->setActive($action === 'configure'); Sidebar::Get()->addWidget($views); if (!isset($this->instant_course_set_view)) { $this->instant_course_set_view = false; } } /** * Show all coursesets the current user has access to. */ public function index_action() { $this->course_set_details = Request::option('course_set_details'); if ($this->course_set_details && Request::isXhr()) { $courseset = new CourseSet($this->course_set_details); $this->render_text($courseset->toString()); return; } $this->ruleTypes = AdmissionRule::getAvailableAdmissionRules(false); $this->coursesets = []; foreach (words('current_institut_id current_rule_types set_name_prefix current_semester_id current_rule_types') as $param) { $this->$param = $_SESSION[self::class][$param] ?? null; } if (Request::submitted('choose_institut')) { $this->current_institut_id = Request::option('choose_institut_id'); $this->current_rule_types = Request::getArray('choose_rule_type'); $this->set_name_prefix = trim(Request::get('set_name_prefix')); $this->current_semester_id = Request::option('select_semester_id'); } if ($this->current_semester_id === null) { $this->current_semester_id = $_SESSION['_default_sem']; } else if ($this->current_semester_id !== '0') { $_SESSION['_default_sem'] = $this->current_semester_id; } if (!isset($this->current_rule_types)) { $this->current_rule_types = [ 'ParticipantRestrictedAdmission' => true, ]; } $filter['course_set_name'] = $this->set_name_prefix; $filter['semester_id'] = $this->current_semester_id != 'all' ? $this->current_semester_id : null; $filter['rule_types'] = array_keys($this->current_rule_types); $this->myInstitutes = CoursesetModel::getInstitutes($filter); if (!$this->current_institut_id && count($this->myInstitutes) > 0) { if (!isset($this->myInstitutes['all']['count']) || $this->myInstitutes['all']['count'] < 100) { $this->current_institut_id = 'all'; } else { $this->current_institut_id = array_key_first($this->myInstitutes) ?? 'all'; } } $chunks = explode('_', $this->current_institut_id); $institut_id = $chunks[0]; $all = $chunks[1] ?? null; if ($institut_id == 'all') { $institutes = array_keys($this->myInstitutes); } else if ($all == 'all') { $institutes[] = $institut_id; $institutes = array_merge($institutes, Institute::find($institut_id)->sub_institutes->pluck('institut_id')); } else { $institutes = [$institut_id]; } foreach ($institutes as $one) { if (!empty($this->myInstitutes[$one]['count'])) { $sets = CourseSet::getCoursesetsByInstituteId($one, $filter); foreach ($sets as $set) { $courseset = new CourseSet($set['set_id']); $this->coursesets[$set['set_id']] = $courseset; } } } uasort($this->coursesets, function($a,$b) { return strnatcasecmp($a->getName(), $b->getName()); }); if (!isset($_SESSION[self::class])) { $_SESSION[self::class] = []; } foreach (words('current_institut_id current_rule_types set_name_prefix current_semester_id current_rule_types') as $param) { $_SESSION[self::class][$param] = $this->$param; } $not_distributed_coursesets = array_filter(array_map(function ($cs) { return ($cs->isSeatDistributionEnabled() && $cs->getSeatDistributionTime() < (time() - 1000) && !$cs->hasAlgorithmRun()) ? $cs->getName() : null; }, $this->coursesets)); if (count($not_distributed_coursesets)) { PageLayout::postInfo( _('Es existieren Anmeldesets, die zum Zeitpunkt der Platzverteilung nicht gelost wurden. Stellen Sie sicher, dass der Cronjob "Losverfahren überprüfen" ausgeführt wird.'), array_unique($not_distributed_coursesets)); } } /** * Configure a new or existing course set. */ public function configure_action($coursesetId = '') { $this->courseset = null; $allCourses = []; if ($GLOBALS['perm']->have_perm('root')) { if ($coursesetId) { // Load course set data. $this->courseset = new CourseSet($coursesetId); $this->myInstitutes = []; $selectedInstitutes = $this->courseset->getInstituteIds(); foreach ($selectedInstitutes as $id => $selected) { $this->myInstitutes[$id] = new Institute($id); } $this->selectedInstitutes = $this->myInstitutes; $selectedCourses = $this->courseset->getCourses(); if (!$this->instant_course_set_view) { $allCourses = CoursesetModel::getInstCourses(array_keys($this->selectedInstitutes), $coursesetId, [], $this->courseset->getSemester()); $this->selectedSemester = $this->courseset->getSemester(); } } else { $this->myInstitutes = []; $this->selectedInstitutes = []; $selectedCourses = []; $this->selectedSemester = $_SESSION['_default_sem'] ?: Semester::findCurrent()->semester_id; } Config::get()->AJAX_AUTOCOMPLETE_DISABLED = false; $this->instSearch = QuickSearch::get('institute_id', new StandardSearch('Institut_id')) ->withoutButton() ->render(); } else { $this->myInstitutes = []; $myInstitutes = Institute::getMyInstitutes(); foreach ($myInstitutes as $institute) { $this->myInstitutes[$institute['Institut_id']] = $institute; } if ($coursesetId) { // Load course set data. $this->courseset = new CourseSet($coursesetId); $selectedInstitutes = $this->courseset->getInstituteIds(); $this->selectedInstitutes = []; foreach ($selectedInstitutes as $id => $selected) { $this->selectedInstitutes[$id] = new Institute($id); } $selectedCourses = $this->courseset->getCourses(); if (!$this->instant_course_set_view) { $allCourses = CoursesetModel::getInstCourses(array_keys($this->selectedInstitutes), $coursesetId, [], $this->courseset->getSemester(), $this->onlyOwnCourses); $this->selectedSemester = $this->courseset->getSemester(); } } else { $this->selectedSemester = $_SESSION['_default_sem'] ?: Semester::findCurrent()->semester_id; $this->selectedInstitutes = $this->myInstitutes; $allCourses = CoursesetModel::getInstCourses(array_keys($this->myInstitutes), $coursesetId, [], $this->selectedSemester, $this->onlyOwnCourses); $selectedCourses = []; } } // If an institute search has been conducted, we need to consider parameters from flash. if ($this->flash['name'] || $this->flash['institutes'] || $this->flash['courses'] || $this->flash['rules'] || $this->flash['userlists'] || $this->flash['infotext'] || $this->flash['semester']) { if (!$this->courseset) { $this->courseset = new CourseSet($coursesetId); } if ($this->flash['name']) { $this->courseset->setName($this->flash['name']); } if ($this->flash['institutes']) { $institutes = $this->flash['institutes']; $this->courseset->setInstitutes($institutes); if ($GLOBALS['perm']->have_perm('root')) { $this->myInstitutes = []; foreach ($institutes as $id) { $this->myInstitutes[$id] = new Institute($id); $this->selectedInstitutes[$id] = $this->myInstitutes[$id]; } } $selectedCourses = $this->courseset->getCourses(); $allCourses = CoursesetModel::getInstCourses(array_flip($institutes), $coursesetId, $selectedCourses, $this->selectedSemester, $this->onlyOwnCourses); } if ($this->flash['courses']) { $courses = $this->flash['courses']; $this->courseset->setCourses($courses); $selectedCourses = $courses; } if ($this->flash['rules']) { $this->courseset->setAdmissionRules($this->flash['rules']); } if ($this->flash['userlists']) { $this->courseset->setUserlists($this->flash['userlists']); } if ($this->flash['infotext']) { $this->courseset->setInfoText($this->flash['infotext']); } if ($this->flash['private']) { $this->courseset->setPrivate($this->flash['private']); } if ($this->flash['semester']) { $this->selectedSemester = $this->flash['semester']; } } // Fetch all lists with special user chances. $this->myUserlists = AdmissionUserList::getUserLists($GLOBALS['user']->id); $fac = $this->get_template_factory(); $tpl = $fac->open('admission/courseset/instcourses'); $tpl->set_attribute('allCourses', $allCourses); $tpl->set_attribute('selectedCourses', $selectedCourses); $this->coursesTpl = $tpl->render(); $tpl = $fac->open('admission/courseset/institutes'); if ($coursesetId) { $tpl->set_attribute('courseset', $this->courseset); } $tpl->set_attribute('instSearch', $this->instSearch); $tpl->set_attribute('selectedInstitutes', $this->selectedInstitutes); $tpl->set_attribute('myInstitutes', $this->myInstitutes); $tpl->set_attribute('controller', $this); if ($GLOBALS['perm']->have_perm('admin') || ($GLOBALS['perm']->have_perm('dozent') && Config::get()->ALLOW_DOZENT_COURSESET_ADMIN)) { $tpl->set_attribute('rights', true); } else { $tpl->set_attribute('rights', false); } $this->instTpl = $tpl->render(); $this->semesters = array_reverse(array_map( fn ($s) => $s->toArray(), Semester::getAll() )); if ($GLOBALS['perm']->have_perm('root')) { $this->isearch = new StandardSearch('Institut_id'); $this->myinst = []; } else { $this->isearch = null; $this->myinst = array_map( fn ($i) => [ 'id' => $i['Institut_id'], 'name' => $i['Name'], 'faculty' => $i['is_fak'] ? null : $i['fakultaets_id'] ], Institute::getMyInstitutes() ); } $props = [ 'all-semesters' => $this->semesters, 'my-institutes'=> $this->myinst, 'my-user-lists' => array_values( array_map( fn ($list) => [ 'id' => $list->getId(), 'name' => $list->getName(), 'factor' => $list->getFactor(), 'count' => $list->getUserCount() ], $this->myUserlists ) ), 'institute-search' => (string) $this->isearch, 'instant-course-set-view' => $this->instant_course_set_view ]; if ($this->courseset) { $props['course-set-id'] = $this->courseset->getId(); } $this->render_vue_app( Studip\VueApp::create('admission/ConfigureCourseSet') ->withProps($props) ); Helpbar::get()->addPlainText( _('Regeln'), _('Hier können Sie die Regeln, Eigenschaften und Zuordnungen des Anmeldesets bearbeiten.') ); Helpbar::get()->addPlainText( _('Info'), _('Sie können das Anmeldeset allen Einrichtungen zuordnen, an denen Sie mindestens Lehrendenrechte haben.') ); Helpbar::get()->addPlainText( _('Sichtbarkeit'), _('Alle Veranstaltungen der Einrichtungen, an denen Sie mindestens Lehrendenrechte haben, können zum Anmeldeset hinzugefügt werden.') ); } /** * Saves the given course set to database. * * @param String $coursesetId the course set to save or empty if it is a * new course set */ public function save_action($coursesetId = '') { if (!Request::submitted('submit') || !Request::get('name') || !$this->instant_course_set_view && !Request::getArray('institutes')) { $this->flash['name'] = Request::get('name'); $this->flash['institutes'] = Request::getArray('institutes'); $this->flash['courses'] = Request::getArray('courses'); $this->flash['rules'] = Request::getArray('rules'); $this->flash['userlists'] = Request::getArray('userlists'); $this->flash['infotext'] = Request::get('infotext'); $this->flash['private'] = (bool) Request::get('private'); $this->flash['semester'] = Request::option('semester'); if (Request::submitted('add_institute')) { $this->flash['institutes'] = array_merge($this->flash['institutes'], [Request::option('institute_id')]); } else { $this->flash['institute_id'] = Request::get('institute_id'); $this->flash['institute_id_parameter'] = Request::get('institute_id_parameter'); } if (!Request::submitted('add_institute') && !Request::option('name')) { $this->flash['error'] = _('Bitte geben Sie einen Namen für das Anmeldeset an!'); } if (!Request::submitted('add_institute') && !Request::getArray('institutes')) { $this->flash['error'] = _('Bitte geben Sie mindestens eine Einrichtung an, zu der das Anmeldeset gehört!'); } $this->redirect($this->url_for('admission/courseset/configure', $coursesetId)); } else { $courseset = new CourseSet($coursesetId); if (!$courseset->getUserId()) { $courseset->setUserId($GLOBALS['user']->id); } $courseset->setName(Request::get('name')); $courseset->setInstitutes(Request::getArray('institutes')); if (Request::option('semester')) { $courseset->setCourses(Request::getArray('courses')); } $courseset->setUserLists(Request::getArray('userlists')); if (!$this->instant_course_set_view && $courseset->isUserAllowedToEdit($GLOBALS['user']->id)) { $courseset->setPrivate((bool) Request::get('private')); } $courseset->setInfoText(Request::get('infotext')); $courseset->clearAdmissionRules(); foreach (Request::getManyObjects('rules', 'AdmissionRule') as $rule) { $courseset->addAdmissionRule($rule); } $courseset->store(); if (Request::option('semester')) { $_SESSION['_default_sem'] = Request::option('semester'); } PageLayout::postSuccess(sprintf(_('Das Anmeldeset: %s wurde gespeichert'), htmlReady($courseset->getName()))); if ($this->instant_course_set_view) { $this->relocate('course/admission'); } else { $this->relocate('admission/courseset/configure', $courseset->getId()); } } } /** * Deletes the given course set. * * @param String $coursesetId the course set to delete */ public function delete_action($coursesetId) { $this->courseset = new CourseSet($coursesetId); if (!$this->courseset->isUserAllowedToEdit(User::findCurrent()->id)) { throw new AccessDeniedException(_('Sie dürfen diese Anmelderegel nicht löschen.')); } if (Request::bool('really')) { $this->courseset->delete(); } $this->relocate('admission/courseset'); } /** * Fetches courses at institutes specified by a given course set, filtered by a * given semester. * * @param String $coursesetId The courseset to fetch institute assignments * from * @see CoursesetModel::getInstCourses */ public function instcourses_action($coursesetId = '') { CSRFProtection::verifyUnsafeRequest(); $this->selectedCourses = []; //autoload if ($coursesetId && !Request::getArray('courses')) { $courseset = new CourseSet($coursesetId); $this->selectedCourses = $courseset->getCourses(); } else if (Request::getArray('courses')) { $this->selectedCourses = Request::getArray('courses'); } $this->allCourses = CoursesetModel::getInstCourses(Request::getArray('institutes'), $coursesetId, $this->selectedCourses, Request::option('semester'), $this->onlyOwnCourses ?: Request::get('course_filter')); } /** * Fetches available institutes for the current user. */ public function institutes_action() { CSRFProtection::verifyUnsafeRequest(); $this->myInstitutes = Institute::getMyInstitutes(); $this->selectedInstitutes = []; foreach(Request::getArray('institutes') as $institute) { $this->selectedInstitutes[$institute] = new Institute($institute); } Config::get()->AJAX_AUTOCOMPLETE_DISABLED = false; $this->instSearch = QuickSearch::get('institute_id', new StandardSearch('Institut_id')) ->withOutButton() ->render(); } /** * Configure settings for several courses at once. * * @param String $set_id course set ID to fetch courses from * @param String $csv export course members to file */ public function configure_courses_action($set_id, $csv = null) { PageLayout::setTitle(_('Ausgewählte Veranstaltungen konfigurieren')); $courseset = new CourseSet($set_id); $this->set_id = $courseset->getId(); $this->courses = Course::findMany($courseset->getCourses(), "ORDER BY VeranstaltungsNummer, Name"); $this->applications = AdmissionPriority::getPrioritiesStats($courseset->getId()); $this->participant_restriction = $courseset->hasAdmissionRule('ParticipantRestrictedAdmission'); $distinct_members = []; $multi_members = []; foreach($this->courses as $course) { $all_members = $course->members->findBy('status', words('user autor'))->pluck('user_id'); $all_members = array_merge($all_members, $course->admission_applicants->findBy('status', words('accepted awaiting'))->pluck('user_id')); $all_members = array_unique($all_members); foreach ($all_members as $one) { if (!isset($multi_members[$one])) { $multi_members[$one] = 0; } $multi_members[$one]++; } $distinct_members = array_unique(array_merge($distinct_members, $all_members)); } $multi_members = array_filter($multi_members, function($a) {return $a > 1;}); $this->count_distinct_members = count($distinct_members); $this->count_multi_members = count($multi_members); if ($csv === 'csv') { $captions = [ _('Nummer'), _('Name'), _('versteckt'), _('Zeiten'), _('Lehrende'), _('max. Teilnehmende'), _('Teilnehmende aktuell'), _('Anzahl Anmeldungen'), _('Anzahl Anmeldungen Prio 1'), _('Warteliste'), _('max. Anzahl Warteliste'), _('automatisches Nachrücken aus der Warteliste') , _('vorläufige Anmeldung'), _('verbindliche Anmeldung'), ]; $data = []; foreach ($this->courses as $course) { $row = []; $row[] = $course->veranstaltungsnummer; $row[] = $course->name; $row[] = $course->visible ? _("nein") : _("ja"); $row[] = join('; ', $course->cycles->toString()); $row[] = join(', ', $course->members->findBy('status','dozent')->orderBy('position')->pluck('Nachname')); $row[] = $course->admission_turnout; $row[] = $course->getNumParticipants(); $row[] = $this->applications[$course->id]['c']; $row[] = $this->applications[$course->id]['h']; $row[] = $course->admission_disable_waitlist ? _('nein') : _('ja'); $row[] = $course->admission_waitlist_max > 0 ? $course->admission_waitlist_max : ''; $row[] = $course->admission_disable_waitlist_move ? _('nein') : _('ja'); $row[] = $course->admission_prelim ? _('ja') : _('nein'); $row[] = $course->admission_binding ? _('ja') : _('nein'); $data[] = $row; } $tmpname = md5(uniqid('tmp')); if (array_to_csv($data, $GLOBALS['TMP_PATH'].'/'.$tmpname, $captions)) { $this->redirect( FileManager::getDownloadURLForTemporaryFile( $tmpname, 'Veranstaltungen_' . $courseset->getName() . '.csv' ) ); return; } } if (in_array($csv, words('download_all_members download_multi_members'))) { $liste = []; $multi_members = $all_participants = []; foreach($this->courses as $course) { $participants = $course->members->findBy('status', words('user autor'))->toGroupedArray('user_id', words('username vorname nachname email status')); $participants += $course->admission_applicants->findBy('status', words('accepted awaiting'))->toGroupedArray('user_id', words('username vorname nachname email status')); $all_participants += $participants; foreach (array_keys($participants) as $one) { $multi_members[$one][] = $course->name . ($course->veranstaltungsnummer ? '|'. $course->veranstaltungsnummer : ''); } foreach ($participants as $part) { $liste[] = [$part['username'], $part['vorname'], $part['nachname'], $part['email'], $course->name . ($course->veranstaltungsnummer ? '|'. $course->veranstaltungsnummer : '') , $part['status']]; } } if ($csv == 'download_all_members') { $captions = [_('Username'), _('Vorname'), _('Nachname'), _('E-Mail'), _('Veranstaltung'), _('Status')]; if (count($liste)) { $tmpname = md5(uniqid('tmp')); if (array_to_csv($liste, $GLOBALS['TMP_PATH'].'/'.$tmpname, $captions)) { $this->redirect( FileManager::getDownloadURLForTemporaryFile( $tmpname, 'Gesamtteilnehmendenliste_' . $courseset->getName() . '.csv' ) ); return; } } } else { $liste = []; $multi_members = array_filter($multi_members, function ($a) {return count($a) > 1;}); $c = 0; $max_count = []; foreach ($multi_members as $user_id => $courses) { $member = $all_participants[$user_id]; $liste[$c] = [$member['username'], $member['vorname'], $member['nachname'], $member['email']]; foreach ($courses as $one) { $liste[$c][] = $one; } $max_count[] = count($courses); $c++; } $captions = [_('Nutzername'), _('Vorname'), _('Nachname'), _('E-Mail')]; foreach (range(1,max($max_count)) as $num) { $captions[] = _('Veranstaltung') . ' ' . $num; } if (count($liste)) { $tmpname = md5(uniqid('tmp')); if (array_to_csv($liste, $GLOBALS['TMP_PATH'].'/'.$tmpname, $captions)) { $this->redirect( FileManager::getDownloadURLForTemporaryFile( $tmpname, 'Mehrfachanmeldungen_' . $courseset->getName() . '.csv' ) ); return; } } } } if (Request::submitted('configure_courses_save')) { CSRFProtection::verifyUnsafeRequest(); $admission_turnouts = Request::intArray('configure_courses_turnout'); $admission_waitlists = Request::intArray('configure_courses_disable_waitlist'); $admission_waitlists_max = Request::intArray('configure_courses_waitlist_max'); $admission_disable_waitlist_move = Request::intArray('admission_disable_waitlist_move'); $admission_bindings = Request::intArray('configure_courses_binding'); $admission_prelims = Request::intArray('configure_courses_prelim'); $hidden = Request::intArray('configure_courses_hidden'); $ok = 0; foreach($this->courses as $course) { if ($GLOBALS['perm']->have_studip_perm(Config::get()->ALLOW_DOZENT_COURSESET_ADMIN ? 'dozent' : 'admin', $course->id)) { $do_update_admission = $course->admission_turnout < $admission_turnouts[$course->id]; $course->admission_turnout = $admission_turnouts[$course->id]; $course->admission_disable_waitlist = isset($admission_waitlists[$course->id]) ? 0 : 1; $course->admission_waitlist_max = $course->admission_disable_waitlist ? 0 : $admission_waitlists_max[$course->id]; $course->admission_disable_waitlist_move = isset($admission_disable_waitlist_move[$course->id]) ? 0 : 1; $course->admission_binding = @$admission_bindings[$course->id] ?: 0; $course->admission_prelim = @$admission_prelims[$course->id] ?: 0; $course->visible = @$hidden[$course->id] ? 0 : 1; $ok += $course->store(); if ($do_update_admission) { AdmissionApplication::addMembers($course->id); } } } if ($ok) { PageLayout::postSuccess(_('Die zugeordneten Veranstaltungen wurden konfiguriert.')); } $this->relocate('admission/courseset/configure/' . $courseset->getId()); return; } } /** * Show users who are on an assigned user factor list. * * @param String $set_id course set to fetch the user lists from */ public function factored_users_action($set_id) { PageLayout::setTitle(_('Liste der Personen')); $courseset = new CourseSet($set_id); $factored_users = $courseset->getUserFactorList(); $applicants = AdmissionPriority::getPriorities($set_id); $this->users = User::findAndMapMany(function($u) use ($factored_users, $applicants) { return array_merge( $u->toArray('username vorname nachname'), ['applicant' => isset($applicants[$u->id]), 'factor' => $factored_users[$u->id]] ); }, array_keys($factored_users), 'ORDER BY Nachname, Vorname'); } /** * Gets the list of applicants for the courses belonging to this course set. * * @param String $set_id course set ID * @param String $csv export users to file */ public function applications_list_action($set_id, $csv = null) { PageLayout::setTitle(_('Liste der Anmeldungen')); $courseset = new CourseSet($set_id); $applicants = AdmissionPriority::getPriorities($set_id); $users = User::findMany(array_keys($applicants), 'ORDER BY Nachname, Vorname'); $courses = SimpleCollection::createFromArray(Course::findMany($courseset->getCourses())); $captions = [_('Nachname'), _('Vorname'), _('Nutzername'), _('Veranstaltung'), _('Nummer'), _('Studiengang'), _('Priorität')]; $data = []; $studycourses = function ($st) { return sprintf( '%s (%s)', trim($st->studycourse_name . ' ' . $st->degree_name), $st->semester ); }; foreach ($users as $user) { $app_courses = $applicants[$user->id]; asort($app_courses); foreach ($app_courses as $course_id => $prio) { $row = []; $row[] = $user->nachname; $row[] = $user->vorname; $row[] = $user->username; $row[] = $courses->findOneBy('id', $course_id)->name; $row[] = $courses->findOneBy('id', $course_id)->veranstaltungsnummer; $row[] = implode('; ', $user->studycourses->map($studycourses)); $row[] = $prio; if ($csv) { $row[] = $user->email; } $data[] = $row; } } if ($csv) { $tmpname = md5(uniqid('tmp')); $captions[] = _("E-Mail"); if (array_to_csv($data, $GLOBALS['TMP_PATH'].'/'.$tmpname, $captions)) { $this->redirect( FileManager::getDownloadURLForTemporaryFile( $tmpname, 'Anmeldungen_' . $courseset->getName() . '.csv' ) ); return; } } $this->captions = $captions; $this->data = $data; $this->set_id = $courseset->getId(); } public function applicants_message_action($set_id) { $courseset = new CourseSet($set_id); $applicants = AdmissionPriority::getPriorities($set_id); $_SESSION['sms_data'] = []; $_SESSION['sms_data']['p_rec'] = User::findAndMapMany(function ($u) { return $u->username; }, array_unique(array_keys($applicants))); $this->redirect(URLHelper::getURL('dispatch.php/messages/write', ['default_subject' => _("Anmeldung:") . ' ' . $courseset->getName(), 'emailrequest' => 1 ] )); } public function copy_action($set_id) { $courseset = new CourseSet($set_id); $cloned_courseset = clone $courseset; $cloned_courseset->setName(_("Kopie von:") . ' ' . $cloned_courseset->getName()); $cloned_courseset->store(); foreach ($cloned_courseset->getAdmissionRules() as $id => $rule) { if ($rule instanceOf ParticipantRestrictedAdmission) { if ($rule->getDistributionTime() && $rule->getDistributionTime() < time()) { $rule->setDistributionTime(strtotime('+1 month 23:59')); $rule->store(); $cloned_courseset->setAlgorithmRun(false); PageLayout::postInfo(sprintf( _('Bitte passen Sie das Datum der automatischen Platzverteilung an, es wurde automatisch auf %s festgelegt!'), strftime('%x %X', $rule->getDistributiontime()) )); } } else if ($rule->getEndTime() && $rule->getEndTime() < time()) { PageLayout::postInfo(sprintf( _('Der Gültigkeitszeitraum der Regel %s endet in der Vergangenheit!'), htmlReady($rule->getName()) )); } } $this->redirect(URLHelper::getURL('dispatch.php/admission/courseset/configure/' . $cloned_courseset->getId(), ['is_copy' => 1])); } /** * Gets courses fulfilling the given condition. * * @param String $seminare_condition SQL condition */ public function get_courses($seminare_condition) { list($institut_id, $all) = explode('_', $this->current_institut_id); // Prepare count statements $query = "SELECT count(*) FROM seminar_user WHERE seminar_id = ? AND status IN ('user', 'autor')"; $count0_statement = DBManager::get()->prepare($query); $query = "SELECT SUM(status = 'accepted') AS count2, SUM(status = 'awaiting') AS count3 FROM admission_seminar_user WHERE seminar_id = ? GROUP BY seminar_id"; $count1_statement = DBManager::get()->prepare($query); $parameters = []; $sql = "SELECT seminare.seminar_id,seminare.Name as course_name,seminare.VeranstaltungsNummer as course_number, admission_prelim, admission_turnout,seminar_courseset.set_id FROM seminar_courseset INNER JOIN courseset_rule csr ON csr.set_id=seminar_courseset.set_id AND csr.type='ParticipantRestrictedAdmission' INNER JOIN seminare ON seminar_courseset.seminar_id=seminare.seminar_id "; if ($institut_id === 'all' && $GLOBALS['perm']->have_perm('root')) { $sql .= "WHERE 1 {$seminare_condition} "; } elseif ($all == 'all') { $sql .= "INNER JOIN Institute USING (Institut_id) WHERE Institute.fakultaets_id = ? {$seminare_condition} "; $parameters[] = $institut_id; } else { $sql .= "WHERE seminare.Institut_id = ? {$seminare_condition} "; $parameters[] = $institut_id; } $sql .= "GROUP BY seminare.Seminar_id ORDER BY seminar_courseset.set_id, seminare.Name"; $statement = DBManager::get()->prepare($sql); $statement->execute($parameters); $ret = []; while ($row = $statement->fetch(PDO::FETCH_ASSOC)) { $seminar_id = $row['seminar_id']; $ret[$seminar_id] = $row; $count0_statement->execute([$seminar_id]); $count = $count0_statement->fetchColumn(); $ret[$seminar_id]['count_teilnehmer'] = $count; $count1_statement->execute([$seminar_id]); $counts = $count1_statement->fetch(PDO::FETCH_ASSOC); $ret[$seminar_id]['count_prelim'] = (int)$counts['count2']; $ret[$seminar_id]['count_waiting'] = (int)$counts['count3']; $cs = new CourseSet($row['set_id']); $ret[$seminar_id]['cs_name'] = $cs->getName(); $ret[$seminar_id]['distribution_time'] = $cs->getSeatDistributionTime(); if ($ta = $cs->getAdmissionRule('TimedAdmission')) { $ret[$seminar_id]['start_time'] = $ta->getStartTime(); $ret[$seminar_id]['end_time'] = $ta->getEndTime(); } if (!$cs->hasAlgorithmRun()) { $ret[$seminar_id]['count_claiming'] = $cs->getNumApplicants(); } } return $ret; } /** * Performs bulk operation on a set of coursesets. */ public function bulk_action() { if (!Request::isPost()) { throw new MethodNotAllowedException(); } $ids = Request::optionArray('ids'); if (Request::submitted('delete')) { $deleted = 0; foreach ($ids as $id) { $courseset = new CourseSet($id); if ($courseset->isUserAllowedToEdit(User::findCurrent()->id)) { $courseset->delete(); $deleted += 1; } } if ($deleted > 0) { PageLayout::postSuccess(_('Die Anmeldesets wurden gelöscht.')); } } $this->redirect('admission/courseset'); } }