moodle-block_mytreestudyplan/classes/skillmgmtservice.php
2018-09-24 11:05:10 +02:00

473 lines
13 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 = 150; // 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);
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));
if($skill_id == 0 || count($levels) > 0)
{
// If global level, or skills are defined, return those
// Sort by points
usort( $levels, function( $a, $b) {
return ( $a->points < $b->points ) ? -1 : 1;
} );
return $levels;
}
else
{
// Else, return a nameless clone of the default levels).
$levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0));
// Sort by points
usort( $levels, function( $a, $b) {
return ( $a->points < $b->points ) ? -1 : 1;
} );
foreach($levels as $lvl)
{
$lvl->id = -255; // replace level id with -255, which is code for "new level" when returned
}
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, $name, $icon )
{
global $CFG, $DB;
$skill = $DB->get_record('block_gradelevel_levelset', array('id' => $id));
if($name != null){
$skill->name = $name;
}
if($icon != null){
$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($name, $icon)
{
global $CFG, $DB;
$skill = new stdClass;
if(empty($name)){
$skill->name = get_string('defaults_name','block_gradelevel');
}
else {
$skill->name = $name;
}
if(empty($icon)){
$skill->icon = "/blocks/gradelevel/pix/undefinedskill.svg";
}
else {
$skill->icon = $icon;
}
$id = $DB->insert_record('block_gradelevel_levelset',$skill, true);
$skill->id = $id;
$skill->html = static::single_skill_editor_item(block_gradelevel_levelset::find_by_id($skill->id));
return $skill;
}
public static function delete_skill(int $id)
{
global $CFG, $DB;
$skill = block_gradelevel_levelset::find_by_id($id);
if(count($skill->list_courses()) > 0)
{
throw new Exception("Cannot delete skills that have courses attached");
}
$result = array('id' => $id);
$result['deleted'] = ($DB->delete_records('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' class='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>";
if($skill_id > 0)
{
$s .= " <button data-action='resetlevels'>".get_string('cfg_resetlevels','block_gradelevel')."</button>";
}
$s .= "</p>";
return $s;
}
public static function render_skill_list()
{
global $CFG;
$skills = block_gradelevel_levelset::list_all();
// Sort by points
usort( $skills, function( $a, $b) {
return ( $a->getName() < $b->getName()) ? -1 : 1;
} );
$s = "<div id='skill_set' class='skill_set'><ul>";
foreach($skills as $skill)
{
$s .= static::single_skill_editor_item($skill);
}
$s .= "</ul>";
$s .= "<a href='#' onclick='return false;' data-action='addskill'>".get_string('cfg_addskill','block_gradelevel')."</a>";
$s .= "</div>";
return $s;
}
public static function render_skill_editor(int $skill_id)
{
$skill = block_gradelevel_levelset::find_by_id($skill_id);
$s = "<div id='skill_set' class='skill_set'><ul>";
$s .= static::single_skill_editor_item($skill,true);
$s .= "</ul></div>";
return $s;
}
private static function single_skill_editor_item($skill,$single=false)
{
global $OUTPUT;
$skill_id = $skill->getId();
$s = "<li class='skill_info' data-id='{$skill_id}'>";
if(!$single){
$s .= "<a data-action='editlevels' href='#'>";
}
$s .= $skill->render_demo_badge(static::DEMOBADGE_SIZE)."</a>";
if(!$single){
$s .= "<a data-action='editlevels' href='#'>";
if(count($skill->list_courses()) == 0){
$s .= "<a class='deleteskill' data-action='deleteskill' onclick='return false;' href='#'><i class='icon fa fa-minus-circle fa-fw' title='".get_string('tooltip_deleteskill','block_gradelevel')."'></i></a>";
}
}
$s .= "<a class='editicon' data-action='editicon' onclick='return false;' href='#'><i class='icon fa fa-pencil fa-fw' title='".get_string('tooltip_editicon','block_gradelevel')."'></i></a>";
$s .= "<figcaption data-for='name'><span data-type='label'>".$skill->getName()."</span>";
$s .= "<a class='editname' data-action='editname' onclick='return false;' href='#'><i class='icon fa fa-pencil fa-fw' title='".get_string('tooltip_editname','block_gradelevel')."'></i></a>";
$s .= "</figcaption></li>";
return $s;
}
}