moodle-block_mytreestudyplan/classes/skillmgmtservice.php
pmk 6b16559201 Added web service for managing levelsets (now mostly called "skills")
Default levels can be configured.
Working on management interface for predefined skills.
2018-09-21 22:30:09 +02:00

406 lines
11 KiB
PHP

<?php
require_once($CFG->libdir.'/gradelib.php');
require_once($CFG->libdir.'/externallib.php');
require_once($CFG->dirroot.'/grade/querylib.php');
//namespace block_gradelevel;
class block_gradelevel_skillmgmtservice extends external_api
{
const DEBUG = false; // enable debug logging
const DEMOBADGE_SIZE = 100; // size of demo badge
private static function log($message)
{
if(self::DEBUG)
{
error_log($message."\n",3,"/tmp/block_gradelevel.log");
}
}
private static function list_courses($skill_id)
{
global $DB;
$list = array();
$links = $DB->get_records('block_gradelevel_course_link', array('levelset_id' => $skill_id));
foreach($links as $link)
{
$list[] = $link->course_id;
}
return $list;
}
// Input parameter config
public static function submit_levels_parameters()
{
return new external_function_parameters(
array(
'skill_id' => new external_value(PARAM_INT, 'id of skill'),
'levels' => new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'id of level'),
'points' => new external_value(PARAM_INT, 'number of points for this level'),
'badgecolor' => new external_value(PARAM_TEXT, 'color of level badge'),
)
)
)
)
);
}
public static function list_levels_parameters()
{
return new external_function_parameters(
array(
'skill_id' => new external_value(PARAM_INT, 'id of skill'),
)
);
}
public static function list_skills_parameters()
{
return new external_function_parameters( array() );
}
public static function get_skill_parameters()
{
return new external_function_parameters(
array(
'id' => new external_value(PARAM_INT, 'id of skill'),
)
);
}
public static function update_skill_parameters()
{
return new external_function_parameters(
array(
'id' => new external_value(PARAM_INT, 'id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
)
);
}
public static function add_skill_parameters()
{
return new external_function_parameters(
array(
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
)
);
}
public static function delete_skill_parameters()
{
return new external_function_parameters(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
)
);
}
// Output parameter config
public static function submit_levels_returns()
{
return new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'id of level'),
'points' => new external_value(PARAM_INT, 'number of points for this level'),
'badgecolor' => new external_value(PARAM_TEXT, 'color of level badge'),
)
)
);
}
public static function list_levels_returns()
{
return new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'id of level'),
'points' => new external_value(PARAM_INT, 'number of points for this level'),
'badgecolor' => new external_value(PARAM_TEXT, 'color of level badge'),
)
)
);
}
public static function list_skills_returns()
{
return new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
)
);
}
public static function get_skill_returns()
{
return new external_single_structure(
array(
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
);
}
public static function update_skill_returns()
{
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
);
}
public static function add_skill_returns()
{
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
);
}
public static function delete_skill_returns()
{
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'deleted' => new external_value(PARAM_BOOL, 'Deletion succesful'),
)
);
}
// Actual functions
public static function submit_levels(int $skill_id, array $levels)
{
global $CFG, $DB;
self::log("submit_levels called, skill_id: {$skill_id}, levels: \n".print_r($levels,true));
$systemcontext = context_system::instance();
self::validate_context($systemcontext);
if(skill_id == 0)
{
// Check if user has capability to manage global levels
require_capability('block/gradelevel:managelevels', $systemcontext);
}
else
{
// Check if user has teacher or manager capability in any of the attached courses
$capability = false;
$courses = self::list_courses($skill_id);
foreach($courses as $course_id)
{
$coursecontext = context_course::instance($course_id);
$capability |= has_capability('block/gradelevel:changelevels', $coursecontext);
}
if(!$capability)
{
throw new Exception("Access denied - you do not have editing capabilities for one of the attached courses");
}
}
foreach($levels as $lvl_raw)
{
// convert level array to stdObj
$lvl = (object) $lvl_raw;
$lvl->levelset_id = $skill_id;
self::log("Processing level: ".print_r($lvl,true));
if($lvl->points >= 0)
{
if($lvl->id >= 0)
{
// Update record
self::log("updating row {$lvl->id}: {$lvl->points}, {$lvl->badgecolor} @ {$lvl->levelset_id}");
$DB->update_record('block_gradelevel_levels',$lvl);
}
else
{
// unset invalid id before insert
unset($lvl->id);
self::log("inserting new row {$lvl->points}, {$lvl->badgecolor} @ {$lvl->levelset_id}");
// Insert record
$DB->insert_record('block_gradelevel_levels',$lvl);
}
}
else
{
// points is empty: delete record if we have a valid id.
if($lvl->id >= 0)
{
self::log("deleting empty row {$lvl->id}");
$DB->delete_records('block_gradelevel_levels', array('id' => $lvl->id));
}
else
{
self::log("ignoring empty row");
}
}/**/
}
return static::list_levels($skill_id);
}
public static function list_levels(int $skill_id)
{
global $CFG, $DB;
$levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $skill_id));
// Sort by points
usort( $levels, function( $a, $b) {
return ( $a->points < $b->points ) ? -1 : 1;
} );
return $levels;
}
public static function list_skills()
{
global $CFG, $DB;
$skills = $DB->get_records('block_gradelevel_levelset');
// Sort by points
usort( $skills, function( $a, $b) {
return ( $a->name < $b->name) ? -1 : 1;
} );
foreach($skills as $skill )
{
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
}
return $skills;
}
public static function get_skill(int $id)
{
global $CFG, $DB;
$skill = $DB->get_record('block_gradelevel_levels', array('id' => $id));
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
return $skill;
}
public static function update_skill(int $id, string $name, string $icon )
{
global $CFG, $DB;
$skill = $DB->get_record('block_gradelevel_levelset', array('id' => $id));
$skill->name = $name;
$skill->icon = $icon;
$DB->update_record('block_gradelevel_levelset',$skill);
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
return $skill;
}
public static function add_skill(string $name, string $icon)
{
global $CFG, $DB;
$skill = stdObj;
$skill->name = $name;
$skill->icon = $icon;
$id = $DB->insert_record('block_gradelevel_levelset',$skill, true);
$skill->id = $id;
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
return $skill;
}
public static function delete_skill(int $id)
{
global $CFG, $DB;
$result = stdObj;
$result->id = $id;
$result->id = ($DB->delete_record('block_gradelevel_levelset',array('id' => $id)))?true:false;
return $result;
}
// Other public functions
public static function render_leveltable($skill_id)
{
$levels = static::list_levels($skill_id);
$s = "<p>".get_string('levelcfg_description','block_gradelevel')."</p>";
$s .= "<table id='level_config' data-skill='{$skill_id}'>";
$s .= "<thead><tr><th>".get_string('levelcfg_head_points','block_gradelevel')."</th><th>".get_string('levelcfg_head_color','block_gradelevel')."</th></tr></thead>";
$s .= "<tbody>";
foreach($levels as $lvl)
{
$color = ltrim($lvl->badgecolor,"#"); // trim any leading hashes
$s .= "<tr data-rowid='{$lvl->id}'><td><input data-name='points' type='number' class='uint' value='{$lvl->points}'></td><td><input type='text' data-name='color' class='jscolor' value='{$color}'></td></tr>";
}
$s .= "</tbody>";
$s .= "<tfoot><tr><td class='block_gradelevel_addlevel' colspan='2'><a data-action='addlevel' href='#' onclick='return false;'>".get_string("levelcfg_addlevel",'block_gradelevel')."</a></td></td></tfoot>";
$s .= "</table>";
$s .= "<p><button data-action='savechanges'>".get_string('savechanges','core')."</button></p>";
return $s;
}
public static function render_skill_list()
{
$skills = block_gradelevel_levelset::list_all();
$s = "<div class='skill_set'><ul>";
foreach($skills as $skill)
{
$skill_id = $skill->getId();
$s .= "<li class='skill_info' data-id='{$skill_id}'>".$skill->render_demo_badge(DEMOBADGE_SIZE);
$s .= "<figcaption data-for='name'>".$skill->getName()."</figcaption>";
$s .= "</li>";
}
$s .= "</ul></div>";
}
}