MDL-12234, fixing unicode issues with global search
[moodle.git] / search / indexlib.php
1 <?php
2 /* 
3 * Author: Michael Champanis
4 *
5 * Reviewed by: Valery Fremaux (2007)
6
7 * Index info class
8 *
9 * Used to retrieve information about an index.
10 * Has methods to check for valid database and data directory,
11 * and the index itself.
12 **/
14 require_once("$CFG->dirroot/search/lib.php");
15 require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
17 class IndexInfo {
18     private $path,        //index data directory
19             $size,        //size of directory (i.e. the whole index)
20             $filecount,   //number of files
21             $indexcount,  //number of docs in index
22             $dbcount,     //number of docs in db
23             $types,       //array of [document types => count]
24             $complete,    //is index completely formed?
25             $time;        //date index was generated
26     
27     public function __construct($path = SEARCH_INDEX_PATH) {
28         global $CFG, $db;
29         
30         $this->path = $path;
31         
32         //test to see if there is a valid index on disk, at the specified path
33         try {
34             $test_index = new Zend_Search_Lucene($this->path, false);
35             $validindex = true;
36         } catch(Exception $e) {
37             $validindex = false;
38         } //catch
39         
40         //retrieve file system info about the index if it is valid
41         if ($validindex) {
42             $this->size = display_size(get_directory_size($this->path));
43             $index_dir  = get_directory_list($this->path, '', false, false);
44             $this->filecount = count($index_dir);
45             $this->indexcount = $test_index->count();
46         } 
47         else {
48             $this->size = 0;
49             $this->filecount = 0;
50             $this->indexcount = 0;
51         } 
52         
53         $db_exists = false; //for now
54         
55         //get all the current tables in moodle
56         $admin_tables = $db->MetaTables();
57         
58         //TODO: use new IndexDBControl class for database checks?
59         
60         //check if our search table exists
61         if (in_array($CFG->prefix.SEARCH_DATABASE_TABLE, $admin_tables)) {
62             //retrieve database information if it does
63             $db_exists = true;
64             
65             //total documents
66             $this->dbcount = count_records(SEARCH_DATABASE_TABLE);
67             
68             //individual document types
69             $types = search_get_document_types();
70             sort($types);
71             
72             foreach($types as $type) {
73                 $c = count_records(SEARCH_DATABASE_TABLE, 'doctype', $type);
74                 $this->types[$type] = (int)$c;
75             }
76         } 
77         else {
78             $this->dbcount = 0;
79             $this->types = array();
80         }
81         
82         //check if the busy flag is set
83         if (isset($CFG->search_indexer_busy) && $CFG->search_indexer_busy == '1') {
84             $this->complete = false;
85         } 
86         else {
87             $this->complete = true;
88         }
89         
90         //get the last run date for the indexer
91         if ($this->valid() && $CFG->search_indexer_run_date) {
92             $this->time = $CFG->search_indexer_run_date;
93         } 
94         else {
95           $this->time = 0;
96         }
97     } //__construct
98     
99     /**
100     * returns false on error, and the error message via referenced variable $err
101     *
102     */
103     public function valid(&$err = null) {
104         $err = array();
105         $ret = true;
106         
107         if (!$this->is_valid_dir()) {
108             $err['dir'] = get_string('invalidindexerror', 'search');
109             $ret = false;
110         }
111         
112         if (!$this->is_valid_db()) {
113             $err['db'] = get_string('emptydatabaseerror', 'search');
114             $ret = false;
115         }
116         
117         if (!$this->complete) {
118             $err['index'] = get_string('uncompleteindexingerror','search');
119             $ret = false;
120         }
121         
122         return $ret;
123     } //valid
124     
125     /**
126     * is the index dir valid
127     *
128     */
129     public function is_valid_dir() {
130         if ($this->filecount > 0) {
131             return true;
132         } 
133         else {
134             return false;
135         }
136     } //is_valid_dir
137     
138     /**
139     * is the db table valid
140     *
141     */
142     public function is_valid_db() {
143         if ($this->dbcount > 0) {
144             return true;
145         } 
146         else {
147             return false;
148         }
149     } //is_valid_db
150     
151     /**
152     * shorthand get method for the class variables
153     *
154     */
155     public function __get($var) {
156         if (in_array($var, array_keys(get_class_vars(get_class($this))))) {
157             return $this->$var;
158         }
159     } //__get
160 } //IndexInfo
163 /* 
164 * DB Index control class
166 * Used to control the search index database table
167 **/
168 class IndexDBControl {
170     /**
171     * does the table exist?
172     * OBSOLETE
173     */
174     public function checkTableExists() {
175         global $CFG, $db;
176         
177         $table = SEARCH_DATABASE_TABLE;
178         $tables = $db->MetaTables();
179         if (in_array($CFG->prefix.$table, $tables)) {
180             return true;
181         } 
182         else {
183             return false;
184         }
185     } //checkTableExists
187     /**
188     * is our database setup valid?
189     * OBSOLETE - Database is installed at install and should not be dropped out
190     */
191     public function checkDB() {
192         global $CFG, $db;
193         
194         $sqlfile = "{$CFG->dirroot}/search/db/$CFG->dbtype.sql";
195         $ret = false;
196         if ($this->checkTableExists()) {
197             execute_sql('drop table '.$CFG->prefix.SEARCH_DATABASE_TABLE, false);
198         }
200         //turn output buffering on - to hide modify_database() output
201         ob_start(); 
202         $ret = modify_database($sqlfile, '', false);
204         //chuck the buffer and resume normal operation
205         ob_end_clean(); 
206         return $ret;
207     } //checkDB
209     /**
210     * add a document record to the table
211     * @param document must be a Lucene SearchDocument instance
212     */
213     public function addDocument($document=null) {
214         global $db, $CFG;
215         
216         if ($document == null) {
217              return false;
218         }
219                 
220         // object to insert into db
221         $doc->doctype   = $document->doctype;
222         $doc->docid     = $document->docid;
223         $doc->itemtype  = $document->itemtype;
224         $doc->title     = search_escape_string($document->title);
225         $doc->url       = search_escape_string($document->url);
226         $doc->update    = time();
227         $doc->docdate   = $document->date;
228         $doc->courseid  = $document->course_id;
229         $doc->groupid   = $document->group_id;
230         
231         //insert summary into db
232         $id = insert_record(SEARCH_DATABASE_TABLE, $doc);
233         
234         return $id;
235     } //addDocument
237     /**
238     * remove a document record from the index
239     * @param document must be a Lucene document instance, or at least a dbid enveloppe
240     */
241     public function delDocument($document) {
242         global $db;
243         
244         delete_records(SEARCH_DATABASE_TABLE, 'id', $document->dbid);
245     } //delDocument
246 } //IndexControl
248 ?>