[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/chat/ -> lib.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Library of functions and constants for module chat
  19   *
  20   * @package   mod_chat
  21   * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  require_once($CFG->dirroot.'/calendar/lib.php');
  28  
  29  // The HTML head for the message window to start with (<!-- nix --> is used to get some browsers starting with output.
  30  global $CHAT_HTMLHEAD;
  31  $CHAT_HTMLHEAD = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head></head>\n<body>\n\n".padding(200);
  32  
  33  // The HTML head for the message window to start with (with js scrolling).
  34  global $CHAT_HTMLHEAD_JS;
  35  $CHAT_HTMLHEAD_JS = <<<EOD
  36  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
  37  <html><head><script type="text/javascript">
  38  //<![CDATA[
  39  function move() {
  40      if (scroll_active)
  41          window.scroll(1,400000);
  42      window.setTimeout("move()",100);
  43  }
  44  var scroll_active = true;
  45  move();
  46  //]]>
  47  </script>
  48  </head>
  49  <body onBlur="scroll_active = true" onFocus="scroll_active = false">
  50  EOD;
  51  global $CHAT_HTMLHEAD_JS;
  52  $CHAT_HTMLHEAD_JS .= padding(200);
  53  
  54  // The HTML code for standard empty pages (e.g. if a user was kicked out).
  55  global $CHAT_HTMLHEAD_OUT;
  56  $CHAT_HTMLHEAD_OUT = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head><title>You are out!</title></head><body></body></html>";
  57  
  58  // The HTML head for the message input page.
  59  global $CHAT_HTMLHEAD_MSGINPUT;
  60  $CHAT_HTMLHEAD_MSGINPUT = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head><title>Message Input</title></head><body>";
  61  
  62  // The HTML code for the message input page, with JavaScript.
  63  global $CHAT_HTMLHEAD_MSGINPUT_JS;
  64  $CHAT_HTMLHEAD_MSGINPUT_JS = <<<EOD
  65  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
  66  <html>
  67      <head><title>Message Input</title>
  68      <script type="text/javascript">
  69      //<![CDATA[
  70      scroll_active = true;
  71      function empty_field_and_submit() {
  72          document.fdummy.arsc_message.value=document.f.arsc_message.value;
  73          document.fdummy.submit();
  74          document.f.arsc_message.focus();
  75          document.f.arsc_message.select();
  76          return false;
  77      }
  78      //]]>
  79      </script>
  80      </head><body OnLoad="document.f.arsc_message.focus();document.f.arsc_message.select();">;
  81  EOD;
  82  
  83  // Dummy data that gets output to the browser as needed, in order to make it show output.
  84  global $CHAT_DUMMY_DATA;
  85  $CHAT_DUMMY_DATA = padding(200);
  86  
  87  /**
  88   * @param int $n
  89   * @return string
  90   */
  91  function padding($n) {
  92      $str = '';
  93      for ($i = 0; $i < $n; $i++) {
  94          $str .= "<!-- nix -->\n";
  95      }
  96      return $str;
  97  }
  98  
  99  /**
 100   * Given an object containing all the necessary data,
 101   * (defined by the form in mod_form.php) this function
 102   * will create a new instance and return the id number
 103   * of the new instance.
 104   *
 105   * @global object
 106   * @param object $chat
 107   * @return int
 108   */
 109  function chat_add_instance($chat) {
 110      global $DB;
 111  
 112      $chat->timemodified = time();
 113  
 114      $returnid = $DB->insert_record("chat", $chat);
 115  
 116      $event = new stdClass();
 117      $event->name        = $chat->name;
 118      $event->description = format_module_intro('chat', $chat, $chat->coursemodule);
 119      $event->courseid    = $chat->course;
 120      $event->groupid     = 0;
 121      $event->userid      = 0;
 122      $event->modulename  = 'chat';
 123      $event->instance    = $returnid;
 124      $event->eventtype   = 'chattime';
 125      $event->timestart   = $chat->chattime;
 126      $event->timeduration = 0;
 127  
 128      calendar_event::create($event);
 129  
 130      return $returnid;
 131  }
 132  
 133  /**
 134   * Given an object containing all the necessary data,
 135   * (defined by the form in mod_form.php) this function
 136   * will update an existing instance with new data.
 137   *
 138   * @global object
 139   * @param object $chat
 140   * @return bool
 141   */
 142  function chat_update_instance($chat) {
 143      global $DB;
 144  
 145      $chat->timemodified = time();
 146      $chat->id = $chat->instance;
 147  
 148      $DB->update_record("chat", $chat);
 149  
 150      $event = new stdClass();
 151  
 152      if ($event->id = $DB->get_field('event', 'id', array('modulename' => 'chat', 'instance' => $chat->id))) {
 153  
 154          $event->name        = $chat->name;
 155          $event->description = format_module_intro('chat', $chat, $chat->coursemodule);
 156          $event->timestart   = $chat->chattime;
 157  
 158          $calendarevent = calendar_event::load($event->id);
 159          $calendarevent->update($event);
 160      }
 161  
 162      return true;
 163  }
 164  
 165  /**
 166   * Given an ID of an instance of this module,
 167   * this function will permanently delete the instance
 168   * and any data that depends on it.
 169   *
 170   * @global object
 171   * @param int $id
 172   * @return bool
 173   */
 174  function chat_delete_instance($id) {
 175      global $DB;
 176  
 177      if (! $chat = $DB->get_record('chat', array('id' => $id))) {
 178          return false;
 179      }
 180  
 181      $result = true;
 182  
 183      // Delete any dependent records here.
 184  
 185      if (! $DB->delete_records('chat', array('id' => $chat->id))) {
 186          $result = false;
 187      }
 188      if (! $DB->delete_records('chat_messages', array('chatid' => $chat->id))) {
 189          $result = false;
 190      }
 191      if (! $DB->delete_records('chat_messages_current', array('chatid' => $chat->id))) {
 192          $result = false;
 193      }
 194      if (! $DB->delete_records('chat_users', array('chatid' => $chat->id))) {
 195          $result = false;
 196      }
 197  
 198      if (! $DB->delete_records('event', array('modulename' => 'chat', 'instance' => $chat->id))) {
 199          $result = false;
 200      }
 201  
 202      return $result;
 203  }
 204  
 205  /**
 206   * Given a course and a date, prints a summary of all chat rooms past and present
 207   * This function is called from block_recent_activity
 208   *
 209   * @global object
 210   * @global object
 211   * @global object
 212   * @param object $course
 213   * @param bool $viewfullnames
 214   * @param int|string $timestart Timestamp
 215   * @return bool
 216   */
 217  function chat_print_recent_activity($course, $viewfullnames, $timestart) {
 218      global $CFG, $USER, $DB, $OUTPUT;
 219  
 220      // This is approximate only, but it is really fast.
 221      $timeout = $CFG->chat_old_ping * 10;
 222  
 223      if (!$mcms = $DB->get_records_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime
 224                                           FROM {course_modules} cm
 225                                           JOIN {modules} md        ON md.id = cm.module
 226                                           JOIN {chat} ch           ON ch.id = cm.instance
 227                                           JOIN {chat_messages} chm ON chm.chatid = ch.id
 228                                          WHERE chm.timestamp > ? AND ch.course = ? AND md.name = 'chat'
 229                                       GROUP BY cm.id
 230                                       ORDER BY lasttime ASC", array($timestart, $course->id))) {
 231           return false;
 232      }
 233  
 234      $past     = array();
 235      $current  = array();
 236      $modinfo = get_fast_modinfo($course); // Reference needed because we might load the groups.
 237  
 238      foreach ($mcms as $cmid => $mcm) {
 239          if (!array_key_exists($cmid, $modinfo->cms)) {
 240              continue;
 241          }
 242          $cm = $modinfo->cms[$cmid];
 243          if (!$modinfo->cms[$cm->id]->uservisible) {
 244              continue;
 245          }
 246  
 247          if (groups_get_activity_groupmode($cm) != SEPARATEGROUPS
 248           or has_capability('moodle/site:accessallgroups', context_module::instance($cm->id))) {
 249              if ($timeout > time() - $mcm->lasttime) {
 250                  $current[] = $cm;
 251              } else {
 252                  $past[] = $cm;
 253              }
 254  
 255              continue;
 256          }
 257  
 258          // Verify groups in separate mode.
 259          if (!$mygroupids = $modinfo->get_groups($cm->groupingid)) {
 260              continue;
 261          }
 262  
 263          // Ok, last post was not for my group - we have to query db to get last message from one of my groups.
 264          // The only minor problem is that the order will not be correct.
 265          $mygroupids = implode(',', $mygroupids);
 266  
 267          if (!$mcm = $DB->get_record_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime
 268                                             FROM {course_modules} cm
 269                                             JOIN {chat} ch           ON ch.id = cm.instance
 270                                             JOIN {chat_messages_current} chm ON chm.chatid = ch.id
 271                                            WHERE chm.timestamp > ? AND cm.id = ? AND
 272                                                  (chm.groupid IN ($mygroupids) OR chm.groupid = 0)
 273                                         GROUP BY cm.id", array($timestart, $cm->id))) {
 274               continue;
 275          }
 276  
 277          $mcms[$cmid]->lasttime = $mcm->lasttime;
 278          if ($timeout > time() - $mcm->lasttime) {
 279              $current[] = $cm;
 280          } else {
 281              $past[] = $cm;
 282          }
 283      }
 284  
 285      if (!$past and !$current) {
 286          return false;
 287      }
 288  
 289      $strftimerecent = get_string('strftimerecent');
 290  
 291      if ($past) {
 292          echo $OUTPUT->heading(get_string("pastchats", 'chat').':', 3);
 293  
 294          foreach ($past as $cm) {
 295              $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id;
 296              $date = userdate($mcms[$cm->id]->lasttime, $strftimerecent);
 297              echo '<div class="head"><div class="date">'.$date.'</div></div>';
 298              echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name, true).'</a></div>';
 299          }
 300      }
 301  
 302      if ($current) {
 303          echo $OUTPUT->heading(get_string("currentchats", 'chat').':', 3);
 304  
 305          $oldest = floor((time() - $CFG->chat_old_ping) / 10) * 10;  // Better db caching.
 306  
 307          $timeold    = time() - $CFG->chat_old_ping;
 308          $timeold    = floor($timeold / 10) * 10;  // Better db caching.
 309          $timeoldext = time() - ($CFG->chat_old_ping * 10); // JSless gui_basic needs much longer timeouts.
 310          $timeoldext = floor($timeoldext / 10) * 10;  // Better db caching.
 311  
 312          $params = array('timeold' => $timeold, 'timeoldext' => $timeoldext, 'cmid' => $cm->id);
 313  
 314          $timeout = "AND ((chu.version<>'basic' AND chu.lastping>:timeold) OR (chu.version='basic' AND chu.lastping>:timeoldext))";
 315  
 316          foreach ($current as $cm) {
 317              // Count users first.
 318              $mygroupids = $modinfo->groups[$cm->groupingid];
 319              if (!empty($mygroupids)) {
 320                  list($subquery, $subparams) = $DB->get_in_or_equal($mygroupids, SQL_PARAMS_NAMED, 'gid');
 321                  $params += $subparams;
 322                  $groupselect = "AND (chu.groupid $subquery OR chu.groupid = 0)";
 323              } else {
 324                  $groupselect = "";
 325              }
 326  
 327              $userfields = user_picture::fields('u');
 328              if (!$users = $DB->get_records_sql("SELECT $userfields
 329                                                    FROM {course_modules} cm
 330                                                    JOIN {chat} ch        ON ch.id = cm.instance
 331                                                    JOIN {chat_users} chu ON chu.chatid = ch.id
 332                                                    JOIN {user} u         ON u.id = chu.userid
 333                                                   WHERE cm.id = :cmid $timeout $groupselect
 334                                                GROUP BY $userfields", $params)) {
 335              }
 336  
 337              $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id;
 338              $date = userdate($mcms[$cm->id]->lasttime, $strftimerecent);
 339  
 340              echo '<div class="head"><div class="date">'.$date.'</div></div>';
 341              echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name, true).'</a></div>';
 342              echo '<div class="userlist">';
 343              if ($users) {
 344                  echo '<ul>';
 345                  foreach ($users as $user) {
 346                      echo '<li>'.fullname($user, $viewfullnames).'</li>';
 347                  }
 348                  echo '</ul>';
 349              }
 350              echo '</div>';
 351          }
 352      }
 353  
 354      return true;
 355  }
 356  
 357  /**
 358   * Function to be run periodically according to the moodle cron
 359   * This function searches for things that need to be done, such
 360   * as sending out mail, toggling flags etc ...
 361   *
 362   * @global object
 363   * @return bool
 364   */
 365  function chat_cron () {
 366      global $DB;
 367  
 368      chat_update_chat_times();
 369  
 370      chat_delete_old_users();
 371  
 372      // Delete old messages with a single SQL query.
 373      $subselect = "SELECT c.keepdays
 374                      FROM {chat} c
 375                     WHERE c.id = {chat_messages}.chatid";
 376  
 377      $sql = "DELETE
 378                FROM {chat_messages}
 379               WHERE ($subselect) > 0 AND timestamp < ( ".time()." -($subselect) * 24 * 3600)";
 380  
 381      $DB->execute($sql);
 382  
 383      $sql = "DELETE
 384                FROM {chat_messages_current}
 385               WHERE timestamp < ( ".time()." - 8 * 3600)";
 386  
 387      $DB->execute($sql);
 388  
 389      return true;
 390  }
 391  
 392  /**
 393   * This standard function will check all instances of this module
 394   * and make sure there are up-to-date events created for each of them.
 395   * If courseid = 0, then every chat event in the site is checked, else
 396   * only chat events belonging to the course specified are checked.
 397   * This function is used, in its new format, by restore_refresh_events()
 398   *
 399   * @global object
 400   * @param int $courseid
 401   * @return bool
 402   */
 403  function chat_refresh_events($courseid = 0) {
 404      global $DB;
 405  
 406      if ($courseid) {
 407          if (! $chats = $DB->get_records("chat", array("course" => $courseid))) {
 408              return true;
 409          }
 410      } else {
 411          if (! $chats = $DB->get_records("chat")) {
 412              return true;
 413          }
 414      }
 415      $moduleid = $DB->get_field('modules', 'id', array('name' => 'chat'));
 416  
 417      foreach ($chats as $chat) {
 418          $cm = get_coursemodule_from_instance('chat', $chat->id, $chat->course);
 419          $event = new stdClass();
 420          $event->name        = $chat->name;
 421          $event->description = format_module_intro('chat', $chat, $cm->id);
 422          $event->timestart   = $chat->chattime;
 423  
 424          if ($event->id = $DB->get_field('event', 'id', array('modulename' => 'chat', 'instance' => $chat->id))) {
 425              $calendarevent = calendar_event::load($event->id);
 426              $calendarevent->update($event);
 427          } else {
 428              $event->courseid    = $chat->course;
 429              $event->groupid     = 0;
 430              $event->userid      = 0;
 431              $event->modulename  = 'chat';
 432              $event->instance    = $chat->id;
 433              $event->eventtype   = 'chattime';
 434              $event->timeduration = 0;
 435              $event->visible = $DB->get_field('course_modules', 'visible', array('module' => $moduleid, 'instance' => $chat->id));
 436  
 437              calendar_event::create($event);
 438          }
 439      }
 440      return true;
 441  }
 442  
 443  // Functions that require some SQL.
 444  
 445  /**
 446   * @global object
 447   * @param int $chatid
 448   * @param int $groupid
 449   * @param int $groupingid
 450   * @return array
 451   */
 452  function chat_get_users($chatid, $groupid=0, $groupingid=0) {
 453      global $DB;
 454  
 455      $params = array('chatid' => $chatid, 'groupid' => $groupid, 'groupingid' => $groupingid);
 456  
 457      if ($groupid) {
 458          $groupselect = " AND (c.groupid=:groupid OR c.groupid='0')";
 459      } else {
 460          $groupselect = "";
 461      }
 462  
 463      if (!empty($groupingid)) {
 464          $groupingjoin = "JOIN {groups_members} gm ON u.id = gm.userid
 465                           JOIN {groupings_groups} gg ON gm.groupid = gg.groupid AND gg.groupingid = :groupingid ";
 466  
 467      } else {
 468          $groupingjoin = '';
 469      }
 470  
 471      $ufields = user_picture::fields('u');
 472      return $DB->get_records_sql("SELECT DISTINCT $ufields, c.lastmessageping, c.firstping
 473                                     FROM {chat_users} c
 474                                     JOIN {user} u ON u.id = c.userid $groupingjoin
 475                                    WHERE c.chatid = :chatid $groupselect
 476                                 ORDER BY c.firstping ASC", $params);
 477  }
 478  
 479  /**
 480   * @global object
 481   * @param int $chatid
 482   * @param int $groupid
 483   * @return array
 484   */
 485  function chat_get_latest_message($chatid, $groupid=0) {
 486      global $DB;
 487  
 488      $params = array('chatid' => $chatid, 'groupid' => $groupid);
 489  
 490      if ($groupid) {
 491          $groupselect = "AND (groupid=:groupid OR groupid=0)";
 492      } else {
 493          $groupselect = "";
 494      }
 495  
 496      $sql = "SELECT *
 497          FROM {chat_messages_current} WHERE chatid = :chatid $groupselect
 498          ORDER BY timestamp DESC";
 499  
 500      // Return the lastest one message.
 501      return $DB->get_record_sql($sql, $params, true);
 502  }
 503  
 504  /**
 505   * login if not already logged in
 506   *
 507   * @global object
 508   * @global object
 509   * @param int $chatid
 510   * @param string $version
 511   * @param int $groupid
 512   * @param object $course
 513   * @return bool|int Returns the chat users sid or false
 514   */
 515  function chat_login_user($chatid, $version, $groupid, $course) {
 516      global $USER, $DB;
 517  
 518      if (($version != 'sockets') and $chatuser = $DB->get_record('chat_users', array('chatid' => $chatid,
 519                                                                                      'userid' => $USER->id,
 520                                                                                      'groupid' => $groupid))) {
 521          // This will update logged user information.
 522          $chatuser->version  = $version;
 523          $chatuser->ip       = $USER->lastip;
 524          $chatuser->lastping = time();
 525          $chatuser->lang     = current_language();
 526  
 527          // Sometimes $USER->lastip is not setup properly during login.
 528          // Update with current value if possible or provide a dummy value for the db.
 529          if (empty($chatuser->ip)) {
 530              $chatuser->ip = getremoteaddr();
 531          }
 532  
 533          if (($chatuser->course != $course->id) or ($chatuser->userid != $USER->id)) {
 534              return false;
 535          }
 536          $DB->update_record('chat_users', $chatuser);
 537  
 538      } else {
 539          $chatuser = new stdClass();
 540          $chatuser->chatid   = $chatid;
 541          $chatuser->userid   = $USER->id;
 542          $chatuser->groupid  = $groupid;
 543          $chatuser->version  = $version;
 544          $chatuser->ip       = $USER->lastip;
 545          $chatuser->lastping = $chatuser->firstping = $chatuser->lastmessageping = time();
 546          $chatuser->sid      = random_string(32);
 547          $chatuser->course   = $course->id; // Caching - needed for current_language too.
 548          $chatuser->lang     = current_language(); // Caching - to resource intensive to find out later.
 549  
 550          // Sometimes $USER->lastip is not setup properly during login.
 551          // Update with current value if possible or provide a dummy value for the db.
 552          if (empty($chatuser->ip)) {
 553              $chatuser->ip = getremoteaddr();
 554          }
 555  
 556          $DB->insert_record('chat_users', $chatuser);
 557  
 558          if ($version == 'sockets') {
 559              // Do not send 'enter' message, chatd will do it.
 560          } else {
 561              chat_send_chatmessage($chatuser, 'enter', true);
 562          }
 563      }
 564  
 565      return $chatuser->sid;
 566  }
 567  
 568  /**
 569   * Delete the old and in the way
 570   *
 571   * @global object
 572   * @global object
 573   */
 574  function chat_delete_old_users() {
 575      // Delete the old and in the way.
 576      global $CFG, $DB;
 577  
 578      $timeold = time() - $CFG->chat_old_ping;
 579      $timeoldext = time() - ($CFG->chat_old_ping * 10); // JSless gui_basic needs much longer timeouts.
 580  
 581      $query = "(version<>'basic' AND lastping<?) OR (version='basic' AND lastping<?)";
 582      $params = array($timeold, $timeoldext);
 583  
 584      if ($oldusers = $DB->get_records_select('chat_users', $query, $params) ) {
 585          $DB->delete_records_select('chat_users', $query, $params);
 586          foreach ($oldusers as $olduser) {
 587              chat_send_chatmessage($olduser, 'exit', true);
 588          }
 589      }
 590  }
 591  
 592  /**
 593   * Updates chat records so that the next chat time is correct
 594   *
 595   * @global object
 596   * @param int $chatid
 597   * @return void
 598   */
 599  function chat_update_chat_times($chatid=0) {
 600      // Updates chat records so that the next chat time is correct.
 601      global $DB;
 602  
 603      $timenow = time();
 604  
 605      $params = array('timenow' => $timenow, 'chatid' => $chatid);
 606  
 607      if ($chatid) {
 608          if (!$chats[] = $DB->get_record_select("chat", "id = :chatid AND chattime <= :timenow AND schedule > 0", $params)) {
 609              return;
 610          }
 611      } else {
 612          if (!$chats = $DB->get_records_select("chat", "chattime <= :timenow AND schedule > 0", $params)) {
 613              return;
 614          }
 615      }
 616  
 617      foreach ($chats as $chat) {
 618          switch ($chat->schedule) {
 619              case 1: // Single event - turn off schedule and disable.
 620                  $chat->chattime = 0;
 621                  $chat->schedule = 0;
 622                  break;
 623              case 2: // Repeat daily.
 624                  while ($chat->chattime <= $timenow) {
 625                      $chat->chattime += 24 * 3600;
 626                  }
 627                  break;
 628              case 3: // Repeat weekly.
 629                  while ($chat->chattime <= $timenow) {
 630                      $chat->chattime += 7 * 24 * 3600;
 631                  }
 632                  break;
 633          }
 634          $DB->update_record("chat", $chat);
 635  
 636          $event = new stdClass(); // Update calendar too.
 637  
 638          $cond = "modulename='chat' AND instance = :chatid AND timestart <> :chattime";
 639          $params = array('chattime' => $chat->chattime, 'chatid' => $chat->id);
 640  
 641          if ($event->id = $DB->get_field_select('event', 'id', $cond, $params)) {
 642              $event->timestart   = $chat->chattime;
 643              $calendarevent = calendar_event::load($event->id);
 644              $calendarevent->update($event, false);
 645          }
 646      }
 647  }
 648  
 649  /**
 650   * Send a message on the chat.
 651   *
 652   * @param object $chatuser The chat user record.
 653   * @param string $messagetext The message to be sent.
 654   * @param bool $system False for non-system messages, true for system messages.
 655   * @param object $cm The course module object, pass it to save a database query when we trigger the event.
 656   * @return int The message ID.
 657   * @since Moodle 2.6
 658   */
 659  function chat_send_chatmessage($chatuser, $messagetext, $system = false, $cm = null) {
 660      global $DB;
 661  
 662      $message = new stdClass();
 663      $message->chatid    = $chatuser->chatid;
 664      $message->userid    = $chatuser->userid;
 665      $message->groupid   = $chatuser->groupid;
 666      $message->message   = $messagetext;
 667      $message->system    = $system ? 1 : 0;
 668      $message->timestamp = time();
 669  
 670      $messageid = $DB->insert_record('chat_messages', $message);
 671      $DB->insert_record('chat_messages_current', $message);
 672      $message->id = $messageid;
 673  
 674      if (!$system) {
 675  
 676          if (empty($cm)) {
 677              $cm = get_coursemodule_from_instance('chat', $chatuser->chatid, $chatuser->course);
 678          }
 679  
 680          $params = array(
 681              'context' => context_module::instance($cm->id),
 682              'objectid' => $message->id,
 683              // We set relateduserid, because when triggered from the chat daemon, the event userid is null.
 684              'relateduserid' => $chatuser->userid
 685          );
 686          $event = \mod_chat\event\message_sent::create($params);
 687          $event->add_record_snapshot('chat_messages', $message);
 688          $event->trigger();
 689      }
 690  
 691      return $message->id;
 692  }
 693  
 694  /**
 695   * @global object
 696   * @global object
 697   * @param object $message
 698   * @param int $courseid
 699   * @param object $sender
 700   * @param object $currentuser
 701   * @param string $chatlastrow
 702   * @return bool|string Returns HTML or false
 703   */
 704  function chat_format_message_manually($message, $courseid, $sender, $currentuser, $chatlastrow = null) {
 705      global $CFG, $USER, $OUTPUT;
 706  
 707      $output = new stdClass();
 708      $output->beep = false;       // By default.
 709      $output->refreshusers = false; // By default.
 710  
 711      // Find the correct timezone for displaying this message.
 712      $tz = core_date::get_user_timezone($currentuser);
 713  
 714      $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz);
 715  
 716      $message->picture = $OUTPUT->user_picture($sender, array('size' => false, 'courseid' => $courseid, 'link' => false));
 717  
 718      if ($courseid) {
 719          $message->picture = "<a onclick=\"window.open('$CFG->wwwroot/user/view.php?id=$sender->id&amp;course=$courseid')\"".
 720                              " href=\"$CFG->wwwroot/user/view.php?id=$sender->id&amp;course=$courseid\">$message->picture</a>";
 721      }
 722  
 723      // Calculate the row class.
 724      if ($chatlastrow !== null) {
 725          $rowclass = ' class="r'.$chatlastrow.'" ';
 726      } else {
 727          $rowclass = '';
 728      }
 729  
 730      // Start processing the message.
 731  
 732      if (!empty($message->system)) {
 733          // System event.
 734          $output->text = $message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender));
 735          $output->html  = '<table class="chat-event"><tr'.$rowclass.'><td class="picture">'.$message->picture.'</td>';
 736          $output->html .= '<td class="text"><span class="event">'.$output->text.'</span></td></tr></table>';
 737          $output->basic = '<tr class="r1">
 738                              <th scope="row" class="cell c1 title"></th>
 739                              <td class="cell c2 text">' . get_string('message'.$message->message, 'chat', fullname($sender)) . '</td>
 740                              <td class="cell c3">' . $message->strtime . '</td>
 741                            </tr>';
 742          if ($message->message == 'exit' or $message->message == 'enter') {
 743              $output->refreshusers = true; // Force user panel refresh ASAP.
 744          }
 745          return $output;
 746      }
 747  
 748      // It's not a system event.
 749      $text = trim($message->message);
 750  
 751      // Parse the text to clean and filter it.
 752      $options = new stdClass();
 753      $options->para = false;
 754      $options->blanktarget = true;
 755      $text = format_text($text, FORMAT_MOODLE, $options, $courseid);
 756  
 757      // And now check for special cases.
 758      $patternto = '#^\s*To\s([^:]+):(.*)#';
 759      $special = false;
 760  
 761      if (substr($text, 0, 5) == 'beep ') {
 762          // It's a beep!
 763          $special = true;
 764          $beepwho = trim(substr($text, 5));
 765  
 766          if ($beepwho == 'all') {   // Everyone.
 767              $outinfobasic = get_string('messagebeepseveryone', 'chat', fullname($sender));
 768              $outinfo = $message->strtime . ': ' . $outinfobasic;
 769              $outmain = '';
 770  
 771              $output->beep = true;  // Eventually this should be set to a filename uploaded by the user.
 772  
 773          } else if ($beepwho == $currentuser->id) {  // Current user.
 774              $outinfobasic = get_string('messagebeepsyou', 'chat', fullname($sender));
 775              $outinfo = $message->strtime . ': ' . $outinfobasic;
 776              $outmain = '';
 777              $output->beep = true;
 778  
 779          } else {  // Something is not caught?
 780              return false;
 781          }
 782      } else if (substr($text, 0, 1) == '/') {     // It's a user command.
 783          $special = true;
 784          $pattern = '#(^\/)(\w+).*#';
 785          preg_match($pattern, $text, $matches);
 786          $command = isset($matches[2]) ? $matches[2] : false;
 787          // Support some IRC commands.
 788          switch ($command) {
 789              case 'me':
 790                  $outinfo = $message->strtime;
 791                  $outmain = '*** <b>'.$sender->firstname.' '.substr($text, 4).'</b>';
 792                  break;
 793              default:
 794                  // Error, we set special back to false to use the classic message output.
 795                  $special = false;
 796                  break;
 797          }
 798      } else if (preg_match($patternto, $text)) {
 799          $special = true;
 800          $matches = array();
 801          preg_match($patternto, $text, $matches);
 802          if (isset($matches[1]) && isset($matches[2])) {
 803              $outinfo = $message->strtime;
 804              $outmain = $sender->firstname.' '.get_string('saidto', 'chat').' <i>'.$matches[1].'</i>: '.$matches[2];
 805          } else {
 806              // Error, we set special back to false to use the classic message output.
 807              $special = false;
 808          }
 809      }
 810  
 811      if (!$special) {
 812          $outinfo = $message->strtime.' '.$sender->firstname;
 813          $outmain = $text;
 814      }
 815  
 816      // Format the message as a small table.
 817  
 818      $output->text  = strip_tags($outinfo.': '.$outmain);
 819  
 820      $output->html  = "<table class=\"chat-message\"><tr$rowclass><td class=\"picture\" valign=\"top\">$message->picture</td>";
 821      $output->html .= "<td class=\"text\"><span class=\"title\">$outinfo</span>";
 822      if ($outmain) {
 823          $output->html .= ": $outmain";
 824          $output->basic = '<tr class="r0">
 825                              <th scope="row" class="cell c1 title">' . $sender->firstname . '</th>
 826                              <td class="cell c2 text">' . $outmain . '</td>
 827                              <td class="cell c3">' . $message->strtime . '</td>
 828                            </tr>';
 829      } else {
 830          $output->basic = '<tr class="r1">
 831                              <th scope="row" class="cell c1 title"></th>
 832                              <td class="cell c2 text">' . $outinfobasic . '</td>
 833                              <td class="cell c3">' . $message->strtime . '</td>
 834                            </tr>';
 835      }
 836      $output->html .= "</td></tr></table>";
 837      return $output;
 838  }
 839  
 840  /**
 841   * Given a message object this function formats it appropriately into text and html then returns the formatted data
 842   * @global object
 843   * @param object $message
 844   * @param int $courseid
 845   * @param object $currentuser
 846   * @param string $chatlastrow
 847   * @return bool|string Returns HTML or false
 848   */
 849  function chat_format_message($message, $courseid, $currentuser, $chatlastrow=null) {
 850      global $DB;
 851  
 852      static $users;     // Cache user lookups.
 853  
 854      if (isset($users[$message->userid])) {
 855          $user = $users[$message->userid];
 856      } else if ($user = $DB->get_record('user', array('id' => $message->userid), user_picture::fields())) {
 857          $users[$message->userid] = $user;
 858      } else {
 859          return null;
 860      }
 861      return chat_format_message_manually($message, $courseid, $user, $currentuser, $chatlastrow);
 862  }
 863  
 864  /**
 865   * @global object
 866   * @param object $message message to be displayed.
 867   * @param mixed $chatuser user chat data
 868   * @param object $currentuser current user for whom the message should be displayed.
 869   * @param int $groupingid course module grouping id
 870   * @param string $theme name of the chat theme.
 871   * @return bool|string Returns HTML or false
 872   */
 873  function chat_format_message_theme ($message, $chatuser, $currentuser, $groupingid, $theme = 'bubble') {
 874      global $CFG, $USER, $OUTPUT, $COURSE, $DB, $PAGE;
 875      require_once($CFG->dirroot.'/mod/chat/locallib.php');
 876  
 877      static $users;     // Cache user lookups.
 878  
 879      $result = new stdClass();
 880  
 881      if (file_exists($CFG->dirroot . '/mod/chat/gui_ajax/theme/'.$theme.'/config.php')) {
 882          include($CFG->dirroot . '/mod/chat/gui_ajax/theme/'.$theme.'/config.php');
 883      }
 884  
 885      if (isset($users[$message->userid])) {
 886          $sender = $users[$message->userid];
 887      } else if ($sender = $DB->get_record('user', array('id' => $message->userid), user_picture::fields())) {
 888          $users[$message->userid] = $sender;
 889      } else {
 890          return null;
 891      }
 892  
 893      // Find the correct timezone for displaying this message.
 894      $tz = core_date::get_user_timezone($currentuser);
 895  
 896      if (empty($chatuser->course)) {
 897          $courseid = $COURSE->id;
 898      } else {
 899          $courseid = $chatuser->course;
 900      }
 901  
 902      $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz);
 903      $message->picture = $OUTPUT->user_picture($sender, array('courseid' => $courseid));
 904  
 905      $message->picture = "<a target='_blank'".
 906                          " href=\"$CFG->wwwroot/user/view.php?id=$sender->id&amp;course=$courseid\">$message->picture</a>";
 907  
 908      // Start processing the message.
 909      if (!empty($message->system)) {
 910          $result->type = 'system';
 911  
 912          $senderprofile = $CFG->wwwroot.'/user/view.php?id='.$sender->id.'&amp;course='.$courseid;
 913          $event = get_string('message'.$message->message, 'chat', fullname($sender));
 914          $eventmessage = new event_message($senderprofile, fullname($sender), $message->strtime, $event, $theme);
 915  
 916          $output = $PAGE->get_renderer('mod_chat');
 917          $result->html = $output->render($eventmessage);
 918  
 919          return $result;
 920      }
 921  
 922      // It's not a system event.
 923      $text = trim($message->message);
 924  
 925      // Parse the text to clean and filter it.
 926      $options = new stdClass();
 927      $options->para = false;
 928      $options->blanktarget = true;
 929      $text = format_text($text, FORMAT_MOODLE, $options, $courseid);
 930  
 931      // And now check for special cases.
 932      $special = false;
 933      $outtime = $message->strtime;
 934  
 935      // Initialise variables.
 936      $outmain = '';
 937      $patternto = '#^\s*To\s([^:]+):(.*)#';
 938  
 939      if (substr($text, 0, 5) == 'beep ') {
 940          $special = true;
 941          // It's a beep!
 942          $result->type = 'beep';
 943          $beepwho = trim(substr($text, 5));
 944  
 945          if ($beepwho == 'all') {   // Everyone.
 946              $outmain = get_string('messagebeepseveryone', 'chat', fullname($sender));
 947          } else if ($beepwho == $currentuser->id) {  // Current user.
 948              $outmain = get_string('messagebeepsyou', 'chat', fullname($sender));
 949          } else if ($sender->id == $currentuser->id) {  // Something is not caught?
 950              // Allow beep for a active chat user only, else user can beep anyone and get fullname.
 951              if (!empty($chatuser) && is_numeric($beepwho)) {
 952                  $chatusers = chat_get_users($chatuser->chatid, $chatuser->groupid, $groupingid);
 953                  if (array_key_exists($beepwho, $chatusers)) {
 954                      $outmain = get_string('messageyoubeep', 'chat', fullname($chatusers[$beepwho]));
 955                  } else {
 956                      $outmain = get_string('messageyoubeep', 'chat', $beepwho);
 957                  }
 958              } else {
 959                  $outmain = get_string('messageyoubeep', 'chat', $beepwho);
 960              }
 961          }
 962      } else if (substr($text, 0, 1) == '/') {     // It's a user command.
 963          $special = true;
 964          $result->type = 'command';
 965          $pattern = '#(^\/)(\w+).*#';
 966          preg_match($pattern, $text, $matches);
 967          $command = isset($matches[2]) ? $matches[2] : false;
 968          // Support some IRC commands.
 969          switch ($command) {
 970              case 'me':
 971                  $outmain = '*** <b>'.$sender->firstname.' '.substr($text, 4).'</b>';
 972                  break;
 973              default:
 974                  // Error, we set special back to false to use the classic message output.
 975                  $special = false;
 976                  break;
 977          }
 978      } else if (preg_match($patternto, $text)) {
 979          $special = true;
 980          $result->type = 'dialogue';
 981          $matches = array();
 982          preg_match($patternto, $text, $matches);
 983          if (isset($matches[1]) && isset($matches[2])) {
 984              $outmain = $sender->firstname.' <b>'.get_string('saidto', 'chat').'</b> <i>'.$matches[1].'</i>: '.$matches[2];
 985          } else {
 986              // Error, we set special back to false to use the classic message output.
 987              $special = false;
 988          }
 989      }
 990  
 991      if (!$special) {
 992          $outmain = $text;
 993      }
 994  
 995      $result->text = strip_tags($outtime.': '.$outmain);
 996  
 997      $mymessageclass = '';
 998      if ($sender->id == $USER->id) {
 999          $mymessageclass = 'chat-message-mymessage';
1000      }
1001  
1002      $senderprofile = $CFG->wwwroot.'/user/view.php?id='.$sender->id.'&amp;course='.$courseid;
1003      $usermessage = new user_message($senderprofile, fullname($sender), $message->picture,
1004                                      $mymessageclass, $outtime, $outmain, $theme);
1005  
1006      $output = $PAGE->get_renderer('mod_chat');
1007      $result->html = $output->render($usermessage);
1008  
1009      // When user beeps other user, then don't show any timestamp to other users in chat.
1010      if (('' === $outmain) && $special) {
1011          return false;
1012      } else {
1013          return $result;
1014      }
1015  }
1016  
1017  /**
1018   * @global object $DB
1019   * @global object $CFG
1020   * @global object $COURSE
1021   * @global object $OUTPUT
1022   * @param object $users
1023   * @param object $course
1024   * @return array return formatted user list
1025   */
1026  function chat_format_userlist($users, $course) {
1027      global $CFG, $DB, $COURSE, $OUTPUT;
1028      $result = array();
1029      foreach ($users as $user) {
1030          $item = array();
1031          $item['name'] = fullname($user);
1032          $item['url'] = $CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$course->id;
1033          $item['picture'] = $OUTPUT->user_picture($user);
1034          $item['id'] = $user->id;
1035          $result[] = $item;
1036      }
1037      return $result;
1038  }
1039  
1040  /**
1041   * Print json format error
1042   * @param string $level
1043   * @param string $msg
1044   */
1045  function chat_print_error($level, $msg) {
1046      header('Content-Length: ' . ob_get_length() );
1047      $error = new stdClass();
1048      $error->level = $level;
1049      $error->msg   = $msg;
1050      $response['error'] = $error;
1051      echo json_encode($response);
1052      ob_end_flush();
1053      exit;
1054  }
1055  
1056  /**
1057   * List the actions that correspond to a view of this module.
1058   * This is used by the participation report.
1059   *
1060   * Note: This is not used by new logging system. Event with
1061   *       crud = 'r' and edulevel = LEVEL_PARTICIPATING will
1062   *       be considered as view action.
1063   *
1064   * @return array
1065   */
1066  function chat_get_view_actions() {
1067      return array('view', 'view all', 'report');
1068  }
1069  
1070  /**
1071   * List the actions that correspond to a post of this module.
1072   * This is used by the participation report.
1073   *
1074   * Note: This is not used by new logging system. Event with
1075   *       crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
1076   *       will be considered as post action.
1077   *
1078   * @return array
1079   */
1080  function chat_get_post_actions() {
1081      return array('talk');
1082  }
1083  
1084  /**
1085   * @global object
1086   * @global object
1087   * @param array $courses
1088   * @param array $htmlarray Passed by reference
1089   */
1090  function chat_print_overview($courses, &$htmlarray) {
1091      global $USER, $CFG;
1092  
1093      if (empty($courses) || !is_array($courses) || count($courses) == 0) {
1094          return array();
1095      }
1096  
1097      if (!$chats = get_all_instances_in_courses('chat', $courses)) {
1098          return;
1099      }
1100  
1101      $strchat = get_string('modulename', 'chat');
1102      $strnextsession  = get_string('nextsession', 'chat');
1103  
1104      foreach ($chats as $chat) {
1105          if ($chat->chattime and $chat->schedule) {  // A chat is scheduled.
1106              $str = '<div class="chat overview"><div class="name">'.
1107                     $strchat.': <a '.($chat->visible ? '' : ' class="dimmed"').
1108                     ' href="'.$CFG->wwwroot.'/mod/chat/view.php?id='.$chat->coursemodule.'">'.
1109                     $chat->name.'</a></div>';
1110              $str .= '<div class="info">'.$strnextsession.': '.userdate($chat->chattime).'</div></div>';
1111  
1112              if (empty($htmlarray[$chat->course]['chat'])) {
1113                  $htmlarray[$chat->course]['chat'] = $str;
1114              } else {
1115                  $htmlarray[$chat->course]['chat'] .= $str;
1116              }
1117          }
1118      }
1119  }
1120  
1121  
1122  /**
1123   * Implementation of the function for printing the form elements that control
1124   * whether the course reset functionality affects the chat.
1125   *
1126   * @param object $mform form passed by reference
1127   */
1128  function chat_reset_course_form_definition(&$mform) {
1129      $mform->addElement('header', 'chatheader', get_string('modulenameplural', 'chat'));
1130      $mform->addElement('advcheckbox', 'reset_chat', get_string('removemessages', 'chat'));
1131  }
1132  
1133  /**
1134   * Course reset form defaults.
1135   *
1136   * @param object $course
1137   * @return array
1138   */
1139  function chat_reset_course_form_defaults($course) {
1140      return array('reset_chat' => 1);
1141  }
1142  
1143  /**
1144   * Actual implementation of the reset course functionality, delete all the
1145   * chat messages for course $data->courseid.
1146   *
1147   * @global object
1148   * @global object
1149   * @param object $data the data submitted from the reset course.
1150   * @return array status array
1151   */
1152  function chat_reset_userdata($data) {
1153      global $CFG, $DB;
1154  
1155      $componentstr = get_string('modulenameplural', 'chat');
1156      $status = array();
1157  
1158      if (!empty($data->reset_chat)) {
1159          $chatessql = "SELECT ch.id
1160                          FROM {chat} ch
1161                         WHERE ch.course=?";
1162          $params = array($data->courseid);
1163  
1164          $DB->delete_records_select('chat_messages', "chatid IN ($chatessql)", $params);
1165          $DB->delete_records_select('chat_messages_current', "chatid IN ($chatessql)", $params);
1166          $DB->delete_records_select('chat_users', "chatid IN ($chatessql)", $params);
1167          $status[] = array('component' => $componentstr, 'item' => get_string('removemessages', 'chat'), 'error' => false);
1168      }
1169  
1170      // Updating dates - shift may be negative too.
1171      if ($data->timeshift) {
1172          shift_course_mod_dates('chat', array('chattime'), $data->timeshift, $data->courseid);
1173          $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false);
1174      }
1175  
1176      return $status;
1177  }
1178  
1179  /**
1180   * Returns all other caps used in module
1181   *
1182   * @return array
1183   */
1184  function chat_get_extra_capabilities() {
1185      return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames');
1186  }
1187  
1188  
1189  /**
1190   * @param string $feature FEATURE_xx constant for requested feature
1191   * @return mixed True if module supports feature, null if doesn't know
1192   */
1193  function chat_supports($feature) {
1194      switch($feature) {
1195          case FEATURE_GROUPS:
1196              return true;
1197          case FEATURE_GROUPINGS:
1198              return true;
1199          case FEATURE_MOD_INTRO:
1200              return true;
1201          case FEATURE_BACKUP_MOODLE2:
1202              return true;
1203          case FEATURE_COMPLETION_TRACKS_VIEWS:
1204              return true;
1205          case FEATURE_GRADE_HAS_GRADE:
1206              return false;
1207          case FEATURE_GRADE_OUTCOMES:
1208              return true;
1209          case FEATURE_SHOW_DESCRIPTION:
1210              return true;
1211          default:
1212              return null;
1213      }
1214  }
1215  
1216  function chat_extend_navigation($navigation, $course, $module, $cm) {
1217      global $CFG;
1218  
1219      $currentgroup = groups_get_activity_group($cm, true);
1220  
1221      if (has_capability('mod/chat:chat', context_module::instance($cm->id))) {
1222          $strenterchat    = get_string('enterchat', 'chat');
1223  
1224          $target = $CFG->wwwroot.'/mod/chat/';
1225          $params = array('id' => $cm->instance);
1226  
1227          if ($currentgroup) {
1228              $params['groupid'] = $currentgroup;
1229          }
1230  
1231          $links = array();
1232  
1233          $url = new moodle_url($target.'gui_'.$CFG->chat_method.'/index.php', $params);
1234          $action = new popup_action('click', $url, 'chat'.$course->id.$cm->instance.$currentgroup,
1235                                     array('height' => 500, 'width' => 700));
1236          $links[] = new action_link($url, $strenterchat, $action);
1237  
1238          $url = new moodle_url($target.'gui_basic/index.php', $params);
1239          $action = new popup_action('click', $url, 'chat'.$course->id.$cm->instance.$currentgroup,
1240                                     array('height' => 500, 'width' => 700));
1241          $links[] = new action_link($url, get_string('noframesjs', 'message'), $action);
1242  
1243          foreach ($links as $link) {
1244              $navigation->add($link->text, $link, navigation_node::TYPE_SETTING, null , null, new pix_icon('i/group' , ''));
1245          }
1246      }
1247  
1248      $chatusers = chat_get_users($cm->instance, $currentgroup, $cm->groupingid);
1249      if (is_array($chatusers) && count($chatusers) > 0) {
1250          $users = $navigation->add(get_string('currentusers', 'chat'));
1251          foreach ($chatusers as $chatuser) {
1252              $userlink = new moodle_url('/user/view.php', array('id' => $chatuser->id, 'course' => $course->id));
1253              $users->add(fullname($chatuser).' '.format_time(time() - $chatuser->lastmessageping),
1254                          $userlink, navigation_node::TYPE_USER, null, null, new pix_icon('i/user', ''));
1255          }
1256      }
1257  }
1258  
1259  /**
1260   * Adds module specific settings to the settings block
1261   *
1262   * @param settings_navigation $settings The settings navigation object
1263   * @param navigation_node $chatnode The node to add module settings to
1264   */
1265  function chat_extend_settings_navigation(settings_navigation $settings, navigation_node $chatnode) {
1266      global $DB, $PAGE, $USER;
1267      $chat = $DB->get_record("chat", array("id" => $PAGE->cm->instance));
1268  
1269      if ($chat->chattime && $chat->schedule) {
1270          $nextsessionnode = $chatnode->add(get_string('nextsession', 'chat').
1271                                            ': '.userdate($chat->chattime).
1272                                            ' ('.usertimezone($USER->timezone).')');
1273          $nextsessionnode->add_class('note');
1274      }
1275  
1276      $currentgroup = groups_get_activity_group($PAGE->cm, true);
1277      if ($currentgroup) {
1278          $groupselect = " AND groupid = '$currentgroup'";
1279      } else {
1280          $groupselect = '';
1281      }
1282  
1283      if ($chat->studentlogs || has_capability('mod/chat:readlog', $PAGE->cm->context)) {
1284          if ($DB->get_records_select('chat_messages', "chatid = ? $groupselect", array($chat->id))) {
1285              $chatnode->add(get_string('viewreport', 'chat'), new moodle_url('/mod/chat/report.php', array('id' => $PAGE->cm->id)));
1286          }
1287      }
1288  }
1289  
1290  /**
1291   * user logout event handler
1292   *
1293   * @param \core\event\user_loggedout $event The event.
1294   * @return void
1295   */
1296  function chat_user_logout(\core\event\user_loggedout $event) {
1297      global $DB;
1298      $DB->delete_records('chat_users', array('userid' => $event->objectid));
1299  }
1300  
1301  /**
1302   * Return a list of page types
1303   * @param string $pagetype current page type
1304   * @param stdClass $parentcontext Block's parent context
1305   * @param stdClass $currentcontext Current context of block
1306   */
1307  function chat_page_type_list($pagetype, $parentcontext, $currentcontext) {
1308      $modulepagetype = array('mod-chat-*' => get_string('page-mod-chat-x', 'chat'));
1309      return $modulepagetype;
1310  }
1311  
1312  /**
1313   * Return a list of the latest messages in the given chat session.
1314   *
1315   * @param  stdClass $chatuser     chat user session data
1316   * @param  int      $chatlasttime last time messages were retrieved
1317   * @return array    list of messages
1318   * @since  Moodle 3.0
1319   */
1320  function chat_get_latest_messages($chatuser, $chatlasttime) {
1321      global $DB;
1322  
1323      $params = array('groupid' => $chatuser->groupid, 'chatid' => $chatuser->chatid, 'lasttime' => $chatlasttime);
1324  
1325      $groupselect = $chatuser->groupid ? " AND (groupid=" . $chatuser->groupid . " OR groupid=0) " : "";
1326  
1327      return $DB->get_records_select('chat_messages_current', 'chatid = :chatid AND timestamp > :lasttime ' . $groupselect,
1328                                      $params, 'timestamp ASC');
1329  }
1330  
1331  /**
1332   * Mark the activity completed (if required) and trigger the course_module_viewed event.
1333   *
1334   * @param  stdClass $chat       chat object
1335   * @param  stdClass $course     course object
1336   * @param  stdClass $cm         course module object
1337   * @param  stdClass $context    context object
1338   * @since Moodle 3.0
1339   */
1340  function chat_view($chat, $course, $cm, $context) {
1341  
1342      // Trigger course_module_viewed event.
1343      $params = array(
1344          'context' => $context,
1345          'objectid' => $chat->id
1346      );
1347  
1348      $event = \mod_chat\event\course_module_viewed::create($params);
1349      $event->add_record_snapshot('course_modules', $cm);
1350      $event->add_record_snapshot('course', $course);
1351      $event->add_record_snapshot('chat', $chat);
1352      $event->trigger();
1353  
1354      // Completion.
1355      $completion = new completion_info($course);
1356      $completion->set_module_viewed($cm);
1357  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1