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