| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php // $Id: lib.php,v 1.538.2.55 2008/10/09 10:51:06 poltawski Exp $ 2 // Library of useful functions 3 4 5 define('COURSE_MAX_LOG_DISPLAY', 150); // days 6 define('COURSE_MAX_LOGS_PER_PAGE', 1000); // records 7 define('COURSE_LIVELOG_REFRESH', 60); // Seconds 8 define('COURSE_MAX_RECENT_PERIOD', 172800); // Two days, in seconds 9 define('COURSE_MAX_SUMMARIES_PER_PAGE', 10); // courses 10 define('COURSE_MAX_COURSES_PER_DROPDOWN',1000); // max courses in log dropdown before switching to optional 11 define('COURSE_MAX_USERS_PER_DROPDOWN',1000); // max users in log dropdown before switching to optional 12 define('FRONTPAGENEWS', '0'); 13 define('FRONTPAGECOURSELIST', '1'); 14 define('FRONTPAGECATEGORYNAMES', '2'); 15 define('FRONTPAGETOPICONLY', '3'); 16 define('FRONTPAGECATEGORYCOMBO', '4'); 17 define('FRONTPAGECOURSELIMIT', 200); // maximum number of courses displayed on the frontpage 18 define('EXCELROWS', 65535); 19 define('FIRSTUSEDEXCELROW', 3); 20 21 define('MOD_CLASS_ACTIVITY', 0); 22 define('MOD_CLASS_RESOURCE', 1); 23 24 25 function make_log_url($module, $url) { 26 switch ($module) { 27 case 'course': 28 case 'file': 29 case 'login': 30 case 'lib': 31 case 'admin': 32 case 'calendar': 33 case 'mnet course': 34 return "/course/$url"; 35 break; 36 case 'user': 37 case 'blog': 38 return "/$module/$url"; 39 break; 40 case 'upload': 41 return $url; 42 break; 43 case 'library': 44 case '': 45 return '/'; 46 break; 47 case 'message': 48 return "/message/$url"; 49 break; 50 default: 51 return "/mod/$module/$url"; 52 break; 53 } 54 } 55 56 57 function build_mnet_logs_array($hostid, $course, $user=0, $date=0, $order="l.time ASC", $limitfrom='', $limitnum='', 58 $modname="", $modid=0, $modaction="", $groupid=0) { 59 60 global $CFG; 61 62 // It is assumed that $date is the GMT time of midnight for that day, 63 // and so the next 86400 seconds worth of logs are printed. 64 65 /// Setup for group handling. 66 67 // TODO: I don't understand group/context/etc. enough to be able to do 68 // something interesting with it here 69 // What is the context of a remote course? 70 71 /// If the group mode is separate, and this user does not have editing privileges, 72 /// then only the user's group can be viewed. 73 //if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 74 // $groupid = get_current_group($course->id); 75 //} 76 /// If this course doesn't have groups, no groupid can be specified. 77 //else if (!$course->groupmode) { 78 // $groupid = 0; 79 //} 80 $groupid = 0; 81 82 $joins = array(); 83 84 $qry = " 85 SELECT 86 l.*, 87 u.firstname, 88 u.lastname, 89 u.picture 90 FROM 91 {$CFG->prefix}mnet_log l 92 LEFT JOIN 93 {$CFG->prefix}user u 94 ON 95 l.userid = u.id 96 WHERE 97 "; 98 99 $where .= "l.hostid = '$hostid'"; 100 101 // TODO: Is 1 really a magic number referring to the sitename? 102 if ($course != 1 || $modid != 0) { 103 $where .= " AND\n l.course='$course'"; 104 } 105 106 if ($modname) { 107 $where .= " AND\n l.module = '$modname'"; 108 } 109 110 if ('site_errors' === $modid) { 111 $where .= " AND\n ( l.action='error' OR l.action='infected' )"; 112 } else if ($modid) { 113 //TODO: This assumes that modids are the same across sites... probably 114 //not true 115 $where .= " AND\n l.cmid = '$modid'"; 116 } 117 118 if ($modaction) { 119 $firstletter = substr($modaction, 0, 1); 120 if (preg_match('/[[:alpha:]]/', $firstletter)) { 121 $where .= " AND\n lower(l.action) LIKE '%" . strtolower($modaction) . "%'"; 122 } else if ($firstletter == '-') { 123 $where .= " AND\n lower(l.action) NOT LIKE '%" . strtolower(substr($modaction, 1)) . "%'"; 124 } 125 } 126 127 if ($user) { 128 $where .= " AND\n l.userid = '$user'"; 129 } 130 131 if ($date) { 132 $enddate = $date + 86400; 133 $where .= " AND\n l.time > '$date' AND l.time < '$enddate'"; 134 } 135 136 $result = array(); 137 $result['totalcount'] = count_records_sql("SELECT COUNT(*) FROM {$CFG->prefix}mnet_log l WHERE $where"); 138 if(!empty($result['totalcount'])) { 139 $where .= "\n ORDER BY\n $order"; 140 $result['logs'] = get_records_sql($qry.$where, $limitfrom, $limitnum); 141 } else { 142 $result['logs'] = array(); 143 } 144 return $result; 145 } 146 147 function build_logs_array($course, $user=0, $date=0, $order="l.time ASC", $limitfrom='', $limitnum='', 148 $modname="", $modid=0, $modaction="", $groupid=0) { 149 150 // It is assumed that $date is the GMT time of midnight for that day, 151 // and so the next 86400 seconds worth of logs are printed. 152 153 /// Setup for group handling. 154 155 /// If the group mode is separate, and this user does not have editing privileges, 156 /// then only the user's group can be viewed. 157 if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 158 $groupid = get_current_group($course->id); 159 } 160 /// If this course doesn't have groups, no groupid can be specified. 161 else if (!$course->groupmode) { 162 $groupid = 0; 163 } 164 165 $joins = array(); 166 167 if ($course->id != SITEID || $modid != 0) { 168 $joins[] = "l.course='$course->id'"; 169 } 170 171 if ($modname) { 172 $joins[] = "l.module = '$modname'"; 173 } 174 175 if ('site_errors' === $modid) { 176 $joins[] = "( l.action='error' OR l.action='infected' )"; 177 } else if ($modid) { 178 $joins[] = "l.cmid = '$modid'"; 179 } 180 181 if ($modaction) { 182 $firstletter = substr($modaction, 0, 1); 183 if (preg_match('/[[:alpha:]]/', $firstletter)) { 184 $joins[] = "lower(l.action) LIKE '%" . strtolower($modaction) . "%'"; 185 } else if ($firstletter == '-') { 186 $joins[] = "lower(l.action) NOT LIKE '%" . strtolower(substr($modaction, 1)) . "%'"; 187 } 188 } 189 190 191 /// Getting all members of a group. 192 if ($groupid and !$user) { 193 if ($gusers = groups_get_members($groupid)) { 194 $gusers = array_keys($gusers); 195 $joins[] = 'l.userid IN (' . implode(',', $gusers) . ')'; 196 } else { 197 $joins[] = 'l.userid = 0'; // No users in groups, so we want something that will always be false. 198 } 199 } 200 else if ($user) { 201 $joins[] = "l.userid = '$user'"; 202 } 203 204 if ($date) { 205 $enddate = $date + 86400; 206 $joins[] = "l.time > '$date' AND l.time < '$enddate'"; 207 } 208 209 $selector = implode(' AND ', $joins); 210 211 $totalcount = 0; // Initialise 212 $result = array(); 213 $result['logs'] = get_logs($selector, $order, $limitfrom, $limitnum, $totalcount); 214 $result['totalcount'] = $totalcount; 215 return $result; 216 } 217 218 219 function print_log($course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100, 220 $url="", $modname="", $modid=0, $modaction="", $groupid=0) { 221 222 global $CFG; 223 224 if (!$logs = build_logs_array($course, $user, $date, $order, $page*$perpage, $perpage, 225 $modname, $modid, $modaction, $groupid)) { 226 notify("No logs found!"); 227 print_footer($course); 228 exit; 229 } 230 231 $courses = array(); 232 233 if ($course->id == SITEID) { 234 $courses[0] = ''; 235 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 236 foreach ($ccc as $cc) { 237 $courses[$cc->id] = $cc->shortname; 238 } 239 } 240 } else { 241 $courses[$course->id] = $course->shortname; 242 } 243 244 $totalcount = $logs['totalcount']; 245 $count=0; 246 $ldcache = array(); 247 $tt = getdate(time()); 248 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 249 250 $strftimedatetime = get_string("strftimedatetime"); 251 252 echo "<div class=\"info\">\n"; 253 print_string("displayingrecords", "", $totalcount); 254 echo "</div>\n"; 255 256 print_paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage&"); 257 258 echo '<table class="logtable generalbox boxaligncenter" summary="">'."\n"; 259 // echo "<table class=\"logtable\" cellpadding=\"3\" cellspacing=\"0\" summary=\"\">\n"; 260 echo "<tr>"; 261 if ($course->id == SITEID) { 262 echo "<th class=\"c0 header\" scope=\"col\">".get_string('course')."</th>\n"; 263 } 264 echo "<th class=\"c1 header\" scope=\"col\">".get_string('time')."</th>\n"; 265 echo "<th class=\"c2 header\" scope=\"col\">".get_string('ip_address')."</th>\n"; 266 echo "<th class=\"c3 header\" scope=\"col\">".get_string('fullname')."</th>\n"; 267 echo "<th class=\"c4 header\" scope=\"col\">".get_string('action')."</th>\n"; 268 echo "<th class=\"c5 header\" scope=\"col\">".get_string('info')."</th>\n"; 269 echo "</tr>\n"; 270 271 // Make sure that the logs array is an array, even it is empty, to avoid warnings from the foreach. 272 if (empty($logs['logs'])) { 273 $logs['logs'] = array(); 274 } 275 276 $row = 1; 277 foreach ($logs['logs'] as $log) { 278 279 $row = ($row + 1) % 2; 280 281 if (isset($ldcache[$log->module][$log->action])) { 282 $ld = $ldcache[$log->module][$log->action]; 283 } else { 284 $ld = get_record('log_display', 'module', $log->module, 'action', $log->action); 285 $ldcache[$log->module][$log->action] = $ld; 286 } 287 if ($ld && is_numeric($log->info)) { 288 // ugly hack to make sure fullname is shown correctly 289 if (($ld->mtable == 'user') and ($ld->field == sql_concat('firstname', "' '" , 'lastname'))) { 290 $log->info = fullname(get_record($ld->mtable, 'id', $log->info), true); 291 } else { 292 $log->info = get_field($ld->mtable, $ld->field, 'id', $log->info); 293 } 294 } 295 296 //Filter log->info 297 $log->info = format_string($log->info); 298 299 // If $log->url has been trimmed short by the db size restriction 300 // code in add_to_log, keep a note so we don't add a link to a broken url 301 $tl=textlib_get_instance(); 302 $brokenurl=($tl->strlen($log->url)==100 && $tl->substr($log->url,97)=='...'); 303 304 $log->url = strip_tags(urldecode($log->url)); // Some XSS protection 305 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 306 $log->url = s($log->url); /// XSS protection and XHTML compatibility - should be in link_to_popup_window() instead!! 307 308 echo '<tr class="r'.$row.'">'; 309 if ($course->id == SITEID) { 310 echo "<td class=\"cell c0\">\n"; 311 if (empty($log->course)) { 312 echo get_string('site') . "\n"; 313 } else { 314 echo " <a href=\"{$CFG->wwwroot}/course/view.php?id={$log->course}\">". format_string($courses[$log->course])."</a>\n"; 315 } 316 echo "</td>\n"; 317 } 318 echo "<td class=\"cell c1\" align=\"right\">".userdate($log->time, '%a'). 319 ' '.userdate($log->time, $strftimedatetime)."</td>\n"; 320 echo "<td class=\"cell c2\">\n"; 321 link_to_popup_window("/iplookup/index.php?ip=$log->ip&user=$log->userid", 'iplookup',$log->ip, 440, 700); 322 echo "</td>\n"; 323 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id))); 324 echo "<td class=\"cell c3\">\n"; 325 echo " <a href=\"$CFG->wwwroot/user/view.php?id={$log->userid}&course={$log->course}\">$fullname</a>\n"; 326 echo "</td>\n"; 327 echo "<td class=\"cell c4\">\n"; 328 $displayaction="$log->module $log->action"; 329 if($brokenurl) { 330 echo $displayaction; 331 } else { 332 link_to_popup_window( make_log_url($log->module,$log->url), 'fromloglive',$displayaction, 440, 700); 333 } 334 echo "</td>\n";; 335 echo "<td class=\"cell c5\">{$log->info}</td>\n"; 336 echo "</tr>\n"; 337 } 338 echo "</table>\n"; 339 340 print_paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage&"); 341 } 342 343 344 function print_mnet_log($hostid, $course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100, 345 $url="", $modname="", $modid=0, $modaction="", $groupid=0) { 346 347 global $CFG; 348 349 if (!$logs = build_mnet_logs_array($hostid, $course, $user, $date, $order, $page*$perpage, $perpage, 350 $modname, $modid, $modaction, $groupid)) { 351 notify("No logs found!"); 352 print_footer($course); 353 exit; 354 } 355 356 if ($course->id == SITEID) { 357 $courses[0] = ''; 358 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.visible')) { 359 foreach ($ccc as $cc) { 360 $courses[$cc->id] = $cc->shortname; 361 } 362 } 363 } 364 365 $totalcount = $logs['totalcount']; 366 $count=0; 367 $ldcache = array(); 368 $tt = getdate(time()); 369 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 370 371 $strftimedatetime = get_string("strftimedatetime"); 372 373 echo "<div class=\"info\">\n"; 374 print_string("displayingrecords", "", $totalcount); 375 echo "</div>\n"; 376 377 print_paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage&"); 378 379 echo "<table class=\"logtable\" cellpadding=\"3\" cellspacing=\"0\">\n"; 380 echo "<tr>"; 381 if ($course->id == SITEID) { 382 echo "<th class=\"c0 header\">".get_string('course')."</th>\n"; 383 } 384 echo "<th class=\"c1 header\">".get_string('time')."</th>\n"; 385 echo "<th class=\"c2 header\">".get_string('ip_address')."</th>\n"; 386 echo "<th class=\"c3 header\">".get_string('fullname')."</th>\n"; 387 echo "<th class=\"c4 header\">".get_string('action')."</th>\n"; 388 echo "<th class=\"c5 header\">".get_string('info')."</th>\n"; 389 echo "</tr>\n"; 390 391 if (empty($logs['logs'])) { 392 echo "</table>\n"; 393 return; 394 } 395 396 $row = 1; 397 foreach ($logs['logs'] as $log) { 398 399 $log->info = $log->coursename; 400 $row = ($row + 1) % 2; 401 402 if (isset($ldcache[$log->module][$log->action])) { 403 $ld = $ldcache[$log->module][$log->action]; 404 } else { 405 $ld = get_record('log_display', 'module', $log->module, 'action', $log->action); 406 $ldcache[$log->module][$log->action] = $ld; 407 } 408 if (0 && $ld && !empty($log->info)) { 409 // ugly hack to make sure fullname is shown correctly 410 if (($ld->mtable == 'user') and ($ld->field == sql_concat('firstname', "' '" , 'lastname'))) { 411 $log->info = fullname(get_record($ld->mtable, 'id', $log->info), true); 412 } else { 413 $log->info = get_field($ld->mtable, $ld->field, 'id', $log->info); 414 } 415 } 416 417 //Filter log->info 418 $log->info = format_string($log->info); 419 420 $log->url = strip_tags(urldecode($log->url)); // Some XSS protection 421 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 422 $log->url = str_replace('&', '&', $log->url); /// XHTML compatibility 423 424 echo '<tr class="r'.$row.'">'; 425 if ($course->id == SITEID) { 426 echo "<td class=\"r$row c0\" >\n"; 427 echo " <a href=\"{$CFG->wwwroot}/course/view.php?id={$log->course}\">".$courses[$log->course]."</a>\n"; 428 echo "</td>\n"; 429 } 430 echo "<td class=\"r$row c1\" align=\"right\">".userdate($log->time, '%a'). 431 ' '.userdate($log->time, $strftimedatetime)."</td>\n"; 432 echo "<td class=\"r$row c2\" >\n"; 433 link_to_popup_window("/iplookup/index.php?ip=$log->ip&user=$log->userid", 'iplookup',$log->ip, 400, 700); 434 echo "</td>\n"; 435 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id))); 436 echo "<td class=\"r$row c3\" >\n"; 437 echo " <a href=\"$CFG->wwwroot/user/view.php?id={$log->userid}\">$fullname</a>\n"; 438 echo "</td>\n"; 439 echo "<td class=\"r$row c4\">\n"; 440 echo $log->action .': '.$log->module; 441 echo "</td>\n";; 442 echo "<td class=\"r$row c5\">{$log->info}</td>\n"; 443 echo "</tr>\n"; 444 } 445 echo "</table>\n"; 446 447 print_paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage&"); 448 } 449 450 451 function print_log_csv($course, $user, $date, $order='l.time DESC', $modname, 452 $modid, $modaction, $groupid) { 453 454 $text = get_string('course')."\t".get_string('time')."\t".get_string('ip_address')."\t". 455 get_string('fullname')."\t".get_string('action')."\t".get_string('info'); 456 457 if (!$logs = build_logs_array($course, $user, $date, $order, '', '', 458 $modname, $modid, $modaction, $groupid)) { 459 return false; 460 } 461 462 $courses = array(); 463 464 if ($course->id == SITEID) { 465 $courses[0] = ''; 466 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 467 foreach ($ccc as $cc) { 468 $courses[$cc->id] = $cc->shortname; 469 } 470 } 471 } else { 472 $courses[$course->id] = $course->shortname; 473 } 474 475 $count=0; 476 $ldcache = array(); 477 $tt = getdate(time()); 478 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 479 480 $strftimedatetime = get_string("strftimedatetime"); 481 482 $filename = 'logs_'.userdate(time(),get_string('backupnameformat'),99,false); 483 $filename .= '.txt'; 484 header("Content-Type: application/download\n"); 485 header("Content-Disposition: attachment; filename=$filename"); 486 header("Expires: 0"); 487 header("Cache-Control: must-revalidate,post-check=0,pre-check=0"); 488 header("Pragma: public"); 489 490 echo get_string('savedat').userdate(time(), $strftimedatetime)."\n"; 491 echo $text; 492 493 if (empty($logs['logs'])) { 494 return true; 495 } 496 497 foreach ($logs['logs'] as $log) { 498 if (isset($ldcache[$log->module][$log->action])) { 499 $ld = $ldcache[$log->module][$log->action]; 500 } else { 501 $ld = get_record('log_display', 'module', $log->module, 'action', $log->action); 502 $ldcache[$log->module][$log->action] = $ld; 503 } 504 if ($ld && !empty($log->info)) { 505 // ugly hack to make sure fullname is shown correctly 506 if (($ld->mtable == 'user') and ($ld->field == sql_concat('firstname', "' '" , 'lastname'))) { 507 $log->info = fullname(get_record($ld->mtable, 'id', $log->info), true); 508 } else { 509 $log->info = get_field($ld->mtable, $ld->field, 'id', $log->info); 510 } 511 } 512 513 //Filter log->info 514 $log->info = format_string($log->info); 515 516 $log->url = strip_tags(urldecode($log->url)); // Some XSS protection 517 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 518 $log->url = str_replace('&', '&', $log->url); // XHTML compatibility 519 520 $firstField = $courses[$log->course]; 521 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id))); 522 $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.' '.$log->action, $log->info); 523 $text = implode("\t", $row); 524 echo $text." \n"; 525 } 526 return true; 527 } 528 529 530 function print_log_xls($course, $user, $date, $order='l.time DESC', $modname, 531 $modid, $modaction, $groupid) { 532 533 global $CFG; 534 535 require_once("$CFG->libdir/excellib.class.php"); 536 537 if (!$logs = build_logs_array($course, $user, $date, $order, '', '', 538 $modname, $modid, $modaction, $groupid)) { 539 return false; 540 } 541 542 $courses = array(); 543 544 if ($course->id == SITEID) { 545 $courses[0] = ''; 546 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 547 foreach ($ccc as $cc) { 548 $courses[$cc->id] = $cc->shortname; 549 } 550 } 551 } else { 552 $courses[$course->id] = $course->shortname; 553 } 554 555 $count=0; 556 $ldcache = array(); 557 $tt = getdate(time()); 558 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 559 560 $strftimedatetime = get_string("strftimedatetime"); 561 562 $nroPages = ceil(count($logs)/(EXCELROWS-FIRSTUSEDEXCELROW+1)); 563 $filename = 'logs_'.userdate(time(),get_string('backupnameformat'),99,false); 564 $filename .= '.xls'; 565 566 $workbook = new MoodleExcelWorkbook('-'); 567 $workbook->send($filename); 568 569 $worksheet = array(); 570 $headers = array(get_string('course'), get_string('time'), get_string('ip_address'), 571 get_string('fullname'), get_string('action'), get_string('info')); 572 573 // Creating worksheets 574 for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) { 575 $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages; 576 $worksheet[$wsnumber] =& $workbook->add_worksheet($sheettitle); 577 $worksheet[$wsnumber]->set_column(1, 1, 30); 578 $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat'). 579 userdate(time(), $strftimedatetime)); 580 $col = 0; 581 foreach ($headers as $item) { 582 $worksheet[$wsnumber]->write(FIRSTUSEDEXCELROW-1,$col,$item,''); 583 $col++; 584 } 585 } 586 587 if (empty($logs['logs'])) { 588 $workbook->close(); 589 return true; 590 } 591 592 $formatDate =& $workbook->add_format(); 593 $formatDate->set_num_format(get_string('log_excel_date_format')); 594 595 $row = FIRSTUSEDEXCELROW; 596 $wsnumber = 1; 597 $myxls =& $worksheet[$wsnumber]; 598 foreach ($logs['logs'] as $log) { 599 if (isset($ldcache[$log->module][$log->action])) { 600 $ld = $ldcache[$log->module][$log->action]; 601 } else { 602 $ld = get_record('log_display', 'module', $log->module, 'action', $log->action); 603 $ldcache[$log->module][$log->action] = $ld; 604 } 605 if ($ld && !empty($log->info)) { 606 // ugly hack to make sure fullname is shown correctly 607 if (($ld->mtable == 'user') and ($ld->field == sql_concat('firstname', "' '" , 'lastname'))) { 608 $log->info = fullname(get_record($ld->mtable, 'id', $log->info), true); 609 } else { 610 $log->info = get_field($ld->mtable, $ld->field, 'id', $log->info); 611 } 612 } 613 614 // Filter log->info 615 $log->info = format_string($log->info); 616 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 617 618 if ($nroPages>1) { 619 if ($row > EXCELROWS) { 620 $wsnumber++; 621 $myxls =& $worksheet[$wsnumber]; 622 $row = FIRSTUSEDEXCELROW; 623 } 624 } 625 626 $myxls->write($row, 0, $courses[$log->course], ''); 627 // Excel counts from 1/1/1900 628 $excelTime=25569+$log->time/(3600*24); 629 $myxls->write($row, 1, $excelTime, $formatDate); 630 $myxls->write($row, 2, $log->ip, ''); 631 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id))); 632 $myxls->write($row, 3, $fullname, ''); 633 $myxls->write($row, 4, $log->module.' '.$log->action, ''); 634 $myxls->write($row, 5, $log->info, ''); 635 636 $row++; 637 } 638 639 $workbook->close(); 640 return true; 641 } 642 643 function print_log_ods($course, $user, $date, $order='l.time DESC', $modname, 644 $modid, $modaction, $groupid) { 645 646 global $CFG; 647 648 require_once("$CFG->libdir/odslib.class.php"); 649 650 if (!$logs = build_logs_array($course, $user, $date, $order, '', '', 651 $modname, $modid, $modaction, $groupid)) { 652 return false; 653 } 654 655 $courses = array(); 656 657 if ($course->id == SITEID) { 658 $courses[0] = ''; 659 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 660 foreach ($ccc as $cc) { 661 $courses[$cc->id] = $cc->shortname; 662 } 663 } 664 } else { 665 $courses[$course->id] = $course->shortname; 666 } 667 668 $count=0; 669 $ldcache = array(); 670 $tt = getdate(time()); 671 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 672 673 $strftimedatetime = get_string("strftimedatetime"); 674 675 $nroPages = ceil(count($logs)/(EXCELROWS-FIRSTUSEDEXCELROW+1)); 676 $filename = 'logs_'.userdate(time(),get_string('backupnameformat'),99,false); 677 $filename .= '.ods'; 678 679 $workbook = new MoodleODSWorkbook('-'); 680 $workbook->send($filename); 681 682 $worksheet = array(); 683 $headers = array(get_string('course'), get_string('time'), get_string('ip_address'), 684 get_string('fullname'), get_string('action'), get_string('info')); 685 686 // Creating worksheets 687 for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) { 688 $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages; 689 $worksheet[$wsnumber] =& $workbook->add_worksheet($sheettitle); 690 $worksheet[$wsnumber]->set_column(1, 1, 30); 691 $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat'). 692 userdate(time(), $strftimedatetime)); 693 $col = 0; 694 foreach ($headers as $item) { 695 $worksheet[$wsnumber]->write(FIRSTUSEDEXCELROW-1,$col,$item,''); 696 $col++; 697 } 698 } 699 700 if (empty($logs['logs'])) { 701 $workbook->close(); 702 return true; 703 } 704 705 $formatDate =& $workbook->add_format(); 706 $formatDate->set_num_format(get_string('log_excel_date_format')); 707 708 $row = FIRSTUSEDEXCELROW; 709 $wsnumber = 1; 710 $myxls =& $worksheet[$wsnumber]; 711 foreach ($logs['logs'] as $log) { 712 if (isset($ldcache[$log->module][$log->action])) { 713 $ld = $ldcache[$log->module][$log->action]; 714 } else { 715 $ld = get_record('log_display', 'module', $log->module, 'action', $log->action); 716 $ldcache[$log->module][$log->action] = $ld; 717 } 718 if ($ld && !empty($log->info)) { 719 // ugly hack to make sure fullname is shown correctly 720 if (($ld->mtable == 'user') and ($ld->field == sql_concat('firstname', "' '" , 'lastname'))) { 721 $log->info = fullname(get_record($ld->mtable, 'id', $log->info), true); 722 } else { 723 $log->info = get_field($ld->mtable, $ld->field, 'id', $log->info); 724 } 725 } 726 727 // Filter log->info 728 $log->info = format_string($log->info); 729 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 730 731 if ($nroPages>1) { 732 if ($row > EXCELROWS) { 733 $wsnumber++; 734 $myxls =& $worksheet[$wsnumber]; 735 $row = FIRSTUSEDEXCELROW; 736 } 737 } 738 739 $myxls->write_string($row, 0, $courses[$log->course]); 740 $myxls->write_date($row, 1, $log->time); 741 $myxls->write_string($row, 2, $log->ip); 742 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id))); 743 $myxls->write_string($row, 3, $fullname); 744 $myxls->write_string($row, 4, $log->module.' '.$log->action); 745 $myxls->write_string($row, 5, $log->info); 746 747 $row++; 748 } 749 750 $workbook->close(); 751 return true; 752 } 753 754 755 function print_log_graph($course, $userid=0, $type="course.png", $date=0) { 756 global $CFG, $USER; 757 if (empty($CFG->gdversion)) { 758 echo "(".get_string("gdneed").")"; 759 } else { 760 // MDL-10818, do not display broken graph when user has no permission to view graph 761 if (has_capability('moodle/site:viewreports', get_context_instance(CONTEXT_COURSE, $course->id)) || 762 ($course->showreports and $USER->id == $userid)) { 763 echo '<img src="'.$CFG->wwwroot.'/course/report/log/graph.php?id='.$course->id. 764 '&user='.$userid.'&type='.$type.'&date='.$date.'" alt="" />'; 765 } 766 } 767 } 768 769 770 function print_overview($courses) { 771 772 global $CFG, $USER; 773 774 $htmlarray = array(); 775 if ($modules = get_records('modules')) { 776 foreach ($modules as $mod) { 777 if (file_exists(dirname(dirname(__FILE__)).'/mod/'.$mod->name.'/lib.php')) { 778 include_once(dirname(dirname(__FILE__)).'/mod/'.$mod->name.'/lib.php'); 779 $fname = $mod->name.'_print_overview'; 780 if (function_exists($fname)) { 781 $fname($courses,$htmlarray); 782 } 783 } 784 } 785 } 786 foreach ($courses as $course) { 787 print_simple_box_start('center', '100%', '', 5, "coursebox"); 788 $linkcss = ''; 789 if (empty($course->visible)) { 790 $linkcss = 'class="dimmed"'; 791 } 792 print_heading('<a title="'. format_string($course->fullname).'" '.$linkcss.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'. format_string($course->fullname).'</a>'); 793 if (array_key_exists($course->id,$htmlarray)) { 794 foreach ($htmlarray[$course->id] as $modname => $html) { 795 echo $html; 796 } 797 } 798 print_simple_box_end(); 799 } 800 } 801 802 803 function print_recent_activity($course) { 804 // $course is an object 805 // This function trawls through the logs looking for 806 // anything new since the user's last login 807 808 global $CFG, $USER, $SESSION; 809 810 $context = get_context_instance(CONTEXT_COURSE, $course->id); 811 812 $viewfullnames = has_capability('moodle/site:viewfullnames', $context); 813 814 $timestart = round(time() - COURSE_MAX_RECENT_PERIOD, -2); // better db caching for guests - 100 seconds 815 816 if (!has_capability('moodle/legacy:guest', $context, NULL, false)) { 817 if (!empty($USER->lastcourseaccess[$course->id])) { 818 if ($USER->lastcourseaccess[$course->id] > $timestart) { 819 $timestart = $USER->lastcourseaccess[$course->id]; 820 } 821 } 822 } 823 824 echo '<div class="activitydate">'; 825 echo get_string('activitysince', '', userdate($timestart)); 826 echo '</div>'; 827 echo '<div class="activityhead">'; 828 829 echo '<a href="'.$CFG->wwwroot.'/course/recent.php?id='.$course->id.'">'.get_string('recentactivityreport').'</a>'; 830 831 echo "</div>\n"; 832 833 $content = false; 834 835 /// Firstly, have there been any new enrolments? 836 837 $users = get_recent_enrolments($course->id, $timestart); 838 839 //Accessibility: new users now appear in an <OL> list. 840 if ($users) { 841 echo '<div class="newusers">'; 842 print_headline(get_string("newusers").':', 3); 843 $content = true; 844 echo "<ol class=\"list\">\n"; 845 foreach ($users as $user) { 846 $fullname = fullname($user, $viewfullnames); 847 echo '<li class="name"><a href="'."$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id\">$fullname</a></li>\n"; 848 } 849 echo "</ol>\n</div>\n"; 850 } 851 852 /// Next, have there been any modifications to the course structure? 853 854 $modinfo =& get_fast_modinfo($course); 855 856 $changelist = array(); 857 858 $logs = get_records_select('log', "time > $timestart AND course = $course->id AND 859 module = 'course' AND 860 (action = 'add mod' OR action = 'update mod' OR action = 'delete mod')", 861 "id ASC"); 862 863 if ($logs) { 864 $actions = array('add mod', 'update mod', 'delete mod'); 865 $newgones = array(); // added and later deleted items 866 foreach ($logs as $key => $log) { 867 if (!in_array($log->action, $actions)) { 868 continue; 869 } 870 $info = split(' ', $log->info); 871 872 if ($info[0] == 'label') { // Labels are ignored in recent activity 873 continue; 874 } 875 876 if (count($info) != 2) { 877 debugging("Incorrect log entry info: id = ".$log->id, DEBUG_DEVELOPER); 878 continue; 879 } 880 881 $modname = $info[0]; 882 $instanceid = $info[1]; 883 884 if ($log->action == 'delete mod') { 885 // unfortunately we do not know if the mod was visible 886 if (!array_key_exists($log->info, $newgones)) { 887 $strdeleted = get_string('deletedactivity', 'moodle', get_string('modulename', $modname)); 888 $changelist[$log->info] = array ('operation' => 'delete', 'text' => $strdeleted); 889 } 890 } else { 891 if (!isset($modinfo->instances[$modname][$instanceid])) { 892 if ($log->action == 'add mod') { 893 // do not display added and later deleted activities 894 $newgones[$log->info] = true; 895 } 896 continue; 897 } 898 $cm = $modinfo->instances[$modname][$instanceid]; 899 if (!$cm->uservisible) { 900 continue; 901 } 902 903 if ($log->action == 'add mod') { 904 $stradded = get_string('added', 'moodle', get_string('modulename', $modname)); 905 $changelist[$log->info] = array('operation' => 'add', 'text' => "$stradded:<br /><a href=\"$CFG->wwwroot/mod/$cm->modname/view.php?id={$cm->id}\">".format_string($cm->name, true)."</a>"); 906 907 } else if ($log->action == 'update mod' and empty($changelist[$log->info])) { 908 $strupdated = get_string('updated', 'moodle', get_string('modulename', $modname)); 909 $changelist[$log->info] = array('operation' => 'update', 'text' => "$strupdated:<br /><a href=\"$CFG->wwwroot/mod/$cm->modname/view.php?id={$cm->id}\">".format_string($cm->name, true)."</a>"); 910 } 911 } 912 } 913 } 914 915 if (!empty($changelist)) { 916 print_headline(get_string('courseupdates').':', 3); 917 $content = true; 918 foreach ($changelist as $changeinfo => $change) { 919 echo '<p class="activity">'.$change['text'].'</p>'; 920 } 921 } 922 923 /// Now display new things from each module 924 925 $usedmodules = array(); 926 foreach($modinfo->cms as $cm) { 927 if (isset($usedmodules[$cm->modname])) { 928 continue; 929 } 930 if (!$cm->uservisible) { 931 continue; 932 } 933 $usedmodules[$cm->modname] = $cm->modname; 934 } 935 936 foreach ($usedmodules as $modname) { // Each module gets it's own logs and prints them 937 if (file_exists($CFG->dirroot.'/mod/'.$modname.'/lib.php')) { 938 include_once($CFG->dirroot.'/mod/'.$modname.'/lib.php'); 939 $print_recent_activity = $modname.'_print_recent_activity'; 940 if (function_exists($print_recent_activity)) { 941 // NOTE: original $isteacher (second parameter below) was replaced with $viewfullnames! 942 $content = $print_recent_activity($course, $viewfullnames, $timestart) || $content; 943 } 944 } else { 945 debugging("Missing lib.php in lib/{$modname} - please reinstall files or uninstall the module"); 946 } 947 } 948 949 if (! $content) { 950 echo '<p class="message">'.get_string('nothingnew').'</p>'; 951 } 952 } 953 954 955 function get_array_of_activities($courseid) { 956 // For a given course, returns an array of course activity objects 957 // Each item in the array contains he following properties: 958 // cm - course module id 959 // mod - name of the module (eg forum) 960 // section - the number of the section (eg week or topic) 961 // name - the name of the instance 962 // visible - is the instance visible or not 963 // groupingid - grouping id 964 // groupmembersonly - is this instance visible to group members only 965 // extra - contains extra string to include in any link 966 967 global $CFG; 968 969 $mod = array(); 970 971 if (!$rawmods = get_course_mods($courseid)) { 972 return $mod; // always return array 973 } 974 975 if ($sections = get_records("course_sections", "course", $courseid, "section ASC")) { 976 foreach ($sections as $section) { 977 if (!empty($section->sequence)) { 978 $sequence = explode(",", $section->sequence); 979 foreach ($sequence as $seq) { 980 if (empty($rawmods[$seq])) { 981 continue; 982 } 983 $mod[$seq]->id = $rawmods[$seq]->instance; 984 $mod[$seq]->cm = $rawmods[$seq]->id; 985 $mod[$seq]->mod = $rawmods[$seq]->modname; 986 $mod[$seq]->section = $section->section; 987 $mod[$seq]->visible = $rawmods[$seq]->visible; 988 $mod[$seq]->groupmode = $rawmods[$seq]->groupmode; 989 $mod[$seq]->groupingid = $rawmods[$seq]->groupingid; 990 $mod[$seq]->groupmembersonly = $rawmods[$seq]->groupmembersonly; 991 $mod[$seq]->extra = ""; 992 993 $modname = $mod[$seq]->mod; 994 $functionname = $modname."_get_coursemodule_info"; 995 996 if (!file_exists("$CFG->dirroot/mod/$modname/lib.php")) { 997 continue; 998 } 999 1000 include_once("$CFG->dirroot/mod/$modname/lib.php"); 1001 1002 if (function_exists($functionname)) { 1003 if ($info = $functionname($rawmods[$seq])) { 1004 if (!empty($info->extra)) { 1005 $mod[$seq]->extra = $info->extra; 1006 } 1007 if (!empty($info->icon)) { 1008 $mod[$seq]->icon = $info->icon; 1009 } 1010 if (!empty($info->name)) { 1011 $mod[$seq]->name = urlencode($info->name); 1012 } 1013 } 1014 } 1015 if (!isset($mod[$seq]->name)) { 1016 $mod[$seq]->name = urlencode(get_field($rawmods[$seq]->modname, "name", "id", $rawmods[$seq]->instance)); 1017 } 1018 } 1019 } 1020 } 1021 } 1022 return $mod; 1023 } 1024 1025 1026 /** 1027 * Returns reference to full info about modules in course (including visibility). 1028 * Cached and as fast as possible (0 or 1 db query). 1029 * @param $course object or 'reset' string to reset caches, modinfo may be updated in db 1030 * @return mixed courseinfo object or nothing if resetting 1031 */ 1032 function &get_fast_modinfo(&$course, $userid=0) { 1033 global $CFG, $USER; 1034 1035 static $cache = array(); 1036 1037 if ($course === 'reset') { 1038 $cache = array(); 1039 $nothing = null; 1040 return $nothing; // we must return some reference 1041 } 1042 1043 if (empty($userid)) { 1044 $userid = $USER->id; 1045 } 1046 1047 if (array_key_exists($course->id, $cache) and $cache[$course->id]->userid == $userid) { 1048 return $cache[$course->id]; 1049 } 1050 1051 if (empty($course->modinfo)) { 1052 // no modinfo yet - load it 1053 rebuild_course_cache($course->id); 1054 $course->modinfo = get_field('course', 'modinfo', 'id', $course->id); 1055 } 1056 1057 $modinfo = new object(); 1058 $modinfo->courseid = $course->id; 1059 $modinfo->userid = $userid; 1060 $modinfo->sections = array(); 1061 $modinfo->cms = array(); 1062 $modinfo->instances = array(); 1063 $modinfo->groups = null; // loaded only when really needed - the only one db query 1064 1065 $info = unserialize($course->modinfo); 1066 if (!is_array($info)) { 1067 // hmm, something is wrong - lets try to fix it 1068 rebuild_course_cache($course->id); 1069 $course->modinfo = get_field('course', 'modinfo', 'id', $course->id); 1070 $info = unserialize($course->modinfo); 1071 if (!is_array($info)) { 1072 return $modinfo; 1073 } 1074 } 1075 1076 if ($info) { 1077 // detect if upgrade required 1078 $first = reset($info); 1079 if (!isset($first->id)) { 1080 rebuild_course_cache($course->id); 1081 $course->modinfo = get_field('course', 'modinfo', 'id', $course->id); 1082 $info = unserialize($course->modinfo); 1083 if (!is_array($info)) { 1084 return $modinfo; 1085 } 1086 } 1087 } 1088 1089 $modlurals = array(); 1090 1091 $cmids = array(); 1092 $contexts = null; 1093 foreach ($info as $mod) { 1094 $cmids[$mod->cm] = $mod->cm; 1095 } 1096 if ($cmids) { 1097 // preload all module contexts with one query 1098 $contexts = get_context_instance(CONTEXT_MODULE, $cmids); 1099 } 1100 1101 foreach ($info as $mod) { 1102 if (empty($mod->name)) { 1103 // something is wrong here 1104 continue; 1105 } 1106 // reconstruct minimalistic $cm 1107 $cm = new object(); 1108 $cm->id = $mod->cm; 1109 $cm->instance = $mod->id; 1110 $cm->course = $course->id; 1111 $cm->modname = $mod->mod; 1112 $cm->name = urldecode($mod->name); 1113 $cm->visible = $mod->visible; 1114 $cm->sectionnum = $mod->section; 1115 $cm->groupmode = $mod->groupmode; 1116 $cm->groupingid = $mod->groupingid; 1117 $cm->groupmembersonly = $mod->groupmembersonly; 1118 $cm->extra = isset($mod->extra) ? urldecode($mod->extra) : ''; 1119 $cm->icon = isset($mod->icon) ? $mod->icon : ''; 1120 $cm->uservisible = true; 1121 1122 // preload long names plurals and also check module is installed properly 1123 if (!isset($modlurals[$cm->modname])) { 1124 if (!file_exists("$CFG->dirroot/mod/$cm->modname/lib.php")) { 1125 continue; 1126 } 1127 $modlurals[$cm->modname] = get_string('modulenameplural', $cm->modname); 1128 } 1129 $cm->modplural = $modlurals[$cm->modname]; 1130 1131 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $contexts[$cm->id], $userid)) { 1132 $cm->uservisible = false; 1133 1134 } else if (!empty($CFG->enablegroupings) and !empty($cm->groupmembersonly) 1135 and !has_capability('moodle/site:accessallgroups', $contexts[$cm->id], $userid)) { 1136 if (is_null($modinfo->groups)) { 1137 $modinfo->groups = groups_get_user_groups($course->id, $userid); 1138 } 1139 if (empty($modinfo->groups[$cm->groupingid])) { 1140 $cm->uservisible = false; 1141 } 1142 } 1143 1144 if (!isset($modinfo->instances[$cm->modname])) { 1145 $modinfo->instances[$cm->modname] = array(); 1146 } 1147 $modinfo->instances[$cm->modname][$cm->instance] =& $cm; 1148 $modinfo->cms[$cm->id] =& $cm; 1149 1150 // reconstruct sections 1151 if (!isset($modinfo->sections[$cm->sectionnum])) { 1152 $modinfo->sections[$cm->sectionnum] = array(); 1153 } 1154 $modinfo->sections[$cm->sectionnum][] = $cm->id; 1155 1156 unset($cm); 1157 } 1158 1159 unset($cache[$course->id]); // prevent potential reference problems when switching users 1160 $cache[$course->id] = $modinfo; 1161 1162 return $cache[$course->id]; 1163 } 1164 1165 1166 function get_all_mods($courseid, &$mods, &$modnames, &$modnamesplural, &$modnamesused) { 1167 // Returns a number of useful structures for course displays 1168 1169 $mods = array(); // course modules indexed by id 1170 $modnames = array(); // all course module names (except resource!) 1171 $modnamesplural= array(); // all course module names (plural form) 1172 $modnamesused = array(); // course module names used 1173 1174 if ($allmods = get_records("modules")) { 1175 foreach ($allmods as $mod) { 1176 if ($mod->visible) { 1177 $modnames[$mod->name] = get_string("modulename", "$mod->name"); 1178 $modnamesplural[$mod->name] = get_string("modulenameplural", "$mod->name"); 1179 } 1180 } 1181 asort($modnames, SORT_LOCALE_STRING); 1182 } else { 1183 error("No modules are installed!"); 1184 } 1185 1186 if ($rawmods = get_course_mods($courseid)) { 1187 foreach($rawmods as $mod) { // Index the mods 1188 if (empty($modnames[$mod->modname])) { 1189 continue; 1190 } 1191 $mods[$mod->id] = $mod; 1192 $mods[$mod->id]->modfullname = $modnames[$mod->modname]; 1193 if (!$mod->visible and !has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $courseid))) { 1194 continue; 1195 } 1196 // Check groupings 1197 if (!groups_course_module_visible($mod)) { 1198 continue; 1199 } 1200 $modnamesused[$mod->modname] = $modnames[$mod->modname]; 1201 } 1202 if ($modnamesused) { 1203 asort($modnamesused, SORT_LOCALE_STRING); 1204 } 1205 } 1206 } 1207 1208 1209 function get_all_sections($courseid) { 1210 1211 return get_records("course_sections", "course", "$courseid", "section", 1212 "section, id, course, summary, sequence, visible"); 1213 } 1214 1215 function course_set_display($courseid, $display=0) { 1216 global $USER; 1217 1218 if ($display == "all" or empty($display)) { 1219 $display = 0; 1220 } 1221 1222 if (empty($USER->id) or $USER->username == 'guest') { 1223 //do not store settings in db for guests 1224 } else if (record_exists("course_display", "userid", $USER->id, "course", $courseid)) { 1225 set_field("course_display", "display", $display, "userid", $USER->id, "course", $courseid); 1226 } else { 1227 $record = new object(); 1228 $record->userid = $USER->id; 1229 $record->course = $courseid; 1230 $record->display = $display; 1231 if (!insert_record("course_display", $record)) { 1232 notify("Could not save your course display!"); 1233 } 1234 } 1235 1236 return $USER->display[$courseid] = $display; // Note: = not == 1237 } 1238 1239 function set_section_visible($courseid, $sectionnumber, $visibility) { 1240 /// For a given course section, markes it visible or hidden, 1241 /// and does the same for every activity in that section 1242 1243 if ($section = get_record("course_sections", "course", $courseid, "section", $sectionnumber)) { 1244 set_field("course_sections", "visible", "$visibility", "id", $section->id); 1245 if (!empty($section->sequence)) { 1246 $modules = explode(",", $section->sequence); 1247 foreach ($modules as $moduleid) { 1248 set_coursemodule_visible($moduleid, $visibility, true); 1249 } 1250 } 1251 rebuild_course_cache($courseid); 1252 } 1253 } 1254 1255 1256 function print_section($course, $section, $mods, $modnamesused, $absolute=false, $width="100%") { 1257 /// Prints a section full of activity modules 1258 global $CFG, $USER; 1259 1260 static $initialised; 1261 1262 static $groupbuttons; 1263 static $groupbuttonslink; 1264 static $isediting; 1265 static $ismoving; 1266 static $strmovehere; 1267 static $strmovefull; 1268 static $strunreadpostsone; 1269 static $usetracking; 1270 static $groupings; 1271 1272 1273 if (!isset($initialised)) { 1274 $groupbuttons = ($course->groupmode or (!$course->groupmodeforce)); 1275 $groupbuttonslink = (!$course->groupmodeforce); 1276 $isediting = isediting($course->id); 1277 $ismoving = $isediting && ismoving($course->id); 1278 if ($ismoving) { 1279 $strmovehere = get_string("movehere"); 1280 $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'")); 1281 } 1282 include_once($CFG->dirroot.'/mod/forum/lib.php'); 1283 if ($usetracking = forum_tp_can_track_forums()) { 1284 $strunreadpostsone = get_string('unreadpostsone', 'forum'); 1285 } 1286 $initialised = true; 1287 } 1288 1289 $labelformatoptions = new object(); 1290 $labelformatoptions->noclean = true; 1291 1292 /// Casting $course->modinfo to string prevents one notice when the field is null 1293 $modinfo = get_fast_modinfo($course); 1294 1295 1296 //Acccessibility: replace table with list <ul>, but don't output empty list. 1297 if (!empty($section->sequence)) { 1298 1299 // Fix bug #5027, don't want style=\"width:$width\". 1300 echo "<ul class=\"section img-text\">\n"; 1301 $sectionmods = explode(",", $section->sequence); 1302 1303 foreach ($sectionmods as $modnumber) { 1304 if (empty($mods[$modnumber])) { 1305 continue; 1306 } 1307 1308 $mod = $mods[$modnumber]; 1309 1310 if ($ismoving and $mod->id == $USER->activitycopy) { 1311 // do not display moving mod 1312 continue; 1313 } 1314 1315 if (isset($modinfo->cms[$modnumber])) { 1316 if (!$modinfo->cms[$modnumber]->uservisible) { 1317 // visibility shortcut 1318 continue; 1319 } 1320 } else { 1321 if (!file_exists("$CFG->dirroot/mod/$mod->modname/lib.php")) { 1322 // module not installed 1323 continue; 1324 } 1325 if (!coursemodule_visible_for_user($mod)) { 1326 // full visibility check 1327 continue; 1328 } 1329 } 1330 1331 echo '<li class="activity '.$mod->modname.'" id="module-'.$modnumber.'">'; // Unique ID 1332 if ($ismoving) { 1333 echo '<a title="'.$strmovefull.'"'. 1334 ' href="'.$CFG->wwwroot.'/course/mod.php?moveto='.$mod->id.'&sesskey='.$USER->sesskey.'">'. 1335 '<img class="movetarget" src="'.$CFG->pixpath.'/movehere.gif" '. 1336 ' alt="'.$strmovehere.'" /></a><br /> 1337 '; 1338 } 1339 1340 if ($mod->indent) { 1341 print_spacer(12, 20 * $mod->indent, false); 1342 } 1343 1344 $extra = ''; 1345 if (!empty($modinfo->cms[$modnumber]->extra)) { 1346 $extra = $modinfo->cms[$modnumber]->extra; 1347 } 1348 1349 if ($mod->modname == "label") { 1350 if (!$mod->visible) { 1351 echo "<div class=\"dimmed_text\">"; 1352 } 1353 echo format_text($extra, FORMAT_HTML, $labelformatoptions); 1354 if (!$mod->visible) { 1355 echo "</div>"; 1356 } 1357 if (!empty($CFG->enablegroupings) && !empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 1358 if (!isset($groupings)) { 1359 $groupings = groups_get_all_groupings($course->id); 1360 } 1361 echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>'; 1362 } 1363 1364 } else { // Normal activity 1365 $instancename = format_string($modinfo->cms[$modnumber]->name, true, $course->id); 1366 1367 if (!empty($modinfo->cms[$modnumber]->icon)) { 1368 $icon = "$CFG->pixpath/".$modinfo->cms[$modnumber]->icon; 1369 } else { 1370 $icon = "$CFG->modpixpath/$mod->modname/icon.gif"; 1371 } 1372 1373 //Accessibility: for files get description via icon. 1374 $altname = ''; 1375 if ('resource'==$mod->modname) { 1376 if (!empty($modinfo->cms[$modnumber]->icon)) { 1377 $possaltname = $modinfo->cms[$modnumber]->icon; 1378 1379 $mimetype = mimeinfo_from_icon('type', $possaltname); 1380 $altname = get_mimetype_description($mimetype); 1381 } else { 1382 $altname = $mod->modfullname; 1383 } 1384 } else { 1385 $altname = $mod->modfullname; 1386 } 1387 // Avoid unnecessary duplication. 1388 if (false!==stripos($instancename, $altname)) { 1389 $altname = ''; 1390 } 1391 // File type after name, for alphabetic lists (screen reader). 1392 if ($altname) { 1393 $altname = get_accesshide(' '.$altname); 1394 } 1395 1396 $linkcss = $mod->visible ? "" : " class=\"dimmed\" "; 1397 echo '<a '.$linkcss.' '.$extra. // Title unnecessary! 1398 ' href="'.$CFG->wwwroot.'/mod/'.$mod->modname.'/view.php?id='.$mod->id.'">'. 1399 '<img src="'.$icon.'" class="activityicon" alt="" /> <span>'. 1400 $instancename.$altname.'</span></a>'; 1401 1402 if (!empty($CFG->enablegroupings) && !empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 1403 if (!isset($groupings)) { 1404 $groupings = groups_get_all_groupings($course->id); 1405 } 1406 echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>'; 1407 } 1408 } 1409 if ($usetracking && $mod->modname == 'forum') { 1410 if ($unread = forum_tp_count_forum_unread_posts($mod, $course)) { 1411 echo '<span class="unread"> <a href="'.$CFG->wwwroot.'/mod/forum/view.php?id='.$mod->id.'">'; 1412 if ($unread == 1) { 1413 echo $strunreadpostsone; 1414 } else { 1415 print_string('unreadpostsnumber', 'forum', $unread); 1416 } 1417 echo '</a></span>'; 1418 } 1419 } 1420 1421 if ($isediting) { 1422 // TODO: we must define this as mod property! 1423 if ($groupbuttons and $mod->modname != 'label' and $mod->modname != 'resource' and $mod->modname != 'glossary') { 1424 if (! $mod->groupmodelink = $groupbuttonslink) { 1425 $mod->groupmode = $course->groupmode; 1426 } 1427 1428 } else { 1429 $mod->groupmode = false; 1430 } 1431 echo ' '; 1432 echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section); 1433 } 1434 echo "</li>\n"; 1435 } 1436 1437 } elseif ($ismoving) { 1438 echo "<ul class=\"section\">\n"; 1439 } 1440 1441 if ($ismoving) { 1442 echo '<li><a title="'.$strmovefull.'"'. 1443 ' href="'.$CFG->wwwroot.'/course/mod.php?movetosection='.$section->id.'&sesskey='.$USER->sesskey.'">'. 1444 '<img class="movetarget" src="'.$CFG->pixpath.'/movehere.gif" '. 1445 ' alt="'.$strmovehere.'" /></a></li> 1446 '; 1447 } 1448 if (!empty($section->sequence) || $ismoving) { 1449 echo "</ul><!--class='section'-->\n\n"; 1450 } 1451 } 1452 1453 /** 1454 * Prints the menus to add activities and resources. 1455 */ 1456 function print_section_add_menus($course, $section, $modnames, $vertical=false, $return=false) { 1457 global $CFG; 1458 1459 // check to see if user can add menus 1460 if (!has_capability('moodle/course:manageactivities', get_context_instance(CONTEXT_COURSE, $course->id))) { 1461 return false; 1462 } 1463 1464 static $resources = false; 1465 static $activities = false; 1466 1467 if ($resources === false) { 1468 $resources = array(); 1469 $activities = array(); 1470 1471 foreach($modnames as $modname=>$modnamestr) { 1472 if (!course_allowed_module($course, $modname)) { 1473 continue; 1474 } 1475 1476 $libfile = "$CFG->dirroot/mod/$modname/lib.php"; 1477 if (!file_exists($libfile)) { 1478 continue; 1479 } 1480 include_once($libfile); 1481 $gettypesfunc = $modname.'_get_types'; 1482 if (function_exists($gettypesfunc)) { 1483 $types = $gettypesfunc(); 1484 foreach($types as $type) { 1485 if (!isset($type->modclass) or !isset($type->typestr)) { 1486 debugging('Incorrect activity type in '.$modname); 1487 continue; 1488 } 1489 if ($type->modclass == MOD_CLASS_RESOURCE) { 1490 $resources[$type->type] = $type->typestr; 1491 } else { 1492 $activities[$type->type] = $type->typestr; 1493 } 1494 } 1495 } else { 1496 // all mods without type are considered activity 1497 $activities[$modname] = $modnamestr; 1498 } 1499 } 1500 } 1501 1502 $straddactivity = get_string('addactivity'); 1503 $straddresource = get_string('addresource'); 1504 1505 $output = '<div class="section_add_menus">'; 1506 1507 if (!$vertical) { 1508 $output .= '<div class="horizontal">'; 1509 } 1510 1511 if (!empty($resources)) { 1512 $output .= popup_form("$CFG->wwwroot/course/mod.php?id=$course->id&section=$section&sesskey=".sesskey()."&add=", 1513 $resources, "ressection$section", "", $straddresource, 'resource/types', $straddresource, true); 1514 } 1515 1516 if (!empty($activities)) { 1517 $output .= ' '; 1518 $output .= popup_form("$CFG->wwwroot/course/mod.php?id=$course->id&section=$section&sesskey=".sesskey()."&add=", 1519 $activities, "section$section", "", $straddactivity, 'mods', $straddactivity, true); 1520 } 1521 1522 if (!$vertical) { 1523 $output .= '</div>'; 1524 } 1525 1526 $output .= '</div>'; 1527 1528 if ($return) { 1529 return $output; 1530 } else { 1531 echo $output; 1532 } 1533 } 1534 1535 /** 1536 * Rebuilds the cached list of course activities stored in the database 1537 * @param int $courseid - id of course to rebuil, empty means all 1538 * @param boolean $clearonly - only clear the modinfo fields, gets rebuild automatically on the fly 1539 */ 1540 function rebuild_course_cache($courseid=0, $clearonly=false) { 1541 global $COURSE; 1542 1543 if ($clearonly) { 1544 $courseselect = empty($courseid) ? "" : "id = $courseid"; 1545 set_field_select('course', 'modinfo', null, $courseselect); 1546 // update cached global COURSE too ;-) 1547 if ($courseid == $COURSE->id) { 1548 $COURSE->modinfo = null; 1549 } 1550 // reset the fast modinfo cache 1551 $reset = 'reset'; 1552 get_fast_modinfo($reset); 1553 return; 1554 } 1555 1556 if ($courseid) { 1557 $select = "id = '$courseid'"; 1558 } else { 1559 $select = ""; 1560 @set_time_limit(0); // this could take a while! MDL-10954 1561 } 1562 1563 if ($rs = get_recordset_select("course", $select,'','id,fullname')) { 1564 while($course = rs_fetch_next_record($rs)) { 1565 $modinfo = serialize(get_array_of_activities($course->id)); 1566 if (!set_field("course", "modinfo", $modinfo, "id", $course->id)) { 1567 notify("Could not cache module information for course '" . format_string($course->fullname) . "'!"); 1568 } 1569 // update cached global COURSE too ;-) 1570 if ($course->id == $COURSE->id) { 1571 $COURSE->modinfo = $modinfo; 1572 } 1573 } 1574 rs_close($rs); 1575 } 1576 // reset the fast modinfo cache 1577 $reset = 'reset'; 1578 get_fast_modinfo($reset); 1579 } 1580 1581 function get_child_categories($parent) { 1582 /// Returns an array of the children categories for the given category 1583 /// ID by caching all of the categories in a static hash 1584 1585 static $allcategories = null; 1586 1587 // only fill in this variable the first time 1588 if (null == $allcategories) { 1589 $allcategories = array(); 1590 1591 $categories = get_categories(); 1592 foreach ($categories as $category) { 1593 if (empty($allcategories[$category->parent])) { 1594 $allcategories[$category->parent] = array(); 1595 } 1596 $allcategories[$category->parent][] = $category; 1597 } 1598 } 1599 1600 if (empty($allcategories[$parent])) { 1601 return array(); 1602 } else { 1603 return $allcategories[