Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   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   * Privacy Subsystem implementation for tool_cohortroles.
  19   *
  20   * @package    tool_cohortroles
  21   * @copyright  2018 Zig Tan <zig@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace tool_cohortroles\privacy;
  26  
  27  use core_privacy\local\metadata\collection;
  28  use core_privacy\local\request\approved_contextlist;
  29  use core_privacy\local\request\context;
  30  use core_privacy\local\request\contextlist;
  31  use core_privacy\local\request\transform;
  32  use core_privacy\local\request\writer;
  33  use core_privacy\local\request\userlist;
  34  use \core_privacy\local\request\approved_userlist;
  35  
  36  defined('MOODLE_INTERNAL') || die();
  37  
  38  /**
  39   * Privacy Subsystem for tool_cohortroles implementing metadata and plugin providers.
  40   *
  41   * @copyright  2018 Zig Tan <zig@moodle.com>
  42   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  43   */
  44  class provider implements
  45          \core_privacy\local\metadata\provider,
  46          \core_privacy\local\request\core_userlist_provider,
  47          \core_privacy\local\request\plugin\provider {
  48  
  49      /**
  50       * Returns meta data about this system.
  51       *
  52       * @param   collection $collection The initialised collection to add items to.
  53       * @return  collection     A listing of user data stored through this system.
  54       */
  55      public static function get_metadata(collection $collection) : collection {
  56          // The tool_cohortroles plugin utilises the mdl_tool_cohortroles table.
  57          $collection->add_database_table(
  58              'tool_cohortroles',
  59              [
  60                  'id' => 'privacy:metadata:tool_cohortroles:id',
  61                  'cohortid' => 'privacy:metadata:tool_cohortroles:cohortid',
  62                  'roleid' => 'privacy:metadata:tool_cohortroles:roleid',
  63                  'userid' => 'privacy:metadata:tool_cohortroles:userid',
  64                  'timecreated' => 'privacy:metadata:tool_cohortroles:timecreated',
  65                  'timemodified' => 'privacy:metadata:tool_cohortroles:timemodified',
  66                  'usermodified' => 'privacy:metadata:tool_cohortroles:usermodified'
  67              ],
  68              'privacy:metadata:tool_cohortroles'
  69          );
  70  
  71          return $collection;
  72      }
  73  
  74      /**
  75       * Get the list of contexts that contain user information for the specified user.
  76       *
  77       * @param   int $userid The user to search.
  78       * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
  79       */
  80      public static function get_contexts_for_userid(int $userid) : contextlist {
  81          $contextlist = new contextlist();
  82  
  83          // When we process user deletions and expiries, we always delete from the user context.
  84          // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
  85          // as roles may change and data may be removed earlier than it should be.
  86  
  87          // Retrieve the context associated with tool_cohortroles records.
  88          $sql = "SELECT DISTINCT c.contextid
  89                    FROM {tool_cohortroles} tc
  90                    JOIN {cohort} c
  91                         ON tc.cohortid = c.id
  92                    JOIN {context} ctx
  93                         ON ctx.id = c.contextid
  94                   WHERE tc.userid = :userid
  95                         AND (ctx.contextlevel = :contextlevel1
  96                             OR ctx.contextlevel = :contextlevel2)";
  97  
  98          $params = [
  99              'userid'        => $userid,
 100              'contextlevel1' => CONTEXT_SYSTEM,
 101              'contextlevel2' => CONTEXT_COURSECAT
 102          ];
 103  
 104          $contextlist->add_from_sql($sql, $params);
 105  
 106          return $contextlist;
 107      }
 108  
 109      /**
 110       * Get the list of users within a specific context.
 111       *
 112       * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
 113       */
 114      public static function get_users_in_context(userlist $userlist) {
 115          $context = $userlist->get_context();
 116  
 117          // When we process user deletions and expiries, we always delete from the user context.
 118          // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
 119          // as roles may change and data may be removed earlier than it should be.
 120  
 121          $allowedcontextlevels = [
 122              CONTEXT_SYSTEM,
 123              CONTEXT_COURSECAT
 124          ];
 125  
 126          if (!in_array($context->contextlevel, $allowedcontextlevels)) {
 127              return;
 128          }
 129  
 130          $sql = "SELECT tc.userid as userid
 131                    FROM {tool_cohortroles} tc
 132                    JOIN {cohort} c
 133                         ON tc.cohortid = c.id
 134                   WHERE c.contextid = :contextid";
 135  
 136          $params = [
 137              'contextid' => $context->id
 138          ];
 139  
 140          $userlist->add_from_sql('userid', $sql, $params);
 141      }
 142  
 143      /**
 144       * Export all user data for the specified user, in the specified contexts.
 145       *
 146       * @param   approved_contextlist $contextlist The approved contexts to export information for.
 147       */
 148      public static function export_user_data(approved_contextlist $contextlist) {
 149          global $DB;
 150  
 151          // Remove contexts different from SYSTEM or COURSECAT.
 152          $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
 153              if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) {
 154                  $carry[] = $context->id;
 155              }
 156              return $carry;
 157          }, []);
 158  
 159          if (empty($contextids)) {
 160              return;
 161          }
 162  
 163          $userid = $contextlist->get_user()->id;
 164  
 165          list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
 166  
 167          // Retrieve the tool_cohortroles records created for the user.
 168          $sql = "SELECT cr.id as cohortroleid,
 169                         c.name as cohortname,
 170                         c.idnumber as cohortidnumber,
 171                         c.description as cohortdescription,
 172                         c.contextid as contextid,
 173                         r.shortname as roleshortname,
 174                         cr.userid as userid,
 175                         cr.timecreated as timecreated,
 176                         cr.timemodified as timemodified
 177                    FROM {tool_cohortroles} cr
 178                    JOIN {cohort} c ON c.id = cr.cohortid
 179                    JOIN {role} r ON r.id = cr.roleid
 180                   WHERE cr.userid = :userid
 181                         AND c.contextid {$contextsql}";
 182  
 183          $params = ['userid' => $userid] + $contextparams;
 184  
 185          $cohortroles = $DB->get_records_sql($sql, $params);
 186  
 187          foreach ($cohortroles as $cohortrole) {
 188              // The tool_cohortroles data export is organised in:
 189              // {User Context}/Cohort roles management/{cohort name}/{role shortname}/data.json.
 190              $subcontext = [
 191                  get_string('pluginname', 'tool_cohortroles'),
 192                  $cohortrole->cohortname,
 193                  $cohortrole->roleshortname
 194              ];
 195  
 196              $data = (object) [
 197                  'cohortname' => $cohortrole->cohortname,
 198                  'cohortidnumber' => $cohortrole->cohortidnumber,
 199                  'cohortdescription' => $cohortrole->cohortdescription,
 200                  'roleshortname' => $cohortrole->roleshortname,
 201                  'userid' => transform::user($cohortrole->userid),
 202                  'timecreated' => transform::datetime($cohortrole->timecreated),
 203                  'timemodified' => transform::datetime($cohortrole->timemodified)
 204              ];
 205  
 206              $context = \context::instance_by_id($cohortrole->contextid);
 207  
 208              writer::with_context($context)->export_data($subcontext, $data);
 209          }
 210      }
 211  
 212      /**
 213       * Delete all data for all users in the specified context.
 214       *
 215       * @param   context $context The specific context to delete data for.
 216       */
 217      public static function delete_data_for_all_users_in_context(\context $context) {
 218          global $DB;
 219  
 220          // When we process user deletions and expiries, we always delete from the user context.
 221          // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
 222          // as roles may change and data may be removed earlier than it should be.
 223  
 224          $allowedcontextlevels = [
 225              CONTEXT_SYSTEM,
 226              CONTEXT_COURSECAT
 227          ];
 228  
 229          if (!in_array($context->contextlevel, $allowedcontextlevels)) {
 230              return;
 231          }
 232  
 233          $cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid',
 234              ['contextid' => $context->id]);
 235  
 236          // Delete the tool_cohortroles records created in the specific context.
 237          $DB->delete_records_list('tool_cohortroles', 'cohortid', $cohortids);
 238      }
 239  
 240      /**
 241       * Delete multiple users within a single context.
 242       *
 243       * @param approved_userlist $userlist The approved context and user information to delete information for.
 244       */
 245      public static function delete_data_for_users(approved_userlist $userlist) {
 246          global $DB;
 247  
 248          // When we process user deletions and expiries, we always delete from the user context.
 249          // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
 250          // as roles may change and data may be removed earlier than it should be.
 251  
 252          $userids = $userlist->get_userids();
 253  
 254          if (empty($userids)) {
 255              return;
 256          }
 257  
 258          $context = $userlist->get_context();
 259  
 260          $allowedcontextlevels = [
 261              CONTEXT_SYSTEM,
 262              CONTEXT_COURSECAT
 263          ];
 264  
 265          if (!in_array($context->contextlevel, $allowedcontextlevels)) {
 266              return;
 267          }
 268  
 269          $cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid',
 270              ['contextid' => $context->id]);
 271  
 272          if (empty($cohortids)) {
 273              return;
 274          }
 275  
 276          list($cohortsql, $cohortparams) = $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED);
 277          list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
 278  
 279          $params = $cohortparams + $userparams;
 280          $select = "cohortid {$cohortsql} AND userid {$usersql}";
 281  
 282          // Delete the tool_cohortroles records created in the specific context for an approved list of users.
 283          $DB->delete_records_select('tool_cohortroles', $select, $params);
 284      }
 285  
 286      /**
 287       * Delete all user data for the specified user, in the specified contexts.
 288       *
 289       * @param   approved_contextlist $contextlist The approved contexts and user information to delete information for.
 290       */
 291      public static function delete_data_for_user(approved_contextlist $contextlist) {
 292          global $DB;
 293  
 294          // When we process user deletions and expiries, we always delete from the user context.
 295          // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
 296          // as roles may change and data may be removed earlier than it should be.
 297  
 298          // Remove contexts different from SYSTEM or COURSECAT.
 299          $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
 300              if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) {
 301                  $carry[] = $context->id;
 302              }
 303              return $carry;
 304          }, []);
 305  
 306          if (empty($contextids)) {
 307              return;
 308          }
 309  
 310          $userid = $contextlist->get_user()->id;
 311  
 312          list($contextsql, $contextparams) =  $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
 313          $selectcontext = "contextid {$contextsql}";
 314          // Get the cohorts in the specified contexts.
 315          $cohortids = $DB->get_fieldset_select('cohort', 'id', $selectcontext, $contextparams);
 316  
 317          if (empty($cohortids)) {
 318              return;
 319          }
 320  
 321          list($cohortsql, $cohortparams) =  $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED);
 322          $selectcohort = "cohortid {$cohortsql} AND userid = :userid";
 323          $params = ['userid' => $userid] + $cohortparams;
 324  
 325          // Delete the tool_cohortroles records created for the userid.
 326          $DB->delete_records_select('tool_cohortroles', $selectcohort, $params);
 327      }
 328  }