* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 * @category Stud.IP * @since 3.5 */ class Search_ModuleController extends MVVController { private $drill_down_filter = []; public function __construct(Trails\Dispatcher $dispatcher) { $this->allow_nobody = Config::get()->getValue('COURSE_SEARCH_IS_VISIBLE_NOBODY'); parent::__construct($dispatcher); } public function before_filter(&$action, &$args) { parent::before_filter($action, $args); $this->drill_down_type = Request::option('type'); $this->drill_down_id = Request::option('id'); $this->sterm = Request::get('sterm'); if ($this->sterm) { URLHelper::bindLinkParam('sterm', $this->sterm); } if ($this->drill_down_type) { URLHelper::bindLinkParam('type', $this->drill_down_type); } if ($this->drill_down_id) { if($this->drill_down_id == '0') { $this->reset_drilldown(); } else { URLHelper::bindLinkParam('id', $this->drill_down_id); } } // set navigation Navigation::activateItem('/search/courses/module'); //set title PageLayout::setTitle(_('Modulverzeichnis - Modulsuche')); $sidebar = Sidebar::get(); $views = new ViewsWidget(); $views->addLink(_('Modulsuche'), $this->url_for('search/module')) ->setActive(); $views->addLink(_('Studienangebot'), $this->url_for('search/angebot')); $views->addLink(_('Studiengänge'), $this->url_for('search/studiengaenge')); $views->addLink(_('Fach-Abschlusskombinationen'), $this->url_for('search/stgtable')); $sidebar->addWidget($views); } protected static function IsVisible() { return MVV::isVisibleSearch(); } public function index_action() { $template = $this->get_template_factory() ->open('search/module/_infobox_info'); $helpbar = Helpbar::get(); $widget = new HelpbarWidget(); $widget->addElement(new WidgetElement($template->render().'
')); $widget->addElement(new WidgetElement(_('Auch unvollständige Namen (mindestens 3 Zeichen) werden akzeptiert.'))); $helpbar->addWidget($widget); $this->setSemester(); $this->page = Request::int('page_module', 1); $do_search = Request::int('do_search'); if (mb_strlen(trim(str_replace('%', '', $this->sterm))) < 3) { if ($do_search) { PageLayout::postInfo(_('Der Suchbegriff muss mindestens 3 Zeichen lang sein.')); } } else { // reset old search if ($do_search) { $this->page = 1; $this->reset_drilldown(); } // search // search in module content $this->search_result['Modul'] = Modul::search($this->sterm); // search for responsible institutes $search_responsible_institutes = $this->search_responsible_institutes(); // search for faecher $search_faecher = $this->search_faecher(); // search for studiengaenge $search_studiengaenge = $this->search_studiengaenge(); $this->search_result['Modul'] = array_unique( array_merge($this->search_result['Modul'], $search_responsible_institutes, $search_faecher, $search_studiengaenge)); foreach ($this->search_result['Modul'] as $i => $mod_id) { $modul = Modul::find($mod_id); $start_sem_begin = $modul->start_semester->beginn ?? 0; $end_sem_end = $modul->end_semester->ende ?? PHP_INT_MAX; if ( $start_sem_begin > $this->selected_semester->beginn || $this->selected_semester->ende > $end_sem_end ) { unset($this->search_result['Modul'][$i]); } } if ($do_search) { PageLayout::postInfo(sprintf(ngettext( '%s Modul gefunden für die Suche nach %s', '%s Module gefunden für die Suche nach %s', count($this->search_result['Modul'])), count($this->search_result['Modul']), htmlReady($this->sterm))); } } $sidebar = Sidebar::get(); $widget = new SelectWidget( _('Semesterauswahl'), $this->indexURL(['sterm' => $this->sterm]), 'sem_select' ); $options = []; $semester = Semester::findAllVisible(); unset($semester[0]); $semester = array_reverse($semester, true); foreach ($semester as $sem) { $options[$sem['semester_id']] = $sem['name']; } $widget->setOptions($options, $this->selected_semester->semester_id); $widget->setMaxLength(100); $sidebar->addWidget($widget, 'sem_filter'); $this->input_search = $this->sterm; $this->result_count = (!empty($this->search_result['Modul']) && is_array($this->search_result['Modul'])) ? count($this->search_result['Modul']) : 0; $drill_down['studiengaenge']['objects'] = $this->drilldown_studiengaenge($this->search_result['Modul'] ?? []); $drill_down['faecher']['objects'] = $this->drilldown_faecher($this->search_result['Modul'] ?? []); $drill_down['institutes']['objects'] = $this->drilldown_institutes($this->search_result['Modul'] ?? []); if (count($drill_down['institutes']['objects']) || count($drill_down['studiengaenge']['objects']) || count($drill_down['faecher']['objects'])) { $widget = new SelectWidget( _('Studiengänge'), $this->indexURL(['sterm' => $this->sterm, 'type' => 'Studiengang']), 'id' ); $options = [0 => _('Alle')]; if(!empty($drill_down['studiengaenge']['objects'])){ foreach ($drill_down['studiengaenge']['objects'] as $studiengang) { $options[$studiengang->studiengang_id] = $studiengang->name; } } $widget->setOptions($options, null); $widget->setMaxLength(100); $sidebar->addWidget($widget, 'studiengaenge_filter'); $widget = new SelectWidget( _('Fächer'), $this->indexURL(['sterm' => $this->sterm, 'type' => 'Fach']), 'id' ); $options = [0 => _('Alle')]; if(!empty($drill_down['faecher']['objects'])){ foreach ($drill_down['faecher']['objects'] as $fach) { $options[$fach->fach_id] = $fach->name; } } $widget->setOptions($options, null); $widget->setMaxLength(100); $sidebar->addWidget($widget, 'faecher_filter'); $widget = new SelectWidget( _('Verantwortliche Einrichtungen'), $this->indexURL(['sterm' => $this->sterm, 'type' => 'Fachbereich']), 'id' ); $widget->class = 'institute-list'; $widget->addElement(new SelectElement(0, _('Alle')), 'select-all'); if(!empty($drill_down['institutes']['objects'])){ foreach ($drill_down['institutes']['objects'] as $institut) { $widget->addElement( new SelectElement( $institut->institut_id, ($institut->institut_id != $institut->fakultaets_id ? ' ' : '') . $institut->name , $institut->institut_id === $this->drill_down_id ), 'select-' . $institut->name ); } } $sidebar->addWidget($widget, 'institutes_filter'); } $this->module = []; $this->count = 0; if (!empty($this->search_result['Modul']) && is_array($this->search_result['Modul']) && count($this->search_result['Modul'])) { if (!empty($this->drill_down_type) && !empty($this->drill_down_id)) { $this->search_result['Modul'] = $this->filter_modules( $this->search_result['Modul'], $this->drill_down_type, $this->drill_down_id); } $this->count = count($this->search_result['Modul']); $this->module = Modul::getAllEnriched('code, bezeichnung', 'ASC', self::$items_per_page, self::$items_per_page * ($this->page - 1), ['mvv_modul.modul_id' => $this->search_result['Modul']]); } } private function filter_modules($module_ids, $filter_by, $filter_id) { $ret = []; foreach ($module_ids as $modul_id) { switch ($filter_by) { case 'Studiengang': foreach (Studiengang::findByModule($modul_id) as $stg) { if ($stg->id == $filter_id) { $ret[] = $modul_id; break; } } break; case 'Fach': foreach (Fach::findPublicByModule($modul_id) as $fa) { if ($fa->id == $filter_id) { $ret[] = $modul_id; break; } } break; case 'Fachbereich': foreach (ModulInst::findByModul_id($modul_id) as $fab){ if ($fab->institut_id == $filter_id) { $ret[] = $modul_id; break; } } break; } } return $ret; } public function details_action($modul_id) { if ($this->drill_down_filter) { $this->drilldown(); } $this->setSemester(); $this->modul = Modul::find($modul_id); $courses = $this->getSemesterCourses($this->modul); $this->semester_select = []; // only valid (semesters between start and end of module) // semesters for selector // $sem_valid = false; // Augsburg Module ohne Angabe der Gültigkeit $sem_valid = !((boolean) $this->modul->start); $sem_number = 1; foreach (Semester::getAll() as $semester) { if ($sem_valid || $this->modul->start == $semester->getId()) { // show only semesters with assigned courses if (in_array($sem_number, $courses)) { $this->semester_select[] = $semester; } $sem_valid = true; } if ($this->modul->end == $semester->getId()) { break; } $sem_number++; } $this->semester_select = array_reverse($this->semester_select); $response = $this->relay('shared/modul/overview', $this->modul->getId(), $this->selected_semester->semester_id); if (Request::isXhr()) { $this->modul_content = $response->body; } else { $this->details_id = $modul_id; $this->modul_content = $response->body; $this->perform_relayed('index'); } } public function drilldown_action() { $this->initPageParams(); $this->drilldown(); $this->page = 1; $this->redirect($this->action_url('index')); } private function drilldown() { $object_type = $this->drill_down_type; if (in_array($object_type, ['Studiengang', 'Fach', 'Fachbereich'])) { $selected_object = $object_type::find($this->drill_down_id); if ($selected_object) { $this->drill_down_filter = $selected_object->getRelatedModules(true, $this->search_result['Modul']); } } } public function reset_drilldown_action() { $this->initPageParams(); $this->page = 1; $this->reset_drilldown(); $this->redirect($this->action_url('index')); } private function reset_drilldown() { unset($this->drill_down_filter); URLHelper::removeLinkParam('filter'); unset($this->drill_down_type); URLHelper::removeLinkParam('type'); unset($this->drill_down_id); URLHelper::removeLinkParam('id'); } private function search_responsible_institutes() { $term = '%' . $this->sterm . '%'; $modul_public_status = ModuleManagementModel::getPublicStatus('Modul'); $version_public_status = ModuleManagementModel::getPublicStatus('StgteilVersion'); $studiengang_public_status = ModuleManagementModel::getPublicStatus('Studiengang'); if (count($modul_public_status) && count($version_public_status) && count($studiengang_public_status)) { $query = 'SELECT DISTINCT(mmi.modul_id) ' . 'FROM Institute i ' . 'INNER JOIN mvv_modul_inst mmi ' . 'ON i.Institut_id = mmi.institut_id ' . 'INNER JOIN mvv_modul mm ON mmi.modul_id = mm.modul_id ' . 'INNER JOIN mvv_stgteilabschnitt_modul msm ' . 'ON mm.modul_id = msm.modul_id ' . 'INNER JOIN mvv_stgteilabschnitt msa ' . 'ON msm.abschnitt_id = msa.abschnitt_id ' . 'INNER JOIN mvv_stgteilversion msv ' . 'ON msa.version_id = msv.version_id ' . 'INNER JOIN mvv_stg_stgteil mss ' . 'ON msv.stgteil_id = mss.stgteil_id ' . 'INNER JOIN mvv_studiengang ms ' . 'ON mss.studiengang_id = ms.studiengang_id ' . 'WHERE i.Name LIKE ? ' . 'AND mm.stat IN (?) AND msv.stat IN (?) ' . 'AND ms.stat IN (?)'; $params = [$term, $modul_public_status, $version_public_status, $studiengang_public_status]; $stmt = DBManager::get()->prepare($query); $stmt->execute($params); } return $stmt->fetchAll(PDO::FETCH_COLUMN); } private function search_studiengaenge() { $term = '%' . $this->sterm . '%'; $modul_public_status = ModuleManagementModel::getPublicStatus('Modul'); $version_public_status = ModuleManagementModel::getPublicStatus('StgteilVersion'); $studiengang_public_status = ModuleManagementModel::getPublicStatus('Studiengang'); if (count($modul_public_status) && count($version_public_status) && count($studiengang_public_status)) { $query = 'SELECT DISTINCT(mm.modul_id) ' . 'FROM mvv_studiengang ms ' . 'INNER JOIN mvv_stg_stgteil USING(studiengang_id) ' . 'INNER JOIN mvv_stgteilversion msv USING(stgteil_id) ' . 'INNER JOIN mvv_stgteilabschnitt USING(version_id) ' . 'INNER JOIN mvv_stgteilabschnitt_modul USING(abschnitt_id) ' . 'INNER JOIN mvv_modul mm USING(modul_id) ' . 'WHERE (ms.name LIKE ? OR ms.name_kurz LIKE ?) ' . 'AND ms.stat IN (?) ' . 'AND msv.stat IN (?) AND mm.stat IN (?)'; $params = [$term, $term, $studiengang_public_status, $version_public_status, $modul_public_status]; $stmt = DBManager::get()->prepare($query); $stmt->execute($params); } return $stmt->fetchAll(PDO::FETCH_COLUMN); } private function search_faecher() { $term = '%' . $this->sterm . '%'; $ret = []; $modul_public_status = ModuleManagementModel::getPublicStatus('Modul'); $version_public_status = ModuleManagementModel::getPublicStatus('StgteilVersion'); $studiengang_public_status = ModuleManagementModel::getPublicStatus('Studiengang'); if (count($modul_public_status) && count($version_public_status)) { $query = 'SELECT DISTINCT(mm.modul_id) ' . 'FROM fach mf INNER JOIN mvv_stgteil USING(fach_id) ' . 'INNER JOIN mvv_stg_stgteil mss USING(stgteil_id) ' . 'INNER JOIN mvv_studiengang ms USING(studiengang_id) ' . 'INNER JOIN mvv_stgteilversion msv ' . 'ON mss.stgteil_id = msv.stgteil_id ' . 'INNER JOIN mvv_stgteilabschnitt USING(version_id) ' . 'INNER JOIN mvv_stgteilabschnitt_modul USING(abschnitt_id) ' . 'INNER JOIN mvv_modul mm USING(modul_id) ' . 'WHERE (mf.name LIKE ? OR mf.name_kurz LIKE ?) ' . 'AND ms.stat IN (?) AND mm.stat IN (?) ' . 'AND msv.stat IN (?)'; $params = [$term, $term, $studiengang_public_status, $modul_public_status, $version_public_status]; $stmt = DBManager::get()->prepare($query); $stmt->execute($params); $ret = $stmt->fetchAll(PDO::FETCH_COLUMN); } return $ret; } private function drilldown_persons($modul_ids) { if (count($modul_ids)) { $stmt = DBManager::get()->prepare('SELECT mmu.modul_id, aum.user_id, ' . $GLOBALS['_fullname_sql']['full'] . ' AS fullname, ' . 'COUNT(mmu.modul_id) AS count_module ' . 'FROM mvv_modul_user mmu LEFT JOIN auth_user_md5 aum USING(user_id) ' . 'LEFT JOIN user_info ui USING(user_id) ' . 'WHERE mmu.modul_id IN (?) ' . 'GROUP BY modul_id ' . 'ORDER BY count_module DESC'); $stmt->execute([$modul_ids]); return $stmt->fetchAll(PDO::FETCH_ASSOC); } return []; } private function drilldown_institutes($modul_ids) { if (is_array($modul_ids) && count($modul_ids)) { $fabs = []; foreach ($modul_ids as $modul_id) { $modul = Modul::find($modul_id); foreach ($modul->getResponsibleInstitutes() as $fab) { $fabs[$fab->id] = Fachbereich::find($fab->id); } } return SimpleORMapCollection::createFromArray($fabs); } return []; } private function drilldown_faecher($modul_ids) { if (is_array($modul_ids) && count($modul_ids)) { return Fach::findPublicByModule($modul_ids); } return []; } private function drilldown_studiengaenge($modul_ids) { if (is_array($modul_ids) && count($modul_ids)) { return Studiengang::findByModule($modul_ids); } return []; } public function reset_action() { $this->reset_search(); $this->redirect('search/module/index'); } protected function reset_search($action = '') { //parent::reset_search(); unset($this->sterm); URLHelper::removeLinkParam('sterm'); $this->reset_drilldown(); } public function overview_action($modul_id) { if ($this->drill_down_filter) { $this->drilldown(); } $this->setSemester(); $this->modul = Modul::get($modul_id); $courses = $this->getSemesterCourses($this->modul); $this->semester_select = []; // only valid (semesters between start and end of module) // semesters for selector // $sem_valid = false; // Augsburg Module ohne Angabe der Gültigkeit $sem_valid = !((boolean) $this->modul->start); $sem_number = 1; foreach (Semester::getAll() as $semester) { if ($sem_valid || $this->modul->start == $semester->getId()) { // show only semesters with assigned courses if (in_array($sem_number, $courses)) { $this->semester_select[] = $semester; } $sem_valid = true; } if ($this->modul->end == $semester->getId()) { break; } $sem_number++; } $this->semester_select = array_reverse($this->semester_select); $response = $this->relay('shared/modul/overview', $this->modul->getId(), $this->selected_semester->semester_id); if (Request::isXhr()) { $this->render_text($response->body); } else { $this->details_id = $modul_id; $this->modul_content = $response->body; $this->perform_relayed('index'); } } public function description_action($modul_id) { if ($this->drill_down_filter) { $this->drilldown(); } $response = $this->relay('shared/modul/description', $modul_id); if (Request::isXhr()) { $this->render_text($response->body); } else { $this->details_id = $modul_id; $this->modul_content = $response->body; $this->perform_relayed('index'); } } private function getSemesterCourses($modul) { $courses = []; foreach ($modul->modulteile as $modulteil) { foreach ($modulteil->lvgruppen as $lvgruppe) { $courses = array_merge( $courses, array_keys($lvgruppe->getAllAssignedCourses(true)) ); } } return $courses; } /** * Sets the default semester if no semester was selected by semester filter. */ private function setSemester() { if (Request::option('sem_select')) { $this->sessSet('selected_semester', Request::option('sem_select')); } if (!$this->sessGet('selected_semester')) { $current_semester = Semester::findDefault(); $this->sessSet('selected_semester', $current_semester['semester_id']); } $this->selected_semester = Semester::find($this->sessGet('selected_semester')); } }