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 * Class that represents an expired context. 19 * 20 * @package tool_dataprivacy 21 * @copyright 2018 David Monllao 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace tool_dataprivacy; 25 use dml_exception; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 /** 30 * Class that represents an expired context. 31 * 32 * @copyright 2018 David Monllao 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 class expired_context extends \core\persistent { 36 37 /** 38 * Database table. 39 */ 40 const TABLE = 'tool_dataprivacy_ctxexpired'; 41 42 /** 43 * Expired contexts with no delete action scheduled. 44 */ 45 const STATUS_EXPIRED = 0; 46 47 /** 48 * Expired contexts approved for deletion. 49 */ 50 const STATUS_APPROVED = 1; 51 52 /** 53 * Already processed expired contexts. 54 */ 55 const STATUS_CLEANED = 2; 56 57 /** 58 * Return the definition of the properties of this model. 59 * 60 * @return array 61 */ 62 protected static function define_properties() { 63 return [ 64 'contextid' => [ 65 'type' => PARAM_INT, 66 'description' => 'The context id.', 67 ], 68 'defaultexpired' => [ 69 'type' => PARAM_INT, 70 'description' => 'Whether to default retention period for the purpose has been reached', 71 'default' => 1, 72 ], 73 'expiredroles' => [ 74 'type' => PARAM_TEXT, 75 'description' => 'This list of roles to include during deletion', 76 'default' => '', 77 ], 78 'unexpiredroles' => [ 79 'type' => PARAM_TEXT, 80 'description' => 'This list of roles to exclude during deletion', 81 'default' => '', 82 ], 83 'status' => [ 84 'choices' => [ 85 self::STATUS_EXPIRED, 86 self::STATUS_APPROVED, 87 self::STATUS_CLEANED, 88 ], 89 'type' => PARAM_INT, 90 'description' => 'The deletion status of the context.', 91 ], 92 ]; 93 } 94 95 /** 96 * Returns expired_contexts instances that match the provided level and status. 97 * 98 * @param int $contextlevel The context level filter criterion. 99 * @param bool $status The expired context record's status. 100 * @param string $sort The sort column. Must match the column name in {tool_dataprivacy_ctxexpired} table 101 * @param int $offset The query offset. 102 * @param int $limit The query limit. 103 * @return expired_context[] 104 * @throws dml_exception 105 */ 106 public static function get_records_by_contextlevel($contextlevel = null, $status = false, $sort = 'timecreated', 107 $offset = 0, $limit = 0) { 108 global $DB; 109 110 $sql = "SELECT expiredctx.* 111 FROM {" . self::TABLE . "} expiredctx 112 JOIN {context} ctx 113 ON ctx.id = expiredctx.contextid"; 114 $params = []; 115 $conditions = []; 116 117 if (!empty($contextlevel)) { 118 $conditions[] = "ctx.contextlevel = :contextlevel"; 119 $params['contextlevel'] = intval($contextlevel); 120 } 121 122 if ($status !== false) { 123 $conditions[] = "expiredctx.status = :status"; 124 $params['status'] = intval($status); 125 } 126 127 if (!empty($conditions)) { 128 $sql .= ' WHERE ' . implode(' AND ', $conditions); 129 } 130 $sql .= " ORDER BY expiredctx.{$sort}"; 131 132 $records = $DB->get_records_sql($sql, $params, $offset, $limit); 133 134 // We return class instances. 135 $instances = array(); 136 foreach ($records as $key => $record) { 137 $instances[$key] = new static(0, $record); 138 } 139 140 return $instances; 141 } 142 143 /** 144 * Returns the number of expired_contexts instances that match the provided level and status. 145 * 146 * @param int $contextlevel 147 * @param bool $status 148 * @return int 149 * @throws dml_exception 150 */ 151 public static function get_record_count_by_contextlevel($contextlevel = null, $status = false) { 152 global $DB; 153 154 $sql = "SELECT COUNT(1) 155 FROM {" . self::TABLE . "} expiredctx 156 JOIN {context} ctx 157 ON ctx.id = expiredctx.contextid"; 158 159 $conditions = []; 160 $params = []; 161 162 if (!empty($contextlevel)) { 163 $conditions[] = "ctx.contextlevel = :contextlevel"; 164 $params['contextlevel'] = intval($contextlevel); 165 } 166 167 if ($status !== false) { 168 $sql .= " AND expiredctx.status = :status"; 169 $params['status'] = intval($status); 170 } 171 if (!empty($conditions)) { 172 $sql .= ' WHERE ' . implode(' AND ', $conditions); 173 } 174 175 return $DB->count_records_sql($sql, $params); 176 } 177 178 /** 179 * Set the list of role IDs for either expiredroles, or unexpiredroles. 180 * 181 * @param string $field 182 * @param int[] $roleids 183 * @return expired_context 184 */ 185 protected function set_roleids_for(string $field, array $roleids) : expired_context { 186 $roledata = json_encode($roleids); 187 188 $this->raw_set($field, $roledata); 189 190 return $this; 191 } 192 193 /** 194 * Get the list of role IDs for either expiredroles, or unexpiredroles. 195 * 196 * @param string $field 197 * @return int[] 198 */ 199 protected function get_roleids_for(string $field) { 200 $value = $this->raw_get($field); 201 if (empty($value)) { 202 return []; 203 } 204 205 return json_decode($value); 206 } 207 208 /** 209 * Set the list of unexpired role IDs. 210 * 211 * @param int[] $roleids 212 * @return expired_context 213 */ 214 protected function set_unexpiredroles(array $roleids) : expired_context { 215 $this->set_roleids_for('unexpiredroles', $roleids); 216 217 return $this; 218 } 219 220 /** 221 * Add a set of role IDs to the list of expired role IDs. 222 * 223 * @param int[] $roleids 224 * @return expired_context 225 */ 226 public function add_expiredroles(array $roleids) : expired_context { 227 $existing = $this->get('expiredroles'); 228 $newvalue = array_merge($existing, $roleids); 229 230 $this->set('expiredroles', $newvalue); 231 232 return $this; 233 } 234 235 /** 236 * Add a set of role IDs to the list of unexpired role IDs. 237 * 238 * @param int[] $roleids 239 * @return unexpired_context 240 */ 241 public function add_unexpiredroles(array $roleids) : expired_context { 242 $existing = $this->get('unexpiredroles'); 243 $newvalue = array_merge($existing, $roleids); 244 245 $this->set('unexpiredroles', $newvalue); 246 247 return $this; 248 } 249 250 /** 251 * Set the list of expired role IDs. 252 * 253 * @param int[] $roleids 254 * @return expired_context 255 */ 256 protected function set_expiredroles(array $roleids) : expired_context { 257 $this->set_roleids_for('expiredroles', $roleids); 258 259 return $this; 260 } 261 262 /** 263 * Get the list of expired role IDs. 264 * 265 * @return int[] 266 */ 267 protected function get_expiredroles() { 268 return $this->get_roleids_for('expiredroles'); 269 } 270 271 /** 272 * Get the list of unexpired role IDs. 273 * 274 * @return int[] 275 */ 276 protected function get_unexpiredroles() { 277 return $this->get_roleids_for('unexpiredroles'); 278 } 279 280 /** 281 * Create a new expired_context based on the context, and expiry_info object. 282 * 283 * @param \context $context 284 * @param expiry_info $info 285 * @param boolean $save 286 * @return expired_context 287 */ 288 public static function create_from_expiry_info(\context $context, expiry_info $info, bool $save = true) : expired_context { 289 $record = (object) [ 290 'contextid' => $context->id, 291 'status' => self::STATUS_EXPIRED, 292 'defaultexpired' => (int) $info->is_default_expired(), 293 ]; 294 295 $expiredcontext = new static(0, $record); 296 $expiredcontext->set('expiredroles', $info->get_expired_roles()); 297 $expiredcontext->set('unexpiredroles', $info->get_unexpired_roles()); 298 299 if ($save) { 300 $expiredcontext->save(); 301 } 302 303 return $expiredcontext; 304 } 305 306 /** 307 * Update the expired_context from an expiry_info object which relates to this context. 308 * 309 * @param expiry_info $info 310 * @return $this 311 */ 312 public function update_from_expiry_info(expiry_info $info) : expired_context { 313 $save = false; 314 315 // Compare the expiredroles. 316 $thisexpired = $this->get('expiredroles'); 317 $infoexpired = $info->get_expired_roles(); 318 319 sort($thisexpired); 320 sort($infoexpired); 321 if ($infoexpired != $thisexpired) { 322 $this->set('expiredroles', $infoexpired); 323 $save = true; 324 } 325 326 // Compare the unexpiredroles. 327 $thisunexpired = $this->get('unexpiredroles'); 328 $infounexpired = $info->get_unexpired_roles(); 329 330 sort($thisunexpired); 331 sort($infounexpired); 332 if ($infounexpired != $thisunexpired) { 333 $this->set('unexpiredroles', $infounexpired); 334 $save = true; 335 } 336 337 if (empty($this->get('defaultexpired')) == $info->is_default_expired()) { 338 $this->set('defaultexpired', (int) $info->is_default_expired()); 339 $save = true; 340 } 341 342 if ($save) { 343 $this->set('status', self::STATUS_EXPIRED); 344 $this->save(); 345 } 346 347 return $this; 348 349 } 350 351 /** 352 * Check whether this expired_context record is in a state ready for deletion to actually take place. 353 * 354 * @return bool 355 */ 356 public function can_process_deletion() : bool { 357 return ($this->get('status') == self::STATUS_APPROVED); 358 } 359 360 /** 361 * Check whether this expired_context record has already been cleaned. 362 * 363 * @return bool 364 */ 365 public function is_complete() : bool { 366 return ($this->get('status') == self::STATUS_CLEANED); 367 } 368 369 /** 370 * Whether this context has 'fully' expired. 371 * That is to say that the default retention period has been reached, and that there are no unexpired roles. 372 * 373 * @return bool 374 */ 375 public function is_fully_expired() : bool { 376 return $this->get('defaultexpired') && empty($this->get('unexpiredroles')); 377 } 378 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body