Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / search / documents / resource_document.php
blob844da54bc7abb5cbb530d22c3b507d4e2bbd409e
1 <?php
2 /**
3 * Global Search Engine for Moodle
5 * @package search
6 * @category core
7 * @subpackage document_wrappers
8 * @author Michael Campanis (mchampan) [cynnical@gmail.com], Valery Fremaux [valery.fremaux@club-internet.fr] > 1.8
9 * @date 2008/03/31
10 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
12 * document handling for all resources
13 * This file contains the mapping between a resource and it's indexable counterpart,
15 * Functions for iterating and retrieving the necessary records are now also included
16 * in this file, rather than mod/resource/lib.php
19 /**
20 * requires and includes
22 require_once("$CFG->dirroot/search/documents/document.php");
23 require_once("$CFG->dirroot/mod/resource/lib.php");
25 /* *
26 * a class for representing searchable information
29 class ResourceSearchDocument extends SearchDocument {
30 public function __construct(&$resource, $context_id) {
31 // generic information; required
32 $doc->docid = $resource['trueid'];
33 $doc->documenttype = SEARCH_TYPE_RESOURCE;
34 $doc->itemtype = $resource['type'];
35 $doc->contextid = $context_id;
37 $doc->title = strip_tags($resource['name']);
38 $doc->date = $resource['timemodified'];
39 $doc->author = '';
40 $doc->contents = strip_tags($resource['summary']).' '.strip_tags($resource['alltext']);
41 $doc->url = resource_make_link($resource['id']);
43 // module specific information; optional
44 $data = array();
46 // construct the parent class
47 parent::__construct($doc, $data, $resource['course'], 0, 0, PATH_FOR_SEARCH_TYPE_RESOURCE);
48 } //constructor
49 } //ResourceSearchDocument
51 /**
52 * constructs valid access links to information
53 * @param resourceId the of the resource
54 * @return a full featured link element as a string
56 function resource_make_link($resource_id) {
57 global $CFG;
59 return $CFG->wwwroot.'/mod/resource/view.php?id='.$resource_id;
60 } //resource_make_link
62 /**
63 * part of standard API
66 function resource_iterator() {
67 //trick to leave search indexer functionality intact, but allow
68 //this document to only use the below function to return info
69 //to be searched
70 return array(true);
71 } //resource_iterator
73 /**
74 * part of standard API
75 * this function does not need a content iterator, returns all the info
76 * itself;
77 * @param notneeded to comply API, remember to fake the iterator array though
78 * @uses CFG
79 * @return an array of searchable documents
81 function resource_get_content_for_index(&$notneeded) {
82 global $CFG;
84 // starting with Moodle native resources
85 $documents = array();
86 $query = "
87 SELECT
88 id as trueid,
89 r.*
90 FROM
91 {$CFG->prefix}resource as r
92 WHERE
93 alltext != '' AND
94 alltext != ' ' AND
95 alltext != '&nbsp;' AND
96 type != 'file'
98 $resources = get_records_sql($query);
100 foreach($resources as $aResource){
101 $coursemodule = get_field('modules', 'id', 'name', 'resource');
102 $cm = get_record('course_modules', 'course', $aResource->course, 'module', $coursemodule, 'instance', $aResource->id);
103 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
104 $aResource->id = $cm->id;
105 $documents[] = new ResourceSearchDocument(get_object_vars($aResource), $context->id);
106 mtrace("finished $aResource->name");
109 // special physical files handling
111 * this sequence searches for a compatible physical stream handler for getting a text
112 * equivalence for the content.
115 if (@$CFG->block_search_enable_file_indexing){
116 $query = "
117 SELECT
118 r.id as trueid,
119 cm.id as id,
120 r.course as course,
121 r.name as name,
122 r.summary as summary,
123 r.alltext as alltext,
124 r.reference as reference,
125 r.type as type,
126 r.timemodified as timemodified
127 FROM
128 {$CFG->prefix}resource as r,
129 {$CFG->prefix}course_modules as cm,
130 {$CFG->prefix}modules as m
131 WHERE
132 r.type = 'file' AND
133 cm.instance = r.id AND
134 cm.course = r.course AND
135 cm.module = m.id AND
136 m.name = 'resource'
138 $resources = get_records_sql($query);
140 // invokes external content extractor if exists.
141 if ($resources){
142 foreach($resources as $aResource){
143 // fetches a physical indexable document and adds it to documents passed by ref
144 $coursemodule = get_field('modules', 'id', 'name', 'resource');
145 $cm = get_record('course_modules', 'id', $aResource->id);
146 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
147 resource_get_physical_file($aResource, $context->id, false, $documents);
151 return $documents;
152 } //resource_get_content_for_index
155 * get text from a physical file
156 * @param resource a resource for which to fetch some representative text
157 * @param getsingle if true, returns a single search document, elsewhere return the array
158 * given as documents increased by one
159 * @param documents the array of documents, by ref, where to add the new document.
160 * @return a search document when unique or false.
162 function resource_get_physical_file(&$resource, $context_id, $getsingle, &$documents = null){
163 global $CFG;
165 // cannot index empty references
166 if (empty($resource->reference)){
167 mtrace("Cannot index, empty reference.");
168 return false;
171 // cannot index remote resources
172 if (resource_is_url($resource->reference)){
173 mtrace("Cannot index remote URLs.");
174 return false;
177 $fileparts = pathinfo($resource->reference);
178 // cannot index unknown or masked types
179 if (empty($fileparts['extension'])) {
180 mtrace("Cannot index without explicit extension.");
181 return false;
184 // cannot index non existent file
185 $file = "{$CFG->dataroot}/{$resource->course}/{$resource->reference}";
186 if (!file_exists($file)){
187 mtrace("Missing resource file $file : will not be indexed.");
188 return false;
191 $ext = strtolower($fileparts['extension']);
193 // cannot index unallowed or unhandled types
194 if (!preg_match("/\b$ext\b/i", $CFG->block_search_filetypes)) {
195 mtrace($fileparts['extension'] . ' is not an allowed extension for indexing');
196 return false;
198 if (file_exists($CFG->dirroot.'/search/documents/physical_'.$ext.'.php')){
199 include_once($CFG->dirroot.'/search/documents/physical_'.$ext.'.php');
200 $function_name = 'get_text_for_indexing_'.$ext;
201 $resource->alltext = $function_name($resource);
202 if (!empty($resource->alltext)){
203 if ($getsingle){
204 $single = new ResourceSearchDocument(get_object_vars($resource), $context_id);
205 mtrace("finished file $resource->name as {$resource->reference}");
206 return $single;
207 } else {
208 $documents[] = new ResourceSearchDocument(get_object_vars($resource), $context_id);
210 mtrace("finished file $resource->name as {$resource->reference}");
212 } else {
213 mtrace("fulltext handler not found for $ext type");
215 return false;
219 * part of standard API.
220 * returns a single resource search document based on a resource_entry id
221 * @param id the id of the accessible document
222 * @return a searchable object or null if failure
224 function resource_single_document($id, $itemtype) {
225 global $CFG;
227 // rewriting with legacy moodle databse API
228 $query = "
229 SELECT
230 r.id as trueid,
231 cm.id as id,
232 r.course as course,
233 r.name as name,
234 r.summary as summary,
235 r.alltext as alltext,
236 r.reference as reference,
237 r.type as type,
238 r.timemodified as timemodified
239 FROM
240 {$CFG->prefix}resource as r,
241 {$CFG->prefix}course_modules as cm,
242 {$CFG->prefix}modules as m
243 WHERE
244 cm.instance = r.id AND
245 cm.course = r.course AND
246 cm.module = m.id AND
247 m.name = 'resource' AND
248 ((r.type != 'file' AND
249 r.alltext != '' AND
250 r.alltext != ' ' AND
251 r.alltext != '&nbsp;') OR
252 r.type = 'file') AND
253 r.id = '{$id}'
255 $resource = get_record_sql($query);
257 if ($resource){
258 $coursemodule = get_field('modules', 'id', 'name', 'resource');
259 $cm = get_record('course_modules', 'id', $resource->id);
260 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
261 if ($resource->type == 'file' && @$CFG->block_search_enable_file_indexing){
262 $document = resource_get_physical_file($resource, true, $context->id);
263 if (!$document) mtrace("Warning : this document {$resource->name} will not be indexed");
264 return $document;
265 } else {
266 return new ResourceSearchDocument(get_object_vars($resource), $context->id);
269 mtrace("null resource");
270 return null;
271 } //resource_single_document
274 * dummy delete function that aggregates id with itemtype.
275 * this was here for a reason, but I can't remember it at the moment.
278 function resource_delete($info, $itemtype) {
279 $object->id = $info;
280 $object->itemtype = $itemtype;
281 return $object;
282 } //resource_delete
285 * returns the var names needed to build a sql query for addition/deletions
288 function resource_db_names() {
289 //[primary id], [table name], [time created field name], [time modified field name], [additional where conditions for sql]
290 return array(array('id', 'resource', 'timemodified', 'timemodified', 'any', " (alltext != '' AND alltext != ' ' AND alltext != '&nbsp;' AND TYPE != 'file') OR TYPE = 'file' "));
291 } //resource_db_names
294 * this function handles the access policy to contents indexed as searchable documents. If this
295 * function does not exist, the search engine assumes access is allowed.
296 * @param path the access path to the module script code
297 * @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
298 * @param this_id the item id within the information class denoted by itemtype. In resources, this id
299 * points to the resource record and not to the module that shows it.
300 * @param user the user record denoting the user who searches
301 * @param group_id the current group used by the user when searching
302 * @return true if access is allowed, false elsewhere
304 function resource_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
305 global $CFG;
307 include_once("{$CFG->dirroot}/{$path}/lib.php");
309 $r = get_record('resource', 'id', $this_id);
310 $module_context = get_record('context', 'id', $context_id);
311 $cm = get_record('course_modules', 'id', $module_context->instanceid);
313 //check if found course module is visible
314 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $module_context)){
315 return false;
318 return true;
322 * post processes the url for cleaner output.
323 * @param string $title
325 function resource_link_post_processing($title){
326 return mb_convert_encoding($title, 'UTF-8', 'auto');