PageRenderTime 53ms CodeModel.GetById 2ms app.highlight 39ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/lib/group.php

https://gitlab.com/mahara-contrib/janrain-auth
PHP | 1476 lines | 1049 code | 145 blank | 282 comment | 158 complexity | d499ce78c570722782f7b2e076d4c3dc MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * Mahara: Electronic portfolio, weblog, resume builder and social networking
   4 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
   5 *                         http://wiki.mahara.org/Contributors
   6 *
   7 * This program is free software: you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation, either version 3 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 *
  20 * @package    mahara
  21 * @subpackage core
  22 * @author     Catalyst IT Ltd
  23 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
  24 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
  25 *
  26 */
  27
  28defined('INTERNAL') || die();
  29
  30// Role related functions
  31
  32/**
  33 * Establishes what role a user has in a given group.
  34 *
  35 * If the user is not in the group, this returns false.
  36 *
  37 * @param mixed $groupid  ID of the group to check
  38 * @param mixed $userid   ID of the user to check. Defaults to the logged in 
  39 *                        user.
  40 * @return mixed          The role the user has in the group, or false if they 
  41 *                        have no role in the group
  42 */
  43function group_user_access($groupid, $userid=null, $refresh=null) {
  44    static $result;
  45
  46    if (!is_logged_in()) {
  47        return false;
  48    }
  49
  50    $groupid = group_param_groupid($groupid);
  51    $userid  = group_param_userid($userid);
  52
  53    if (isset($result[$groupid][$userid]) && !isset($refresh)) {
  54        return $result[$groupid][$userid];
  55    }
  56
  57    return $result[$groupid][$userid] = get_field('group_member', 'role', 'group', $groupid, 'member', $userid);
  58}
  59
  60/**
  61 * Returns whether the given user is the only administrator in the given group.
  62 *
  63 * If the user isn't in the group, or they're not an admin, or there is another admin, false 
  64 * is returned.
  65 *
  66 * @param int $groupid The ID of the group to check
  67 * @param int $userid  The ID of the user to check
  68 * @returns boolean
  69 */
  70function group_is_only_admin($groupid, $userid=null) {
  71    static $result;
  72
  73    $groupid = group_param_groupid($groupid);
  74    $userid  = group_param_userid($userid);
  75
  76    if (isset($result[$groupid][$userid])) {
  77        return $result[$groupid][$userid];
  78    }
  79
  80    return $result[$groupid][$userid] = (group_user_access($groupid, $userid) == 'admin'
  81        && count_records('group_member', 'group', $groupid, 'role', 'admin') == 1);
  82}
  83
  84/**
  85 * Returns whether the given user is allowed to change their role to the 
  86 * requested role in the given group.
  87 *
  88 * This function is checking whether _role changes_ are allowed, not if a user 
  89 * is allowed to be added to a group.
  90 *
  91 * @param int $groupid The ID of the group to check
  92 * @param int $userid  The ID of the user to check
  93 * @param string $role The role the user wishes to switch to
  94 * @returns boolean
  95 */
  96function group_can_change_role($groupid, $userid, $role) {
  97    $groupid = group_param_groupid($groupid);
  98    $userid  = group_param_userid($userid);
  99
 100    if (!group_user_access($groupid, $userid)) {
 101        return false;
 102    }
 103
 104    // Sole remaining admins can never change their role
 105    if (group_is_only_admin($groupid, $userid)) {
 106        return false;
 107    }
 108
 109    // admin role permissions check
 110    if ($role == 'admin') {
 111        $group = group_current_group();
 112        safe_require('grouptype', $group->grouptype);
 113        return call_static_method('GroupType' . $group->grouptype, 'can_become_admin', $userid);
 114    }
 115
 116    return true;
 117}
 118
 119/**
 120 * Changes a user role in a group, if this is allowed.
 121 *
 122 * @param int $groupid The ID of the group
 123 * @param int $userid  The ID of the user whose role needs changing
 124 * @param string $role The role the user wishes to switch to
 125 * @throws AccessDeniedException If the specified role change is not allowed. 
 126 *                               Check with group_can_change_role first if you 
 127 *                               need to.
 128 */
 129function group_change_role($groupid, $userid, $role) {
 130    // group_can_change_role checks whether the group and user parameters are valid
 131    if (!group_can_change_role($groupid, $userid, $role)) {
 132        throw new AccessDeniedException(get_string('usercannotchangetothisrole', 'group'));
 133    }
 134
 135    set_field('group_member', 'role', $role, 'group', $groupid, 'member', $userid);
 136}
 137
 138/**
 139 * Returns whether a user is allowed to edit views in a given group
 140 *
 141 * @param int $groupid The ID of the group
 142 * @param int $userid The ID of the user
 143 * @returns boolean
 144 */
 145function group_user_can_edit_views($groupid, $userid=null) {
 146    // root user can always do whatever it wants
 147    $sysuser = get_record('usr', 'username', 'root');
 148    if ($sysuser->id == $userid) {
 149        return true;
 150    }
 151
 152    if (!is_logged_in()) {
 153        return false;
 154    }
 155
 156    $groupid = group_param_groupid($groupid);
 157    $userid  = group_param_userid($userid);
 158
 159    return get_field_sql('
 160        SELECT
 161            r.edit_views
 162        FROM
 163            {group_member} m
 164            INNER JOIN {group} g ON (m.group = g.id AND g.deleted = 0)
 165            INNER JOIN {grouptype_roles} r ON (g.grouptype = r.grouptype AND m.role = r.role)
 166        WHERE
 167            m.group = ?
 168            AND m.member = ?', array($groupid, $userid));
 169}
 170
 171/**
 172 * Returns whether a user is allowed to assess views that have been submitted 
 173 * to the given group.
 174 *
 175 * @param int $groupid ID of group
 176 * @param int $userid  ID of user
 177 * @return boolean
 178 */
 179function group_user_can_assess_submitted_views($groupid, $userid) {
 180    $groupid = group_param_groupid($groupid);
 181    $userid  = group_param_userid($userid);
 182
 183    return get_field_sql('
 184        SELECT
 185            r.see_submitted_views
 186        FROM
 187            {group_member} m
 188            INNER JOIN {group} g ON (m.group = g.id AND g.deleted = 0)
 189            INNER JOIN {grouptype_roles} r ON (g.grouptype = r.grouptype AND r.role = m.role)
 190        WHERE
 191            m.member = ?
 192            AND m.group = ?', array($userid, $groupid));
 193}
 194
 195// Functions for creation/deletion of groups, and adding/removing users to groups
 196
 197/**
 198 * Creates a group.
 199 *
 200 * All group creation should be done through this function, as the 
 201 * implementation of group creation may change over time.
 202 *
 203 * @param array $data Data required to create the group. The following 
 204 * key/value pairs can be specified:
 205 *
 206 * - name: The group name [required, must be unique]
 207 * - description: The group description [optional, defaults to empty string]
 208 * - grouptype: The grouptype for the new group. Must be an installed grouptype.
 209 * - jointype: The jointype for the new group. One of 'open', 'invite', 
 210 *             'request' or 'controlled'
 211 * - ctime: The unix timestamp of the time the group will be recorded as having 
 212 *          been created. Defaults to the current time.
 213 * - members: Array of users who should be in the group, structured like this:
 214 *            array(
 215 *                userid => role,
 216 *                userid => role,
 217 *                ...
 218 *            )
 219 * @return int The ID of the created group
 220 */
 221function group_create($data) {
 222    if (!is_array($data)) {
 223        throw new InvalidArgumentException("group_create: data must be an array, see the doc comment for this "
 224            . "function for details on its format");
 225    }
 226
 227    if (!isset($data['name'])) {
 228        throw new InvalidArgumentException("group_create: must specify a name for the group");
 229    }
 230
 231    if (!isset($data['grouptype']) || !in_array($data['grouptype'], group_get_grouptypes())) {
 232        throw new InvalidArgumentException("group_create: grouptype specified must be an installed grouptype");
 233    }
 234
 235    safe_require('grouptype', $data['grouptype']);
 236
 237    if (isset($data['jointype'])) {
 238        if (!in_array($data['jointype'], call_static_method('GroupType' . $data['grouptype'], 'allowed_join_types'))) {
 239            throw new InvalidArgumentException("group_create: jointype specified is not allowed by the grouptype specified");
 240        }
 241    }
 242    else {
 243        throw new InvalidArgumentException("group_create: jointype specified must be one of the valid join types");
 244    }
 245
 246    if (!isset($data['ctime'])) {
 247        $data['ctime'] = time();
 248    }
 249    $data['ctime'] = db_format_timestamp($data['ctime']);
 250
 251    if (!is_array($data['members']) || count($data['members']) == 0) {
 252        throw new InvalidArgumentException("group_create: at least one member must be specified for adding to the group");
 253    }
 254
 255    $data['public'] = (isset($data['public'])) ? intval($data['public']) : 0;
 256    $data['usersautoadded'] = (isset($data['usersautoadded'])) ? intval($data['usersautoadded']) : 0;
 257
 258    db_begin();
 259
 260    $id = insert_record(
 261        'group',
 262        (object) array(
 263            'name'           => $data['name'],
 264            'description'    => $data['description'],
 265            'grouptype'      => $data['grouptype'],
 266            'category'       => $data['category'],
 267            'jointype'       => $data['jointype'],
 268            'ctime'          => $data['ctime'],
 269            'mtime'          => $data['ctime'],
 270            'public'         => $data['public'],
 271            'usersautoadded' => $data['usersautoadded'],
 272        ),
 273        'id',
 274        true
 275    );
 276
 277    foreach ($data['members'] as $userid => $role) {
 278        insert_record(
 279            'group_member',
 280            (object) array(
 281                'group'  => $id,
 282                'member' => $userid,
 283                'role'   => $role,
 284                'ctime'  => $data['ctime'],
 285            )
 286        );
 287    }
 288
 289    // Copy views for the new group
 290    $templates = get_column('view_autocreate_grouptype', 'view', 'grouptype', $data['grouptype']);
 291    $templates = get_records_sql_array("
 292        SELECT v.id, v.title, v.description 
 293        FROM {view} v
 294        INNER JOIN {view_autocreate_grouptype} vag ON vag.view = v.id
 295        WHERE vag.grouptype = 'standard'", array());
 296    if ($templates) {
 297        require_once(get_config('libroot') . 'view.php');
 298        foreach ($templates as $template) {
 299            list($view) = View::create_from_template(array(
 300                'group'       => $id,
 301                'title'       => $template->title,
 302                'description' => $template->description,
 303            ), $template->id);
 304            $view->set_access(array(array(
 305                'type'      => 'group',
 306                'id'        => $id,
 307                'startdate' => null,
 308                'stopdate'  => null,
 309                'role'      => null
 310            )));
 311        }
 312    }
 313
 314    $data['id'] = $id;
 315    // install the homepage
 316    if ($t = get_record('view', 'type', 'grouphomepage', 'template', 1, 'owner', 0)) {
 317        require_once('view.php');
 318        $template = new View($t->id, (array)$t);
 319        list($homepage) = View::create_from_template(array(
 320            'group' => $id,
 321            'title' => $template->get('title'),
 322            'description' => $template->get('description'),
 323            'type' => 'grouphomepage',
 324        ), $t->id, 0, false);
 325    }
 326    insert_record('view_access', (object) array(
 327        'view' => $homepage->get('id'),
 328        'accesstype' => $data['public'] ? 'public' : 'loggedin',
 329    ));
 330    handle_event('creategroup', $data);
 331    db_commit();
 332
 333    return $id;
 334}
 335
 336/**
 337 * Deletes a group.
 338 *
 339 * All group deleting should be done through this function, even though it is 
 340 * simple. What is required to perform group deletion may change over time.
 341 *
 342 * @param int $groupid The group to delete
 343 *
 344 * {{@internal Maybe later we can have a group_can_be_deleted function if 
 345 * necessary}}
 346 */
 347function group_delete($groupid) {
 348    $groupid = group_param_groupid($groupid);
 349    update_record('group',
 350        array(
 351            'deleted' => 1,
 352            'name' => get_field('group', 'name', 'id', $groupid) . '.deleted.' . time(),
 353        ),
 354        array(
 355            'id' => $groupid,
 356        )
 357    );
 358}
 359
 360/**
 361 * Adds a member to a group.
 362 *
 363 * Doesn't do any jointype checking, that should be handled by the caller.
 364 *
 365 * TODO: it should though. We should probably have group_user_can_be_added
 366 *
 367 * @param int $groupid
 368 * @param int $userid
 369 * @param string $role
 370 */
 371function group_add_user($groupid, $userid, $role=null) {
 372    $groupid = group_param_groupid($groupid);
 373    $userid  = group_param_userid($userid);
 374
 375    $gm = new StdClass;
 376    $gm->member = $userid;
 377    $gm->group = $groupid;
 378    $gm->ctime =  db_format_timestamp(time());
 379    if (!$role) {
 380        $role = get_field_sql('SELECT gt.defaultrole FROM {grouptype} gt, {group} g WHERE g.id = ? AND g.grouptype = gt.name', array($groupid));
 381    }
 382    $gm->role = $role;
 383
 384    db_begin();
 385    insert_record('group_member', $gm);
 386    delete_records('group_member_request', 'group', $groupid, 'member', $userid);
 387    handle_event('userjoinsgroup', $gm);
 388    db_commit();
 389}
 390
 391/**
 392 * Checks whether a user is allowed to leave a group.
 393 *
 394 * This checks things like if they're the owner and the group membership type
 395 *
 396 * @param mixed $group  DB record or ID of group to check
 397 * @param int   $userid (optional, will default to logged in user)
 398 */
 399function group_user_can_leave($group, $userid=null) {
 400    global $USER;
 401    static $result;
 402
 403    $userid = optional_userid($userid);
 404
 405    if (is_numeric($group)) {
 406        if (!$group = get_record('group', 'id', $group, 'deleted', 0)) {
 407            return false;
 408        }
 409    }
 410
 411    // Return cached value if we have it
 412    if (isset($result[$group->id][$userid])) {
 413        return $result[$group->id][$userid];
 414    }
 415
 416    if ($group->jointype == 'controlled' && group_user_access($group->id, $USER->get('id')) != 'admin') {
 417        return ($result[$group->id][$userid] = false);
 418    }
 419
 420    if (group_is_only_admin($group->id, $userid)) {
 421        return ($result[$group->id][$userid] = false);
 422    }
 423
 424    return ($result[$group->id][$userid] = true);
 425}
 426
 427/**
 428 * Removes a user from a group.
 429 *
 430 * @param int $groupid ID of group
 431 * @param int $userid  ID of user to remove
 432 */
 433function group_remove_user($groupid, $userid=null, $force=false) {
 434    // group_user_can_leave checks the validity of groupid and userid
 435    if (!$force && !group_user_can_leave($groupid, $userid)) {
 436        throw new AccessDeniedException(get_string('usercantleavegroup', 'group'));
 437    }
 438    delete_records('group_member', 'group', $groupid, 'member', $userid);
 439
 440    require_once(get_config('docroot') . 'interaction/lib.php');
 441    $interactions = get_column('interaction_instance', 'id', 'group', $groupid);
 442    foreach ($interactions as $interaction) {
 443        interaction_instance_from_id($interaction)->interaction_remove_user($userid);
 444    }
 445}
 446
 447/**
 448 * Invite a user to a group.
 449 *
 450 * @param object $group group
 451 * @param object $userid  User to invite
 452 * @param object $userfrom  User sending the invitation
 453 */
 454function group_invite_user($group, $userid, $userfrom, $role='member', $delay=null) {
 455    $user = optional_userobj($userid);
 456
 457    $data = new StdClass;
 458    $data->group = $group->id;
 459    $data->member= $user->id;
 460    $data->ctime = db_format_timestamp(time());
 461    $data->role = $role;
 462    ensure_record_exists('group_member_invite', $data, $data);
 463    $lang = get_user_language($user->id);
 464    require_once('activity.php');
 465    $activitydata = array(
 466        'users'   => array($user->id),
 467        'subject' => get_string_from_language($lang, 'invitetogroupsubject', 'group'),
 468        'message' => get_string_from_language($lang, 'invitetogroupmessage', 'group', display_name($userfrom, $user), $group->name),
 469        'url'     => get_config('wwwroot') . 'group/view.php?id=' . $group->id,
 470        'urltext' => $group->name,
 471    );
 472    activity_occurred('maharamessage', $activitydata, null, null, $delay);
 473}
 474
 475// Pieforms for various operations on groups
 476
 477/**
 478 * Form for users to join a given group
 479 */
 480function group_get_join_form($name, $groupid, $returnto='view') {
 481    return pieform(array(
 482        'name' => $name,
 483        'successcallback' => 'joingroup_submit',
 484        'autofocus' => false,
 485        'elements' => array(
 486            'join' => array(
 487                'type' => 'submit',
 488                'value' => get_string('joingroup', 'group')
 489            ),
 490            'group' => array(
 491                'type' => 'hidden',
 492                'value' => $groupid
 493            ),
 494            'returnto' => array(
 495                'type' => 'hidden',
 496                'value' => $returnto
 497            ),
 498        )
 499    ));
 500}
 501
 502/**
 503 * Form for accepting/declining a group invite
 504 */
 505function group_get_accept_form($name, $groupid, $returnto) {
 506    return pieform(array(
 507       'name'     => $name,
 508       'renderer' => 'oneline',
 509       'successcallback' => 'group_invite_submit',
 510       'elements' => array(
 511            'accept' => array(
 512                'type'  => 'submit',
 513                'value' => get_string('acceptinvitegroup', 'group')
 514            ),
 515            'decline' => array(
 516                'type'  => 'submit',
 517                'value' => get_string('declineinvitegroup', 'group')
 518            ),
 519            'group' => array(
 520                'type' => 'hidden',
 521                'value' => $groupid
 522            ),
 523            'returnto' => array(
 524                'type' => 'hidden',
 525                'value' => $returnto
 526            )
 527        )
 528    ));
 529}
 530
 531/**
 532 * Form for adding a user to a group
 533 */
 534function group_get_adduser_form($userid, $groupid) {
 535    return pieform(array(
 536        'name'                => 'adduser' . $userid,
 537        'successcallback'     => 'group_adduser_submit',
 538        'renderer'            => 'div',
 539        'elements'            => array(
 540            'group' => array(
 541                'type'    => 'hidden',
 542                'value' => $groupid,
 543            ),
 544            'member' => array(
 545                'type'  => 'hidden',
 546                'value' => $userid,
 547            ),
 548            'submit' => array(
 549                'type'  => 'submit',
 550                'value' => get_string('add') . ' ' . display_name($userid),
 551            ),
 552        ),
 553    ));
 554}
 555
 556/**
 557 * Form for removing a user from a group
 558 */
 559function group_get_removeuser_form($userid, $groupid) {
 560    require_once('pieforms/pieform.php');
 561    return pieform(array(
 562        'name'                => 'removeuser' . $userid,
 563        'validatecallback'    => 'group_removeuser_validate',
 564        'successcallback'     => 'group_removeuser_submit',
 565        'renderer'            => 'oneline',
 566        'elements'            => array(
 567            'group' => array(
 568                'type'    => 'hidden',
 569                'value' => $groupid,
 570            ),
 571            'member' => array(
 572                'type'  => 'hidden',
 573                'value' => $userid,
 574            ),
 575            'removeuser' => array(
 576                'type'  => 'submit',
 577                'value' => get_string('removefromgroup', 'group'),
 578            ),
 579        ),
 580    ));
 581}
 582
 583/**
 584 * Form for denying request (request jointype group)
 585 */
 586function group_get_denyuser_form($userid, $groupid) {
 587    require_once('pieforms/pieform.php');
 588    return pieform(array(
 589        'name'                => 'denyuser' . $userid,
 590        'successcallback'     => 'group_denyuser_submit',
 591        'renderer'            => 'oneline',
 592        'elements'            => array(
 593            'group' => array(
 594                'type'    => 'hidden',
 595                'value' => $groupid,
 596            ),
 597            'member' => array(
 598                'type'  => 'hidden',
 599                'value' => $userid,
 600            ),
 601            'denyuser' => array(
 602                'type'  => 'submit',
 603                'value' => get_string('declinerequest', 'group'),
 604            ),
 605        ),
 606    ));
 607}
 608
 609// Functions for handling submission of group related forms
 610
 611function joingroup_submit(Pieform $form, $values) {
 612    global $SESSION, $USER;
 613    group_add_user($values['group'], $USER->get('id'));
 614    $SESSION->add_ok_msg(get_string('joinedgroup', 'group'));
 615    if (substr($values['returnto'], 0, 1) == '/') {
 616        $next = $values['returnto'];
 617    }
 618    else {
 619        $next = '/group/view.php?id=' . $values['group'];
 620    }
 621    redirect($next);
 622}
 623
 624function group_invite_submit(Pieform $form, $values) {
 625    global $SESSION, $USER;
 626    $inviterecord = get_record('group_member_invite', 'member', $USER->get('id'), 'group', $values['group']);
 627    if ($inviterecord) {
 628        delete_records('group_member_invite', 'group', $values['group'], 'member', $USER->get('id'));
 629        if (isset($values['accept'])) {
 630            group_add_user($values['group'], $USER->get('id'), $inviterecord->role);
 631            $SESSION->add_ok_msg(get_string('groupinviteaccepted', 'group'));
 632            if (substr($values['returnto'], 0, 1) == '/') {
 633                $next = $values['returnto'];
 634            }
 635            else {
 636                $next = '/group/view.php?id=' . $values['group'];
 637            }
 638            redirect($next);
 639        }
 640        else {
 641            $SESSION->add_ok_msg(get_string('groupinvitedeclined', 'group'));
 642            redirect($values['returnto'] == 'find' ? '/group/find.php' : '/group/mygroups.php');
 643        }
 644    }
 645}
 646
 647function group_adduser_submit(Pieform $form, $values) {
 648    global $SESSION;
 649    $group = (int)$values['group'];
 650    if (group_user_access($group) != 'admin') {
 651        $SESSION->add_error_msg(get_string('accessdenied', 'error'));
 652        redirect('/group/members.php?id=' . $group . '&membershiptype=request');
 653    }
 654    group_add_user($group, $values['member']);
 655    $SESSION->add_ok_msg(get_string('useradded', 'group'));
 656    if (count_records('group_member_request', 'group', $group)) {
 657        redirect('/group/members.php?id=' . $group . '&membershiptype=request');
 658    }
 659    redirect('/group/members.php?id=' . $group);
 660}
 661
 662/**
 663 * Denying request (request jointype group)
 664 */
 665function group_denyuser_submit(Pieform $form, $values) {
 666    global $SESSION;
 667    $group = (int)$values['group'];
 668    if (group_user_access($group) != 'admin') {
 669        $SESSION->add_error_msg(get_string('accessdenied', 'error'));
 670        redirect('/group/members.php?id=' . $group . '&membershiptype=request');
 671    }
 672    delete_records('group_member_request', 'group', $values['group'], 'member', $values['member']);
 673    $SESSION->add_ok_msg(get_string('declinerequestsuccess', 'group'));
 674    if (count_records('group_member_request', 'group', $group)) {
 675        redirect('/group/members.php?id=' . $group . '&membershiptype=request');
 676    }
 677    redirect('/group/members.php?id=' . $group);
 678}
 679
 680function group_removeuser_validate(Pieform $form, $values) {
 681    global $user, $group, $SESSION;
 682    if (!group_user_can_leave($values['group'], $values['member'])) {
 683        $form->set_error('submit', get_string('usercantleavegroup', 'group'));
 684    }
 685}
 686
 687function group_removeuser_submit(Pieform $form, $values) {
 688    global $SESSION;
 689    $group = (int)$values['group'];
 690    if (group_user_access($group) != 'admin') {
 691        $SESSION->add_error_msg(get_string('accessdenied', 'error'));
 692        redirect('/group/members.php?id=' . $group);
 693    }
 694    group_remove_user($group, $values['member']);
 695    $SESSION->add_ok_msg(get_string('userremoved', 'group'));
 696    redirect('/group/members.php?id=' . $group);
 697}
 698
 699/**
 700 * Form for submitting views to a group
 701 */
 702function group_view_submission_form($groupid, $viewdata) {
 703    $options = array();
 704    foreach ($viewdata as $view) {
 705        if (empty($view->submittedgroup) && empty($view->submittedhost)) {
 706            $options[$view->id] = $view->title;
 707        }
 708    }
 709    if (empty($options)) {
 710        return;
 711    }
 712    return pieform(array(
 713        'name' => 'group_view_submission_form_' . $groupid,
 714        'method' => 'post',
 715        'renderer' => 'oneline',
 716        'autofocus' => false,
 717        'successcallback' => 'group_view_submission_form_submit',
 718        'elements' => array(
 719            'text1' => array(
 720                'type' => 'html', 'value' => get_string('submit', 'group') . ' ',
 721            ),
 722            'options' => array(
 723                'type' => 'select',
 724                'collapseifoneoption' => false,
 725                'options' => $options,
 726            ),
 727            'text2' => array(
 728                'type' => 'html',
 729                'value' => get_string('forassessment', 'view'),
 730            ),
 731            'submit' => array(
 732                'type' => 'submit',
 733                'value' => get_string('submit')
 734            ),
 735            'group' => array(
 736                'type' => 'hidden',
 737                'value' => $groupid
 738            ),
 739            'returnto' => array(
 740                'type' => 'hidden',
 741                'value' => get_config('wwwroot') . 'group/view.php?id=' . $groupid,
 742            ),
 743        ),
 744    ));
 745}
 746
 747function group_view_submission_form_submit(Pieform $form, $values) {
 748    redirect('/view/submit.php?id=' . $values['options'] . '&group=' . $values['group'] . '&returnto=group');
 749}
 750
 751// Miscellaneous group related functions
 752
 753/**
 754 * Returns a list of user IDs who are admins for a group
 755 *
 756 * @param int ID of group
 757 * @return array
 758 */
 759function group_get_admin_ids($groupid) {
 760    return (array)get_column_sql("SELECT \"member\"
 761        FROM {group_member}
 762        WHERE \"group\" = ?
 763        AND \"role\" = 'admin'", $groupid);
 764}
 765
 766/**
 767 * Gets information about what the roles in a given group are able to do
 768 *
 769 * @param int $groupid ID of group to get role information for
 770 * @return array
 771 */
 772function group_get_role_info($groupid) {
 773    $roles = get_records_sql_assoc('SELECT "role", edit_views, see_submitted_views, gr.grouptype FROM {grouptype_roles} gr
 774        INNER JOIN {group} g ON g.grouptype = gr.grouptype
 775        WHERE g.id = ?', array($groupid));
 776    foreach ($roles as $role) {
 777        $role->display = get_string($role->role, 'grouptype.'.$role->grouptype);
 778        $role->name = $role->role;
 779    }
 780    return $roles;
 781}
 782
 783function group_get_default_artefact_permissions($groupid) {
 784    $type = get_field('group', 'grouptype', 'id', $groupid);
 785    safe_require('grouptype', $type);
 786    return call_static_method('GroupType' . $type, 'default_artefact_rolepermissions');
 787}
 788
 789/**
 790 * Sets up groups for display in mygroups.php and find.php
 791 *
 792 * @param array $groups    Initial group data, including the current user's 
 793 *                         membership type in each group. See mygroups.php for
 794 *                         the query to build this information.
 795 * @param string $returnto Where forms generated for display should be told to return to
 796 */
 797function group_prepare_usergroups_for_display($groups, $returnto='mygroups') {
 798    if (!$groups) {
 799        return;
 800    }
 801
 802    // Retrieve a list of all the group admins, for placing in each $group object
 803    $groupadmins = array();
 804    $groupids = array_map(create_function('$a', 'return $a->id;'), $groups);
 805    if ($groupids) {
 806        $groupadmins = get_records_sql_array('SELECT "group", "member"
 807            FROM {group_member}
 808            WHERE "group" IN (' . implode(',', db_array_to_ph($groupids)) . ")
 809            AND \"role\" = 'admin'", $groupids);
 810        if (!$groupadmins) {
 811            $groupadmins = array();
 812        }
 813    }
 814
 815    $i = 0;
 816    foreach ($groups as $group) {
 817        $group->admins = array();
 818        foreach ($groupadmins as $admin) {
 819            if ($admin->group == $group->id) {
 820                $group->admins[] = $admin->member;
 821            }
 822        }
 823        if ($group->membershiptype == 'member') {
 824            $group->canleave = group_user_can_leave($group->id);
 825        }
 826        else if ($group->jointype == 'open') {
 827            $group->groupjoin = group_get_join_form('joingroup' . $i++, $group->id);
 828        }
 829        else if ($group->membershiptype == 'invite') {
 830            $group->invite = group_get_accept_form('invite' . $i++, $group->id, $returnto);
 831        }
 832        $group->settingsdescription = group_display_settings($group);
 833    }
 834}
 835
 836/*
 837 * Used by admin/groups/groups.php and admin/groups/groups.json.php for listing groups.
 838 */
 839function build_grouplist_html($query, $limit, $offset, &$count=null) {
 840
 841    $groups = search_group($query, $limit, $offset, 'all');
 842    $count = $groups['count'];
 843
 844    if ($ids = array_map(create_function('$a', 'return intval($a->id);'), $groups['data'])) {
 845        $sumsql = "(m.role = 'admin')";
 846        if (is_postgres()) {
 847            $sumsql .= '::int';
 848        }
 849
 850        // Member & admin counts
 851        $ids = join(',', $ids);
 852        $counts = get_records_sql_assoc("
 853            SELECT m.group, COUNT(m.member) AS members, SUM($sumsql) AS admins
 854            FROM {group_member} m
 855            WHERE m.group IN ($ids)
 856            GROUP BY m.group",
 857            array()
 858        );
 859    }
 860
 861    foreach ($groups['data'] as &$group) {
 862        $group->visibility = $group->public ? get_string('Public', 'group') : get_string('Members', 'group');
 863        $group->admins = empty($counts[$group->id]->admins) ? 0 : $counts[$group->id]->admins;
 864        $group->members = empty($counts[$group->id]->members) ? 0 : $counts[$group->id]->members;
 865        if (get_config('allowgroupcategories')) {
 866            $group->categorytitle = ($group->category) ? get_field('group_category', 'title', 'id', $group->category) : '';
 867        }
 868    }
 869
 870    $smarty = smarty_core();
 871    $smarty->assign('groups', $groups['data']);
 872    $data = array();
 873    $data['tablerows'] = $smarty->fetch('admin/groups/groupsresults.tpl');
 874
 875    $pagination = build_pagination(array(
 876                'id' => 'admgroupslist_pagination',
 877                'datatable' => 'admgroupslist',
 878                'url' => get_config('wwwroot') . 'admin/groups/groups.php' . (!empty($query) ? '?query=' . urlencode($query) : ''),
 879                'jsonscript' => 'admin/groups/groups.json.php',
 880                'count' => $count,
 881                'limit' => $limit,
 882                'offset' => $offset,
 883                'resultcounttextsingular' => get_string('group', 'group'),
 884                'resultcounttextplural' => get_string('groups', 'group'),
 885            ));
 886
 887    $data['pagination'] = $pagination['html'];
 888    $data['pagination_js'] = $pagination['javascript'];
 889
 890    return $data;
 891}
 892
 893function group_get_membersearch_data($results, $group, $query, $membershiptype) {
 894    global $USER;
 895
 896    $params = array();
 897    if (!empty($query)) {
 898        $params[] = 'query=' . $query;
 899    }
 900    $params[] = 'limit=' . $results['limit'];
 901    if (!empty($membershiptype)) {
 902        $params[] = 'membershiptype=' . $membershiptype;
 903    }
 904    $searchurl = get_config('wwwroot') . 'group/members.php?id=' . $group . '&amp;' . join('&amp;', $params);
 905
 906    $smarty = smarty_core();
 907
 908    $role = group_user_access($group);
 909    $userid = $USER->get('id');
 910    foreach ($results['data'] as &$r) {
 911        if ($role == 'admin' && ($r['id'] != $userid || group_user_can_leave($group, $r['id']))) {
 912            $r['removeform'] = group_get_removeuser_form($r['id'], $group);
 913        }
 914        // NOTE: this is a quick approximation. We should really check whether, 
 915        // for each role in the group, that the user can change to it (using 
 916        // group_can_change_role).  This only controls whether the 'change 
 917        // role' link appears though, so it doesn't matter too much. If the 
 918        // user clicks on this link, changerole.php does the full check and 
 919        // sends them back here saying that the user has no roles they can 
 920        // change to anyway.
 921        $r['canchangerole'] = !group_is_only_admin($group, $r['id']);
 922    }
 923
 924    if (!empty($membershiptype)) {
 925        if ($membershiptype == 'request') {
 926            foreach ($results['data'] as &$r) {
 927                $r['addform'] = group_get_adduser_form($r['id'], $group);
 928                $r['denyform'] = group_get_denyuser_form($r['id'], $group);
 929                // TODO: this will suck when there's quite a few on the page, 
 930                // would be better to grab all the reasons in one go
 931                $r['reason']  = get_field('group_member_request', 'reason', 'group', $group, 'member', $r['id']);
 932            }
 933        }
 934        $smarty->assign('membershiptype', $membershiptype);
 935    }
 936
 937    $results['cdata'] = array_chunk($results['data'], 2);
 938    $results['roles'] = group_get_role_info($group);
 939    $smarty->assign_by_ref('results', $results);
 940    $smarty->assign('searchurl', $searchurl);
 941    $smarty->assign('pagebaseurl', $searchurl);
 942    $smarty->assign('caneditroles', group_user_access($group) == 'admin');
 943    $smarty->assign('group', $group);
 944    $html = $smarty->fetch('group/membersearchresults.tpl');
 945
 946    $pagination = build_pagination(array(
 947        'id' => 'member_pagination',
 948        'class' => 'center',
 949        'url' => $searchurl,
 950        'count' => $results['count'],
 951        'limit' => $results['limit'],
 952        'offset' => $results['offset'],
 953        'datatable' => 'membersearchresults',
 954        'jsonscript' => 'group/membersearchresults.json.php',
 955        'firsttext' => '',
 956        'previoustext' => '',
 957        'nexttext' => '',
 958        'lasttext' => '',
 959        'numbersincludefirstlast' => false,
 960        'resultcounttextsingular' => get_string('member', 'group'),
 961        'resultcounttextplural' => get_string('members', 'group'),
 962    ));
 963
 964    return array($html, $pagination, $results['count'], $results['offset'], $membershiptype);
 965}
 966
 967
 968/**
 969 * Returns a list of available grouptypes
 970 *
 971 * @return array
 972 */
 973function group_get_grouptypes() {
 974    static $grouptypes = null;
 975
 976    if (is_null($grouptypes)) {
 977        $grouptypes = get_column('grouptype', 'name');
 978    }
 979
 980    return $grouptypes;
 981}
 982
 983
 984/**
 985 * Returns a list of grouptype & jointype options to be used in create
 986 * group/edit group drop-downs.
 987 * 
 988 * If there is more than one group type with the same join type,
 989 * prefix the join types with the group type for display.
 990 */
 991function group_get_grouptype_options($currentgrouptype=null) {
 992    $groupoptions = array();
 993    $jointypecount = array('open' => 0, 'invite' => 0, 'request' => 0, 'controlled' => 0);
 994    $grouptypes = group_get_grouptypes();
 995    $enabled = array_map(create_function('$a', 'return $a->name;'), plugins_installed('grouptype'));
 996    if (is_null($currentgrouptype) || in_array($currentgrouptype, $enabled)) {
 997        $grouptypes = array_intersect($enabled, $grouptypes);
 998    }
 999    foreach ($grouptypes as $grouptype) {
1000        safe_require('grouptype', $grouptype);
1001        if (call_static_method('GroupType' . $grouptype, 'can_be_created_by_user')) {
1002            $grouptypename = get_string('name', 'grouptype.' . $grouptype);
1003            foreach (call_static_method('GroupType' . $grouptype, 'allowed_join_types') as $jointype) {
1004                $jointypecount[$jointype]++;
1005                $groupoptions['jointype']["$grouptype.$jointype"] = get_string('membershiptype.'.$jointype, 'group');
1006                $groupoptions['grouptype']["$grouptype.$jointype"] = $grouptypename . ': ' . get_string('membershiptype.'.$jointype, 'group');
1007            }
1008        }
1009    }
1010    $duplicates = array_reduce($jointypecount, create_function('$a, $b', 'return $a || $b > 1;'));
1011    if ($duplicates) {
1012        return $groupoptions['grouptype'];
1013    }
1014    return $groupoptions['jointype'];
1015}
1016
1017/**
1018 * Returns a datastructure describing the tabs that appear on a group page
1019 *
1020 * @param object $group Database record of group to get tabs for
1021 * @return array
1022 */
1023function group_get_menu_tabs() {
1024    static $menu;
1025
1026    $group = group_current_group();
1027    if (!$group) {
1028        return null;
1029    }
1030    $menu = array(
1031        'info' => array(
1032            'path' => 'groups/info',
1033            'url' => 'group/view.php?id='.$group->id,
1034            'title' => get_string('About', 'group'),
1035            'weight' => 20
1036        ),
1037        'members' => array(
1038            'path' => 'groups/members',
1039            'url' => 'group/members.php?id='.$group->id,
1040            'title' => get_string('Members', 'group'),
1041            'weight' => 30
1042        ),
1043    );
1044    if ($group->public || group_user_access($group->id)) {
1045        $menu['forums'] = array(  // @todo: get this from a function in the interaction plugin (or better, make forums an artefact plugin)
1046            'path' => 'groups/forums',
1047            'url' => 'interaction/forum/index.php?group='.$group->id,
1048            'title' => get_string('nameplural', 'interaction.forum'),
1049            'weight' => 40,
1050        );
1051    }
1052    $menu['views'] = array(
1053        'path' => 'groups/views',
1054        'url' => 'view/groupviews.php?group='.$group->id,
1055        'title' => get_string('Views', 'group'),
1056        'weight' => 50,
1057    );
1058    $menu['share'] = array(
1059        'path' => 'groups/share',
1060        'url' => 'group/shareviews.php?group='.$group->id,
1061        'title' => get_string('share', 'view'),
1062        'weight' => 60,
1063    );
1064
1065    if (group_user_access($group->id)) {
1066        safe_require('grouptype', $group->grouptype);
1067        $artefactplugins = call_static_method('GroupType' . $group->grouptype, 'get_group_artefact_plugins');
1068        if ($plugins = get_records_array('artefact_installed', 'active', 1)) {
1069            foreach ($plugins as &$plugin) {
1070                if (!in_array($plugin->name, $artefactplugins)) {
1071                    continue;
1072                }
1073                safe_require('artefact', $plugin->name);
1074                $plugin_menu = call_static_method(generate_class_name('artefact',$plugin->name), 'group_tabs', $group->id);
1075                $menu = array_merge($menu, $plugin_menu);
1076            }
1077        }
1078    }
1079
1080    if (defined('MENUITEM')) {
1081        $key = substr(MENUITEM, strlen('groups/'));
1082        if ($key && isset($menu[$key])) {
1083            $menu[$key]['selected'] = true;
1084        }
1085    }
1086
1087    return $menu;
1088}
1089
1090/**
1091 * Used by this file to perform validation of group ID function arguments
1092 *
1093 * @param int $groupid
1094 * @return int
1095 * @throws InvalidArgumentException
1096 */
1097function group_param_groupid($groupid) {
1098    $groupid = (int)$groupid;
1099
1100    if ($groupid == 0) {
1101        throw new InvalidArgumentException("group_user_access: group argument should be an integer");
1102    }
1103
1104    return $groupid;
1105}
1106
1107/**
1108 * Used by this file to perform validation of user ID function arguments
1109 *
1110 * @param int $userid
1111 * @return int
1112 * @throws InvalidArgumentException
1113 */
1114function group_param_userid($userid) {
1115    if (is_null($userid)) {
1116        global $USER;
1117        $userid = (int)$USER->get('id');
1118    }
1119    else {
1120        $userid = (int)$userid;
1121    }
1122
1123    if ($userid == 0) {
1124        throw new InvalidArgumentException("group_user_access: user argument should be an integer");
1125    }
1126
1127    return $userid;
1128}
1129
1130
1131function group_current_group() {
1132    static $group;
1133
1134    // This function sometimes gets called by the smarty function
1135    // during the execution of a GroupNotFound exception.  This
1136    // variable prevents a 2nd exception from being thrown.  Perhaps
1137    // better achieved with a global in the exception handler?
1138    static $dying;
1139
1140    if (defined('GROUP') && !$dying) {
1141        $group = get_record_select('group', 'id = ? AND deleted = 0', array(GROUP), '*, ' . db_format_tsfield('ctime'));
1142        if (!$group) {
1143            $dying = 1;
1144            throw new GroupNotFoundException(get_string('groupnotfound', 'group', GROUP));
1145        }
1146    }
1147    else {
1148        $group = null;
1149    }
1150
1151    return $group;
1152}
1153
1154
1155/**
1156 * creates the group sideblock
1157 */
1158function group_sideblock() {
1159    require_once('group.php');
1160    $data['group'] = group_current_group();
1161    if (!$data['group']) {
1162        return null;
1163    }
1164    $data['menu'] = group_get_menu_tabs();
1165    // @todo either: remove this if interactions become group
1166    // artefacts, or: do this in interaction/lib.php if we leave them
1167    // as interactions
1168    $data['forums'] = get_records_select_array(
1169        'interaction_instance',
1170        '"group" = ? AND deleted = ? AND plugin = ?',
1171        array(GROUP, 0, 'forum'),
1172        'ctime',
1173        'id, plugin, title'
1174    );
1175    if (!$data['forums']) {
1176        $data['forums'] = array();
1177    }
1178    else {
1179        safe_require('interaction', 'forum');
1180        $data['forums'] = PluginInteractionForum::sideblock_sort($data['forums']);
1181    }
1182    return $data;
1183}
1184
1185
1186function group_get_associated_groups($userid, $filter='all', $limit=20, $offset=0, $category='') {
1187
1188    // Strangely, casting is only needed for invite, request and admin and only in 
1189    // postgres
1190    if (is_mysql()) {
1191        $invitesql  = "'invite'";
1192        $requestsql = "'request'";
1193        $adminsql   = "'admin'";
1194        $empty      = "''";
1195    }
1196    else {
1197        $invitesql  = "CAST('invite' AS TEXT)";
1198        $requestsql = "CAST('request' AS TEXT)";
1199        $adminsql   = "CAST('admin' AS TEXT)";
1200        $empty      = "CAST('' AS TEXT)";
1201    }
1202    // TODO: make it work on other databases?
1203
1204    // Different filters join on the different kinds of association
1205    if ($filter == 'admin') {
1206        $sql = "
1207            INNER JOIN (
1208                SELECT g.id, $adminsql AS membershiptype, $empty AS reason, $adminsql AS role
1209                FROM {group} g
1210                INNER JOIN {group_member} gm ON (gm.group = g.id AND gm.member = ? AND gm.role = 'admin')
1211            ) t ON t.id = g.id";
1212        $values = array($userid);
1213    }
1214    else if ($filter == 'member') {
1215        $sql = "
1216            INNER JOIN (
1217                SELECT g.id, 'admin' AS membershiptype, $empty AS reason, $adminsql AS role
1218                FROM {group} g
1219                INNER JOIN {group_member} gm ON (gm.group = g.id AND gm.member = ? AND gm.role = 'admin')
1220                UNION
1221                SELECT g.id, 'member' AS type, $empty AS reason, gm.role AS role
1222                FROM {group} g
1223                INNER JOIN {group_member} gm ON (gm.group = g.id AND gm.member = ? AND gm.role != 'admin')
1224            ) t ON t.id = g.id";
1225        $values = array($userid, $userid);
1226    }
1227    else if ($filter == 'invite') {
1228        $sql = "
1229            INNER JOIN (
1230                SELECT g.id, $invitesql AS membershiptype, gmi.reason, gmi.role
1231                FROM {group} g
1232                INNER JOIN {group_member_invite} gmi ON (gmi.group = g.id AND gmi.member = ?)
1233            ) t ON t.id = g.id";
1234        $values = array($userid);
1235    }
1236    else if ($filter == 'request') {
1237        $sql = "
1238            INNER JOIN (
1239                SELECT g.id, $requestsql AS membershiptype, gmr.reason, $empty AS role
1240                FROM {group} g
1241                INNER JOIN {group_member_request} gmr ON (gmr.group = g.id AND gmr.member = ?)
1242            ) t ON t.id = g.id";
1243        $values = array($userid);
1244    }
1245    else { // all or some other text
1246        $filter = 'all';
1247        $sql = "
1248            INNER JOIN (
1249                SELECT g.id, 'admin' AS membershiptype, '' AS reason, 'admin' AS role
1250                FROM {group} g
1251                INNER JOIN {group_member} gm ON (gm.group = g.id AND gm.member = ? AND gm.role = 'admin')
1252                UNION
1253                SELECT g.id, 'member' AS membershiptype, '' AS reason, gm.role AS role
1254                FROM {group} g
1255                INNER JOIN {group_member} gm ON (g.id = gm.group AND gm.member = ? AND gm.role != 'admin')
1256                UNION
1257                SELECT g.id, 'invite' AS membershiptype, gmi.reason, gmi.role
1258                FROM {group} g
1259                INNER JOIN {group_member_invite} gmi ON (gmi.group = g.id AND gmi.member = ?)
1260                UNION SELECT g.id, 'request' AS membershiptype, gmr.reason, '' AS role
1261                FROM {group} g
1262                INNER JOIN {group_member_request} gmr ON (gmr.group = g.id AND gmr.member = ?)
1263            ) t ON t.id = g.id";
1264        $values = array($userid, $userid, $userid, $userid);
1265    }
1266    
1267    $values[] = 0;
1268    
1269    $catsql = '';
1270    if (!empty($category)) {
1271        if ($category == -1) { //find unassigned groups
1272            $catsql = ' AND g.category IS NULL';
1273        } else {
1274            $catsql = ' AND g.category = ?';
1275            $values[] = $category;
1276        }
1277    }
1278
1279    $count = count_records_sql('SELECT COUNT(*) FROM {group} g ' . $sql . ' WHERE g.deleted = ?'.$catsql, $values);
1280    
1281    // almost the same as query used in find - common parts should probably be pulled out
1282    // gets the groups filtered by above
1283    // and the first three members by id
1284    
1285    $sql = 'SELECT g1.id, g1.name, g1.description, g1.public, g1.jointype, g1.grouptype, g1.membershiptype, g1.reason, g1.role, g1.membercount, COUNT(gmr.member) AS requests
1286        FROM (
1287        SELECT g.id, g.name, g.description, g.public, g.jointype, g.grouptype, t.membershiptype, t.reason, t.role, COUNT(gm.member) AS membercount
1288            FROM {group} g
1289            LEFT JOIN {group_member} gm ON (gm.group = g.id)' .
1290            $sql . '
1291            WHERE g.deleted = ?' .
1292            $catsql . '
1293            GROUP BY g.id, g.name, g.description, g.public, g.jointype, g.grouptype, t.membershiptype, t.reason, t.role
1294            ORDER BY g.name
1295        ) g1
1296        LEFT JOIN {group_member_request} gmr ON (gmr.group = g1.id)
1297        GROUP BY g1.id, g1.name, g1.description, g1.public, g1.jointype, g1.grouptype, g1.membershiptype, g1.reason, g1.role, g1.membercount';
1298
1299    $groups = get_records_sql_array($sql, $values, $offset, $limit);
1300    
1301    return array('groups' => $groups ? $groups : array(), 'count' => $count);
1302
1303}
1304
1305
1306function group_get_user_groups($userid=null, $roles=null) {
1307    static $usergroups = array();
1308
1309    if (is_null($userid)) {
1310        global $USER;
1311        $userid = $USER->get('id');
1312    }
1313
1314    if (empty($roles) && isset($usergroups[$userid])) {
1315        return $usergroups[$userid];
1316    }
1317
1318    if (!$groups = get_records_sql_array(
1319        "SELECT g.id, g.name, gm.role, g.jointype, g.grouptype, gtr.see_submitted_views, g.category
1320        FROM {group} g
1321        JOIN {group_member} gm ON (gm.group = g.id)
1322        JOIN {grouptype_roles} gtr ON (g.grouptype = gtr.grouptype AND gm.role = gtr.role)
1323        WHERE gm.member = ?
1324        AND g.deleted = 0 " . (is_array($roles) ? (' AND gm.role IN (' . join(',', array_map('db_quote', $roles)) . ')') : '') . "
1325        ORDER BY gm.role = 'admin' DESC, gm.role, g.id", array($userid))) {
1326        $groups = array();
1327    }
1328
1329    if (empty($roles)) {
1330        $usergroups[$userid] = $groups;
1331    }
1332
1333    return $groups;
1334}
1335
1336
1337function group_get_member_ids($group, $roles=null) {
1338    $rolesql = is_null($roles) ? '' : (' AND gm.role IN (' . join(',', array_map('db_quote', $roles)) . ')');
1339    return get_column_sql('
1340        SELECT gm.member
1341        FROM {group_member} gm INNER JOIN {group} g ON gm.group = g.id
1342        WHERE g.deleted = 0 AND g.id = ?' . $rolesql,
1343        array($group)
1344    );
1345}
1346
1347function group_can_create_groups() {
1348    global $USER;
1349    $creators = get_config('creategroups');
1350    if ($creators == 'all') {
1351        return true;
1352    }
1353    if ($USER->get('admin') || $USER->is_institutional_admin()) {
1354        return true;
1355    }
1356    return $creators == 'staff' && ($USER->get('staff') || $USER->is_institutional_staff());
1357}
1358
1359function group_get_user_course_groups($userid=null) {
1360    if (is_null($userid)) {
1361        global $USER;
1362        $userid = $USER->get('id');
1363    }
1364    if ($groups = get_records_sql_array(
1365        "SELECT g.id, g.name
1366        FROM {group_member} u
1367        INNER JOIN {group} g ON (u.group = g.id AND g.deleted = 0)
1368        INNER JOIN {grouptype} t ON t.name = g.grouptype
1369        WHERE u.member = ?
1370        AND t.submittableto = 1
1371        ORDER BY g.name
1372        ", array($userid))) {
1373        return $groups;
1374    }
1375    return array();
1376}
1377
1378function group_allows_submission($grouptype) {
1379    static $grouptypes = null;
1380    if (is_null($grouptypes)) {
1381        $grouptypes = get_records_assoc('grouptype');
1382    }
1383    return (bool) $grouptypes[$grouptype]->submittableto;
1384}
1385
1386function group_display_settings($group) {
1387    $string = get_string('membershiptype.'.$group->jointype, 'group');
1388    if (group_allows_submission($group->grouptype)) {
1389        $string .= ', ' . get_string('allowssubmissions', 'group');
1390    }
1391    if ($group->public) {
1392        $string .= ', ' . get_string('publiclyvisible', 'group');
1393    }
1394    return $string;
1395}
1396
1397/**
1398 * Return the view object for this group's homepage view
1399 *
1400 * @param int $groupid the id of the group to fetch the view for
1401 *
1402 * @throws ViewNotFoundException
1403 */
1404function group_get_homepage_view($groupid) {
1405    $v = get_record('view', 'group', $groupid, 'type', 'grouphomepage');
1406    return new View($v->id, (array)$v);
1407}
1408
1409/**
1410 * install the group homepage view
1411 * This creates a template at system level
1412 * which is subsequently copied to group hompages
1413 *
1414 * @return int the id of the new template
1415 */
1416function install_system_grouphomepage_view() {
1417    $dbtime = db_format_timestamp(time());
1418    // create a system template for group homepage views
1419    require_once(get_config('libroot') . 'view.php');
1420    $viewdata = (object) array(
1421        'type'        => 'grouphomepage',
1422        'owner'       => 0,
1423        'numcolumns'  => 1,
1424        'template'    => 1,
1425        'title'       => get_string('grouphomepage', 'view'),
1426        'ctime'       => $dbtime,
1427        'atime'       => $dbtime,
1428        'mtime'       => $dbtime,
1429    );
1430    $id = insert_record('view', $viewdata, 'id', true);
1431    $accessdata = (object) array('view' => $id, 'accesstype' => 'loggedin');
1432    insert_record('view_access', $accessdata);
1433    $blocktypes = array(
1434        array(
1435            'blocktype' => 'groupinfo',
1436            'title' => '',
1437            'column' => 1,
1438            'config' => null,
1439        ),
1440        array(
1441            'blocktype' => 'recentforumposts',
1442            'title' => get_string('latestforumposts', 'interaction.forum'),
1443            'column' => 1,
1444            'config' => null,
1445        ),
1446        array(
1447            'blo…

Large files files are truncated, but you can click here to view the full file