aboutsummaryrefslogtreecommitdiff
path: root/app/controllers/search/module.php
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+github@gmail.com>2021-07-22 16:07:19 +0200
committerJan-Hendrik Willms <tleilax+github@gmail.com>2021-07-22 16:19:12 +0200
commita3da1483a9e689846179159355badfec8073dbec (patch)
tree770dcca6bdf5f6f2a11b0e7fcbbeda6919a3fc52 /app/controllers/search/module.php
current code from svn, revision 62608
Diffstat (limited to 'app/controllers/search/module.php')
-rw-r--r--app/controllers/search/module.php601
1 files changed, 601 insertions, 0 deletions
diff --git a/app/controllers/search/module.php b/app/controllers/search/module.php
new file mode 100644
index 0000000..b9f3d22
--- /dev/null
+++ b/app/controllers/search/module.php
@@ -0,0 +1,601 @@
+<?php
+/**
+ * module.php - Search_ModuleController
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * @author Peter Thienel <thienel@data-quest.de>
+ * @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 before_filter(&$action, &$args)
+ {
+ $this->allow_nobody = Config::get()->COURSE_SEARCH_IS_VISIBLE_NOBODY;
+
+ 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 after_filter($action, $args) {
+ parent::after_filter($action, $args);
+ }
+
+ 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().'</br>'));
+ $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 = Semester::find($modul->start);
+ $end_sem = Semester::find($modul->end);
+ if ($start_sem->beginn > $this->selected_semester->beginn
+ || ($this->selected_semester->ende > $end_sem->ende && $end_sem != null)) {
+ unset($this->search_result['Modul'][$i]);
+ }
+ }
+
+ if ($do_search) {
+ PageLayout::postInfo(sprintf(ngettext(
+ '%s Modul gefunden für die Suche nach <em>%s</em>',
+ '%s Module gefunden für die Suche nach <em>%s</em>',
+ count($this->search_result['Modul'])),
+ count($this->search_result['Modul']),
+ htmlReady($this->sterm)));
+ }
+ }
+
+ $sidebar = Sidebar::get();
+
+ $widget = new SelectWidget(_('Semesterauswahl'),
+ $this->url_for('',['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 = 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->url_for('',['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->url_for('',['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->url_for('',['sterm' => $this->sterm, 'type' => 'Fachbereich']), 'id');
+ $widget->class = 'institute-list';
+ $options = [0 => 'Alle'];
+ $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 = [];
+ if (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->url_for('/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->url_for('/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_persons()
+ {
+ $term = '%' . $this->sterm . '%';
+ $stmt = DBManager::get()->prepare('SELECT modul_id, user_id FROM '
+ . 'mvv_modul_user LEFT JOIN auth_user_md5 USING(user_id) '
+ . 'WHERE Vorname LIKE ? OR Nachname LIKE ? '
+ . ' OR username LIKE ?');
+ $stmt->execute([$term, $term, $term]);
+ $ret = [];
+ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $module) {
+ $ret[$module['modul_id']][] = $module['user_id'];
+ }
+ return $ret;
+ }
+
+ 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')) {
+ $semester_switch = (int) Config::get()->SEMESTER_TIME_SWITCH;
+ $current_semester = Semester::findByTimestamp(time() + $semester_switch * 7 * 24 * 60 * 60);
+ $this->sessSet('selected_semester', $current_semester['semester_id']);
+ }
+ $this->selected_semester = Semester::find($this->sessGet('selected_semester'));
+ }
+}