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   * Contains class for displaying a badgeclass.
  19   *
  20   * @package   core_badges
  21   * @copyright 2019 Damyon Wiese
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core_badges\external;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  use core\external\exporter;
  30  use renderer_base;
  31  
  32  /**
  33   * Class for displaying a badge competency.
  34   *
  35   * @package   core_badges
  36   * @copyright 2019 Damyon Wiese
  37   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   */
  39  class badgeclass_exporter extends exporter {
  40  
  41      /**
  42       * Constructor - saves the persistent object, and the related objects.
  43       *
  44       * @param mixed $data - Either an stdClass or an array of values.
  45       * @param array $related - An optional list of pre-loaded objects related to this object.
  46       */
  47      public function __construct($data, $related = array()) {
  48          // Having mixed $data is causing some issues. As this class is treating $data as an object everywhere, it can be converted
  49          // to object at this point, to avoid errors and get the expected behaviour always.
  50          // $data is an array when this class is a request exporter in backpack_api_mapping, but it is an object when this is
  51          // used as a response exporter.
  52          $data = (object) $data;
  53  
  54          $pick = $this->pick_related();
  55          foreach ($pick as $one) {
  56              $isarray = false;
  57              // Allow [] to mean an array of values.
  58              if (substr($one, -2) === '[]') {
  59                  $one = substr($one, 0, -2);
  60                  $isarray = true;
  61              }
  62              $prefixed = 'related_' . $one;
  63              if (property_exists($data, $one) && !array_key_exists($one, $related)) {
  64                  if ($isarray) {
  65                      $newrelated = [];
  66                      foreach ($data->$one as $item) {
  67                          $newrelated[] = (object) $item;
  68                      }
  69                      $related[$one] = $newrelated;
  70                  } else {
  71                      $related[$one] = (object) $data->$one;
  72                  }
  73                  unset($data->$one);
  74              } else if (property_exists($data, $prefixed) && !array_key_exists($one, $related)) {
  75                  if ($isarray) {
  76                      $newrelated = [];
  77                      foreach ($data->$prefixed as $item) {
  78                          $newrelated[] = (object) $item;
  79                      }
  80                      $related[$one] = $newrelated;
  81                  } else {
  82                      $related[$one] = (object) $data->$prefixed;
  83                  }
  84                  unset($data->$prefixed);
  85              } else if (!array_key_exists($one, $related)) {
  86                  $related[$one] = null;
  87              }
  88          }
  89          parent::__construct($data, $related);
  90      }
  91  
  92      /**
  93       * List properties passed in $data that should be moved to $related in the constructor.
  94       *
  95       * @return array A list of properties to move from $data to $related.
  96       */
  97      public static function pick_related() {
  98          return ['alignment[]', 'criteria'];
  99      }
 100  
 101      /**
 102       * Map data from a request response to the internal structure.
 103       *
 104       * @param stdClass $data The remote data.
 105       * @param string $apiversion The backpack version used to communicate remotely.
 106       * @return stdClass
 107       */
 108      public static function map_external_data($data, $apiversion) {
 109          $mapped = new \stdClass();
 110          if (isset($data->entityType)) {
 111              $mapped->type = $data->entityType;
 112          } else {
 113              $mapped->type = $data->type;
 114          }
 115          if (isset($data->entityId)) {
 116              $mapped->id = $data->entityId;
 117          } else {
 118              $mapped->id = $data->id;
 119          }
 120          $mapped->name = $data->name;
 121          $mapped->image = $data->image;
 122          $mapped->issuer = $data->issuer;
 123          $mapped->description = $data->description;
 124          if (isset($data->openBadgeId)) {
 125              $mapped->hostedUrl = $data->openBadgeId;
 126          } else {
 127              $mapped->hostedUrl = $data->id;
 128          }
 129  
 130          return $mapped;
 131      }
 132  
 133      /**
 134       * Return the list of properties.
 135       *
 136       * @return array
 137       */
 138      protected static function define_properties() {
 139          return [
 140              'type' => [
 141                  'type' => PARAM_ALPHA,
 142                  'description' => 'BadgeClass',
 143              ],
 144              'id' => [
 145                  'type' => PARAM_RAW,
 146                  'description' => 'Unique identifier for this badgeclass',
 147              ],
 148              'issuer' => [
 149                  'type' => PARAM_RAW,
 150                  'description' => 'Unique identifier for this badgeclass',
 151                  'optional' => true,
 152              ],
 153              'name' => [
 154                  'type' => PARAM_TEXT,
 155                  'description' => 'Name of the badgeclass',
 156              ],
 157              'image' => [
 158                  'type' => PARAM_URL,
 159                  'description' => 'URL to the image.',
 160              ],
 161              'description' => [
 162                  'type' => PARAM_TEXT,
 163                  'description' => 'Description of the badge class.',
 164              ],
 165              'hostedUrl' => [
 166                  'type' => PARAM_RAW,
 167                  'description' => 'Identifier of the open badge for this assertion',
 168                  'optional' => true,
 169              ],
 170          ];
 171      }
 172  
 173      /**
 174       * Returns a list of objects that are related.
 175       *
 176       * @return array
 177       */
 178      protected static function define_related() {
 179          return array(
 180              'context' => 'context',
 181              'alignment' => 'stdClass[]?',
 182              'criteria' => 'stdClass?',
 183          );
 184      }
 185  
 186      /**
 187       * Return the list of additional properties.
 188       *
 189       * @return array
 190       */
 191      protected static function define_other_properties() {
 192          return array(
 193              'alignment' => array(
 194                  'type' => alignment_exporter::read_properties_definition(),
 195                  'optional' => true,
 196                  'multiple' => true
 197              ),
 198              'criteriaUrl' => array(
 199                  'type' => PARAM_URL,
 200                  'optional' => true
 201              ),
 202              'criteriaNarrative' => array(
 203                  'type' => PARAM_TEXT,
 204                  'optional' => true
 205              )
 206          );
 207      }
 208  
 209      /**
 210       * We map from related data passed as data to this exporter to clean exportable values.
 211       *
 212       * @param renderer_base $output
 213       * @return array
 214       */
 215      protected function get_other_values(renderer_base $output) {
 216          global $DB;
 217          $result = [];
 218  
 219          if (array_key_exists('alignment', $this->related) && $this->related['alignment'] !== null) {
 220              $alignment = [];
 221              foreach ($this->related['alignment'] as $alignment) {
 222                  $exporter = new alignment_exporter($alignment, $this->related);
 223                  $alignments[] = $exporter->export($output);
 224              }
 225              $result['alignment'] = $alignments;
 226          }
 227          if (array_key_exists('criteria', $this->related) && $this->related['criteria'] !== null) {
 228              if (property_exists($this->related['criteria'], 'id') && $this->related['criteria']->id !== null) {
 229                  $result['criteriaUrl'] = $this->related['criteria']->id;
 230              }
 231              if (property_exists($this->related['criteria'], 'narrative') && $this->related['criteria']->narrative !== null) {
 232                  $result['criteriaNarrative'] = $this->related['criteria']->narrative;
 233              }
 234          }
 235  
 236          return $result;
 237      }
 238  }