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 400] [Versions 311 and 401] [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   * Contains class core_tag_external
  19   *
  20   * @package    core_tag
  21   * @copyright  2015 Marina Glancy
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  require_once("$CFG->libdir/externallib.php");
  28  require_once("$CFG->dirroot/webservice/externallib.php");
  29  
  30  /**
  31   * Tags-related web services
  32   *
  33   * @package    core_tag
  34   * @copyright  2015 Marina Glancy
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class core_tag_external extends external_api {
  38  
  39      /**
  40       * Parameters for function update_tags()
  41       *
  42       * @return external_function_parameters
  43       */
  44      public static function update_tags_parameters() {
  45          return new external_function_parameters(
  46              array(
  47                  'tags' => new external_multiple_structure(
  48                      new external_single_structure(
  49                          array(
  50                              'id' => new external_value(PARAM_INT, 'tag id'),
  51                              'rawname' => new external_value(PARAM_RAW, 'tag raw name (may contain capital letters)',
  52                                      VALUE_OPTIONAL),
  53                              'description' => new external_value(PARAM_RAW, 'tag description', VALUE_OPTIONAL),
  54                              'descriptionformat' => new external_value(PARAM_INT, 'tag description format', VALUE_OPTIONAL),
  55                              'flag' => new external_value(PARAM_INT, 'flag', VALUE_OPTIONAL),
  56                              'official' => new external_value(PARAM_INT,
  57                                  '(deprecated, use isstandard) whether this flag is standard', VALUE_OPTIONAL),
  58                              'isstandard' => new external_value(PARAM_INT, 'whether this flag is standard', VALUE_OPTIONAL),
  59                          )
  60                      )
  61                  )
  62              )
  63          );
  64      }
  65  
  66      /**
  67       * Update tags
  68       *
  69       * @param array $tags
  70       */
  71      public static function update_tags($tags) {
  72          global $CFG, $PAGE, $DB;
  73  
  74          // Validate and normalize parameters.
  75          $tags = self::validate_parameters(self::update_tags_parameters(), array('tags' => $tags));
  76  
  77          $systemcontext = context_system::instance();
  78          $canmanage = has_capability('moodle/tag:manage', $systemcontext);
  79          $canedit = has_capability('moodle/tag:edit', $systemcontext);
  80          $warnings = array();
  81  
  82          if (empty($CFG->usetags)) {
  83              throw new moodle_exception('tagsaredisabled', 'tag');
  84          }
  85  
  86          $renderer = $PAGE->get_renderer('core');
  87          foreach ($tags['tags'] as $tag) {
  88              $tag = (array)$tag;
  89              if (array_key_exists('rawname', $tag)) {
  90                  $tag['rawname'] = clean_param($tag['rawname'], PARAM_TAG);
  91                  if (empty($tag['rawname'])) {
  92                      unset($tag['rawname']);
  93                  }
  94              }
  95              if (!$canmanage) {
  96                  // User without manage capability can not change any fields except for descriptions.
  97                  $tag = array_intersect_key($tag, array('id' => 1,
  98                      'description' => 1, 'descriptionformat' => 1));
  99              }
 100              if (!$canedit) {
 101                  // User without edit capability can not change description.
 102                  $tag = array_diff_key($tag,
 103                          array('description' => 1, 'descriptionformat' => 1));
 104              }
 105              if (count($tag) <= 1) {
 106                  $warnings[] = array(
 107                      'item' => $tag['id'],
 108                      'warningcode' => 'nothingtoupdate',
 109                      'message' => get_string('nothingtoupdate', 'core_tag')
 110                  );
 111                  continue;
 112              }
 113              if (!$tagobject = core_tag_tag::get($tag['id'], '*')) {
 114                  $warnings[] = array(
 115                      'item' => $tag['id'],
 116                      'warningcode' => 'tagnotfound',
 117                      'message' => get_string('tagnotfound', 'error')
 118                  );
 119                  continue;
 120              }
 121              // First check if new tag name is allowed.
 122              if (!empty($tag['rawname']) && ($existing = core_tag_tag::get_by_name($tagobject->tagcollid, $tag['rawname']))) {
 123                  if ($existing->id != $tag['id']) {
 124                      $warnings[] = array(
 125                          'item' => $tag['id'],
 126                          'warningcode' => 'namesalreadybeeingused',
 127                          'message' => get_string('namesalreadybeeingused', 'core_tag')
 128                      );
 129                      continue;
 130                  }
 131              }
 132              if (array_key_exists('official', $tag)) {
 133                  // Parameter 'official' deprecated and replaced with 'isstandard'.
 134                  $tag['isstandard'] = $tag['official'] ? 1 : 0;
 135                  unset($tag['official']);
 136              }
 137              if (isset($tag['flag'])) {
 138                  if ($tag['flag']) {
 139                      $tagobject->flag();
 140                  } else {
 141                      $tagobject->reset_flag();
 142                  }
 143                  unset($tag['flag']);
 144              }
 145              unset($tag['id']);
 146              if (count($tag)) {
 147                  $tagobject->update($tag);
 148              }
 149          }
 150          return array('warnings' => $warnings);
 151      }
 152  
 153      /**
 154       * Return structure for update_tag()
 155       *
 156       * @return external_description
 157       */
 158      public static function update_tags_returns() {
 159          return new external_single_structure(
 160              array(
 161                  'warnings' => new external_warnings()
 162              )
 163          );
 164      }
 165  
 166      /**
 167       * Parameters for function get_tags()
 168       *
 169       * @return external_function_parameters
 170       */
 171      public static function get_tags_parameters() {
 172          return new external_function_parameters(
 173              array(
 174                  'tags' => new external_multiple_structure(
 175                      new external_single_structure(
 176                          array(
 177                              'id' => new external_value(PARAM_INT, 'tag id'),
 178                          )
 179                      )
 180                  )
 181              )
 182          );
 183      }
 184  
 185      /**
 186       * Get tags by their ids
 187       *
 188       * @param array $tags
 189       */
 190      public static function get_tags($tags) {
 191          global $CFG, $PAGE, $DB;
 192  
 193          // Validate and normalize parameters.
 194          $tags = self::validate_parameters(self::get_tags_parameters(), array('tags' => $tags));
 195  
 196          $systemcontext = context_system::instance();
 197          self::validate_context($systemcontext);
 198  
 199          $canmanage = has_capability('moodle/tag:manage', $systemcontext);
 200          $canedit = has_capability('moodle/tag:edit', $systemcontext);
 201  
 202          $return = array();
 203          $warnings = array();
 204  
 205          if (empty($CFG->usetags)) {
 206              throw new moodle_exception('tagsaredisabled', 'tag');
 207          }
 208  
 209          $renderer = $PAGE->get_renderer('core');
 210          foreach ($tags['tags'] as $tag) {
 211              $tag = (array)$tag;
 212              if (!$tagobject = $DB->get_record('tag', array('id' => $tag['id']))) {
 213                  $warnings[] = array(
 214                      'item' => $tag['id'],
 215                      'warningcode' => 'tagnotfound',
 216                      'message' => get_string('tagnotfound', 'error')
 217                  );
 218                  continue;
 219              }
 220              $tagoutput = new \core_tag\output\tag($tagobject);
 221              // Do not return some information to users without permissions.
 222              $rv = $tagoutput->export_for_template($renderer);
 223              if (!$canmanage) {
 224                  if (!$canedit) {
 225                      unset($rv->isstandard);
 226                      unset($rv->official);
 227                  }
 228                  unset($rv->flag);
 229              }
 230              $return[] = $rv;
 231          }
 232          return array('tags' => $return, 'warnings' => $warnings);
 233      }
 234  
 235      /**
 236       * Return structure for get_tag()
 237       *
 238       * @return external_description
 239       */
 240      public static function get_tags_returns() {
 241          return new external_single_structure(
 242              array(
 243                  'tags' => new external_multiple_structure( new external_single_structure(
 244                      array(
 245                          'id' => new external_value(PARAM_INT, 'tag id'),
 246                          'tagcollid' => new external_value(PARAM_INT, 'tag collection id'),
 247                          'name' => new external_value(PARAM_TAG, 'name'),
 248                          'rawname' => new external_value(PARAM_RAW, 'tag raw name (may contain capital letters)'),
 249                          'description' => new external_value(PARAM_RAW, 'tag description'),
 250                          'descriptionformat' => new external_format_value(PARAM_INT, 'tag description format'),
 251                          'flag' => new external_value(PARAM_INT, 'flag', VALUE_OPTIONAL),
 252                          'official' => new external_value(PARAM_INT,
 253                              'whether this flag is standard (deprecated, use isstandard)', VALUE_OPTIONAL),
 254                          'isstandard' => new external_value(PARAM_INT, 'whether this flag is standard', VALUE_OPTIONAL),
 255                          'viewurl' => new external_value(PARAM_URL, 'URL to view'),
 256                      ), 'information about one tag')
 257                  ),
 258                  'warnings' => new external_warnings()
 259              )
 260          );
 261      }
 262  
 263      /**
 264       * Parameters for function get_tagindex()
 265       *
 266       * @return external_function_parameters
 267       */
 268      public static function get_tagindex_parameters() {
 269          return new external_function_parameters(
 270              array(
 271                  'tagindex' => new external_single_structure(array(
 272                      'tag' => new external_value(PARAM_TAG, 'tag name'),
 273                      'tc' => new external_value(PARAM_INT, 'tag collection id'),
 274                      'ta' => new external_value(PARAM_INT, 'tag area id'),
 275                      'excl' => new external_value(PARAM_BOOL, 'exlusive mode for this tag area', VALUE_OPTIONAL, 0),
 276                      'from' => new external_value(PARAM_INT, 'context id where the link was displayed', VALUE_OPTIONAL, 0),
 277                      'ctx' => new external_value(PARAM_INT, 'context id where to search for items', VALUE_OPTIONAL, 0),
 278                      'rec' => new external_value(PARAM_INT, 'search in the context recursive', VALUE_OPTIONAL, 1),
 279                      'page' => new external_value(PARAM_INT, 'page number (0-based)', VALUE_OPTIONAL, 0),
 280                  ), 'parameters')
 281              )
 282          );
 283      }
 284  
 285      /**
 286       * Get tags by their ids
 287       *
 288       * @param array $params
 289       */
 290      public static function get_tagindex($params) {
 291          global $PAGE;
 292          // Validate and normalize parameters.
 293          $tagindex = self::validate_parameters(
 294                  self::get_tagindex_parameters(), array('tagindex' => $params));
 295          $params = $tagindex['tagindex'] + array(
 296              'excl' => 0,
 297              'from' => 0,
 298              'ctx' => 0,
 299              'rec' => 1,
 300              'page' => 0
 301          );
 302  
 303          // Login to the course / module if applicable.
 304          $context = $params['ctx'] ? context::instance_by_id($params['ctx']) : context_system::instance();
 305          self::validate_context($context);
 306  
 307          $tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*', MUST_EXIST);
 308          $tagareas = core_tag_collection::get_areas($params['tc']);
 309          $tagindex = $tag->get_tag_index($tagareas[$params['ta']], $params['excl'], $params['from'],
 310                  $params['ctx'], $params['rec'], $params['page']);
 311          $renderer = $PAGE->get_renderer('core');
 312          return $tagindex->export_for_template($renderer);
 313      }
 314  
 315      /**
 316       * Return structure for get_tag()
 317       *
 318       * @return external_description
 319       */
 320      public static function get_tagindex_returns() {
 321          return new external_single_structure(
 322              array(
 323                  'tagid' => new external_value(PARAM_INT, 'tag id'),
 324                  'ta' => new external_value(PARAM_INT, 'tag area id'),
 325                  'component' => new external_value(PARAM_COMPONENT, 'component'),
 326                  'itemtype' => new external_value(PARAM_NOTAGS, 'itemtype'),
 327                  'nextpageurl' => new external_value(PARAM_URL, 'URL for the next page', VALUE_OPTIONAL),
 328                  'prevpageurl' => new external_value(PARAM_URL, 'URL for the next page', VALUE_OPTIONAL),
 329                  'exclusiveurl' => new external_value(PARAM_URL, 'URL for exclusive link', VALUE_OPTIONAL),
 330                  'exclusivetext' => new external_value(PARAM_TEXT, 'text for exclusive link', VALUE_OPTIONAL),
 331                  'title' => new external_value(PARAM_RAW, 'title'),
 332                  'content' => new external_value(PARAM_RAW, 'title'),
 333                  'hascontent' => new external_value(PARAM_INT, 'whether the content is present'),
 334                  'anchor' => new external_value(PARAM_TEXT, 'name of anchor', VALUE_OPTIONAL),
 335              ), 'tag index'
 336          );
 337      }
 338  
 339  
 340      /**
 341       * Parameters for function get_tagindex_per_area()
 342       *
 343       * @return external_function_parameters
 344       * @since  Moodle 3.7
 345       */
 346      public static function get_tagindex_per_area_parameters() {
 347          return new external_function_parameters(
 348              array(
 349                  'tagindex' => new external_single_structure(array(
 350                      'id' => new external_value(PARAM_INT, 'tag id', VALUE_OPTIONAL, 0),
 351                      'tag' => new external_value(PARAM_TAG, 'tag name', VALUE_OPTIONAL, ''),
 352                      'tc' => new external_value(PARAM_INT, 'tag collection id', VALUE_OPTIONAL, 0),
 353                      'ta' => new external_value(PARAM_INT, 'tag area id', VALUE_OPTIONAL, 0),
 354                      'excl' => new external_value(PARAM_BOOL, 'exlusive mode for this tag area', VALUE_OPTIONAL, 0),
 355                      'from' => new external_value(PARAM_INT, 'context id where the link was displayed', VALUE_OPTIONAL, 0),
 356                      'ctx' => new external_value(PARAM_INT, 'context id where to search for items', VALUE_OPTIONAL, 0),
 357                      'rec' => new external_value(PARAM_INT, 'search in the context recursive', VALUE_OPTIONAL, 1),
 358                      'page' => new external_value(PARAM_INT, 'page number (0-based)', VALUE_OPTIONAL, 0),
 359                  ), 'parameters')
 360              )
 361          );
 362      }
 363  
 364      /**
 365       * Returns the tag index per multiple areas if requested.
 366       *
 367       * @param array $params Tag index required information.
 368       * @throws moodle_exception
 369       * @since  Moodle 3.7
 370       */
 371      public static function get_tagindex_per_area($params) {
 372          global $CFG, $PAGE;
 373          // Validate and normalize parameters.
 374          $tagindex = self::validate_parameters(
 375              self::get_tagindex_per_area_parameters(), array('tagindex' => $params));
 376          $params = $tagindex['tagindex'] + array(    // Force defaults.
 377              'id' => 0,
 378              'tag' => '',
 379              'tc' => 0,
 380              'ta' => 0,
 381              'excl' => 0,
 382              'from' => 0,
 383              'ctx' => 0,
 384              'rec' => 1,
 385              'page' => 0,
 386          );
 387  
 388          if (empty($CFG->usetags)) {
 389              throw new moodle_exception('tagsaredisabled', 'tag');
 390          }
 391  
 392          if (!empty($params['tag'])) {
 393              if (empty($params['tc'])) {
 394                  // Tag name specified but tag collection was not. Try to guess it.
 395                  $tags = core_tag_tag::guess_by_name($params['tag'], '*');
 396                  if (count($tags) > 1) {
 397                      // It is in more that one collection, do not display.
 398                      throw new moodle_exception('Tag is in more that one collection, please indicate one.');
 399                  } else if (count($tags) == 1) {
 400                      $tag = reset($tags);
 401                  }
 402              } else {
 403                  if (!$tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*')) {
 404                      // Not found in collection.
 405                      throw new moodle_exception('notagsfound', 'tag');
 406                  }
 407              }
 408          } else if (!empty($params['id'])) {
 409              $tag = core_tag_tag::get($params['id'], '*');
 410          }
 411  
 412          if (empty($tag)) {
 413              throw new moodle_exception('notagsfound', 'tag');
 414          }
 415  
 416          // Login to the course / module if applicable.
 417          $context = !empty($params['ctx']) ? context::instance_by_id($params['ctx']) : context_system::instance();
 418          self::validate_context($context);
 419  
 420          $tag = core_tag_tag::get_by_name($params['tc'], $tag->name, '*', MUST_EXIST);
 421          $tagareas = core_tag_collection::get_areas($params['tc']);
 422          $tagareaid = $params['ta'];
 423  
 424           $exclusivemode = 0;
 425          // Find all areas in this collection and their items tagged with this tag.
 426          if ($tagareaid) {
 427              $tagareas = array($tagareas[$tagareaid]);
 428          }
 429          if (!$tagareaid && count($tagareas) == 1) {
 430              // Automatically set "exclusive" mode for tag collection with one tag area only.
 431              $params['excl'] = 1;
 432          }
 433  
 434          $renderer = $PAGE->get_renderer('core');
 435          $result = array();
 436          foreach ($tagareas as $ta) {
 437              $tagindex = $tag->get_tag_index($ta, $params['excl'], $params['from'], $params['ctx'], $params['rec'], $params['page']);
 438              if (!empty($tagindex->hascontent)) {
 439                  $result[] = $tagindex->export_for_template($renderer);
 440              }
 441          }
 442          return $result;
 443      }
 444  
 445      /**
 446       * Return structure for get_tagindex_per_area
 447       *
 448       * @return external_description
 449       * @since  Moodle 3.7
 450       */
 451      public static function get_tagindex_per_area_returns() {
 452          return new external_multiple_structure(
 453              self::get_tagindex_returns()
 454          );
 455      }
 456  
 457      /**
 458       * Returns description of get_tag_areas() parameters.
 459       *
 460       * @return external_function_parameters
 461       * @since  Moodle 3.7
 462       */
 463      public static function get_tag_areas_parameters() {
 464          return new external_function_parameters(array());
 465      }
 466  
 467      /**
 468       * Retrieves existing tag areas.
 469       *
 470       * @return array an array of warnings and objects containing the plugin information
 471       * @throws moodle_exception
 472       * @since  Moodle 3.7
 473       */
 474      public static function get_tag_areas() {
 475          global $CFG, $PAGE;
 476  
 477          if (empty($CFG->usetags)) {
 478              throw new moodle_exception('tagsaredisabled', 'tag');
 479          }
 480  
 481          $context = context_system::instance();
 482          self::validate_context($context);
 483          $PAGE->set_context($context); // Needed by internal APIs.
 484          $output = $PAGE->get_renderer('core');
 485  
 486          $areas = core_tag_area::get_areas();
 487          $exportedareas = array();
 488          foreach ($areas as $itemtype => $component) {
 489              foreach ($component as $area) {
 490                  // Move optional fields not part of the DB table to otherdata.
 491                  $locked = false;
 492                  if (isset($area->locked)) {
 493                      $locked = $area->locked;
 494                      unset($area->locked);
 495                  }
 496                  $exporter = new \core_tag\external\tag_area_exporter($area, array('locked' => $locked));
 497                  $exportedareas[] = $exporter->export($output);
 498              }
 499          }
 500  
 501          return array(
 502              'areas' => $exportedareas,
 503              'warnings' => array(),
 504          );
 505      }
 506  
 507      /**
 508       * Returns description of get_tag_areas() result value.
 509       *
 510       * @return external_description
 511       * @since  Moodle 3.7
 512       */
 513      public static function get_tag_areas_returns() {
 514          return new external_single_structure(
 515              array(
 516                  'areas' => new external_multiple_structure(
 517                      \core_tag\external\tag_area_exporter::get_read_structure()
 518                  ),
 519                  'warnings' => new external_warnings(),
 520              )
 521          );
 522      }
 523  
 524      /**
 525       * Returns description of get_tag_collections() parameters.
 526       *
 527       * @return external_function_parameters
 528       * @since  Moodle 3.7
 529       */
 530      public static function get_tag_collections_parameters() {
 531          return new external_function_parameters(array());
 532      }
 533  
 534      /**
 535       * Retrieves existing tag collections.
 536       *
 537       * @return array an array of warnings and tag collections
 538       * @throws moodle_exception
 539       * @since  Moodle 3.7
 540       */
 541      public static function get_tag_collections() {
 542          global $CFG, $PAGE;
 543  
 544          if (empty($CFG->usetags)) {
 545              throw new moodle_exception('tagsaredisabled', 'tag');
 546          }
 547  
 548          $context = context_system::instance();
 549          self::validate_context($context);
 550          $PAGE->set_context($context); // Needed by internal APIs.
 551          $output = $PAGE->get_renderer('core');
 552  
 553          $collections = core_tag_collection::get_collections();
 554          $exportedcollections = array();
 555          foreach ($collections as $collection) {
 556              $exporter = new \core_tag\external\tag_collection_exporter($collection);
 557              $exportedcollections[] = $exporter->export($output);
 558          }
 559  
 560          return array(
 561              'collections' => $exportedcollections,
 562              'warnings' => array(),
 563          );
 564      }
 565  
 566      /**
 567       * Returns description of get_tag_collections() result value.
 568       *
 569       * @return external_description
 570       * @since  Moodle 3.7
 571       */
 572      public static function get_tag_collections_returns() {
 573          return new external_single_structure(
 574              array(
 575                  'collections' => new external_multiple_structure(
 576                      \core_tag\external\tag_collection_exporter::get_read_structure()
 577                  ),
 578                  'warnings' => new external_warnings(),
 579              )
 580          );
 581      }
 582  
 583      /**
 584       * Returns description of get_tag_cloud() parameters.
 585       *
 586       * @return external_function_parameters
 587       * @since  Moodle 3.7
 588       */
 589      public static function get_tag_cloud_parameters() {
 590          return new external_function_parameters(
 591              array(
 592                  'tagcollid' => new external_value(PARAM_INT, 'Tag collection id.', VALUE_DEFAULT, 0),
 593                  'isstandard' => new external_value(PARAM_BOOL, 'Whether to return only standard tags.', VALUE_DEFAULT, false),
 594                  'limit' => new external_value(PARAM_INT, 'Maximum number of tags to retrieve.', VALUE_DEFAULT, 150),
 595                  'sort' => new external_value(PARAM_ALPHA, 'Sort order for display
 596                      (id, name, rawname, count, flag, isstandard, tagcollid).', VALUE_DEFAULT, 'name'),
 597                  'search' => new external_value(PARAM_RAW, 'Search string.', VALUE_DEFAULT, ''),
 598                  'fromctx' => new external_value(PARAM_INT, 'Context id where this tag cloud is displayed.', VALUE_DEFAULT, 0),
 599                  'ctx' => new external_value(PARAM_INT, 'Only retrieve tag instances in this context.', VALUE_DEFAULT, 0),
 600                  'rec' => new external_value(PARAM_INT, 'Retrieve tag instances in the $ctx context and it\'s children.',
 601                      VALUE_DEFAULT, 1),
 602              )
 603          );
 604      }
 605  
 606      /**
 607       * Retrieves a tag cloud for display.
 608       *
 609       * @param int $tagcollid tag collection id
 610       * @param bool $isstandard return only standard tags
 611       * @param int $limit maximum number of tags to retrieve, tags are sorted by the instance count
 612       *            descending here regardless of $sort parameter
 613       * @param string $sort sort order for display, default 'name' - tags will be sorted after they are retrieved
 614       * @param string $search search string
 615       * @param int $fromctx context id where this tag cloud is displayed
 616       * @param int $ctx only retrieve tag instances in this context
 617       * @param int $rec retrieve tag instances in the $ctx context and it's children (default 1)
 618       * @return array an array of warnings and tag cloud information and items
 619       * @throws moodle_exception
 620       * @since  Moodle 3.7
 621       */
 622      public static function get_tag_cloud($tagcollid = 0, $isstandard = false, $limit = 150, $sort = 'name',
 623              $search = '', $fromctx = 0, $ctx = 0, $rec = 1) {
 624          global $CFG, $PAGE;
 625  
 626          $params = self::validate_parameters(self::get_tag_cloud_parameters(),
 627              array(
 628                  'tagcollid' => $tagcollid,
 629                  'isstandard' => $isstandard,
 630                  'limit' => $limit,
 631                  'sort' => $sort,
 632                  'search' => $search,
 633                  'fromctx' => $fromctx,
 634                  'ctx' => $ctx,
 635                  'rec' => $rec,
 636              )
 637          );
 638  
 639          if (empty($CFG->usetags)) {
 640              throw new moodle_exception('tagsaredisabled', 'tag');
 641          }
 642  
 643          $context = context_system::instance();
 644          self::validate_context($context);
 645          $PAGE->set_context($context); // Needed by internal APIs.
 646          $output = $PAGE->get_renderer('core');
 647  
 648          $tagcloud = core_tag_collection::get_tag_cloud($params['tagcollid'], $params['isstandard'], $params['limit'],
 649              $params['sort'], $params['search'], $params['fromctx'], $params['ctx'], $params['rec']);
 650  
 651          $result = $tagcloud->export_for_template($output);
 652          $result->warnings = array();
 653  
 654          return (array) $result;
 655      }
 656  
 657      /**
 658       * Returns description of get_tag_cloud() result value.
 659       *
 660       * @return external_description
 661       * @since  Moodle 3.7
 662       */
 663      public static function get_tag_cloud_returns() {
 664          return new external_single_structure(
 665              array(
 666                  'tags' => new external_multiple_structure(
 667                      new external_single_structure(
 668                          array(
 669                              'name' => new external_value(PARAM_TAG, 'Tag name.'),
 670                              'viewurl' => new external_value(PARAM_RAW, 'URL to view the tag index.'),
 671                              'flag' => new external_value(PARAM_BOOL, 'Whether the tag is flagged as inappropriate.',
 672                                  VALUE_OPTIONAL),
 673                              'isstandard' => new external_value(PARAM_BOOL, 'Whether is a standard tag or not.', VALUE_OPTIONAL),
 674                              'count' => new external_value(PARAM_INT, 'Number of tag instances.', VALUE_OPTIONAL),
 675                              'size' => new external_value(PARAM_INT, 'Proportional size to display the tag.', VALUE_OPTIONAL),
 676                          ), 'Tags.'
 677                      )
 678                  ),
 679                  'tagscount' => new external_value(PARAM_INT, 'Number of tags returned.'),
 680                  'totalcount' => new external_value(PARAM_INT, 'Total count of tags.'),
 681                  'warnings' => new external_warnings(),
 682              )
 683          );
 684      }
 685  }