Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]

   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 class for requesting user data.
  19   *
  20   * @package    core
  21   * @category   privacy
  22   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace core\privacy;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  use core_privacy\local\metadata\collection;
  31  use core_privacy\local\request\approved_contextlist;
  32  use core_privacy\local\request\approved_userlist;
  33  use core_privacy\local\request\contextlist;
  34  use core_privacy\local\request\userlist;
  35  use core_privacy\local\request\writer;
  36  
  37  /**
  38   * Privacy class for requesting user data.
  39   *
  40   * @package    core
  41   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  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\subsystem\provider,
  47          \core_privacy\local\request\core_userlist_provider {
  48  
  49      /**
  50       * Returns information about the user data stored in this component.
  51       *
  52       * @param  collection $collection A list of information about this component
  53       * @return collection The collection object filled out with information about this component.
  54       */
  55      public static function get_metadata(collection $collection) : collection {
  56          // Except for moodlenet_share_progress, these tables are really data about site configuration and not user data.
  57  
  58          // The config_log includes information about which user performed a configuration change.
  59          // The value and oldvalue may contain sensitive information such as accounts for service passwords..
  60          // This is not considered to be user data.
  61          $collection->add_database_table('config_log', [
  62                  'userid'        => 'privacy:metadata:config_log:userid',
  63                  'timemodified'  => 'privacy:metadata:config_log:timemodified',
  64                  'plugin'        => 'privacy:metadata:config_log:plugin',
  65                  'name'          => 'privacy:metadata:config_log:name',
  66                  'value'         => 'privacy:metadata:config_log:value',
  67                  'oldvalue'      => 'privacy:metadata:config_log:oldvalue',
  68              ], 'privacy:metadata:config_log');
  69  
  70          // The upgrade_log includes information about which user performed an upgrade.
  71          // This is not considered to be user data.
  72          $collection->add_database_table('upgrade_log', [
  73                  'type'          => 'privacy:metadata:upgrade_log:type',
  74                  'plugin'        => 'privacy:metadata:upgrade_log:plugin',
  75                  'version'       => 'privacy:metadata:upgrade_log:version',
  76                  'targetversion' => 'privacy:metadata:upgrade_log:targetversion',
  77                  'info'          => 'privacy:metadata:upgrade_log:info',
  78                  'details'       => 'privacy:metadata:upgrade_log:details',
  79                  'backtrace'     => 'privacy:metadata:upgrade_log:backtrace',
  80                  'userid'        => 'privacy:metadata:upgrade_log:userid',
  81                  'timemodified'  => 'privacy:metadata:upgrade_log:timemodified',
  82              ], 'privacy:metadata:upgrade_log');
  83  
  84          // The task_adhoc includes information about pending adhoc tasks, some of which may be run as a user.
  85          // These are removed as the task completes.
  86          $collection->add_database_table('task_adhoc', [
  87                  'component'     => 'privacy:metadata:task_adhoc:component',
  88                  'nextruntime'   => 'privacy:metadata:task_adhoc:nextruntime',
  89                  'userid'        => 'privacy:metadata:task_adhoc:userid',
  90              ], 'privacy:metadata:task_adhoc');
  91  
  92          // The task_log table stores debugging data for tasks.
  93          // These are cleaned regularly and intended purely for debugging.
  94          $collection->add_database_table('task_log', [
  95                  'component'     => 'privacy:metadata:task_log:component',
  96                  'userid'        => 'privacy:metadata:task_log:userid',
  97              ], 'privacy:metadata:task_log');
  98  
  99          // The events_queue includes information about pending events tasks.
 100          // These are stored for short periods whilst being processed into other locations.
 101          $collection->add_database_table('events_queue', [
 102                  'eventdata'     => 'privacy:metadata:events_queue:eventdata',
 103                  'stackdump'     => 'privacy:metadata:events_queue:stackdump',
 104                  'userid'        => 'privacy:metadata:events_queue:userid',
 105                  'timecreated'   => 'privacy:metadata:events_queue:timecreated',
 106              ], 'privacy:metadata:events_queue');
 107  
 108          // The log table is defined in core but used in logstore_legacy.
 109          $collection->add_database_table('log', [
 110              'time' => 'privacy:metadata:log:time',
 111              'userid' => 'privacy:metadata:log:userid',
 112              'ip' => 'privacy:metadata:log:ip',
 113              'action' => 'privacy:metadata:log:action',
 114              'url' => 'privacy:metadata:log:url',
 115              'info' => 'privacy:metadata:log:info'
 116          ], 'privacy:metadata:log');
 117  
 118          // The oauth2_refresh_token stores refresh tokens, allowing ongoing access to select oauth2 services.
 119          // Such tokens are not considered to be user data.
 120          $collection->add_database_table('oauth2_refresh_token', [
 121              'timecreated' => 'privacy:metadata:oauth2_refresh_token:timecreated',
 122              'timemodified' => 'privacy:metadata:oauth2_refresh_token:timemodified',
 123              'userid' => 'privacy:metadata:oauth2_refresh_token:userid',
 124              'issuerid' => 'privacy:metadata:oauth2_refresh_token:issuerid',
 125              'token' => 'privacy:metadata:oauth2_refresh_token:token',
 126              'scopehash' => 'privacy:metadata:oauth2_refresh_token:scopehash'
 127          ], 'privacy:metadata:oauth2_refresh_token');
 128  
 129          // The moodlenet_share_progress includes details of an attempted share of a resource to MoodleNet.
 130          $collection->add_database_table('moodlenet_share_progress', [
 131              'type' => 'privacy:metadata:moodlenet_share_progress:type',
 132              'courseid' => 'privacy:metadata:moodlenet_share_progress:courseid',
 133              'cmid' => 'privacy:metadata:moodlenet_share_progress:cmid',
 134              'userid' => 'privacy:metadata:moodlenet_share_progress:userid',
 135              'timecreated' => 'privacy:metadata:moodlenet_share_progress:timecreated',
 136              'resourceurl' => 'privacy:metadata:moodlenet_share_progress:resourceurl',
 137              'status' => 'privacy:metadata:moodlenet_share_progress:status',
 138          ], 'privacy:metadata:moodlenet_share_progress');
 139  
 140          // This resourceurl field is an external link from MoodleNet.
 141          $collection->add_external_location_link('moodlenet_share_progress', [
 142              'resourceurl' => 'privacy:metadata:moodlenet_share_progress:resourceurl',
 143          ], 'privacy:metadata:moodlenet_share_progress');
 144  
 145          return $collection;
 146      }
 147  
 148      /**
 149       * Get the list of contexts that contain user information for the specified user.
 150       *
 151       * @param   int $userid The user to search.
 152       * @return  contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
 153       */
 154      public static function get_contexts_for_userid(int $userid) : contextlist {
 155          $contextlist = new contextlist();
 156  
 157          // MoodleNet share progress uses the user context.
 158          $sql = "SELECT ctx.id
 159                    FROM {context} ctx
 160                    JOIN {moodlenet_share_progress} msp ON ctx.instanceid = msp.userid
 161                         AND ctx.contextlevel = :contextlevel
 162                   WHERE msp.userid = :userid";
 163          $params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER];
 164          $contextlist->add_from_sql($sql, $params);
 165  
 166          return $contextlist;
 167      }
 168  
 169      /**
 170       * Get the list of users who have data within a context.
 171       *
 172       * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
 173       */
 174      public static function get_users_in_context(userlist $userlist) {
 175          // Except for moodlenet_share_progress, don't add any users.
 176          $context = $userlist->get_context();
 177  
 178          // MoodleNet share progress uses the user context.
 179          if ($context->contextlevel == CONTEXT_USER) {
 180              // Get all distinct userids from the table.
 181              $sql = "SELECT DISTINCT userid
 182                        FROM {moodlenet_share_progress}
 183                       WHERE userid = :userid";
 184              $params = ['userid' => $context->instanceid];
 185              $userlist->add_from_sql('userid', $sql, $params);
 186          }
 187      }
 188  
 189      /**
 190       * Export all user data for the specified user, in the specified contexts.
 191       *
 192       * @param approved_contextlist $contextlist The approved contexts to export information for.
 193       */
 194      public static function export_user_data(approved_contextlist $contextlist) {
 195          // Except for moodlenet_share_progress, none of the core tables should be exported.
 196          global $DB;
 197  
 198          foreach ($contextlist as $context) {
 199              // MoodleNet share progress uses the user context.
 200              if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $contextlist->get_user()->id) {
 201                  // Get the user's MoodleNet share progress data.
 202                  $sharedata = $DB->get_records('moodlenet_share_progress', ['userid' => $context->instanceid]);
 203                  $subcontext = get_string('privacy:metadata:moodlenet_share_progress', 'moodle');
 204                  writer::with_context($context)->export_data([$subcontext], (object) $sharedata);
 205              }
 206          }
 207      }
 208  
 209      /**
 210       * Delete all data for all users in the specified context.
 211       *
 212       * @param \context $context The specific context to delete data for.
 213       */
 214      public static function delete_data_for_all_users_in_context(\context $context) {
 215          // Except for moodlenet_share_progress, none of the the data from these tables should be deleted.
 216          global $DB;
 217  
 218          // MoodleNet share progress uses the user context.
 219          if ($context->contextlevel == CONTEXT_USER) {
 220              $DB->delete_records('moodlenet_share_progress', ['userid' => $context->instanceid]);
 221          }
 222      }
 223  
 224      /**
 225       * Delete all user data for the specified user, in the specified contexts.
 226       *
 227       * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
 228       */
 229      public static function delete_data_for_user(approved_contextlist $contextlist) {
 230          // Except for moodlenet_share_progress, none of the the data from these tables should be deleted.
 231          // Note: Although it may be tempting to delete the adhoc task data, do not do so.
 232          // The delete process is run as an adhoc task.
 233          global $DB;
 234  
 235          foreach ($contextlist as $context) {
 236              // MoodleNet share progress uses the user context.
 237              if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $contextlist->get_user()->id) {
 238                  $DB->delete_records('moodlenet_share_progress', ['userid' => $context->instanceid]);
 239              }
 240          }
 241      }
 242  
 243      /**
 244       * Delete multiple users within a single context.
 245       *
 246       * @param   approved_userlist       $userlist The approved context and user information to delete information for.
 247       */
 248      public static function delete_data_for_users(approved_userlist $userlist) {
 249          // Except for moodlenet_share_progress, none of the the data from these tables should be deleted.
 250          // Note: Although it may be tempting to delete the adhoc task data, do not do so.
 251          // The delete process is run as an adhoc task.
 252          global $DB;
 253  
 254          $context = $userlist->get_context();
 255  
 256          if (!in_array($context->instanceid, $userlist->get_userids())) {
 257              return;
 258          }
 259  
 260          // MoodleNet share progress uses the user context.
 261          if ($context->contextlevel == CONTEXT_USER) {
 262              $DB->delete_records('moodlenet_share_progress', ['userid' => $context->instanceid]);
 263          }
 264      }
 265  }