diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..866f1e1 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..5c3679e --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,14 @@ +{ + "ExpandedNodes": [ + "", + "\\amd", + "\\classes", + "\\db", + "\\lang", + "\\lang\\en", + "\\lang\\nl", + "\\pix" + ], + "SelectedNode": "\\db\\access.php", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/block_gradelevel/v15/.suo b/.vs/block_gradelevel/v15/.suo new file mode 100644 index 0000000..f88cf9c Binary files /dev/null and b/.vs/block_gradelevel/v15/.suo differ diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..72cd8d2 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/LICENSE b/LICENSE index 6d0608a..8917076 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ -Copyright 2018 P.M. Kuipers - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - +Copyright 2018 P.M. Kuipers + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/amd/build/renderbadge.min.js b/amd/build/renderbadge.min.js index 0873ac7..a1c4232 100644 --- a/amd/build/renderbadge.min.js +++ b/amd/build/renderbadge.min.js @@ -1 +1 @@ -define(["jquery","core/str","core/ajax","block_gradelevel/debugger"],function(e,t,i,l){let r=l("renderbadge");r.enable();let a={init:function(){r.info("Setting up badge renderers"),e("figure.levelbadge").each(function(){a.setup_badge(this,!0)})},setup_badge:function(t,i){let l=e(t),n=e(t).data("badge-props");if(r.info("Setting up skill badge on ",t,n),n&&i)r.info(" skill badge was already configured. Skipping process...");else{n=a.fetchProperties(t);let i=e("");e("canvas",t).remove(),l.append(i),a.render(i[0],n),l.data("badge-props",n)}},render:function(e,t){let i=e.getContext("2d"),l={base:t.color,light:a.shadeBlendConvert(.6,t.color),dark:a.shadeBlendConvert(.3,t.color),lightPoint:a.shadeBlendConvert(.8,t.color),reflection:{lightest:"#ffffff51",darkest:"#ffffff20"},radialGradient:{x0:.75,y0:.25,r0:.05,x1:.6,y1:.4,r1:.4},levelText:"white"},n={size:Math.min(t.height,t.width),borderWidth:.05,reflection:{angle:-20,offset:.125},levelText:{x:.5,y:.9,size:.2,font:"Open Sans, Arial, helvetica, sans-serif"},icon:{x:.5,y:.47,scale:.7}};r.info(" Config",n),r.info(" Colors",l),r.info(" Props",t);let s=i.createRadialGradient(n.size*l.radialGradient.x0,n.size*l.radialGradient.y0,n.size*l.radialGradient.r0,n.size*l.radialGradient.x1,n.size*l.radialGradient.y1,n.size*l.radialGradient.r1);s.addColorStop(0,l.lightPoint),s.addColorStop(1,l.base),i.beginPath(),i.fillStyle=s,i.arc(.5*n.size,.5*n.size,n.size/2,0,2*Math.PI),i.fill();let o=Math.asin(n.reflection.offset),d=n.reflection.angle/360*2*Math.PI,h=i.createLinearGradient((.5-n.reflection.offset*Math.sin(d))/2*n.size,(.5+n.reflection.offset*Math.cos(d))/2*n.size,Math.sin(d)/2*n.size,Math.cos(d)/2*n.size);h.addColorStop(0,l.reflection.lightest),h.addColorStop(1,l.reflection.darkest),i.beginPath(),i.fillStyle=h,i.arc(.5*n.size,.5*n.size,n.size/2,0+o+d,Math.PI-o+d),i.fill();let f=n.size*n.borderWidth;if(i.beginPath(),i.strokeStyle=l.light,i.lineWidth=f,i.arc(.5*n.size,.5*n.size,n.size/2-f/2,0,2*Math.PI),i.stroke(),i.beginPath(),i.strokeStyle=l.dark,i.lineWidth=f,i.arc(.5*n.size,.5*n.size,n.size/2-f/2,0-Math.PI/2,2*t.progress*Math.PI-Math.PI/2),i.stroke(),t.level&&(i.font=n.size*n.levelText.size+"px "+n.levelText.font,i.fillStyle=l.levelText,i.textAlign="center",i.fillText(""+t.level,n.size*n.levelText.x,n.size*n.levelText.y)),t.image){let e=new Image;e.onload=function(){let e={x:0,y:0,w:n.size*n.icon.scale,h:n.size*n.icon.scale};this.width>this.height?e.h*=this.height/this.width:e.w*=this.width/this.height,e.x=n.size*n.icon.x-e.w/2,e.y=n.size*n.icon.y-e.h/2,i.drawImage(this,e.x,e.y,e.w,e.h)},e.src=t.image}},fetchProperties:function(t){let i=e(t),l=i.find("img"),r=null;return l.length>0&&(r=l.attr("src")),{progress:i.attr("data-progress"),width:i.attr("data-width"),height:i.attr("data-height"),color:"#"+i.attr("data-color"),level:i.attr("data-level"),image:r}},shadeBlendConvert:function(e,t,i){if("number"!=typeof e||e<-1||e>1||"string"!=typeof t||"r"!=t[0]&&"#"!=t[0]||i&&"string"!=typeof i)return null;this.sbcRip||(this.sbcRip=(e=>{let t=e.length,i={};if(t>9){if((e=e.split(",")).length<3||e.length>4)return null;i[0]=l(e[0].split("(")[1]),i[1]=l(e[1]),i[2]=l(e[2]),i[3]=e[3]?parseFloat(e[3]):-1}else{if(8==t||6==t||t<4)return null;t<6&&(e="#"+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]+(t>4?e[4]+""+e[4]:"")),e=l(e.slice(1),16),i[0]=e>>16&255,i[1]=e>>8&255,i[2]=255&e,i[3]=-1,9!=t&&5!=t||(i[3]=r(i[2]/255*1e4)/1e4,i[2]=i[1],i[1]=i[0],i[0]=e>>24&255)}return i}));var l=parseInt,r=Math.round,a=t.length>9,n=(a="string"==typeof i?i.length>9||"c"==i&&!a:a,e<0),s=(e=n?-1*e:e,i=i&&"c"!=i?i:n?"#000000":"#FFFFFF",this.sbcRip(t)),o=this.sbcRip(i);return s&&o?a?"rgb"+(s[3]>-1||o[3]>-1?"a(":"(")+r((o[0]-s[0])*e+s[0])+","+r((o[1]-s[1])*e+s[1])+","+r((o[2]-s[2])*e+s[2])+(s[3]<0&&o[3]<0?")":","+(s[3]>-1&&o[3]>-1?r(1e4*((o[3]-s[3])*e+s[3]))/1e4:o[3]<0?s[3]:o[3])+")"):"#"+(4294967296+16777216*r((o[0]-s[0])*e+s[0])+65536*r((o[1]-s[1])*e+s[1])+256*r((o[2]-s[2])*e+s[2])+(s[3]>-1&&o[3]>-1?r(255*((o[3]-s[3])*e+s[3])):o[3]>-1?r(255*o[3]):s[3]>-1?r(255*s[3]):255)).toString(16).slice(1,s[3]>-1||o[3]>-1?void 0:-2):null}};return a}); \ No newline at end of file +define(["jquery","core/str","core/ajax","block_gradelevel/debugger"],function(e,t,i,r){let l=r("renderbadge");function n(e){if(/^#([A-Fa-f0-9]{3})$/.test(e)){let t=e.substring(1).split(""),i="0x"+[t[0],t[0],t[1],t[1],t[2],t[2]].join("");return"rgb("+[i>>16&255,i>>8&255,255&i].join(",")+")"}if(/^#([A-Fa-f0-9]{6})$/.test(e)){let t="0x"+e.substring(1).split("").join("");return"rgb("+[t>>16&255,t>>8&255,255&t].join(",")+")"}if(/^#([A-Fa-f0-9]{8})$/.test(e)){let t=e.substring(1).split(""),i="0x"+[t[0],t[1],t[2],t[3],t[4],t[5]].join(""),r="0x"+[t[6],t[7]].join("");return"rgba("+[i>>16&255,i>>8&255,255&i].join(",")+","+r/255+")"}throw Error("Invalid hex code: "+e)}l.enable();let a={init:function(){l.info("Setting up badge renderers"),e("figure.levelbadge").each(function(){a.setup_badge(this,!0)})},setup_badge:function(t,i){let r=e(t),n=e(t).data("badge-props");if(l.info("Setting up skill badge on ",t,n),n&&i)l.info(" skill badge was already configured. Skipping process...");else{n=a.fetchProperties(t);let i=e("");e("canvas",t).remove(),r.append(i),a.render(i[0],n),r.data("badge-props",n)}},render:function(e,t){let i=e.getContext("2d"),r={base:t.color,light:a.shadeBlendConvert(.6,t.color),dark:a.shadeBlendConvert(.3,t.color),lightPoint:a.shadeBlendConvert(.8,t.color),reflection:{lightest:"#ffffff51",darkest:"#ffffff20"},radialGradient:{x0:.75,y0:.25,r0:.05,x1:.6,y1:.4,r1:.4},levelText:"white"},s={size:Math.min(t.height,t.width),borderWidth:.05,reflection:{angle:-20,offset:.125},levelText:{x:.5,y:.9,size:.2,font:"Open Sans, Arial, helvetica, sans-serif"},icon:{x:.5,y:.47,scale:.7}};l.info(" Config",s),l.info(" Colors",r),l.info(" Props",t);let o=i.createRadialGradient(s.size*r.radialGradient.x0,s.size*r.radialGradient.y0,s.size*r.radialGradient.r0,s.size*r.radialGradient.x1,s.size*r.radialGradient.y1,s.size*r.radialGradient.r1);o.addColorStop(0,n(r.lightPoint)),o.addColorStop(1,n(r.base)),i.beginPath(),i.fillStyle=o,i.arc(.5*s.size,.5*s.size,s.size/2,0,2*Math.PI),i.fill();let d=Math.asin(s.reflection.offset),h=s.reflection.angle/360*2*Math.PI;l.info("rflAngleRad:",h);let f=i.createLinearGradient((.5-s.reflection.offset*Math.sin(h))/2*s.size,(.5+s.reflection.offset*Math.cos(h))/2*s.size,Math.sin(h)/2*s.size,Math.cos(h)/2*s.size);l.info("rflGradient",f),f.addColorStop(0,n(r.reflection.lightest)),f.addColorStop(1,n(r.reflection.darkest)),i.beginPath(),i.fillStyle=f,i.arc(.5*s.size,.5*s.size,s.size/2,0+d+h,Math.PI-d+h),i.fill(),l.info("Starting with border");let g=s.size*s.borderWidth;if(i.beginPath(),i.strokeStyle=r.light,i.lineWidth=g,i.arc(.5*s.size,.5*s.size,s.size/2-g/2,0,2*Math.PI),i.stroke(),i.beginPath(),i.strokeStyle=r.dark,i.lineWidth=g,i.arc(.5*s.size,.5*s.size,s.size/2-g/2,0-Math.PI/2,2*t.progress*Math.PI-Math.PI/2),i.stroke(),t.level&&(i.font=s.size*s.levelText.size+"px "+s.levelText.font,i.fillStyle=r.levelText,i.textAlign="center",i.fillText(""+t.level,s.size*s.levelText.x,s.size*s.levelText.y)),t.image){let e=new Image;e.onload=function(){let e={x:0,y:0,w:s.size*s.icon.scale,h:s.size*s.icon.scale};this.width>this.height?e.h*=this.height/this.width:e.w*=this.width/this.height,e.x=s.size*s.icon.x-e.w/2,e.y=s.size*s.icon.y-e.h/2,i.drawImage(this,e.x,e.y,e.w,e.h)},e.src=t.image}},fetchProperties:function(t){let i=e(t),r=i.find("img"),l=null;return r.length>0&&(l=r.attr("src")),{progress:i.attr("data-progress"),width:i.attr("data-width"),height:i.attr("data-height"),color:"#"+i.attr("data-color"),level:i.attr("data-level"),image:l}},shadeBlendConvert:function(e,t,i){if("number"!=typeof e||e<-1||e>1||"string"!=typeof t||"r"!=t[0]&&"#"!=t[0]||i&&"string"!=typeof i)return null;this.sbcRip||(this.sbcRip=(e=>{let t=e.length,i={};if(t>9){if((e=e.split(",")).length<3||e.length>4)return null;i[0]=r(e[0].split("(")[1]),i[1]=r(e[1]),i[2]=r(e[2]),i[3]=e[3]?parseFloat(e[3]):-1}else{if(8==t||6==t||t<4)return null;t<6&&(e="#"+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]+(t>4?e[4]+""+e[4]:"")),e=r(e.slice(1),16),i[0]=e>>16&255,i[1]=e>>8&255,i[2]=255&e,i[3]=-1,9!=t&&5!=t||(i[3]=l(i[2]/255*1e4)/1e4,i[2]=i[1],i[1]=i[0],i[0]=e>>24&255)}return i}));var r=parseInt,l=Math.round,n=t.length>9,a=(n="string"==typeof i?i.length>9||"c"==i&&!n:n,e<0),s=(e=a?-1*e:e,i=i&&"c"!=i?i:a?"#000000":"#FFFFFF",this.sbcRip(t)),o=this.sbcRip(i);return s&&o?n?"rgb"+(s[3]>-1||o[3]>-1?"a(":"(")+l((o[0]-s[0])*e+s[0])+","+l((o[1]-s[1])*e+s[1])+","+l((o[2]-s[2])*e+s[2])+(s[3]<0&&o[3]<0?")":","+(s[3]>-1&&o[3]>-1?l(1e4*((o[3]-s[3])*e+s[3]))/1e4:o[3]<0?s[3]:o[3])+")"):"#"+(4294967296+16777216*l((o[0]-s[0])*e+s[0])+65536*l((o[1]-s[1])*e+s[1])+256*l((o[2]-s[2])*e+s[2])+(s[3]>-1&&o[3]>-1?l(255*((o[3]-s[3])*e+s[3])):o[3]>-1?l(255*o[3]):s[3]>-1?l(255*s[3]):255)).toString(16).slice(1,s[3]>-1||o[3]>-1?void 0:-2):null}};return a}); \ No newline at end of file diff --git a/amd/src/renderbadge.js b/amd/src/renderbadge.js index 15e573d..0f30388 100644 --- a/amd/src/renderbadge.js +++ b/amd/src/renderbadge.js @@ -7,6 +7,29 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio let debug = Debugger("renderbadge"); debug.enable(); + // function is used to overcome Edge's non-support of CSS4 hex rgba notation (@nov 2018) + /* eslint-disable no-bitwise*/ + function hexToRgbA(hex){ + /*eslint no-bitwise: "off"*/ + if(/^#([A-Fa-f0-9]{3})$/.test(hex)){ + let h= hex.substring(1).split(''); + let c= '0x'+[h[0], h[0], h[1], h[1], h[2], h[2]].join(''); + return 'rgb('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+')'; + } + if(/^#([A-Fa-f0-9]{6})$/.test(hex)){ + let h= hex.substring(1).split(''); + let c= '0x'+h.join(''); + return 'rgb('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+')'; + } + if(/^#([A-Fa-f0-9]{8})$/.test(hex)){ + let h= hex.substring(1).split(''); + let c = '0x' + [h[0],h[1],h[2],h[3],h[4],h[5],].join(''); + let a= '0x' + [h[6],h[7],].join(''); + return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+','+a/255.0+')'; + } + throw Error('Invalid hex code: ' + hex); + } + /* eslint-enable no-bitwise */ let self = { init: function init() { debug.info("Setting up badge renderers"); @@ -90,8 +113,8 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio config.size * colors.radialGradient.y1, (config.size ) * colors.radialGradient.r1 ); - baseGradient.addColorStop(0, colors.lightPoint); - baseGradient.addColorStop(1, colors.base); + baseGradient.addColorStop(0, hexToRgbA(colors.lightPoint)); + baseGradient.addColorStop(1, hexToRgbA(colors.base)); ctx.beginPath(); ctx.fillStyle = baseGradient; ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2, 0, 2 * Math.PI); @@ -102,21 +125,23 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio let rflOffset = Math.asin(config.reflection.offset); let rflAngleRad = (config.reflection.angle / 360.0) * 2 * Math.PI; + debug.info("rflAngleRad:",rflAngleRad); let rflGradient = ctx.createLinearGradient( (0.5 - config.reflection.offset * Math.sin(rflAngleRad))/2 * config.size, (0.5 + config.reflection.offset * Math.cos(rflAngleRad))/2 * config.size, Math.sin(rflAngleRad)/2 * config.size, Math.cos(rflAngleRad)/2 * config.size ); - rflGradient.addColorStop(0, colors.reflection.lightest); - rflGradient.addColorStop(1, colors.reflection.darkest); + debug.info("rflGradient",rflGradient); + rflGradient.addColorStop(0, hexToRgbA(colors.reflection.lightest)); + rflGradient.addColorStop(1, hexToRgbA(colors.reflection.darkest)); ctx.beginPath(); ctx.fillStyle = rflGradient; ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2, 0 + rflOffset + rflAngleRad, Math.PI - rflOffset + rflAngleRad); ctx.fill(); - + debug.info("Starting with border"); // draw empty border let strokeWidth = config.size * config.borderWidth; ctx.beginPath(); diff --git a/block_gradelevel.php b/block_gradelevel.php index ef735f3..aab1f73 100644 --- a/block_gradelevel.php +++ b/block_gradelevel.php @@ -1,89 +1,89 @@ -libdir.'/gradelib.php'); -require_once($CFG->dirroot.'/grade/querylib.php'); -require_once($CFG->dirroot.'/blocks/gradelevel/lib.php'); - -use block_gradelevel; - -class block_gradelevel extends block_base { - - public $levelset; - - public function init() { - global $PAGE; - global $COURSE; - - $this->title = get_config('gradelevel', 'blocktitle'); - if(empty($this->title)) - { - $this->title = get_string('title', 'block_gradelevel'); - } - - // include javascript and run badge renderer when page loading is complete - $PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); - - // find or create the levelset for this course - $this->levelset = block_gradelevel_levelset::find_by_course($COURSE->id); - } - - // The PHP tag and the curly bracket for the class definition - // will only be closed after there is another function added in the next section. - - public function html_attributes() { - $attributes = parent::html_attributes(); // Get default values - $attributes['class'] .= ' block_'. $this->name(); // Append our class to class attribute - return $attributes; - } - - public function get_content() { - global $CFG; - global $USER; - global $COURSE; - - if ($this->content !== null) { - return $this->content; - } - - $this->content = new stdClass; - - if(empty($this->levelset)) - { - $this->content->text = "
"; - $this->content->footer = get_string("unattached_course",'block_gradelevel'); - } - else { - // below can be a single call to $this->levelset->get_user_leveldata() once the need for debugging (fixed point total) is gone - $pointstotal = $this->levelset->get_levelset_grade($USER->id); - $level_info = $this->levelset->calculate_level($pointstotal); - - $this->content->text = $this->levelset->render_badge($pointstotal); - - if($level_info->levelup_total > 0) - { - $this->content->footer = "
".get_string('levelup_at','block_gradelevel')." {$level_info->points_in_level}/{$level_info->levelup_total}
"; - } - else - { - $this->content->footer = "
".get_string('levelup_done','block_gradelevel')."
"; - } - - $coursecontext = context_course::instance($COURSE->id); - - if(has_capability('block/gradelevel:viewresults', $coursecontext)) - { - $this->content->footer .= "\n"; - } - } - return $this->content; - } - - - public function hide_header() { return !get_config('gradelevel', 'showtitle'); } - - public function has_config() { return true; } - - - - - +libdir.'/gradelib.php'); +require_once($CFG->dirroot.'/grade/querylib.php'); +require_once($CFG->dirroot.'/blocks/gradelevel/lib.php'); + +use block_gradelevel; + +class block_gradelevel extends block_base { + + public $levelset; + + public function init() { + global $PAGE; + global $COURSE; + + $this->title = get_config('gradelevel', 'blocktitle'); + if(empty($this->title)) + { + $this->title = get_string('title', 'block_gradelevel'); + } + + // include javascript and run badge renderer when page loading is complete + $PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); + + // find or create the levelset for this course + $this->levelset = block_gradelevel_levelset::find_by_course($COURSE->id); + } + + // The PHP tag and the curly bracket for the class definition + // will only be closed after there is another function added in the next section. + + public function html_attributes() { + $attributes = parent::html_attributes(); // Get default values + $attributes['class'] .= ' block_'. $this->name(); // Append our class to class attribute + return $attributes; + } + + public function get_content() { + global $CFG; + global $USER; + global $COURSE; + + if ($this->content !== null) { + return $this->content; + } + + $this->content = new stdClass; + + if(empty($this->levelset)) + { + $this->content->text = "
"; + $this->content->footer = get_string("unattached_course",'block_gradelevel'); + } + else { + // below can be a single call to $this->levelset->get_user_leveldata() once the need for debugging (fixed point total) is gone + $pointstotal = $this->levelset->get_levelset_grade($USER->id); + $level_info = $this->levelset->calculate_level($pointstotal); + + $this->content->text = $this->levelset->render_badge($pointstotal); + + if($level_info->levelup_total > 0) + { + $this->content->footer = "
".get_string('levelup_at','block_gradelevel')." {$level_info->points_in_level}/{$level_info->levelup_total}
"; + } + else + { + $this->content->footer = "
".get_string('levelup_done','block_gradelevel')."
"; + } + + $coursecontext = context_course::instance($COURSE->id); + + if(has_capability('block/gradelevel:viewresults', $coursecontext)) + { + $this->content->footer .= "\n"; + } + } + return $this->content; + } + + + public function hide_header() { return !get_config('gradelevel', 'showtitle'); } + + public function has_config() { return true; } + + + + + } \ No newline at end of file diff --git a/cfg_globallevels.php b/cfg_globallevels.php index 8a72895..391ff25 100644 --- a/cfg_globallevels.php +++ b/cfg_globallevels.php @@ -1,34 +1,34 @@ -libdir.'/adminlib.php'); - - -admin_externalpage_setup("block_gradelevel_default_levels"); - -$systemcontext = context_system::instance(); -// Check if user has capability to manage skills -require_capability('block/gradelevel:skillmanager', $systemcontext); - - -$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init'); - -print $OUTPUT->header(); -print $OUTPUT->heading(get_string('cfgpage_globallevels', 'block_gradelevel')); - -// render page for skill level 0 (global) -print block_gradelevel_skillmgmtservice::render_leveltable(0); -print $OUTPUT->footer(); +libdir.'/adminlib.php'); + + +admin_externalpage_setup("block_gradelevel_default_levels"); + +$systemcontext = context_system::instance(); +// Check if user has capability to manage skills +require_capability('block/gradelevel:skillmanager', $systemcontext); + + +$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init'); + +print $OUTPUT->header(); +print $OUTPUT->heading(get_string('cfgpage_globallevels', 'block_gradelevel')); + +// render page for skill level 0 (global) +print block_gradelevel_skillmgmtservice::render_leveltable(0); +print $OUTPUT->footer(); diff --git a/cfg_skilllevels.php b/cfg_skilllevels.php index 7404ad7..0ce716c 100644 --- a/cfg_skilllevels.php +++ b/cfg_skilllevels.php @@ -1,48 +1,48 @@ -libdir.'/adminlib.php'); - - -admin_externalpage_setup("block_gradelevel_config_skills"); - - -$skill_id = required_param('skill_id', PARAM_INT); - -$systemcontext = context_system::instance(); -// Check if user has capability to manage skills -require_capability('block/gradelevel:skillmanager', $systemcontext); - -$skill = block_gradelevel_levelset::find_by_id($skill_id); - -$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); -$PAGE->requires->js_call_amd('block_gradelevel/skilleditor', 'init'); -$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init'); - -print $OUTPUT->header(); - -// render skill editor -print $OUTPUT->heading(get_string('cfgpage_editskill','block_gradelevel')." ".$skill->getName()); -print block_gradelevel_skillmgmtservice::render_skill_editor($skill_id); - -// render level editor -print $OUTPUT->heading(get_string('cfgpage_skilllevels','block_gradelevel')); -print block_gradelevel_skillmgmtservice::render_leveltable($skill_id); - -// add back button to return to skill management page -$cfg_skills_url = $CFG->wwwroot."/blocks/gradelevel/cfg_skills.php"; -print ""; -print $OUTPUT->footer(); +libdir.'/adminlib.php'); + + +admin_externalpage_setup("block_gradelevel_config_skills"); + + +$skill_id = required_param('skill_id', PARAM_INT); + +$systemcontext = context_system::instance(); +// Check if user has capability to manage skills +require_capability('block/gradelevel:skillmanager', $systemcontext); + +$skill = block_gradelevel_levelset::find_by_id($skill_id); + +$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); +$PAGE->requires->js_call_amd('block_gradelevel/skilleditor', 'init'); +$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init'); + +print $OUTPUT->header(); + +// render skill editor +print $OUTPUT->heading(get_string('cfgpage_editskill','block_gradelevel')." ".$skill->getName()); +print block_gradelevel_skillmgmtservice::render_skill_editor($skill_id); + +// render level editor +print $OUTPUT->heading(get_string('cfgpage_skilllevels','block_gradelevel')); +print block_gradelevel_skillmgmtservice::render_leveltable($skill_id); + +// add back button to return to skill management page +$cfg_skills_url = $CFG->wwwroot."/blocks/gradelevel/cfg_skills.php"; +print ""; +print $OUTPUT->footer(); diff --git a/cfg_skills.php b/cfg_skills.php index 3d9139b..52798cf 100644 --- a/cfg_skills.php +++ b/cfg_skills.php @@ -1,35 +1,35 @@ -libdir.'/adminlib.php'); - - -admin_externalpage_setup("block_gradelevel_config_skills"); - -$systemcontext = context_system::instance(); -// Check if user has capability to manage skills -require_capability('block/gradelevel:skillmanager', $systemcontext); - - -$PAGE->requires->js_call_amd('block_gradelevel/skilleditor', 'init'); -$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); - -print $OUTPUT->header(); -print $OUTPUT->heading(get_string('cfgpage_skills', 'block_gradelevel')); - -// render page for skill level 0 (global) -print block_gradelevel_skillmgmtservice::render_skill_list(0); -print $OUTPUT->footer(); +libdir.'/adminlib.php'); + + +admin_externalpage_setup("block_gradelevel_config_skills"); + +$systemcontext = context_system::instance(); +// Check if user has capability to manage skills +require_capability('block/gradelevel:skillmanager', $systemcontext); + + +$PAGE->requires->js_call_amd('block_gradelevel/skilleditor', 'init'); +$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); + +print $OUTPUT->header(); +print $OUTPUT->heading(get_string('cfgpage_skills', 'block_gradelevel')); + +// render page for skill level 0 (global) +print block_gradelevel_skillmgmtservice::render_skill_list(0); +print $OUTPUT->footer(); diff --git a/classes/levelset.php b/classes/levelset.php index 47f331e..d42b049 100644 --- a/classes/levelset.php +++ b/classes/levelset.php @@ -1,492 +1,492 @@ -libdir.'/gradelib.php'); -require_once($CFG->dirroot.'/grade/querylib.php'); - -//namespace block_gradelevel; - -class block_gradelevel_levelset { - const UNDEFINED_BADGE_COLOR="#3F3F3F"; - const NULL_BADGE_COLOR = "#320000"; - const DEFAULT_ICON = "/blocks/gradelevel/pix/undefinedskill.svg"; - - const GLOBAL_DEFAULTS = array( - 0 => "#320000", - 250 => "#2ad4ff", // + 250 - 750 => "#cd7f32", // + 500 - 1750 => "#92A1A6", // + 1000 - 2750 => "#f6ae00", // + 2000 - ); - - private $id; - private $data; - private $levels = null; - private $global_levels = null; - - /** - * Construct a levelset object for an existing database item - * - */ - private function __construct($id = null, $dataObject = null) - { - global $DB; - - $this->id = $id; - if($id != null) - { - if(isset($dataObject) && isset($dataObject->id) && $dataObject->id == $id) // slight sanity check - { - $this->data = $dataObject; - } - else { - // database validity check went south, retrieve again - $this->data = $DB->get_record('block_gradelevel_levelset', array('id' => $this->id)); - } - - //retrieve levels for this levelset - $this->levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $this->id)); - - usort( $this->levels, function( $a, $b) { - return ( $a->points < $b->points ) ? -1 : 1; - } ); - - } - // retrieve global levels - $this->global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0)); - - usort( $this->global_levels, function( $a, $b) { - return ( $a->points < $b->points ) ? -1 : 1; - } ); - - // if no global levels are defined, insert default global levels - if(count($this->global_levels) == 0) - { - foreach(static::GLOBAL_DEFAULTS as $points => $color) - { - // setup default - $row = new stdClass; - $row->levelset_id = 0; - $row->points = $points; - $row->badgecolor = $color; - // insert into db - if(!$DB->insert_record('block_gradelevel_levels',$row)){ - print_error('inserterror', 'block_gradelevel'); - } - - } - - // and reload global levels; - $this->global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0)); - - usort( $this->global_levels, function( $a, $b) { - return ( $a->points < $b->points ) ? -1 : 1; - } ); - - } - - } - - public function getId() : string - { - return $this->id; - } - - public function setName(string $name) - { - $this->data->name = $name; - } - - public function getName() : string - { - return $this->data->name; - } - - public function setIcon(string $iconname) - { - $this->data->icon = $iconname; - } - - public function getIcon() : string - { - $icon = $this->data->icon; - if(empty($icon)) - { - $icon = static::DEFAULT_ICON; - } - return $icon; - } - - - - /** - * Find a levelset for a given course - * - * @params int $course_id The id of the course to find a levelset for - * @return levelset The levelset for this course or null if none found; - */ - static public function find_by_course($course_id) - { - global $DB; - - try { - // FIXME: Make this more efficient by joining it into one sql statement. - $records = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id)); - if(count($records) > 0) - { - $levelset = $DB->get_record('block_gradelevel_levelset', array('id' => array_values($records)[0]->levelset_id)); - if($levelset) - { - return new static($levelset->id,$levelset); - } - } - } - catch(Exception $x){} // catch error if table does not (yet exist) - return null; // return null if no current levelset linked - } - - static public function find_by_id(int $id) - { - global $DB; - - $levelset = $DB->get_record('block_gradelevel_levelset', array('id' => $id)); - if($levelset) - { - return new static($levelset->id,$levelset); - } - else - { - return null; - } - - } - - /** - * List attached courses for this levelset - * - * @return array An array with the id's of attached courses - */ - public function list_courses() - { - global $DB; - $list = array(); - $links = $DB->get_records('block_gradelevel_course_link', array('levelset_id' => $this->id)); - foreach($links as $link) - { - $list[] = $link->course_id; - } - - return $list; - } - - /** - * Attach a course to this levelset. The course will be detached from any other levelsets. - * - * @params int $course_id The id of the course to attach - */ - public function attach_course($course_id) - { - global $DB; - // check if course attachement is already done - if(!in_array($course_id,$this->list_courses)) - { - // no, now find an existing attachment for this course - $rows = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id)); - if(empty($rows)) - { - // create new attachment if existing link was not found - $row = new stdClass; - $row->levelset_id = $this->id; - $row->course_id = $course_id; - // insert new row - if(!$DB->insert_record('block_gradelevel_course_link',$row)){ - print_error('inserterror', 'block_gradelevel'); - } - } - else - { - // update existing link (automatically detaches course from its previous levelset) - $row = array_values($rows)[0]; - - $row->course_id = $course_id; - // update existing row - if(!$DB->update_record('block_gradelevel_course_link',$row)){ - print_error('updateerror', 'block_gradelevel'); - } - } - } - - } - - /** - * Detache a course from this levelset. - * - * @params int $course_id The id of the course to detach - */ - public function detach_course($course_id) - { - global $DB; - $rows = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id, 'levelset_id' => $this->id)); - if(!empty($rows)) - { - if(!$DB->delete_records('block_gradelevel_course_link', array('id' => array_values($rows)[0]->id))) - { - print_error('deleteerror','block_gradelevel'); - } - } - } - - - /** - * Store changes made to the levelset data parameter containing levelset data - * - */ - public function save_data() - { - global $DB; - if($this->data->id == $this->id) // sanity check so we don't kill everything - { - if(!$DB->update_record('block_gradelevel_levelset',$this->data)){ - print_error('updateerror', 'block_gradelevel'); - } - } - else - { - print_error('datarowchanged_error', 'block_gradelevel'); - } - - } - - /** - * Retrieve point total for all attached courses for a given user - * - * @param int $user_id The id - * @return int Total points for this user in this levelset - */ - public function get_levelset_grade($user_id) - { - // loop through all attached courses and add up the grade points gathered - $points = 0; - foreach($this->list_courses() as $course_id) - { - $result = grade_get_course_grade($user_id,$course_id); - $points += $result->grade; - } - return $points; - } - - /** - * Return the levelup data for a given userid in this levelset - * - * @param int $user_id The id - * @return stdClass A stdClass containing the level data for the specified number of point - */ - public function get_user_leveldata($user_id) - { - $points = $this->get_levelset_grade($user_id); - return $this->calculate_level($points); - } - - - - /** - * Create a new levelset - * - * @params string $name Optional name of the new levelset - * @return levelset The new levelset - */ - static public function create_new($name="New levelset") - { - global $DB; - // create a new levelset - - $row = new stdClass; - $row->name = $name; - - if(!$id = $DB->insert_record('block_gradelevel_levelset',$row, true)){ - print_error('inserterror', 'block_gradelevel'); - } - else - { - $rows = $DB->get_records('block_gradelevel_levelset', array('id' => $id)); - if(count($rows) > 0) - { - return new static($id,array_values($rows)[0]); - } - } - - throw new RuntimeException("Could not create new levelset"); - } - - /** - * List all levelsets - * - * @return array Array of levelset - */ - static public function list_all() - { - global $DB; - $list = array(); - $levelsets = $DB->get_records('block_gradelevel_levelset'); - - foreach($levelsets as $lset) - { - $list[] = new static($lset->id,$lset); - } - - return $list; - - } - - /** - * Calculate the levelup data, given a specified set of points - * - * @params int points The amount of points to calculate for - * @return stdClass A stdClass containing the level data for the specified number of point - */ - public function calculate_level($points){ - - $levels = $this->badgelevels(); - - $level = 0; - $badge_color = static::NULL_BADGE_COLOR; - $current_at = 0; - $next_at = 0; - foreach($levels as $threshold => $badgeColor) - { - if($points >= $threshold){ - $level++; - $badge_color = $badgeColor; - $current_at = $threshold; - } - else - { - $next_at = $threshold; - break; - } - } - - $levelup_points = $next_at - $current_at; - $points_in_level = $points - $current_at; - if($levelup_points == 0){ // at max level - $progress = 0; - $points_in_level = 0; - } - else - { - $progress = $points_in_level / $levelup_points; - } - - $result = new stdClass; - $result->level = $level; - $result->badge_color = $badge_color; - $result->progress = $progress; - $result->next_at = $next_at; - $result->levelup_total = $levelup_points; - $result->points_in_level = $points_in_level; - return $result; - } - - /** - * Simplified list of levels and associated badge colors for this levelset - * Takes data from global levelset if more specialized data is not set - * - * @return array An array of points (keys) and badge color (values), sorted by level - */ - public function badgelevels() - { - - $level_info = array(); - - // If we have levels defined, use those, otherwise use the global levels - if(!empty($this->levels)) - { - if(array_values($this->levels)[0]->points > 0) - { - // insert level 0 - $level_info[0] = static::NULL_BADGE_COLOR; - } - - $i = 0; - foreach($this->levels as $lvl) - { - // Check if color is properly set or needs to be retrieved from global config - if(!empty($lvl->badgecolor)) { - $color = $lvl->badgecolor; - } - else - { - $color = static::UNDEFINED_BADGE_COLOR; - } - - $level_info[$lvl->points] = $color; - $i++; - } - - } - else - { - if(empty($this->global_levels) || array_values($this->global_levels)[0]->points > 0) - { - // insert level 1 if levels don't start at 0 points, - // or if no global levels are defined. - At least start somewhere... - $level_info[0] = static::NULL_BADGE_COLOR; - } - - // use global levels if levelset is not defined. - foreach($this->global_levels as $lvl) - { - // Check if color is properly set - if(!empty($lvl->badgecolor)) { - $color = $lvl->badgecolor; - } - else - { - $color = static::UNDEFINED_BADGE_COLOR; - } - $level_info[$lvl->points] = $color; - } - } - - return $level_info; - - } - - public function render_badge(int $points,int $size=150){ - global $CFG; - - $info = $this->calculate_level($points); - - $image = $this->getIcon(); - if(strncmp($image,"data:",5) == 0) - { - $image_url = $CFG->wwwroot."/blocks/gradelevel/view-icon.php?skillid=".$this->id; - } - else - { - $image_url = $image; - } - - $html = "
badgelevels(); - $maxpoints = array_pop(array_keys($levels)); - - return $this->render_badge($maxpoints, $size); - - } - +libdir.'/gradelib.php'); +require_once($CFG->dirroot.'/grade/querylib.php'); + +//namespace block_gradelevel; + +class block_gradelevel_levelset { + const UNDEFINED_BADGE_COLOR="#3F3F3F"; + const NULL_BADGE_COLOR = "#320000"; + const DEFAULT_ICON = "/blocks/gradelevel/pix/undefinedskill.svg"; + + const GLOBAL_DEFAULTS = array( + 0 => "#320000", + 250 => "#2ad4ff", // + 250 + 750 => "#cd7f32", // + 500 + 1750 => "#92A1A6", // + 1000 + 2750 => "#f6ae00", // + 2000 + ); + + private $id; + private $data; + private $levels = null; + private $global_levels = null; + + /** + * Construct a levelset object for an existing database item + * + */ + private function __construct($id = null, $dataObject = null) + { + global $DB; + + $this->id = $id; + if($id != null) + { + if(isset($dataObject) && isset($dataObject->id) && $dataObject->id == $id) // slight sanity check + { + $this->data = $dataObject; + } + else { + // database validity check went south, retrieve again + $this->data = $DB->get_record('block_gradelevel_levelset', array('id' => $this->id)); + } + + //retrieve levels for this levelset + $this->levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $this->id)); + + usort( $this->levels, function( $a, $b) { + return ( $a->points < $b->points ) ? -1 : 1; + } ); + + } + // retrieve global levels + $this->global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0)); + + usort( $this->global_levels, function( $a, $b) { + return ( $a->points < $b->points ) ? -1 : 1; + } ); + + // if no global levels are defined, insert default global levels + if(count($this->global_levels) == 0) + { + foreach(static::GLOBAL_DEFAULTS as $points => $color) + { + // setup default + $row = new stdClass; + $row->levelset_id = 0; + $row->points = $points; + $row->badgecolor = $color; + // insert into db + if(!$DB->insert_record('block_gradelevel_levels',$row)){ + print_error('inserterror', 'block_gradelevel'); + } + + } + + // and reload global levels; + $this->global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0)); + + usort( $this->global_levels, function( $a, $b) { + return ( $a->points < $b->points ) ? -1 : 1; + } ); + + } + + } + + public function getId() : string + { + return $this->id; + } + + public function setName(string $name) + { + $this->data->name = $name; + } + + public function getName() : string + { + return $this->data->name; + } + + public function setIcon(string $iconname) + { + $this->data->icon = $iconname; + } + + public function getIcon() : string + { + $icon = $this->data->icon; + if(empty($icon)) + { + $icon = static::DEFAULT_ICON; + } + return $icon; + } + + + + /** + * Find a levelset for a given course + * + * @params int $course_id The id of the course to find a levelset for + * @return levelset The levelset for this course or null if none found; + */ + static public function find_by_course($course_id) + { + global $DB; + + try { + // FIXME: Make this more efficient by joining it into one sql statement. + $records = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id)); + if(count($records) > 0) + { + $levelset = $DB->get_record('block_gradelevel_levelset', array('id' => array_values($records)[0]->levelset_id)); + if($levelset) + { + return new static($levelset->id,$levelset); + } + } + } + catch(Exception $x){} // catch error if table does not (yet exist) + return null; // return null if no current levelset linked + } + + static public function find_by_id(int $id) + { + global $DB; + + $levelset = $DB->get_record('block_gradelevel_levelset', array('id' => $id)); + if($levelset) + { + return new static($levelset->id,$levelset); + } + else + { + return null; + } + + } + + /** + * List attached courses for this levelset + * + * @return array An array with the id's of attached courses + */ + public function list_courses() + { + global $DB; + $list = array(); + $links = $DB->get_records('block_gradelevel_course_link', array('levelset_id' => $this->id)); + foreach($links as $link) + { + $list[] = $link->course_id; + } + + return $list; + } + + /** + * Attach a course to this levelset. The course will be detached from any other levelsets. + * + * @params int $course_id The id of the course to attach + */ + public function attach_course($course_id) + { + global $DB; + // check if course attachement is already done + if(!in_array($course_id,$this->list_courses)) + { + // no, now find an existing attachment for this course + $rows = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id)); + if(empty($rows)) + { + // create new attachment if existing link was not found + $row = new stdClass; + $row->levelset_id = $this->id; + $row->course_id = $course_id; + // insert new row + if(!$DB->insert_record('block_gradelevel_course_link',$row)){ + print_error('inserterror', 'block_gradelevel'); + } + } + else + { + // update existing link (automatically detaches course from its previous levelset) + $row = array_values($rows)[0]; + + $row->course_id = $course_id; + // update existing row + if(!$DB->update_record('block_gradelevel_course_link',$row)){ + print_error('updateerror', 'block_gradelevel'); + } + } + } + + } + + /** + * Detache a course from this levelset. + * + * @params int $course_id The id of the course to detach + */ + public function detach_course($course_id) + { + global $DB; + $rows = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id, 'levelset_id' => $this->id)); + if(!empty($rows)) + { + if(!$DB->delete_records('block_gradelevel_course_link', array('id' => array_values($rows)[0]->id))) + { + print_error('deleteerror','block_gradelevel'); + } + } + } + + + /** + * Store changes made to the levelset data parameter containing levelset data + * + */ + public function save_data() + { + global $DB; + if($this->data->id == $this->id) // sanity check so we don't kill everything + { + if(!$DB->update_record('block_gradelevel_levelset',$this->data)){ + print_error('updateerror', 'block_gradelevel'); + } + } + else + { + print_error('datarowchanged_error', 'block_gradelevel'); + } + + } + + /** + * Retrieve point total for all attached courses for a given user + * + * @param int $user_id The id + * @return int Total points for this user in this levelset + */ + public function get_levelset_grade($user_id) + { + // loop through all attached courses and add up the grade points gathered + $points = 0; + foreach($this->list_courses() as $course_id) + { + $result = grade_get_course_grade($user_id,$course_id); + $points += $result->grade; + } + return $points; + } + + /** + * Return the levelup data for a given userid in this levelset + * + * @param int $user_id The id + * @return stdClass A stdClass containing the level data for the specified number of point + */ + public function get_user_leveldata($user_id) + { + $points = $this->get_levelset_grade($user_id); + return $this->calculate_level($points); + } + + + + /** + * Create a new levelset + * + * @params string $name Optional name of the new levelset + * @return levelset The new levelset + */ + static public function create_new($name="New levelset") + { + global $DB; + // create a new levelset + + $row = new stdClass; + $row->name = $name; + + if(!$id = $DB->insert_record('block_gradelevel_levelset',$row, true)){ + print_error('inserterror', 'block_gradelevel'); + } + else + { + $rows = $DB->get_records('block_gradelevel_levelset', array('id' => $id)); + if(count($rows) > 0) + { + return new static($id,array_values($rows)[0]); + } + } + + throw new RuntimeException("Could not create new levelset"); + } + + /** + * List all levelsets + * + * @return array Array of levelset + */ + static public function list_all() + { + global $DB; + $list = array(); + $levelsets = $DB->get_records('block_gradelevel_levelset'); + + foreach($levelsets as $lset) + { + $list[] = new static($lset->id,$lset); + } + + return $list; + + } + + /** + * Calculate the levelup data, given a specified set of points + * + * @params int points The amount of points to calculate for + * @return stdClass A stdClass containing the level data for the specified number of point + */ + public function calculate_level($points){ + + $levels = $this->badgelevels(); + + $level = 0; + $badge_color = static::NULL_BADGE_COLOR; + $current_at = 0; + $next_at = 0; + foreach($levels as $threshold => $badgeColor) + { + if($points >= $threshold){ + $level++; + $badge_color = $badgeColor; + $current_at = $threshold; + } + else + { + $next_at = $threshold; + break; + } + } + + $levelup_points = $next_at - $current_at; + $points_in_level = $points - $current_at; + if($levelup_points == 0){ // at max level + $progress = 0; + $points_in_level = 0; + } + else + { + $progress = $points_in_level / $levelup_points; + } + + $result = new stdClass; + $result->level = $level; + $result->badge_color = $badge_color; + $result->progress = $progress; + $result->next_at = $next_at; + $result->levelup_total = $levelup_points; + $result->points_in_level = $points_in_level; + return $result; + } + + /** + * Simplified list of levels and associated badge colors for this levelset + * Takes data from global levelset if more specialized data is not set + * + * @return array An array of points (keys) and badge color (values), sorted by level + */ + public function badgelevels() + { + + $level_info = array(); + + // If we have levels defined, use those, otherwise use the global levels + if(!empty($this->levels)) + { + if(array_values($this->levels)[0]->points > 0) + { + // insert level 0 + $level_info[0] = static::NULL_BADGE_COLOR; + } + + $i = 0; + foreach($this->levels as $lvl) + { + // Check if color is properly set or needs to be retrieved from global config + if(!empty($lvl->badgecolor)) { + $color = $lvl->badgecolor; + } + else + { + $color = static::UNDEFINED_BADGE_COLOR; + } + + $level_info[$lvl->points] = $color; + $i++; + } + + } + else + { + if(empty($this->global_levels) || array_values($this->global_levels)[0]->points > 0) + { + // insert level 1 if levels don't start at 0 points, + // or if no global levels are defined. - At least start somewhere... + $level_info[0] = static::NULL_BADGE_COLOR; + } + + // use global levels if levelset is not defined. + foreach($this->global_levels as $lvl) + { + // Check if color is properly set + if(!empty($lvl->badgecolor)) { + $color = $lvl->badgecolor; + } + else + { + $color = static::UNDEFINED_BADGE_COLOR; + } + $level_info[$lvl->points] = $color; + } + } + + return $level_info; + + } + + public function render_badge(int $points,int $size=150){ + global $CFG; + + $info = $this->calculate_level($points); + + $image = $this->getIcon(); + if(strncmp($image,"data:",5) == 0) + { + $image_url = $CFG->wwwroot."/blocks/gradelevel/view-icon.php?skillid=".$this->id; + } + else + { + $image_url = $image; + } + + $html = "
badgelevels(); + $maxpoints = array_pop(array_keys($levels)); + + return $this->render_badge($maxpoints, $size); + + } + } \ No newline at end of file diff --git a/classes/skillmgmtservice.php b/classes/skillmgmtservice.php index 7ef35c0..401b221 100644 --- a/classes/skillmgmtservice.php +++ b/classes/skillmgmtservice.php @@ -1,473 +1,473 @@ -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 = "
    "; - foreach($skills as $skill) - { - $s .= static::single_skill_editor_item($skill); - } - - $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 = "
    "; - $s .= static::single_skill_editor_item($skill,true); - $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; - } - +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 = "
      "; + foreach($skills as $skill) + { + $s .= static::single_skill_editor_item($skill); + } + + $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 = "
      "; + $s .= static::single_skill_editor_item($skill,true); + $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; + } + } \ No newline at end of file diff --git a/db/access.php b/db/access.php index f93e569..4b61ef2 100644 --- a/db/access.php +++ b/db/access.php @@ -1,49 +1,49 @@ - array( - 'captype' => 'write', - 'contextlevel' => CONTEXT_SYSTEM, - 'archetypes' => array( - 'user' => CAP_ALLOW - ), - - 'clonepermissionsfrom' => 'moodle/my:manageblocks' - ), - - 'block/gradelevel:addinstance' => array( - 'riskbitmask' => RISK_SPAM | RISK_XSS, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_BLOCK, - 'archetypes' => array( - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ), - - 'clonepermissionsfrom' => 'moodle/site:manageblocks' - ), - - 'block/gradelevel:skillmanager' => array( - 'riskbitmask' => RISK_CONFIG | RISK_DATALOSS | RISK_XSS, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_SYSTEM, - 'archetypes' => array( - 'manager' => CAP_ALLOW - ), - ), - - 'block/gradelevel:viewresults' => array( - 'riskbitmask' => RISK_DATALOSS | RISK_XSS, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_BLOCK, - 'archetypes' => array( - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ), - - ), - + array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + 'user' => CAP_ALLOW + ), + + 'clonepermissionsfrom' => 'moodle/my:manageblocks' + ), + + 'block/gradelevel:addinstance' => array( + 'riskbitmask' => RISK_SPAM | RISK_XSS, + + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => array( + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ), + + 'clonepermissionsfrom' => 'moodle/site:manageblocks' + ), + + 'block/gradelevel:skillmanager' => array( + 'riskbitmask' => RISK_CONFIG | RISK_DATALOSS | RISK_XSS, + + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + 'manager' => CAP_ALLOW + ), + ), + + 'block/gradelevel:viewresults' => array( + 'riskbitmask' => RISK_DATALOSS | RISK_XSS, + + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => array( + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ), + + ), + ); \ No newline at end of file diff --git a/db/install.xml b/db/install.xml index 8924ab4..4164451 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,44 +1,44 @@ - - - - - - - - - - - - - - -
    - - - - - - - - - - - -
    - - - - - - - - - - - -
    -
    + + + + + + + + + + + + + + +
    + + + + + + + + + + + +
    + + + + + + + + + + + +
    +
    \ No newline at end of file diff --git a/db/services.php b/db/services.php index b9cdef4..ecf3fb4 100644 --- a/db/services.php +++ b/db/services.php @@ -1,93 +1,93 @@ - array( - 'functions' => array('block_gradelevel_submit_levels', 'block_gradelevel_list_levels'), - 'requiredcapability' => 'block/gradelevel:changelevels', - 'shortname'=> 'block_gradelevel_levelmgmt', - 'restrictedusers' => 0, - 'enabled' => 0, - 'ajax' => true, - ), -); - -$functions = array( - 'block_gradelevel_submit_levels' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'submit_levels', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'Update level settings for a given skill', //human readable description of the web service function - 'type' => 'write', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - 'block_gradelevel_list_levels' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'list_levels', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'List level settings for a given skill', //human readable description of the web service function - 'type' => 'read', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - 'block_gradelevel_list_skills' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'list_skills', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'List skills', //human readable description of the web service function - 'type' => 'read', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - 'block_gradelevel_get_skill' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'get_skill', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'Retrieve skill information', //human readable description of the web service function - 'type' => 'read', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - 'block_gradelevel_update_skill' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'update_skill', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'Update a skill', //human readable description of the web service function - 'type' => 'read', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - 'block_gradelevel_add_skill' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'add_skill', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'Add a new skill', //human readable description of the web service function - 'type' => 'read', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - 'block_gradelevel_delete_skill' => array( //web service function name - 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function - 'methodname' => 'delete_skill', //external function name - 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function - 'description' => 'Delete a skill', //human readable description of the web service function - 'type' => 'read', //database rights of the web service function (read, write) - 'ajax' => true, - 'capabilities' => 'block/gradelevel:skillmanager', - 'loginrequired' => true, - 'services' => array('block_gradelevel_levelmgmt'), - ), - -); + array( + 'functions' => array('block_gradelevel_submit_levels', 'block_gradelevel_list_levels'), + 'requiredcapability' => 'block/gradelevel:changelevels', + 'shortname'=> 'block_gradelevel_levelmgmt', + 'restrictedusers' => 0, + 'enabled' => 0, + 'ajax' => true, + ), +); + +$functions = array( + 'block_gradelevel_submit_levels' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'submit_levels', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'Update level settings for a given skill', //human readable description of the web service function + 'type' => 'write', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + 'block_gradelevel_list_levels' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'list_levels', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'List level settings for a given skill', //human readable description of the web service function + 'type' => 'read', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + 'block_gradelevel_list_skills' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'list_skills', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'List skills', //human readable description of the web service function + 'type' => 'read', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + 'block_gradelevel_get_skill' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'get_skill', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'Retrieve skill information', //human readable description of the web service function + 'type' => 'read', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + 'block_gradelevel_update_skill' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'update_skill', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'Update a skill', //human readable description of the web service function + 'type' => 'read', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + 'block_gradelevel_add_skill' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'add_skill', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'Add a new skill', //human readable description of the web service function + 'type' => 'read', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + 'block_gradelevel_delete_skill' => array( //web service function name + 'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function + 'methodname' => 'delete_skill', //external function name + 'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function + 'description' => 'Delete a skill', //human readable description of the web service function + 'type' => 'read', //database rights of the web service function (read, write) + 'ajax' => true, + 'capabilities' => 'block/gradelevel:skillmanager', + 'loginrequired' => true, + 'services' => array('block_gradelevel_levelmgmt'), + ), + +); diff --git a/db/upgrade.php b/db/upgrade.php index e043fec..e5069f2 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,70 +1,70 @@ -get_manager(); - - /// Add a new column newcol to the mdl_myqtype_options - if ($oldversion < 2018091600) { - - // Define table block_gradelevel_levelset to be created. - $table = new xmldb_table('block_gradelevel_levelset'); - - // Adding fields to table block_gradelevel_levelset. - $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); - $table->add_field('name', XMLDB_TYPE_CHAR, '128', null, null, null, null); - $table->add_field('parent_id', XMLDB_TYPE_INTEGER, '10', null, null, null, null); - $table->add_field('icon', XMLDB_TYPE_TEXT, null, null, null, null, null); - - - // Adding keys to table block_gradelevel_levelset. - $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); - $table->add_key('parent_id_idx', XMLDB_KEY_FOREIGN, array('parent_id'), 'block_gradelevel_levelset', array('id')); - - // Conditionally launch create table for block_gradelevel_levelset. - if (!$dbman->table_exists($table)) { - $dbman->create_table($table); - } - - // Define table block_gradelevel_levels to be created. - $table = new xmldb_table('block_gradelevel_levels'); - - // Adding fields to table block_gradelevel_levels. - $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); - $table->add_field('levelset_id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); - $table->add_field('points', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - $table->add_field('badgecolor', XMLDB_TYPE_CHAR, '10', null, null, null, null); - - // Adding keys to table block_gradelevel_levels. - $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); - $table->add_key('levelset_id_idx', XMLDB_KEY_FOREIGN, array('levelset_id'), 'block_gradelevel_levelset', array('id')); - - // Conditionally launch create table for block_gradelevel_levels. - if (!$dbman->table_exists($table)) { - $dbman->create_table($table); - } - - // Define table block_gradelevel_course_link to be created. - $table = new xmldb_table('block_gradelevel_course_link'); - - // Adding fields to table block_gradelevel_course_link. - $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); - $table->add_field('course_id', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null); - $table->add_field('levelset_id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); - - // Adding keys to table block_gradelevel_course_link. - $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); - $table->add_key('course_id_idx', XMLDB_KEY_FOREIGN_UNIQUE, array('course_id'), 'mdl_course', array('id')); - $table->add_key('levelset_id_idx', XMLDB_KEY_FOREIGN, array('levelset_id'), 'block_gradelevel_levelset', array('id')); - - // Conditionally launch create table for block_gradelevel_course_link. - if (!$dbman->table_exists($table)) { - $dbman->create_table($table); - } - - // Gradelevel savepoint reached. - upgrade_block_savepoint(true, 2018091600, 'gradelevel'); - - } - - return true; +get_manager(); + + /// Add a new column newcol to the mdl_myqtype_options + if ($oldversion < 2018091600) { + + // Define table block_gradelevel_levelset to be created. + $table = new xmldb_table('block_gradelevel_levelset'); + + // Adding fields to table block_gradelevel_levelset. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('name', XMLDB_TYPE_CHAR, '128', null, null, null, null); + $table->add_field('parent_id', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + $table->add_field('icon', XMLDB_TYPE_TEXT, null, null, null, null, null); + + + // Adding keys to table block_gradelevel_levelset. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('parent_id_idx', XMLDB_KEY_FOREIGN, array('parent_id'), 'block_gradelevel_levelset', array('id')); + + // Conditionally launch create table for block_gradelevel_levelset. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Define table block_gradelevel_levels to be created. + $table = new xmldb_table('block_gradelevel_levels'); + + // Adding fields to table block_gradelevel_levels. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('levelset_id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('points', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('badgecolor', XMLDB_TYPE_CHAR, '10', null, null, null, null); + + // Adding keys to table block_gradelevel_levels. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('levelset_id_idx', XMLDB_KEY_FOREIGN, array('levelset_id'), 'block_gradelevel_levelset', array('id')); + + // Conditionally launch create table for block_gradelevel_levels. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Define table block_gradelevel_course_link to be created. + $table = new xmldb_table('block_gradelevel_course_link'); + + // Adding fields to table block_gradelevel_course_link. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('course_id', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null); + $table->add_field('levelset_id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table block_gradelevel_course_link. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('course_id_idx', XMLDB_KEY_FOREIGN_UNIQUE, array('course_id'), 'mdl_course', array('id')); + $table->add_key('levelset_id_idx', XMLDB_KEY_FOREIGN, array('levelset_id'), 'block_gradelevel_levelset', array('id')); + + // Conditionally launch create table for block_gradelevel_course_link. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Gradelevel savepoint reached. + upgrade_block_savepoint(true, 2018091600, 'gradelevel'); + + } + + return true; } \ No newline at end of file diff --git a/doc_USER_GRADE.txt b/doc_USER_GRADE.txt index 1877541..a6b6084 100644 --- a/doc_USER_GRADE.txt +++ b/doc_USER_GRADE.txt @@ -1,184 +1,184 @@ - USER: stdClass Object -( - [id] => 2 - [auth] => manual - [confirmed] => 1 - [policyagreed] => 0 - [deleted] => 0 - [suspended] => 0 - [mnethostid] => 1 - [username] => admin - [idnumber] => - [firstname] => Admin - [lastname] => User - [email] => pm@miqra.nl - [emailstop] => 0 - [icq] => - [skype] => - [yahoo] => - [aim] => - [msn] => - [phone1] => - [phone2] => - [institution] => - [department] => - [address] => - [city] => - [country] => - [lang] => en - [calendartype] => gregorian - [theme] => - [timezone] => 99 - [firstaccess] => 1530717879 - [lastaccess] => 1536959033 - [lastlogin] => 1530732921 - [currentlogin] => 1536953353 - [lastip] => 2001:985:a081:1:5dfc:c799:21e1:4fdc - [secret] => - [picture] => 0 - [url] => - [descriptionformat] => 1 - [mailformat] => 1 - [maildigest] => 0 - [maildisplay] => 1 - [autosubscribe] => 1 - [trackforums] => 0 - [timecreated] => 0 - [timemodified] => 1530717931 - [trustbitmask] => 0 - [imagealt] => - [lastnamephonetic] => - [firstnamephonetic] => - [middlename] => - [alternatename] => - [lastcourseaccess] => Array - ( - [2] => 1530738819 - ) - - [currentcourseaccess] => Array - ( - [2] => 1536959033 - ) - - [groupmember] => Array - ( - ) - - [profile] => Array - ( - ) - - [sesskey] => ejGT6VqIBv - [ajax_updatable_user_prefs] => Array - ( - [drawer-open-nav] => alpha - [filepicker_recentrepository] => int - [filepicker_recentlicense] => safedir - [filepicker_recentviewmode] => int - [filemanager_recentviewmode] => int - ) - - [editing] => 1 - [preference] => Array - ( - [core_message_migrate_data] => 1 - [auth_manual_passwordupdatetime] => 1530717931 - [email_bounce_count] => 1 - [email_send_count] => 1 - [filepicker_recentrepository] => 4 - [filepicker_recentlicense] => allrightsreserved - [login_failed_count_since_success] => 6 - [ifirst] => - [ilast] => - [_lastloaded] => 1536959033 - ) - - [enrol] => Array - ( - [enrolled] => Array - ( - [2] => 2147483647 - ) - - [tempguest] => Array - ( - ) - - ) - - [grade_last_report] => Array - ( - [2] => grader - ) - - [gradeediting] => Array - ( - [2] => 0 - ) - - [access] => Array - ( - [ra] => Array - ( - [/1] => Array - ( - [7] => 7 - ) - - [/1/2] => Array - ( - [8] => 8 - ) - - [/1/40/23] => Array - ( - [3] => 3 - [5] => 5 - ) - - ) - - [time] => 1536958657 - [rsw] => Array - ( - ) - - ) - -) - -COURSE: stdClass Object -( - [id] => 2 - [category] => 2 - [sortorder] => 20001 - [fullname] => PIC Microcontrollers programmeren - [shortname] => PIC-MCU3 - [idnumber] => - [summary] => Programmeren van PIC18 microcontrollers van microchip. - [summaryformat] => 1 - [format] => topics - [showgrades] => 1 - [newsitems] => 0 - [startdate] => 1526594400 - [enddate] => 0 - [marker] => 0 - [maxbytes] => 0 - [legacyfiles] => 0 - [showreports] => 0 - [visible] => 1 - [visibleold] => 1 - [groupmode] => 0 - [groupmodeforce] => 0 - [defaultgroupingid] => 0 - [lang] => - [calendartype] => - [theme] => - [timecreated] => 1526555879 - [timemodified] => 1536956992 - [requested] => 0 - [enablecompletion] => 1 - [completionnotify] => 0 - [cacherev] => 1536956992 -) + USER: stdClass Object +( + [id] => 2 + [auth] => manual + [confirmed] => 1 + [policyagreed] => 0 + [deleted] => 0 + [suspended] => 0 + [mnethostid] => 1 + [username] => admin + [idnumber] => + [firstname] => Admin + [lastname] => User + [email] => pm@miqra.nl + [emailstop] => 0 + [icq] => + [skype] => + [yahoo] => + [aim] => + [msn] => + [phone1] => + [phone2] => + [institution] => + [department] => + [address] => + [city] => + [country] => + [lang] => en + [calendartype] => gregorian + [theme] => + [timezone] => 99 + [firstaccess] => 1530717879 + [lastaccess] => 1536959033 + [lastlogin] => 1530732921 + [currentlogin] => 1536953353 + [lastip] => 2001:985:a081:1:5dfc:c799:21e1:4fdc + [secret] => + [picture] => 0 + [url] => + [descriptionformat] => 1 + [mailformat] => 1 + [maildigest] => 0 + [maildisplay] => 1 + [autosubscribe] => 1 + [trackforums] => 0 + [timecreated] => 0 + [timemodified] => 1530717931 + [trustbitmask] => 0 + [imagealt] => + [lastnamephonetic] => + [firstnamephonetic] => + [middlename] => + [alternatename] => + [lastcourseaccess] => Array + ( + [2] => 1530738819 + ) + + [currentcourseaccess] => Array + ( + [2] => 1536959033 + ) + + [groupmember] => Array + ( + ) + + [profile] => Array + ( + ) + + [sesskey] => ejGT6VqIBv + [ajax_updatable_user_prefs] => Array + ( + [drawer-open-nav] => alpha + [filepicker_recentrepository] => int + [filepicker_recentlicense] => safedir + [filepicker_recentviewmode] => int + [filemanager_recentviewmode] => int + ) + + [editing] => 1 + [preference] => Array + ( + [core_message_migrate_data] => 1 + [auth_manual_passwordupdatetime] => 1530717931 + [email_bounce_count] => 1 + [email_send_count] => 1 + [filepicker_recentrepository] => 4 + [filepicker_recentlicense] => allrightsreserved + [login_failed_count_since_success] => 6 + [ifirst] => + [ilast] => + [_lastloaded] => 1536959033 + ) + + [enrol] => Array + ( + [enrolled] => Array + ( + [2] => 2147483647 + ) + + [tempguest] => Array + ( + ) + + ) + + [grade_last_report] => Array + ( + [2] => grader + ) + + [gradeediting] => Array + ( + [2] => 0 + ) + + [access] => Array + ( + [ra] => Array + ( + [/1] => Array + ( + [7] => 7 + ) + + [/1/2] => Array + ( + [8] => 8 + ) + + [/1/40/23] => Array + ( + [3] => 3 + [5] => 5 + ) + + ) + + [time] => 1536958657 + [rsw] => Array + ( + ) + + ) + +) + +COURSE: stdClass Object +( + [id] => 2 + [category] => 2 + [sortorder] => 20001 + [fullname] => PIC Microcontrollers programmeren + [shortname] => PIC-MCU3 + [idnumber] => + [summary] => Programmeren van PIC18 microcontrollers van microchip. + [summaryformat] => 1 + [format] => topics + [showgrades] => 1 + [newsitems] => 0 + [startdate] => 1526594400 + [enddate] => 0 + [marker] => 0 + [maxbytes] => 0 + [legacyfiles] => 0 + [showreports] => 0 + [visible] => 1 + [visibleold] => 1 + [groupmode] => 0 + [groupmodeforce] => 0 + [defaultgroupingid] => 0 + [lang] => + [calendartype] => + [theme] => + [timecreated] => 1526555879 + [timemodified] => 1536956992 + [requested] => 0 + [enablecompletion] => 1 + [completionnotify] => 0 + [cacherev] => 1536956992 +) diff --git a/edit_form.php b/edit_form.php index 18a06b0..9391192 100644 --- a/edit_form.php +++ b/edit_form.php @@ -1,82 +1,82 @@ -dirroot.'/blocks/gradelevel/lib.php'); - -class block_gradelevel_edit_form extends block_edit_form { - - - protected function specific_definition($mform) { - global $CFG; - // retrieve levelset - $levelset = $this->block->levelset; - - // Section header title according to language file. - $mform->addElement('header', 'config_header', get_string('blocksettings', 'block')); - - $skills = block_gradelevel_levelset::list_all(); - // sort by name - usort( $skills, function( $a, $b) { - return ( $a->getName() < $b->getName()) ? -1 : 1; - } ); - - $options = array( '-1' => get_string('edit_noneskill', 'block_gradelevel')); - foreach($skills as $skill) - { - $options[$skill->getId()] = $skill->getName(); - } - - // A sample string variable with a default value. - $mform->addElement('select', 'attached_skill', get_string('edit_pickskill', 'block_gradelevel'), $options); - - - } - - public function set_data($defaults) - { - global $COURSE; - - $defaults->attached_skill = -1; - // retrieve levelset - $skill = block_gradelevel_levelset::find_by_course($COURSE->id); - if(isset($skill)){ - $defaults->attached_skill = $skill->getId(); - } - - - parent::set_data($defaults); - } - - - public function get_data() - { - $data = parent::get_data(); - - if(isset($data)) - { - $this->save_data($data); - } - - return $data; - } - - protected function save_data($data) - { - global $COURSE; - // retrieve levelset - - if(isset($data->attached_skill)) - { - $currentskill = block_gradelevel_levelset::find_by_course($COURSE->id); - if(isset($currentskill)) - { - $currentskill->detach_course($COURSE->id); - } - - $skill = block_gradelevel_levelset::find_by_id($data->attached_skill); - if(isset($skill)){ - $skill->attach_course($COURSE->id); - } - } - } - +dirroot.'/blocks/gradelevel/lib.php'); + +class block_gradelevel_edit_form extends block_edit_form { + + + protected function specific_definition($mform) { + global $CFG; + // retrieve levelset + $levelset = $this->block->levelset; + + // Section header title according to language file. + $mform->addElement('header', 'config_header', get_string('blocksettings', 'block')); + + $skills = block_gradelevel_levelset::list_all(); + // sort by name + usort( $skills, function( $a, $b) { + return ( $a->getName() < $b->getName()) ? -1 : 1; + } ); + + $options = array( '-1' => get_string('edit_noneskill', 'block_gradelevel')); + foreach($skills as $skill) + { + $options[$skill->getId()] = $skill->getName(); + } + + // A sample string variable with a default value. + $mform->addElement('select', 'attached_skill', get_string('edit_pickskill', 'block_gradelevel'), $options); + + + } + + public function set_data($defaults) + { + global $COURSE; + + $defaults->attached_skill = -1; + // retrieve levelset + $skill = block_gradelevel_levelset::find_by_course($COURSE->id); + if(isset($skill)){ + $defaults->attached_skill = $skill->getId(); + } + + + parent::set_data($defaults); + } + + + public function get_data() + { + $data = parent::get_data(); + + if(isset($data)) + { + $this->save_data($data); + } + + return $data; + } + + protected function save_data($data) + { + global $COURSE; + // retrieve levelset + + if(isset($data->attached_skill)) + { + $currentskill = block_gradelevel_levelset::find_by_course($COURSE->id); + if(isset($currentskill)) + { + $currentskill->detach_course($COURSE->id); + } + + $skill = block_gradelevel_levelset::find_by_id($data->attached_skill); + if(isset($skill)){ + $skill->attach_course($COURSE->id); + } + } + } + } \ No newline at end of file diff --git a/lang/en/block_gradelevel.php b/lang/en/block_gradelevel.php index 79122b9..fef09e4 100644 --- a/lang/en/block_gradelevel.php +++ b/lang/en/block_gradelevel.php @@ -1,54 +1,54 @@ -libdir.'/gradelib.php'); -require_once($CFG->dirroot.'/grade/querylib.php'); - +libdir.'/gradelib.php'); +require_once($CFG->dirroot.'/grade/querylib.php'); + diff --git a/package-lock.json b/package-lock.json index 48e341a..5a05955 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3 +1,3 @@ -{ - "lockfileVersion": 1 -} +{ + "lockfileVersion": 1 +} diff --git a/pix/undefinedskill.svg b/pix/undefinedskill.svg index ae44c4e..01dd950 100644 --- a/pix/undefinedskill.svg +++ b/pix/undefinedskill.svg @@ -1,772 +1,772 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - M - - - - - FZ - - - - - M - - - - - FZ - - S - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + M + + + + + FZ + + + + + M + + + + + FZ + + S + + + diff --git a/settings.php b/settings.php index 17b7ee7..d4f01a2 100644 --- a/settings.php +++ b/settings.php @@ -1,40 +1,40 @@ -add('blocksettings', new admin_category('block_gradelevel', get_string('cfgpage_generic', 'block_gradelevel'))); - - -$settings->add(new admin_setting_configcheckbox( - 'gradelevel/showtitle', - get_string('labelshowtitle', 'block_gradelevel'), - get_string('descshowtitle', 'block_gradelevel'), - true - )); - -$settings->add(new admin_setting_configtext( - 'gradelevel/blocktitle', - get_string('labeltitle', 'block_gradelevel'), - get_string('desctitle', 'block_gradelevel'), - get_string('title', 'block_gradelevel') - )); - - -$ADMIN->add("block_gradelevel", $settings); - -// Add the default levels page -$ADMIN->add("block_gradelevel", new admin_externalpage( - 'block_gradelevel_default_levels', - get_string('cfgpage_globallevels', 'block_gradelevel'), - $CFG->wwwroot . '/blocks/gradelevel/cfg_globallevels.php' - ) - ); - -// Add the skill configpage -$ADMIN->add("block_gradelevel", new admin_externalpage( - 'block_gradelevel_config_skills', - get_string('cfgpage_skills', 'block_gradelevel'), - $CFG->wwwroot . '/blocks/gradelevel/cfg_skills.php' - ) - ); - - +add('blocksettings', new admin_category('block_gradelevel', get_string('cfgpage_generic', 'block_gradelevel'))); + + +$settings->add(new admin_setting_configcheckbox( + 'gradelevel/showtitle', + get_string('labelshowtitle', 'block_gradelevel'), + get_string('descshowtitle', 'block_gradelevel'), + true + )); + +$settings->add(new admin_setting_configtext( + 'gradelevel/blocktitle', + get_string('labeltitle', 'block_gradelevel'), + get_string('desctitle', 'block_gradelevel'), + get_string('title', 'block_gradelevel') + )); + + +$ADMIN->add("block_gradelevel", $settings); + +// Add the default levels page +$ADMIN->add("block_gradelevel", new admin_externalpage( + 'block_gradelevel_default_levels', + get_string('cfgpage_globallevels', 'block_gradelevel'), + $CFG->wwwroot . '/blocks/gradelevel/cfg_globallevels.php' + ) + ); + +// Add the skill configpage +$ADMIN->add("block_gradelevel", new admin_externalpage( + 'block_gradelevel_config_skills', + get_string('cfgpage_skills', 'block_gradelevel'), + $CFG->wwwroot . '/blocks/gradelevel/cfg_skills.php' + ) + ); + + $settings = null; \ No newline at end of file diff --git a/styles.css b/styles.css index 732ce46..490c2df 100644 --- a/styles.css +++ b/styles.css @@ -1,145 +1,145 @@ -figure.levelbadge, figure.dummybadge { - text-align: center; -} - -div.pointinfo { - text-align: center; - font-family: "Open Sans", Arial, helvetica, sans-serif; -} - -div.pointinfo.complete { - font-weight: bold; -} - -div.pointinfo span.currentpoints { - font-weight: bold; -} - -div.pointinfo span.leveluppoints { - font-weight: bold; -} - -div.teachermode { - text-align: center; -} - -td.block_gradelevel_addlevel { - text-align: right; - -} -input.jscolor[type=text] { - width: 5em; -} - - -div.skill_set ul { - padding-left: 0px; - margin-left: 0px; -} - -div.skill_set li.skill_info { - position: relative; /* needed to have absolute positions be relative to this li */ - list-style: none; - display: inline-block; - width: 220px; - height: 220px; - border-color: #ccc; - border-width: 1px; - border-style: solid; - margin: 5px; - padding: 5px; - padding-top: 10px; -} - - -div.skill_set li.skill_info figcaption { - text-align: center; -} - -div.skill_set li.skill_info input[type=text] { - width: 150px; -} - -div.skill_set li.skill_info a.editicon { - position: absolute; - top: 5px; - right: 10px; -} - -div.skill_set li.skill_info a.deleteskill { - position: absolute; - top: 5px; - left: 7px; -} -div.skill_set li.skill_info a.deleteskill i.icon { - color: red; -} - -div.skill_set li.skill_info a.deleteskill i.icon.disabled { - color: #ccc; -} - -div.skill_set li.skill_info a.editname { - margin-left: 5px; -} - -table.level_config tr[data-rowid='-255'] { -} - -table.level_config tr[data-rowid='-255'] td { - -} - -table.level_config tr[data-rowid='-255'] input[data-name='points'] { - background-color: #F0F0F0; -} - -div.block_gradelevel_results ul { - padding-left: 0px; - margin-left: 0px; -} - -div .block_gradelevel_results li.result_badge { - position: relative; /* needed to have absolute positions be relative to this li */ - list-style: none; - display: inline-block; - width: 190px; - height: 210px; - border-color: #ccc; - border-width: 1px; - border-style: solid; - margin: 5px; - padding: 5px; - padding-top: 10px; -} - - -div.block_gradelevel_results li.result_badge figcaption { - text-align: center; - height: 3em; - margin-bottom: 0.5rem; -} - -div.block_gradelevel_results li.result_badge div.pointinfo { - font-size: 85%; -} - -div.block_gradelevel_results li.result_badge figcaption span.namepart { - break-inside: avoid; - display: inline-block; -} - -div.block_gradelevel_results figure.levelset_icon { - margin-bottom: 0.5rem; -} - -figure.levelset_icon { - background-color: #ccc; - background-image: -moz-linear-gradient(45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(-45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #aaa 75%), -moz-linear-gradient(-45deg, transparent 75%, #aaa 75%); - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #aaa), color-stop(.25, transparent)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #aaa), color-stop(.25, transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #aaa)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #aaa)); - -moz-background-size: 32px 32px; - background-size: 32px 33px; - -webkit-background-size: 32px 33px; /* override value for shitty webkit */ - background-position: 0 0, 16px 0, 16px -16px, 0px 16px; - display: inline-block; +figure.levelbadge, figure.dummybadge { + text-align: center; +} + +div.pointinfo { + text-align: center; + font-family: "Open Sans", Arial, helvetica, sans-serif; +} + +div.pointinfo.complete { + font-weight: bold; +} + +div.pointinfo span.currentpoints { + font-weight: bold; +} + +div.pointinfo span.leveluppoints { + font-weight: bold; +} + +div.teachermode { + text-align: center; +} + +td.block_gradelevel_addlevel { + text-align: right; + +} +input.jscolor[type=text] { + width: 5em; +} + + +div.skill_set ul { + padding-left: 0px; + margin-left: 0px; +} + +div.skill_set li.skill_info { + position: relative; /* needed to have absolute positions be relative to this li */ + list-style: none; + display: inline-block; + width: 220px; + height: 220px; + border-color: #ccc; + border-width: 1px; + border-style: solid; + margin: 5px; + padding: 5px; + padding-top: 10px; +} + + +div.skill_set li.skill_info figcaption { + text-align: center; +} + +div.skill_set li.skill_info input[type=text] { + width: 150px; +} + +div.skill_set li.skill_info a.editicon { + position: absolute; + top: 5px; + right: 10px; +} + +div.skill_set li.skill_info a.deleteskill { + position: absolute; + top: 5px; + left: 7px; +} +div.skill_set li.skill_info a.deleteskill i.icon { + color: red; +} + +div.skill_set li.skill_info a.deleteskill i.icon.disabled { + color: #ccc; +} + +div.skill_set li.skill_info a.editname { + margin-left: 5px; +} + +table.level_config tr[data-rowid='-255'] { +} + +table.level_config tr[data-rowid='-255'] td { + +} + +table.level_config tr[data-rowid='-255'] input[data-name='points'] { + background-color: #F0F0F0; +} + +div.block_gradelevel_results ul { + padding-left: 0px; + margin-left: 0px; +} + +div .block_gradelevel_results li.result_badge { + position: relative; /* needed to have absolute positions be relative to this li */ + list-style: none; + display: inline-block; + width: 190px; + height: 210px; + border-color: #ccc; + border-width: 1px; + border-style: solid; + margin: 5px; + padding: 5px; + padding-top: 10px; +} + + +div.block_gradelevel_results li.result_badge figcaption { + text-align: center; + height: 3em; + margin-bottom: 0.5rem; +} + +div.block_gradelevel_results li.result_badge div.pointinfo { + font-size: 85%; +} + +div.block_gradelevel_results li.result_badge figcaption span.namepart { + break-inside: avoid; + display: inline-block; +} + +div.block_gradelevel_results figure.levelset_icon { + margin-bottom: 0.5rem; +} + +figure.levelset_icon { + background-color: #ccc; + background-image: -moz-linear-gradient(45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(-45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #aaa 75%), -moz-linear-gradient(-45deg, transparent 75%, #aaa 75%); + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #aaa), color-stop(.25, transparent)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #aaa), color-stop(.25, transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #aaa)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #aaa)); + -moz-background-size: 32px 32px; + background-size: 32px 33px; + -webkit-background-size: 32px 33px; /* override value for shitty webkit */ + background-position: 0 0, 16px 0, 16px -16px, 0px 16px; + display: inline-block; } \ No newline at end of file diff --git a/version.php b/version.php index 760c91c..5c3fab6 100644 --- a/version.php +++ b/version.php @@ -1,4 +1,4 @@ -component = 'block_gradelevel'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494) -$plugin->version = 2018092402; // YYYYMMDDHH (year, month, day, 24-hr time) +component = 'block_gradelevel'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494) +$plugin->version = 2018112400; // YYYYMMDDHH (year, month, day, iteration) $plugin->requires = 2018050800; // YYYYMMDDHH (This is the release version for Moodle 3.5) \ No newline at end of file diff --git a/view-icon.php b/view-icon.php index c09b0ec..24cf0a2 100644 --- a/view-icon.php +++ b/view-icon.php @@ -1,49 +1,49 @@ -get_record('block_gradelevel_levelset', array('id' => $skillid)); - -if(is_object($skill)) -{ - $image = $skill->icon; - - if(strncmp($image,"data:",5) == 0) - { - $parts = explode(",",ltrim(substr($image,5)),2); - $typeinfo = explode(";",$parts[0]); - if(count($typeinfo) > 1 && $typeinfo[1] == "base64") - { - $binary = base64_decode($parts[1]); - } - else - { - $binary = $parts[0]; - } - $mime = $typeinfo[0]; - - // set header - header("Content-type: {$mime}"); - header("Pragma:"); - // Allow cache for 5 seconds - header("Cache-Control: public, max-age=5"); - // print data - print $binary; - } - else - { - // redirect to specified url - header("Location: {$image}",true,302); - } - -} -else -{ - http_response_code(404); - print "Image not found"; -} +get_record('block_gradelevel_levelset', array('id' => $skillid)); + +if(is_object($skill)) +{ + $image = $skill->icon; + + if(strncmp($image,"data:",5) == 0) + { + $parts = explode(",",ltrim(substr($image,5)),2); + $typeinfo = explode(";",$parts[0]); + if(count($typeinfo) > 1 && $typeinfo[1] == "base64") + { + $binary = base64_decode($parts[1]); + } + else + { + $binary = $parts[0]; + } + $mime = $typeinfo[0]; + + // set header + header("Content-type: {$mime}"); + header("Pragma:"); + // Allow cache for 5 seconds + header("Cache-Control: public, max-age=5"); + // print data + print $binary; + } + else + { + // redirect to specified url + header("Location: {$image}",true,302); + } + +} +else +{ + http_response_code(404); + print "Image not found"; +} diff --git a/view-results.php b/view-results.php index a371918..f2044ce 100644 --- a/view-results.php +++ b/view-results.php @@ -1,90 +1,90 @@ -set_url('/blocks/gradelevel/view-results.php', array('courseid' => $courseid)); -$PAGE->set_pagelayout('standard'); - -$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); - -print $OUTPUT->header(); -print $OUTPUT->heading(get_string('results_heading', 'block_gradelevel') . " " . $skill->getName()); -print "

    ".get_string('course', 'core')." " . $COURSE->fullname."

    "; - -//retrieve groups -$course_groups = groups_get_all_groups($COURSE->id); -// retrieve users -$remaining_users = get_enrolled_users($coursecontext); - -print "
    "; -if(count($course_groups > 0)) -{ - // loop through all groups first - foreach($course_groups as $grp) - { - // Get members - $members = get_enrolled_users($coursecontext,'mod/assignment:submit',$grp->id); - $count_members = count($members); - - // show group name - print $OUTPUT->heading($grp->name." ({$count_members})",4,array('groupname')); - - // Sort on last name - usort( $members, function( $a, $b) { - return ( $a->lastname < $b->lastname ) ? -1 : 1; - } ); - - print "
      "; - foreach($members as $usr) - { - $pointstotal = $skill->get_levelset_grade($usr->id); - $level_info = $skill->calculate_level($pointstotal); - - print "
    • "; - print $skill->render_badge($pointstotal,BADGE_SIZE); - print "
      {$usr->firstname} {$usr->lastname}
      "; - print "
      ".get_string('levelup_at','block_gradelevel')." {$level_info->points_in_level}/{$level_info->levelup_total}
      "; - print "
    • "; - unset($remaining_users[$usr->id]); - } - print "
    "; - } - - $count_members = count($remaining_users); - print $OUTPUT->heading(get_string('results_ungrouped','block_gradelevel')." ({$count_members})" ,4,array('groupname')); - -} -usort( $remaining_users, function( $a, $b) { - return ( $a->lastname < $b->lastname ) ? -1 : 1; -} ); -print "
      "; -foreach($remaining_users as $usr) -{ - $pointstotal = $skill->get_levelset_grade($usr->id); - $level_info = $skill->calculate_level($pointstotal); - print "
    • "; - print $skill->render_badge($pointstotal,BADGE_SIZE); - print "
      {$usr->firstname} {$usr->lastname}
      "; - print "
      ".get_string('levelup_at','block_gradelevel')." {$level_info->points_in_level}/{$level_info->levelup_total}
      "; - print "
    • "; - -} -print "
    "; - -print "
    "; - -print $OUTPUT->footer(); +set_url('/blocks/gradelevel/view-results.php', array('courseid' => $courseid)); +$PAGE->set_pagelayout('standard'); + +$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init'); + +print $OUTPUT->header(); +print $OUTPUT->heading(get_string('results_heading', 'block_gradelevel') . " " . $skill->getName()); +print "

    ".get_string('course', 'core')." " . $COURSE->fullname."

    "; + +//retrieve groups +$course_groups = groups_get_all_groups($COURSE->id); +// retrieve users +$remaining_users = get_enrolled_users($coursecontext); + +print "
    "; +if(count($course_groups > 0)) +{ + // loop through all groups first + foreach($course_groups as $grp) + { + // Get members + $members = get_enrolled_users($coursecontext,'mod/assignment:submit',$grp->id); + $count_members = count($members); + + // show group name + print $OUTPUT->heading($grp->name." ({$count_members})",4,array('groupname')); + + // Sort on last name + usort( $members, function( $a, $b) { + return ( $a->lastname < $b->lastname ) ? -1 : 1; + } ); + + print "
      "; + foreach($members as $usr) + { + $pointstotal = $skill->get_levelset_grade($usr->id); + $level_info = $skill->calculate_level($pointstotal); + + print "
    • "; + print $skill->render_badge($pointstotal,BADGE_SIZE); + print "
      {$usr->firstname} {$usr->lastname}
      "; + print "
      ".get_string('levelup_at','block_gradelevel')." {$level_info->points_in_level}/{$level_info->levelup_total}
      "; + print "
    • "; + unset($remaining_users[$usr->id]); + } + print "
    "; + } + + $count_members = count($remaining_users); + print $OUTPUT->heading(get_string('results_ungrouped','block_gradelevel')." ({$count_members})" ,4,array('groupname')); + +} +usort( $remaining_users, function( $a, $b) { + return ( $a->lastname < $b->lastname ) ? -1 : 1; +} ); +print "
      "; +foreach($remaining_users as $usr) +{ + $pointstotal = $skill->get_levelset_grade($usr->id); + $level_info = $skill->calculate_level($pointstotal); + print "
    • "; + print $skill->render_badge($pointstotal,BADGE_SIZE); + print "
      {$usr->firstname} {$usr->lastname}
      "; + print "
      ".get_string('levelup_at','block_gradelevel')." {$level_info->points_in_level}/{$level_info->levelup_total}
      "; + print "
    • "; + +} +print "
    "; + +print "
    "; + +print $OUTPUT->footer();