3 * Global Search Engine for Moodle
7 * @subpackage search_engine
8 * @author Michael Champanis (mchampan) [cynnical@gmail.com], Valery Fremaux [valery.fremaux@club-internet.fr] > 1.8
10 * @version prepared for 2.0
11 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
13 * General function library
15 * This file must not contain any PHP 5, because it is used to test for PHP 5
16 * itself, and needs to be able to be executed on PHP 4 installations.
23 define('SEARCH_INDEX_PATH', $CFG->dataroot
.'/search');
24 define('SEARCH_DATABASE_TABLE', 'block_search_documents');
27 include_once $CFG->dirroot
.'/search/searchtypes.php';
30 * collects all searchable items identities
31 * @param boolean $namelist if true, only returns list of names of searchable items
32 * @param boolean $verbose if true, prints a discovering status
33 * @return an array of names or an array of type descriptors
35 function search_collect_searchables($namelist=false, $verbose=true){
38 $searchables = array();
39 $searchables_names = array();
41 /// get all installed modules
42 if ($mods = $DB->get_records('modules', null, 'name', 'id,name')){
44 $searchabletypes = array_values(search_get_document_types());
46 foreach($mods as $mod){
47 $plugin = new StdClass();
48 $plugin->name
= $mod->name
;
49 $plugin->type
= 'mod';
50 if (in_array($mod->name
, $searchabletypes)){
51 $plugin->location
= 'internal';
52 $searchables[$plugin->name
] = $plugin;
53 $searchables_names[] = $mod->name
;
55 $documentfile = $CFG->dirroot
."/mod/{$mod->name}/search_document.php";
56 $plugin->location
= 'mod';
57 if (file_exists($documentfile)){
58 $searchables[$plugin->name
] = $plugin;
59 $searchables_names[] = $mod->name
;
63 if ($verbose) mtrace(count($searchables).' modules to search in / '.count($mods).' modules found.');
66 /// collects blocks as indexable information may be found in blocks either
67 if ($blocks = $DB->get_records('block', null, 'name', 'id,name')) {
68 $blocks_searchables = array();
69 // prepend the "block_" prefix to discriminate document type plugins
70 foreach($blocks as $block){
71 $plugin = new StdClass();
72 $plugin->dirname
= $block->name
;
73 $plugin->name
= 'block_'.$block->name
;
74 if (in_array('SEARCH_TYPE_'.strtoupper($block->name
), $searchabletypes)){
75 $plugin->location
= 'internal';
76 $plugin->type
= 'block';
77 $blocks_searchables[$plugin->name
] = $plugin;
78 $searchables_names[] = $plugin->name
;
80 $documentfile = $CFG->dirroot
."/blocks/{$plugin->dirname}/search_document.php";
81 if (file_exists($documentfile)){
82 $plugin->location
= 'blocks';
83 $plugin->type
= 'block';
84 $blocks_searchables[$plugin->name
] = $plugin;
85 $searchables_names[] = $plugin->name
;
89 if ($verbose) mtrace(count($blocks_searchables).' blocks to search in / '.count($blocks).' blocks found.');
90 $searchables = array_merge($searchables, $blocks_searchables);
93 /// add virtual modules onto the back of the array
95 $additional = search_get_additional_modules($searchables_names);
96 if (!empty($additional)){
97 if ($verbose) mtrace(count($additional).' additional to search in.');
98 $searchables = array_merge($searchables, $additional);
102 return $searchables_names;
107 * returns all the document type constants that are known in core implementation
108 * @param prefix a pattern for recognizing constants
109 * @return an array of type labels
111 function search_get_document_types($prefix = 'SEARCH_TYPE_') {
113 foreach (get_defined_constants() as $key => $value) {
114 if (preg_match("/^{$prefix}/", $key)){
123 * additional virtual modules to index
125 * By adding 'moo' to the extras array, an additional document type
126 * documents/moo_document.php will be indexed - this allows for
127 * virtual modules to be added to the index, i.e. non-module specific
130 function search_get_additional_modules(&$searchables_names) {
131 $extras = array(/* additional keywords go here */);
132 if (defined('SEARCH_EXTRAS')){
133 $extras = explode(',', SEARCH_EXTRAS
);
137 $temp = new StdClass
;
138 foreach($extras as $extra) {
139 $plugin = new StdClass();
140 $plugin->name
= $extra;
141 $plugin->location
= 'internal';
142 eval('$plugin->type = TYPE_FOR_SEARCH_TYPE_'.strtoupper($extra).';');
143 $ret[$plugin->name
] = $plugin;
144 $searchables_names[] = $extra;
151 * shortens a url so it can fit on the results page
153 * @param length the size limit we want
155 function search_shorten_url($url, $length=30) {
156 return substr($url, 0, $length)."...";
160 * simple timer function, on first call, records a current microtime stamp, outputs result on 2nd call
161 * @param cli an output formatting switch
164 function search_stopwatch($cli = false) {
165 if (!empty($GLOBALS['search_script_start_time'])) {
166 if (!$cli) print '<em>';
167 print round(microtime(true) - $GLOBALS['search_script_start_time'], 6).' '.get_string('seconds', 'search');
168 if (!$cli) print '</em>';
169 unset($GLOBALS['search_script_start_time']);
171 $GLOBALS['search_script_start_time'] = microtime(true);
176 * print and exit (for debugging)
177 * @param str a variable to explore
180 function search_pexit($str = "") {
181 if (is_array($str) or is_object($str)) {
189 function search_updatedcallback($name) {
191 // set block to hidden when global search is disabled.
192 if ($CFG->enableglobalsearch
!= 1) {
193 $DB->set_field('block', 'visible', 0, array('name'=>'search')); // Hide block