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 enrol_flatfile.
  19   *
  20   * @package    enrol_flatfile
  21   * @category   privacy
  22   * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace enrol_flatfile\privacy;
  27  
  28  use core_privacy\local\metadata\collection;
  29  use core_privacy\local\request\approved_contextlist;
  30  use core_privacy\local\request\approved_userlist;
  31  use core_privacy\local\request\context;
  32  use core_privacy\local\request\contextlist;
  33  use core_privacy\local\request\userlist;
  34  use core_privacy\local\request\writer;
  35  use core_privacy\local\request\transform;
  36  
  37  defined('MOODLE_INTERNAL') || die();
  38  
  39  /**
  40   * Privacy Subsystem for enrol_flatfile implementing null_provider.
  41   *
  42   * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
  43   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  44   */
  45  class provider implements
  46          \core_privacy\local\metadata\provider,
  47          \core_privacy\local\request\plugin\provider,
  48          \core_privacy\local\request\core_userlist_provider {
  49  
  50      /**
  51       * Returns meta data about this system.
  52       *
  53       * @param   collection $collection The initialised collection to add items to.
  54       * @return  collection     A listing of user data stored through this system.
  55       */
  56      public static function get_metadata(collection $collection) : collection {
  57          return $collection->add_database_table('enrol_flatfile', [
  58              'action' => 'privacy:metadata:enrol_flatfile:action',
  59              'roleid' => 'privacy:metadata:enrol_flatfile:roleid',
  60              'userid' => 'privacy:metadata:enrol_flatfile:userid',
  61              'courseid' => 'privacy:metadata:enrol_flatfile:courseid',
  62              'timestart' => 'privacy:metadata:enrol_flatfile:timestart',
  63              'timeend' => 'privacy:metadata:enrol_flatfile:timeend',
  64              'timemodified' => 'privacy:metadata:enrol_flatfile:timemodified'
  65          ], 'privacy:metadata:enrol_flatfile');
  66      }
  67  
  68      /**
  69       * Get the list of contexts that contain user information for the specified user.
  70       *
  71       * @param   int $userid The user to search.
  72       * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
  73       */
  74      public static function get_contexts_for_userid(int $userid) : contextlist {
  75          $sql = "SELECT c.id
  76                    FROM {enrol_flatfile} ef
  77                    JOIN {context} c ON c.contextlevel = ? AND c.instanceid = ef.courseid
  78                   WHERE ef.userid = ?";
  79          $params = [CONTEXT_COURSE, $userid];
  80  
  81          $contextlist = new contextlist();
  82          $contextlist->set_component('enrol_flatfile');
  83          return $contextlist->add_from_sql($sql, $params);
  84      }
  85  
  86      /**
  87       * Get the list of users who have data within a context.
  88       *
  89       * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
  90       */
  91      public static function get_users_in_context(userlist $userlist) {
  92          $context = $userlist->get_context();
  93  
  94          if ($context->contextlevel != CONTEXT_COURSE) {
  95              return;
  96          }
  97  
  98          $sql = "SELECT userid FROM {enrol_flatfile} WHERE courseid = ?";
  99          $params = [$context->instanceid];
 100          $userlist->add_from_sql('userid', $sql, $params);
 101      }
 102  
 103      /**
 104       * Export all user data for the specified user, in the specified contexts.
 105       *
 106       * @param approved_contextlist $contextlist The approved contexts to export information for.
 107       */
 108      public static function export_user_data(approved_contextlist $contextlist) {
 109          global $DB;
 110  
 111          // Ensure all contexts are CONTEXT_COURSE.
 112          $contexts = static::validate_contextlist_contexts($contextlist);
 113          if (empty($contexts)) {
 114              return;
 115          }
 116  
 117          // Get the context instance ids from the contexts. These  are the course ids..
 118          $contextinstanceids = array_map(function($context) {
 119              return $context->instanceid;
 120          }, $contexts);
 121          $userid = $contextlist->get_user()->id;
 122  
 123          // Now, we just need to fetch and format all entries corresponding to the contextids provided.
 124          $sql = "SELECT ef.action, r.shortname, ef.courseid, ef.timestart, ef.timeend, ef.timemodified
 125                    FROM {enrol_flatfile} ef
 126                    JOIN {context} c ON c.contextlevel = :contextlevel AND c.instanceid = ef.courseid
 127                    JOIN {role} r ON r.id = ef.roleid
 128                   WHERE ef.userid = :userid";
 129          $params = ['contextlevel' => CONTEXT_COURSE, 'userid' => $userid];
 130          list($insql, $inparams) = $DB->get_in_or_equal($contextinstanceids, SQL_PARAMS_NAMED);
 131          $sql .= " AND ef.courseid $insql";
 132          $params = array_merge($params, $inparams);
 133  
 134          $futureenrolments = $DB->get_recordset_sql($sql, $params);
 135          $enrolmentdata = [];
 136          foreach ($futureenrolments as $futureenrolment) {
 137              // It's possible to have more than one future enrolment per course.
 138              $futureenrolment->timestart = transform::datetime($futureenrolment->timestart);
 139              $futureenrolment->timeend = transform::datetime($futureenrolment->timeend);
 140              $futureenrolment->timemodified = transform::datetime($futureenrolment->timemodified);
 141              $enrolmentdata[$futureenrolment->courseid][] = $futureenrolment;
 142          }
 143          $futureenrolments->close();
 144  
 145          // And finally, write out the data to the relevant course contexts.
 146          $subcontext = \core_enrol\privacy\provider::get_subcontext([get_string('pluginname', 'enrol_flatfile')]);
 147          foreach ($enrolmentdata as $courseid => $enrolments) {
 148              $data = (object) [
 149                  'pendingenrolments' => $enrolments,
 150              ];
 151              writer::with_context(\context_course::instance($courseid))->export_data($subcontext, $data);
 152          }
 153      }
 154  
 155      /**
 156       * Delete all data for all users in the specified context.
 157       *
 158       * @param \context $context The specific context to delete data for.
 159       */
 160      public static function delete_data_for_all_users_in_context(\context $context) {
 161          if ($context->contextlevel != CONTEXT_COURSE) {
 162              return;
 163          }
 164          global $DB;
 165          $DB->delete_records('enrol_flatfile', ['courseid' => $context->instanceid]);
 166      }
 167  
 168      /**
 169       * Delete all user data for the specified user, in the specified contexts.
 170       *
 171       * @param   approved_contextlist $contextlist The approved contexts and user information to delete information for.
 172       */
 173      public static function delete_data_for_user(approved_contextlist $contextlist) {
 174          // Only delete data from contexts which are at the CONTEXT_COURSE contextlevel.
 175          $contexts = self::validate_contextlist_contexts($contextlist);
 176          if (empty($contexts)) {
 177              return;
 178          }
 179  
 180          // Get the course ids based on the provided contexts.
 181          $contextinstanceids = array_map(function($context) {
 182              return $context->instanceid;
 183          }, $contextlist->get_contexts());
 184  
 185          global $DB;
 186          $user = $contextlist->get_user();
 187          list($insql, $inparams) = $DB->get_in_or_equal($contextinstanceids, SQL_PARAMS_NAMED);
 188          $params = array_merge(['userid' => $user->id], $inparams);
 189          $sql = "userid = :userid AND courseid $insql";
 190          $DB->delete_records_select('enrol_flatfile', $sql, $params);
 191      }
 192  
 193      /**
 194       * Delete multiple users within a single context.
 195       *
 196       * @param   approved_userlist       $userlist The approved context and user information to delete information for.
 197       */
 198      public static function delete_data_for_users(approved_userlist $userlist) {
 199          global $DB;
 200  
 201          $context = $userlist->get_context();
 202  
 203          if ($context->contextlevel != CONTEXT_COURSE) {
 204              return;
 205          }
 206  
 207          $userids = $userlist->get_userids();
 208  
 209          list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
 210          $params = array_merge(['courseid' => $context->instanceid], $inparams);
 211          $sql = "courseid = :courseid AND userid $insql";
 212          $DB->delete_records_select('enrol_flatfile', $sql, $params);
 213      }
 214  
 215      /**
 216       * Simple sanity check on the contextlist contexts, making sure they're of CONTEXT_COURSE contextlevel.
 217       *
 218       * @param approved_contextlist $contextlist
 219       * @return array the array of contexts filtered to only include those of CONTEXT_COURSE contextlevel.
 220       */
 221      protected static function validate_contextlist_contexts(approved_contextlist $contextlist) {
 222          return array_reduce($contextlist->get_contexts(), function($carry, $context) {
 223              if ($context->contextlevel == CONTEXT_COURSE) {
 224                  $carry[] = $context;
 225              }
 226              return $carry;
 227          }, []);
 228      }
 229  }