Skip to content
Snippets Groups Projects
Select Git revision
  • 442d9d2625dd56c1c867bf9c8fc7ddb36d63dd14
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

globalsearch.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    globalsearch.php 6.22 KiB
    <?php
    /**
     * globalsearch.php - controller to perform global search operations and provide settings.
     *
     * 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      Thomas Hackl <thomas.hackl@uni-passau.de>
     * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
     * @category    Stud.IP
     * @since       4.1
     */
    
    class GlobalSearchController extends AuthenticatedController
    {
        public function before_filter(&$action, &$args)
        {
            parent::before_filter($action, $args);
    
            if (in_array($action, ['settings', 'saveconfig'])) {
                $GLOBALS['perm']->check('root');
            }
        }
    
        /**
         * Perform search in all registered modules for the given search term.
         */
        public function find_action($limit)
        {
            $limit = min(100, (int)$limit);
            // Perform search by mysqli (=async) or by PDO (=sync)?
            $async = Config::get()->GLOBALSEARCH_ASYNC_QUERIES
                     && extension_loaded('mysqli');
            if ($async) {
                // throw exceptions on mysqli error
                $driver = new mysqli_driver();
                $driver->report_mode = MYSQLI_REPORT_ERROR;
            }
    
            // Now load all modules
            $modules = GlobalSearchModule::getActiveSearchModules();
    
            $search = trim(Request::get('search'));
    
            $filter = json_decode(Request::get('filters'), true);
    
            $result = [];
    
            foreach ($modules as $className) {
                $partSQL = $className::getSQL($search, $filter, $limit);
    
                // No valid sql? Leave.
                if (!$partSQL) {
                    continue;
                }
    
                // Global config setting says to use mysqli
                if ($async) {
                    $mysqli = new mysqli($GLOBALS['DB_STUDIP_HOST'], $GLOBALS['DB_STUDIP_USER'],
                        $GLOBALS['DB_STUDIP_PASSWORD'], $GLOBALS['DB_STUDIP_DATABASE']);
                    mysqli_set_charset($mysqli, 'UTF8');
                    if ($mysqli->multi_query($partSQL . '; SELECT FOUND_ROWS() as found_rows;')) {
                        do {
                            if ($res = $mysqli->store_result()) {
                                $all_links[$className][] = $res->fetch_all(MYSQLI_ASSOC);
                                $res->free();
                            }
                        } while ($mysqli->more_results() && $mysqli->next_result());
                    }
                    $entries = $all_links[$className][0];
                    $entries_count = (int)$all_links[$className][1][0]['found_rows'];
                // Global config setting calls for PDO
                } else {
                    $entries = DBManager::get()->fetchAll($partSQL);
                    $entries_count_array = DBManager::get()->fetchAll('SELECT FOUND_ROWS() as found_rows');
                    $entries_count = (int)$entries_count_array[0]['found_rows'];
                }
    
                // No results? Leave.
                if (!is_array($entries)) {
                    continue;
                }
    
                // Walk through results
                $found = [];
                foreach ($entries as $one) {
                    // Filter item and add to result if necessary.
                    if ($item = $className::filter($one, $search)) {
                        $found[] = $item;
                    }
                }
    
                // Nothing found? Leave.
                if (count($found) === 0) {
                    continue;
                }
    
                $result[$className] = [
                    'name'       => $className::getName(),
                    'fullsearch' => $className::getSearchURL($search),
                    'content'    => $found,
                    // If we found more results than needed, indicate a "more" link
                    // for full search.
                    'more'       => count($found) > Config::get()->GLOBALSEARCH_MAX_RESULT_OF_TYPE,
                    // If there are more results than our arbitrary LIMIT, a plus
                    // ('+') should be shown besides the category result count
                    'plus'       => count($found) < $entries_count,
                ];
            }
    
            GlobalSearchModule::clearCache();
    
            // Sort
            $positions = array_flip($modules);
            uksort($result, function($a, $b) use ($positions) {
                return $positions[$a] - $positions[$b];
            });
    
            // Send me an answer
            $this->render_json($result);
        }
    
        /**
         * Provide a GUI for configuring the search module order and other settings.
         */
        public function settings_action()
        {
            PageLayout::setTitle(_('Globale Suche: Einstellungen'));
            Navigation::activateItem('/admin/config/globalsearch');
    
            $this->config = Config::get()->GLOBALSEARCH_MODULES;
            $this->modules = [];
    
            foreach ($this->config as $className => $config) {
                if (class_exists($className)) {
                    $this->modules[$className] = new $className();
                }
            }
    
            // Search declared classes for GlobalSearchModules
            foreach (get_declared_classes() as $className) {
                if (is_subclass_of($className, 'GlobalSearchModule')) {
    
                    // Add new classes at module array end and not activated.
                    if (!isset($this->modules[$className])) {
                        $this->modules[$className] = new $className();
                    }
                }
            }
        }
    
        /**
         * Saves the set values to global configuration.
         */
        public function saveconfig_action()
        {
            CSRFProtection::verifyUnsafeRequest();
    
            $config = [];
    
            foreach (Request::getArray('modules') as $module) {
                $config[$module['class']] = [
                    'active'   => (bool)$module['active'],
                    'fulltext' => is_a($module['class'], 'GlobalSearchFulltext', true) && $module['fulltext']
                ];
            }
    
            Config::get()->store('GLOBALSEARCH_ASYNC_QUERIES', Request::int('async_queries', 0));
            Config::get()->store('GLOBALSEARCH_MAX_RESULT_OF_TYPE', Request::int('entries_per_type', 3));
            Config::get()->store('GLOBALSEARCH_MODULES', $config);
    
            PageLayout::postSuccess(_('Die Einstellungen wurden gespeichert.'));
    
            $this->redirect('globalsearch/settings');
        }
    }