[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/ -> grouplib.php (source)

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  20   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21   * @package    core_group
  22   */
  23  
  24  defined('MOODLE_INTERNAL') || die();
  25  
  26  /**
  27   * Groups not used in course or activity
  28   */
  29  define('NOGROUPS', 0);
  30  
  31  /**
  32   * Groups used, users do not see other groups
  33   */
  34  define('SEPARATEGROUPS', 1);
  35  
  36  /**
  37   * Groups used, students see other groups
  38   */
  39  define('VISIBLEGROUPS', 2);
  40  
  41  
  42  /**
  43   * Determines if a group with a given groupid exists.
  44   *
  45   * @category group
  46   * @param int $groupid The groupid to check for
  47   * @return bool True if the group exists, false otherwise or if an error
  48   * occurred.
  49   */
  50  function groups_group_exists($groupid) {
  51      global $DB;
  52      return $DB->record_exists('groups', array('id'=>$groupid));
  53  }
  54  
  55  /**
  56   * Gets the name of a group with a specified id
  57   *
  58   * @category group
  59   * @param int $groupid The id of the group
  60   * @return string The name of the group
  61   */
  62  function groups_get_group_name($groupid) {
  63      global $DB;
  64      return $DB->get_field('groups', 'name', array('id'=>$groupid));
  65  }
  66  
  67  /**
  68   * Gets the name of a grouping with a specified id
  69   *
  70   * @category group
  71   * @param int $groupingid The id of the grouping
  72   * @return string The name of the grouping
  73   */
  74  function groups_get_grouping_name($groupingid) {
  75      global $DB;
  76      return $DB->get_field('groupings', 'name', array('id'=>$groupingid));
  77  }
  78  
  79  /**
  80   * Returns the groupid of a group with the name specified for the course.
  81   * Group names should be unique in course
  82   *
  83   * @category group
  84   * @param int $courseid The id of the course
  85   * @param string $name name of group (without magic quotes)
  86   * @return int $groupid
  87   */
  88  function groups_get_group_by_name($courseid, $name) {
  89      $data = groups_get_course_data($courseid);
  90      foreach ($data->groups as $group) {
  91          if ($group->name == $name) {
  92              return $group->id;
  93          }
  94      }
  95      return false;
  96  }
  97  
  98  /**
  99   * Returns the groupid of a group with the idnumber specified for the course.
 100   * Group idnumbers should be unique within course
 101   *
 102   * @category group
 103   * @param int $courseid The id of the course
 104   * @param string $idnumber idnumber of group
 105   * @return group object
 106   */
 107  function groups_get_group_by_idnumber($courseid, $idnumber) {
 108      if (empty($idnumber)) {
 109          return false;
 110      }
 111      $data = groups_get_course_data($courseid);
 112      foreach ($data->groups as $group) {
 113          if ($group->idnumber == $idnumber) {
 114              return $group;
 115          }
 116      }
 117      return false;
 118  }
 119  
 120  /**
 121   * Returns the groupingid of a grouping with the name specified for the course.
 122   * Grouping names should be unique in course
 123   *
 124   * @category group
 125   * @param int $courseid The id of the course
 126   * @param string $name name of group (without magic quotes)
 127   * @return int $groupid
 128   */
 129  function groups_get_grouping_by_name($courseid, $name) {
 130      $data = groups_get_course_data($courseid);
 131      foreach ($data->groupings as $grouping) {
 132          if ($grouping->name == $name) {
 133              return $grouping->id;
 134          }
 135      }
 136      return false;
 137  }
 138  
 139  /**
 140   * Returns the groupingid of a grouping with the idnumber specified for the course.
 141   * Grouping names should be unique within course
 142   *
 143   * @category group
 144   * @param int $courseid The id of the course
 145   * @param string $idnumber idnumber of the group
 146   * @return grouping object
 147   */
 148  function groups_get_grouping_by_idnumber($courseid, $idnumber) {
 149      if (empty($idnumber)) {
 150          return false;
 151      }
 152      $data = groups_get_course_data($courseid);
 153      foreach ($data->groupings as $grouping) {
 154          if ($grouping->idnumber == $idnumber) {
 155              return $grouping;
 156          }
 157      }
 158      return false;
 159  }
 160  
 161  /**
 162   * Get the group object
 163   *
 164   * @category group
 165   * @param int $groupid ID of the group.
 166   * @param string $fields (default is all fields)
 167   * @param int $strictness (IGNORE_MISSING - default)
 168   * @return stdGlass group object
 169   */
 170  function groups_get_group($groupid, $fields='*', $strictness=IGNORE_MISSING) {
 171      global $DB;
 172      return $DB->get_record('groups', array('id'=>$groupid), $fields, $strictness);
 173  }
 174  
 175  /**
 176   * Get the grouping object
 177   *
 178   * @category group
 179   * @param int $groupingid ID of the group.
 180   * @param string $fields
 181   * @param int $strictness (IGNORE_MISSING - default)
 182   * @return stdClass group object
 183   */
 184  function groups_get_grouping($groupingid, $fields='*', $strictness=IGNORE_MISSING) {
 185      global $DB;
 186      return $DB->get_record('groupings', array('id'=>$groupingid), $fields, $strictness);
 187  }
 188  
 189  /**
 190   * Gets array of all groups in a specified course.
 191   *
 192   * @category group
 193   * @param int $courseid The id of the course.
 194   * @param mixed $userid optional user id or array of ids, returns only groups of the user.
 195   * @param int $groupingid optional returns only groups in the specified grouping.
 196   * @param string $fields
 197   * @return array Returns an array of the group objects (userid field returned if array in $userid)
 198   */
 199  function groups_get_all_groups($courseid, $userid=0, $groupingid=0, $fields='g.*') {
 200      global $DB;
 201  
 202      // We need to check that we each field in the fields list belongs to the group table and that it has not being
 203      // aliased. If its something else we need to avoid the cache and run the query as who knows whats going on.
 204      $knownfields = true;
 205      if ($fields !== 'g.*') {
 206          // Quickly check if the first field is no longer g.id as using the
 207          // cache will return an array indexed differently than when expect
 208          if (strpos($fields, 'g.*') !== 0 && strpos($fields, 'g.id') !== 0) {
 209              $knownfields = false;
 210          } else {
 211              $fieldbits = explode(',', $fields);
 212              foreach ($fieldbits as $bit) {
 213                  $bit = trim($bit);
 214                  if (strpos($bit, 'g.') !== 0 or stripos($bit, ' AS ') !== false) {
 215                      $knownfields = false;
 216                      break;
 217                  }
 218              }
 219          }
 220      }
 221  
 222      if (empty($userid) && $knownfields) {
 223          // We can use the cache.
 224          $data = groups_get_course_data($courseid);
 225          if (empty($groupingid)) {
 226              // All groups.. Easy!
 227              $groups = $data->groups;
 228          } else {
 229              $groups = array();
 230              foreach ($data->mappings as $mapping) {
 231                  if ($mapping->groupingid != $groupingid) {
 232                      continue;
 233                  }
 234                  if (isset($data->groups[$mapping->groupid])) {
 235                      $groups[$mapping->groupid] = $data->groups[$mapping->groupid];
 236                  }
 237              }
 238          }
 239          // Yay! We could use the cache. One more query saved.
 240          return $groups;
 241      }
 242  
 243  
 244      if (empty($userid)) {
 245          $userfrom  = "";
 246          $userwhere = "";
 247          $params = array();
 248  
 249      } else {
 250          list($usql, $params) = $DB->get_in_or_equal($userid);
 251          $userfrom  = ", {groups_members} gm";
 252          $userwhere = "AND g.id = gm.groupid AND gm.userid $usql";
 253      }
 254  
 255      if (!empty($groupingid)) {
 256          $groupingfrom  = ", {groupings_groups} gg";
 257          $groupingwhere = "AND g.id = gg.groupid AND gg.groupingid = ?";
 258          $params[] = $groupingid;
 259      } else {
 260          $groupingfrom  = "";
 261          $groupingwhere = "";
 262      }
 263  
 264      array_unshift($params, $courseid);
 265  
 266      return $DB->get_records_sql("SELECT $fields
 267                                     FROM {groups} g $userfrom $groupingfrom
 268                                    WHERE g.courseid = ? $userwhere $groupingwhere
 269                                 ORDER BY name ASC", $params);
 270  }
 271  
 272  
 273  /**
 274   * Gets array of all groups in current user.
 275   *
 276   * @since Moodle 2.5
 277   * @category group
 278   * @return array Returns an array of the group objects.
 279   */
 280  function groups_get_my_groups() {
 281      global $DB, $USER;
 282      return $DB->get_records_sql("SELECT *
 283                                     FROM {groups_members} gm
 284                                     JOIN {groups} g
 285                                      ON g.id = gm.groupid
 286                                    WHERE gm.userid = ?
 287                                     ORDER BY name ASC", array($USER->id));
 288  }
 289  
 290  /**
 291   * Returns info about user's groups in course.
 292   *
 293   * @category group
 294   * @param int $courseid
 295   * @param int $userid $USER if not specified
 296   * @return array Array[groupingid][groupid] including grouping id 0 which means all groups
 297   */
 298  function groups_get_user_groups($courseid, $userid=0) {
 299      global $USER, $DB;
 300  
 301      if (empty($userid)) {
 302          $userid = $USER->id;
 303      }
 304  
 305      $sql = "SELECT g.id, gg.groupingid
 306                FROM {groups} g
 307                     JOIN {groups_members} gm   ON gm.groupid = g.id
 308                LEFT JOIN {groupings_groups} gg ON gg.groupid = g.id
 309               WHERE gm.userid = ? AND g.courseid = ?";
 310      $params = array($userid, $courseid);
 311  
 312      $rs = $DB->get_recordset_sql($sql, $params);
 313  
 314      if (!$rs->valid()) {
 315          $rs->close(); // Not going to iterate (but exit), close rs
 316          return array('0' => array());
 317      }
 318  
 319      $result    = array();
 320      $allgroups = array();
 321  
 322      foreach ($rs as $group) {
 323          $allgroups[$group->id] = $group->id;
 324          if (is_null($group->groupingid)) {
 325              continue;
 326          }
 327          if (!array_key_exists($group->groupingid, $result)) {
 328              $result[$group->groupingid] = array();
 329          }
 330          $result[$group->groupingid][$group->id] = $group->id;
 331      }
 332      $rs->close();
 333  
 334      $result['0'] = array_keys($allgroups); // all groups
 335  
 336      return $result;
 337  }
 338  
 339  /**
 340   * Gets an array of all groupings in a specified course. This value is cached
 341   * for a single course (so you can call it repeatedly for the same course
 342   * without a performance penalty).
 343   *
 344   * @category group
 345   * @param int $courseid return all groupings from course with this courseid
 346   * @return array Returns an array of the grouping objects (empty if none)
 347   */
 348  function groups_get_all_groupings($courseid) {
 349      $data = groups_get_course_data($courseid);
 350      return $data->groupings;
 351  }
 352  
 353  /**
 354   * Determines if the user is a member of the given group.
 355   *
 356   * If $userid is null, use the global object.
 357   *
 358   * @category group
 359   * @param int $groupid The group to check for membership.
 360   * @param int $userid The user to check against the group.
 361   * @return bool True if the user is a member, false otherwise.
 362   */
 363  function groups_is_member($groupid, $userid=null) {
 364      global $USER, $DB;
 365  
 366      if (!$userid) {
 367          $userid = $USER->id;
 368      }
 369  
 370      return $DB->record_exists('groups_members', array('groupid'=>$groupid, 'userid'=>$userid));
 371  }
 372  
 373  /**
 374   * Determines if current or specified is member of any active group in activity
 375   *
 376   * @category group
 377   * @staticvar array $cache
 378   * @param stdClass|cm_info $cm course module object
 379   * @param int $userid id of user, null means $USER->id
 380   * @return bool true if user member of at least one group used in activity
 381   */
 382  function groups_has_membership($cm, $userid=null) {
 383      global $CFG, $USER, $DB;
 384  
 385      static $cache = array();
 386  
 387      if (empty($userid)) {
 388          $userid = $USER->id;
 389      }
 390  
 391      $cachekey = $userid.'|'.$cm->course.'|'.$cm->groupingid;
 392      if (isset($cache[$cachekey])) {
 393          return($cache[$cachekey]);
 394      }
 395  
 396      if ($cm->groupingid) {
 397          // find out if member of any group in selected activity grouping
 398          $sql = "SELECT 'x'
 399                    FROM {groups_members} gm, {groupings_groups} gg
 400                   WHERE gm.userid = ? AND gm.groupid = gg.groupid AND gg.groupingid = ?";
 401          $params = array($userid, $cm->groupingid);
 402  
 403      } else {
 404          // no grouping used - check all groups in course
 405          $sql = "SELECT 'x'
 406                    FROM {groups_members} gm, {groups} g
 407                   WHERE gm.userid = ? AND gm.groupid = g.id AND g.courseid = ?";
 408          $params = array($userid, $cm->course);
 409      }
 410  
 411      $cache[$cachekey] = $DB->record_exists_sql($sql, $params);
 412  
 413      return $cache[$cachekey];
 414  }
 415  
 416  /**
 417   * Returns the users in the specified group.
 418   *
 419   * @category group
 420   * @param int $groupid The groupid to get the users for
 421   * @param int $fields The fields to return
 422   * @param int $sort optional sorting of returned users
 423   * @return array|bool Returns an array of the users for the specified
 424   * group or false if no users or an error returned.
 425   */
 426  function groups_get_members($groupid, $fields='u.*', $sort='lastname ASC') {
 427      global $DB;
 428  
 429      return $DB->get_records_sql("SELECT $fields
 430                                     FROM {user} u, {groups_members} gm
 431                                    WHERE u.id = gm.userid AND gm.groupid = ?
 432                                 ORDER BY $sort", array($groupid));
 433  }
 434  
 435  
 436  /**
 437   * Returns the users in the specified grouping.
 438   *
 439   * @category group
 440   * @param int $groupingid The groupingid to get the users for
 441   * @param string $fields The fields to return
 442   * @param string $sort optional sorting of returned users
 443   * @return array|bool Returns an array of the users for the specified
 444   * group or false if no users or an error returned.
 445   */
 446  function groups_get_grouping_members($groupingid, $fields='u.*', $sort='lastname ASC') {
 447      global $DB;
 448  
 449      return $DB->get_records_sql("SELECT $fields
 450                                     FROM {user} u
 451                                       INNER JOIN {groups_members} gm ON u.id = gm.userid
 452                                       INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid
 453                                    WHERE  gg.groupingid = ?
 454                                 ORDER BY $sort", array($groupingid));
 455  }
 456  
 457  /**
 458   * Returns effective groupmode used in course
 459   *
 460   * @category group
 461   * @param stdClass $course course object.
 462   * @return int group mode
 463   */
 464  function groups_get_course_groupmode($course) {
 465      return $course->groupmode;
 466  }
 467  
 468  /**
 469   * Returns effective groupmode used in activity, course setting
 470   * overrides activity setting if groupmodeforce enabled.
 471   *
 472   * If $cm is an instance of cm_info it is easier to use $cm->effectivegroupmode
 473   *
 474   * @category group
 475   * @param cm_info|stdClass $cm the course module object. Only the ->course and ->groupmode need to be set.
 476   * @param stdClass $course object optional course object to improve perf
 477   * @return int group mode
 478   */
 479  function groups_get_activity_groupmode($cm, $course=null) {
 480      if ($cm instanceof cm_info) {
 481          return $cm->effectivegroupmode;
 482      }
 483      if (isset($course->id) and $course->id == $cm->course) {
 484          //ok
 485      } else {
 486          // Get course object (reuse $COURSE if possible).
 487          $course = get_course($cm->course, false);
 488      }
 489  
 490      return empty($course->groupmodeforce) ? $cm->groupmode : $course->groupmode;
 491  }
 492  
 493  /**
 494   * Print group menu selector for course level.
 495   *
 496   * @category group
 497   * @param stdClass $course course object
 498   * @param mixed $urlroot return address. Accepts either a string or a moodle_url
 499   * @param bool $return return as string instead of printing
 500   * @return mixed void or string depending on $return param
 501   */
 502  function groups_print_course_menu($course, $urlroot, $return=false) {
 503      global $USER, $OUTPUT;
 504  
 505      if (!$groupmode = $course->groupmode) {
 506          if ($return) {
 507              return '';
 508          } else {
 509              return;
 510          }
 511      }
 512  
 513      $context = context_course::instance($course->id);
 514      $aag = has_capability('moodle/site:accessallgroups', $context);
 515  
 516      $usergroups = array();
 517      if ($groupmode == VISIBLEGROUPS or $aag) {
 518          $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
 519          // Get user's own groups and put to the top.
 520          $usergroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
 521      } else {
 522          $allowedgroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
 523      }
 524  
 525      $activegroup = groups_get_course_group($course, true, $allowedgroups);
 526  
 527      $groupsmenu = array();
 528      if (!$allowedgroups or $groupmode == VISIBLEGROUPS or $aag) {
 529          $groupsmenu[0] = get_string('allparticipants');
 530      }
 531  
 532      $groupsmenu += groups_sort_menu_options($allowedgroups, $usergroups);
 533  
 534      if ($groupmode == VISIBLEGROUPS) {
 535          $grouplabel = get_string('groupsvisible');
 536      } else {
 537          $grouplabel = get_string('groupsseparate');
 538      }
 539  
 540      if ($aag and $course->defaultgroupingid) {
 541          if ($grouping = groups_get_grouping($course->defaultgroupingid)) {
 542              $grouplabel = $grouplabel . ' (' . format_string($grouping->name) . ')';
 543          }
 544      }
 545  
 546      if (count($groupsmenu) == 1) {
 547          $groupname = reset($groupsmenu);
 548          $output = $grouplabel.': '.$groupname;
 549      } else {
 550          $select = new single_select(new moodle_url($urlroot), 'group', $groupsmenu, $activegroup, null, 'selectgroup');
 551          $select->label = $grouplabel;
 552          $output = $OUTPUT->render($select);
 553      }
 554  
 555      $output = '<div class="groupselector">'.$output.'</div>';
 556  
 557      if ($return) {
 558          return $output;
 559      } else {
 560          echo $output;
 561      }
 562  }
 563  
 564  /**
 565   * Turn an array of groups into an array of menu options.
 566   * @param array $groups of group objects.
 567   * @return array groupid => formatted group name.
 568   */
 569  function groups_list_to_menu($groups) {
 570      $groupsmenu = array();
 571      foreach ($groups as $group) {
 572          $groupsmenu[$group->id] = format_string($group->name);
 573      }
 574      return $groupsmenu;
 575  }
 576  
 577  /**
 578   * Takes user's allowed groups and own groups and formats for use in group selector menu
 579   * If user has allowed groups + own groups will add to an optgroup
 580   * Own groups are removed from allowed groups
 581   * @param array $allowedgroups All groups user is allowed to see
 582   * @param array $usergroups Groups user belongs to
 583   * @return array
 584   */
 585  function groups_sort_menu_options($allowedgroups, $usergroups) {
 586      $useroptions = array();
 587      if ($usergroups) {
 588          $useroptions = groups_list_to_menu($usergroups);
 589  
 590          // Remove user groups from other groups list.
 591          foreach ($usergroups as $group) {
 592              unset($allowedgroups[$group->id]);
 593          }
 594      }
 595  
 596      $allowedoptions = array();
 597      if ($allowedgroups) {
 598          $allowedoptions = groups_list_to_menu($allowedgroups);
 599      }
 600  
 601      if ($useroptions && $allowedoptions) {
 602          return array(
 603              1 => array(get_string('mygroups', 'group') => $useroptions),
 604              2 => array(get_string('othergroups', 'group') => $allowedoptions)
 605          );
 606      } else if ($useroptions) {
 607          return $useroptions;
 608      } else {
 609          return $allowedoptions;
 610      }
 611  }
 612  
 613  /**
 614   * Generates html to print menu selector for course level, listing all groups.
 615   * Note: This api does not do any group mode check use groups_print_course_menu() instead if you want proper checks.
 616   *
 617   * @param stdclass          $course  course object.
 618   * @param string|moodle_url $urlroot return address. Accepts either a string or a moodle_url.
 619   * @param bool              $update  set this to true to update current active group based on the group param.
 620   * @param int               $activegroup Change group active to this group if $update set to true.
 621   *
 622   * @return string html or void
 623   */
 624  function groups_allgroups_course_menu($course, $urlroot, $update = false, $activegroup = 0) {
 625      global $SESSION, $OUTPUT, $USER;
 626  
 627      $groupmode = groups_get_course_groupmode($course);
 628      $context = context_course::instance($course->id);
 629      $groupsmenu = array();
 630  
 631      if (has_capability('moodle/site:accessallgroups', $context)) {
 632          $groupsmenu[0] = get_string('allparticipants');
 633          $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
 634      } else {
 635          $allowedgroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
 636      }
 637  
 638      $groupsmenu += groups_list_to_menu($allowedgroups);
 639  
 640      if ($update) {
 641          // Init activegroup array if necessary.
 642          if (!isset($SESSION->activegroup)) {
 643              $SESSION->activegroup = array();
 644          }
 645          if (!isset($SESSION->activegroup[$course->id])) {
 646              $SESSION->activegroup[$course->id] = array(SEPARATEGROUPS => array(), VISIBLEGROUPS => array(), 'aag' => array());
 647          }
 648          if (empty($groupsmenu[$activegroup])) {
 649              $activegroup = key($groupsmenu); // Force set to one of accessible groups.
 650          }
 651          $SESSION->activegroup[$course->id][$groupmode][$course->defaultgroupingid] = $activegroup;
 652      }
 653  
 654      $grouplabel = get_string('groups');
 655      if (count($groupsmenu) == 0) {
 656          return '';
 657      } else if (count($groupsmenu) == 1) {
 658          $groupname = reset($groupsmenu);
 659          $output = $grouplabel.': '.$groupname;
 660      } else {
 661          $select = new single_select(new moodle_url($urlroot), 'group', $groupsmenu, $activegroup, null, 'selectgroup');
 662          $select->label = $grouplabel;
 663          $output = $OUTPUT->render($select);
 664      }
 665  
 666      return $output;
 667  
 668  }
 669  
 670  /**
 671   * Print group menu selector for activity.
 672   *
 673   * @category group
 674   * @param stdClass|cm_info $cm course module object
 675   * @param string|moodle_url $urlroot return address that users get to if they choose an option;
 676   *   should include any parameters needed, e.g. "$CFG->wwwroot/mod/forum/view.php?id=34"
 677   * @param bool $return return as string instead of printing
 678   * @param bool $hideallparticipants If true, this prevents the 'All participants'
 679   *   option from appearing in cases where it normally would. This is intended for
 680   *   use only by activities that cannot display all groups together. (Note that
 681   *   selecting this option does not prevent groups_get_activity_group from
 682   *   returning 0; it will still do that if the user has chosen 'all participants'
 683   *   in another activity, or not chosen anything.)
 684   * @return mixed void or string depending on $return param
 685   */
 686  function groups_print_activity_menu($cm, $urlroot, $return=false, $hideallparticipants=false) {
 687      global $USER, $OUTPUT;
 688  
 689      if ($urlroot instanceof moodle_url) {
 690          // no changes necessary
 691  
 692      } else {
 693          if (strpos($urlroot, 'http') !== 0) { // Will also work for https
 694              // Display error if urlroot is not absolute (this causes the non-JS version to break)
 695              debugging('groups_print_activity_menu requires absolute URL for ' .
 696                        '$urlroot, not <tt>' . s($urlroot) . '</tt>. Example: ' .
 697                        'groups_print_activity_menu($cm, $CFG->wwwroot . \'/mod/mymodule/view.php?id=13\');',
 698                        DEBUG_DEVELOPER);
 699          }
 700          $urlroot = new moodle_url($urlroot);
 701      }
 702  
 703      if (!$groupmode = groups_get_activity_groupmode($cm)) {
 704          if ($return) {
 705              return '';
 706          } else {
 707              return;
 708          }
 709      }
 710  
 711      $context = context_module::instance($cm->id);
 712      $aag = has_capability('moodle/site:accessallgroups', $context);
 713  
 714      $usergroups = array();
 715      if ($groupmode == VISIBLEGROUPS or $aag) {
 716          $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping
 717          // Get user's own groups and put to the top.
 718          $usergroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid);
 719      } else {
 720          $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
 721      }
 722  
 723      $activegroup = groups_get_activity_group($cm, true, $allowedgroups);
 724  
 725      $groupsmenu = array();
 726      if ((!$allowedgroups or $groupmode == VISIBLEGROUPS or $aag) and !$hideallparticipants) {
 727          $groupsmenu[0] = get_string('allparticipants');
 728      }
 729  
 730      $groupsmenu += groups_sort_menu_options($allowedgroups, $usergroups);
 731  
 732      if ($groupmode == VISIBLEGROUPS) {
 733          $grouplabel = get_string('groupsvisible');
 734      } else {
 735          $grouplabel = get_string('groupsseparate');
 736      }
 737  
 738      if ($aag and $cm->groupingid) {
 739          if ($grouping = groups_get_grouping($cm->groupingid)) {
 740              $grouplabel = $grouplabel . ' (' . format_string($grouping->name) . ')';
 741          }
 742      }
 743  
 744      if (count($groupsmenu) == 1) {
 745          $groupname = reset($groupsmenu);
 746          $output = $grouplabel.': '.$groupname;
 747      } else {
 748          $select = new single_select($urlroot, 'group', $groupsmenu, $activegroup, null, 'selectgroup');
 749          $select->label = $grouplabel;
 750          $output = $OUTPUT->render($select);
 751      }
 752  
 753      $output = '<div class="groupselector">'.$output.'</div>';
 754  
 755      if ($return) {
 756          return $output;
 757      } else {
 758          echo $output;
 759      }
 760  }
 761  
 762  /**
 763   * Returns group active in course, changes the group by default if 'group' page param present
 764   *
 765   * @category group
 766   * @param stdClass $course course bject
 767   * @param bool $update change active group if group param submitted
 768   * @param array $allowedgroups list of groups user may access (INTERNAL, to be used only from groups_print_course_menu())
 769   * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
 770   */
 771  function groups_get_course_group($course, $update=false, $allowedgroups=null) {
 772      global $USER, $SESSION;
 773  
 774      if (!$groupmode = $course->groupmode) {
 775          // NOGROUPS used
 776          return false;
 777      }
 778  
 779      $context = context_course::instance($course->id);
 780      if (has_capability('moodle/site:accessallgroups', $context)) {
 781          $groupmode = 'aag';
 782      }
 783  
 784      if (!is_array($allowedgroups)) {
 785          if ($groupmode == VISIBLEGROUPS or $groupmode === 'aag') {
 786              $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
 787          } else {
 788              $allowedgroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
 789          }
 790      }
 791  
 792      _group_verify_activegroup($course->id, $groupmode, $course->defaultgroupingid, $allowedgroups);
 793  
 794      // set new active group if requested
 795      $changegroup = optional_param('group', -1, PARAM_INT);
 796      if ($update and $changegroup != -1) {
 797  
 798          if ($changegroup == 0) {
 799              // do not allow changing to all groups without accessallgroups capability
 800              if ($groupmode == VISIBLEGROUPS or $groupmode === 'aag') {
 801                  $SESSION->activegroup[$course->id][$groupmode][$course->defaultgroupingid] = 0;
 802              }
 803  
 804          } else {
 805              if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
 806                  $SESSION->activegroup[$course->id][$groupmode][$course->defaultgroupingid] = $changegroup;
 807              }
 808          }
 809      }
 810  
 811      return $SESSION->activegroup[$course->id][$groupmode][$course->defaultgroupingid];
 812  }
 813  
 814  /**
 815   * Returns group active in activity, changes the group by default if 'group' page param present
 816   *
 817   * @category group
 818   * @param stdClass|cm_info $cm course module object
 819   * @param bool $update change active group if group param submitted
 820   * @param array $allowedgroups list of groups user may access (INTERNAL, to be used only from groups_print_activity_menu())
 821   * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
 822   */
 823  function groups_get_activity_group($cm, $update=false, $allowedgroups=null) {
 824      global $USER, $SESSION;
 825  
 826      if (!$groupmode = groups_get_activity_groupmode($cm)) {
 827          // NOGROUPS used
 828          return false;
 829      }
 830  
 831      $context = context_module::instance($cm->id);
 832      if (has_capability('moodle/site:accessallgroups', $context)) {
 833          $groupmode = 'aag';
 834      }
 835  
 836      if (!is_array($allowedgroups)) {
 837          if ($groupmode == VISIBLEGROUPS or $groupmode === 'aag') {
 838              $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid);
 839          } else {
 840              $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid);
 841          }
 842      }
 843  
 844      _group_verify_activegroup($cm->course, $groupmode, $cm->groupingid, $allowedgroups);
 845  
 846      // set new active group if requested
 847      $changegroup = optional_param('group', -1, PARAM_INT);
 848      if ($update and $changegroup != -1) {
 849  
 850          if ($changegroup == 0) {
 851              // allgroups visible only in VISIBLEGROUPS or when accessallgroups
 852              if ($groupmode == VISIBLEGROUPS or $groupmode === 'aag') {
 853                  $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
 854              }
 855  
 856          } else {
 857              if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
 858                  $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $changegroup;
 859              }
 860          }
 861      }
 862  
 863      return $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid];
 864  }
 865  
 866  /**
 867   * Gets a list of groups that the user is allowed to access within the
 868   * specified activity.
 869   *
 870   * @category group
 871   * @param stdClass|cm_info $cm Course-module
 872   * @param int $userid User ID (defaults to current user)
 873   * @return array An array of group objects, or false if none
 874   */
 875  function groups_get_activity_allowed_groups($cm,$userid=0) {
 876      // Use current user by default
 877      global $USER;
 878      if(!$userid) {
 879          $userid=$USER->id;
 880      }
 881  
 882      // Get groupmode for activity, taking into account course settings
 883      $groupmode=groups_get_activity_groupmode($cm);
 884  
 885      // If visible groups mode, or user has the accessallgroups capability,
 886      // then they can access all groups for the activity...
 887      $context = context_module::instance($cm->id);
 888      if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context, $userid)) {
 889          return groups_get_all_groups($cm->course, 0, $cm->groupingid);
 890      } else {
 891          // ...otherwise they can only access groups they belong to
 892          return groups_get_all_groups($cm->course, $userid, $cm->groupingid);
 893      }
 894  }
 895  
 896  /**
 897   * Determine if a given group is visible to user or not in a given context.
 898   *
 899   * @since Moodle 2.6
 900   * @param int      $groupid Group id to test. 0 for all groups.
 901   * @param stdClass $course  Course object.
 902   * @param stdClass $cm      Course module object.
 903   * @param int      $userid  user id to test against. Defaults to $USER.
 904   * @return boolean true if visible, false otherwise
 905   */
 906  function groups_group_visible($groupid, $course, $cm = null, $userid = null) {
 907      global $USER;
 908  
 909      if (empty($userid)) {
 910          $userid = $USER->id;
 911      }
 912  
 913      $groupmode = empty($cm) ? groups_get_course_groupmode($course) : groups_get_activity_groupmode($cm, $course);
 914      if ($groupmode == NOGROUPS || $groupmode == VISIBLEGROUPS) {
 915          // Groups are not used, or everything is visible, no need to go any further.
 916          return true;
 917      }
 918  
 919      $context = empty($cm) ? context_course::instance($course->id) : context_module::instance($cm->id);
 920      if (has_capability('moodle/site:accessallgroups', $context, $userid)) {
 921          // User can see everything. Groupid = 0 is handled here as well.
 922          return true;
 923      } else if ($groupid != 0) {
 924          // Group mode is separate, and user doesn't have access all groups capability. Check if user can see requested group.
 925          $groups = empty($cm) ? groups_get_all_groups($course->id, $userid) : groups_get_activity_allowed_groups($cm, $userid);
 926          if (array_key_exists($groupid, $groups)) {
 927              // User can see the group.
 928              return true;
 929          }
 930      }
 931      return false;
 932  }
 933  
 934  /**
 935   * Internal method, sets up $SESSION->activegroup and verifies previous value
 936   *
 937   * @param int $courseid
 938   * @param int|string $groupmode SEPARATEGROUPS, VISIBLEGROUPS or 'aag' (access all groups)
 939   * @param int $groupingid 0 means all groups
 940   * @param array $allowedgroups list of groups user can see
 941   */
 942  function _group_verify_activegroup($courseid, $groupmode, $groupingid, array $allowedgroups) {
 943      global $SESSION, $USER;
 944  
 945      // init activegroup array if necessary
 946      if (!isset($SESSION->activegroup)) {
 947          $SESSION->activegroup = array();
 948      }
 949      if (!array_key_exists($courseid, $SESSION->activegroup)) {
 950          $SESSION->activegroup[$courseid] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array(), 'aag'=>array());
 951      }
 952  
 953      // make sure that the current group info is ok
 954      if (array_key_exists($groupingid, $SESSION->activegroup[$courseid][$groupmode]) and !array_key_exists($SESSION->activegroup[$courseid][$groupmode][$groupingid], $allowedgroups)) {
 955          // active group does not exist anymore or is 0
 956          if ($SESSION->activegroup[$courseid][$groupmode][$groupingid] > 0 or $groupmode == SEPARATEGROUPS) {
 957              // do not do this if all groups selected and groupmode is not separate
 958              unset($SESSION->activegroup[$courseid][$groupmode][$groupingid]);
 959          }
 960      }
 961  
 962      // set up defaults if necessary
 963      if (!array_key_exists($groupingid, $SESSION->activegroup[$courseid][$groupmode])) {
 964          if ($groupmode == 'aag') {
 965              $SESSION->activegroup[$courseid][$groupmode][$groupingid] = 0; // all groups by default if user has accessallgroups
 966  
 967          } else if ($allowedgroups) {
 968              if ($groupmode != SEPARATEGROUPS and $mygroups = groups_get_all_groups($courseid, $USER->id, $groupingid)) {
 969                  $firstgroup = reset($mygroups);
 970              } else {
 971                  $firstgroup = reset($allowedgroups);
 972              }
 973              $SESSION->activegroup[$courseid][$groupmode][$groupingid] = $firstgroup->id;
 974  
 975          } else {
 976              // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
 977              // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
 978              $SESSION->activegroup[$courseid][$groupmode][$groupingid] = 0;
 979          }
 980      }
 981  }
 982  
 983  /**
 984   * Caches group data for a particular course to speed up subsequent requests.
 985   *
 986   * @param int $courseid The course id to cache data for.
 987   * @param cache $cache The cache if it has already been initialised. If not a new one will be created.
 988   * @return stdClass A data object containing groups, groupings, and mappings.
 989   */
 990  function groups_cache_groupdata($courseid, cache $cache = null) {
 991      global $DB;
 992  
 993      if ($cache === null) {
 994          // Initialise a cache if we wern't given one.
 995          $cache = cache::make('core', 'groupdata');
 996      }
 997  
 998      // Get the groups that belong to the course.
 999      $groups = $DB->get_records('groups', array('courseid' => $courseid), 'name ASC');
1000      // Get the groupings that belong to the course.
1001      $groupings = $DB->get_records('groupings', array('courseid' => $courseid), 'name ASC');
1002  
1003      if (!is_array($groups)) {
1004          $groups = array();
1005      }
1006  
1007      if (!is_array($groupings)) {
1008          $groupings = array();
1009      }
1010  
1011      if (!empty($groupings)) {
1012          // Finally get the mappings between the two.
1013          list($insql, $params) = $DB->get_in_or_equal(array_keys($groupings));
1014          $mappings = $DB->get_records_sql("
1015                  SELECT gg.id, gg.groupingid, gg.groupid
1016                    FROM {groupings_groups} gg
1017                    JOIN {groups} g ON g.id = gg.groupid
1018                   WHERE gg.groupingid $insql
1019                ORDER BY g.name ASC", $params);
1020      } else {
1021          $mappings = array();
1022      }
1023  
1024      // Prepare the data array.
1025      $data = new stdClass;
1026      $data->groups = $groups;
1027      $data->groupings = $groupings;
1028      $data->mappings = $mappings;
1029      // Cache the data.
1030      $cache->set($courseid, $data);
1031      // Finally return it so it can be used if desired.
1032      return $data;
1033  }
1034  
1035  /**
1036   * Gets group data for a course.
1037   *
1038   * This returns an object with the following properties:
1039   *   - groups : An array of all the groups in the course.
1040   *   - groupings : An array of all the groupings within the course.
1041   *   - mappings : An array of group to grouping mappings.
1042   *
1043   * @param int $courseid The course id to get data for.
1044   * @param cache $cache The cache if it has already been initialised. If not a new one will be created.
1045   * @return stdClass
1046   */
1047  function groups_get_course_data($courseid, cache $cache = null) {
1048      if ($cache === null) {
1049          // Initialise a cache if we wern't given one.
1050          $cache = cache::make('core', 'groupdata');
1051      }
1052      // Try to retrieve it from the cache.
1053      $data = $cache->get($courseid);
1054      if ($data === false) {
1055          $data = groups_cache_groupdata($courseid, $cache);
1056      }
1057      return $data;
1058  }
1059  
1060  /**
1061   * Determine if the current user can see at least one of the groups of the specified user.
1062   *
1063   * @param stdClass $course  Course object.
1064   * @param int $userid  user id to check against.
1065   * @param stdClass $cm Course module object. Optional, just for checking at activity level instead course one.
1066   * @return boolean true if visible, false otherwise
1067   * @since Moodle 2.9
1068   */
1069  function groups_user_groups_visible($course, $userid, $cm = null) {
1070      global $USER;
1071  
1072      $groupmode = empty($cm) ? groups_get_course_groupmode($course) : groups_get_activity_groupmode($cm, $course);
1073      if ($groupmode == NOGROUPS || $groupmode == VISIBLEGROUPS) {
1074          // Groups are not used, or everything is visible, no need to go any further.
1075          return true;
1076      }
1077  
1078      $context = empty($cm) ? context_course::instance($course->id) : context_module::instance($cm->id);
1079      if (has_capability('moodle/site:accessallgroups', $context)) {
1080          // User can see everything.
1081          return true;
1082      } else {
1083          // Group mode is separate, and user doesn't have access all groups capability.
1084          if (empty($cm)) {
1085              $usergroups = groups_get_all_groups($course->id, $userid);
1086              $currentusergroups = groups_get_all_groups($course->id, $USER->id);
1087          } else {
1088              $usergroups = groups_get_activity_allowed_groups($cm, $userid);
1089              $currentusergroups = groups_get_activity_allowed_groups($cm, $USER->id);
1090          }
1091  
1092          $samegroups = array_intersect_key($currentusergroups, $usergroups);
1093          if (!empty($samegroups)) {
1094              // We share groups!
1095              return true;
1096          }
1097      }
1098      return false;
1099  }


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