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 = "

".get_string('levelcfg_description','block_gradelevel')."

"; $s .= ""; $s .= ""; $s .= ""; foreach($levels as $lvl) { $color = ltrim($lvl->badgecolor,"#"); // trim any leading hashes $s .= ""; } $s .= ""; $s .= ""; $s .= "
".get_string('levelcfg_head_points','block_gradelevel')."".get_string('levelcfg_head_color','block_gradelevel')."
".get_string("levelcfg_addlevel",'block_gradelevel')."
"; $s .= "

"; if($skill_id > 0) { $s .= " "; } $s .= "

"; 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 = "
"; $s .= "".get_string('cfg_addskill','block_gradelevel').""; $s .= "
"; return $s; } public static function render_skill_editor(int $skill_id) { $skill = block_gradelevel_levelset::find_by_id($skill_id); $s = "
"; return $s; } private static function single_skill_editor_item($skill,$single=false) { global $OUTPUT; $skill_id = $skill->getId(); $s = "
  • "; if(!$single){ $s .= ""; } $s .= $skill->render_demo_badge(static::DEMOBADGE_SIZE).""; if(!$single){ $s .= ""; if(count($skill->list_courses()) == 0){ $s .= ""; } } $s .= ""; $s .= "
    ".$skill->getName().""; $s .= ""; $s .= "
  • "; return $s; } }