[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/course/ -> lib.php (source)

   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&amp;perpage=$perpage&amp;");
 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&amp;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}&amp;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&amp;perpage=$perpage&amp;");
 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&amp;perpage=$perpage&amp;");
 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('&', '&amp;', $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&amp;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&amp;perpage=$perpage&amp;");
 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('&', '&amp;', $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                   '&amp;user='.$userid.'&amp;type='.$type.'&amp;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&amp;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.'&amp;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 '&nbsp;&nbsp;';
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.'&amp;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&amp;section=$section&amp;sesskey=".sesskey()."&amp;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&amp;section=$section&amp;sesskey=".sesskey()."&amp;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[