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.

Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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   * Core grades external functions
  19   *
  20   * @package    core_grades
  21   * @copyright  2012 Andrew Davis
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   * @since Moodle 2.7
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die;
  27  
  28  require_once("$CFG->libdir/externallib.php");
  29  require_once("$CFG->libdir/gradelib.php");
  30  require_once("$CFG->dirroot/grade/querylib.php");
  31  
  32  /**
  33   * core grades functions
  34   */
  35  class core_grades_external extends external_api {
  36      /**
  37       * Returns description of method parameters
  38       *
  39       * @return external_function_parameters
  40       * @since Moodle 2.7
  41       * @deprecated Moodle 3.2 MDL-51373 - Please do not call this function any more.
  42       * @see gradereport_user_external::get_grade_items for a similar function
  43       */
  44      public static function get_grades_parameters() {
  45          return new external_function_parameters(
  46              array(
  47                  'courseid' => new external_value(PARAM_INT, 'id of course'),
  48                  'component' => new external_value(
  49                      PARAM_COMPONENT, 'A component, for example mod_forum or mod_quiz', VALUE_DEFAULT, ''),
  50                  'activityid' => new external_value(PARAM_INT, 'The activity ID', VALUE_DEFAULT, null),
  51                  'userids' => new external_multiple_structure(
  52                      new external_value(PARAM_INT, 'user ID'),
  53                      'An array of user IDs, leave empty to just retrieve grade item information', VALUE_DEFAULT, array()
  54                  )
  55              )
  56          );
  57      }
  58  
  59      /**
  60       * Returns student course total grade and grades for activities.
  61       * This function does not return category or manual items.
  62       * This function is suitable for managers or teachers not students.
  63       *
  64       * @param  int $courseid        Course id
  65       * @param  string $component    Component name
  66       * @param  int $activityid      Activity id
  67       * @param  array  $userids      Array of user ids
  68       * @return array                Array of grades
  69       * @since Moodle 2.7
  70       * @deprecated Moodle 3.2 MDL-51373 - Please do not call this function any more.
  71       * @see gradereport_user_external::get_grade_items for a similar function
  72       */
  73      public static function get_grades($courseid, $component = null, $activityid = null, $userids = array()) {
  74          global $CFG, $USER, $DB;
  75  
  76          $params = self::validate_parameters(self::get_grades_parameters(),
  77              array('courseid' => $courseid, 'component' => $component, 'activityid' => $activityid, 'userids' => $userids));
  78  
  79          $gradesarray = array(
  80              'items'     => array(),
  81              'outcomes'  => array()
  82          );
  83  
  84          $coursecontext = context_course::instance($params['courseid']);
  85  
  86          try {
  87              self::validate_context($coursecontext);
  88          } catch (Exception $e) {
  89              $exceptionparam = new stdClass();
  90              $exceptionparam->message = $e->getMessage();
  91              $exceptionparam->courseid = $params['courseid'];
  92              throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
  93          }
  94  
  95          require_capability('moodle/grade:viewhidden', $coursecontext);
  96  
  97          $course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST);
  98  
  99          $access = false;
 100          if (has_capability('moodle/grade:viewall', $coursecontext)) {
 101              // Can view all user's grades in this course.
 102              $access = true;
 103  
 104          } else if ($course->showgrades && count($params['userids']) == 1) {
 105              // Course showgrades == students/parents can access grades.
 106  
 107              if ($params['userids'][0] == $USER->id and has_capability('moodle/grade:view', $coursecontext)) {
 108                  // Student can view their own grades in this course.
 109                  $access = true;
 110  
 111              } else if (has_capability('moodle/grade:viewall', context_user::instance($params['userids'][0]))) {
 112                  // User can view the grades of this user. Parent most probably.
 113                  $access = true;
 114              }
 115          }
 116  
 117          if (!$access) {
 118              throw new moodle_exception('nopermissiontoviewgrades', 'error');
 119          }
 120  
 121          $itemtype = null;
 122          $itemmodule = null;
 123          $iteminstance = null;
 124  
 125          if (!empty($params['component'])) {
 126              list($itemtype, $itemmodule) = normalize_component($params['component']);
 127          }
 128  
 129          $cm = null;
 130          if (!empty($itemmodule) && !empty($params['activityid'])) {
 131              if (!$cm = get_coursemodule_from_id($itemmodule, $params['activityid'])) {
 132                  throw new moodle_exception('invalidcoursemodule');
 133              }
 134              $iteminstance = $cm->instance;
 135          }
 136  
 137          // Load all the module info.
 138          $modinfo = get_fast_modinfo($params['courseid']);
 139          $activityinstances = $modinfo->get_instances();
 140  
 141          $gradeparams = array('courseid' => $params['courseid']);
 142          if (!empty($itemtype)) {
 143              $gradeparams['itemtype'] = $itemtype;
 144          }
 145          if (!empty($itemmodule)) {
 146              $gradeparams['itemmodule'] = $itemmodule;
 147          }
 148          if (!empty($iteminstance)) {
 149              $gradeparams['iteminstance'] = $iteminstance;
 150          }
 151  
 152          if ($activitygrades = grade_item::fetch_all($gradeparams)) {
 153              $canviewhidden = has_capability('moodle/grade:viewhidden', context_course::instance($params['courseid']));
 154  
 155              foreach ($activitygrades as $activitygrade) {
 156  
 157                  if ($activitygrade->itemtype != 'course' and $activitygrade->itemtype != 'mod') {
 158                      // This function currently only supports course and mod grade items. Manual and category not supported.
 159                      continue;
 160                  }
 161  
 162                  $context = $coursecontext;
 163  
 164                  if ($activitygrade->itemtype == 'course') {
 165                      $item = grade_get_course_grades($course->id, $params['userids']);
 166                      $item->itemnumber = 0;
 167  
 168                      $grades = new stdClass;
 169                      $grades->items = array($item);
 170                      $grades->outcomes = array();
 171  
 172                  } else {
 173                      $cm = $activityinstances[$activitygrade->itemmodule][$activitygrade->iteminstance];
 174                      $instance = $cm->instance;
 175                      $context = context_module::instance($cm->id, IGNORE_MISSING);
 176  
 177                      $grades = grade_get_grades($params['courseid'], $activitygrade->itemtype,
 178                                                  $activitygrade->itemmodule, $instance, $params['userids']);
 179                  }
 180  
 181                  // Convert from objects to arrays so all web service clients are supported.
 182                  // While we're doing that we also remove grades the current user can't see due to hiding.
 183                  foreach ($grades->items as $gradeitem) {
 184                      // Switch the stdClass instance for a grade item instance so we can call is_hidden() and use the ID.
 185                      $gradeiteminstance = self::get_grade_item(
 186                          $course->id, $activitygrade->itemtype, $activitygrade->itemmodule, $activitygrade->iteminstance, 0);
 187                      if (!$canviewhidden && $gradeiteminstance->is_hidden()) {
 188                          continue;
 189                      }
 190  
 191                      // Format mixed bool/integer parameters.
 192                      $gradeitem->hidden = (empty($gradeitem->hidden)) ? 0 : $gradeitem->hidden;
 193                      $gradeitem->locked = (empty($gradeitem->locked)) ? 0 : $gradeitem->locked;
 194  
 195                      $gradeitemarray = (array)$gradeitem;
 196                      $gradeitemarray['grades'] = array();
 197  
 198                      if (!empty($gradeitem->grades)) {
 199                          foreach ($gradeitem->grades as $studentid => $studentgrade) {
 200                              if (!$canviewhidden) {
 201                                  // Need to load the grade_grade object to check visibility.
 202                                  $gradegradeinstance = grade_grade::fetch(
 203                                      array(
 204                                          'userid' => $studentid,
 205                                          'itemid' => $gradeiteminstance->id
 206                                      )
 207                                  );
 208                                  // The grade grade may be legitimately missing if the student has no grade.
 209                                  if (!empty($gradegradeinstance) && $gradegradeinstance->is_hidden()) {
 210                                      continue;
 211                                  }
 212                              }
 213  
 214                              // Format mixed bool/integer parameters.
 215                              $studentgrade->hidden = (empty($studentgrade->hidden)) ? 0 : $studentgrade->hidden;
 216                              $studentgrade->locked = (empty($studentgrade->locked)) ? 0 : $studentgrade->locked;
 217                              $studentgrade->overridden = (empty($studentgrade->overridden)) ? 0 : $studentgrade->overridden;
 218  
 219                              if ($gradeiteminstance->itemtype != 'course' and !empty($studentgrade->feedback)) {
 220                                  list($studentgrade->feedback, $studentgrade->feedbackformat) =
 221                                      external_format_text($studentgrade->feedback, $studentgrade->feedbackformat,
 222                                      $context->id, $params['component'], 'feedback', null);
 223                              }
 224  
 225                              $gradeitemarray['grades'][$studentid] = (array)$studentgrade;
 226                              // Add the student ID as some WS clients can't access the array key.
 227                              $gradeitemarray['grades'][$studentid]['userid'] = $studentid;
 228                          }
 229                      }
 230  
 231                      if ($gradeiteminstance->itemtype == 'course') {
 232                          $gradesarray['items']['course'] = $gradeitemarray;
 233                          $gradesarray['items']['course']['activityid'] = 'course';
 234                      } else {
 235                          $gradesarray['items'][$cm->id] = $gradeitemarray;
 236                          // Add the activity ID as some WS clients can't access the array key.
 237                          $gradesarray['items'][$cm->id]['activityid'] = $cm->id;
 238                      }
 239                  }
 240  
 241                  foreach ($grades->outcomes as $outcome) {
 242                      // Format mixed bool/integer parameters.
 243                      $outcome->hidden = (empty($outcome->hidden)) ? 0 : $outcome->hidden;
 244                      $outcome->locked = (empty($outcome->locked)) ? 0 : $outcome->locked;
 245  
 246                      $gradesarray['outcomes'][$cm->id] = (array)$outcome;
 247                      $gradesarray['outcomes'][$cm->id]['activityid'] = $cm->id;
 248  
 249                      $gradesarray['outcomes'][$cm->id]['grades'] = array();
 250                      if (!empty($outcome->grades)) {
 251                          foreach ($outcome->grades as $studentid => $studentgrade) {
 252                              if (!$canviewhidden) {
 253                                  // Need to load the grade_grade object to check visibility.
 254                                  $gradeiteminstance = self::get_grade_item($course->id, $activitygrade->itemtype,
 255                                                                             $activitygrade->itemmodule, $activitygrade->iteminstance,
 256                                                                             $activitygrade->itemnumber);
 257                                  $gradegradeinstance = grade_grade::fetch(
 258                                      array(
 259                                          'userid' => $studentid,
 260                                          'itemid' => $gradeiteminstance->id
 261                                      )
 262                                  );
 263                                  // The grade grade may be legitimately missing if the student has no grade.
 264                                  if (!empty($gradegradeinstance ) && $gradegradeinstance->is_hidden()) {
 265                                      continue;
 266                                  }
 267                              }
 268  
 269                              // Format mixed bool/integer parameters.
 270                              $studentgrade->hidden = (empty($studentgrade->hidden)) ? 0 : $studentgrade->hidden;
 271                              $studentgrade->locked = (empty($studentgrade->locked)) ? 0 : $studentgrade->locked;
 272  
 273                              if (!empty($studentgrade->feedback)) {
 274                                  list($studentgrade->feedback, $studentgrade->feedbackformat) =
 275                                      external_format_text($studentgrade->feedback, $studentgrade->feedbackformat,
 276                                      $context->id, $params['component'], 'feedback', null);
 277                              }
 278  
 279                              $gradesarray['outcomes'][$cm->id]['grades'][$studentid] = (array)$studentgrade;
 280  
 281                              // Add the student ID into the grade structure as some WS clients can't access the key.
 282                              $gradesarray['outcomes'][$cm->id]['grades'][$studentid]['userid'] = $studentid;
 283                          }
 284                      }
 285                  }
 286              }
 287          }
 288  
 289          return $gradesarray;
 290      }
 291  
 292      /**
 293       * Get a grade item
 294       * @param  int $courseid        Course id
 295       * @param  string $itemtype     Item type
 296       * @param  string $itemmodule   Item module
 297       * @param  int $iteminstance    Item instance
 298       * @param  int $itemnumber      Item number
 299       * @return grade_item           A grade_item instance
 300       * @deprecated Moodle 3.2 MDL-51373 - Please do not call this function any more.
 301       * @see gradereport_user_external::get_grade_items for a similar function
 302       */
 303      private static function get_grade_item($courseid, $itemtype, $itemmodule = null, $iteminstance = null, $itemnumber = null) {
 304          $gradeiteminstance = null;
 305          if ($itemtype == 'course') {
 306              $gradeiteminstance = grade_item::fetch(array('courseid' => $courseid, 'itemtype' => $itemtype));
 307          } else {
 308              $gradeiteminstance = grade_item::fetch(
 309                  array('courseid' => $courseid, 'itemtype' => $itemtype,
 310                      'itemmodule' => $itemmodule, 'iteminstance' => $iteminstance, 'itemnumber' => $itemnumber));
 311          }
 312          return $gradeiteminstance;
 313      }
 314  
 315      /**
 316       * Returns description of method result value
 317       *
 318       * @return external_description
 319       * @since Moodle 2.7
 320       * @deprecated Moodle 3.2 MDL-51373 - Please do not call this function any more.
 321       * @see gradereport_user_external::get_grade_items for a similar function
 322       */
 323      public static function get_grades_returns() {
 324          return new external_single_structure(
 325              array(
 326                  'items'  => new external_multiple_structure(
 327                      new external_single_structure(
 328                          array(
 329                              'activityid' => new external_value(
 330                                  PARAM_ALPHANUM, 'The ID of the activity or "course" for the course grade item'),
 331                              'itemnumber'  => new external_value(PARAM_INT, 'Will be 0 unless the module has multiple grades'),
 332                              'scaleid' => new external_value(PARAM_INT, 'The ID of the custom scale or 0'),
 333                              'name' => new external_value(PARAM_RAW, 'The module name'),
 334                              'grademin' => new external_value(PARAM_FLOAT, 'Minimum grade'),
 335                              'grademax' => new external_value(PARAM_FLOAT, 'Maximum grade'),
 336                              'gradepass' => new external_value(PARAM_FLOAT, 'The passing grade threshold'),
 337                              'locked' => new external_value(PARAM_INT, '0 means not locked, > 1 is a date to lock until'),
 338                              'hidden' => new external_value(PARAM_INT, '0 means not hidden, > 1 is a date to hide until'),
 339                              'grades' => new external_multiple_structure(
 340                                  new external_single_structure(
 341                                      array(
 342                                          'userid' => new external_value(
 343                                              PARAM_INT, 'Student ID'),
 344                                          'grade' => new external_value(
 345                                              PARAM_FLOAT, 'Student grade'),
 346                                          'locked' => new external_value(
 347                                              PARAM_INT, '0 means not locked, > 1 is a date to lock until'),
 348                                          'hidden' => new external_value(
 349                                              PARAM_INT, '0 means not hidden, 1 hidden, > 1 is a date to hide until'),
 350                                          'overridden' => new external_value(
 351                                              PARAM_INT, '0 means not overridden, > 1 means overridden'),
 352                                          'feedback' => new external_value(
 353                                              PARAM_RAW, 'Feedback from the grader'),
 354                                          'feedbackformat' => new external_value(
 355                                              PARAM_INT, 'The format of the feedback'),
 356                                          'usermodified' => new external_value(
 357                                              PARAM_INT, 'The ID of the last user to modify this student grade'),
 358                                          'datesubmitted' => new external_value(
 359                                              PARAM_INT, 'A timestamp indicating when the student submitted the activity'),
 360                                          'dategraded' => new external_value(
 361                                              PARAM_INT, 'A timestamp indicating when the assignment was grades'),
 362                                          'str_grade' => new external_value(
 363                                              PARAM_RAW, 'A string representation of the grade'),
 364                                          'str_long_grade' => new external_value(
 365                                              PARAM_RAW, 'A nicely formatted string representation of the grade'),
 366                                          'str_feedback' => new external_value(
 367                                              PARAM_RAW, 'A formatted string representation of the feedback from the grader'),
 368                                      )
 369                                  )
 370                              ),
 371                          )
 372                      )
 373                  ),
 374                  'outcomes'  => new external_multiple_structure(
 375                      new external_single_structure(
 376                          array(
 377                              'activityid' => new external_value(
 378                                  PARAM_ALPHANUM, 'The ID of the activity or "course" for the course grade item'),
 379                              'itemnumber'  => new external_value(PARAM_INT, 'Will be 0 unless the module has multiple grades'),
 380                              'scaleid' => new external_value(PARAM_INT, 'The ID of the custom scale or 0'),
 381                              'name' => new external_value(PARAM_RAW, 'The module name'),
 382                              'locked' => new external_value(PARAM_INT, '0 means not locked, > 1 is a date to lock until'),
 383                              'hidden' => new external_value(PARAM_INT, '0 means not hidden, > 1 is a date to hide until'),
 384                              'grades' => new external_multiple_structure(
 385                                  new external_single_structure(
 386                                      array(
 387                                          'userid' => new external_value(
 388                                              PARAM_INT, 'Student ID'),
 389                                          'grade' => new external_value(
 390                                              PARAM_FLOAT, 'Student grade'),
 391                                          'locked' => new external_value(
 392                                              PARAM_INT, '0 means not locked, > 1 is a date to lock until'),
 393                                          'hidden' => new external_value(
 394                                              PARAM_INT, '0 means not hidden, 1 hidden, > 1 is a date to hide until'),
 395                                          'feedback' => new external_value(
 396                                              PARAM_RAW, 'Feedback from the grader'),
 397                                          'feedbackformat' => new external_value(
 398                                              PARAM_INT, 'The feedback format'),
 399                                          'usermodified' => new external_value(
 400                                              PARAM_INT, 'The ID of the last user to modify this student grade'),
 401                                          'str_grade' => new external_value(
 402                                              PARAM_RAW, 'A string representation of the grade'),
 403                                          'str_feedback' => new external_value(
 404                                              PARAM_RAW, 'A formatted string representation of the feedback from the grader'),
 405                                      )
 406                                  )
 407                              ),
 408                          )
 409                      ), 'An array of outcomes associated with the grade items', VALUE_OPTIONAL
 410                  )
 411              )
 412          );
 413  
 414      }
 415  
 416      /**
 417       * Marking the method as deprecated.
 418       *
 419       * @return bool
 420       */
 421      public static function get_grades_is_deprecated() {
 422          return true;
 423      }
 424  
 425      /**
 426       * Returns description of method parameters
 427       *
 428       * @return external_function_parameters
 429       * @since Moodle 2.7
 430       */
 431      public static function update_grades_parameters() {
 432          return new external_function_parameters(
 433              array(
 434                  'source' => new external_value(PARAM_TEXT, 'The source of the grade update'),
 435                  'courseid' => new external_value(PARAM_INT, 'id of course'),
 436                  'component' => new external_value(PARAM_COMPONENT, 'A component, for example mod_forum or mod_quiz'),
 437                  'activityid' => new external_value(PARAM_INT, 'The activity ID'),
 438                  'itemnumber' => new external_value(
 439                      PARAM_INT, 'grade item ID number for modules that have multiple grades. Typically this is 0.'),
 440                  'grades' => new external_multiple_structure(
 441                      new external_single_structure(
 442                          array(
 443                              'studentid' => new external_value(PARAM_INT, 'Student ID'),
 444                              'grade' => new external_value(PARAM_FLOAT, 'Student grade'),
 445                              'str_feedback' => new external_value(
 446                                  PARAM_TEXT, 'A string representation of the feedback from the grader', VALUE_OPTIONAL),
 447                          )
 448                  ), 'Any student grades to alter', VALUE_DEFAULT, array()),
 449                  'itemdetails' => new external_single_structure(
 450                      array(
 451                          'itemname' => new external_value(
 452                              PARAM_ALPHANUMEXT, 'The grade item name', VALUE_OPTIONAL),
 453                          'idnumber' => new external_value(
 454                              PARAM_INT, 'Arbitrary ID provided by the module responsible for the grade item', VALUE_OPTIONAL),
 455                          'gradetype' => new external_value(
 456                              PARAM_INT, 'The type of grade (0 = none, 1 = value, 2 = scale, 3 = text)', VALUE_OPTIONAL),
 457                          'grademax' => new external_value(
 458                              PARAM_FLOAT, 'Maximum grade allowed', VALUE_OPTIONAL),
 459                          'grademin' => new external_value(
 460                              PARAM_FLOAT, 'Minimum grade allowed', VALUE_OPTIONAL),
 461                          'scaleid' => new external_value(
 462                              PARAM_INT, 'The ID of the custom scale being is used', VALUE_OPTIONAL),
 463                          'multfactor' => new external_value(
 464                              PARAM_FLOAT, 'Multiply all grades by this number', VALUE_OPTIONAL),
 465                          'plusfactor' => new external_value(
 466                              PARAM_FLOAT, 'Add this to all grades', VALUE_OPTIONAL),
 467                          'deleted' => new external_value(
 468                              PARAM_BOOL, 'True if the grade item should be deleted', VALUE_OPTIONAL),
 469                          'hidden' => new external_value(
 470                              PARAM_BOOL, 'True if the grade item is hidden', VALUE_OPTIONAL),
 471                      ), 'Any grade item settings to alter', VALUE_DEFAULT, array()
 472                  )
 473              )
 474          );
 475      }
 476  
 477      /**
 478       * Update a grade item and, optionally, student grades
 479       *
 480       * @param  string $source       The source of the grade update
 481       * @param  int $courseid        The course id
 482       * @param  string $component    Component name
 483       * @param  int $activityid      The activity id
 484       * @param  int $itemnumber      The item number
 485       * @param  array  $grades      Array of grades
 486       * @param  array  $itemdetails Array of item details
 487       * @return int                  A status flag
 488       * @since Moodle 2.7
 489       */
 490      public static function update_grades($source, $courseid, $component, $activityid,
 491          $itemnumber, $grades = array(), $itemdetails = array()) {
 492          global $CFG;
 493  
 494          $params = self::validate_parameters(
 495              self::update_grades_parameters(),
 496              array(
 497                  'source' => $source,
 498                  'courseid' => $courseid,
 499                  'component' => $component,
 500                  'activityid' => $activityid,
 501                  'itemnumber' => $itemnumber,
 502                  'grades' => $grades,
 503                  'itemdetails' => $itemdetails
 504              )
 505          );
 506  
 507          list($itemtype, $itemmodule) = normalize_component($params['component']);
 508  
 509          if (! $cm = get_coursemodule_from_id($itemmodule, $activityid)) {
 510              throw new moodle_exception('invalidcoursemodule');
 511          }
 512          $iteminstance = $cm->instance;
 513  
 514          $coursecontext = context_course::instance($params['courseid']);
 515  
 516          try {
 517              self::validate_context($coursecontext);
 518          } catch (Exception $e) {
 519              $exceptionparam = new stdClass();
 520              $exceptionparam->message = $e->getMessage();
 521              $exceptionparam->courseid = $params['courseid'];
 522              throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
 523          }
 524  
 525          $hidinggrades = false;
 526          $editinggradeitem = false;
 527          $editinggrades = false;
 528  
 529          $gradestructure = array();
 530          foreach ($grades as $grade) {
 531              $editinggrades = true;
 532              $gradestructure[ $grade['studentid'] ] = array('userid' => $grade['studentid'], 'rawgrade' => $grade['grade']);
 533          }
 534          if (!empty($params['itemdetails'])) {
 535              if (isset($params['itemdetails']['hidden'])) {
 536                  $hidinggrades = true;
 537              } else {
 538                  $editinggradeitem = true;
 539              }
 540          }
 541  
 542          if ($editinggradeitem && !has_capability('moodle/grade:manage', $coursecontext)) {
 543              throw new moodle_exception('nopermissiontoviewgrades', 'error', '', null,
 544                  'moodle/grade:manage required to edit grade information');
 545          }
 546          if ($hidinggrades && !has_capability('moodle/grade:hide', $coursecontext) &&
 547              !has_capability('moodle/grade:hide', $coursecontext)) {
 548              throw new moodle_exception('nopermissiontoviewgrades', 'error', '', null,
 549                  'moodle/grade:hide required to hide grade items');
 550          }
 551          if ($editinggrades && !has_capability('moodle/grade:edit', $coursecontext)) {
 552              throw new moodle_exception('nopermissiontoviewgrades', 'error', '', null,
 553                  'moodle/grade:edit required to edit grades');
 554          }
 555  
 556          return grade_update($params['source'], $params['courseid'], $itemtype,
 557              $itemmodule, $iteminstance, $itemnumber, $gradestructure, $params['itemdetails']);
 558      }
 559  
 560      /**
 561       * Returns description of method result value
 562       *
 563       * @return external_description
 564       * @since Moodle 2.7
 565       */
 566      public static function update_grades_returns() {
 567          return new external_value(
 568              PARAM_INT,
 569              'A value like ' . GRADE_UPDATE_OK . ' => OK, ' . GRADE_UPDATE_FAILED . ' => FAILED
 570              as defined in lib/grade/constants.php'
 571          );
 572      }
 573  }