Added service functions for grade/badge/completion progress

This commit is contained in:
PMKuipers 2023-06-16 13:49:47 +02:00
parent 780765ff79
commit 7b95d06c4f
6 changed files with 180 additions and 11 deletions

View file

@ -127,4 +127,15 @@ class badgeinfo {
return $badge; return $badge;
} }
function count_issued(array $student_ids){
$issuecount = 0;
foreach($student_ids as $uid){
if($this->badge->is_issued($userid)){
$issuecount++;
}
}
return $issuecount;
}
} }

View file

@ -39,8 +39,8 @@ class completionscanner
return self::$course_students[$courseid]; return self::$course_students[$courseid];
} }
public function __construct($course,\completion_criteria $crit){ public function __construct(\completion_criteria $crit){
$this->course = $course; $this->course = $crit->course;
$this->crit = $crit; $this->crit = $crit;
// Find a related scanner if the type is an activity type // Find a related scanner if the type is an activity type

View file

@ -53,6 +53,7 @@ class corecompletioninfo {
public static function completion_item_editor_structure($value=VALUE_REQUIRED){ public static function completion_item_editor_structure($value=VALUE_REQUIRED){
return new \external_single_structure([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT,'criteria id',VALUE_OPTIONAL),
"title" => new \external_value(PARAM_TEXT,'name of subitem',VALUE_OPTIONAL), "title" => new \external_value(PARAM_TEXT,'name of subitem',VALUE_OPTIONAL),
"link" => new \external_value(PARAM_TEXT, 'optional link to more details',VALUE_OPTIONAL), "link" => new \external_value(PARAM_TEXT, 'optional link to more details',VALUE_OPTIONAL),
"details" => new \external_single_structure([ "details" => new \external_single_structure([
@ -85,7 +86,7 @@ class corecompletioninfo {
public static function completion_item_user_structure($value=VALUE_REQUIRED){ public static function completion_item_user_structure($value=VALUE_REQUIRED){
return new \external_single_structure([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT,'id of subitem',VALUE_OPTIONAL), "id" => new \external_value(PARAM_INT,'id of completion',VALUE_OPTIONAL),
"title" => new \external_value(PARAM_TEXT,'name of subitem',VALUE_OPTIONAL), "title" => new \external_value(PARAM_TEXT,'name of subitem',VALUE_OPTIONAL),
"details" => new \external_single_structure([ "details" => new \external_single_structure([
"type" => new \external_value(PARAM_RAW, 'type',VALUE_OPTIONAL), "type" => new \external_value(PARAM_RAW, 'type',VALUE_OPTIONAL),

View file

@ -3,10 +3,15 @@ namespace local_treestudyplan;
require_once($CFG->libdir.'/externallib.php'); require_once($CFG->libdir.'/externallib.php');
use \local_treestudyplan\courseinfo; use \local_treestudyplan\courseinfo;
use \local_treestudyplan\associationservice;
use \local_treestudyplan\local\helpers\webservicehelper; use \local_treestudyplan\local\helpers\webservicehelper;
use \local_treestudyplan\completionscanner;
use \local_treestudyplan\gradingscanner;
class courseservice extends \external_api class courseservice extends \external_api
{ {
const CAP_EDIT = "local/treestudyplan:editstudyplan";
const CAP_VIEW = "local/treestudyplan:viewuserreports";
/************************ /************************
* * * *
@ -50,7 +55,7 @@ class courseservice extends \external_api
$root = \core_course_category::get($root_id); $root = \core_course_category::get($root_id);
$context = $root->get_context(); $context = $root->get_context();
// Make sure the user has access to the context for editing purposes // Make sure the user has access to the context for editing purposes
webservicehelper::require_capabilities("local/treestudyplan:editstudyplan",$context); webservicehelper::require_capabilities(self::CAP_EDIT,$context);
// Determine top categories from provided context // Determine top categories from provided context
@ -135,9 +140,9 @@ class courseservice extends \external_api
public static function list_accessible_categories($operation="edit") public static function list_accessible_categories($operation="edit")
{ {
if($operation == "edit"){ if($operation == "edit"){
$capability = "local/treestudyplan:editstudyplan"; $capability = self::CAP_EDIT;
} else { // $operation == "view" || default } else { // $operation == "view" || default
$capability = "local/treestudyplan:viewuserreports"; $capability = self::CAP_VIEW;
} }
$cats = static::categories_by_capability($capability); $cats = static::categories_by_capability($capability);
@ -208,9 +213,9 @@ class courseservice extends \external_api
{ {
global $DB; global $DB;
if($operation == "edit"){ if($operation == "edit"){
$capability = "local/treestudyplan:editstudyplan"; $capability = self::CAP_EDIT;
} else { // $operation == "view" || default } else { // $operation == "view" || default
$capability = "local/treestudyplan:viewuserreports"; $capability = self::CAP_VIEW;
} }
$context_ids = []; $context_ids = [];
$rs = $DB->get_recordset_sql("SELECT DISTINCT context_id, COUNT(*) as num FROM {local_treestudyplan} $rs = $DB->get_recordset_sql("SELECT DISTINCT context_id, COUNT(*) as num FROM {local_treestudyplan}
@ -243,9 +248,9 @@ class courseservice extends \external_api
public static function list_accessible_categories_with_usage($operation='edit'){ public static function list_accessible_categories_with_usage($operation='edit'){
global $DB; global $DB;
if($operation == "edit"){ if($operation == "edit"){
$capability = "local/treestudyplan:editstudyplan"; $capability = self::CAP_EDIT;
} else { // $operation == "view" || default } else { // $operation == "view" || default
$capability = "local/treestudyplan:viewuserreports"; $capability = self::CAP_VIEW;
} }
// retrieve context ids used // retrieve context ids used
$context_ids = []; $context_ids = [];
@ -269,6 +274,7 @@ class courseservice extends \external_api
} }
$o = new \stdClass(); $o = new \stdClass();
$o->cat = $cat; $o->cat = $cat;
$o->ctxid = $ctxid;
$o->count = $count; $o->count = $count;
$list[] = $o; $list[] = $o;
} }
@ -276,4 +282,119 @@ class courseservice extends \external_api
} }
/**************************************
*
* Progress scanners for teacherview
*
**************************************/
public static function scan_grade_progress_parameters()
{
return new \external_function_parameters( [
"gradeitemid" => new \external_value(PARAM_INT, 'Grade item ID to scan progress for',VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT, 'Study plan id to check progress in',VALUE_DEFAULT),
]);
}
public static function scan_grade_progress_returns()
{
return gradingscanner::structure(VALUE_REQUIRED);
}
public static function scan_grade_progress($gradeitemid, $studyplanid)
{
global $DB;
// Verify access to the study plan
$o = studyplan::findById($studyplanid);
webservicehelper::require_capabilities(self::CAP_VIEW,$o->context());
// Retrieve grade item
$gi = \grade_item::fetch(["id" => $gradeitemid]);
// Validate course is linked to studyplan
$courseid = $gi->courseid;
if(!$o->course_linked($courseid)){
throw new \webservice_access_exception("Course {$courseid} linked to grade item {$gradeitemid} is not linked to studyplan {$o->id()}");
}
$scanner = new gradingscanner($gi);
return $scanner->model();
}
public static function scan_completion_progress_parameters()
{
return new \external_function_parameters( [
"criteriaid" => new \external_value(PARAM_INT, 'CriteriaID to scan progress for',VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT, 'Study plan id to check progress in',VALUE_DEFAULT),
]);
}
public static function scan_completion_progress_returns()
{
return completionscanner::structure(VALUE_REQUIRED);
}
public static function scan_completion_progress($criteriaid, $studyplanid)
{
global $DB;
// Verify access to the study plan
$o = studyplan::findById($studyplanid);
webservicehelper::require_capabilities(self::CAP_VIEW,$o->context());
$crit = \completion_criteria::fetch(["id" => $criteriaid]);
$courseid = $crit->course;
if(!$o->course_linked($courseid)){
throw new \webservice_access_exception("Course {$courseid} linked to criteria {$criteriaid} is not linked to studyplan {$o->id()}");
}
$scanner = new completionscanner($crit);
return $scanner->model();
}
public static function scan_badge_progress_parameters()
{
return new \external_function_parameters( [
"badgeid" => new \external_value(PARAM_INT, 'Badge to scan progress for',VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT, 'Study plan id to limit progress search to (to determine which students to scan)',VALUE_DEFAULT),
]);
}
public static function scan_badge_progress_returns()
{
return new \external_single_structure([
"total" => new \external_value(PARAM_INT, 'Total number of students scanned'),
"issued" => new \external_value(PARAM_INT, 'Number of issued badges'),
]);
}
public static function scan_badge_progress($badgeid,$studyplanid)
{
global $DB;
// Check access to the study plan
$o = studyplan::findById($studyplanid);
webservicehelper::require_capabilities(self::CAP_VIEW,$o->context());
// Validate that badge is linked to studyplan
if(!$o->badge_linked($badgeid)){
throw new \webservice_access_exception("Badge {$badgeid} is not linked to studyplan {$o->id()}");
}
// Get badge info
$badge = new \core_badges\badge($badgeid);
$badgeinfo = new badgeinfo($badge);
// get the connected users
$students = associationservice::all_associated($studyplanid);
// Just get the user ids
$studentids = array_map(function ($a){ return $a["id"];},$students);
return [
"total" => count($studentids),
"issued" => $badgeinfo->count_issued($studentids),
];
}
} }

View file

@ -721,5 +721,41 @@ class studyplan {
return true; return true;
} }
/**
* See if the specified course id is linked in this studyplan
*/
public function course_linked($courseid){
global $DB;
$sql = "SELECT COUNT(i.id)
FROM {local_treestudyplan}
INNER JOIN {local_treestudyplan_line} l ON p.id = l.studyplan_id
INNER JOIN {local_treestudyplan_item} i ON l.id = i.line_id
WHERE p.id = :planid
AND i.course_id = :courseid";
$count = $DB->get_field_sql($sql,["courseid" => $courseid, "planid" => $this->id]);
return ($count > 0)?true:false;
}
/**
* See if the specified course id is linked in this studyplan
*/
public function badge_linked($badgeid){
global $DB;
$sql = "SELECT COUNT(i.id)
FROM {local_treestudyplan}
INNER JOIN {local_treestudyplan_line} l ON p.id = l.studyplan_id
INNER JOIN {local_treestudyplan_item} i ON l.id = i.line_id
WHERE p.id = :planid
AND i.badge_id = :badgeid";
$count = $DB->get_field_sql($sql,["badgeid" => $badgeid, "planid" => $this->id]);
return ($count > 0)?true:false;
}
} }

View file

@ -1,6 +1,6 @@
<?php <?php
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494) $plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494)
$plugin->version = 2023051700; // YYYYMMDDHH (year, month, day, iteration) $plugin->version = 2023061600; // YYYYMMDDHH (year, month, day, iteration)
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11) $plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11)
$plugin->dependencies = [ $plugin->dependencies = [