1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Group visibility methods 19 * 20 * @package core_group 21 * @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net} 22 * @author Mark Johnson <mark.johnson@catalyst-eu.net> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace core_group; 27 28 /** 29 * Group visibility methods. 30 */ 31 class visibility { 32 33 /** 34 * Store the number groups with visibility other than ALL on the course. 35 * 36 * @param int $courseid Course ID to update the cache for. 37 * @param \cache|null $cache Existing cache instance. If null, once will be created. 38 * @return void 39 * @throws \dml_exception 40 */ 41 public static function update_hiddengroups_cache(int $courseid, ?\cache $cache = null): void { 42 global $DB; 43 if (!$cache) { 44 $cache = \cache::make('core', 'coursehiddengroups'); 45 } 46 $hiddengroups = $DB->count_records_select('groups', 'courseid = ? AND visibility != ?', 47 [$courseid, GROUPS_VISIBILITY_ALL]); 48 $cache->set($courseid, $hiddengroups); 49 } 50 51 /** 52 * Return whether a course currently had hidden groups. 53 * 54 * This can be used as a shortcut to decide whether visibility restrictions need to be applied. If this returns false, 55 * we may be able to use cached data, or do a much simpler query. 56 * 57 * @param int $courseid 58 * @return bool 59 * @throws \coding_exception 60 * @throws \dml_exception 61 */ 62 public static function course_has_hidden_groups(int $courseid): bool { 63 $cache = \cache::make('core', 'coursehiddengroups'); 64 $hiddengroups = $cache->get($courseid); 65 if ($hiddengroups === false) { 66 self::update_hiddengroups_cache($courseid, $cache); 67 $cache->get($courseid); 68 } 69 return $hiddengroups > 0; 70 } 71 72 /** 73 * Can the current user view all the groups on the course? 74 * 75 * Returns true if there are no groups on the course with visibility != ALL, 76 * or if the user has viewhiddengroups. 77 * 78 * This is useful for deciding whether we need to perform additional visibility checkes 79 * such as the sql_* methods of this class. 80 * 81 * @param int $courseid 82 * @return bool 83 */ 84 public static function can_view_all_groups(int $courseid): bool { 85 $viewhidden = has_capability('moodle/course:viewhiddengroups', \context_course::instance($courseid)); 86 $hashidden = self::course_has_hidden_groups($courseid); 87 return $viewhidden || !$hashidden; 88 } 89 90 /** 91 * Return SQL conditions for determining whether a user can see a group and its memberships. 92 * 93 * @param int $userid 94 * @param string $groupsalias The SQL alias being used for the groups table. 95 * @param string $groupsmembersalias The SQL alias being used for the groups_members table. 96 * @return array [$where, $params] 97 */ 98 public static function sql_group_visibility_where(int $userid, 99 string $groupsalias = 'g', string $groupsmembersalias = 'gm'): array { 100 global $USER; 101 // Apply visibility restrictions. 102 // Everyone can see who is in groups with ALL visibility. 103 $where = "({$groupsalias}.visibility = :all"; 104 $params['all'] = GROUPS_VISIBILITY_ALL; 105 if ($userid == $USER->id) { 106 // If the user is looking at their own groups, they can see those with MEMBERS or OWN visibility. 107 $where .= " OR {$groupsalias}.visibility IN (:members, :own)"; 108 $params['members'] = GROUPS_VISIBILITY_MEMBERS; 109 $params['own'] = GROUPS_VISIBILITY_OWN; 110 } else { 111 list($memberssql, $membersparams) = self::sql_members_visibility_condition($groupsalias, $groupsmembersalias); 112 // If someone else's groups, they can see those with MEMBERS visibilty, only if they are a member too. 113 $where .= " OR ($memberssql)"; 114 $params = array_merge($params, $membersparams); 115 } 116 $where .= ")"; 117 return [$where, $params]; 118 } 119 120 /** 121 * Return SQL conditions for determining whether a user can see a group's members. 122 * 123 * @param string $groupsalias The SQL alias being used for the groups table. 124 * @param string $groupsmembersalias The SQL alias being used for the groups_members table. 125 * @param string $useralias The SQL alias being used for the user table. 126 * @param string $paramprefix Prefix for the parameter names. 127 * @return array [$where, $params] 128 */ 129 public static function sql_member_visibility_where( 130 string $groupsalias = 'g', 131 string $groupsmembersalias = 'gm', 132 string $useralias = 'u', 133 string $paramprefix = '', 134 ): array { 135 global $USER; 136 137 list($memberssql, $membersparams) = self::sql_members_visibility_condition($groupsalias, $groupsmembersalias, $paramprefix); 138 139 $where = "( 140 {$groupsalias}.visibility = :{$paramprefix}all 141 OR ($memberssql) 142 OR ({$groupsalias}.visibility = :{$paramprefix}own AND {$useralias}.id = :{$paramprefix}currentuser2) 143 )"; 144 $params = [ 145 "{$paramprefix}all" => GROUPS_VISIBILITY_ALL, 146 "{$paramprefix}own" => GROUPS_VISIBILITY_OWN, 147 "{$paramprefix}currentuser2" => $USER->id, 148 ]; 149 $params = array_merge($params, $membersparams); 150 return [$where, $params]; 151 } 152 153 /** 154 * Return a condition to check if a user can view a group because it has MEMBERS visibility and they are a member. 155 * 156 * @param string $groupsalias The SQL alias being used for the groups table. 157 * @param string $groupsmembersalias The SQL alias being used for the groups_members table. 158 * @param string $paramprefix Prefix for the parameter names. 159 * @return array [$sql, $params] 160 */ 161 protected static function sql_members_visibility_condition( 162 string $groupsalias = 'g', 163 string $groupsmembersalias = 'gm', 164 string $paramprefix = '', 165 ): array { 166 global $USER; 167 $sql = "{$groupsalias}.visibility = :{$paramprefix}members 168 AND ( 169 SELECT gm2.id 170 FROM {groups_members} gm2 171 WHERE gm2.groupid = {$groupsmembersalias}.groupid 172 AND gm2.userid = :{$paramprefix}currentuser 173 ) IS NOT NULL"; 174 $params = [ 175 "{$paramprefix}members" => GROUPS_VISIBILITY_MEMBERS, 176 "{$paramprefix}currentuser" => $USER->id 177 ]; 178 179 return [$sql, $params]; 180 } 181 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body