* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 * @category Stud.IP * @since 4.1 */ abstract class GlobalSearchModule { /** * Employ generic cache methods. Be aware that this cache is shared among * the search modules so use indices properly: * * - user/:id for users * - range/:id for courses and institutes * - folder/id for folders * * Please add to this list if you add a new module that introduces a new * type. */ use GlobalSearchCacheTrait; /** * Returns the displayname for this module * * @return string */ abstract public static function getName(); /** * Has to return a SQL Query that discovers all objects. All retrieved data is passed row by row to getGlobalSearchFilter. * * @param string $search the input query string * @param array $filter an array with search limiting filter information (e.g. 'category', 'semester', etc.) * @return string SQL Query to discover elements for the search */ abstract public static function getSQL($search, $filter, $limit); /** * Returns an array of information for the found element. Following informations (key: description) are necessary * * - name: The name of the object * - url: The url to send the user to when he clicks the link * * Additional informations are: * * - additional: Subtitle for the hit * - expand: Url if the user further expands the search * - img: Avatar for the * * @param array $data One row returned from getSQL SQL Query * @param string $search The searchstring (Use for markup e.g. self::mark) * @return array Information Array */ abstract public static function filter($data, $search); /** * Returns the filters that are displayed in the sidebar of the global search. * * @return array Filters for this class. */ public static function getFilters() { return []; } /** * Returns the URL that can be called for a full search, containing * the specified category and the searchterm. * * Overwrite this method in your subclass to provide the category * specific search. * * @param string $searchterm what to search for? * @return string URL to the full search, containing the searchterm and the category */ public static function getSearchURL($searchterm) { return ''; } /** * Function to mark a querystring in a resultstring * * @param string $string Result string that should be displayed * @param string $query Query string to mark up * @param bool $longtext Indicates whether result might be a longer text * @param bool|true $filename Indicates whether the query string might denote a file. * @return string */ public static function mark($string, $query, $longtext = false, $filename = false) { // Secure $string = strip_tags($string); // Maximum length for an unshortened string. $maxlength = 100; if ($filename && mb_strpos($query, '/') !== false) { $args = explode('/', $query, 2); if ($args[1]) { return self::mark($string, trim($args[1])); } return self::mark($string, trim($args[0])); } $query = trim($query); // Replace direct string $quoted = preg_quote($query, '/'); $result = preg_replace("/{$quoted}/Si", "$0", $string, -1, $found); if ($found) { // Check for overlength if ($longtext && mb_strlen($result) > $maxlength) { $start = max([0, mb_stripos($result, '') - 20]); return '[...]' . mb_substr($result, $start, $maxlength) . '[...]'; } return $result; } // Replace camelcase $i = 1; $replacement = "${$i}"; foreach (preg_split('//u', mb_strtoupper($query), -1, PREG_SPLIT_NO_EMPTY) as $letter) { $quoted = preg_quote($letter, '/'); $queryletter[] = "({$quoted})"; $replacement .= '$' . ++$i . '$' . ++$i; } $pattern = '/([\w\W]*)' . implode('([\w\W]*)', $queryletter) . '/S'; $result = preg_replace($pattern, $replacement, $string, -1, $found); if ($found) { // Check for overlength if ($longtext && mb_strlen($result) > $maxlength) { $start = max([0, mb_stripos($result, '') - 20]); $space = mb_stripos($result, ' ', $start); $start = $space < $start + 20 ? $space : $start; return '[...]' . mb_substr($result, $start, $maxlength) . '[...]'; } return $result; } // Check for overlength if ($longtext && mb_strlen($result) > $maxlength) { return '[...]' . mb_substr($string, 0, $maxlength) . '[...]'; } if (mb_strlen($string) > $maxlength) { return mb_substr($string, 0, $maxlength) . '[...]'; } return $string; } /** * Get the selected institute with sub-institutes as an array of IDs * or a single institute as a string to use in the SQL query. * * @param string $institute_id ID of the given institute or faculty * @return array: a single institute as string if selected * or an array of institute IDs if a faculty was selected */ public static function getInstituteIdsForSQL($institute_id) { $institutes = Institute::findByFaculty($institute_id); if ($institutes) { $institute_ids = array_column($institutes, 'Institut_id'); $institute_ids[] = $institute_id; return $institute_ids; } else { return [$institute_id]; } } /** * Get the selected seminar class with sub-types as an array * or a single seminar type as a string to use in an SQL query. * * @param string $sem_class a single sem_type ID or a sem_class containing multiple sem_types * @return string: seminar class/types formatted for an SQL query */ public static function getSeminarTypesForSQL($sem_class) { $classes = SemClass::getClasses(); if ($pos = strpos($sem_class, '_')) { // return just the sem_types.id (which is equal to seminare.status) return substr($sem_class, $pos + 1); } else { $type_ids = []; // return an array containing all sem_types belonging to the chosen sem_class $class = $classes[$sem_class]; foreach ($class->getSemTypes() as $types_id => $types) { array_push($type_ids, $types['id']); } return $type_ids; } } /** * Get the current semester considering the given * SEMESTER_TIME_SWITCH in the CONFIG * (n weeks before the next semester) * * @return int The start time of the current semester. */ public static function getCurrentSemester() { $sem_time_switch = Config::get()->SEMESTER_TIME_SWITCH; $current_semester = Semester::findByTimestamp(time() + $sem_time_switch * 7 * 24 * 3600); return (int)$current_semester['beginn']; } /** * Returns a list of all active search modules * @return array search_class => data */ public static function getActiveSearchModules() { $modules = (array)array_filter( Config::get()->GLOBALSEARCH_MODULES, function ($data, $module) { if ($module === 'GlobalSearchModules' && !MVV::isVisibleSearch()) { return false; } if (in_array($module, ['GlobalSearchResources', 'GlobalSearchRoomAssignments']) && !Config::get()->RESOURCES_ENABLE ) { return false; } return $data['active'] && class_exists($module, true); }, ARRAY_FILTER_USE_BOTH ); return array_keys($modules); } }