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.
/grade/ -> querylib.php (source)
   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   * Functions used to retrieve grades objects
  19   *
  20   * @package   core_grades
  21   * @category  grade
  22   * @copyright 2008 Petr Skoda and Nicolas Connault
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  /**
  27   * Returns the aggregated or calculated course grade(s) for a single course for one or more users
  28   *
  29   * @param int $courseid The ID of course
  30   * @param int|array $userid_or_ids Optional ID of the graded user or array of user IDs; if userid not used, returns only information about grade_item
  31   * @return stdClass Returns an object containing information about course grade item. scaleid, name, grade
  32   *         and locked status etc and user course grades: $item->grades[$userid] => $usercoursegrade
  33   */
  34  function grade_get_course_grades($courseid, $userid_or_ids=null) {
  35  
  36      $grade_item = grade_item::fetch_course_item($courseid);
  37  
  38      if ($grade_item->needsupdate) {
  39          grade_regrade_final_grades($courseid);
  40      }
  41  
  42      $item = new stdClass();
  43      $item->scaleid    = $grade_item->scaleid;
  44      $item->name       = $grade_item->get_name();
  45      $item->grademin   = $grade_item->grademin;
  46      $item->grademax   = $grade_item->grademax;
  47      $item->gradepass  = $grade_item->gradepass;
  48      $item->locked     = $grade_item->is_locked();
  49      $item->hidden     = $grade_item->is_hidden();
  50      $item->grades     = array();
  51  
  52      switch ($grade_item->gradetype) {
  53          case GRADE_TYPE_NONE:
  54              break;
  55  
  56          case GRADE_TYPE_VALUE:
  57              $item->scaleid = 0;
  58              break;
  59  
  60          case GRADE_TYPE_TEXT:
  61              $item->scaleid   = 0;
  62              $item->grademin   = 0;
  63              $item->grademax   = 0;
  64              $item->gradepass  = 0;
  65              break;
  66      }
  67  
  68      if (empty($userid_or_ids)) {
  69          $userids = array();
  70  
  71      } else if (is_array($userid_or_ids)) {
  72          $userids = $userid_or_ids;
  73  
  74      } else {
  75          $userids = array($userid_or_ids);
  76      }
  77  
  78      if ($userids) {
  79          $grade_grades = grade_grade::fetch_users_grades($grade_item, $userids, true);
  80          foreach ($userids as $userid) {
  81              $grade_grades[$userid]->grade_item =& $grade_item;
  82  
  83              $grade = new stdClass();
  84              $grade->grade          = $grade_grades[$userid]->finalgrade;
  85              $grade->locked         = $grade_grades[$userid]->is_locked();
  86              $grade->hidden         = $grade_grades[$userid]->is_hidden();
  87              $grade->overridden     = $grade_grades[$userid]->overridden;
  88              $grade->feedback       = $grade_grades[$userid]->feedback;
  89              $grade->feedbackformat = $grade_grades[$userid]->feedbackformat;
  90              $grade->usermodified   = $grade_grades[$userid]->usermodified;
  91              $grade->dategraded     = $grade_grades[$userid]->get_dategraded();
  92              $grade->datesubmitted  = $grade_grades[$userid]->get_datesubmitted();
  93  
  94              // create text representation of grade
  95              if ($grade_item->needsupdate) {
  96                  $grade->grade          = false;
  97                  $grade->str_grade      = get_string('error');
  98                  $grade->str_long_grade = $grade->str_grade;
  99  
 100              } else if (is_null($grade->grade)) {
 101                  $grade->str_grade      = '-';
 102                  $grade->str_long_grade = $grade->str_grade;
 103  
 104              } else {
 105                  $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
 106                  if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
 107                      $grade->str_long_grade = $grade->str_grade;
 108                  } else {
 109                      $a = new stdClass();
 110                      $a->grade = $grade->str_grade;
 111                      $a->max   = grade_format_gradevalue($grade_item->grademax, $grade_item);
 112                      $grade->str_long_grade = get_string('gradelong', 'grades', $a);
 113                  }
 114              }
 115  
 116              // create html representation of feedback
 117              if (is_null($grade->feedback)) {
 118                  $grade->str_feedback = '';
 119              } else {
 120                  $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
 121              }
 122  
 123              $item->grades[$userid] = $grade;
 124          }
 125      }
 126  
 127      return $item;
 128  }
 129  
 130  /**
 131   * Returns the aggregated or calculated course grade for a single user for one or more courses
 132   *
 133   * @param int $userid The ID of the single user
 134   * @param int|array $courseid_or_ids Optional ID of course or array of IDs, empty means all of the user's courses
 135   * @return mixed grade info or grades array including item info, false if error
 136   */
 137  function grade_get_course_grade($userid, $courseid_or_ids=null) {
 138  
 139      if (!is_array($courseid_or_ids)) {
 140          if (empty($courseid_or_ids)) {
 141              if (!$courses = enrol_get_users_courses($userid)) {
 142                  return false;
 143              }
 144              $courseids = array_keys($courses);
 145              return grade_get_course_grade($userid, $courseids);
 146          }
 147          if (!is_numeric($courseid_or_ids)) {
 148              return false;
 149          }
 150          if (!$grades = grade_get_course_grade($userid, array($courseid_or_ids))) {
 151              return false;
 152          } else {
 153              // only one grade - not array
 154              $grade = reset($grades);
 155              return $grade;
 156          }
 157      }
 158  
 159      foreach ($courseid_or_ids as $courseid) {
 160          $grade_item = grade_item::fetch_course_item($courseid);
 161          $course_items[$grade_item->courseid] = $grade_item;
 162      }
 163  
 164      $grades = array();
 165      foreach ($course_items as $grade_item) {
 166          if ($grade_item->needsupdate) {
 167              grade_regrade_final_grades($courseid);
 168          }
 169  
 170          $item = new stdClass();
 171          $item->scaleid    = $grade_item->scaleid;
 172          $item->name       = $grade_item->get_name();
 173          $item->grademin   = $grade_item->grademin;
 174          $item->grademax   = $grade_item->grademax;
 175          $item->gradepass  = $grade_item->gradepass;
 176          $item->locked     = $grade_item->is_locked();
 177          $item->hidden     = $grade_item->is_hidden();
 178  
 179          switch ($grade_item->gradetype) {
 180              case GRADE_TYPE_NONE:
 181                  break;
 182  
 183              case GRADE_TYPE_VALUE:
 184                  $item->scaleid = 0;
 185                  break;
 186  
 187              case GRADE_TYPE_TEXT:
 188                  $item->scaleid   = 0;
 189                  $item->grademin   = 0;
 190                  $item->grademax   = 0;
 191                  $item->gradepass  = 0;
 192                  break;
 193          }
 194          $grade_grade = new grade_grade(array('userid'=>$userid, 'itemid'=>$grade_item->id));
 195          $grade_grade->grade_item =& $grade_item;
 196  
 197          $grade = new stdClass();
 198          $grade->grade          = $grade_grade->finalgrade;
 199          $grade->locked         = $grade_grade->is_locked();
 200          $grade->hidden         = $grade_grade->is_hidden();
 201          $grade->overridden     = $grade_grade->overridden;
 202          $grade->feedback       = $grade_grade->feedback;
 203          $grade->feedbackformat = $grade_grade->feedbackformat;
 204          $grade->usermodified   = $grade_grade->usermodified;
 205          $grade->dategraded     = $grade_grade->get_dategraded();
 206          $grade->item           = $item;
 207  
 208          // create text representation of grade
 209          if ($grade_item->needsupdate) {
 210              $grade->grade          = false;
 211              $grade->str_grade      = get_string('error');
 212              $grade->str_long_grade = $grade->str_grade;
 213  
 214          } else if (is_null($grade->grade)) {
 215              $grade->str_grade      = '-';
 216              $grade->str_long_grade = $grade->str_grade;
 217  
 218          } else {
 219              $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
 220              if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
 221                  $grade->str_long_grade = $grade->str_grade;
 222              } else {
 223                  $a = new stdClass();
 224                  $a->grade = $grade->str_grade;
 225                  $a->max   = grade_format_gradevalue($grade_item->grademax, $grade_item);
 226                  $grade->str_long_grade = get_string('gradelong', 'grades', $a);
 227              }
 228          }
 229  
 230          // create html representation of feedback
 231          if (is_null($grade->feedback)) {
 232              $grade->str_feedback = '';
 233          } else {
 234              $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
 235          }
 236  
 237          $grades[$grade_item->courseid] = $grade;
 238      }
 239  
 240      return $grades;
 241  }
 242  
 243  /**
 244   * Returns all grade items (including outcomes) or main item for a given activity identified by $cm object.
 245   *
 246   * @param cm_info $cm A course module object (preferably with modname property)
 247   * @param bool $only_main_item Limit the search to the primary grade item for the activity, 'itemnumber'==0
 248   * @return mixed An array of grade item instances, one grade item if $only_main_item == true, false if error or not found
 249   */
 250  function grade_get_grade_items_for_activity($cm, $only_main_item=false) {
 251      global $CFG, $DB;
 252  
 253      if (!isset($cm->modname)) {
 254          $params = array($cm->id);
 255          $cm = $DB->get_record_sql("SELECT cm.*, md.name as modname
 256                                      FROM {course_modules} cm,
 257                                           {modules} md
 258                                     WHERE cm.id = ? AND md.id = cm.module", $params);
 259      }
 260  
 261  
 262      if (empty($cm) or empty($cm->instance) or empty($cm->course)) {
 263          debugging("Incorrect cm parameter in grade_get_grade_items_for_activity()!");
 264          return false;
 265      }
 266  
 267      if ($only_main_item) {
 268          return grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0));
 269      } else {
 270          return grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course));
 271      }
 272  }
 273  
 274  /**
 275   * Returns whether or not a user received grades in main grade item for given activity
 276   *
 277   * @param cm_info $cm The activity context module
 278   * @param int $userid The user ID
 279   * @return bool True if graded, false if user not graded yet
 280   */
 281  function grade_is_user_graded_in_activity($cm, $userid) {
 282  
 283      $grade_items = grade_get_grade_items_for_activity($cm, true);
 284      if (empty($grade_items)) {
 285          return false;
 286      }
 287  
 288      $grade_item = reset($grade_items);
 289  
 290      if ($grade_item->gradetype == GRADE_TYPE_NONE) {
 291          return false;
 292      }
 293  
 294      if ($grade_item->needsupdate) {
 295          // activity items should never fail to regrade
 296          grade_regrade_final_grades($grade_item->courseid);
 297      }
 298  
 299      if (!$grade = $grade_item->get_final($userid)) {
 300          return false;
 301      }
 302  
 303      if (is_null($grade->finalgrade)) {
 304          return false;
 305      }
 306  
 307      return true;
 308  }
 309  
 310  /**
 311   * Returns an array of activities (defined as $cm objects) which are gradeable from gradebook, outcomes are ignored.
 312   *
 313   * @param int $courseid If provided then restrict to one course.
 314   * @param string $modulename If defined (could be 'forum', 'assignment' etc) then only that type are returned.
 315   * @return array $cm objects
 316   */
 317  function grade_get_gradable_activities($courseid, $modulename='') {
 318      global $CFG, $DB;
 319  
 320      if (empty($modulename)) {
 321          if (!$modules = $DB->get_records('modules', array('visible' => '1'))) {
 322              return false;
 323          }
 324          $result = array();
 325          foreach ($modules as $module) {
 326              if ($cms = grade_get_gradable_activities($courseid, $module->name)) {
 327                  $result =  $result + $cms;
 328              }
 329          }
 330          if (empty($result)) {
 331              return false;
 332          } else {
 333              return $result;
 334          }
 335      }
 336  
 337      $params = array($courseid, $modulename, GRADE_TYPE_NONE, $modulename);
 338      $sql = "SELECT cm.*, m.name, md.name as modname
 339                FROM {grade_items} gi, {course_modules} cm, {modules} md, {{$modulename}} m
 340               WHERE gi.courseid = ? AND
 341                     gi.itemtype = 'mod' AND
 342                     gi.itemmodule = ? AND
 343                     gi.itemnumber = 0 AND
 344                     gi.gradetype != ? AND
 345                     gi.iteminstance = cm.instance AND
 346                     cm.instance = m.id AND
 347                     md.name = ? AND
 348                     md.id = cm.module";
 349  
 350      return $DB->get_records_sql($sql, $params);
 351  }
 352