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.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 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   * Blocks external API
  19   *
  20   * @package    core_block
  21   * @category   external
  22   * @copyright  2017 Juan Leyva <juan@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @since      Moodle 3.3
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die;
  28  
  29  require_once("$CFG->libdir/externallib.php");
  30  require_once("$CFG->dirroot/my/lib.php");
  31  
  32  /**
  33   * Blocks external functions
  34   *
  35   * @package    core_block
  36   * @category   external
  37   * @copyright  2015 Juan Leyva <juan@moodle.com>
  38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   * @since      Moodle 3.3
  40   */
  41  class core_block_external extends external_api {
  42  
  43  
  44      /**
  45       * Returns a block structure.
  46       *
  47       * @return external_single_structure a block single structure.
  48       * @since  Moodle 3.6
  49       */
  50      private static function get_block_structure() {
  51          return new external_single_structure(
  52              array(
  53                  'instanceid'    => new external_value(PARAM_INT, 'Block instance id.'),
  54                  'name'          => new external_value(PARAM_PLUGIN, 'Block name.'),
  55                  'region'        => new external_value(PARAM_ALPHANUMEXT, 'Block region.'),
  56                  'positionid'    => new external_value(PARAM_INT, 'Position id.'),
  57                  'collapsible'   => new external_value(PARAM_BOOL, 'Whether the block is collapsible.'),
  58                  'dockable'      => new external_value(PARAM_BOOL, 'Whether the block is dockable.'),
  59                  'weight'        => new external_value(PARAM_INT, 'Used to order blocks within a region.', VALUE_OPTIONAL),
  60                  'visible'       => new external_value(PARAM_BOOL, 'Whether the block is visible.', VALUE_OPTIONAL),
  61                  'contents'      => new external_single_structure(
  62                      array(
  63                          'title'         => new external_value(PARAM_RAW, 'Block title.'),
  64                          'content'       => new external_value(PARAM_RAW, 'Block contents.'),
  65                          'contentformat' => new external_format_value('content'),
  66                          'footer'        => new external_value(PARAM_RAW, 'Block footer.'),
  67                          'files'         => new external_files('Block files.'),
  68                      ),
  69                      'Block contents (if required).', VALUE_OPTIONAL
  70                  ),
  71                  'configs' => new external_multiple_structure(
  72                      new external_single_structure(
  73                          array(
  74                              'name' => new external_value(PARAM_RAW, 'Name.'),
  75                              'value' => new external_value(PARAM_RAW, 'JSON encoded representation of the config value.'),
  76                              'type' => new external_value(PARAM_ALPHA, 'Type (instance or plugin).'),
  77                          )
  78                      ),
  79                      'Block instance and plugin configuration settings.', VALUE_OPTIONAL
  80                  ),
  81              ), 'Block information.'
  82          );
  83      }
  84  
  85      /**
  86       * Convenience function for getting all the blocks of the current $PAGE.
  87       *
  88       * @param bool $includeinvisible Whether to include not visible blocks or not
  89       * @param bool $returncontents Whether to return the block contents
  90       * @return array Block information
  91       * @since  Moodle 3.6
  92       */
  93      private static function get_all_current_page_blocks($includeinvisible = false, $returncontents = false) {
  94          global $PAGE, $OUTPUT;
  95  
  96          // Set page URL to a fake URL to avoid errors.
  97          $PAGE->set_url(new \moodle_url('/webservice/core_block_external/'));
  98  
  99          // Load the block instances for all the regions.
 100          $PAGE->blocks->load_blocks($includeinvisible);
 101          $PAGE->blocks->create_all_block_instances();
 102  
 103          $allblocks = array();
 104          $blocks = $PAGE->blocks->get_content_for_all_regions($OUTPUT);
 105          foreach ($blocks as $region => $regionblocks) {
 106              $regioninstances = $PAGE->blocks->get_blocks_for_region($region);
 107              // Index block instances to retrieve required info.
 108              $blockinstances = array();
 109              foreach ($regioninstances as $ri) {
 110                  $blockinstances[$ri->instance->id] = $ri;
 111              }
 112  
 113              foreach ($regionblocks as $bc) {
 114                  $block = [
 115                      'instanceid' => $bc->blockinstanceid,
 116                      'name' => $blockinstances[$bc->blockinstanceid]->instance->blockname,
 117                      'region' => $region,
 118                      'positionid' => $bc->blockpositionid,
 119                      'collapsible' => (bool) $bc->collapsible,
 120                      'dockable' => (bool) $bc->dockable,
 121                      'weight' => $blockinstances[$bc->blockinstanceid]->instance->weight,
 122                      'visible' => $blockinstances[$bc->blockinstanceid]->instance->visible,
 123                  ];
 124                  if ($returncontents) {
 125                      $block['contents'] = (array) $blockinstances[$bc->blockinstanceid]->get_content_for_external($OUTPUT);
 126                  }
 127                  $configs = (array) $blockinstances[$bc->blockinstanceid]->get_config_for_external();
 128                  foreach ($configs as $type => $data) {
 129                      foreach ((array) $data as $name => $value) {
 130                          $block['configs'][] = [
 131                              'name' => $name,
 132                              'value' => json_encode($value), // Always JSON encode, we may receive non-scalar values.
 133                              'type' => $type,
 134                          ];
 135                      }
 136                  }
 137  
 138                  $allblocks[] = $block;
 139              }
 140          }
 141          return $allblocks;
 142      }
 143  
 144      /**
 145       * Returns description of get_course_blocks parameters.
 146       *
 147       * @return external_function_parameters
 148       * @since Moodle 3.3
 149       */
 150      public static function get_course_blocks_parameters() {
 151          return new external_function_parameters(
 152              array(
 153                  'courseid'  => new external_value(PARAM_INT, 'course id'),
 154                  'returncontents' => new external_value(PARAM_BOOL, 'Whether to return the block contents.', VALUE_DEFAULT, false),
 155              )
 156          );
 157      }
 158  
 159      /**
 160       * Returns blocks information for a course.
 161       *
 162       * @param int $courseid The course id
 163       * @param bool $returncontents Whether to return the block contents
 164       * @return array Blocks list and possible warnings
 165       * @throws moodle_exception
 166       * @since Moodle 3.3
 167       */
 168      public static function get_course_blocks($courseid, $returncontents = false) {
 169          global $PAGE;
 170  
 171          $warnings = array();
 172          $params = self::validate_parameters(self::get_course_blocks_parameters(),
 173              ['courseid' => $courseid, 'returncontents' => $returncontents]);
 174  
 175          $course = get_course($params['courseid']);
 176          $context = context_course::instance($course->id);
 177          self::validate_context($context);
 178  
 179          // Specific layout for frontpage course.
 180          if ($course->id == SITEID) {
 181              $PAGE->set_pagelayout('frontpage');
 182              $PAGE->set_pagetype('site-index');
 183          } else {
 184              $PAGE->set_pagelayout('course');
 185              // Ensure course format is set (view course/view.php).
 186              $course->format = course_get_format($course)->get_format();
 187              $PAGE->set_pagetype('course-view-' . $course->format);
 188          }
 189  
 190          $allblocks = self::get_all_current_page_blocks(false, $params['returncontents']);
 191  
 192          return array(
 193              'blocks' => $allblocks,
 194              'warnings' => $warnings
 195          );
 196      }
 197  
 198      /**
 199       * Returns description of get_course_blocks result values.
 200       *
 201       * @return external_single_structure
 202       * @since Moodle 3.3
 203       */
 204      public static function get_course_blocks_returns() {
 205  
 206          return new external_single_structure(
 207              array(
 208                  'blocks' => new external_multiple_structure(self::get_block_structure(), 'List of blocks in the course.'),
 209                  'warnings'  => new external_warnings(),
 210              )
 211          );
 212      }
 213  
 214      /**
 215       * Returns description of get_dashboard_blocks parameters.
 216       *
 217       * @return external_function_parameters
 218       * @since Moodle 3.6
 219       */
 220      public static function get_dashboard_blocks_parameters() {
 221          return new external_function_parameters(
 222              array(
 223                  'userid'  => new external_value(PARAM_INT, 'User id (optional), default is current user.', VALUE_DEFAULT, 0),
 224                  'returncontents' => new external_value(PARAM_BOOL, 'Whether to return the block contents.', VALUE_DEFAULT, false),
 225                  'mypage' => new external_value(PARAM_TEXT, 'What my page to return blocks of', VALUE_DEFAULT, MY_PAGE_DEFAULT),
 226              )
 227          );
 228      }
 229  
 230      /**
 231       * Returns blocks information for the given user dashboard.
 232       *
 233       * @param int $userid The user id to retrieve the blocks from, optional, default is to current user.
 234       * @param bool $returncontents Whether to return the block contents
 235       * @param string $mypage The page to get blocks of within my
 236       * @return array Blocks list and possible warnings
 237       * @throws moodle_exception
 238       * @since Moodle 3.6
 239       */
 240      public static function get_dashboard_blocks($userid = 0, $returncontents = false, $mypage = MY_PAGE_DEFAULT) {
 241          global $CFG, $USER, $PAGE;
 242  
 243          require_once($CFG->dirroot . '/my/lib.php');
 244  
 245          $warnings = array();
 246          $params = self::validate_parameters(self::get_dashboard_blocks_parameters(),
 247              ['userid' => $userid, 'returncontents' => $returncontents, 'mypage' => $mypage]);
 248  
 249          $userid = $params['userid'];
 250          if (empty($userid)) {
 251              $userid = $USER->id;
 252          }
 253  
 254          if ($USER->id != $userid) {
 255              // We must check if the current user can view other users dashboard.
 256              require_capability('moodle/site:config', context_system::instance());
 257              $user = core_user::get_user($userid, '*', MUST_EXIST);
 258              core_user::require_active_user($user);
 259          }
 260  
 261          $context = context_user::instance($userid);;
 262          self::validate_context($context);
 263  
 264          $currentpage = null;
 265          if ($params['mypage'] === MY_PAGE_DEFAULT) {
 266              $currentpage = my_get_page($userid);
 267          } else if ($params['mypage'] === MY_PAGE_COURSES) {
 268              $currentpage = my_get_page($userid, MY_PAGE_PUBLIC, MY_PAGE_COURSES);
 269          }
 270  
 271          if (!$currentpage) {
 272              throw new moodle_exception('mymoodlesetup');
 273          }
 274  
 275          $PAGE->set_context($context);
 276          $PAGE->set_pagelayout('mydashboard');
 277          $PAGE->set_pagetype('my-index');
 278          $PAGE->blocks->add_region('content');   // Need to add this special regition to retrieve the central blocks.
 279          $PAGE->set_subpage($currentpage->id);
 280  
 281          // Load the block instances in the current $PAGE for all the regions.
 282          $returninvisible = has_capability('moodle/my:manageblocks', $context) ? true : false;
 283          $allblocks = self::get_all_current_page_blocks($returninvisible, $params['returncontents']);
 284  
 285          // Temporary hack to be removed in 4.1.
 286          // Return always the course overview block so old versions of the app can list the user courses.
 287          if ($mypage == MY_PAGE_DEFAULT && core_useragent::is_moodle_app()) {
 288              $myoverviewfound = false;
 289  
 290              foreach ($allblocks as $block) {
 291                  if ($block['name'] == 'myoverview' && $block['visible']) {
 292                      $myoverviewfound = true;
 293                      break;
 294                  }
 295              }
 296  
 297              if (!$myoverviewfound) {
 298                  // Include a course overview fake block.
 299                  $allblocks[] = [
 300                      'instanceid' => 0,
 301                      'name' => 'myoverview',
 302                      'region' => 'forced',
 303                      'positionid' => null,
 304                      'collapsible' => true,
 305                      'dockable' => false,
 306                      'weight' => 0,
 307                      'visible' => true,
 308                  ];
 309              }
 310          }
 311          // End of the hack to be removed in 4.1 see MDL-73670.
 312  
 313          return array(
 314              'blocks' => $allblocks,
 315              'warnings' => $warnings
 316          );
 317      }
 318  
 319      /**
 320       * Returns description of get_dashboard_blocks result values.
 321       *
 322       * @return external_single_structure
 323       * @since Moodle 3.6
 324       */
 325      public static function get_dashboard_blocks_returns() {
 326  
 327          return new external_single_structure(
 328              array(
 329                  'blocks' => new external_multiple_structure(self::get_block_structure(), 'List of blocks in the dashboard.'),
 330                  'warnings'  => new external_warnings(),
 331              )
 332          );
 333      }
 334  }