MDL-10680:
[moodle-linuxchix.git] / search / documents / resource_document.php
blob3bc782b0f29e4042581d1edd086936d1163b8191
1 <?php
2 /**
3 * Global Search Engine for Moodle
4 * Michael Champanis (mchampan) [cynnical@gmail.com]
5 * review 1.8+ : Valery Fremaux [valery.fremaux@club-internet.fr]
6 * 2007/08/02
8 * document handling for all resources
9 * This file contains the mapping between a resource and it's indexable counterpart,
11 * Functions for iterating and retrieving the necessary records are now also included
12 * in this file, rather than mod/resource/lib.php
13 **/
15 require_once("$CFG->dirroot/search/documents/document.php");
16 require_once("$CFG->dirroot/mod/resource/lib.php");
18 /*
19 * a class for representing searchable information
21 **/
22 class ResourceSearchDocument extends SearchDocument {
23 public function __construct(&$resource, $context_id) {
24 // generic information; required
25 $doc->docid = $resource['trueid'];
26 $doc->documenttype = SEARCH_TYPE_RESOURCE;
27 $doc->itemtype = $resource['type'];
28 $doc->contextid = $context_id;
30 $doc->title = strip_tags($resource['name']);
31 $doc->date = $resource['timemodified'];
32 $doc->author = '';
33 $doc->contents = strip_tags($resource['summary']).' '.strip_tags($resource['alltext']);
34 $doc->url = resource_make_link($resource['id']);
36 // module specific information; optional
37 $data = array();
39 // construct the parent class
40 parent::__construct($doc, $data, $resource['course'], 0, 0, PATH_FOR_SEARCH_TYPE_RESOURCE);
41 } //constructor
42 } //ResourceSearchDocument
44 /**
45 * constructs valid access links to information
46 * @param resourceId the of the resource
47 * @return a full featured link element as a string
49 function resource_make_link($resource_id) {
50 global $CFG;
52 return $CFG->wwwroot.'/mod/resource/view.php?id='.$resource_id;
53 } //resource_make_link
55 /**
56 * part of standard API
59 function resource_iterator() {
60 //trick to leave search indexer functionality intact, but allow
61 //this document to only use the below function to return info
62 //to be searched
63 return array(true);
64 } //resource_iterator
66 /**
67 * part of standard API
68 * this function does not need a content iterator, returns all the info
69 * itself;
70 * @param notneeded to comply API, remember to fake the iterator array though
71 * @return an array of searchable documents
73 function resource_get_content_for_index(&$notneeded) {
74 global $CFG;
76 // starting with Moodle native resources
77 $documents = array();
78 $query = "
79 SELECT
80 id as trueid,
81 r.*
82 FROM
83 {$CFG->prefix}resource as r
84 WHERE
85 alltext != '' AND
86 alltext != ' ' AND
87 alltext != '&nbsp;' AND
88 type != 'file'
90 $resources = get_records_sql($query);
92 foreach($resources as $aResource){
93 $coursemodule = get_field('modules', 'id', 'name', 'resource');
94 $cm = get_record('course_modules', 'course', $aResource->course, 'module', $coursemodule, 'instance', $aResource->id);
95 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
96 $aResource->id = $cm->id;
97 $documents[] = new ResourceSearchDocument(get_object_vars($aResource), $context->id);
98 mtrace("finished $aResource->name");
101 // special physical files handling
103 * this sequence searches for a compatible physical stream handler for getting a text
104 * equivalence for the content.
107 if (@$CFG->block_search_enable_file_indexing){
108 $query = "
109 SELECT
110 r.id as trueid,
111 cm.id as id,
112 r.course as course,
113 r.name as name,
114 r.summary as summary,
115 r.alltext as alltext,
116 r.reference as reference,
117 r.type as type,
118 r.timemodified as timemodified
119 FROM
120 {$CFG->prefix}resource as r,
121 {$CFG->prefix}course_modules as cm,
122 {$CFG->prefix}modules as m
123 WHERE
124 r.type = 'file' AND
125 cm.instance = r.id AND
126 cm.course = r.course AND
127 cm.module = m.id AND
128 m.name = 'resource'
130 $resources = get_records_sql($query);
132 // invokes external content extractor if exists.
133 foreach($resources as $aResource){
134 // fetches a physical indexable document and adds it to documents passed by ref
135 $coursemodule = get_field('modules', 'id', 'name', 'resource');
136 $cm = get_record('course_modules', 'id', $aResource->id);
137 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
138 resource_get_physical_file($aResource, $context->id, false, $documents);
141 return $documents;
142 } //resource_get_content_for_index
145 * get text from a physical file
146 * @param resource a resource for which to fetch some representative text
147 * @param getsingle if true, returns a single search document, elsewhere return the array
148 * given as documents increased by one
149 * @param documents the array of documents, by ref, where to add the new document.
150 * @return a search document when unique or false.
152 function resource_get_physical_file(&$resource, $context_id, $getsingle, &$documents = null){
153 global $CFG;
155 // cannot index empty references
156 if (empty($resource->reference)) return false;
158 // cannot index remote resources
159 if (resource_is_url($resource->reference)){
160 mtrace("Cannot index remote URLs.");
161 return false;
164 $fileparts = pathinfo($resource->reference);
165 // cannot index unknown or masked types
166 if (empty($fileparts['extension'])) {
167 return false;
170 // cannot index non existent file
171 $file = "{$CFG->dataroot}/{$resource->course}/{$resource->reference}";
172 if (!file_exists($file)){
173 mtrace("Missing resource file $file : will not be indexed.");
174 return false;
177 $ext = strtolower($fileparts['extension']);
179 // cannot index unallowed or unhandled types
180 if (!preg_match("/\b$ext\b/i", $CFG->block_search_filetypes)) {
181 mtrace($fileparts['extension'] . ' is not an allowed extension for indexing');
182 return false;
184 if (file_exists($CFG->dirroot.'/search/documents/physical_'.$ext.'.php')){
185 include_once($CFG->dirroot.'/search/documents/physical_'.$ext.'.php');
186 $function_name = 'get_text_for_indexing_'.$ext;
187 $resource->alltext = $function_name($resource);
188 if (!empty($resource->alltext)){
189 if ($getsingle){
190 return new ResourceSearchDocument(get_object_vars($resource));
192 else{
193 $documents[] = new ResourceSearchDocument(get_object_vars($resource), $context_id);
195 mtrace("finished file $resource->name as {$resource->reference}");
198 else{
199 mtrace("fulltext handler not found for $ext type");
201 return false;
205 * part of standard API.
206 * returns a single resource search document based on a resource_entry id
207 * @param id the id of the accessible document
208 * @return a searchable object or null if failure
210 function resource_single_document($id, $itemtype) {
211 global $CFG;
213 // rewriting with legacy moodle databse API
214 $query = "
215 SELECT
216 r.id as trueid,
217 cm.id as id,
218 r.course as course,
219 r.name as name,
220 r.summary as summary,
221 r.alltext as alltext,
222 r.reference as reference,
223 r.type as type,
224 r.timemodified as timemodified
225 FROM
226 {$CFG->prefix}resource as r,
227 {$CFG->prefix}course_modules as cm,
228 {$CFG->prefix}modules as m
229 WHERE
230 cm.instance = r.id AND
231 cm.course = r.course AND
232 cm.module = m.id AND
233 m.name = 'resource' AND
234 ((r.type != 'file' AND
235 r.alltext != '' AND
236 r.alltext != ' ' AND
237 r.alltext != '&nbsp;') OR
238 r.type = 'file') AND
239 r.id = '{$id}'
241 $resource = get_record_sql($query);
243 if ($resource){
244 $coursemodule = get_field('modules', 'id', 'name', 'resource');
245 $cm = get_record('course_modules', 'id', $resource->id);
246 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
247 if ($resource->type == 'file' && @$CFG->block_search_enable_file_indexing){
248 $document = resource_get_physical_file($resource, true, $context->id);
249 if (!$document) mtrace("Warning : this document {$resource->name} will not be indexed");
250 return $document;
252 else{
253 return new ResourceSearchDocument(get_object_vars($resource), $context->id);
256 mtrace("null resource");
257 return null;
258 } //resource_single_document
261 * dummy delete function that aggregates id with itemtype.
262 * this was here for a reason, but I can't remember it at the moment.
265 function resource_delete($info, $itemtype) {
266 $object->id = $info;
267 $object->itemtype = $itemtype;
268 return $object;
269 } //resource_delete
272 * returns the var names needed to build a sql query for addition/deletions
275 function resource_db_names() {
276 //[primary id], [table name], [time created field name], [time modified field name], [additional where conditions for sql]
277 return array(array('id', 'resource', 'timemodified', 'timemodified', '*', " (alltext != '' AND alltext != ' ' AND alltext != '&nbsp;' AND TYPE != 'file') OR TYPE = 'file' "));
278 } //resource_db_names
281 * this function handles the access policy to contents indexed as searchable documents. If this
282 * function does not exist, the search engine assumes access is allowed.
283 * @param path the access path to the module script code
284 * @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
285 * @param this_id the item id within the information class denoted by itemtype. In resources, this id
286 * points to the resource record and not to the module that shows it.
287 * @param user the user record denoting the user who searches
288 * @param group_id the current group used by the user when searching
289 * @return true if access is allowed, false elsewhere
291 function resource_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
292 global $CFG;
294 include_once("{$CFG->dirroot}/{$path}/lib.php");
296 $r = get_record('resource', 'id', $this_id);
297 $module_context = get_record('context', 'id', $context_id);
298 $cm = get_record('course_modules', 'id', $module_context->instance);
300 //check if found course module is visible
301 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $module_context)){
302 return false;
305 return true;
306 } //resource_check_text_access