Automatic installer.php lang files by installer_builder (20070726)
[moodle-linuxchix.git] / search / documents / data_document.php
blobafb52901fef9470e758b5fdf96fc52e8a056d035
1 <?php
2 /**
3 * Global Search Engine for Moodle
4 * add-on 1.8+ : Valery Fremaux [valery.fremaux@club-internet.fr]
5 * 2007/08/02
7 * document handling for data activity module
8 * This file contains the mapping between a database object and it's indexable counterpart,
10 * Functions for iterating and retrieving the necessary records are now also included
11 * in this file, rather than mod/data/lib.php
12 **/
14 require_once("$CFG->dirroot/search/documents/document.php");
15 require_once("$CFG->dirroot/mod/data/lib.php");
17 /*
18 * a class for representing searchable information (data records)
20 **/
21 class DataSearchDocument extends SearchDocument {
23 /**
24 * constructor
27 public function __construct(&$record, $course_id, $context_id) {
28 // generic information; required
29 $doc->docid = $record['id'];
30 $doc->documenttype = SEARCH_TYPE_DATA;
31 $doc->itemtype = 'record';
32 $doc->contextid = $context_id;
34 $doc->title = $record['title'];
35 $doc->date = $record['timemodified'];
36 //remove '(ip.ip.ip.ip)' from data record author field
37 if ($record['userid']){
38 $user = get_record('user', 'id', $record['userid']);
40 $doc->author = (isset($user)) ? $user->firstname.' '.$user->lastname : '' ;
41 $doc->contents = $record['content'];
42 $doc->url = data_make_link($record['dataid'], $record['id']);
44 // module specific information; optional
45 // $data->params = serialize(@$record['params']); may be useful
46 $data->database = $record['dataid'];
48 // construct the parent class
49 parent::__construct($doc, $data, $course_id, $record['groupid'], $record['userid'], PATH_FOR_SEARCH_TYPE_DATA);
50 } //constructor
51 } //ChatSearchDocument
53 /*
54 * a class for representing searchable information (comments on data records)
56 **/
57 class DataCommentSearchDocument extends SearchDocument {
59 /**
60 * constructor
63 public function __construct(&$comment, $course_id, $context_id) {
64 // generic information; required
65 $doc->docid = $comment['id'];
66 $doc->documenttype = SEARCH_TYPE_DATA;
67 $doc->itemtype = 'comment';
68 $doc->contextid = $context_id;
70 $doc->title = get_string('commenton', 'search').' '.$comment['title'];
71 $doc->date = $comment['modified'];
72 //remove '(ip.ip.ip.ip)' from data record author field
73 $doc->author = preg_replace('/\(.*?\)/', '', $comment['author']);
74 $doc->contents = $comment['content'];
75 $doc->url = data_make_link($data_id, $comment['recordid']);
77 // module specific information; optional
78 $data->database = $comment['dataid'];
80 // construct the parent class
81 parent::__construct($doc, $data, $course_id, $comment['groupid'], $comment['userid'], PATH_FOR_SEARCH_TYPE_DATA);
82 } //constructor
83 } //ChatCommentSearchDocument
85 /**
86 * constructs a valid link to a data record content
87 * @param database_id the database reference
88 * @param record_id the record reference
89 * @return a valid url top access the information as a string
91 function data_make_link($database_id, $record_id) {
92 global $CFG;
94 return $CFG->wwwroot.'/mod/data/view.php?d='.$database_id.'&amp;rid='.$record_id;
95 } //data_make_link
97 /**
98 * fetches all the records for a given database
99 * @param database_id the database
100 * @param typematch a comma separated list of types that should be considered for searching or *
101 * @return an array of objects representing the data records.
103 function data_get_records($database_id, $typematch = '*') {
104 global $CFG;
106 $fieldset = get_records('data_fields', 'dataid', $database_id);
107 $query = "
108 SELECT
110 FROM
111 {$CFG->prefix}data_content as c,
112 {$CFG->prefix}data_records as r
113 WHERE
114 c.recordid = r.id AND
115 r.dataid = {$database_id}
116 ORDER BY
117 c.fieldid
119 $data = get_records_sql($query);
120 $records = array();
121 if ($data){
122 foreach($data as $aDatum){
123 if($typematch == '*' || preg_match("/\\b{$fieldset[$aDatum->fieldid]->type}\\b/", $typematch)){
124 if (!isset($records[$aDatum->recordid])){
125 $records[$aDatum->recordid]['_first'] = $aDatum->content.' '.$aDatum->content1.' '.$aDatum->content2.' '.$aDatum->content3.' '.$aDatum->content4.' ';
127 else{
128 $records[$aDatum->recordid][$fieldset[$aDatum->fieldid]->name] = $aDatum->content.' '.$aDatum->content1.' '.$aDatum->content2.' '.$aDatum->content3.' '.$aDatum->content4.' ';
133 return $records;
134 } //data_get_records
137 * fetches all the comments for a given database
138 * @param database_id the database
139 * @return an array of objects representing the data record comments.
141 function data_get_comments($database_id) {
142 global $CFG;
144 $query = "
145 SELECT
146 c.id,
147 r.groupid,
148 c.userid,
149 c.recordid,
150 c.content,
151 c.created,
152 c.modified,
153 r.dataid
154 FROM
155 {$CFG->prefix}data_comments as c,
156 {$CFG->prefix}data_records as r
157 WHERE
158 c.recordid = r.id
160 $comments = get_records_sql($query);
161 return $comments;
162 } //data_get_comments
166 * part of search engine API
169 function data_iterator() {
170 $databases = get_records('data');
171 return $databases;
172 } //data_iterator
175 * part of search engine API
176 * @param database the database instance
177 * @return an array of searchable documents
179 function data_get_content_for_index(&$database) {
181 $documents = array();
182 $recordTitles = array();
183 $coursemodule = get_field('modules', 'id', 'name', 'data');
184 $cm = get_record('course_modules', 'course', $database->course, 'module', $coursemodule, 'instance', $database->id);
185 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
187 // getting records for indexing
188 $records_content = data_get_records($database->id, 'text');
189 if ($records_content){
190 foreach(array_keys($records_content) as $aRecordId) {
192 // extract title as first record in order
193 $first = $records_content[$aRecordId]['_first'];
194 unset($records_content[$aRecordId]['_first']);
196 // concatenates all other texts
197 foreach($records_content[$aRecordId] as $aField){
198 $content = @$content.' '.$aField;
200 if (strlen($content) > 0) {
201 unset($recordMetaData);
202 $recordMetaData = get_record('data_records', 'id', $aRecordId);
203 $recordMetaData->title = $first;
204 $recordTitles[$aRecordId] = $first;
205 $recordMetaData->content = $content;
206 $documents[] = new DataSearchDocument(get_object_vars($recordMetaData), $database->course, $context->id);
211 // getting comments for indexing
212 $records_comments = data_get_comments($database->id);
213 if ($records_comments){
214 foreach($records_comments as $aComment){
215 $aComment->title = $recordsTitle[$aComment->recordid];
216 $documents[] = new DataCommentSearchDocument(get_object_vars($aComment), $database->course, $context->id);
219 return $documents;
220 } //data_get_content_for_index
223 * returns a single data search document based on a data entry id
224 * @param id the id of the record
225 * @param the type of the information
226 * @return a single searchable document
228 function data_single_document($id, $itemtype) {
230 if ($itemtype == 'record'){
231 // get main record
232 $recordMetaData = get_record('data_records', 'id', $id);
233 // get context
234 $record_course = get_field('data', 'course', 'id', $recordMetaData->dataid);
235 $coursemodule = get_field('modules', 'id', 'name', 'data');
236 $cm = get_record('course_modules', 'course', $record_course, 'module', $coursemodule, 'instance', $recordMetaData->dataid);
237 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
238 // compute text
239 $recordData = get_records_select('data_content', "recordid = $id AND type = 'text'", 'recordid');
240 $accumulator = '';
241 if ($recordData){
242 $first = $recordData[0];
243 if (count($recordData) > 1){
244 $others = array_splice($recordData, 0, 1);
245 foreach($others as $aDatum){
246 $accumulator .= $data->content.' '.$data->content1.' '.$data->content2.' '.$data->content3.' '.$data->content4.' ';
250 // add extra fields
251 $recordMetaData->title = $first;
252 $recordMetaData->content = $accumulator;
253 // make document
254 $documents[] = new DataSearchDocument(get_object_vars($recordMetaData), $record_course, $context->id);
256 elseif($itemtype == 'comment'){
257 // get main records
258 $comment = get_record('data_comments', 'id', $id);
259 $record = get_record('data_records', 'id', $comment->recordid);
260 // get context
261 $record_course = get_field('data', 'course', 'id', $record->dataid);
262 $coursemodule = get_field('modules', 'id', 'name', 'data');
263 $cm = get_record('course_modules', 'course', $record_course, 'module', $coursemodule, 'instance', $recordMetaData->dataid);
264 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
265 // add extra fields
266 $comment->title = get_field('search_document', 'title', 'docid', $record->id, 'itemtype', 'record');
267 $comment->dataid = $record->dataid;
268 $comment->groupid = $record->groupid;
269 // make document
270 $documents[] = new DataCommentSearchDocument(get_object_vars($comment), $record_course, $context->id);
272 else{
273 mtrace('Error : bad or missing item type');
275 } //data_single_document
278 * dummy delete function that packs id with itemtype.
279 * this was here for a reason, but I can't remember it at the moment.
282 function data_delete($info, $itemtype) {
283 $object->id = $info;
284 $object->itemtype = $itemtype;
285 return $object;
286 } //data_delete
289 * returns the var names needed to build a sql query for addition/deletions
292 function data_db_names() {
293 //[primary id], [table name], [time created field name], [time modified field name]
294 return array(
295 array('id', 'data_records', 'timecreated', 'timemodified', 'record'),
296 array('id', 'data_comments', 'created', 'modified', 'comment')
298 } //data_db_names
301 * this function handles the access policy to contents indexed as searchable documents. If this
302 * function does not exist, the search engine assumes access is allowed.
303 * When this point is reached, we already know that :
304 * - user is legitimate in the surrounding context
305 * - user may be guest and guest access is allowed to the module
306 * - the function may perform local checks within the module information logic
307 * @param path the access path to the module script code
308 * @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
309 * @param this_id the item id within the information class denoted by itemtype. In databases, this id
310 * points out an indexed data record page.
311 * @param user the user record denoting the user who searches
312 * @param group_id the current group used by the user when searching
313 * @return true if access is allowed, false elsewhere
315 function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
316 global $CFG;
318 // get the database object and all related stuff
319 if ($itemtype == 'record'){
320 $record = get_record('data_records', 'id', $this_id);
322 elseif($itemtype == 'comment'){
323 $comment = get_record('data_comments', 'id', $this_id);
324 $record = get_record('data_records', 'id', $comment->recordid);
326 else{
327 // we do not know what type of information is required
328 return false;
330 $data = get_record('data', 'id', $record->dataid);
331 $course = get_record('course', 'id', $data->course);
332 $module_context = get_record('context', 'id', $context_id);
333 $cm = get_record('course_modules', 'id', $module_context->instance);
334 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $module_context)) return false;
336 //group consistency check : checks the following situations about groups
337 // trap if user is not same group and groups are separated
338 $current_group = get_current_group($course->id);
339 if ((groupmode($course) == SEPARATEGROUPS) && !ismember($group_id) && !has_capability('moodle/site:accessallgroups', $module_context)) return false;
341 //ownership check : checks the following situations about user
342 // trap if user is not owner and has cannot see other's entries
343 if ($itemtype == 'record'){
344 if ($user->id != $record->userid && !has_capability('mod/data:viewentry', $module_context) && !has_capability('mod/data:manageentries', $module_context)) return false;
347 //approval check
348 // trap if unapproved and has not approval capabilities
349 // TODO : report a potential capability lack of : mod/data:approve
350 $approval = get_field('data_records', 'approved', 'id', $record->id);
351 if (!$approval && !isteacher($data->course) && !has_capability('mod/data:manageentries', $module_context)) return false;
353 //minimum records to view check
354 // trap if too few records
355 // TODO : report a potential capability lack of : mod/data:viewhiddenentries
356 $recordsAmount = count_records('data_records', 'dataid', $data->id);
357 if ($data->requiredentriestoview > $recordsAmount && !isteacher($data->course) && !has_capability('mod/data:manageentries', $module_context)) return false;
359 //opening periods check
360 // trap if user has not capability to see hidden records and date is out of opening range
361 // TODO : report a potential capability lack of : mod/data:viewhiddenentries
362 $now = usertime(time());
363 if ($data->timeviewfrom > 0)
364 if ($now < $data->timeviewfrom && !isteacher($data->course) && !has_capability('mod/data:manageentries', $module_context)) return false;
365 if ($data->timeviewto > 0)
366 if ($now > $data->timeviewto && !isteacher($data->course) && !has_capability('mod/data:manageentries', $module_context)) return false;
368 return true;
369 } // data_check_text_access