Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.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 repository_onedrive.
  19   *
  20   * @package    repository_onedrive
  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 repository_onedrive\privacy;
  26  
  27  use core_privacy\local\metadata\collection;
  28  use core_privacy\local\request\approved_contextlist;
  29  use core_privacy\local\request\approved_userlist;
  30  use core_privacy\local\request\context;
  31  use core_privacy\local\request\contextlist;
  32  use core_privacy\local\request\transform;
  33  use core_privacy\local\request\userlist;
  34  use \core_privacy\local\request\writer;
  35  
  36  defined('MOODLE_INTERNAL') || die();
  37  
  38  /**
  39   * Privacy Subsystem for repository_onedrive 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          $collection->add_external_location_link(
  57              'onedrive.live.com',
  58              [
  59                  'searchtext' => 'privacy:metadata:repository_onedrive:searchtext'
  60              ],
  61              'privacy:metadata:repository_onedrive'
  62          );
  63  
  64          // The repository_onedrive has a 'repository_onedrive_access' table that contains user data.
  65          $collection->add_database_table(
  66              'repository_onedrive_access',
  67              [
  68                  'itemid' => 'privacy:metadata:repository_onedrive:repository_onedrive_access:itemid',
  69                  'permissionid' => 'privacy:metadata:repository_onedrive:repository_onedrive_access:permissionid',
  70                  'timecreated' => 'privacy:metadata:repository_onedrive:repository_onedrive_access:timecreated',
  71                  'timemodified' => 'privacy:metadata:repository_onedrive:repository_onedrive_access:timemodified',
  72                  'usermodified' => 'privacy:metadata:repository_onedrive:repository_onedrive_access:usermodified'
  73              ],
  74              'privacy:metadata:repository_onedrive'
  75          );
  76  
  77          return $collection;
  78      }
  79  
  80      /**
  81       * Get the list of contexts that contain user information for the specified user.
  82       *
  83       * @param   int $userid The user to search.
  84       * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
  85       */
  86      public static function get_contexts_for_userid(int $userid) : contextlist {
  87          $contextlist = new contextlist();
  88  
  89          // The data is associated at the user context level, so retrieve the user's context id.
  90          $sql = "SELECT c.id
  91                    FROM {repository_onedrive_access} roa
  92                    JOIN {context} c ON c.instanceid = roa.usermodified AND c.contextlevel = :contextuser
  93                   WHERE roa.usermodified = :userid
  94                GROUP BY c.id";
  95  
  96          $params = [
  97              'contextuser'   => CONTEXT_USER,
  98              'userid'        => $userid
  99          ];
 100  
 101          $contextlist->add_from_sql($sql, $params);
 102  
 103          return $contextlist;
 104      }
 105  
 106      /**
 107       * Get the list of users who have data within a context.
 108       *
 109       * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
 110       */
 111      public static function get_users_in_context(userlist $userlist) {
 112          $context = $userlist->get_context();
 113  
 114          if (!$context instanceof \context_user) {
 115              return;
 116          }
 117  
 118          // The data is associated at the user context level, so retrieve the user's context id.
 119          $sql = "SELECT usermodified AS userid
 120                    FROM {repository_onedrive_access}
 121                   WHERE usermodified = ?";
 122          $params = [$context->instanceid];
 123          $userlist->add_from_sql('userid', $sql, $params);
 124      }
 125  
 126      /**
 127       * Export all user data for the specified user, in the specified contexts.
 128       *
 129       * @param   approved_contextlist $contextlist The approved contexts to export information for.
 130       */
 131      public static function export_user_data(approved_contextlist $contextlist) {
 132          global $DB;
 133  
 134          // If the user has data, then only the User context should be present so get the first context.
 135          $contexts = $contextlist->get_contexts();
 136          if (count($contexts) == 0) {
 137              return;
 138          }
 139          $context = reset($contexts);
 140  
 141          // Sanity check that context is at the User context level, then get the userid.
 142          if ($context->contextlevel !== CONTEXT_USER) {
 143              return;
 144          }
 145          $userid = $context->instanceid;
 146  
 147          $sql = "SELECT roa.id as id,
 148                         roa.itemid as itemid,
 149                         roa.permissionid as permissionid,
 150                         roa.timecreated as timecreated,
 151                         roa.timemodified as timemodified
 152                    FROM {repository_onedrive_access} roa
 153                   WHERE roa.usermodified = :userid";
 154  
 155          $params = [
 156              'userid' => $userid
 157          ];
 158  
 159          $onedriveaccesses = $DB->get_records_sql($sql, $params);
 160          $index = 0;
 161          foreach ($onedriveaccesses as $onedriveaccess) {
 162              // Data export is organised in: {User Context}/Repository plug-ins/{Plugin Name}/Access/{index}/data.json.
 163              $index++;
 164              $subcontext = [
 165                  get_string('plugin', 'core_repository'),
 166                  get_string('pluginname', 'repository_onedrive'),
 167                  get_string('access', 'repository_onedrive'),
 168                  $index
 169              ];
 170  
 171              $data = (object) [
 172                  'itemid' => $onedriveaccess->itemid,
 173                  'permissionid' => $onedriveaccess->permissionid,
 174                  'timecreated' => transform::datetime($onedriveaccess->timecreated),
 175                  'timemodified' => transform::datetime($onedriveaccess->timemodified)
 176              ];
 177  
 178              writer::with_context($context)->export_data($subcontext, $data);
 179          }
 180  
 181      }
 182  
 183      /**
 184       * Delete all data for all users in the specified context.
 185       *
 186       * @param   context $context The specific context to delete data for.
 187       */
 188      public static function delete_data_for_all_users_in_context(\context $context) {
 189          global $DB;
 190  
 191          // Sanity check that context is at the User context level, then get the userid.
 192          if ($context->contextlevel !== CONTEXT_USER) {
 193              return;
 194          }
 195          $userid = $context->instanceid;
 196  
 197          $DB->delete_records('repository_onedrive_access', ['usermodified' => $userid]);
 198      }
 199  
 200      /**
 201       * Delete all user data for the specified user, in the specified contexts.
 202       *
 203       * @param   approved_contextlist $contextlist The approved contexts and user information to delete information for.
 204       */
 205      public static function delete_data_for_user(approved_contextlist $contextlist) {
 206          global $DB;
 207  
 208          // If the user has data, then only the User context should be present so get the first context.
 209          $contexts = $contextlist->get_contexts();
 210          if (count($contexts) == 0) {
 211              return;
 212          }
 213          $context = reset($contexts);
 214  
 215          // Sanity check that context is at the User context level, then get the userid.
 216          if ($context->contextlevel !== CONTEXT_USER) {
 217              return;
 218          }
 219          $userid = $context->instanceid;
 220  
 221          $DB->delete_records('repository_onedrive_access', ['usermodified' => $userid]);
 222      }
 223  
 224      /**
 225       * Delete multiple users within a single context.
 226       *
 227       * @param   approved_userlist       $userlist The approved context and user information to delete information for.
 228       */
 229      public static function delete_data_for_users(approved_userlist $userlist) {
 230          global $DB;
 231          $context = $userlist->get_context();
 232  
 233          // Sanity check that context is at the User context level, then get the userid.
 234          if ($context->contextlevel !== CONTEXT_USER) {
 235              return;
 236          }
 237  
 238          $userids = $userlist->get_userids();
 239          list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
 240          $params = [
 241              'contextid' => $context->id,
 242              'contextuser' => CONTEXT_USER,
 243          ];
 244          $params = array_merge($params, $inparams);
 245  
 246          // Fetch the repository_onedrive_access IDs in the context for approved users.
 247          $sql = "SELECT roa.id
 248                    FROM {repository_onedrive_access} roa
 249                    JOIN {context} c ON c.instanceid = roa.usermodified
 250                     AND c.contextlevel = :contextuser
 251                     AND c.id = :contextid
 252                   WHERE roa.usermodified {$insql}";
 253          $accessids = $DB->get_fieldset_sql($sql, $params);
 254  
 255          // Delete the relevant repository_onedrive_access data.
 256          list($insql, $params) = $DB->get_in_or_equal($accessids, SQL_PARAMS_NAMED);
 257          $DB->delete_records_select('repository_onedrive_access', "id {$insql}", $params);
 258      }
 259  }