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.

Differences Between: [Versions 311 and 402] [Versions 311 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 Subsystem implementation for block_html.
  19   *
  20   * @package    block_html
  21   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace block_html\privacy;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  use \core_privacy\local\request\userlist;
  30  use \core_privacy\local\request\approved_contextlist;
  31  use \core_privacy\local\request\approved_userlist;
  32  use \core_privacy\local\request\writer;
  33  use \core_privacy\local\request\helper;
  34  use \core_privacy\local\request\deletion_criteria;
  35  use \core_privacy\local\metadata\collection;
  36  
  37  /**
  38   * Privacy Subsystem implementation for block_html.
  39   *
  40   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class provider implements
  44          // The block_html block stores user provided data.
  45          \core_privacy\local\metadata\provider,
  46  
  47          // This plugin is capable of determining which users have data within it.
  48          \core_privacy\local\request\core_userlist_provider,
  49  
  50          // The block_html block provides data directly to core.
  51          \core_privacy\local\request\plugin\provider {
  52  
  53      /**
  54       * Returns information about how block_html stores its data.
  55       *
  56       * @param   collection     $collection The initialised collection to add items to.
  57       * @return  collection     A listing of user data stored through this system.
  58       */
  59      public static function get_metadata(collection $collection) : collection {
  60          $collection->link_subsystem('block', 'privacy:metadata:block');
  61  
  62          return $collection;
  63      }
  64  
  65      /**
  66       * Get the list of contexts that contain user information for the specified user.
  67       *
  68       * @param   int         $userid     The user to search.
  69       * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
  70       */
  71      public static function get_contexts_for_userid(int $userid) : \core_privacy\local\request\contextlist {
  72          // This block doesn't know who information is stored against unless it
  73          // is at the user context.
  74          $contextlist = new \core_privacy\local\request\contextlist();
  75  
  76          $sql = "SELECT c.id
  77                    FROM {block_instances} b
  78              INNER JOIN {context} c ON c.instanceid = b.id AND c.contextlevel = :contextblock
  79              INNER JOIN {context} bpc ON bpc.id = b.parentcontextid
  80                   WHERE b.blockname = 'html'
  81                     AND bpc.contextlevel = :contextuser
  82                     AND bpc.instanceid = :userid";
  83  
  84          $params = [
  85              'contextblock' => CONTEXT_BLOCK,
  86              'contextuser' => CONTEXT_USER,
  87              'userid' => $userid,
  88          ];
  89  
  90          $contextlist->add_from_sql($sql, $params);
  91  
  92          return $contextlist;
  93      }
  94  
  95      /**
  96       * Get the list of users who have data within a context.
  97       *
  98       * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
  99       */
 100      public static function get_users_in_context(userlist $userlist) {
 101          // This block doesn't know who information is stored against unless it
 102          // is at the user context.
 103          $context = $userlist->get_context();
 104  
 105          if (!$context instanceof \context_block) {
 106              return;
 107          }
 108  
 109          $sql = "SELECT bpc.instanceid AS userid
 110                    FROM {block_instances} bi
 111                    JOIN {context} bpc ON bpc.id = bi.parentcontextid
 112                   WHERE bi.blockname = 'html'
 113                     AND bpc.contextlevel = :contextuser
 114                     AND bi.id = :blockinstanceid";
 115  
 116          $params = [
 117              'contextuser' => CONTEXT_USER,
 118              'blockinstanceid' => $context->instanceid
 119          ];
 120  
 121          $userlist->add_from_sql('userid', $sql, $params);
 122      }
 123  
 124      /**
 125       * Export all user data for the specified user, in the specified contexts.
 126       *
 127       * @param   approved_contextlist    $contextlist    The approved contexts to export information for.
 128       */
 129      public static function export_user_data(approved_contextlist $contextlist) {
 130          global $DB;
 131  
 132          $user = $contextlist->get_user();
 133  
 134          list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
 135  
 136          $sql = "SELECT
 137                      c.id AS contextid,
 138                      bi.*
 139                    FROM {context} c
 140              INNER JOIN {block_instances} bi ON bi.id = c.instanceid AND c.contextlevel = :contextlevel
 141                   WHERE bi.blockname = 'html'
 142                     AND(
 143                      c.id {$contextsql}
 144                  )
 145          ";
 146  
 147          $params = [
 148              'contextlevel' => CONTEXT_BLOCK,
 149          ];
 150          $params += $contextparams;
 151  
 152          $instances = $DB->get_recordset_sql($sql, $params);
 153          foreach ($instances as $instance) {
 154              $context = \context_block::instance($instance->id);
 155              $block = block_instance('html', $instance);
 156              if (empty($block->config)) {
 157                  // Skip this block. It has not been configured.
 158                  continue;
 159              }
 160  
 161              $html = writer::with_context($context)
 162                  ->rewrite_pluginfile_urls([], 'block_html', 'content', null, $block->config->text);
 163  
 164              // Default to FORMAT_HTML which is what will have been used before the
 165              // editor was properly implemented for the block.
 166              $format = isset($block->config->format) ? $block->config->format : FORMAT_HTML;
 167  
 168              $filteropt = (object) [
 169                  'overflowdiv' => true,
 170                  'noclean' => true,
 171              ];
 172              $html = format_text($html, $format, $filteropt);
 173  
 174              $data = helper::get_context_data($context, $user);
 175              helper::export_context_files($context, $user);
 176              $data->title = $block->config->title;
 177              $data->content = $html;
 178  
 179              writer::with_context($context)->export_data([], $data);
 180          }
 181          $instances->close();
 182      }
 183  
 184      /**
 185       * Delete all data for all users in the specified context.
 186       *
 187       * @param   context                 $context   The specific context to delete data for.
 188       */
 189      public static function delete_data_for_all_users_in_context(\context $context) {
 190  
 191          if (!$context instanceof \context_block) {
 192              return;
 193          }
 194  
 195          // The only way to delete data for the html block is to delete the block instance itself.
 196          if ($blockinstance = static::get_instance_from_context($context)) {
 197              blocks_delete_instance($blockinstance);
 198          }
 199      }
 200  
 201      /**
 202       * Delete multiple users within a single context.
 203       *
 204       * @param   approved_userlist       $userlist The approved context and user information to delete information for.
 205       */
 206      public static function delete_data_for_users(approved_userlist $userlist) {
 207          $context = $userlist->get_context();
 208  
 209          if ($context instanceof \context_block && ($blockinstance = static::get_instance_from_context($context))) {
 210              blocks_delete_instance($blockinstance);
 211          }
 212      }
 213  
 214      /**
 215       * Delete all user data for the specified user, in the specified contexts.
 216       *
 217       * @param   approved_contextlist    $contextlist    The approved contexts and user information to delete information for.
 218       */
 219      public static function delete_data_for_user(approved_contextlist $contextlist) {
 220          // The only way to delete data for the html block is to delete the block instance itself.
 221          foreach ($contextlist as $context) {
 222  
 223              if (!$context instanceof \context_block) {
 224                  continue;
 225              }
 226              if ($blockinstance = static::get_instance_from_context($context)) {
 227                  blocks_delete_instance($blockinstance);
 228              }
 229          }
 230      }
 231  
 232      /**
 233       * Get the block instance record for the specified context.
 234       *
 235       * @param   \context_block $context The context to fetch
 236       * @return  \stdClass
 237       */
 238      protected static function get_instance_from_context(\context_block $context) {
 239          global $DB;
 240  
 241          return $DB->get_record('block_instances', ['id' => $context->instanceid, 'blockname' => 'html']);
 242      }
 243  }