1 <?php 2 // This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>. 16 17 namespace core\context; 18 19 use core\context; 20 use stdClass; 21 use coding_exception, moodle_url; 22 23 /** 24 * User context class 25 * 26 * @package core_access 27 * @category access 28 * @copyright Petr Skoda 29 * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 * @since Moodle 4.2 31 */ 32 class user extends context { 33 /** @var int numeric context level value matching legacy CONTEXT_USER */ 34 public const LEVEL = 30; 35 36 /** 37 * Please use \core\context\user::instance($userid) if you need the instance of context. 38 * Alternatively if you know only the context id use \core\context::instance_by_id($contextid) 39 * 40 * @param stdClass $record 41 */ 42 protected function __construct(stdClass $record) { 43 parent::__construct($record); 44 if ($record->contextlevel != self::LEVEL) { 45 throw new coding_exception('Invalid $record->contextlevel in core\context\user constructor.'); 46 } 47 } 48 49 /** 50 * Returns short context name. 51 * 52 * @since Moodle 4.2 53 * 54 * @return string 55 */ 56 public static function get_short_name(): string { 57 return 'user'; 58 } 59 60 /** 61 * Returns human readable context level name. 62 * 63 * @return string the human readable context level name. 64 */ 65 public static function get_level_name() { 66 return get_string('user'); 67 } 68 69 /** 70 * Returns human readable context identifier. 71 * 72 * @param boolean $withprefix whether to prefix the name of the context with User 73 * @param boolean $short does not apply to user context 74 * @param boolean $escape does not apply to user context 75 * @return string the human readable context name. 76 */ 77 public function get_context_name($withprefix = true, $short = false, $escape = true) { 78 global $DB; 79 80 $name = ''; 81 if ($user = $DB->get_record('user', array('id' => $this->_instanceid, 'deleted' => 0))) { 82 if ($withprefix) { 83 $name = get_string('user').': '; 84 } 85 $name .= fullname($user); 86 } 87 return $name; 88 } 89 90 /** 91 * Returns the most relevant URL for this context. 92 * 93 * @return moodle_url 94 */ 95 public function get_url() { 96 global $COURSE; 97 98 if ($COURSE->id == SITEID) { 99 $url = new moodle_url('/user/profile.php', array('id' => $this->_instanceid)); 100 } else { 101 $url = new moodle_url('/user/view.php', array('id' => $this->_instanceid, 'courseid' => $COURSE->id)); 102 } 103 return $url; 104 } 105 106 /** 107 * Returns list of all possible parent context levels. 108 * @since Moodle 4.2 109 * 110 * @return int[] 111 */ 112 public static function get_possible_parent_levels(): array { 113 return [system::LEVEL]; 114 } 115 116 /** 117 * Returns context instance database name. 118 * 119 * @return string|null table name for all levels except system. 120 */ 121 protected static function get_instance_table(): ?string { 122 return 'user'; 123 } 124 125 /** 126 * Returns list of columns that can be used from behat 127 * to look up context by reference. 128 * 129 * @return array list of column names from instance table 130 */ 131 protected static function get_behat_reference_columns(): array { 132 return ['username']; 133 } 134 135 /** 136 * Returns array of relevant context capability records. 137 * 138 * @param string $sort 139 * @return array 140 */ 141 public function get_capabilities(string $sort = self::DEFAULT_CAPABILITY_SORT) { 142 global $DB; 143 144 $extracaps = array('moodle/grade:viewall'); 145 list($extra, $params) = $DB->get_in_or_equal($extracaps, SQL_PARAMS_NAMED, 'cap'); 146 147 return $DB->get_records_select('capabilities', "contextlevel = :level OR name {$extra}", 148 $params + ['level' => self::LEVEL], $sort); 149 } 150 151 /** 152 * Returns user context instance. 153 * 154 * @param int $userid id from {user} table 155 * @param int $strictness 156 * @return user|false context instance 157 */ 158 public static function instance($userid, $strictness = MUST_EXIST) { 159 global $DB; 160 161 if ($context = context::cache_get(self::LEVEL, $userid)) { 162 return $context; 163 } 164 165 if (!$record = $DB->get_record('context', array('contextlevel' => self::LEVEL, 'instanceid' => $userid))) { 166 if ($user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0), 'id', $strictness)) { 167 $record = context::insert_context_record(self::LEVEL, $user->id, '/'.SYSCONTEXTID, 0); 168 } 169 } 170 171 if ($record) { 172 $context = new user($record); 173 context::cache_add($context); 174 return $context; 175 } 176 177 return false; 178 } 179 180 /** 181 * Create missing context instances at user context level 182 */ 183 protected static function create_level_instances() { 184 global $DB; 185 186 $sql = "SELECT " . self::LEVEL . ", u.id 187 FROM {user} u 188 WHERE u.deleted = 0 189 AND NOT EXISTS (SELECT 'x' 190 FROM {context} cx 191 WHERE u.id = cx.instanceid AND cx.contextlevel=" . self::LEVEL . ")"; 192 $contextdata = $DB->get_recordset_sql($sql); 193 foreach ($contextdata as $context) { 194 context::insert_context_record(self::LEVEL, $context->id, null); 195 } 196 $contextdata->close(); 197 } 198 199 /** 200 * Returns sql necessary for purging of stale context instances. 201 * 202 * @return string cleanup SQL 203 */ 204 protected static function get_cleanup_sql() { 205 $sql = " 206 SELECT c.* 207 FROM {context} c 208 LEFT OUTER JOIN {user} u ON (c.instanceid = u.id AND u.deleted = 0) 209 WHERE u.id IS NULL AND c.contextlevel = " . self::LEVEL . " 210 "; 211 212 return $sql; 213 } 214 215 /** 216 * Rebuild context paths and depths at user context level. 217 * 218 * @param bool $force 219 */ 220 protected static function build_paths($force) { 221 global $DB; 222 223 // First update normal users. 224 $path = $DB->sql_concat('?', 'id'); 225 $pathstart = '/' . SYSCONTEXTID . '/'; 226 $params = array($pathstart); 227 228 if ($force) { 229 $where = "depth <> 2 OR path IS NULL OR path <> ({$path})"; 230 $params[] = $pathstart; 231 } else { 232 $where = "depth = 0 OR path IS NULL"; 233 } 234 235 $sql = "UPDATE {context} 236 SET depth = 2, 237 path = {$path} 238 WHERE contextlevel = " . self::LEVEL . " 239 AND ($where)"; 240 $DB->execute($sql, $params); 241 } 242 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body