MDL-54844 mod_glossary: Limiting of glossary searching.
[moodle.git] / mod / glossary / lib.php
CommitLineData
e121db76 1<?php
07842023 2
e121db76 3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Library of functions and constants for module glossary
20 * (replace glossary with the name of your module and delete this line)
21 *
d01fb561 22 * @package mod_glossary
e121db76 23 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
dde5bfbc 26require_once($CFG->libdir . '/completionlib.php');
214b1cf7 27
7dd88447 28define("GLOSSARY_SHOW_ALL_CATEGORIES", 0);
29define("GLOSSARY_SHOW_NOT_CATEGORISED", -1);
c76e673a 30
1ac87c73 31define("GLOSSARY_NO_VIEW", -1);
7dd88447 32define("GLOSSARY_STANDARD_VIEW", 0);
33define("GLOSSARY_CATEGORY_VIEW", 1);
c197e607 34define("GLOSSARY_DATE_VIEW", 2);
1ac87c73 35define("GLOSSARY_AUTHOR_VIEW", 3);
36define("GLOSSARY_ADDENTRY_VIEW", 4);
37define("GLOSSARY_IMPORT_VIEW", 5);
38define("GLOSSARY_EXPORT_VIEW", 6);
39define("GLOSSARY_APPROVAL_VIEW", 7);
fb443f1a 40
223d6cb3
NS
41// Glossary tabs.
42define('GLOSSARY_STANDARD', 'standard');
43define('GLOSSARY_AUTHOR', 'author');
44define('GLOSSARY_CATEGORY', 'category');
45define('GLOSSARY_DATE', 'date');
46
47// Glossary displayformats.
48define('GLOSSARY_CONTINUOUS', 'continuous');
49define('GLOSSARY_DICTIONARY', 'dictionary');
50define('GLOSSARY_FULLWITHOUTAUTHOR', 'fullwithoutauthor');
51
da9c60ec 52/// STANDARD FUNCTIONS ///////////////////////////////////////////////////////////
e121db76 53/**
54 * @global object
55 * @param object $glossary
56 * @return int
57 */
07842023 58function glossary_add_instance($glossary) {
c18269c7 59 global $DB;
07842023 60/// Given an object containing all the necessary data,
7cac0c4b 61/// (defined by the form in mod_form.php) this function
07842023 62/// will create a new instance and return the id number
63/// of the new instance.
64
e6d45048 65 if (empty($glossary->ratingtime) or empty($glossary->assessed)) {
63dd5fb2 66 $glossary->assesstimestart = 0;
67 $glossary->assesstimefinish = 0;
68 }
69
63e21b9b 70 if (empty($glossary->globalglossary) ) {
0de786f7 71 $glossary->globalglossary = 0;
63e21b9b 72 }
73
e0a91e11 74 if (!has_capability('mod/glossary:manageentries', context_system::instance())) {
0de786f7 75 $glossary->globalglossary = 0;
76 }
77
e6d45048 78 $glossary->timecreated = time();
07842023 79 $glossary->timemodified = $glossary->timecreated;
80
ff424012 81 //Check displayformat is a valid one
82 $formats = get_list_of_plugins('mod/glossary/formats','TEMPLATE');
83 if (!in_array($glossary->displayformat, $formats)) {
5973a4c4 84 print_error('unknowformat', '', '', $glossary->displayformat);
a02c77dc 85 }
24c1be88 86
2a7eff41 87 $returnid = $DB->insert_record("glossary", $glossary);
88 $glossary->id = $returnid;
89 glossary_grade_item_update($glossary);
e6d45048 90
91 return $returnid;
07842023 92}
93
e121db76 94/**
95 * Given an object containing all the necessary data,
96 * (defined by the form in mod_form.php) this function
97 * will update an existing instance with new data.
98 *
99 * @global object
100 * @global object
101 * @param object $glossary
102 * @return bool
103 */
07842023 104function glossary_update_instance($glossary) {
c18269c7 105 global $CFG, $DB;
a02c77dc 106
da5754f8 107 if (empty($glossary->globalglossary)) {
108 $glossary->globalglossary = 0;
109 }
0de786f7 110
e0a91e11 111 if (!has_capability('mod/glossary:manageentries', context_system::instance())) {
63e21b9b 112 // keep previous
113 unset($glossary->globalglossary);
114 }
115
07842023 116 $glossary->timemodified = time();
e6d45048 117 $glossary->id = $glossary->instance;
07842023 118
e6d45048 119 if (empty($glossary->ratingtime) or empty($glossary->assessed)) {
63dd5fb2 120 $glossary->assesstimestart = 0;
121 $glossary->assesstimefinish = 0;
122 }
123
ff424012 124 //Check displayformat is a valid one
125 $formats = get_list_of_plugins('mod/glossary/formats','TEMPLATE');
126 if (!in_array($glossary->displayformat, $formats)) {
5973a4c4 127 print_error('unknowformat', '', '', $glossary->displayformat);
ff424012 128 }
129
dd88de0e 130 $DB->update_record("glossary", $glossary);
2a7eff41 131 if ($glossary->defaultapproval) {
132 $DB->execute("UPDATE {glossary_entries} SET approved = 1 where approved <> 1 and glossaryid = ?", array($glossary->id));
5eaa2d34 133 }
2a7eff41 134 glossary_grade_item_update($glossary);
07842023 135
dd88de0e 136 return true;
07842023 137}
138
49bcd737 139/**
140 * Given an ID of an instance of this module,
141 * this function will permanently delete the instance
142 * and any data that depends on it.
e121db76 143 *
144 * @global object
49bcd737 145 * @param int $id glossary id
146 * @return bool success
147 */
07842023 148function glossary_delete_instance($id) {
650a0c0a 149 global $DB, $CFG;
07842023 150
49bcd737 151 if (!$glossary = $DB->get_record('glossary', array('id'=>$id))) {
07842023 152 return false;
153 }
154
49bcd737 155 if (!$cm = get_coursemodule_from_instance('glossary', $id)) {
156 return false;
157 }
07842023 158
703a2c2e 159 if (!$context = context_module::instance($cm->id, IGNORE_MISSING)) {
49bcd737 160 return false;
161 }
07842023 162
49bcd737 163 $fs = get_file_storage();
164
165 if ($glossary->mainglossary) {
166 // unexport entries
167 $sql = "SELECT ge.id, ge.sourceglossaryid, cm.id AS sourcecmid
168 FROM {glossary_entries} ge
169 JOIN {modules} m ON m.name = 'glossary'
170 JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = ge.sourceglossaryid)
171 WHERE ge.glossaryid = ? AND ge.sourceglossaryid > 0";
172
173 if ($exported = $DB->get_records_sql($sql, array($id))) {
174 foreach ($exported as $entry) {
175 $entry->glossaryid = $entry->sourceglossaryid;
176 $entry->sourceglossaryid = 0;
e0a91e11 177 $newcontext = context_module::instance($entry->sourcecmid);
64f93798 178 if ($oldfiles = $fs->get_area_files($context->id, 'mod_glossary', 'attachment', $entry->id)) {
49bcd737 179 foreach ($oldfiles as $oldfile) {
39790bd8 180 $file_record = new stdClass();
49bcd737 181 $file_record->contextid = $newcontext->id;
182 $fs->create_file_from_storedfile($file_record, $oldfile);
183 }
64f93798 184 $fs->delete_area_files($context->id, 'mod_glossary', 'attachment', $entry->id);
49bcd737 185 $entry->attachment = '1';
072f7533 186 } else {
49bcd737 187 $entry->attachment = '0';
072f7533 188 }
49bcd737 189 $DB->update_record('glossary_entries', $entry);
49210b90 190 }
191 }
49bcd737 192 } else {
193 // move exported entries to main glossary
194 $sql = "UPDATE {glossary_entries}
195 SET sourceglossaryid = 0
196 WHERE sourceglossaryid = ?";
197 $DB->execute($sql, array($id));
07842023 198 }
49bcd737 199
200 // Delete any dependent records
201 $entry_select = "SELECT id FROM {glossary_entries} WHERE glossaryid = ?";
d95ed8e3 202 $DB->delete_records_select('comments', "contextid=? AND commentarea=? AND itemid IN ($entry_select)", array($id, 'glossary_entry', $context->id));
49bcd737 203 $DB->delete_records_select('glossary_alias', "entryid IN ($entry_select)", array($id));
49bcd737 204
205 $category_select = "SELECT id FROM {glossary_categories} WHERE glossaryid = ?";
206 $DB->delete_records_select('glossary_entries_categories', "categoryid IN ($category_select)", array($id));
207 $DB->delete_records('glossary_categories', array('glossaryid'=>$id));
3b953472 208 $DB->delete_records('glossary_entries', array('glossaryid'=>$id));
49bcd737 209
fa686bc4 210 // delete all files
211 $fs->delete_area_files($context->id);
49bcd737 212
e6d45048 213 glossary_grade_item_delete($glossary);
07842023 214
37625e2a
PS
215 $DB->delete_records('glossary', array('id'=>$id));
216
217 // Reset caches.
218 \mod_glossary\local\concept_cache::reset_glossary($glossary);
219
220 return true;
07842023 221}
222
e121db76 223/**
224 * Return a small object with summary information about what a
225 * user has done with a given particular instance of this module
226 * Used for user activity reports.
227 * $return->time = the time they did it
228 * $return->info = a short text description
229 *
230 * @param object $course
231 * @param object $user
232 * @param object $mod
233 * @param object $glossary
234 * @return object|null
235 */
07842023 236function glossary_user_outline($course, $user, $mod, $glossary) {
1a96363a
NC
237 global $CFG;
238
239 require_once("$CFG->libdir/gradelib.php");
240 $grades = grade_get_grades($course->id, 'mod', 'glossary', $glossary->id, $user->id);
241 if (empty($grades->items[0]->grades)) {
242 $grade = false;
243 } else {
244 $grade = reset($grades->items[0]->grades);
245 }
07842023 246
1ac87c73 247 if ($entries = glossary_get_user_entries($glossary->id, $user->id)) {
39790bd8 248 $result = new stdClass();
1ac87c73 249 $result->info = count($entries) . ' ' . get_string("entries", "glossary");
250
63dd5fb2 251 $lastentry = array_pop($entries);
252 $result->time = $lastentry->timemodified;
1a96363a
NC
253
254 if ($grade) {
255 $result->info .= ', ' . get_string('grade') . ': ' . $grade->str_long_grade;
256 }
257 return $result;
258 } else if ($grade) {
39790bd8 259 $result = new stdClass();
1a96363a 260 $result->info = get_string('grade') . ': ' . $grade->str_long_grade;
4433f871
AD
261
262 //datesubmitted == time created. dategraded == time modified or time overridden
263 //if grade was last modified by the user themselves use date graded. Otherwise use date submitted
94a74f54 264 //TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
4433f871
AD
265 if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
266 $result->time = $grade->dategraded;
267 } else {
268 $result->time = $grade->datesubmitted;
269 }
270
1ac87c73 271 return $result;
272 }
273 return NULL;
274}
275
e121db76 276/**
277 * @global object
278 * @param int $glossaryid
279 * @param int $userid
280 * @return array
281 */
1ac87c73 282function glossary_get_user_entries($glossaryid, $userid) {
283/// Get all the entries for a user in a glossary
ae8c3566 284 global $DB;
1ac87c73 285
ae8c3566 286 return $DB->get_records_sql("SELECT e.*, u.firstname, u.lastname, u.email, u.picture
287 FROM {glossary} g, {glossary_entries} e, {user} u
288 WHERE g.id = ?
a02c77dc 289 AND e.glossaryid = g.id
ae8c3566 290 AND e.userid = ?
1ac87c73 291 AND e.userid = u.id
ae8c3566 292 ORDER BY e.timemodified ASC", array($glossaryid, $userid));
07842023 293}
294
e121db76 295/**
296 * Print a detailed representation of what a user has done with
297 * a given particular instance of this module, for user activity reports.
298 *
299 * @global object
300 * @param object $course
301 * @param object $user
302 * @param object $mod
303 * @param object $glossary
304 */
07842023 305function glossary_user_complete($course, $user, $mod, $glossary) {
1a96363a
NC
306 global $CFG, $OUTPUT;
307 require_once("$CFG->libdir/gradelib.php");
308
309 $grades = grade_get_grades($course->id, 'mod', 'glossary', $glossary->id, $user->id);
310 if (!empty($grades->items[0]->grades)) {
311 $grade = reset($grades->items[0]->grades);
312 echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade);
313 if ($grade->str_feedback) {
314 echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback);
315 }
316 }
07842023 317
1ac87c73 318 if ($entries = glossary_get_user_entries($glossary->id, $user->id)) {
a359c29b 319 echo '<table width="95%" border="0"><tr><td>';
1ac87c73 320 foreach ($entries as $entry) {
321 $cm = get_coursemodule_from_instance("glossary", $glossary->id, $course->id);
322 glossary_print_entry($course, $cm, $glossary, $entry,"","",0);
323 echo '<p>';
324 }
a359c29b 325 echo '</td></tr></table>';
1ac87c73 326 }
07842023 327}
486a138b
JF
328
329/**
330 * Returns all glossary entries since a given time for specified glossary
efd412dd 331 *
486a138b
JF
332 * @param array $activities sequentially indexed array of objects
333 * @param int $index
334 * @param int $timestart
335 * @param int $courseid
336 * @param int $cmid
337 * @param int $userid defaults to 0
338 * @param int $groupid defaults to 0
339 * @return void adds items into $activities and increases $index
340 */
341function glossary_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid = 0, $groupid = 0) {
342 global $COURSE, $USER, $DB;
343
344 if ($COURSE->id == $courseid) {
345 $course = $COURSE;
346 } else {
347 $course = $DB->get_record('course', array('id' => $courseid));
348 }
349
350 $modinfo = get_fast_modinfo($course);
351 $cm = $modinfo->cms[$cmid];
352 $context = context_module::instance($cm->id);
353
e19c086c 354 if (!$cm->uservisible) {
486a138b
JF
355 return;
356 }
357
358 $viewfullnames = has_capability('moodle/site:viewfullnames', $context);
e19c086c
MG
359 // Groups are not yet supported for glossary. See MDL-10728 .
360 /*
486a138b
JF
361 $accessallgroups = has_capability('moodle/site:accessallgroups', $context);
362 $groupmode = groups_get_activity_groupmode($cm, $course);
e19c086c 363 */
486a138b
JF
364
365 $params['timestart'] = $timestart;
366
367 if ($userid) {
368 $userselect = "AND u.id = :userid";
369 $params['userid'] = $userid;
370 } else {
371 $userselect = '';
372 }
373
374 if ($groupid) {
375 $groupselect = 'AND gm.groupid = :groupid';
376 $groupjoin = 'JOIN {groups_members} gm ON gm.userid=u.id';
377 $params['groupid'] = $groupid;
378 } else {
379 $groupselect = '';
380 $groupjoin = '';
381 }
382
e19c086c
MG
383 $approvedselect = "";
384 if (!has_capability('mod/glossary:approve', $context)) {
385 $approvedselect = " AND ge.approved = 1 ";
386 }
387
486a138b
JF
388 $params['timestart'] = $timestart;
389 $params['glossaryid'] = $cm->instance;
390
e19c086c 391 $ufields = user_picture::fields('u', null, 'userid');
486a138b 392 $entries = $DB->get_records_sql("
e19c086c
MG
393 SELECT ge.id AS entryid, ge.glossaryid, ge.concept, ge.definition, ge.approved,
394 ge.timemodified, $ufields
486a138b
JF
395 FROM {glossary_entries} ge
396 JOIN {user} u ON u.id = ge.userid
397 $groupjoin
398 WHERE ge.timemodified > :timestart
399 AND ge.glossaryid = :glossaryid
e19c086c 400 $approvedselect
486a138b
JF
401 $userselect
402 $groupselect
403 ORDER BY ge.timemodified ASC", $params);
efd412dd 404
486a138b
JF
405 if (!$entries) {
406 return;
407 }
efd412dd 408
486a138b 409 foreach ($entries as $entry) {
e19c086c
MG
410 // Groups are not yet supported for glossary. See MDL-10728 .
411 /*
486a138b
JF
412 $usersgroups = null;
413 if ($entry->userid != $USER->id) {
414 if ($groupmode == SEPARATEGROUPS and !$accessallgroups) {
415 if (is_null($usersgroups)) {
416 $usersgroups = groups_get_all_groups($course->id, $entry->userid, $cm->groupingid);
417 if (is_array($usersgroups)) {
418 $usersgroups = array_keys($usersgroups);
419 } else {
420 $usersgroups = array();
421 }
422 }
e19c086c 423 if (!array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid))) {
486a138b
JF
424 continue;
425 }
426 }
427 }
e19c086c 428 */
486a138b
JF
429
430 $tmpactivity = new stdClass();
e19c086c 431 $tmpactivity->user = user_picture::unalias($entry, null, 'userid');
cb0f82dd 432 $tmpactivity->user->fullname = fullname($tmpactivity->user, $viewfullnames);
486a138b
JF
433 $tmpactivity->type = 'glossary';
434 $tmpactivity->cmid = $cm->id;
50a8374e 435 $tmpactivity->glossaryid = $entry->glossaryid;
486a138b
JF
436 $tmpactivity->name = format_string($cm->name, true);
437 $tmpactivity->sectionnum = $cm->sectionnum;
438 $tmpactivity->timestamp = $entry->timemodified;
9bba1308 439 $tmpactivity->content = new stdClass();
50a8374e 440 $tmpactivity->content->entryid = $entry->entryid;
486a138b
JF
441 $tmpactivity->content->concept = $entry->concept;
442 $tmpactivity->content->definition = $entry->definition;
e19c086c 443 $tmpactivity->content->approved = $entry->approved;
486a138b
JF
444
445 $activities[$index++] = $tmpactivity;
446 }
447
448 return true;
449}
450
451/**
452 * Outputs the glossary entry indicated by $activity
efd412dd 453 *
486a138b
JF
454 * @param object $activity the activity object the glossary resides in
455 * @param int $courseid the id of the course the glossary resides in
456 * @param bool $detail not used, but required for compatibilty with other modules
457 * @param int $modnames not used, but required for compatibilty with other modules
458 * @param bool $viewfullnames not used, but required for compatibilty with other modules
459 * @return void
460 */
461function glossary_print_recent_mod_activity($activity, $courseid, $detail, $modnames, $viewfullnames) {
462 global $OUTPUT;
463
50a8374e 464 echo html_writer::start_tag('div', array('class'=>'glossary-activity clearfix'));
486a138b
JF
465 if (!empty($activity->user)) {
466 echo html_writer::tag('div', $OUTPUT->user_picture($activity->user, array('courseid'=>$courseid)),
50a8374e 467 array('class' => 'glossary-activity-picture'));
486a138b
JF
468 }
469
50a8374e
FM
470 echo html_writer::start_tag('div', array('class'=>'glossary-activity-content'));
471 echo html_writer::start_tag('div', array('class'=>'glossary-activity-entry'));
472
e19c086c
MG
473 if (isset($activity->content->approved) && !$activity->content->approved) {
474 $urlparams = array('g' => $activity->glossaryid, 'mode' => 'approval', 'hook' => $activity->content->concept);
475 $class = array('class' => 'dimmed_text');
476 } else {
477 $urlparams = array('g' => $activity->glossaryid, 'mode' => 'entry', 'hook' => $activity->content->entryid);
478 $class = array();
479 }
480 echo html_writer::link(new moodle_url('/mod/glossary/view.php', $urlparams),
481 strip_tags($activity->content->concept), $class);
486a138b
JF
482 echo html_writer::end_tag('div');
483
484 $url = new moodle_url('/user/view.php', array('course'=>$courseid, 'id'=>$activity->user->id));
485 $name = $activity->user->fullname;
e19c086c 486 $link = html_writer::link($url, $name, $class);
486a138b
JF
487
488 echo html_writer::start_tag('div', array('class'=>'user'));
489 echo $link .' - '. userdate($activity->timestamp);
490 echo html_writer::end_tag('div');
491
50a8374e
FM
492 echo html_writer::end_tag('div');
493
486a138b
JF
494 echo html_writer::end_tag('div');
495 return;
496}
e121db76 497/**
498 * Given a course and a time, this module should find recent activity
499 * that has occurred in glossary activities and print it out.
500 * Return true if there was output, or false is there was none.
501 *
502 * @global object
503 * @global object
504 * @global object
505 * @param object $course
506 * @param object $viewfullnames
507 * @param int $timestart
508 * @return bool
509 */
dd97c328 510function glossary_print_recent_activity($course, $viewfullnames, $timestart) {
c3963fbd 511 global $CFG, $USER, $DB, $OUTPUT, $PAGE;
dd97c328 512
513 //TODO: use timestamp in approved field instead of changing timemodified when approving in 2.0
fe1776b9
AB
514 if (!defined('GLOSSARY_RECENT_ACTIVITY_LIMIT')) {
515 define('GLOSSARY_RECENT_ACTIVITY_LIMIT', 50);
516 }
dd97c328 517 $modinfo = get_fast_modinfo($course);
518 $ids = array();
fe1776b9 519
dd97c328 520 foreach ($modinfo->cms as $cm) {
521 if ($cm->modname != 'glossary') {
522 continue;
523 }
524 if (!$cm->uservisible) {
525 continue;
526 }
fe1776b9 527 $ids[$cm->instance] = $cm->id;
dd97c328 528 }
529
530 if (!$ids) {
531 return false;
532 }
533
fe1776b9
AB
534 // generate list of approval capabilities for all glossaries in the course.
535 $approvals = array();
536 foreach ($ids as $glinstanceid => $glcmid) {
e0a91e11 537 $context = context_module::instance($glcmid);
bcab2b21
JF
538 if (has_capability('mod/glossary:view', $context)) {
539 // get records glossary entries that are approved if user has no capability to approve entries.
540 if (has_capability('mod/glossary:approve', $context)) {
541 $approvals[] = ' ge.glossaryid = :glsid'.$glinstanceid.' ';
542 } else {
543 $approvals[] = ' (ge.approved = 1 AND ge.glossaryid = :glsid'.$glinstanceid.') ';
544 }
545 $params['glsid'.$glinstanceid] = $glinstanceid;
fe1776b9 546 }
07842023 547 }
548
bcab2b21
JF
549 if (count($approvals) == 0) {
550 return false;
551 }
fe1776b9 552 $selectsql = 'SELECT ge.id, ge.concept, ge.approved, ge.timemodified, ge.glossaryid,
37695a6f 553 '.user_picture::fields('u',null,'userid');
fe1776b9 554 $countsql = 'SELECT COUNT(*)';
a359c29b 555
fe1776b9
AB
556 $joins = array(' FROM {glossary_entries} ge ');
557 $joins[] = 'JOIN {user} u ON u.id = ge.userid ';
558 $fromsql = implode($joins, "\n");
dd97c328 559
fe1776b9 560 $params['timestart'] = $timestart;
c3963fbd 561 $clausesql = ' WHERE ge.timemodified > :timestart ';
8f7dc7f1 562
c3963fbd
JF
563 if (count($approvals) > 0) {
564 $approvalsql = 'AND ('. implode($approvals, ' OR ') .') ';
565 } else {
5599f206 566 $approvalsql = '';
c3963fbd
JF
567 }
568 $ordersql = 'ORDER BY ge.timemodified ASC';
fe1776b9
AB
569 $entries = $DB->get_records_sql($selectsql.$fromsql.$clausesql.$approvalsql.$ordersql, $params, 0, (GLOSSARY_RECENT_ACTIVITY_LIMIT+1));
570
571 if (empty($entries)) {
dd97c328 572 return false;
573 }
fe1776b9 574
a8608cba 575 echo $OUTPUT->heading(get_string('newentries', 'glossary').':', 3);
dd97c328 576 $strftimerecent = get_string('strftimerecent');
fe1776b9 577 $entrycount = 0;
dd97c328 578 foreach ($entries as $entry) {
fe1776b9
AB
579 if ($entrycount < GLOSSARY_RECENT_ACTIVITY_LIMIT) {
580 if ($entry->approved) {
581 $dimmed = '';
582 $urlparams = array('g' => $entry->glossaryid, 'mode' => 'entry', 'hook' => $entry->id);
583 } else {
584 $dimmed = ' dimmed_text';
585 $urlparams = array('id' => $ids[$entry->glossaryid], 'mode' => 'approval', 'hook' => format_text($entry->concept, true));
586 }
587 $link = new moodle_url($CFG->wwwroot.'/mod/glossary/view.php' , $urlparams);
588 echo '<div class="head'.$dimmed.'">';
589 echo '<div class="date">'.userdate($entry->timemodified, $strftimerecent).'</div>';
590 echo '<div class="name">'.fullname($entry, $viewfullnames).'</div>';
591 echo '</div>';
a8608cba 592 echo '<div class="info"><a href="'.$link.'">'.format_string($entry->concept, true).'</a></div>';
fe1776b9 593 $entrycount += 1;
dd97c328 594 } else {
48e6de1c 595 $numnewentries = $DB->count_records_sql($countsql.$joins[0].$clausesql.$approvalsql, $params);
fe1776b9
AB
596 echo '<div class="head"><div class="activityhead">'.get_string('andmorenewentries', 'glossary', $numnewentries - GLOSSARY_RECENT_ACTIVITY_LIMIT).'</div></div>';
597 break;
07842023 598 }
599 }
600
dd97c328 601 return true;
07842023 602}
603
e121db76 604/**
605 * @global object
606 * @param object $log
607 */
1ac87c73 608function glossary_log_info($log) {
ae8c3566 609 global $DB;
1ac87c73 610
ae8c3566 611 return $DB->get_record_sql("SELECT e.*, u.firstname, u.lastname
612 FROM {glossary_entries} e, {user} u
613 WHERE e.id = ? AND u.id = ?", array($log->info, $log->userid));
1ac87c73 614}
615
e121db76 616/**
617 * Function to be run periodically according to the moodle cron
618 * This function searches for things that need to be done, such
619 * as sending out mail, toggling flags etc ...
620 * @return bool
621 */
07842023 622function glossary_cron () {
07842023 623 return true;
624}
625
d31bae70 626/**
627 * Return grade for given user or all users.
628 *
a153c9f2
AD
629 * @param stdClass $glossary A glossary instance
630 * @param int $userid Optional user id, 0 means all users
631 * @return array An array of grades, false if none
d31bae70 632 */
612607bd 633function glossary_get_user_grades($glossary, $userid=0) {
63e87951
AD
634 global $CFG;
635
636 require_once($CFG->dirroot.'/rating/lib.php');
63e87951 637
2b04c41c 638 $ratingoptions = new stdClass;
63e87951
AD
639
640 //need these to work backwards to get a context id. Is there a better way to get contextid from a module instance?
641 $ratingoptions->modulename = 'glossary';
642 $ratingoptions->moduleid = $glossary->id;
2b04c41c
SH
643 $ratingoptions->component = 'mod_glossary';
644 $ratingoptions->ratingarea = 'entry';
63e87951
AD
645
646 $ratingoptions->userid = $userid;
647 $ratingoptions->aggregationmethod = $glossary->assessed;
648 $ratingoptions->scaleid = $glossary->scale;
649 $ratingoptions->itemtable = 'glossary_entries';
650 $ratingoptions->itemtableusercolumn = 'userid';
651
2b04c41c 652 $rm = new rating_manager();
63e87951 653 return $rm->get_user_grades($ratingoptions);
e6d45048 654}
655
d251b259
AD
656/**
657 * Return rating related permissions
2b04c41c
SH
658 *
659 * @param int $contextid the context id
660 * @param string $component The component we want to get permissions for
661 * @param string $ratingarea The ratingarea that we want to get permissions for
d251b259
AD
662 * @return array an associative array of the user's rating permissions
663 */
2b04c41c
SH
664function glossary_rating_permissions($contextid, $component, $ratingarea) {
665 if ($component != 'mod_glossary' || $ratingarea != 'entry') {
666 // We don't know about this component/ratingarea so just return null to get the
667 // default restrictive permissions.
d251b259 668 return null;
d251b259 669 }
d197ea43 670 $context = context::instance_by_id($contextid);
2b04c41c
SH
671 return array(
672 'view' => has_capability('mod/glossary:viewrating', $context),
673 'viewany' => has_capability('mod/glossary:viewanyrating', $context),
674 'viewall' => has_capability('mod/glossary:viewallratings', $context),
675 'rate' => has_capability('mod/glossary:rate', $context)
676 );
d251b259
AD
677}
678
aeafd436 679/**
2c2ff8d5
AD
680 * Validates a submitted rating
681 * @param array $params submitted data
682 * context => object the context in which the rated items exists [required]
2b04c41c
SH
683 * component => The component for this module - should always be mod_forum [required]
684 * ratingarea => object the context in which the rated items exists [required]
685 * itemid => int the ID of the object being rated [required]
2c2ff8d5
AD
686 * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required]
687 * rating => int the submitted rating
688 * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required]
689 * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [optional]
778361c3 690 * @return boolean true if the rating is valid. Will throw rating_exception if not
aeafd436 691 */
778361c3 692function glossary_rating_validate($params) {
2c2ff8d5
AD
693 global $DB, $USER;
694
2b04c41c
SH
695 // Check the component is mod_forum
696 if ($params['component'] != 'mod_glossary') {
697 throw new rating_exception('invalidcomponent');
2c2ff8d5
AD
698 }
699
2b04c41c
SH
700 // Check the ratingarea is post (the only rating area in forum)
701 if ($params['ratingarea'] != 'entry') {
702 throw new rating_exception('invalidratingarea');
703 }
704
705 // Check the rateduserid is not the current user .. you can't rate your own posts
706 if ($params['rateduserid'] == $USER->id) {
707 throw new rating_exception('nopermissiontorate');
708 }
709
710 $glossarysql = "SELECT g.id as glossaryid, g.scale, g.course, e.userid as userid, e.approved, e.timecreated, g.assesstimestart, g.assesstimefinish
2c2ff8d5
AD
711 FROM {glossary_entries} e
712 JOIN {glossary} g ON e.glossaryid = g.id
713 WHERE e.id = :itemid";
2b04c41c
SH
714 $glossaryparams = array('itemid' => $params['itemid']);
715 $info = $DB->get_record_sql($glossarysql, $glossaryparams);
716 if (!$info) {
778361c3
AD
717 //item doesn't exist
718 throw new rating_exception('invaliditemid');
2c2ff8d5 719 }
f2e72593 720
6ac149dc
AD
721 if ($info->scale != $params['scaleid']) {
722 //the scale being submitted doesnt match the one in the database
723 throw new rating_exception('invalidscaleid');
724 }
725
6ac149dc 726 //check that the submitted rating is valid for the scale
5693d56c
EL
727
728 // lower limit
729 if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) {
6ac149dc 730 throw new rating_exception('invalidnum');
5693d56c
EL
731 }
732
733 // upper limit
734 if ($info->scale < 0) {
6ac149dc 735 //its a custom scale
2b04c41c 736 $scalerecord = $DB->get_record('scale', array('id' => -$info->scale));
6ac149dc
AD
737 if ($scalerecord) {
738 $scalearray = explode(',', $scalerecord->scale);
739 if ($params['rating'] > count($scalearray)) {
740 throw new rating_exception('invalidnum');
741 }
742 } else {
743 throw new rating_exception('invalidscaleid');
744 }
745 } else if ($params['rating'] > $info->scale) {
746 //if its numeric and submitted rating is above maximum
747 throw new rating_exception('invalidnum');
748 }
749
2c2ff8d5
AD
750 //check the item we're rating was created in the assessable time window
751 if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) {
752 if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) {
778361c3 753 throw new rating_exception('notavailable');
2c2ff8d5
AD
754 }
755 }
756
2b04c41c 757 $cm = get_coursemodule_from_instance('glossary', $info->glossaryid, $info->course, false, MUST_EXIST);
e0a91e11 758 $context = context_module::instance($cm->id, MUST_EXIST);
2c2ff8d5 759
2b04c41c
SH
760 // if the supplied context doesnt match the item's context
761 if ($context->id != $params['context']->id) {
778361c3 762 throw new rating_exception('invalidcontext');
2c2ff8d5
AD
763 }
764
765 return true;
aeafd436
AD
766}
767
d31bae70 768/**
775f811a 769 * Update activity grades
d31bae70 770 *
a153c9f2
AD
771 * @category grade
772 * @param stdClass $glossary Null means all glossaries (with extra cmidnumber property)
775f811a 773 * @param int $userid specific user only, 0 means all
a153c9f2 774 * @param bool $nullifnone If true and the user has no grade then a grade item with rawgrade == null will be inserted
d31bae70 775 */
612607bd 776function glossary_update_grades($glossary=null, $userid=0, $nullifnone=true) {
ae8c3566 777 global $CFG, $DB;
adcbb43a 778 require_once($CFG->libdir.'/gradelib.php');
e6d45048 779
775f811a 780 if (!$glossary->assessed) {
781 glossary_grade_item_update($glossary);
3e6303b7 782
775f811a 783 } else if ($grades = glossary_get_user_grades($glossary, $userid)) {
784 glossary_grade_item_update($glossary, $grades);
eafb9d9e 785
775f811a 786 } else if ($userid and $nullifnone) {
39790bd8 787 $grade = new stdClass();
775f811a 788 $grade->userid = $userid;
789 $grade->rawgrade = NULL;
790 glossary_grade_item_update($glossary, $grade);
a02c77dc 791
e6d45048 792 } else {
775f811a 793 glossary_grade_item_update($glossary);
794 }
795}
796
d31bae70 797/**
612607bd 798 * Create/update grade item for given glossary
d31bae70 799 *
a153c9f2
AD
800 * @category grade
801 * @param stdClass $glossary object with extra cmidnumber
802 * @param mixed $grades Optional array/object of grade(s); 'reset' means reset grades in gradebook
612607bd 803 * @return int, 0 if ok, error code otherwise
d31bae70 804 */
0b5a80a1 805function glossary_grade_item_update($glossary, $grades=NULL) {
612607bd 806 global $CFG;
ae8c3566 807 require_once($CFG->libdir.'/gradelib.php');
808
7f46236f 809 $params = array('itemname'=>$glossary->name, 'idnumber'=>$glossary->cmidnumber);
e6d45048 810
5980d52f 811 if (!$glossary->assessed or $glossary->scale == 0) {
612607bd 812 $params['gradetype'] = GRADE_TYPE_NONE;
34601114 813
814 } else if ($glossary->scale > 0) {
e8586b5f 815 $params['gradetype'] = GRADE_TYPE_VALUE;
e6d45048 816 $params['grademax'] = $glossary->scale;
817 $params['grademin'] = 0;
818
819 } else if ($glossary->scale < 0) {
e8586b5f 820 $params['gradetype'] = GRADE_TYPE_SCALE;
e6d45048 821 $params['scaleid'] = -$glossary->scale;
e6d45048 822 }
823
0b5a80a1 824 if ($grades === 'reset') {
825 $params['reset'] = true;
826 $grades = NULL;
827 }
828
829 return grade_update('mod/glossary', $glossary->course, 'mod', 'glossary', $glossary->id, 0, $grades, $params);
e6d45048 830}
831
d31bae70 832/**
833 * Delete grade item for given glossary
1adbd2c3 834 *
a153c9f2 835 * @category grade
dd232d01 836 * @param object $glossary object
d31bae70 837 */
e6d45048 838function glossary_grade_item_delete($glossary) {
612607bd 839 global $CFG;
840 require_once($CFG->libdir.'/gradelib.php');
841
b67ec72f 842 return grade_update('mod/glossary', $glossary->course, 'mod', 'glossary', $glossary->id, 0, NULL, array('deleted'=>1));
07842023 843}
844
e121db76 845/**
846 * @global object
847 * @param int $gloassryid
848 * @param int $scaleid
849 * @return bool
850 */
0f1a97c2 851function glossary_scale_used ($glossaryid,$scaleid) {
852//This function returns if a scale is being used by one glossary
ae8c3566 853 global $DB;
a02c77dc 854
0f1a97c2 855 $return = false;
856
ae8c3566 857 $rec = $DB->get_record("glossary", array("id"=>$glossaryid, "scale"=>-$scaleid));
0f1a97c2 858
2127fedd 859 if (!empty($rec) && !empty($scaleid)) {
a02c77dc 860 $return = true;
861 }
862
0f1a97c2 863 return $return;
864}
865
85c9ebb9 866/**
867 * Checks if scale is being used by any instance of glossary
868 *
869 * This is used to find out if scale used anywhere
e121db76 870 *
871 * @global object
872 * @param int $scaleid
85c9ebb9 873 * @return boolean True if the scale is used by any glossary
874 */
875function glossary_scale_used_anywhere($scaleid) {
ae8c3566 876 global $DB;
877
878 if ($scaleid and $DB->record_exists('glossary', array('scale'=>-$scaleid))) {
85c9ebb9 879 return true;
880 } else {
881 return false;
882 }
883}
884
07842023 885//////////////////////////////////////////////////////////////////////////////////////
886/// Any other glossary functions go here. Each of them must have a name that
887/// starts with glossary_
888
e121db76 889/**
890 * This function return an array of valid glossary_formats records
891 * Everytime it's called, every existing format is checked, new formats
892 * are included if detected and old formats are deleted and any glossary
893 * using an invalid format is updated to the default (dictionary).
894 *
895 * @global object
896 * @global object
897 * @return array
898 */
a359c29b 899function glossary_get_available_formats() {
ae8c3566 900 global $CFG, $DB;
a359c29b 901
902 //Get available formats (plugin) and insert (if necessary) them into glossary_formats
77495793 903 $formats = get_list_of_plugins('mod/glossary/formats', 'TEMPLATE');
904 $pluginformats = array();
a359c29b 905 foreach ($formats as $format) {
906 //If the format file exists
907 if (file_exists($CFG->dirroot.'/mod/glossary/formats/'.$format.'/'.$format.'_format.php')) {
908 include_once($CFG->dirroot.'/mod/glossary/formats/'.$format.'/'.$format.'_format.php');
909 //If the function exists
910 if (function_exists('glossary_show_entry_'.$format)) {
77495793 911 //Acummulate it as a valid format
912 $pluginformats[] = $format;
a359c29b 913 //If the format doesn't exist in the table
ae8c3566 914 if (!$rec = $DB->get_record('glossary_formats', array('name'=>$format))) {
a359c29b 915 //Insert the record in glossary_formats
39790bd8 916 $gf = new stdClass();
a359c29b 917 $gf->name = $format;
918 $gf->popupformatname = $format;
919 $gf->visible = 1;
29645f97
MG
920 $id = $DB->insert_record('glossary_formats', $gf);
921 $rec = $DB->get_record('glossary_formats', array('id' => $id));
a359c29b 922 }
223d6cb3 923
29645f97 924 if (empty($rec->showtabs)) {
223d6cb3
NS
925 glossary_set_default_visible_tabs($rec);
926 }
a359c29b 927 }
928 }
929 }
930
931 //Delete non_existent formats from glossary_formats table
ae8c3566 932 $formats = $DB->get_records("glossary_formats");
a359c29b 933 foreach ($formats as $format) {
934 $todelete = false;
77495793 935 //If the format in DB isn't a valid previously detected format then delete the record
936 if (!in_array($format->name,$pluginformats)) {
a359c29b 937 $todelete = true;
a359c29b 938 }
939
940 if ($todelete) {
941 //Delete the format
ae8c3566 942 $DB->delete_records('glossary_formats', array('name'=>$format->name));
a359c29b 943 //Reasign existing glossaries to default (dictionary) format
ae8c3566 944 if ($glossaries = $DB->get_records('glossary', array('displayformat'=>$format->name))) {
a359c29b 945 foreach($glossaries as $glossary) {
ae8c3566 946 $DB->set_field('glossary','displayformat','dictionary', array('id'=>$glossary->id));
a359c29b 947 }
948 }
949 }
950 }
951
952 //Now everything is ready in glossary_formats table
ae8c3566 953 $formats = $DB->get_records("glossary_formats");
a359c29b 954
955 return $formats;
956}
957
e121db76 958/**
959 * @param bool $debug
960 * @param string $text
961 * @param int $br
962 */
1ac87c73 963function glossary_debug($debug,$text,$br=1) {
964 if ( $debug ) {
41905731 965 echo '<font color="red">' . $text . '</font>';
1ac87c73 966 if ( $br ) {
a9ef4a63 967 echo '<br />';
1ac87c73 968 }
969 }
07842023 970}
971
e121db76 972/**
973 *
974 * @global object
975 * @param int $glossaryid
976 * @param string $entrylist
977 * @param string $pivot
978 * @return array
979 */
ea14e783 980function glossary_get_entries($glossaryid, $entrylist, $pivot = "") {
ae8c3566 981 global $DB;
ea14e783 982 if ($pivot) {
983 $pivot .= ",";
984 }
07842023 985
ae8c3566 986 return $DB->get_records_sql("SELECT $pivot id,userid,concept,definition,format
987 FROM {glossary_entries}
988 WHERE glossaryid = ?
989 AND id IN ($entrylist)", array($glossaryid));
07842023 990}
359f2758 991
e121db76 992/**
993 * @global object
994 * @global object
995 * @param object $concept
996 * @param string $courseid
997 * @return array
998 */
359f2758 999function glossary_get_entries_search($concept, $courseid) {
ae8c3566 1000 global $CFG, $DB;
359f2758 1001
a02c77dc 1002 //Check if the user is an admin
6c351232 1003 $bypassadmin = 1; //This means NO (by default)
e0a91e11 1004 if (has_capability('moodle/course:viewhiddenactivities', context_system::instance())) {
6c351232 1005 $bypassadmin = 0; //This means YES
a02c77dc 1006 }
6c351232 1007
a02c77dc 1008 //Check if the user is a teacher
6c351232 1009 $bypassteacher = 1; //This means NO (by default)
e0a91e11 1010 if (has_capability('mod/glossary:manageentries', context_course::instance($courseid))) {
6c351232 1011 $bypassteacher = 0; //This means YES
a02c77dc 1012 }
6c351232 1013
2f1e464a 1014 $conceptlower = core_text::strtolower(trim($concept));
359f2758 1015
ae8c3566 1016 $params = array('courseid1'=>$courseid, 'courseid2'=>$courseid, 'conceptlower'=>$conceptlower, 'concept'=>$concept);
c76e673a 1017
ae8c3566 1018 return $DB->get_records_sql("SELECT e.*, g.name as glossaryname, cm.id as cmid, cm.course as courseid
1019 FROM {glossary_entries} e, {glossary} g,
1020 {course_modules} cm, {modules} m
1021 WHERE m.name = 'glossary' AND
1022 cm.module = m.id AND
1023 (cm.visible = 1 OR cm.visible = $bypassadmin OR
1024 (cm.course = :courseid1 AND cm.visible = $bypassteacher)) AND
1025 g.id = cm.instance AND
1026 e.glossaryid = g.id AND
1027 ( (e.casesensitive != 0 AND LOWER(concept) = :conceptlower) OR
1028 (e.casesensitive = 0 and concept = :concept)) AND
2e300e13 1029 (g.course = :courseid2 OR g.globalglossary = 1) AND
ae8c3566 1030 e.usedynalink != 0 AND
1031 g.usedynalink != 0", $params);
c76e673a 1032}
07842023 1033
e121db76 1034/**
1035 * @global object
1036 * @global object
1037 * @param object $course
1038 * @param object $course
1039 * @param object $glossary
1040 * @param object $entry
1041 * @param string $mode
1042 * @param string $hook
1043 * @param int $printicons
1044 * @param int $displayformat
e121db76 1045 * @param bool $printview
1046 * @return mixed
1047 */
63e87951 1048function glossary_print_entry($course, $cm, $glossary, $entry, $mode='',$hook='',$printicons = 1, $displayformat = -1, $printview = false) {
b8340d19 1049 global $USER, $CFG;
37d543b5 1050 $return = false;
b1918034 1051 if ( $displayformat < 0 ) {
1052 $displayformat = $glossary->displayformat;
1053 }
b620a995 1054 if ($entry->approved or ($USER->id == $entry->userid) or ($mode == 'approval' and !$entry->approved) ) {
a359c29b 1055 $formatfile = $CFG->dirroot.'/mod/glossary/formats/'.$displayformat.'/'.$displayformat.'_format.php';
ae06e00e 1056 if ($printview) {
1057 $functionname = 'glossary_print_entry_'.$displayformat;
1058 } else {
1059 $functionname = 'glossary_show_entry_'.$displayformat;
1060 }
a359c29b 1061
1062 if (file_exists($formatfile)) {
1063 include_once($formatfile);
1064 if (function_exists($functionname)) {
63e87951 1065 $return = $functionname($course, $cm, $glossary, $entry,$mode,$hook,$printicons);
ae06e00e 1066 } else if ($printview) {
1067 //If the glossary_print_entry_XXXX function doesn't exist, print default (old) print format
ccde17c3 1068 $return = glossary_print_entry_default($entry, $glossary, $cm);
c76e673a 1069 }
767a31c3 1070 }
07842023 1071 }
a359c29b 1072 return $return;
07842023 1073}
b8340d19 1074
e121db76 1075/**
1076 * Default (old) print format used if custom function doesn't exist in format
1077 *
1078 * @param object $entry
1079 * @param object $glossary
1080 * @param object $cm
1081 * @return void Output is echo'd
1082 */
ccde17c3 1083function glossary_print_entry_default ($entry, $glossary, $cm) {
99d19c13
PS
1084 global $CFG;
1085
1086 require_once($CFG->libdir . '/filelib.php');
1087
e5d932cc 1088 echo $OUTPUT->heading(strip_tags($entry->concept), 4);
7d8a3cb0 1089
1090 $definition = $entry->definition;
1091
7d8a3cb0 1092 $definition = '<span class="nolink">' . strip_tags($definition) . '</span>';
1093
e0a91e11 1094 $context = context_module::instance($cm->id);
64f93798 1095 $definition = file_rewrite_pluginfile_urls($definition, 'pluginfile.php', $context->id, 'mod_glossary', 'entry', $entry->id);
cbc2b5df 1096
39790bd8 1097 $options = new stdClass();
ae06e00e 1098 $options->para = false;
cbc2b5df 1099 $options->trusted = $entry->definitiontrust;
367a75fa
SH
1100 $options->context = $context;
1101 $options->overflowdiv = true;
cbc2b5df 1102 $definition = format_text($definition, $entry->definitionformat, $options);
ae06e00e 1103 echo ($definition);
1104 echo '<br /><br />';
1105}
a359c29b 1106
120a18f0 1107/**
e5d932cc 1108 * Print glossary concept/term as a heading &lt;h4>
e121db76 1109 * @param object $entry
120a18f0 1110 */
218c0385 1111function glossary_print_entry_concept($entry, $return=false) {
2d8e042e 1112 global $OUTPUT;
50d24a3c 1113
e5d932cc 1114 $text = $OUTPUT->heading(format_string($entry->concept), 4);
ff8352de 1115 if (!empty($entry->highlight)) {
1116 $text = highlight($entry->highlight, $text);
1117 }
218c0385
AD
1118
1119 if ($return) {
1120 return $text;
1121 } else {
1122 echo $text;
1123 }
81bdc9e9 1124}
1d9ddaaf 1125
e121db76 1126/**
1127 *
367a75fa 1128 * @global moodle_database DB
e121db76 1129 * @param object $entry
1130 * @param object $glossary
1131 * @param object $cm
1132 */
ccde17c3 1133function glossary_print_entry_definition($entry, $glossary, $cm) {
37625e2a 1134 global $GLOSSARY_EXCLUDEENTRY;
701fff21 1135
f287e69c 1136 $definition = $entry->definition;
1137
37625e2a
PS
1138 // Do not link self.
1139 $GLOSSARY_EXCLUDEENTRY = $entry->id;
f287e69c 1140
e0a91e11 1141 $context = context_module::instance($cm->id);
64f93798 1142 $definition = file_rewrite_pluginfile_urls($definition, 'pluginfile.php', $context->id, 'mod_glossary', 'entry', $entry->id);
cbc2b5df 1143
ea7a9614
PS
1144 $options = new stdClass();
1145 $options->para = false;
1146 $options->trusted = $entry->definitiontrust;
367a75fa
SH
1147 $options->context = $context;
1148 $options->overflowdiv = true;
50d24a3c 1149
cbc2b5df 1150 $text = format_text($definition, $entry->definitionformat, $options);
1151
4e489ae9 1152 // Stop excluding concepts from autolinking
37625e2a 1153 unset($GLOSSARY_EXCLUDEENTRY);
cbc2b5df 1154
ff8352de 1155 if (!empty($entry->highlight)) {
1156 $text = highlight($entry->highlight, $text);
1157 }
359f2758 1158 if (isset($entry->footer)) { // Unparsed footer info
1159 $text .= $entry->footer;
1160 }
ff8352de 1161 echo $text;
1d9ddaaf 1162}
1163
e121db76 1164/**
1165 *
1166 * @global object
1167 * @param object $course
1168 * @param object $cm
1169 * @param object $glossary
1170 * @param object $entry
1171 * @param string $mode
1172 * @param string $hook
1173 * @param string $type
1174 * @return string|void
1175 */
b8340d19 1176function glossary_print_entry_aliases($course, $cm, $glossary, $entry,$mode='',$hook='', $type = 'print') {
ae8c3566 1177 global $DB;
1178
81bdc9e9 1179 $return = '';
ae8c3566 1180 if ( $aliases = $DB->get_records('glossary_alias', array('entryid'=>$entry->id))) {
81bdc9e9 1181 foreach ($aliases as $alias) {
33cc423e 1182 if (trim($alias->alias)) {
81bdc9e9 1183 if ($return == '') {
656eb813 1184 $return = '<select id="keyword" style="font-size:8pt">';
81bdc9e9 1185 }
1186 $return .= "<option>$alias->alias</option>";
1187 }
1188 }
1189 if ($return != '') {
1190 $return .= '</select>';
81bdc9e9 1191 }
a02c77dc 1192 }
1ac87c73 1193 if ($type == 'print') {
81bdc9e9 1194 echo $return;
1195 } else {
1196 return $return;
1197 }
1198}
1199
e121db76 1200/**
1201 *
1202 * @global object
1203 * @global object
1204 * @global object
1205 * @param object $course
1206 * @param object $cm
1207 * @param object $glossary
1208 * @param object $entry
1209 * @param string $mode
1210 * @param string $hook
1211 * @param string $type
1212 * @return string|void
1213 */
b8340d19 1214function glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode='',$hook='', $type = 'print') {
4096752d 1215 global $USER, $CFG, $DB, $OUTPUT;
a02c77dc 1216
e0a91e11 1217 $context = context_module::instance($cm->id);
81bdc9e9 1218
36ce6ea2 1219 $output = false; //To decide if we must really return text in "return". Activate when needed only!
81bdc9e9 1220 $importedentry = ($entry->sourceglossaryid == $glossary->id);
81bdc9e9 1221 $ismainglossary = $glossary->mainglossary;
b8340d19 1222
1223
9362b9b6 1224 $return = '<span class="commands">';
097d705e 1225 // Differentiate links for each entry.
2d1e0971 1226 $altsuffix = ': '.strip_tags(format_text($entry->concept));
1227
81bdc9e9 1228 if (!$entry->approved) {
36ce6ea2 1229 $output = true;
851d3b7a
FM
1230 $return .= html_writer::tag('span', get_string('entryishidden','glossary'),
1231 array('class' => 'glossary-hidden-note'));
81bdc9e9 1232 }
b8340d19 1233
d0372ed6
HB
1234 if (has_capability('mod/glossary:approve', $context) && !$glossary->defaultapproval && $entry->approved) {
1235 $output = true;
1236 $return .= '<a class="action-icon" title="' . get_string('disapprove', 'glossary').
1237 '" href="approve.php?newstate=0&amp;eid='.$entry->id.'&amp;mode='.$mode.
1238 '&amp;hook='.urlencode($hook).'&amp;sesskey='.sesskey().
1239 '"><img src="'.$OUTPUT->pix_url('t/block').'" class="smallicon" alt="'.
1240 get_string('disapprove','glossary').$altsuffix.'" /></a>';
1241 }
1242
6708a1f5
SH
1243 $iscurrentuser = ($entry->userid == $USER->id);
1244
1245 if (has_capability('mod/glossary:manageentries', $context) or (isloggedin() and has_capability('mod/glossary:write', $context) and $iscurrentuser)) {
81bdc9e9 1246 // only teachers can export entries so check it out
0468976c 1247 if (has_capability('mod/glossary:export', $context) and !$ismainglossary and !$importedentry) {
ae8c3566 1248 $mainglossary = $DB->get_record('glossary', array('mainglossary'=>1,'course'=>$course->id));
81bdc9e9 1249 if ( $mainglossary ) { // if there is a main glossary defined, allow to export the current entry
36ce6ea2 1250 $output = true;
851d3b7a 1251 $return .= '<a class="action-icon" title="'.get_string('exporttomainglossary','glossary') . '" href="exportentry.php?id='.$entry->id.'&amp;prevmode='.$mode.'&amp;hook='.urlencode($hook).'"><img src="'.$OUTPUT->pix_url('export', 'glossary').'" class="smallicon" alt="'.get_string('exporttomainglossary','glossary').$altsuffix.'" /></a>';
81bdc9e9 1252 }
1253 }
1254
1255 if ( $entry->sourceglossaryid ) {
b5d0cafc 1256 $icon = $OUTPUT->pix_url('minus', 'glossary'); // graphical metaphor (minus) for deleting an imported entry
81bdc9e9 1257 } else {
b5d0cafc 1258 $icon = $OUTPUT->pix_url('t/delete');
81bdc9e9 1259 }
1260
ff1e2621 1261 //Decide if an entry is editable:
1262 // -It isn't a imported entry (so nobody can edit a imported (from secondary to main) entry)) and
1263 // -The user is teacher or he is a student with time permissions (edit period or editalways defined).
516c7276 1264 $ineditperiod = ((time() - $entry->timecreated < $CFG->maxeditingtime) || $glossary->editalways);
6cb34d44 1265 if ( !$importedentry and (has_capability('mod/glossary:manageentries', $context) or ($entry->userid == $USER->id and ($ineditperiod and has_capability('mod/glossary:write', $context))))) {
36ce6ea2 1266 $output = true;
fc5e0844 1267 $return .= "<a class='action-icon' title=\"" . get_string("delete") . "\" href=\"deleteentry.php?id=$cm->id&amp;mode=delete&amp;entry=$entry->id&amp;prevmode=$mode&amp;hook=".urlencode($hook)."\"><img src=\"";
81bdc9e9 1268 $return .= $icon;
fc5e0844 1269 $return .= "\" class=\"smallicon\" alt=\"" . get_string("delete") .$altsuffix."\" /></a>";
a02c77dc 1270
fc5e0844 1271 $return .= "<a class='action-icon' title=\"" . get_string("edit") . "\" href=\"edit.php?cmid=$cm->id&amp;id=$entry->id&amp;mode=$mode&amp;hook=".urlencode($hook)."\"><img src=\"" . $OUTPUT->pix_url('t/edit') . "\" class=\"smallicon\" alt=\"" . get_string("edit") .$altsuffix. "\" /></a>";
81bdc9e9 1272 } elseif ( $importedentry ) {
fc5e0844 1273 $return .= "<font size=\"-1\">" . get_string("exportedentry","glossary") . "</font>";
81bdc9e9 1274 }
1275 }
6708a1f5 1276 if (!empty($CFG->enableportfolios) && (has_capability('mod/glossary:exportentry', $context) || ($iscurrentuser && has_capability('mod/glossary:exportownentry', $context)))) {
24ba58ee 1277 require_once($CFG->libdir . '/portfoliolib.php');
0d06b6fd 1278 $button = new portfolio_add_button();
37743241 1279 $button->set_callback_options('glossary_entry_portfolio_caller', array('id' => $cm->id, 'entryid' => $entry->id), 'mod_glossary');
59dd457e
PL
1280
1281 $filecontext = $context;
1282 if ($entry->sourceglossaryid == $cm->instance) {
1283 if ($maincm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
e0a91e11 1284 $filecontext = context_module::instance($maincm->id);
59dd457e
PL
1285 }
1286 }
1287 $fs = get_file_storage();
2403ea41
AD
1288 if ($files = $fs->get_area_files($filecontext->id, 'mod_glossary', 'attachment', $entry->id, "timemodified", false)
1289 || $files = $fs->get_area_files($filecontext->id, 'mod_glossary', 'entry', $entry->id, "timemodified", false)) {
1290
59dd457e 1291 $button->set_formats(PORTFOLIO_FORMAT_RICHHTML);
24ba58ee
PL
1292 } else {
1293 $button->set_formats(PORTFOLIO_FORMAT_PLAINHTML);
59dd457e
PL
1294 }
1295
0d06b6fd 1296 $return .= $button->to_html(PORTFOLIO_ADD_ICON_LINK);
49a12552 1297 }
9362b9b6 1298 $return .= '</span>';
a02c77dc 1299
6708a1f5
SH
1300 if (!empty($CFG->usecomments) && has_capability('mod/glossary:comment', $context) and $glossary->allowcomments) {
1301 require_once($CFG->dirroot . '/comment/lib.php');
1302 $cmt = new stdClass();
1303 $cmt->component = 'mod_glossary';
1304 $cmt->context = $context;
1305 $cmt->course = $course;
1306 $cmt->cm = $cm;
1307 $cmt->area = 'glossary_entry';
1308 $cmt->itemid = $entry->id;
1309 $cmt->showcount = true;
1310 $comment = new comment($cmt);
1311 $return .= '<div>'.$comment->output(true).'</div>';
c8092ea5 1312 $output = true;
c8092ea5
DC
1313 }
1314
36ce6ea2 1315 //If we haven't calculated any REAL thing, delete result ($return)
1316 if (!$output) {
1317 $return = '';
1318 }
1319 //Print or get
1ac87c73 1320 if ($type == 'print') {
81bdc9e9 1321 echo $return;
1322 } else {
1323 return $return;
a0d1e2bb 1324 }
1325}
1326
e121db76 1327/**
1328 * @param object $course
1329 * @param object $cm
1330 * @param object $glossary
1331 * @param object $entry
1332 * @param string $mode
1333 * @param object $hook
1334 * @param bool $printicons
e121db76 1335 * @param bool $aliases
63e87951 1336 * @return void
e121db76 1337 */
63e87951 1338function glossary_print_entry_lower_section($course, $cm, $glossary, $entry, $mode, $hook, $printicons, $aliases=true) {
26983d03 1339 if ($aliases) {
9362b9b6 1340 $aliases = glossary_print_entry_aliases($course, $cm, $glossary, $entry, $mode, $hook,'html');
26983d03 1341 }
9362b9b6 1342 $icons = '';
cbc2b5df 1343 if ($printicons) {
9362b9b6 1344 $icons = glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode, $hook,'html');
1ac87c73 1345 }
15dd3edb 1346 if ($aliases || $icons || !empty($entry->rating)) {
9362b9b6 1347 echo '<table>';
a359c29b 1348 if ( $aliases ) {
9362b9b6 1349 echo '<tr valign="top"><td class="aliases">' .
656eb813
RW
1350 '<label for="keyword">' . get_string('aliases','glossary').': </label>' .
1351 $aliases . '</td></tr>';
a359c29b 1352 }
1353 if ($icons) {
9362b9b6 1354 echo '<tr valign="top"><td class="icons">'.$icons.'</td></tr>';
a359c29b 1355 }
198ff498 1356 if (!empty($entry->rating)) {
9362b9b6 1357 echo '<tr valign="top"><td class="ratings">';
63e87951 1358 glossary_print_entry_ratings($course, $entry);
a359c29b 1359 echo '</td></tr>';
1360 }
1361 echo '</table>';
81bdc9e9 1362 }
1363}
1364
e121db76 1365/**
0181759e
AN
1366 * Print the list of attachments for this glossary entry
1367 *
1368 * @param object $entry
1369 * @param object $cm The coursemodule
1370 * @param string $format The format for this view (html, or text)
1371 * @param string $unused1 This parameter is no longer used
1372 * @param string $unused2 This parameter is no longer used
e121db76 1373 */
0181759e
AN
1374function glossary_print_entry_attachment($entry, $cm, $format = null, $unused1 = null, $unused2 = null) {
1375 // Valid format values: html: The HTML link for the attachment is an icon; and
1376 // text: The HTML link for the attachment is text.
1d9ddaaf 1377 if ($entry->attachment) {
0181759e 1378 echo '<div class="attachments">';
1fad754c 1379 echo glossary_print_attachments($entry, $cm, $format);
0181759e
AN
1380 echo '</div>';
1381 }
1382 if ($unused1) {
1383 debugging('The align parameter is deprecated, please use appropriate CSS instead', DEBUG_DEVELOPER);
1384 }
1385 if ($unused2 !== null) {
1386 debugging('The insidetable parameter is deprecated, please use appropriate CSS instead', DEBUG_DEVELOPER);
1d9ddaaf 1387 }
1388}
1389
e121db76 1390/**
1391 * @global object
1392 * @param object $cm
1393 * @param object $entry
1394 * @param string $mode
1395 * @param string $align
1396 * @param bool $insidetable
1397 */
cbc2b5df 1398function glossary_print_entry_approval($cm, $entry, $mode, $align="right", $insidetable=true) {
f2a1963c 1399 global $CFG, $OUTPUT;
cff611fc 1400
cbc2b5df 1401 if ($mode == 'approval' and !$entry->approved) {
77495793 1402 if ($insidetable) {
a8466100 1403 echo '<table class="glossaryapproval" align="'.$align.'"><tr><td align="'.$align.'">';
77495793 1404 }
851d3b7a
FM
1405 echo $OUTPUT->action_icon(
1406 new moodle_url('approve.php', array('eid' => $entry->id, 'mode' => $mode, 'sesskey' => sesskey())),
1407 new pix_icon('t/approve', get_string('approve','glossary'), '',
1408 array('class' => 'iconsmall', 'align' => $align))
1409 );
77495793 1410 if ($insidetable) {
a8466100 1411 echo '</td></tr></table>';
77495793 1412 }
1d9ddaaf 1413 }
1414}
07842023 1415
e121db76 1416/**
1417 * It returns all entries from all glossaries that matches the specified criteria
1418 * within a given $course. It performs an $extended search if necessary.
1419 * It restrict the search to only one $glossary if the $glossary parameter is set.
1420 *
1421 * @global object
1422 * @global object
1423 * @param object $course
1424 * @param array $searchterms
1425 * @param int $extended
1426 * @param object $glossary
1427 * @return array
1428 */
c80828fe 1429function glossary_search($course, $searchterms, $extended = 0, $glossary = NULL) {
ae8c3566 1430 global $CFG, $DB;
07842023 1431
c80828fe 1432 if ( !$glossary ) {
ae8c3566 1433 if ( $glossaries = $DB->get_records("glossary", array("course"=>$course->id)) ) {
c80828fe 1434 $glos = "";
1435 foreach ( $glossaries as $glossary ) {
1436 $glos .= "$glossary->id,";
1437 }
9cae3799 1438 $glos = substr($glos,0,-1);
c80828fe 1439 }
1440 } else {
1441 $glos = $glossary->id;
1442 }
a02c77dc 1443
e0a91e11 1444 if (!has_capability('mod/glossary:manageentries', context_course::instance($glossary->course))) {
ae8c3566 1445 $glossarymodule = $DB->get_record("modules", array("name"=>"glossary"));
6a22879b 1446 $onlyvisible = " AND g.id = cm.instance AND cm.visible = 1 AND cm.module = $glossarymodule->id";
ae8c3566 1447 $onlyvisibletable = ", {course_modules} cm";
07842023 1448 } else {
1449
1450 $onlyvisible = "";
1451 $onlyvisibletable = "";
1452 }
1453
ae8c3566 1454 if ($DB->sql_regex_supported()) {
1455 $REGEXP = $DB->sql_regex(true);
1456 $NOTREGEXP = $DB->sql_regex(false);
a02c77dc 1457 }
07842023 1458
ae8c3566 1459 $searchcond = array();
1460 $params = array();
1461 $i = 0;
1462
1463 $concat = $DB->sql_concat('e.concept', "' '", 'e.definition');
07842023 1464
1465
1466 foreach ($searchterms as $searchterm) {
ae8c3566 1467 $i++;
1468
e99cfeb8 1469 $NOT = false; /// Initially we aren't going to perform NOT LIKE searches, only MSSQL and Oracle
ae8c3566 1470 /// will use it to simulate the "-" operator with LIKE clause
07842023 1471
6f4bdb9c 1472 /// Under Oracle and MSSQL, trim the + and - operators and perform
ae8c3566 1473 /// simpler LIKE (or NOT LIKE) queries
1474 if (!$DB->sql_regex_supported()) {
1475 if (substr($searchterm, 0, 1) == '-') {
e99cfeb8 1476 $NOT = true;
ae8c3566 1477 }
6f4bdb9c 1478 $searchterm = trim($searchterm, '+-');
1479 }
1480
ae8c3566 1481 // TODO: +- may not work for non latin languages
1482
1483 if (substr($searchterm,0,1) == '+') {
1484 $searchterm = trim($searchterm, '+-');
1485 $searchterm = preg_quote($searchterm, '|');
1486 $searchcond[] = "$concat $REGEXP :ss$i";
1487 $params['ss'.$i] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)";
1488
07842023 1489 } else if (substr($searchterm,0,1) == "-") {
ae8c3566 1490 $searchterm = trim($searchterm, '+-');
1491 $searchterm = preg_quote($searchterm, '|');
1492 $searchcond[] = "$concat $NOTREGEXP :ss$i";
1493 $params['ss'.$i] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)";
1494
07842023 1495 } else {
47586394 1496 $searchcond[] = $DB->sql_like($concat, ":ss$i", false, true, $NOT);
ae8c3566 1497 $params['ss'.$i] = "%$searchterm%";
07842023 1498 }
1499 }
1500
ae8c3566 1501 if (empty($searchcond)) {
1502 $totalcount = 0;
1503 return array();
1504 }
1505
1506 $searchcond = implode(" AND ", $searchcond);
07842023 1507
ae8c3566 1508 $sql = "SELECT e.*
1509 FROM {glossary_entries} e, {glossary} g $onlyvisibletable
1510 WHERE $searchcond
ad58adac 1511 AND (e.glossaryid = g.id or e.sourceglossaryid = g.id) $onlyvisible
ae8c3566 1512 AND g.id IN ($glos) AND e.approved <> 0";
07842023 1513
ae8c3566 1514 return $DB->get_records_sql($sql, $params);
07842023 1515}
1516
e121db76 1517/**
1518 * @global object
1519 * @param array $searchterms
1520 * @param object $glossary
1521 * @param bool $extended
1522 * @return array
1523 */
c80828fe 1524function glossary_search_entries($searchterms, $glossary, $extended) {
ae8c3566 1525 global $DB;
1526
1527 $course = $DB->get_record("course", array("id"=>$glossary->course));
c80828fe 1528 return glossary_search($course,$searchterms,$extended,$glossary);
1529}
1530
49bcd737 1531/**
1532 * if return=html, then return a html string.
1533 * if return=text, then return a text-only string.
1534 * otherwise, print HTML for non-images, and return image HTML
1535 * if attachment is an image, $align set its aligment.
e121db76 1536 *
1537 * @global object
1538 * @global object
49bcd737 1539 * @param object $entry
1540 * @param object $cm
1541 * @param string $type html, txt, empty
1fad754c 1542 * @param string $unused This parameter is no longer used
e121db76 1543 * @return string image string or nothing depending on $type param
49bcd737 1544 */
1fad754c 1545function glossary_print_attachments($entry, $cm, $type=NULL, $unused = null) {
d436d197 1546 global $CFG, $DB, $OUTPUT;
e179048e 1547
703a2c2e 1548 if (!$context = context_module::instance($cm->id, IGNORE_MISSING)) {
49bcd737 1549 return '';
e179048e 1550 }
a02c77dc 1551
ca3d4806
SM
1552 if ($entry->sourceglossaryid == $cm->instance) {
1553 if (!$maincm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
49bcd737 1554 return '';
a02c77dc 1555 }
e0a91e11 1556 $filecontext = context_module::instance($maincm->id);
e179048e 1557
49bcd737 1558 } else {
1559 $filecontext = $context;
1560 }
e179048e 1561
49bcd737 1562 $strattachment = get_string('attachment', 'glossary');
e179048e 1563
49bcd737 1564 $fs = get_file_storage();
e179048e 1565
49bcd737 1566 $imagereturn = '';
1567 $output = '';
e179048e 1568
64f93798 1569 if ($files = $fs->get_area_files($filecontext->id, 'mod_glossary', 'attachment', $entry->id, "timemodified", false)) {
49bcd737 1570 foreach ($files as $file) {
1571 $filename = $file->get_filename();
1572 $mimetype = $file->get_mimetype();
559276b1 1573 $iconimage = $OUTPUT->pix_icon(file_file_icon($file), get_mimetype_description($file), 'moodle', array('class' => 'icon'));
64f93798 1574 $path = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$context->id.'/mod_glossary/attachment/'.$entry->id.'/'.$filename);
e179048e 1575
49bcd737 1576 if ($type == 'html') {
1577 $output .= "<a href=\"$path\">$iconimage</a> ";
1578 $output .= "<a href=\"$path\">".s($filename)."</a>";
1579 $output .= "<br />";
18b8fbfa 1580
49bcd737 1581 } else if ($type == 'text') {
1582 $output .= "$strattachment ".s($filename).":\n$path\n";
e179048e 1583
49bcd737 1584 } else {
1585 if (in_array($mimetype, array('image/gif', 'image/jpeg', 'image/png'))) {
1586 // Image attachments don't get printed as links
1587 $imagereturn .= "<br /><img src=\"$path\" alt=\"\" />";
1588 } else {
1589 $output .= "<a href=\"$path\">$iconimage</a> ";
35716b86 1590 $output .= format_text("<a href=\"$path\">".s($filename)."</a>", FORMAT_HTML, array('context'=>$context));
49bcd737 1591 $output .= '<br />';
18b8fbfa 1592 }
e179048e 1593 }
1594 }
1595 }
49bcd737 1596
1597 if ($type) {
1598 return $output;
1599 } else {
1600 echo $output;
1601 return $imagereturn;
1602 }
e179048e 1603}
1604
7978d5dc
DM
1605////////////////////////////////////////////////////////////////////////////////
1606// File API //
1607////////////////////////////////////////////////////////////////////////////////
1608
aa9bcfcd 1609/**
1610 * Lists all browsable file areas
e121db76 1611 *
d2b7803e
DC
1612 * @package mod_glossary
1613 * @category files
1614 * @param stdClass $course course object
1615 * @param stdClass $cm course module object
1616 * @param stdClass $context context object
e121db76 1617 * @return array
aa9bcfcd 1618 */
1619function glossary_get_file_areas($course, $cm, $context) {
7978d5dc
DM
1620 return array(
1621 'attachment' => get_string('areaattachment', 'mod_glossary'),
1622 'entry' => get_string('areaentry', 'mod_glossary'),
1623 );
aa9bcfcd 1624}
1625
00ecac72
MG
1626/**
1627 * File browsing support for glossary module.
1628 *
1629 * @param file_browser $browser
1630 * @param array $areas
1631 * @param stdClass $course
1632 * @param cm_info $cm
1633 * @param context $context
1634 * @param string $filearea
1635 * @param int $itemid
1636 * @param string $filepath
1637 * @param string $filename
1638 * @return file_info_stored file_info_stored instance or null if not found
1639 */
6b8b0b2e 1640function glossary_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
35ca63c1 1641 global $CFG, $DB, $USER;
00ecac72
MG
1642
1643 if ($context->contextlevel != CONTEXT_MODULE) {
1644 return null;
1645 }
1646
7978d5dc
DM
1647 if (!isset($areas[$filearea])) {
1648 return null;
1649 }
00ecac72 1650
7978d5dc
DM
1651 if (is_null($itemid)) {
1652 require_once($CFG->dirroot.'/mod/glossary/locallib.php');
1653 return new glossary_file_info_container($browser, $course, $cm, $context, $areas, $filearea);
1654 }
00ecac72 1655
7978d5dc
DM
1656 if (!$entry = $DB->get_record('glossary_entries', array('id' => $itemid))) {
1657 return null;
1658 }
00ecac72 1659
7978d5dc
DM
1660 if (!$glossary = $DB->get_record('glossary', array('id' => $cm->instance))) {
1661 return null;
1662 }
1663
1664 if ($glossary->defaultapproval and !$entry->approved and !has_capability('mod/glossary:approve', $context)) {
1665 return null;
1666 }
1667
1668 // this trickery here is because we need to support source glossary access
1669 if ($entry->glossaryid == $cm->instance) {
1670 $filecontext = $context;
1671 } else if ($entry->sourceglossaryid == $cm->instance) {
1672 if (!$maincm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
00ecac72
MG
1673 return null;
1674 }
e0a91e11 1675 $filecontext = context_module::instance($maincm->id);
7978d5dc
DM
1676 } else {
1677 return null;
1678 }
1679
1680 $fs = get_file_storage();
1681 $filepath = is_null($filepath) ? '/' : $filepath;
1682 $filename = is_null($filename) ? '.' : $filename;
1683 if (!($storedfile = $fs->get_file($filecontext->id, 'mod_glossary', $filearea, $itemid, $filepath, $filename))) {
1684 return null;
00ecac72 1685 }
35ca63c1
AG
1686
1687 // Checks to see if the user can manage files or is the owner.
1688 // TODO MDL-33805 - Do not use userid here and move the capability check above.
1689 if (!has_capability('moodle/course:managefiles', $context) && $storedfile->get_userid() != $USER->id) {
1690 return null;
1691 }
1692
7978d5dc 1693 $urlbase = $CFG->wwwroot.'/pluginfile.php';
00ecac72 1694
7978d5dc 1695 return new file_info_stored($browser, $filecontext, $storedfile, $urlbase, s($entry->concept), true, true, false, false);
00ecac72
MG
1696}
1697
49bcd737 1698/**
1699 * Serves the glossary attachments. Implements needed access control ;-)
e121db76 1700 *
d2b7803e
DC
1701 * @package mod_glossary
1702 * @category files
1703 * @param stdClass $course course object
1704 * @param stdClass $cm course module object
1705 * @param stdClsss $context context object
1706 * @param string $filearea file area
1707 * @param array $args extra arguments
1708 * @param bool $forcedownload whether or not force download
261cbbac 1709 * @param array $options additional options affecting the file serving
86900a93 1710 * @return bool false if file not found, does not return if found - justsend the file
49bcd737 1711 */
261cbbac 1712function glossary_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
49bcd737 1713 global $CFG, $DB;
a02c77dc 1714
64f93798 1715 if ($context->contextlevel != CONTEXT_MODULE) {
49bcd737 1716 return false;
1717 }
e179048e 1718
64f93798 1719 require_course_login($course, true, $cm);
49bcd737 1720
64f93798
PS
1721 if ($filearea === 'attachment' or $filearea === 'entry') {
1722 $entryid = (int)array_shift($args);
0a8a7b6c 1723
1724 require_course_login($course, true, $cm);
1adbd2c3 1725
aa9bcfcd 1726 if (!$entry = $DB->get_record('glossary_entries', array('id'=>$entryid))) {
1727 return false;
e179048e 1728 }
49bcd737 1729
64f93798 1730 if (!$glossary = $DB->get_record('glossary', array('id'=>$cm->instance))) {
aa9bcfcd 1731 return false;
1732 }
e179048e 1733
aa9bcfcd 1734 if ($glossary->defaultapproval and !$entry->approved and !has_capability('mod/glossary:approve', $context)) {
1735 return false;
1736 }
1737
64f93798
PS
1738 // this trickery here is because we need to support source glossary access
1739
1740 if ($entry->glossaryid == $cm->instance) {
aa9bcfcd 1741 $filecontext = $context;
1742
64f93798 1743 } else if ($entry->sourceglossaryid == $cm->instance) {
aa9bcfcd 1744 if (!$maincm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
64f93798 1745 return false;
aa9bcfcd 1746 }
e0a91e11 1747 $filecontext = context_module::instance($maincm->id);
aa9bcfcd 1748
1749 } else {
1750 return false;
1751 }
1752
64f93798
PS
1753 $relativepath = implode('/', $args);
1754 $fullpath = "/$filecontext->id/mod_glossary/$filearea/$entryid/$relativepath";
aa9bcfcd 1755
1756 $fs = get_file_storage();
1757 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
1758 return false;
1759 }
1760
1761 // finally send the file
261cbbac 1762 send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
1ca1c8f8
PS
1763
1764 } else if ($filearea === 'export') {
1765 require_login($course, false, $cm);
1766 require_capability('mod/glossary:export', $context);
1767
1768 if (!$glossary = $DB->get_record('glossary', array('id'=>$cm->instance))) {
1769 return false;
1770 }
1771
1772 $cat = array_shift($args);
1773 $cat = clean_param($cat, PARAM_ALPHANUM);
1774
1775 $filename = clean_filename(strip_tags(format_string($glossary->name)).'.xml');
1776 $content = glossary_generate_export_file($glossary, NULL, $cat);
1777
1778 send_file($content, $filename, 0, 0, true, true);
e179048e 1779 }
1780
aa9bcfcd 1781 return false;
e179048e 1782}
1783
e121db76 1784/**
1785 *
1786 */
ad58adac 1787function glossary_print_tabbed_table_end() {
9ca8cc08 1788 echo "</div></div>";
06d94a52 1789}
1790
e121db76 1791/**
1792 * @param object $cm
1793 * @param object $glossary
1794 * @param string $mode
1795 * @param string $hook
1796 * @param string $sortkey
1797 * @param string $sortorder
1798 */
1ac87c73 1799function glossary_print_approval_menu($cm, $glossary,$mode, $hook, $sortkey = '', $sortorder = '') {
a359c29b 1800 if ($glossary->showalphabet) {
7a3ec1af 1801 echo '<div class="glossaryexplain">' . get_string("explainalphabet","glossary") . '</div><br />';
677038ee 1802 }
1ac87c73 1803 glossary_print_special_links($cm, $glossary, $mode, $hook);
c76e673a 1804
c4a35419 1805 glossary_print_alphabet_links($cm, $glossary, $mode, $hook,$sortkey, $sortorder);
c76e673a 1806
1ac87c73 1807 glossary_print_all_links($cm, $glossary, $mode, $hook);
894ff63f 1808
db87439a 1809 glossary_print_sorting_links($cm, $mode, 'CREATION', 'asc');
c76e673a 1810}
e121db76 1811/**
1812 * @param object $cm
1813 * @param object $glossary
1814 * @param string $hook
1815 * @param string $sortkey
1816 * @param string $sortorder
1817 */
1ac87c73 1818function glossary_print_import_menu($cm, $glossary, $mode, $hook, $sortkey='', $sortorder = '') {
7a3ec1af 1819 echo '<div class="glossaryexplain">' . get_string("explainimport","glossary") . '</div>';
748b1932 1820}
1821
e121db76 1822/**
1823 * @param object $cm
1824 * @param object $glossary
1825 * @param string $hook
1826 * @param string $sortkey
1827 * @param string $sortorder
1828 */
1ac87c73 1829function glossary_print_export_menu($cm, $glossary, $mode, $hook, $sortkey='', $sortorder = '') {
7a3ec1af 1830 echo '<div class="glossaryexplain">' . get_string("explainexport","glossary") . '</div>';
748b1932 1831}
e121db76 1832/**
1833 * @param object $cm
1834 * @param object $glossary
1835 * @param string $hook
1836 * @param string $sortkey
1837 * @param string $sortorder
1838 */
1ac87c73 1839function glossary_print_alphabet_menu($cm, $glossary, $mode, $hook, $sortkey='', $sortorder = '') {
1840 if ( $mode != 'date' ) {
a359c29b 1841 if ($glossary->showalphabet) {
7a3ec1af 1842 echo '<div class="glossaryexplain">' . get_string("explainalphabet","glossary") . '</div><br />';
c197e607 1843 }
c76e673a 1844
1ac87c73 1845 glossary_print_special_links($cm, $glossary, $mode, $hook);
c76e673a 1846
c4a35419 1847 glossary_print_alphabet_links($cm, $glossary, $mode, $hook, $sortkey, $sortorder);
c197e607 1848
1ac87c73 1849 glossary_print_all_links($cm, $glossary, $mode, $hook);
c197e607 1850 } else {
1ac87c73 1851 glossary_print_sorting_links($cm, $mode, $sortkey,$sortorder);
1852 }
1853}
1854
e121db76 1855/**
1856 * @param object $cm
1857 * @param object $glossary
1858 * @param string $hook
1859 * @param string $sortkey
1860 * @param string $sortorder
1861 */
1ac87c73 1862function glossary_print_author_menu($cm, $glossary,$mode, $hook, $sortkey = '', $sortorder = '') {
a359c29b 1863 if ($glossary->showalphabet) {
7a3ec1af 1864 echo '<div class="glossaryexplain">' . get_string("explainalphabet","glossary") . '</div><br />';
c197e607 1865 }
1ac87c73 1866
c4a35419 1867 glossary_print_alphabet_links($cm, $glossary, $mode, $hook, $sortkey, $sortorder);
1ac87c73 1868 glossary_print_all_links($cm, $glossary, $mode, $hook);
7a3ec1af 1869 glossary_print_sorting_links($cm, $mode, $sortkey,$sortorder);
c76e673a 1870}
1871
e121db76 1872/**
1873 * @global object
1874 * @global object
1875 * @param object $cm
1876 * @param object $glossary
1877 * @param string $hook
1878 * @param object $category
1879 */
1ac87c73 1880function glossary_print_categories_menu($cm, $glossary, $hook, $category) {
c9472f43 1881 global $CFG, $DB, $OUTPUT;
a02c77dc 1882
e0a91e11 1883 $context = context_module::instance($cm->id);
3a26f0ea 1884
bce3e3dc
EL
1885 // Prepare format_string/text options
1886 $fmtoptions = array(
1887 'context' => $context);
1888
41905731 1889 echo '<table border="0" width="100%">';
c197e607 1890 echo '<tr>';
c76e673a 1891
5bd76d7f 1892 echo '<td align="center" style="width:20%">';
0468976c 1893 if (has_capability('mod/glossary:managecategories', $context)) {
c76e673a 1894 $options['id'] = $cm->id;
1ac87c73 1895 $options['mode'] = 'cat';
1896 $options['hook'] = $hook;
5c2ed7e2 1897 echo $OUTPUT->single_button(new moodle_url("editcategories.php", $options), get_string("editcategories","glossary"), "get");
c76e673a 1898 }
c197e607 1899 echo '</td>';
c76e673a 1900
5bd76d7f 1901 echo '<td align="center" style="width:60%">';
c197e607 1902 echo '<b>';
c76e673a 1903
f8dab966 1904 $menu = array();
c76e673a 1905 $menu[GLOSSARY_SHOW_ALL_CATEGORIES] = get_string("allcategories","glossary");
1906 $menu[GLOSSARY_SHOW_NOT_CATEGORISED] = get_string("notcategorised","glossary");
677038ee 1907
ae8c3566 1908 $categories = $DB->get_records("glossary_categories", array("glossaryid"=>$glossary->id), "name ASC");
c197e607 1909 $selected = '';
c76e673a 1910 if ( $categories ) {
1911 foreach ($categories as $currentcategory) {
1912 $url = $currentcategory->id;
1913 if ( $category ) {
1914 if ($currentcategory->id == $category->id) {
1915 $selected = $url;
1916 }
1917 }
bce3e3dc 1918 $menu[$url] = format_string($currentcategory->name, true, $fmtoptions);
c76e673a 1919 }
1920 }
1921 if ( !$selected ) {
1922 $selected = GLOSSARY_SHOW_NOT_CATEGORISED;
1923 }
1924
1925 if ( $category ) {
bce3e3dc 1926 echo format_string($category->name, true, $fmtoptions);
c76e673a 1927 } else {
1ac87c73 1928 if ( $hook == GLOSSARY_SHOW_NOT_CATEGORISED ) {
c76e673a 1929
1930 echo get_string("entrieswithoutcategory","glossary");
1931 $selected = GLOSSARY_SHOW_NOT_CATEGORISED;
1932
1ac87c73 1933 } elseif ( $hook == GLOSSARY_SHOW_ALL_CATEGORIES ) {
c76e673a 1934
1935 echo get_string("allcategories","glossary");
1936 $selected = GLOSSARY_SHOW_ALL_CATEGORIES;
1937
1938 }
1939 }
c197e607 1940 echo '</b></td>';
5bd76d7f 1941 echo '<td align="center" style="width:20%">';
1adbd2c3 1942
f8dab966 1943 $select = new single_select(new moodle_url("/mod/glossary/view.php", array('id'=>$cm->id, 'mode'=>'cat')), 'hook', $menu, $selected, null, "catmenu");
656eb813 1944 $select->set_label(get_string('categories', 'glossary'), array('class' => 'accesshide'));
f8dab966 1945 echo $OUTPUT->render($select);
677038ee 1946
c197e607 1947 echo '</td>';
1948 echo '</tr>';
c76e673a 1949
c197e607 1950 echo '</table>';
c76e673a 1951}
1952
e121db76 1953/**
1954 * @global object
1955 * @param object $cm
1956 * @param object $glossary
1957 * @param string $mode
1958 * @param string $hook
1959 */
1ac87c73 1960function glossary_print_all_links($cm, $glossary, $mode, $hook) {
a02c77dc 1961global $CFG;
a359c29b 1962 if ( $glossary->showall) {
c76e673a 1963 $strallentries = get_string("allentries", "glossary");
1ac87c73 1964 if ( $hook == 'ALL' ) {
c76e673a 1965 echo "<b>$strallentries</b>";
1966 } else {
1967 $strexplainall = strip_tags(get_string("explainall","glossary"));
839f2456 1968 echo "<a title=\"$strexplainall\" href=\"$CFG->wwwroot/mod/glossary/view.php?id=$cm->id&amp;mode=$mode&amp;hook=ALL\">$strallentries</a>";
c76e673a 1969 }
1970 }
1971}
1972
e121db76 1973/**
1974 * @global object
1975 * @param object $cm
1976 * @param object $glossary
1977 * @param string $mode
1978 * @param string $hook
1979 */
1ac87c73 1980function glossary_print_special_links($cm, $glossary, $mode, $hook) {
c76e673a 1981global $CFG;
a359c29b 1982 if ( $glossary->showspecial) {
c76e673a 1983 $strspecial = get_string("special", "glossary");
1ac87c73 1984 if ( $hook == 'SPECIAL' ) {
677038ee 1985 echo "<b>$strspecial</b> | ";
1986 } else {
1987 $strexplainspecial = strip_tags(get_string("explainspecial","glossary"));
839f2456 1988 echo "<a title=\"$strexplainspecial\" href=\"$CFG->wwwroot/mod/glossary/view.php?id=$cm->id&amp;mode=$mode&amp;hook=SPECIAL\">$strspecial</a> | ";
677038ee 1989 }
914cb260 1990 }
c76e673a 1991}
677038ee 1992
e121db76 1993/**
1994 * @global object
1995 * @param object $glossary
1996 * @param string $mode
1997 * @param string $hook
1998 * @param string $sortkey
1999 * @param string $sortorder
2000 */
c4a35419 2001function glossary_print_alphabet_links($cm, $glossary, $mode, $hook, $sortkey, $sortorder) {
c76e673a 2002global $CFG;
a359c29b 2003 if ( $glossary->showalphabet) {
9b22ac0a 2004 $alphabet = explode(",", get_string('alphabet', 'langconfig'));
677038ee 2005 for ($i = 0; $i < count($alphabet); $i++) {
1ac87c73 2006 if ( $hook == $alphabet[$i] and $hook) {
677038ee 2007 echo "<b>$alphabet[$i]</b>";
2008 } else {
82015ed2 2009 echo "<a href=\"$CFG->wwwroot/mod/glossary/view.php?id=$cm->id&amp;mode=$mode&amp;hook=".urlencode($alphabet[$i])."&amp;sortkey=$sortkey&amp;sortorder=$sortorder\">$alphabet[$i]</a>";
677038ee 2010 }
4ce27469 2011 echo ' | ';
767a31c3 2012 }
677038ee 2013 }
c76e673a 2014}
2015
e121db76 2016/**
2017 * @global object
2018 * @param object $cm
2019 * @param string $mode
2020 * @param string $sortkey
2021 * @param string $sortorder
2022 */
1ac87c73 2023function glossary_print_sorting_links($cm, $mode, $sortkey = '',$sortorder = '') {
eaed2fd1 2024 global $CFG, $OUTPUT;
677038ee 2025
c4a35419 2026 $asc = get_string("ascending","glossary");
2027 $desc = get_string("descending","glossary");
2028 $bopen = '<b>';
2029 $bclose = '</b>';
a02c77dc 2030
c197e607 2031 $neworder = '';
468c120a 2032 $currentorder = '';
2033 $currentsort = '';
677038ee 2034 if ( $sortorder ) {
c197e607 2035 if ( $sortorder == 'asc' ) {
468c120a 2036 $currentorder = $asc;
839f2456 2037 $neworder = '&amp;sortorder=desc';
468c120a 2038 $newordertitle = get_string('changeto', 'glossary', $desc);
677038ee 2039 } else {
468c120a 2040 $currentorder = $desc;
839f2456 2041 $neworder = '&amp;sortorder=asc';
468c120a 2042 $newordertitle = get_string('changeto', 'glossary', $asc);
677038ee 2043 }
b5d0cafc 2044 $icon = " <img src=\"".$OUTPUT->pix_url($sortorder, 'glossary')."\" class=\"icon\" alt=\"$newordertitle\" />";
677038ee 2045 } else {
c4a35419 2046 if ( $sortkey != 'CREATION' and $sortkey != 'UPDATE' and
2047 $sortkey != 'FIRSTNAME' and $sortkey != 'LASTNAME' ) {
677038ee 2048 $icon = "";
c4a35419 2049 $newordertitle = $asc;
677038ee 2050 } else {
c4a35419 2051 $newordertitle = $desc;
839f2456 2052 $neworder = '&amp;sortorder=desc';
b5d0cafc 2053 $icon = ' <img src="'.$OUTPUT->pix_url('asc', 'glossary').'" class="icon" alt="'.$newordertitle.'" />';
677038ee 2054 }
2055 }
c4a35419 2056 $ficon = '';
2057 $fneworder = '';
2058 $fbtag = '';
2059 $fendbtag = '';
2060
2061 $sicon = '';
2062 $sneworder = '';
ae078733 2063
2064 $sbtag = '';
2065 $fbtag = '';
2066 $fendbtag = '';
2067 $sendbtag = '';
2068
c4a35419 2069 $sendbtag = '';
2070
2071 if ( $sortkey == 'CREATION' or $sortkey == 'FIRSTNAME' ) {
2072 $ficon = $icon;
2073 $fneworder = $neworder;
2074 $fordertitle = $newordertitle;
2075 $sordertitle = $asc;
2076 $fbtag = $bopen;
2077 $fendbtag = $bclose;
2078 } elseif ($sortkey == 'UPDATE' or $sortkey == 'LASTNAME') {
2079 $sicon = $icon;
2080 $sneworder = $neworder;
2081 $fordertitle = $asc;
2082 $sordertitle = $newordertitle;
2083 $sbtag = $bopen;
2084 $sendbtag = $bclose;
677038ee 2085 } else {
c4a35419 2086 $fordertitle = $asc;
2087 $sordertitle = $asc;
677038ee 2088 }
c4a35419 2089
2090 if ( $sortkey == 'CREATION' or $sortkey == 'UPDATE' ) {
2091 $forder = 'CREATION';
2092 $sorder = 'UPDATE';
2093 $fsort = get_string("sortbycreation", "glossary");
2094 $ssort = get_string("sortbylastupdate", "glossary");
2095
468c120a 2096 $currentsort = $fsort;
2097 if ($sortkey == 'UPDATE') {
2098 $currentsort = $ssort;
2099 }
c4a35419 2100 $sort = get_string("sortchronogically", "glossary");
2101 } elseif ( $sortkey == 'FIRSTNAME' or $sortkey == 'LASTNAME') {
2102 $forder = 'FIRSTNAME';
2103 $sorder = 'LASTNAME';
2104 $fsort = get_string("firstname");
2105 $ssort = get_string("lastname");
2106
468c120a 2107 $currentsort = $fsort;
2108 if ($sortkey == 'LASTNAME') {
2109 $currentsort = $ssort;
2110 }
c4a35419 2111 $sort = get_string("sortby", "glossary");
2112 }
468c120a 2113 $current = '<span class="accesshide">'.get_string('current', 'glossary', "$currentsort $currentorder").'</span>';
2114 echo "<br />$current $sort: $sbtag<a title=\"$ssort $sordertitle\" href=\"$CFG->wwwroot/mod/glossary/view.php?id=$cm->id&amp;sortkey=$sorder$sneworder&amp;mode=$mode\">$ssort$sicon</a>$sendbtag | ".
839f2456 2115 "$fbtag<a title=\"$fsort $fordertitle\" href=\"$CFG->wwwroot/mod/glossary/view.php?id=$cm->id&amp;sortkey=$forder$fneworder&amp;mode=$mode\">$fsort$ficon</a>$fendbtag<br />";
fb443f1a 2116}
ad58adac 2117
e121db76 2118/**
2119 *
2120 * @param object $entry0
2121 * @param object $entry1
2122 * @return int [-1 | 0 | 1]
2123 */
ad58adac 2124function glossary_sort_entries ( $entry0, $entry1 ) {
a02c77dc 2125
2f1e464a 2126 if ( core_text::strtolower(ltrim($entry0->concept)) < core_text::strtolower(ltrim($entry1->concept)) ) {
ad58adac 2127 return -1;
2f1e464a 2128 } elseif ( core_text::strtolower(ltrim($entry0->concept)) > core_text::strtolower(ltrim($entry1->concept)) ) {
ad58adac 2129 return 1;
2130 } else {
2131 return 0;
2132 }
2133}
2134
ed0201dd 2135
e121db76 2136/**
2137 * @global object
2138 * @global object
2139 * @global object
2140 * @param object $course
2141 * @param object $entry
e121db76 2142 * @return bool
2143 */
63e87951 2144function glossary_print_entry_ratings($course, $entry) {
63e87951
AD
2145 global $OUTPUT;
2146 if( !empty($entry->rating) ){
2147 echo $OUTPUT->render($entry->rating);
2148 }
63dd5fb2 2149}
2150
e121db76 2151/**
2152 *
2153 * @global object
2154 * @global object
2155 * @global object
2156 * @param int $courseid
2157 * @param array $entries
2158 * @param int $displayformat
2159 */
b1918034 2160function glossary_print_dynaentry($courseid, $entries, $displayformat = -1) {
ae8c3566 2161 global $USER,$CFG, $DB;
cca6f7f1 2162
36a2b6bd 2163 echo '<div class="boxaligncenter">';
a8466100 2164 echo '<table class="glossarypopup" cellspacing="0"><tr>';
2165 echo '<td>';
1d9ddaaf 2166 if ( $entries ) {
2167 foreach ( $entries as $entry ) {
ae8c3566 2168 if (! $glossary = $DB->get_record('glossary', array('id'=>$entry->glossaryid))) {
5973a4c4 2169 print_error('invalidid', 'glossary');
cca6f7f1 2170 }
ae8c3566 2171 if (! $course = $DB->get_record('course', array('id'=>$glossary->course))) {
5973a4c4 2172 print_error('coursemisconf');
1d9ddaaf 2173 }
a8466100 2174 if (!$cm = get_coursemodule_from_instance('glossary', $entry->glossaryid, $glossary->course) ) {
5973a4c4 2175 print_error('invalidid', 'glossary');
1d9ddaaf 2176 }
1f63b7c6 2177
2178 //If displayformat is present, override glossary->displayformat
a359c29b 2179 if ($displayformat < 0) {
1f63b7c6 2180 $dp = $glossary->displayformat;
a359c29b 2181 } else {
1f63b7c6 2182 $dp = $displayformat;
2183 }
2184
a359c29b 2185 //Get popupformatname
ae8c3566 2186 $format = $DB->get_record('glossary_formats', array('name'=>$dp));
a359c29b 2187 $displayformat = $format->popupformatname;
2188
2189 //Check displayformat variable and set to default if necessary
2190 if (!$displayformat) {
2191 $displayformat = 'dictionary';
584dcac9 2192 }
1f63b7c6 2193
a359c29b 2194 $formatfile = $CFG->dirroot.'/mod/glossary/formats/'.$displayformat.'/'.$displayformat.'_format.php';
2195 $functionname = 'glossary_show_entry_'.$displayformat;
2196
2197 if (file_exists($formatfile)) {
2198 include_once($formatfile);
2199 if (function_exists($functionname)) {
2200 $functionname($course, $cm, $glossary, $entry,'','','','');
2201 }
2202 }
cca6f7f1 2203 }
cca6f7f1 2204 }
a8466100 2205 echo '</td>';
36a2b6bd 2206 echo '</tr></table></div>';
1d9ddaaf 2207}
4f4ca7b5 2208
e121db76 2209/**
2210 *
2211 * @global object
2212 * @param array $entries
2213 * @param array $aliases
2214 * @param array $categories
2215 * @return string
2216 */
6c0a9413 2217function glossary_generate_export_csv($entries, $aliases, $categories) {
2218 global $CFG;
2219 $csv = '';
2220 $delimiter = '';
2221 require_once($CFG->libdir . '/csvlib.class.php');
2222 $delimiter = csv_import_reader::get_delimiter('comma');
2223 $csventries = array(0 => array(get_string('concept', 'glossary'), get_string('definition', 'glossary')));
2224 $csvaliases = array(0 => array());
2225 $csvcategories = array(0 => array());
2226 $aliascount = 0;
2227 $categorycount = 0;
2228
2229 foreach ($entries as $entry) {
2230 $thisaliasesentry = array();
2231 $thiscategoriesentry = array();
cbc2b5df 2232 $thiscsventry = array($entry->concept, nl2br($entry->definition));
6c0a9413 2233
2234 if (array_key_exists($entry->id, $aliases) && is_array($aliases[$entry->id])) {
2235 $thiscount = count($aliases[$entry->id]);
2236 if ($thiscount > $aliascount) {
2237 $aliascount = $thiscount;
2238 }
2239 foreach ($aliases[$entry->id] as $alias) {
2240 $thisaliasesentry[] = trim($alias);
2241 }
2242 }
2243 if (array_key_exists($entry->id, $categories) && is_array($categories[$entry->id])) {
2244 $thiscount = count($categories[$entry->id]);
2245 if ($thiscount > $categorycount) {
2246 $categorycount = $thiscount;
2247 }
2248 foreach ($categories[$entry->id] as $catentry) {
2249 $thiscategoriesentry[] = trim($catentry);
2250 }
2251 }
2252 $csventries[$entry->id] = $thiscsventry;
2253 $csvaliases[$entry->id] = $thisaliasesentry;
2254 $csvcategories[$entry->id] = $thiscategoriesentry;
2255
2256 }
2257 $returnstr = '';
2258 foreach ($csventries as $id => $row) {
2259 $aliasstr = '';
2260 $categorystr = '';
2261 if ($id == 0) {
2262 $aliasstr = get_string('alias', 'glossary');
2263 $categorystr = get_string('category', 'glossary');
2264 }
2265 $row = array_merge($row, array_pad($csvaliases[$id], $aliascount, $aliasstr), array_pad($csvcategories[$id], $categorycount, $categorystr));
2266 $returnstr .= '"' . implode('"' . $delimiter . '"', $row) . '"' . "\n";
2267 }
2268 return $returnstr;
2269}
2270
e121db76 2271/**
1ca1c8f8 2272 *
e121db76 2273 * @param object $glossary
1ca1c8f8
PS
2274 * @param string $ignored invalid parameter
2275 * @param int|string $hook
e121db76 2276 * @return string
2277 */
1ca1c8f8 2278function glossary_generate_export_file($glossary, $ignored = "", $hook = 0) {
ae8c3566 2279 global $CFG, $DB;
212039c0 2280
985af410
MG
2281 // Large exports are likely to take their time and memory.
2282 core_php_time_limit::raise();
2283 raise_memory_limit(MEMORY_EXTRA);
2284
27d01f7c
MG
2285 $cm = get_coursemodule_from_instance('glossary', $glossary->id, $glossary->course);
2286 $context = context_module::instance($cm->id);
2287
212039c0 2288 $co = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
2289
2290 $co .= glossary_start_tag("GLOSSARY",0,true);
2291 $co .= glossary_start_tag("INFO",1,true);
2292 $co .= glossary_full_tag("NAME",2,false,$glossary->name);
2293 $co .= glossary_full_tag("INTRO",2,false,$glossary->intro);
72c4be39 2294 $co .= glossary_full_tag("INTROFORMAT",2,false,$glossary->introformat);
212039c0 2295 $co .= glossary_full_tag("ALLOWDUPLICATEDENTRIES",2,false,$glossary->allowduplicatedentries);
2296 $co .= glossary_full_tag("DISPLAYFORMAT",2,false,$glossary->displayformat);
2297 $co .= glossary_full_tag("SHOWSPECIAL",2,false,$glossary->showspecial);
2298 $co .= glossary_full_tag("SHOWALPHABET",2,false,$glossary->showalphabet);
2299 $co .= glossary_full_tag("SHOWALL",2,false,$glossary->showall);
2300 $co .= glossary_full_tag("ALLOWCOMMENTS",2,false,$glossary->allowcomments);
2301 $co .= glossary_full_tag("USEDYNALINK",2,false,$glossary->usedynalink);
2302 $co .= glossary_full_tag("DEFAULTAPPROVAL",2,false,$glossary->defaultapproval);
2303 $co .= glossary_full_tag("GLOBALGLOSSARY",2,false,$glossary->globalglossary);
2304 $co .= glossary_full_tag("ENTBYPAGE",2,false,$glossary->entbypage);
27d01f7c 2305 $co .= glossary_xml_export_files('INTROFILES', 2, $context->id, 'intro', 0);
4f4ca7b5 2306
ae8c3566 2307 if ( $entries = $DB->get_records("glossary_entries", array("glossaryid"=>$glossary->id))) {
212039c0 2308 $co .= glossary_start_tag("ENTRIES",2,true);
748b1932 2309 foreach ($entries as $entry) {
046a797c 2310 $permissiongranted = 1;
1ac87c73 2311 if ( $hook ) {
2312 switch ( $hook ) {
046a797c 2313 case "ALL":
2314 case "SPECIAL":
2315 break;
2316 default:
1ac87c73 2317 $permissiongranted = ($entry->concept[ strlen($hook)-1 ] == $hook);
046a797c 2318 break;
2319 }
2320 }
1ac87c73 2321 if ( $hook ) {
2322 switch ( $hook ) {
046a797c 2323 case GLOSSARY_SHOW_ALL_CATEGORIES:
2324 break;
2325 case GLOSSARY_SHOW_NOT_CATEGORISED:
ae8c3566 2326 $permissiongranted = !$DB->record_exists("glossary_entries_categories", array("entryid"=>$entry->id));
046a797c 2327 break;
2328 default:
ae8c3566 2329 $permissiongranted = $DB->record_exists("glossary_entries_categories", array("entryid"=>$entry->id, "categoryid"=>$hook));
046a797c 2330 break;
2331 }
2332 }
2333 if ( $entry->approved and $permissiongranted ) {
212039c0 2334 $co .= glossary_start_tag("ENTRY",3,true);
2335 $co .= glossary_full_tag("CONCEPT",4,false,trim($entry->concept));
cbc2b5df 2336 $co .= glossary_full_tag("DEFINITION",4,false,$entry->definition);
72c4be39 2337 $co .= glossary_full_tag("FORMAT",4,false,$entry->definitionformat); // note: use old name for BC reasons
212039c0 2338 $co .= glossary_full_tag("USEDYNALINK",4,false,$entry->usedynalink);
2339 $co .= glossary_full_tag("CASESENSITIVE",4,false,$entry->casesensitive);
2340 $co .= glossary_full_tag("FULLMATCH",4,false,$entry->fullmatch);
2341 $co .= glossary_full_tag("TEACHERENTRY",4,false,$entry->teacherentry);
748b1932 2342
ae8c3566 2343 if ( $aliases = $DB->get_records("glossary_alias", array("entryid"=>$entry->id))) {
212039c0 2344 $co .= glossary_start_tag("ALIASES",4,true);
7965be79 2345 foreach ($aliases as $alias) {
212039c0 2346 $co .= glossary_start_tag("ALIAS",5,true);
2347 $co .= glossary_full_tag("NAME",6,false,trim($alias->alias));
2348 $co .= glossary_end_tag("ALIAS",5,true);
7965be79 2349 }
212039c0 2350 $co .= glossary_end_tag("ALIASES",4,true);
7965be79 2351 }
ae8c3566 2352 if ( $catentries = $DB->get_records("glossary_entries_categories", array("entryid"=>$entry->id))) {
212039c0 2353 $co .= glossary_start_tag("CATEGORIES",4,true);
748b1932 2354 foreach ($catentries as $catentry) {
ae8c3566 2355 $category = $DB->get_record("glossary_categories", array("id"=>$catentry->categoryid));
748b1932 2356
212039c0 2357 $co .= glossary_start_tag("CATEGORY",5,true);
2358 $co .= glossary_full_tag("NAME",6,false,$category->name);
2359 $co .= glossary_full_tag("USEDYNALINK",6,false,$category->usedynalink);
2360 $co .= glossary_end_tag("CATEGORY",5,true);
748b1932 2361 }
212039c0 2362 $co .= glossary_end_tag("CATEGORIES",4,true);
748b1932 2363 }
4f4ca7b5 2364
27d01f7c
MG
2365 // Export files embedded in entries.
2366 $co .= glossary_xml_export_files('ENTRYFILES', 4, $context->id, 'entry', $entry->id);
2367
2368 // Export attachments.
2369 $co .= glossary_xml_export_files('ATTACHMENTFILES', 4, $context->id, 'attachment', $entry->id);
2370
212039c0 2371 $co .= glossary_end_tag("ENTRY",3,true);
4f4ca7b5 2372 }
2373 }
212039c0 2374 $co .= glossary_end_tag("ENTRIES",2,true);
748b1932 2375
4f4ca7b5 2376 }
748b1932 2377
2378
212039c0 2379 $co .= glossary_end_tag("INFO",1,true);
2380 $co .= glossary_end_tag("GLOSSARY",0,true);
4f4ca7b5 2381
212039c0 2382 return $co;
4f4ca7b5 2383}
212039c0 2384/// Functions designed by Eloy Lafuente
2385/// Functions to create, open and write header of the xml file
4f4ca7b5 2386
e121db76 2387/**
2388 * Read import file and convert to current charset
2389 *
2390 * @global object
2391 * @param string $file
2392 * @return string
2393 */
b61e3e80 2394function glossary_read_imported_file($file_content) {
9f79b50f 2395 require_once "../../lib/xmlize.php";
2396 global $CFG;
2397
b61e3e80 2398 return xmlize($file_content, 0);
748b1932 2399}
4f4ca7b5 2400
e121db76 2401/**
2402 * Return the xml start tag
2403 *
2404 * @param string $tag
2405 * @param int $level
2406 * @param bool $endline
2407 * @return string
2408 */
4f4ca7b5 2409function glossary_start_tag($tag,$level=0,$endline=false) {
2410 if ($endline) {
2411 $endchar = "\n";
2412 } else {
2413 $endchar = "";
2414 }
2415 return str_repeat(" ",$level*2)."<".strtoupper($tag).">".$endchar;
2416}
a02c77dc 2417
e121db76 2418/**
2419 * Return the xml end tag
2420 * @param string $tag
2421 * @param int $level
2422 * @param bool $endline
2423 * @return string
2424 */
4f4ca7b5 2425function glossary_end_tag($tag,$level=0,$endline=true) {
2426 if ($endline) {
2427 $endchar = "\n";
2428 } else {
2429 $endchar = "";
2430 }
2431 return str_repeat(" ",$level*2)."</".strtoupper($tag).">".$endchar;
2432}
a02c77dc 2433
e121db76 2434/**
2435 * Return the start tag, the contents and the end tag
2436 *
2437 * @global object
2438 * @param string $tag
2439 * @param int $level
2440 * @param bool $endline
2441 * @param string $content
2442 * @return string
2443 */
212039c0 2444function glossary_full_tag($tag,$level=0,$endline=true,$content) {
9f79b50f 2445 global $CFG;
a02c77dc 2446
4f4ca7b5 2447 $st = glossary_start_tag($tag,$level,$endline);
212039c0 2448 $co = preg_replace("/\r\n|\r/", "\n", s($content));
4f4ca7b5 2449 $et = glossary_end_tag($tag,0,true);
2450 return $st.$co.$et;
2451}
2452
27d01f7c
MG
2453/**
2454 * Prepares file area to export as part of XML export
2455 *
2456 * @param string $tag XML tag to use for the group
2457 * @param int $taglevel
2458 * @param int $contextid
2459 * @param string $filearea
2460 * @param int $itemid
2461 * @return string
2462 */
2463function glossary_xml_export_files($tag, $taglevel, $contextid, $filearea, $itemid) {
2464 $co = '';
2465 $fs = get_file_storage();
2466 if ($files = $fs->get_area_files(
2467 $contextid, 'mod_glossary', $filearea, $itemid, 'itemid,filepath,filename', false)) {
2468 $co .= glossary_start_tag($tag, $taglevel, true);
2469 foreach ($files as $file) {
2470 $co .= glossary_start_tag('FILE', $taglevel + 1, true);
2471 $co .= glossary_full_tag('FILENAME', $taglevel + 2, false, $file->get_filename());
2472 $co .= glossary_full_tag('FILEPATH', $taglevel + 2, false, $file->get_filepath());
2473 $co .= glossary_full_tag('CONTENTS', $taglevel + 2, false, base64_encode($file->get_content()));
2474 $co .= glossary_end_tag('FILE', $taglevel + 1);
2475 }
2476 $co .= glossary_end_tag($tag, $taglevel);
2477 }
2478 return $co;
2479}
2480
2481/**
2482 * Parses files from XML import and inserts them into file system
2483 *
2484 * @param array $xmlparent parent element in parsed XML tree
2485 * @param string $tag
2486 * @param int $contextid
2487 * @param string $filearea
2488 * @param int $itemid
2489 * @return int
2490 */
2491function glossary_xml_import_files($xmlparent, $tag, $contextid, $filearea, $itemid) {
2492 $count = 0;
2493 if (isset($xmlparent[$tag][0]['#']['FILE'])) {
2494 $fs = get_file_storage();
2495 $files = $xmlparent[$tag][0]['#']['FILE'];
2496 foreach ($files as $file) {
2497 $filerecord = array(
2498 'contextid' => $contextid,
2499 'component' => 'mod_glossary',
2500 'filearea' => $filearea,
2501 'itemid' => $itemid,
2502 'filepath' => $file['#']['FILEPATH'][0]['#'],
2503 'filename' => $file['#']['FILENAME'][0]['#'],
2504 );
2505 $content = $file['#']['CONTENTS'][0]['#'];
2506 $fs->create_file_from_string($filerecord, base64_decode($content));
2507 $count++;
2508 }
2509 }
2510 return $count;
2511}
2512
e121db76 2513/**
2514 * How many unrated entries are in the given glossary for a given user?
2515 *
2b04c41c 2516 * @global moodle_database $DB
e121db76 2517 * @param int $glossaryid
2518 * @param int $userid
2519 * @return int
2520 */
63dd5fb2 2521function glossary_count_unrated_entries($glossaryid, $userid) {
ae8c3566 2522 global $DB;
2e4b4fc0 2523
2b04c41c
SH
2524 $sql = "SELECT COUNT('x') as num
2525 FROM {glossary_entries}
2526 WHERE glossaryid = :glossaryid AND
2527 userid <> :userid";
2528 $params = array('glossaryid' => $glossaryid, 'userid' => $userid);
2529 $entries = $DB->count_records_sql($sql, $params);
2530
2531 if ($entries) {
2532 // We need to get the contextid for the glossaryid we have been given.
2533 $sql = "SELECT ctx.id
2534 FROM {context} ctx
2535 JOIN {course_modules} cm ON cm.id = ctx.instanceid
2536 JOIN {modules} m ON m.id = cm.module
2537 JOIN {glossary} g ON g.id = cm.instance
2538 WHERE ctx.contextlevel = :contextlevel AND
2539 m.name = 'glossary' AND
2540 g.id = :glossaryid";
2541 $contextid = $DB->get_field_sql($sql, array('glossaryid' => $glossaryid, 'contextlevel' => CONTEXT_MODULE));
2542
2543 // Now we need to count the ratings that this user has made
2544 $sql = "SELECT COUNT('x') AS num
2545 FROM {glossary_entries} e
2e099772 2546 JOIN {rating} r ON r.itemid = e.id
2b04c41c
SH
2547 WHERE e.glossaryid = :glossaryid AND
2548 r.userid = :userid AND
2549 r.component = 'mod_glossary' AND
2550 r.ratingarea = 'entry' AND
2551 r.contextid = :contextid";
2e099772 2552 $params = array('glossaryid' => $glossaryid, 'userid' => $userid, 'contextid' => $contextid);
2b04c41c
SH
2553 $rated = $DB->count_records_sql($sql, $params);
2554 if ($rated) {
2555 // The number or enties minus the number or rated entries equals the number of unrated
2556 // entries
2e099772
PS
2557 if ($entries > $rated) {
2558 return $entries - $rated;
63dd5fb2 2559 } else {
2560 return 0; // Just in case there was a counting error
2561 }
2562 } else {
2e099772 2563 return (int)$entries;
63dd5fb2 2564 }
2565 } else {
2566 return 0;
2567 }
2568}
2569
e121db76 2570/**
2571 *
2572 * Returns the html code to represent any pagging bar. Paramenters are:
2573 *
2574 * The function dinamically show the first and last pages, and "scroll" over pages.
2575 * Fully compatible with Moodle's print_paging_bar() function. Perhaps some day this
2576 * could replace the general one. ;-)
2577 *
2578 * @param int $totalcount total number of records to be displayed
2579 * @param int $page page currently selected (0 based)
2580 * @param int $perpage number of records per page
2581 * @param string $baseurl url to link in each page, the string 'page=XX' will be added automatically.
1adbd2c3 2582 *
e121db76 2583 * @param int $maxpageallowed Optional maximum number of page allowed.
2584 * @param int $maxdisplay Optional maximum number of page links to show in the bar
2585 * @param string $separator Optional string to be used between pages in the bar
2586 * @param string $specialtext Optional string to be showed as an special link
2587 * @param string $specialvalue Optional value (page) to be used in the special link
2588 * @param bool $previousandnext Optional to decide if we want the previous and next links
2589 * @return string
2590 */
e2cf5316 2591function glossary_get_paging_bar($totalcount, $page, $perpage, $baseurl, $maxpageallowed=99999, $maxdisplay=20, $separator="&nbsp;", $specialtext="", $specialvalue=-1, $previousandnext = true) {
e2cf5316 2592
2593 $code = '';
2594
2595 $showspecial = false;
2596 $specialselected = false;
2597
2598 //Check if we have to show the special link
2599 if (!empty($specialtext)) {
2600 $showspecial = true;
2601 }
2602 //Check if we are with the special link selected
2603 if ($showspecial && $page == $specialvalue) {
2604 $specialselected = true;
a02c77dc 2605 }
e2cf5316 2606
2607 //If there are results (more than 1 page)
2608 if ($totalcount > $perpage) {
36a2b6bd 2609 $code .= "<div style=\"text-align:center\">";
e2cf5316 2610 $code .= "<p>".get_string("page").":";
2611
2612 $maxpage = (int)(($totalcount-1)/$perpage);
2613
2614 //Lower and upper limit of page
2615 if ($page < 0) {
2616 $page = 0;
2617 }
2618 if ($page > $maxpageallowed) {
2619 $page = $maxpageallowed;
2620 }
2621 if ($page > $maxpage) {
2622 $page = $maxpage;
2623 }
2624
2625 //Calculate the window of pages
2626 $pagefrom = $page - ((int)($maxdisplay / 2));
2627 if ($pagefrom < 0) {
2628 $pagefrom = 0;
2629 }
2630 $pageto = $pagefrom + $maxdisplay - 1;
2631 if ($pageto > $maxpageallowed) {
2632 $pageto = $maxpageallowed;
2633 }
2634 if ($pageto > $maxpage) {
2635 $pageto = $maxpage;
2636 }
2637
2638 //Some movements can be necessary if don't see enought pages
2639 if ($pageto - $pagefrom < $maxdisplay - 1) {
2640 if ($pageto - $maxdisplay + 1 > 0) {
2641 $pagefrom = $pageto - $maxdisplay + 1;
2642 }
2643 }
2644
2645 //Calculate first and last if necessary
2646 $firstpagecode = '';
2647 $lastpagecode = '';
2648 if ($pagefrom > 0) {
2649 $firstpagecode = "$separator<a href=\"{$baseurl}page=0\">1</a>";
2650 if ($pagefrom > 1) {
2651 $firstpagecode .= "$separator...";
2652 }
2653 }
2654 if ($pageto < $maxpage) {
2655 if ($pageto < $maxpage -1) {
2656 $lastpagecode = "$separator...";
2657 }
2658 $lastpagecode .= "$separator<a href=\"{$baseurl}page=$maxpage\">".($maxpage+1)."</a>";
2659 }
2660
2661 //Previous
2662 if ($page > 0 && $previousandnext) {
2663 $pagenum = $page - 1;
2664 $code .= "&nbsp;(<a href=\"{$baseurl}page=$pagenum\">".get_string("previous")."</a>)&nbsp;";
2665 }
2666
2667 //Add first
2668 $code .= $firstpagecode;
2669
2670 $pagenum = $pagefrom;
2671
2672 //List of maxdisplay pages
2673 while ($pagenum <= $pageto) {
2674 $pagetoshow = $pagenum +1;
2675 if ($pagenum == $page && !$specialselected) {
08ec7ec6 2676 $code .= "$separator<b>$pagetoshow</b>";
e2cf5316 2677 } else {
2678 $code .= "$separator<a href=\"{$baseurl}page=$pagenum\">$pagetoshow</a>";
2679 }
2680 $pagenum++;
2681 }
2682
2683 //Add last
2684 $code .= $lastpagecode;
2685
2686 //Next
2687 if ($page < $maxpage && $page < $maxpageallowed && $previousandnext) {
2688 $pagenum = $page + 1;
2689 $code .= "$separator(<a href=\"{$baseurl}page=$pagenum\">".get_string("next")."</a>)";
2690 }
2691
2692 //Add special
2693 if ($showspecial) {
2694 $code .= '<br />';
2695 if ($specialselected) {
08ec7ec6 2696 $code .= "<b>$specialtext</b>";
e2cf5316 2697 } else {
2698 $code .= "$separator<a href=\"{$baseurl}page=$specialvalue\">$specialtext</a>";
2699 }
2700 }
2701
2702 //End html
2703 $code .= "</p>";
36a2b6bd 2704 $code .= "</div>";
e2cf5316 2705 }
2706
2707 return $code;
2708}
b2b4ec30 2709
e121db76 2710/**
b2b4ec30
RT
2711 * List the actions that correspond to a view of this module.
2712 * This is used by the participation report.
2713 *
2714 * Note: This is not used by new logging system. Event with
2715 * crud = 'r' and edulevel = LEVEL_PARTICIPATING will
2716 * be considered as view action.
2717 *
e121db76 2718 * @return array
2719 */
f3221af9 2720function glossary_get_view_actions() {
cf051cc4 2721 return array('view','view all','view entry');
f3221af9 2722}
b2b4ec30 2723
e121db76 2724/**
b2b4ec30
RT
2725 * List the actions that correspond to a post of this module.
2726 * This is used by the participation report.
2727 *
2728 * Note: This is not used by new logging system. Event with
2729 * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
2730 * will be considered as post action.
2731 *
e121db76 2732 * @return array
2733 */
f3221af9 2734function glossary_get_post_actions() {
c8092ea5 2735 return array('add category','add entry','approve entry','delete category','delete entry','edit category','update entry');
f3221af9 2736}
2737
0b5a80a1 2738
2739/**
2740 * Implementation of the function for printing the form elements that control
2741 * whether the course reset functionality affects the glossary.
e121db76 2742 * @param object $mform form passed by reference
0b5a80a1 2743 */
2744function glossary_reset_course_form_definition(&$mform) {
2745 $mform->addElement('header', 'glossaryheader', get_string('modulenameplural', 'glossary'));
2746 $mform->addElement('checkbox', 'reset_glossary_all', get_string('resetglossariesall','glossary'));
2747
2748 $mform->addElement('select', 'reset_glossary_types', get_string('resetglossaries', 'glossary'),
2749 array('main'=>get_string('mainglossary', 'glossary'), 'secondary'=>get_string('secondaryglossary', 'glossary')), array('multiple' => 'multiple'));
2750 $mform->setAdvanced('reset_glossary_types');
2751 $mform->disabledIf('reset_glossary_types', 'reset_glossary_all', 'checked');
2752
2753 $mform->addElement('checkbox', 'reset_glossary_notenrolled', get_string('deletenotenrolled', 'glossary'));
2754 $mform->disabledIf('reset_glossary_notenrolled', 'reset_glossary_all', 'checked');
2755
2756 $mform->addElement('checkbox', 'reset_glossary_ratings', get_string('deleteallratings'));
2757 $mform->disabledIf('reset_glossary_ratings', 'reset_glossary_all', 'checked');
2758
2759 $mform->addElement('checkbox', 'reset_glossary_comments', get_string('deleteallcomments'));
2760 $mform->disabledIf('reset_glossary_comments', 'reset_glossary_all', 'checked');
2761}
2762
2763/**
2764 * Course reset form defaults.
e121db76 2765 * @return array
0b5a80a1 2766 */
2767function glossary_reset_course_form_defaults($course) {
2768 return array('reset_glossary_all'=>0, 'reset_glossary_ratings'=>1, 'reset_glossary_comments'=>1, 'reset_glossary_notenrolled'=>0);
2769}
2770
2771/**
2772 * Removes all grades from gradebook
e121db76 2773 *
a153c9f2
AD
2774 * @param int $courseid The ID of the course to reset
2775 * @param string $type The optional type of glossary. 'main', 'secondary' or ''
0b5a80a1 2776 */
2777function glossary_reset_gradebook($courseid, $type='') {
ae8c3566 2778 global $DB;
0b5a80a1 2779
2780 switch ($type) {
2781 case 'main' : $type = "AND g.mainglossary=1"; break;
2782 case 'secondary' : $type = "AND g.mainglossary=0"; break;
2783 default : $type = ""; //all
2784 }
2785
2786 $sql = "SELECT g.*, cm.idnumber as cmidnumber, g.course as courseid
ae8c3566 2787 FROM {glossary} g, {course_modules} cm, {modules} m
2788 WHERE m.name='glossary' AND m.id=cm.module AND cm.instance=g.id AND g.course=? $type";
0b5a80a1 2789
ae8c3566 2790 if ($glossarys = $DB->get_records_sql($sql, array($courseid))) {
0b5a80a1 2791 foreach ($glossarys as $glossary) {
2792 glossary_grade_item_update($glossary, 'reset');
2793 }
2794 }
2795}
2796/**
72d2982e 2797 * Actual implementation of the reset course functionality, delete all the
0b5a80a1 2798 * glossary responses for course $data->courseid.
e121db76 2799 *
2800 * @global object
0b5a80a1 2801 * @param $data the data submitted from the reset course.
2802 * @return array status array
2803 */
2804function glossary_reset_userdata($data) {
ae8c3566 2805 global $CFG, $DB;
d251b259 2806 require_once($CFG->dirroot.'/rating/lib.php');
0b5a80a1 2807
2808 $componentstr = get_string('modulenameplural', 'glossary');
2809 $status = array();
2810
2811 $allentriessql = "SELECT e.id
ae8c3566 2812 FROM {glossary_entries} e
2813 JOIN {glossary} g ON e.glossaryid = g.id
2814 WHERE g.course = ?";
0b5a80a1 2815
2816 $allglossariessql = "SELECT g.id
ae8c3566 2817 FROM {glossary} g
2818 WHERE g.course = ?";
2819
2820 $params = array($data->courseid);
0b5a80a1 2821
49bcd737 2822 $fs = get_file_storage();
2823
d251b259 2824 $rm = new rating_manager();
2b04c41c
SH
2825 $ratingdeloptions = new stdClass;
2826 $ratingdeloptions->component = 'mod_glossary';
2827 $ratingdeloptions->ratingarea = 'entry';
d251b259 2828
0b5a80a1 2829 // delete entries if requested
2830 if (!empty($data->reset_glossary_all)
2831 or (!empty($data->reset_glossary_types) and in_array('main', $data->reset_glossary_types) and in_array('secondary', $data->reset_glossary_types))) {
2832
4140cf6b
DC
2833 $params[] = 'glossary_entry';
2834 $DB->delete_records_select('comments', "itemid IN ($allentriessql) AND commentarea=?", $params);
d484419c 2835 $DB->delete_records_select('glossary_alias', "entryid IN ($allentriessql)", $params);
ae8c3566 2836 $DB->delete_records_select('glossary_entries', "glossaryid IN ($allglossariessql)", $params);
0b5a80a1 2837
49bcd737 2838 // now get rid of all attachments
ae8c3566 2839 if ($glossaries = $DB->get_records_sql($allglossariessql, $params)) {
0b5a80a1 2840 foreach ($glossaries as $glossaryid=>$unused) {
49bcd737 2841 if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
2842 continue;
2843 }
e0a91e11 2844 $context = context_module::instance($cm->id);
64f93798 2845 $fs->delete_area_files($context->id, 'mod_glossary', 'attachment');
d251b259
AD
2846
2847 //delete ratings
2848 $ratingdeloptions->contextid = $context->id;
2849 $rm->delete_ratings($ratingdeloptions);
0b5a80a1 2850 }
2851 }
2852
2853 // remove all grades from gradebook
2854 if (empty($data->reset_gradebook_grades)) {
2855 glossary_reset_gradebook($data->courseid);
2856 }
2857
2858 $status[] = array('component'=>$componentstr, 'item'=>get_string('resetglossariesall', 'glossary'), 'error'=>false);
2859
2860 } else if (!empty($data->reset_glossary_types)) {
b310a86e
PS
2861 $mainentriessql = "$allentriessql AND g.mainglossary=1";
2862 $secondaryentriessql = "$allentriessql AND g.mainglossary=0";
0b5a80a1 2863
2864 $mainglossariessql = "$allglossariessql AND g.mainglossary=1";
2865 $secondaryglossariessql = "$allglossariessql AND g.mainglossary=0";
2866
2867 if (in_array('main', $data->reset_glossary_types)) {
4140cf6b
DC
2868 $params[] = 'glossary_entry';
2869 $DB->delete_records_select('comments', "itemid IN ($mainentriessql) AND commentarea=?", $params);
ae8c3566 2870 $DB->delete_records_select('glossary_entries', "glossaryid IN ($mainglossariessql)", $params);
0b5a80a1 2871
ae8c3566 2872 if ($glossaries = $DB->get_records_sql($mainglossariessql, $params)) {
0b5a80a1 2873 foreach ($glossaries as $glossaryid=>$unused) {
49bcd737 2874 if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
2875 continue;
2876 }
e0a91e11 2877 $context = context_module::instance($cm->id);
64f93798 2878 $fs->delete_area_files($context->id, 'mod_glossary', 'attachment');
d251b259
AD
2879
2880 //delete ratings
2881 $ratingdeloptions->contextid = $context->id;
2882 $rm->delete_ratings($ratingdeloptions);
0b5a80a1 2883 }
2884 }
2885
2886 // remove all grades from gradebook
2887 if (empty($data->reset_gradebook_grades)) {
2888 glossary_reset_gradebook($data->courseid, 'main');
2889 }
2890
b310a86e 2891 $status[] = array('component'=>$componentstr, 'item'=>get_string('resetglossaries', 'glossary').': '.get_string('mainglossary', 'glossary'), 'error'=>false);
0b5a80a1 2892
2893 } else if (in_array('secondary', $data->reset_glossary_types)) {
4140cf6b
DC
2894 $params[] = 'glossary_entry';
2895 $DB->delete_records_select('comments', "itemid IN ($secondaryentriessql) AND commentarea=?", $params);
ae8c3566 2896 $DB->delete_records_select('glossary_entries', "glossaryid IN ($secondaryglossariessql)", $params);
0b5a80a1 2897 // remove exported source flag from entries in main glossary
b310a86e 2898 $DB->execute("UPDATE {glossary_entries}
ae8c3566 2899 SET sourceglossaryid=0
2900 WHERE glossaryid IN ($mainglossariessql)", $params);
0b5a80a1 2901
ae8c3566 2902 if ($glossaries = $DB->get_records_sql($secondaryglossariessql, $params)) {
0b5a80a1 2903 foreach ($glossaries as $glossaryid=>$unused) {
49bcd737 2904 if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
2905 continue;
2906 }
e0a91e11 2907 $context = context_module::instance($cm->id);
64f93798 2908 $fs->delete_area_files($context->id, 'mod_glossary', 'attachment');
d251b259
AD
2909
2910 //delete ratings
2911 $ratingdeloptions->contextid = $context->id;
2912 $rm->delete_ratings($ratingdeloptions);
0b5a80a1 2913 }
2914 }
2915
2916 // remove all grades from gradebook
2917 if (empty($data->reset_gradebook_grades)) {
2918 glossary_reset_gradebook($data->courseid, 'secondary');
2919 }
2920
2921 $status[] = array('component'=>$componentstr, 'item'=>get_string('resetglossaries', 'glossary').': '.get_string('secondaryglossary', 'glossary'), 'error'=>false);
2922 }
2923 }
2924
2925 // remove entries by users not enrolled into course
2926 if (!empty($data->reset_glossary_notenrolled)) {
2927 $entriessql = "SELECT e.id, e.userid, e.glossaryid, u.id AS userexists, u.deleted AS userdeleted
ae8c3566 2928 FROM {glossary_entries} e
2929 JOIN {glossary} g ON e.glossaryid = g.id
2930 LEFT JOIN {user} u ON e.userid = u.id
2931 WHERE g.course = ? AND e.userid > 0";
0b5a80a1 2932
e0a91e11 2933 $course_context = context_course::instance($data->courseid);
0b5a80a1 2934 $notenrolled = array();
ec577b05
EL
2935 $rs = $DB->get_recordset_sql($entriessql, $params);
2936 if ($rs->valid()) {
ae8c3566 2937 foreach ($rs as $entry) {
0b5a80a1 2938 if (array_key_exists($entry->userid, $notenrolled) or !$entry->userexists or $entry->userdeleted
4f0c2d00 2939 or !is_enrolled($course_context , $entry->userid)) {
4140cf6b 2940 $DB->delete_records('comments', array('commentarea'=>'glossary_entry', 'itemid'=>$entry->id));
ae8c3566 2941 $DB->delete_records('glossary_entries', array('id'=>$entry->id));
49bcd737 2942
2943 if ($cm = get_coursemodule_from_instance('glossary', $entry->glossaryid)) {
e0a91e11 2944 $context = context_module::instance($cm->id);
64f93798 2945 $fs->delete_area_files($context->id, 'mod_glossary', 'attachment', $entry->id);
2e4b4fc0
AD
2946
2947 //delete ratings
2948 $ratingdeloptions->contextid = $context->id;
2949 $rm->delete_ratings($ratingdeloptions);
49bcd737 2950 }
0b5a80a1 2951 }
2952 }
0b5a80a1 2953 $status[] = array('component'=>$componentstr, 'item'=>get_string('deletenotenrolled', 'glossary'), 'error'=>false);
2954 }
ec577b05 2955 $rs->close();
0b5a80a1 2956 }
2957
2958 // remove all ratings
2959 if (!empty($data->reset_glossary_ratings)) {
2e4b4fc0
AD
2960 //remove ratings
2961 if ($glossaries = $DB->get_records_sql($allglossariessql, $params)) {
2962 foreach ($glossaries as $glossaryid=>$unused) {
2963 if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
2964 continue;
2965 }
e0a91e11 2966 $context = context_module::instance($cm->id);
2e4b4fc0
AD
2967
2968 //delete ratings
2969 $ratingdeloptions->contextid = $context->id;
2970 $rm->delete_ratings($ratingdeloptions);
2971 }
2972 }
2973
0b5a80a1 2974 // remove all grades from gradebook
2975 if (empty($data->reset_gradebook_grades)) {
2976 glossary_reset_gradebook($data->courseid);
2977 }
2978 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallratings'), 'error'=>false);
2979 }
2980
4140cf6b 2981 // remove comments
0b5a80a1 2982 if (!empty($data->reset_glossary_comments)) {
4140cf6b
DC
2983 $params[] = 'glossary_entry';
2984 $DB->delete_records_select('comments', "itemid IN ($allentriessql) AND commentarea= ? ", $params);
0b5a80a1 2985 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallcomments'), 'error'=>false);
2986 }
2987
2988 /// updating dates - shift may be negative too
2989 if ($data->timeshift) {
2990 shift_course_mod_dates('glossary', array('assesstimestart', 'assesstimefinish'), $data->timeshift, $data->courseid);
2991 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);
2992 }
2993
2994 return $status;
2995}
2996
f432bebf 2997/**
2998 * Returns all other caps used in module
e121db76 2999 * @return array
f432bebf 3000 */
3001function glossary_get_extra_capabilities() {
16b86ae4 3002 return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/site:trustcontent', 'moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate', 'moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete');
f432bebf 3003}
3004
18a2a0cb 3005/**
3006 * @param string $feature FEATURE_xx constant for requested feature
3007 * @return mixed True if module supports feature, null if doesn't know
3008 */
3009function glossary_supports($feature) {
3010 switch($feature) {
42f103be 3011 case FEATURE_GROUPS: return false;
3012 case FEATURE_GROUPINGS: return false;
dc5c2bd9 3013 case FEATURE_MOD_INTRO: return true;
18a2a0cb 3014 case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
dde5bfbc 3015 case FEATURE_COMPLETION_HAS_RULES: return true;
42f103be 3016 case FEATURE_GRADE_HAS_GRADE: return true;
3017 case FEATURE_GRADE_OUTCOMES: return true;
63e87951 3018 case FEATURE_RATE: return true;
d3ce7c2c 3019 case FEATURE_BACKUP_MOODLE2: return true;
3e4c2435 3020 case FEATURE_SHOW_DESCRIPTION: return true;
42f103be 3021
18a2a0cb 3022 default: return null;
3023 }
3024}
0961861e 3025
dde5bfbc
EL
3026/**
3027 * Obtains the automatic completion state for this glossary based on any conditions
3028 * in glossary settings.
3029 *
3030 * @global object
3031 * @global object
3032 * @param object $course Course
3033 * @param object $cm Course-module
3034 * @param int $userid User ID
3035 * @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
3036 * @return bool True if completed, false if not. (If no conditions, then return
3037 * value depends on comparison type)
3038 */
3039function glossary_get_completion_state($course,$cm,$userid,$type) {
3040 global $CFG, $DB;
3041
3042 // Get glossary details
3043 if (!($glossary=$DB->get_record('glossary',array('id'=>$cm->instance)))) {
3044 throw new Exception("Can't find glossary {$cm->instance}");
3045 }
3046
3047 $result=$type; // Default return value
3048
3049 if ($glossary->completionentries) {
3050 $value = $glossary->completionentries <=
3051 $DB->count_records('glossary_entries',array('glossaryid'=>$glossary->id, 'userid'=>$userid, 'approved'=>1));
3052 if ($type == COMPLETION_AND) {
3053 $result = $result && $value;
3054 } else {
3055 $result = $result || $value;
3056 }
3057 }
3058
3059 return $result;
3060}
3061
0961861e 3062function glossary_extend_navigation($navigation, $course, $module, $cm) {
223d6cb3
NS
3063 global $CFG, $DB;
3064
29645f97 3065 $displayformat = $DB->get_record('glossary_formats', array('name' => $module->displayformat));
223d6cb3 3066 // Get visible tabs for the format and check if the menu needs to be displayed.
29645f97 3067 $showtabs = glossary_get_visible_tabs($displayformat);
223d6cb3
NS
3068
3069 foreach ($showtabs as $showtabkey => $showtabvalue) {
3070
3071 switch($showtabvalue) {
3072 case GLOSSARY_STANDARD :
29645f97
MG
3073 $navigation->add(get_string('standardview', 'glossary'), new moodle_url('/mod/glossary/view.php',
3074 array('id' => $cm->id, 'mode' => 'letter')));
223d6cb3
NS
3075 break;
3076 case GLOSSARY_CATEGORY :
29645f97
MG
3077 $navigation->add(get_string('categoryview', 'glossary'), new moodle_url('/mod/glossary/view.php',
3078 array('id' => $cm->id, 'mode' => 'cat')));
223d6cb3
NS
3079 break;
3080 case GLOSSARY_DATE :
29645f97
MG
3081 $navigation->add(get_string('dateview', 'glossary'), new moodle_url('/mod/glossary/view.php',
3082 array('id' => $cm->id, 'mode' => 'date')));
223d6cb3
NS
3083 break;
3084 case GLOSSARY_AUTHOR :
29645f97
MG
3085 $navigation->add(get_string('authorview', 'glossary'), new moodle_url('/mod/glossary/view.php',
3086 array('id' => $cm->id, 'mode' => 'author')));
223d6cb3
NS
3087 break;
3088 }
3089 }
0961861e 3090}
3091
0b29477b
SH
3092/**
3093 * Adds module specific settings to the settings block
3094 *
3095 * @param settings_navigation $settings The settings navigation object
3096 * @param navigation_node $glossarynode The node to add module settings to
3097 */
3098function glossary_extend_settings_navigation(settings_navigation $settings, navigation_node $glossarynode) {
eb7ee156 3099 global $PAGE, $DB, $CFG, $USER;
0961861e 3100
3101 $mode = optional_param('mode', '', PARAM_ALPHA);
3102 $hook = optional_param('hook', 'ALL', PARAM_CLEAN);
3103
0961861e 3104 if (has_capability('mod/glossary:import', $PAGE->cm->context)) {
0b29477b 3105 $glossarynode->add(get_string('importentries', 'glossary'), new moodle_url('/mod/glossary/import.php', array('id'=>$PAGE->cm->id)));
0961861e 3106 }
3107
3108 if (has_capability('mod/glossary:export', $PAGE->cm->context)) {
0b29477b 3109 $glossarynode->add(get_string('exportentries', 'glossary'), new moodle_url('/mod/glossary/export.php', array('id'=>$PAGE->cm->id, 'mode'=>$mode, 'hook'=>$hook)));
0961861e 3110 }
3111
56115eea 3112 if (has_capability('mod/glossary:approve', $PAGE->cm->context) && ($hiddenentries = $DB->count_records('glossary_entries', array('glossaryid'=>$PAGE->cm->instance, 'approved'=>0)))) {
0b29477b 3113 $glossarynode->add(get_string('waitingapproval', 'glossary'), new moodle_url('/mod/glossary/view.php', array('id'=>$PAGE->cm->id, 'mode'=>'approval')));
0961861e 3114 }
3115
3116 if (has_capability('mod/glossary:write', $PAGE->cm->context)) {
0b29477b 3117 $glossarynode->add(get_string('addentry', 'glossary'), new moodle_url('/mod/glossary/edit.php', array('cmid'=>$PAGE->cm->id)));
0961861e 3118 }
9e86f2e7
AD
3119
3120 $glossary = $DB->get_record('glossary', array("id" => $PAGE->cm->instance));
3121
c3963fbd 3122 if (!empty($CFG->enablerssfeeds) && !empty($CFG->glossary_enablerssfeeds) && $glossary->rsstype && $glossary->rssarticles && has_capability('mod/glossary:view', $PAGE->cm->context)) {
9e86f2e7
AD
3123 require_once("$CFG->libdir/rsslib.php");
3124
3125 $string = get_string('rsstype','forum');
3126
aa60291e 3127 $url = new moodle_url(rss_get_url($PAGE->cm->context->id, $USER->id, 'mod_glossary', $glossary->id));
9e86f2e7
AD
3128 $glossarynode->add($string, $url, settings_navigation::TYPE_SETTING, null, null, new pix_icon('i/rss', ''));
3129 }
3406acde 3130}
c1951ea9
DC
3131
3132/**
3133 * Running addtional permission check on plugin, for example, plugins
3134 * may have switch to turn on/off comments option, this callback will
3135 * affect UI display, not like pluginname_comment_validate only throw
3136 * exceptions.
3137 * Capability check has been done in comment->check_permissions(), we
3138 * don't need to do it again here.
3139 *
35453657
DC
3140 * @package mod_glossary
3141 * @category comment
3142 *
c1951ea9
DC
3143 * @param stdClass $comment_param {
3144 * context => context the context object
3145 * courseid => int course id
3146 * cm => stdClass course module object
3147 * commentarea => string comment area
3148 * itemid => int itemid
3149 * }
3150 * @return array
3151 */
3152function glossary_comment_permissions($comment_param) {
3153 return array('post'=>true, 'view'=>true);
3154}
3155
3156/**
3157 * Validate comment parameter before perform other comments actions
3158 *
35453657
DC
3159 * @package mod_glossary
3160 * @category comment
3161 *
c1951ea9
DC
3162 * @param stdClass $comment_param {
3163 * context => context the context object
3164 * courseid => int course id
3165 * cm => stdClass course module object
3166 * commentarea => string comment area
3167 * itemid => int itemid
3168 * }
3169 * @return boolean
3170 */
3171function glossary_comment_validate($comment_param) {