diff --git a/grade/querylib.php b/grade/querylib.php index b45dc2458e3..316a98ff64e 100644 --- a/grade/querylib.php +++ b/grade/querylib.php @@ -89,6 +89,7 @@ function grade_get_course_grades($courseid, $userid_or_ids=null) { $grade->feedbackformat = $grade_grades[$userid]->feedbackformat; $grade->usermodified = $grade_grades[$userid]->usermodified; $grade->dategraded = $grade_grades[$userid]->get_dategraded(); + $grade->datesubmitted = $grade_grades[$userid]->get_datesubmitted(); // create text representation of grade if ($grade_item->needsupdate) { diff --git a/lib/classes/grades_external.php b/lib/classes/grades_external.php index 5781accbe3c..930602efb57 100644 --- a/lib/classes/grades_external.php +++ b/lib/classes/grades_external.php @@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die; require_once("$CFG->libdir/externallib.php"); require_once("$CFG->libdir/gradelib.php"); +require_once("$CFG->dirroot/grade/querylib.php"); /** * core grades functions @@ -69,6 +70,11 @@ class core_grades_external extends external_api { $params = self::validate_parameters(self::get_grades_parameters(), array('courseid' => $courseid, 'component' => $component, 'activityid' => $activityid, 'userids' => $userids)); + $gradesarray = array( + 'items' => array(), + 'outcomes' => array() + ); + $coursecontext = context_course::instance($params['courseid']); try { @@ -106,155 +112,168 @@ class core_grades_external extends external_api { $itemtype = null; $itemmodule = null; + $iteminstance = null; + if (!empty($params['component'])) { list($itemtype, $itemmodule) = normalize_component($params['component']); } $cm = null; - if (!empty($itemmodule) && !empty($activityid)) { - if (! $cm = get_coursemodule_from_id($itemmodule, $activityid)) { + if (!empty($itemmodule) && !empty($params['activityid'])) { + if (!$cm = get_coursemodule_from_id($itemmodule, $params['activityid'])) { throw new moodle_exception('invalidcoursemodule'); } + $iteminstance = $cm->instance; } - $cminstanceid = null; - if (!empty($cm)) { - $cminstanceid = $cm->instance; - } - $grades = grade_get_grades($params['courseid'], $itemtype, $itemmodule, $cminstanceid, $params['userids']); - - $acitivityinstances = null; if (empty($cm)) { // If we're dealing with multiple activites load all the module info. $modinfo = get_fast_modinfo($params['courseid']); - $acitivityinstances = $modinfo->get_instances(); + $activityinstances = $modinfo->get_instances(); } - foreach ($grades->items as $gradeitem) { - if (!empty($cm)) { - // If they only requested one activity we will already have the cm. - $modulecm = $cm; - } else if (!empty($gradeitem->itemmodule)) { - $modulecm = $acitivityinstances[$gradeitem->itemmodule][$gradeitem->iteminstance]; - } else { - // Course grade item. - continue; - } + $gradeparams = array('courseid' => $params['courseid']); + if (!empty($itemtype)) { + $gradeparams['itemtype'] = $itemtype; + } + if (!empty($itemmodule)) { + $gradeparams['itemmodule'] = $itemmodule; + } + if (!empty($iteminstance)) { + $gradeparams['iteminstance'] = $iteminstance; + } - // Make student feedback ready for output. - foreach ($gradeitem->grades as $studentgrade) { - if (!empty($studentgrade->feedback)) { - list($studentgrade->feedback, $categoryinfo->feedbackformat) = - external_format_text($studentgrade->feedback, $studentgrade->feedbackformat, - $modulecm->id, $params['component'], 'feedback', null); + if ($activitygrades = grade_item::fetch_all($gradeparams)) { + $canviewhidden = has_capability('moodle/grade:viewhidden', context_course::instance($params['courseid'])); + + foreach ($activitygrades as $activitygrade) { + + if ($activitygrade->itemtype != 'course' and $activitygrade->itemtype != 'mod') { + // This function currently only supports course and mod grade items. Manual and category not supported. + continue; } - } - } - // Convert from objects to arrays so all web service clients are supported. - // While we're doing that we also remove grades the current user can't see due to hiding. - $gradesarray = array(); - $canviewhidden = has_capability('moodle/grade:viewhidden', context_course::instance($params['courseid'])); + if ($activitygrade->itemtype == 'course') { + $item = grade_get_course_grades($course->id, $params['userids']); + $item->itemnumber = 0; - $gradesarray['items'] = array(); - foreach ($grades->items as $gradeitem) { - // Switch the stdClass instance for a grade item instance so we can call is_hidden() and use the ID. - $gradeiteminstance = self::get_grade_item( - $course->id, $gradeitem->itemtype, $gradeitem->itemmodule, $gradeitem->iteminstance, 0); - if (!$canviewhidden && $gradeiteminstance->is_hidden()) { - continue; - } + $grades = new stdClass; + $grades->items = array($item); + $grades->outcomes = array(); - // Format mixed bool/integer parameters. - $gradeitem->hidden = (empty($gradeitem->hidden)) ? 0 : $gradeitem->hidden; - $gradeitem->locked = (empty($gradeitem->locked)) ? 0 : $gradeitem->locked; + } else { + if (!$cm) { + $cm = $activityinstances[$activitygrade->itemmodule][$activitygrade->iteminstance]; + } + $instance = $cm->instance; + $grades = grade_get_grades($params['courseid'], $activitygrade->itemtype, + $activitygrade->itemmodule, $instance, $params['userids']); + } - $gradeitemarray = (array)$gradeitem; - $gradeitemarray['grades'] = array(); - - if (!empty($gradeitem->grades)) { - foreach ($gradeitem->grades as $studentid => $studentgrade) { - if (!$canviewhidden) { - // Need to load the grade_grade object to check visibility. - $gradegradeinstance = grade_grade::fetch( - array( - 'userid' => $studentid, - 'itemid' => $gradeiteminstance->id - ) - ); - // The grade grade may be legitimately missing if the student has no grade. - if (!empty($gradegradeinstance) && $gradegradeinstance->is_hidden()) { - continue; - } + // Convert from objects to arrays so all web service clients are supported. + // While we're doing that we also remove grades the current user can't see due to hiding. + foreach ($grades->items as $gradeitem) { + // Switch the stdClass instance for a grade item instance so we can call is_hidden() and use the ID. + $gradeiteminstance = self::get_grade_item( + $course->id, $activitygrade->itemtype, $activitygrade->itemmodule, $activitygrade->iteminstance, 0); + if (!$canviewhidden && $gradeiteminstance->is_hidden()) { + continue; } // Format mixed bool/integer parameters. - $studentgrade->hidden = (empty($studentgrade->hidden)) ? 0 : $studentgrade->hidden; - $studentgrade->locked = (empty($studentgrade->locked)) ? 0 : $studentgrade->locked; - $studentgrade->overridden = (empty($studentgrade->overridden)) ? 0 : $studentgrade->overridden; + $gradeitem->hidden = (empty($gradeitem->hidden)) ? 0 : $gradeitem->hidden; + $gradeitem->locked = (empty($gradeitem->locked)) ? 0 : $gradeitem->locked; - $gradeitemarray['grades'][$studentid] = (array)$studentgrade; - // Add the student ID as some WS clients can't access the array key. - $gradeitemarray['grades'][$studentid]['userid'] = $studentid; - } - } + $gradeitemarray = (array)$gradeitem; + $gradeitemarray['grades'] = array(); - // If they requested grades for multiple activities load the cm object now. - $modulecm = $cm; - if (empty($modulecm) && !empty($gradeiteminstance->itemmodule)) { - $modulecm = $acitivityinstances[$gradeiteminstance->itemmodule][$gradeiteminstance->iteminstance]; - } - if ($gradeiteminstance->itemtype == 'course') { - $gradesarray['items']['course'] = $gradeitemarray; - $gradesarray['items']['course']['activityid'] = 'course'; - } else { - $gradesarray['items'][$modulecm->id] = $gradeitemarray; - // Add the activity ID as some WS clients can't access the array key. - $gradesarray['items'][$modulecm->id]['activityid'] = $modulecm->id; - } - } + if (!empty($gradeitem->grades)) { + foreach ($gradeitem->grades as $studentid => $studentgrade) { + if (!$canviewhidden) { + // Need to load the grade_grade object to check visibility. + $gradegradeinstance = grade_grade::fetch( + array( + 'userid' => $studentid, + 'itemid' => $gradeiteminstance->id + ) + ); + // The grade grade may be legitimately missing if the student has no grade. + if (!empty($gradegradeinstance) && $gradegradeinstance->is_hidden()) { + continue; + } + } - $gradesarray['outcomes'] = array(); - foreach ($grades->outcomes as $outcome) { - $modulecm = $cm; - if (empty($modulecm)) { - $modulecm = $acitivityinstances[$outcome->itemmodule][$outcome->iteminstance]; - } + // Format mixed bool/integer parameters. + $studentgrade->hidden = (empty($studentgrade->hidden)) ? 0 : $studentgrade->hidden; + $studentgrade->locked = (empty($studentgrade->locked)) ? 0 : $studentgrade->locked; + $studentgrade->overridden = (empty($studentgrade->overridden)) ? 0 : $studentgrade->overridden; - // Format mixed bool/integer parameters. - $outcome->hidden = (empty($outcome->hidden)) ? 0 : $outcome->hidden; - $outcome->locked = (empty($outcome->locked)) ? 0 : $outcome->locked; + if ($gradeiteminstance->itemtype != 'course' and !empty($studentgrade->feedback)) { + list($studentgrade->feedback, $studentgrade->feedbackformat) = + external_format_text($studentgrade->feedback, $studentgrade->feedbackformat, + $cm->id, $params['component'], 'feedback', null); + } - $gradesarray['outcomes'][$modulecm->id] = (array)$outcome; - $gradesarray['outcomes'][$modulecm->id]['activityid'] = $modulecm->id; - - $gradesarray['outcomes'][$modulecm->id]['grades'] = array(); - if (!empty($outcome->grades)) { - foreach ($outcome->grades as $studentid => $studentgrade) { - if (!$canviewhidden) { - // Need to load the grade_grade object to check visibility. - $gradeiteminstance = self::get_grade_item( - $course->id, $outcome->itemtype, $outcome->itemmodule, $outcome->iteminstance, $outcome->itemnumber); - $gradegradeinstance = grade_grade::fetch( - array( - 'userid' => $studentid, - 'itemid' => $gradeiteminstance->id - ) - ); - // The grade grade may be legitimately missing if the student has no grade. - if (!empty($gradegradeinstance ) && $gradegradeinstance->is_hidden()) { - continue; + $gradeitemarray['grades'][$studentid] = (array)$studentgrade; + // Add the student ID as some WS clients can't access the array key. + $gradeitemarray['grades'][$studentid]['userid'] = $studentid; } } + if ($gradeiteminstance->itemtype == 'course') { + $gradesarray['items']['course'] = $gradeitemarray; + $gradesarray['items']['course']['activityid'] = 'course'; + } else { + $gradesarray['items'][$cm->id] = $gradeitemarray; + // Add the activity ID as some WS clients can't access the array key. + $gradesarray['items'][$cm->id]['activityid'] = $cm->id; + } + } + + foreach ($grades->outcomes as $outcome) { // Format mixed bool/integer parameters. - $studentgrade->hidden = (empty($studentgrade->hidden)) ? 0 : $studentgrade->hidden; - $studentgrade->locked = (empty($studentgrade->locked)) ? 0 : $studentgrade->locked; + $outcome->hidden = (empty($outcome->hidden)) ? 0 : $outcome->hidden; + $outcome->locked = (empty($outcome->locked)) ? 0 : $outcome->locked; - $gradesarray['outcomes'][$modulecm->id]['grades'][$studentid] = (array)$studentgrade; + $gradesarray['outcomes'][$cm->id] = (array)$outcome; + $gradesarray['outcomes'][$cm->id]['activityid'] = $cm->id; - // Add the student ID into the grade structure as some WS clients can't access the key. - $gradesarray['outcomes'][$modulecm->id]['grades'][$studentid]['userid'] = $studentid; + $gradesarray['outcomes'][$cm->id]['grades'] = array(); + if (!empty($outcome->grades)) { + foreach ($outcome->grades as $studentid => $studentgrade) { + if (!$canviewhidden) { + // Need to load the grade_grade object to check visibility. + $gradeiteminstance = self::get_grade_item($course->id, $activitygrade->itemtype, + $activitygrade->itemmodule, $activitygrade->iteminstance, + $activitygrade->itemnumber); + $gradegradeinstance = grade_grade::fetch( + array( + 'userid' => $studentid, + 'itemid' => $gradeiteminstance->id + ) + ); + // The grade grade may be legitimately missing if the student has no grade. + if (!empty($gradegradeinstance ) && $gradegradeinstance->is_hidden()) { + continue; + } + } + + // Format mixed bool/integer parameters. + $studentgrade->hidden = (empty($studentgrade->hidden)) ? 0 : $studentgrade->hidden; + $studentgrade->locked = (empty($studentgrade->locked)) ? 0 : $studentgrade->locked; + + if (!empty($studentgrade->feedback)) { + list($studentgrade->feedback, $studentgrade->feedbackformat) = + external_format_text($studentgrade->feedback, $studentgrade->feedbackformat, + $cm->id, $params['component'], 'feedback', null); + } + + $gradesarray['outcomes'][$cm->id]['grades'][$studentid] = (array)$studentgrade; + + // Add the student ID into the grade structure as some WS clients can't access the key. + $gradesarray['outcomes'][$cm->id]['grades'][$studentid]['userid'] = $studentid; + } + } } } } diff --git a/lib/gradelib.php b/lib/gradelib.php index f7e4b5c0f70..cb9170a866a 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -326,7 +326,7 @@ function grade_update_outcomes($source, $courseid, $itemtype, $itemmodule, $item } /** - * Returns grading information for one or more activities, optionally with user grades + * Returns grading information for given activity, optionally with user grades * Manual, course or category items can not be queried. * * @category grade @@ -337,7 +337,7 @@ function grade_update_outcomes($source, $courseid, $itemtype, $itemmodule, $item * @param mixed $userid_or_ids Either a single user ID, an array of user IDs or null. If user ID or IDs are not supplied returns information about grade_item * @return array Array of grade information objects (scaleid, name, grade and locked status, etc.) indexed with itemnumbers */ -function grade_get_grades($courseid, $itemtype = null, $itemmodule = null, $iteminstance = null, $userid_or_ids=null) { +function grade_get_grades($courseid, $itemtype, $itemmodule, $iteminstance, $userid_or_ids=null) { global $CFG; $return = new stdClass(); @@ -353,17 +353,7 @@ function grade_get_grades($courseid, $itemtype = null, $itemmodule = null, $item } } - $params = array('courseid' => $courseid); - if (!empty($itemtype)) { - $params['itemtype'] = $itemtype; - } - if (!empty($itemmodule)) { - $params['itemmodule'] = $itemmodule; - } - if (!empty($iteminstance)) { - $params['iteminstance'] = $iteminstance; - } - if ($grade_items = grade_item::fetch_all($params)) { + if ($grade_items = grade_item::fetch_all(array('itemtype'=>$itemtype, 'itemmodule'=>$itemmodule, 'iteminstance'=>$iteminstance, 'courseid'=>$courseid))) { foreach ($grade_items as $grade_item) { $decimalpoints = null; diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 13124832a49..c1c222450c1 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -31,6 +31,7 @@ information provided here is intended especially for developers. * Added an extra parameter to the function get_formatted_help_string() (default null) which is used to specify additional string parameters. * User settings node and course node in navigation now support callbacks from admin tools. +* grade_get_grades() optional parameteres $itemtype, $itemmodule, $iteminstance are now required. DEPRECATIONS: * completion_info->get_incomplete_criteria() is deprecated and will be removed in Moodle 3.0.