Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are 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   * H5P activity grader class.
  19   *
  20   * @package    mod_h5pactivity
  21   * @since      Moodle 3.9
  22   * @copyright  2020 Ferran Recio <ferran@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace mod_h5pactivity\local;
  27  
  28  use context_module;
  29  use cm_info;
  30  use moodle_recordset;
  31  use stdClass;
  32  
  33  /**
  34   * Class for handling H5P activity grading.
  35   *
  36   * @package    mod_h5pactivity
  37   * @since      Moodle 3.9
  38   * @copyright  2020 Ferran Recio <ferran@moodle.com>
  39   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  class grader {
  42  
  43      /** @var stdClass course_module record. */
  44      private $instance;
  45  
  46      /** @var string idnumber course_modules idnumber. */
  47      private $idnumber;
  48  
  49      /**
  50       * Class contructor.
  51       *
  52       * @param stdClass $instance H5Pactivity instance object
  53       * @param string $idnumber course_modules idnumber
  54       */
  55      public function __construct(stdClass $instance, string $idnumber = '') {
  56          $this->instance = $instance;
  57          $this->idnumber = $idnumber;
  58      }
  59  
  60      /**
  61       * Delete grade item for given mod_h5pactivity instance.
  62       *
  63       * @return int Returns GRADE_UPDATE_OK, GRADE_UPDATE_FAILED, GRADE_UPDATE_MULTIPLE or GRADE_UPDATE_ITEM_LOCKED
  64       */
  65      public function grade_item_delete(): ?int {
  66          global $CFG;
  67          require_once($CFG->libdir.'/gradelib.php');
  68  
  69          return grade_update('mod/h5pactivity', $this->instance->course, 'mod', 'h5pactivity',
  70                  $this->instance->id, 0, null, ['deleted' => 1]);
  71      }
  72  
  73      /**
  74       * Creates or updates grade item for the given mod_h5pactivity instance.
  75       *
  76       * @param mixed $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
  77       * @return int 0 if ok, error code otherwise
  78       */
  79      public function grade_item_update($grades = null): int {
  80          global $CFG;
  81          require_once($CFG->libdir.'/gradelib.php');
  82  
  83          $item = [];
  84          $item['itemname'] = clean_param($this->instance->name, PARAM_NOTAGS);
  85          $item['gradetype'] = GRADE_TYPE_VALUE;
  86          if (!empty($this->idnumber)) {
  87              $item['idnumber'] = $this->idnumber;
  88          }
  89  
  90          if ($this->instance->grade > 0) {
  91              $item['gradetype'] = GRADE_TYPE_VALUE;
  92              $item['grademax']  = $this->instance->grade;
  93              $item['grademin']  = 0;
  94          } else if ($this->instance->grade < 0) {
  95              $item['gradetype'] = GRADE_TYPE_SCALE;
  96              $item['scaleid']   = -$this->instance->grade;
  97          } else {
  98              $item['gradetype'] = GRADE_TYPE_NONE;
  99          }
 100  
 101          if ($grades === 'reset') {
 102              $item['reset'] = true;
 103              $grades = null;
 104          }
 105  
 106          return grade_update('mod/h5pactivity', $this->instance->course, 'mod',
 107                  'h5pactivity', $this->instance->id, 0, $grades, $item);
 108      }
 109  
 110      /**
 111       * Update grades in the gradebook.
 112       *
 113       * @param int $userid Update grade of specific user only, 0 means all participants.
 114       */
 115      public function update_grades(int $userid = 0): void {
 116          // Scaled and none grading doesn't have grade calculation.
 117          if ($this->instance->grade <= 0) {
 118              $this->grade_item_update();
 119              return;
 120          }
 121          // Populate array of grade objects indexed by userid.
 122          $grades = $this->get_user_grades_for_gradebook($userid);
 123  
 124          if (!empty($grades)) {
 125              $this->grade_item_update($grades);
 126          } else {
 127              $this->grade_item_update();
 128          }
 129      }
 130  
 131      /**
 132       * Get an updated list of user grades and feedback for the gradebook.
 133       *
 134       * @param int $userid int or 0 for all users
 135       * @return array of grade data formated for the gradebook api
 136       *         The data required by the gradebook api is userid,
 137       *                                                   rawgrade,
 138       *                                                   feedback,
 139       *                                                   feedbackformat,
 140       *                                                   usermodified,
 141       *                                                   dategraded,
 142       *                                                   datesubmitted
 143       */
 144      private function get_user_grades_for_gradebook(int $userid = 0): array {
 145          $grades = [];
 146  
 147          // In case of using manual grading this update must delete previous automatic gradings.
 148          if ($this->instance->grademethod == manager::GRADEMANUAL || !$this->instance->enabletracking) {
 149              return $this->get_user_grades_for_deletion($userid);
 150          }
 151  
 152          $manager = manager::create_from_instance($this->instance);
 153  
 154          $scores = $manager->get_users_scaled_score($userid);
 155          if (!$scores) {
 156              return $grades;
 157          }
 158  
 159          // Maxgrade depends on the type of grade used:
 160          // - grade > 0: regular quantitative grading.
 161          // - grade = 0: no grading.
 162          // - grade < 0: scale used.
 163          $maxgrade = floatval($this->instance->grade);
 164  
 165          // Convert scaled scores into gradebok compatible objects.
 166          foreach ($scores as $userid => $score) {
 167              $grades[$userid] = [
 168                  'userid' => $userid,
 169                  'rawgrade' => $maxgrade * $score->scaled,
 170                  'dategraded' => $score->timemodified,
 171                  'datesubmitted' => $score->timemodified,
 172              ];
 173          }
 174  
 175          return $grades;
 176      }
 177  
 178      /**
 179       * Get an deletion list of user grades and feedback for the gradebook.
 180       *
 181       * This method is used to delete all autmatic gradings when grading method is set to manual.
 182       *
 183       * @param int $userid int or 0 for all users
 184       * @return array of grade data formated for the gradebook api
 185       *         The data required by the gradebook api is userid,
 186       *                                                   rawgrade (null to delete),
 187       *                                                   dategraded,
 188       *                                                   datesubmitted
 189       */
 190      private function get_user_grades_for_deletion (int $userid = 0): array {
 191          $grades = [];
 192  
 193          if ($userid) {
 194              $grades[$userid] = [
 195                  'userid' => $userid,
 196                  'rawgrade' => null,
 197                  'dategraded' => time(),
 198                  'datesubmitted' => time(),
 199              ];
 200          } else {
 201              $manager = manager::create_from_instance($this->instance);
 202              $users = get_enrolled_users($manager->get_context(), 'mod/h5pactivity:submit');
 203              foreach ($users as $user) {
 204                  $grades[$user->id] = [
 205                      'userid' => $user->id,
 206                      'rawgrade' => null,
 207                      'dategraded' => time(),
 208                      'datesubmitted' => time(),
 209                  ];
 210              }
 211          }
 212          return $grades;
 213      }
 214  }