. */ if (! defined('BASEPATH')) exit('No direct script access allowed'); use \stdClass as stdClass; /** * */ class SearchBarLib { // Error constats const ERROR_WRONG_JSON = 'ERR001'; const ERROR_WRONG_SEARCHSTR = 'ERR002'; const ERROR_NO_TYPES = 'ERR003'; const ERROR_WRONG_TYPES = 'ERR004'; const ERROR_NOT_AUTH = 'ERR005'; // List of allowed types of search const ALLOWED_TYPES = ['mitarbeiter', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms']; const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id='; private $_ci; // Code igniter instance /** * Gets the CI instance and loads model */ public function __construct() { $this->_ci =& get_instance(); // get code igniter instance // It is loaded only to have the DB_Model available $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); } //------------------------------------------------------------------------------------------------------------------ // Public methods /** * It performes the search of the given search string using the specified search types */ public function search($searchstr, $types) { // Checks if the given parameters are fine $search = $this->_checkParameters($searchstr, $types); // If the check was successful then perform the search if (isSuccess($search)) $search = $this->_search($searchstr, $types); return $search; // return the result } //------------------------------------------------------------------------------------------------------------------ // Private methods /** * Checks: * - The given searchstr is a not empty string * - The given types is a not empty array and contains allowed search types */ private function _checkParameters($searchstr, $types) { // If searchstr is empty if (isEmptyString($searchstr)) return error(self::ERROR_WRONG_SEARCHSTR); // If types is not an array or it is empty if (isEmptyArray($types)) return error(self::ERROR_NO_TYPES); // If all the elements in types are allowed search types if (!isEmptyArray(array_diff($types, self::ALLOWED_TYPES))) return error(self::ERROR_WRONG_TYPES); return success(); // The check is fine! } /** * Loops on types and perform the search of that type using searchstr * Then it collects all the returned data into an array as property of an object */ private function _search($searchstr, $types) { // Object to be returned $result = new stdClass(); $result->data = array(); // For each search type foreach ($types as $type) { // Perform the search and then add the result to data $result->data = array_merge($result->data, $this->{'_'.$type}($searchstr, $type)); } return $result; } private function _mitarbeiter_ohne_zuordnung($searchstr, $type) { $dbModel = new DB_Model(); $sql = ' SELECT \''.$type.'\' AS type, b.uid AS uid, p.person_id AS person_id, p.vorname || \' \' || p.nachname AS name, ARRAY_AGG(DISTINCT(org.bezeichnung)) AS organisationunit_name, COALESCE(b.alias, b.uid) || \''.'@'.DOMAIN.'\' AS email, TRIM(COALESCE(k.kontakt, \'\') || \' \' || COALESCE(m.telefonklappe, \'\')) AS phone, \''.base_url(self::PHOTO_IMG_URL).'\' || p.person_id AS photo_url, ARRAY_AGG(DISTINCT(stdkst.bezeichnung)) AS standardkostenstelle FROM public.tbl_mitarbeiter m JOIN public.tbl_benutzer b ON(b.uid = m.mitarbeiter_uid) LEFT JOIN ( SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid FROM public.tbl_benutzerfunktion bf JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) WHERE bf.funktion_kurzbz = \'kstzuordnung\' AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid ) stdkst ON stdkst.uid = b.uid JOIN public.tbl_person p USING(person_id) LEFT JOIN ( SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid FROM public.tbl_benutzerfunktion bf JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) WHERE bf.funktion_kurzbz = \'oezuordnung\' AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid ) org ON org.uid = b.uid LEFT JOIN ( SELECT kontakt, standort_id FROM public.tbl_kontakt WHERE kontakttyp = \'telefon\' ) k ON(k.standort_id = m.standort_id) WHERE (stdkst.bezeichnung IS NULL OR org.bezeichnung IS NULL) AND ( ' . $this->buildSearchClause( $dbModel, array('b.uid', 'p.vorname', 'p.nachname'), $searchstr ) . ' ) GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone '; $employees = $dbModel->execReadOnlyQuery($sql); // If something has been found then return it if (hasData($employees)) return getData($employees); // Otherwise return an empty array return array(); } protected function buildSearchClause(DB_Model $dbModel, array $columns, $searchstr) { $searchstr = preg_replace('/[[:punct:]]/', ' ', $searchstr); $document = implode(' || \' \' || ', $columns); $query = '\'' . implode(':* & ', explode(' ', trim($searchstr))) . ':*\''; $reversequery = '\'*:' . implode(' & *:', explode(' ', trim($searchstr))) . '\''; $nospacequery = '\'' . implode('', explode(' ', trim($searchstr))) . ':*\''; $searchclause = <<execReadOnlyQuery(' SELECT \''.$type.'\' AS type, b.uid AS uid, p.person_id AS person_id, p.vorname || \' \' || p.nachname AS name, ARRAY_AGG(DISTINCT(org.bezeichnung)) AS organisationunit_name, COALESCE(b.alias, b.uid) || \''.'@'.DOMAIN.'\' AS email, TRIM(COALESCE(k.kontakt, \'\') || \' \' || COALESCE(m.telefonklappe, \'\')) AS phone, \''.base_url(self::PHOTO_IMG_URL).'\' || p.person_id AS photo_url, ARRAY_AGG(DISTINCT(stdkst.bezeichnung)) AS standardkostenstelle FROM public.tbl_mitarbeiter m JOIN public.tbl_benutzer b ON(b.uid = m.mitarbeiter_uid) JOIN ( SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid FROM public.tbl_benutzerfunktion bf JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) WHERE bf.funktion_kurzbz = \'kstzuordnung\' AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid ) stdkst ON stdkst.uid = b.uid JOIN public.tbl_person p USING(person_id) JOIN ( SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid FROM public.tbl_benutzerfunktion bf JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) WHERE bf.funktion_kurzbz = \'oezuordnung\' AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid ) org ON org.uid = b.uid LEFT JOIN ( SELECT kontakt, standort_id FROM public.tbl_kontakt WHERE kontakttyp = \'telefon\' ) k ON(k.standort_id = m.standort_id) WHERE ' . $this->buildSearchClause( $dbModel, array('b.uid', 'p.vorname', 'p.nachname', 'org.bezeichnung', 'stdkst.bezeichnung'), $searchstr ) . ' GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone '); // If something has been found then return it if (hasData($employees)) return getData($employees); // Otherwise return an empty array return array(); } /** * Seach for organisation units */ private function _organisationunit($searchstr, $type) { $dbModel = new DB_Model(); $ous = $dbModel->execReadOnlyQuery(' SELECT \''.$type.'\' AS type, o.oe_kurzbz AS oe_kurzbz, \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS name, oParent.oe_kurzbz AS parentoe_kurzbz, (CASE WHEN oParent.bezeichnung IS NOT NULL THEN \'[\' || otParent.bezeichnung || \'] \' || oParent.bezeichnung END) AS parentoe_name, ARRAY_AGG(DISTINCT(bfLeader.uid)) AS leader_uid, ARRAY_AGG(DISTINCT(bfLeader.vorname || \' \' || bfLeader.nachname)) AS leader_name, COUNT(bfCount.benutzerfunktion_id) AS number_of_people, (CASE WHEN o.mailverteiler = TRUE THEN o.oe_kurzbz || \''.'@'.DOMAIN.'\' END) AS mailgroup FROM public.tbl_organisationseinheit o JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) LEFT JOIN public.tbl_organisationseinheit oParent ON(oParent.oe_kurzbz = o.oe_parent_kurzbz) LEFT JOIN public.tbl_organisationseinheittyp otParent ON(oParent.organisationseinheittyp_kurzbz = otParent.organisationseinheittyp_kurzbz) LEFT JOIN ( SELECT benutzerfunktion_id, oe_kurzbz FROM public.tbl_benutzerfunktion WHERE funktion_kurzbz = \'oezuordnung\' AND (datum_von IS NULL OR datum_von <= NOW()) AND (datum_bis IS NULL OR datum_bis >= NOW()) ) bfCount ON(bfCount.oe_kurzbz = o.oe_kurzbz) LEFT JOIN ( SELECT bf.oe_kurzbz, bf.uid, p.vorname, p.nachname FROM public.tbl_benutzerfunktion bf JOIN public.tbl_benutzer b USING(uid) JOIN public.tbl_person p USING(person_id) WHERE funktion_kurzbz = \'Leitung\' AND (datum_von IS NULL OR datum_von <= NOW()) AND (datum_bis IS NULL OR datum_bis >= NOW()) AND b.aktiv = TRUE ) bfLeader ON(bfLeader.oe_kurzbz = o.oe_kurzbz) WHERE o.aktiv = true AND (' . $this->buildSearchClause( $dbModel, array('o.oe_kurzbz', 'o.bezeichnung', 'ot.bezeichnung'), $searchstr ) . ') GROUP BY type, o.oe_kurzbz, o.bezeichnung, ot.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung, otParent.bezeichnung '); // If something has been found if (hasData($ous)) { // Loop through the returned dataset foreach (getData($ous) as $ou) { // Create the new property leaders as an empty array $ou->leaders = array(); // Loop through the found leaders for this organisation unit for ($i = 0; $i < count($ou->leader_uid); $i++) { // If a leader exists for this organisationunit and has a name :D if (!isEmptyString($ou->leader_uid[$i]) && !isEmptyString($ou->leader_name[$i])) { // Empty object that will contains the leader uid and name $leader = new stdClass(); // Set the properties name and uid $leader->uid = $ou->leader_uid[$i]; $leader->name = $ou->leader_name[$i]; // Add the leader object to the leaders array $ou->leaders[] = $leader; } } // Remove the not needed properties leader_uid and leader_name unset($ou->leader_uid); unset($ou->leader_name); } // Returns the changed dataset return getData($ous); } // Otherwise return an empty array return array(); } /** * Search for persons */ private function _person($searchstr, $type) { return array(); } /** * Search for students */ private function _student($searchstr, $type) { $dbModel = new DB_Model(); $students = $dbModel->execReadOnlyQuery(' SELECT \''.$type.'\' AS type, s.student_uid AS uid, s.matrikelnr, p.person_id AS person_id, p.vorname || \' \' || p.nachname AS name, k.kontakt as email , p.foto FROM public.tbl_student s JOIN public.tbl_benutzer b ON(b.uid = s.student_uid) JOIN public.tbl_person p USING(person_id) LEFT JOIN ( SELECT kontakt, person_id FROM public.tbl_kontakt WHERE kontakttyp = \'email\' ) as k USING(person_id) WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' GROUP BY type, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto '); // If something has been found then return it if (hasData($students)) return getData($students); // Otherwise return an empty array return array(); } /** * Search for prestudents */ private function _prestudent($searchstr, $type) { $dbModel = new DB_Model(); $prestudent = $dbModel->execReadOnlyQuery(' SELECT \''.$type.'\' AS type, ps.prestudent_id, ps.studiengang_kz, p.person_id AS person_id, b.uid, p.vorname || \' \' || p.nachname AS name, ( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = \'email\' AND person_id = p.person_id LIMIT 1 ) as email, p.foto, sg.bezeichnung FROM public.tbl_prestudent ps LEFT JOIN public.tbl_student s USING (prestudent_id) LEFT JOIN public.tbl_benutzer b ON (b.uid = s.student_uid) JOIN public.tbl_person p ON (p.person_id = ps.person_id) LEFT JOIN public.tbl_studiengang sg ON (sg.studiengang_kz = ps.studiengang_kz) WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' or cast(ps.prestudent_id as text) ILIKE \'%'.$dbModel->escapeLIKE($searchstr).'%\' GROUP BY type, b.uid, ps.prestudent_id, ps.studiengang_kz, sg.bezeichnung, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto '); // If something has been found then return it if (hasData($prestudent)) return getData($prestudent); // Otherwise return an empty array return array(); } /** * Search for documents */ private function _document($searchstr, $type) { return array(); } /** * Search for CMSs */ private function _cms($searchstr, $type) { return array(); } /** * Search for rooms */ private function _raum($searchstr, $type) { $dbModel = new DB_Model(); $rooms = $dbModel->execReadOnlyQuery(' SELECT \''.$type.'\' AS type, COALESCE(ort.ort_kurzbz, \'N/A\') as ort_kurzbz, COALESCE(ort.gebteil, \'N/A\') as building, COALESCE(ort.ausstattung, \'N/A\') as austattung, COALESCE(CAST(ort.stockwerk AS VARCHAR), \'N/A\') as floor, COALESCE(CAST(ort.dislozierung AS VARCHAR), \'N/A\') as room_number, COALESCE(CAST(ort.content_id AS VARCHAR), \'N/A\') as content_id, CASE WHEN standort.plz IS NULL OR standort.ort IS NULL THEN CASE WHEN standort.strasse IS NULL THEN CASE WHEN ort.stockwerk IS NULL THEN \'N/A\' ELSE CONCAT(ort.stockwerk,\' Stockwerk\') END ELSE CASE WHEN ort.stockwerk IS NULL THEN standort.strasse ELSE CONCAT(standort.strasse,\' / \',ort.stockwerk,\' Stockwerk\') END END ELSE CASE WHEN standort.strasse IS NULL THEN CASE WHEN ort.stockwerk IS NULL THEN CONCAT(standort.plz,\' \',standort.ort) ELSE CONCAT(standort.plz,\' \',standort.ort,\' / \',ort.stockwerk,\' Stockwerk\') END ELSE CASE WHEN ort.stockwerk IS NULL THEN CONCAT(standort.plz,\' \',standort.ort,\' / \',standort.strasse) ELSE CONCAT(standort.plz,\' \',standort.ort,\', \',standort.strasse,\' / \',ort.stockwerk,\' Stockwerk\') END END END as standort, CASE WHEN ort.max_person IS NULL OR ort.arbeitsplaetze IS NULL THEN \'N/A\' ELSE CONCAT(ort.max_person,\', davon \',ort.arbeitsplaetze,\' PC-Plätze\') END as sitzplaetze FROM public.tbl_ort as ort LEFT JOIN ( select ort,standort_id,strasse, plz FROM public.tbl_standort LEFT JOIN public.tbl_adresse USING(adresse_id) ) standort USING(standort_id) WHERE ort.aktiv = true AND ort.lehre = true AND (' . $this->buildSearchClause( $dbModel, array('ort.ort_kurzbz', 'ort.bezeichnung'), $searchstr ) . ')' ); // If something has been found if (hasData($rooms)) { // Returns the dataset return getData($rooms); } // Otherwise return an empty array return array(); } }