Fixes
This commit is contained in:
parent
97ce14fe20
commit
c938b994a1
2
amd/build/report-viewer-components.min.js
vendored
2
amd/build/report-viewer-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
amd/build/studyplan-editor-components.min.js
vendored
2
amd/build/studyplan-editor-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
amd/build/treestudyplan-components.min.js
vendored
2
amd/build/treestudyplan-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
amd/build/util/psidebar-vue.min.js
vendored
2
amd/build/util/psidebar-vue.min.js
vendored
|
@ -1,3 +1,3 @@
|
||||||
define("local_treestudyplan/util/psidebar-vue",["exports","./css-calc"],(function(_exports,_cssCalc){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;var _default={install(Vue){Vue.component("p-sidebar",{props:{value:{type:Boolean,default:!0},right:{type:Boolean,default:!1},shadow:{type:Boolean,default:!1},target:{type:String,default:"body"},offsetRef:{type:String,default:""}},data:()=>({wrapper:null,contentwrapper:null,resizeobserver:null}),computed:{},methods:{initWrappers(target){this.wrapper=document.querySelector("#p-sidebar-wrapper"),this.wrapper||(this.wrapper=document.createElement("div"),this.wrapper.setAttribute("id","p-sidebar-wrapper")),this.contentwrapper=document.querySelector("#p-sidebar-contentwrapper"),this.contentwrapper||(this.contentwrapper=document.createElement("div"),this.contentwrapper.setAttribute("id","p-sidebar-contentwrapper"),this.wrapper.appendChild(this.contentwrapper));let targetEl=document.querySelector(target);for(console.info(`Targeting '${target}' to `,targetEl),targetEl&&"HTML"!=targetEl.nodeType||(targetEl=document.querySelector("body"));targetEl.childNodes.length>0;)this.contentwrapper.appendChild(targetEl.childNodes[0]);targetEl.appendChild(this.wrapper)},rePosition(right){const el=this.$refs.container;right?this.wrapper.insertBefore(el,this.contentwrapper.nextSibling):this.wrapper.insertBefore(el,this.contentwrapper)},setOffset(reference){const ref=reference?document.querySelector(reference):null;console.info(`Setting offset from '${reference}'`,ref);let offsetTop=ref?ref.offsetTop:0;offsetTop+=0!=offsetTop?"px":"";const el=this.$refs.container;el.style.height=`calc( 100vh - ${offsetTop})`,el.style.marginTop=offsetTop}},watch:{right(newVal){this.rePosition(newVal)},offsetRef(reference){this.setOffset(reference)}},mounted(){const el=this.$refs.container;this.initWrappers(this.target),this.setOffset(this.offsetRef),this.rePosition(this.right,this.besides),this.resizeObserver=new ResizeObserver((()=>{let wx=0-el.getBoundingClientRect().width;wx+=0!=wx?"px":"",el.style.setProperty("--p-sidebar-hideoffset",wx)})),this.resizeObserver.observe(el)},unmounted(){this.resizeObserver&&this.resizeObserver.disconnect()},template:"\n <div>\n <div ref='container' \n :class=\"'p-sidebar ' + (right?'p-sidebar-right ':'') + (shadow?'p-sidebar-shadow ':'') + (value?'shown ':'hidden ')\"\n ><slot></slot></div>\n </div>\n "})}};return _exports.default=_default,_exports.default}));
|
define("local_treestudyplan/util/psidebar-vue",["exports","./debugger"],(function(_exports,_debugger){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;let debug=new(_debugger=(obj=_debugger)&&obj.__esModule?obj:{default:obj}).default("p-sidebar");var _default={install(Vue){Vue.component("p-sidebar",{props:{value:{type:Boolean,default:!0},right:{type:Boolean,default:!1},shadow:{type:Boolean,default:!1},target:{type:String,default:"body"},offsetRef:{type:String,default:""}},data:()=>({wrapper:null,contentwrapper:null,resizeobserver:null}),computed:{},methods:{initWrappers(target){let initializeWrapperContent=!1;if(this.wrapper=document.querySelector("#p-sidebar-wrapper"),this.wrapper||(initializeWrapperContent=!0,this.wrapper=document.createElement("div"),this.wrapper.setAttribute("id","p-sidebar-wrapper")),this.contentwrapper=document.querySelector("#p-sidebar-contentwrapper"),this.contentwrapper||(initializeWrapperContent=!0,this.contentwrapper=document.createElement("div"),this.contentwrapper.setAttribute("id","p-sidebar-contentwrapper"),this.wrapper.appendChild(this.contentwrapper)),initializeWrapperContent){let targetEl=document.querySelector(target);for(console.info(`Targeting '${target}' to `,targetEl),targetEl&&"HTML"!=targetEl.nodeType||(targetEl=document.querySelector("body")),debug.warn("Initializing wrappers with content of target ",targetEl);targetEl.childNodes.length>0;)this.contentwrapper.appendChild(targetEl.childNodes[0]);targetEl.appendChild(this.wrapper)}},rePosition(right){const el=this.$refs.container;right?this.wrapper.insertBefore(el,this.contentwrapper.nextSibling):this.wrapper.insertBefore(el,this.contentwrapper)},setOffset(reference){const ref=reference?document.querySelector(reference):null;console.info(`Setting offset from '${reference}'`,ref);let offsetTop=ref?ref.offsetTop:0;offsetTop+=0!=offsetTop?"px":"";const el=this.$refs.container;el.style.height=`calc( 100vh - ${offsetTop})`,el.style.marginTop=offsetTop}},watch:{right(newVal){this.rePosition(newVal)},offsetRef(reference){this.setOffset(reference)}},mounted(){const el=this.$refs.container;this.initWrappers(this.target),this.setOffset(this.offsetRef),this.rePosition(this.right,this.besides),this.resizeObserver=new ResizeObserver((()=>{let wx=0-el.getBoundingClientRect().width;wx+=0!=wx?"px":"",el.style.setProperty("--p-sidebar-hideoffset",wx)})),this.resizeObserver.observe(el)},unmounted(){this.resizeObserver&&this.resizeObserver.disconnect()},template:"\n <div>\n <div ref='container' \n :class=\"'p-sidebar ' + (right?'p-sidebar-right ':'') + (shadow?'p-sidebar-shadow ':'') + (value?'shown ':'hidden ')\"\n ><slot></slot></div>\n </div>\n "})}};return _exports.default=_default,_exports.default}));
|
||||||
|
|
||||||
//# sourceMappingURL=psidebar-vue.min.js.map
|
//# sourceMappingURL=psidebar-vue.min.js.map
|
File diff suppressed because one or more lines are too long
|
@ -152,6 +152,7 @@ export default {
|
||||||
required_goal: "required_goal",
|
required_goal: "required_goal",
|
||||||
student_not_tracked: "student_not_tracked",
|
student_not_tracked: "student_not_tracked",
|
||||||
not_enrolled: "not_enrolled",
|
not_enrolled: "not_enrolled",
|
||||||
|
noenddate: "noenddate",
|
||||||
},
|
},
|
||||||
teachercourse: {
|
teachercourse: {
|
||||||
select_conditions: "select_conditions",
|
select_conditions: "select_conditions",
|
||||||
|
@ -164,6 +165,7 @@ export default {
|
||||||
required_goal: "required_goal",
|
required_goal: "required_goal",
|
||||||
student_from_plan_enrolled: "student_from_plan_enrolled",
|
student_from_plan_enrolled: "student_from_plan_enrolled",
|
||||||
students_from_plan_enrolled: "students_from_plan_enrolled",
|
students_from_plan_enrolled: "students_from_plan_enrolled",
|
||||||
|
noenddate: "noenddate",
|
||||||
},
|
},
|
||||||
competency: {
|
competency: {
|
||||||
competency_not_configured: "competency_not_configured",
|
competency_not_configured: "competency_not_configured",
|
||||||
|
@ -1485,7 +1487,7 @@ export default {
|
||||||
return format_date(this.value.course.startdate);
|
return format_date(this.value.course.startdate);
|
||||||
},
|
},
|
||||||
enddate(){
|
enddate(){
|
||||||
if(this.value.course.enddate){
|
if(this.value.course.enddate > 0){
|
||||||
return format_date(this.value.course.enddate);
|
return format_date(this.value.course.enddate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2264,7 +2266,7 @@ export default {
|
||||||
return format_date(this.value.course.startdate);
|
return format_date(this.value.course.startdate);
|
||||||
},
|
},
|
||||||
enddate(){
|
enddate(){
|
||||||
if(this.value.course.enddate){
|
if(this.value.course.enddate > 0){
|
||||||
return format_date(this.value.course.enddate);
|
return format_date(this.value.course.enddate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2449,6 +2451,17 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
startdate(){
|
||||||
|
return format_date(this.value.course.startdate);
|
||||||
|
},
|
||||||
|
enddate(){
|
||||||
|
if(this.value.course.enddate > 0){
|
||||||
|
return format_date(this.value.course.enddate);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return this.text.noenddate;
|
||||||
|
}
|
||||||
|
},
|
||||||
wwwroot() {
|
wwwroot() {
|
||||||
return Config.wwwroot;
|
return Config.wwwroot;
|
||||||
}
|
}
|
||||||
|
@ -2495,10 +2508,9 @@ export default {
|
||||||
<div class="r-course-detail-header-right">
|
<div class="r-course-detail-header-right">
|
||||||
<div :class="'r-timing-'+value.course.timing">
|
<div :class="'r-timing-'+value.course.timing">
|
||||||
{{text['coursetiming_'+value.course.timing]}}<br>
|
{{text['coursetiming_'+value.course.timing]}}<br>
|
||||||
{{ value.course.startdate }} - {{ value.course.enddate }}
|
{{ startdate }} - {{ enddate }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<s-
|
|
||||||
</template>
|
</template>
|
||||||
<b-form-group
|
<b-form-group
|
||||||
:label="text.select_grades"
|
:label="text.select_grades"
|
||||||
|
|
|
@ -223,6 +223,7 @@ export default {
|
||||||
selected: 'selected',
|
selected: 'selected',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
context: 'context',
|
context: 'context',
|
||||||
|
search: 'search',
|
||||||
},
|
},
|
||||||
item_text: {
|
item_text: {
|
||||||
select_conditions: "select_conditions",
|
select_conditions: "select_conditions",
|
||||||
|
@ -248,6 +249,7 @@ export default {
|
||||||
ok: "ok@core",
|
ok: "ok@core",
|
||||||
cancel: "cancel@core",
|
cancel: "cancel@core",
|
||||||
delete: "delete@core",
|
delete: "delete@core",
|
||||||
|
noenddate: "noenddate",
|
||||||
},
|
},
|
||||||
invalid: {
|
invalid: {
|
||||||
error: 'error',
|
error: 'error',
|
||||||
|
@ -1111,7 +1113,7 @@ export default {
|
||||||
<b-form-input
|
<b-form-input
|
||||||
type="text"
|
type="text"
|
||||||
@input="searchUsers($event)"
|
@input="searchUsers($event)"
|
||||||
placeholder="Search users"></b-form-input>
|
:placeholder="text.search + ' ' + text.users"></b-form-input>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<b-row>
|
<b-row>
|
||||||
|
@ -1144,7 +1146,7 @@ export default {
|
||||||
</b-row>
|
</b-row>
|
||||||
</b-container>
|
</b-container>
|
||||||
</b-tab>
|
</b-tab>
|
||||||
<b-tab :title="text.coaches">
|
<b-tab :title="text.coaches" v-if="premiumenabled()">
|
||||||
<b-container>
|
<b-container>
|
||||||
<b-row class='mb-2 mt-2'>
|
<b-row class='mb-2 mt-2'>
|
||||||
<b-col>{{text.associated_coaches}}</b-col>
|
<b-col>{{text.associated_coaches}}</b-col>
|
||||||
|
@ -1157,7 +1159,7 @@ export default {
|
||||||
<b-form-input
|
<b-form-input
|
||||||
type="text"
|
type="text"
|
||||||
@input="searchCoaches($event)"
|
@input="searchCoaches($event)"
|
||||||
placeholder="Search coaches"></b-form-input>
|
:placeholder="text.search + ' ' + text.coaches"></b-form-input>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<b-row>
|
<b-row>
|
||||||
|
@ -1455,7 +1457,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const self=this;
|
const self=this;
|
||||||
if(this.value.pages[0].studylines.length == 0){
|
if(this.value.pages[0].studylines.length == 0 && !this.coaching){
|
||||||
// start in editmode if studylines on first page are empty
|
// start in editmode if studylines on first page are empty
|
||||||
this.edit.studyline.editmode = true;
|
this.edit.studyline.editmode = true;
|
||||||
}
|
}
|
||||||
|
@ -3402,7 +3404,7 @@ export default {
|
||||||
return format_date(this.value.course.startdate);
|
return format_date(this.value.course.startdate);
|
||||||
},
|
},
|
||||||
enddate(){
|
enddate(){
|
||||||
if(this.value.course.enddate){
|
if(this.value.course.enddate > 0){
|
||||||
return format_date(this.value.course.enddate);
|
return format_date(this.value.course.enddate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -304,7 +304,8 @@ export default {
|
||||||
<slot></slot
|
<slot></slot
|
||||||
><p v-if="value.startdate > 0"
|
><p v-if="value.startdate > 0"
|
||||||
class="s-studyline-header-period-datespan small">
|
class="s-studyline-header-period-datespan small">
|
||||||
<span class="date">{{ startdate }}</span> - <span class="date">{{ enddate }}</span>
|
<span class="date">{{ startdate }}</span>
|
||||||
|
- <span class="date" v-if="this.value.enddate > 0">{{ enddate }}</span><span class="date" v-else>∞</span>
|
||||||
</p>
|
</p>
|
||||||
<div v-if="current && mode == 'view'" class='s-studyline-period-highlight'></div>
|
<div v-if="current && mode == 'view'" class='s-studyline-period-highlight'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
/*eslint-disable no-console */
|
/*eslint-disable no-console */
|
||||||
/*eslint-env es6*/
|
/*eslint-env es6*/
|
||||||
|
|
||||||
import {calc} from "./css-calc";
|
import Debugger from './debugger';
|
||||||
|
let debug = new Debugger("p-sidebar");
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(Vue/*,options*/){
|
install(Vue/*,options*/){
|
||||||
|
@ -42,9 +43,12 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initWrappers(target) {
|
initWrappers(target) {
|
||||||
// First check if the sidebar wrapper already exists.
|
let initializeWrapperContent = false;
|
||||||
|
// First check if the sidebar wrapper already exists.
|
||||||
|
// Creating the wrappers over and over again is a recipe for disaster.
|
||||||
this.wrapper = document.querySelector("#p-sidebar-wrapper");
|
this.wrapper = document.querySelector("#p-sidebar-wrapper");
|
||||||
if (! this.wrapper) {
|
if (!this.wrapper) {
|
||||||
|
initializeWrapperContent = true;
|
||||||
// Otherwise, create it.
|
// Otherwise, create it.
|
||||||
this.wrapper = document.createElement("div");
|
this.wrapper = document.createElement("div");
|
||||||
this.wrapper.setAttribute("id","p-sidebar-wrapper");
|
this.wrapper.setAttribute("id","p-sidebar-wrapper");
|
||||||
|
@ -52,31 +56,33 @@ export default {
|
||||||
// First check if the contentwrapper already exists
|
// First check if the contentwrapper already exists
|
||||||
this.contentwrapper = document.querySelector("#p-sidebar-contentwrapper");
|
this.contentwrapper = document.querySelector("#p-sidebar-contentwrapper");
|
||||||
if (!this.contentwrapper) {
|
if (!this.contentwrapper) {
|
||||||
|
initializeWrapperContent = true;
|
||||||
// Otherwise, create it.
|
// Otherwise, create it.
|
||||||
this.contentwrapper = document.createElement("div");
|
this.contentwrapper = document.createElement("div");
|
||||||
this.contentwrapper.setAttribute("id","p-sidebar-contentwrapper");
|
this.contentwrapper.setAttribute("id","p-sidebar-contentwrapper");
|
||||||
this.wrapper.appendChild(this.contentwrapper);
|
this.wrapper.appendChild(this.contentwrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find containing target (otherwise use body)
|
if (initializeWrapperContent) {
|
||||||
let targetEl = document.querySelector(target);
|
// Find containing target (otherwise use body)
|
||||||
console.info(`Targeting '${target}' to `,targetEl);
|
let targetEl = document.querySelector(target);
|
||||||
if (!targetEl || targetEl.nodeType == "HTML") {
|
console.info(`Targeting '${target}' to `,targetEl);
|
||||||
targetEl = document.querySelector("body");
|
if (!targetEl || targetEl.nodeType == "HTML") {
|
||||||
|
targetEl = document.querySelector("body");
|
||||||
|
}
|
||||||
|
debug.warn(`Initializing wrappers with content of target `,targetEl);
|
||||||
|
// Move all target content parts to content wrapper....
|
||||||
|
while (targetEl.childNodes.length >0) {
|
||||||
|
this.contentwrapper.appendChild(targetEl.childNodes[0]);
|
||||||
|
}
|
||||||
|
// Add sidebar wrapper to target Element
|
||||||
|
targetEl.appendChild(this.wrapper);
|
||||||
}
|
}
|
||||||
// Move all target content parts to content wrapper....
|
|
||||||
while (targetEl.childNodes.length >0) {
|
|
||||||
this.contentwrapper.appendChild(targetEl.childNodes[0]);
|
|
||||||
}
|
|
||||||
// Add sidebar wrapper to target Element
|
|
||||||
targetEl.appendChild(this.wrapper);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
rePosition(right) {
|
rePosition(right) {
|
||||||
// Place the container elsewhere in the DOM.
|
// Place the container elsewhere in the DOM.
|
||||||
const el = this.$refs.container;
|
const el = this.$refs.container;
|
||||||
|
|
||||||
|
|
||||||
if(right) {
|
if(right) {
|
||||||
this.wrapper.insertBefore(el,this.contentwrapper.nextSibling);
|
this.wrapper.insertBefore(el,this.contentwrapper.nextSibling);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -365,7 +365,7 @@ class corecompletioninfo {
|
||||||
$details = [
|
$details = [
|
||||||
"type" => get_string('manualcompletionby', 'completion'),
|
"type" => get_string('manualcompletionby', 'completion'),
|
||||||
"criteria" => $criteria->get_title(),
|
"criteria" => $criteria->get_title(),
|
||||||
"requirement" => get_string('markedcompleteby', 'completion', $criteria),
|
"requirement" => get_string('markedcompleteby', 'completion', $criteria->get_title()),
|
||||||
"status" => "",
|
"status" => "",
|
||||||
];
|
];
|
||||||
} else if ($type == COMPLETION_CRITERIA_TYPE_COURSE) {
|
} else if ($type == COMPLETION_CRITERIA_TYPE_COURSE) {
|
||||||
|
|
|
@ -408,7 +408,7 @@ class courseinfo {
|
||||||
*/
|
*/
|
||||||
public function is_enrolled_student($userid) : bool {
|
public function is_enrolled_student($userid) : bool {
|
||||||
global $CFG;
|
global $CFG;
|
||||||
foreach (explode(', ', $CFG->gradebookroles) as $roleid) {
|
foreach (explode(',', $CFG->gradebookroles) as $roleid) {
|
||||||
if (user_has_role_assignment($userid, $roleid, $this->coursecontext->id)) {
|
if (user_has_role_assignment($userid, $roleid, $this->coursecontext->id)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ require_once($CFG->dirroot.'/repository/lib.php');
|
||||||
use local_treestudyplan\aggregator;
|
use local_treestudyplan\aggregator;
|
||||||
use local_treestudyplan\studyplan;
|
use local_treestudyplan\studyplan;
|
||||||
use local_treestudyplan\premium;
|
use local_treestudyplan\premium;
|
||||||
use local_treestudyplan\contextinfo;
|
use local_treestudyplan\debug;
|
||||||
use local_treestudyplan\studyplanservice;
|
use local_treestudyplan\studyplanservice;
|
||||||
use local_treestudyplan\courseservice;
|
use local_treestudyplan\courseservice;
|
||||||
use local_treestudyplan\form\text_integer;
|
use local_treestudyplan\form\text_integer;
|
||||||
|
@ -384,7 +384,9 @@ class studyplan_editform extends formbase {
|
||||||
Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass)
|
Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass)
|
||||||
so we return it in a consistent way
|
so we return it in a consistent way
|
||||||
*/
|
*/
|
||||||
return studyplanservice::clean_returnvalue(studyplan::simple_structure(),$plan->simple_model());
|
$response = studyplanservice::clean_returnvalue(studyplan::simple_structure(),$plan->simple_model());
|
||||||
|
debug::dump($response);
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class premium extends \external_api {
|
||||||
|
|
||||||
// Toggle the variable below to enable support for premium stuff.
|
// Toggle the variable below to enable support for premium stuff.
|
||||||
// If set to false, all premium features will be enabled and no premium settings panel will be visible.
|
// If set to false, all premium features will be enabled and no premium settings panel will be visible.
|
||||||
private static $premium_supported = true;
|
private static $premium_supported = false;
|
||||||
|
|
||||||
private static $premiumcrt = "-----BEGIN CERTIFICATE-----
|
private static $premiumcrt = "-----BEGIN CERTIFICATE-----
|
||||||
MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx
|
MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx
|
||||||
|
@ -67,7 +67,6 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
return self::$premium_supported;
|
return self::$premium_supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static function decrypt($encrypted) {
|
private static function decrypt($encrypted) {
|
||||||
// Get the public key.
|
// Get the public key.
|
||||||
$key = \openssl_get_publickey(self::$premiumcrt);
|
$key = \openssl_get_publickey(self::$premiumcrt);
|
||||||
|
@ -161,6 +160,36 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function debuginfo() {
|
||||||
|
$s = "<pre>";
|
||||||
|
try {
|
||||||
|
$activationkey = \get_config("local_treestudyplan","premium_key");
|
||||||
|
if (strlen($activationkey) > 0) {
|
||||||
|
$keydata = self::trim_headers($activationkey);
|
||||||
|
$json = self::decrypt($keydata);
|
||||||
|
$s .= "Decoded key data:\n----\n";
|
||||||
|
$s .= $json . "\n----\n";
|
||||||
|
$decoded = \json_decode($json,false);
|
||||||
|
$s .= "Read as object:\n----\n";
|
||||||
|
$s .= print_r($decoded,true) ."\n----\n";
|
||||||
|
$status = self::premiumStatus();
|
||||||
|
$s .= "Parsed premium status block:\n----\n";
|
||||||
|
$s .= print_r($status,true) ."\n----\n";
|
||||||
|
$s .= "Message: " . self::statusdescription() . "\n";
|
||||||
|
} else {
|
||||||
|
$s .= "Premium key empty";
|
||||||
|
}
|
||||||
|
} catch (\Throwable $x) {
|
||||||
|
$s .= "!!! " . get_class($x) . ": " . $x->getCode() . " | " . $x->getMessage(). "\n";
|
||||||
|
$stack = explode("\n",$x->getTraceAsString());
|
||||||
|
foreach ($stack as $l) {
|
||||||
|
$s .= " " . trim($l) ."\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$s.="</pre>";
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Determine, cache and retrieve premium status
|
* Determine, cache and retrieve premium status
|
||||||
* @return object
|
* @return object
|
||||||
|
@ -177,13 +206,10 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
$o->expires = "";
|
$o->expires = "";
|
||||||
$o->expired = false;
|
$o->expired = false;
|
||||||
$o->issued = "";
|
$o->issued = "";
|
||||||
$o->message = \get_string("premium:notregistered","local_treestudyplan");
|
try {
|
||||||
|
$activationkey = \get_config("local_treestudyplan","premium_key");
|
||||||
$activationkey = \get_config("local_treestudyplan","premium_key");
|
if (strlen($activationkey) > 0) {
|
||||||
if (strlen($activationkey) > 0) {
|
|
||||||
$activationkey;
|
|
||||||
|
|
||||||
try {
|
|
||||||
$keydata = self::trim_headers($activationkey);
|
$keydata = self::trim_headers($activationkey);
|
||||||
$json = self::decrypt($keydata);
|
$json = self::decrypt($keydata);
|
||||||
$decoded = \json_decode($json,false);
|
$decoded = \json_decode($json,false);
|
||||||
|
@ -215,9 +241,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
} catch (\Exception $x) {}
|
} catch (\Exception $x) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( \in_array('treestudyplan',$o->intents)
|
||||||
|
|
||||||
if ( \in_array('treestudyplan',$o->intents)
|
|
||||||
&& !empty($o->issued)
|
&& !empty($o->issued)
|
||||||
&& self::website_match($o->website)
|
&& self::website_match($o->website)
|
||||||
) {
|
) {
|
||||||
|
@ -237,10 +261,9 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (\ValueError $x) {
|
|
||||||
$o->status = \get_string("premium:invalidactivationcontent","local_treestudyplan");
|
|
||||||
}
|
}
|
||||||
|
} catch (\ValueError $x) {
|
||||||
|
$o->status = \get_string("premium:invalidactivationcontent","local_treestudyplan");
|
||||||
}
|
}
|
||||||
self::$cachedpremiumstatus = $o;
|
self::$cachedpremiumstatus = $o;
|
||||||
|
|
||||||
|
@ -254,7 +277,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
private static function website_match($key) {
|
private static function website_match($key) {
|
||||||
global $CFG;
|
global $CFG;
|
||||||
$site = $CFG->wwwroot;
|
$site = $CFG->wwwroot;
|
||||||
// Add double slashes to key and site if no scheme is set.
|
// Add double slashes to key and site if no scheme is set.
|
||||||
// Basically: if no double slashes present before any dots,shashes or @s.
|
// Basically: if no double slashes present before any dots,shashes or @s.
|
||||||
if(!\preg_match_all('#^[^./@]*?//#',$key )) {
|
if(!\preg_match_all('#^[^./@]*?//#',$key )) {
|
||||||
$key = "//".$key;
|
$key = "//".$key;
|
||||||
|
@ -271,6 +294,11 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($keyurl->host == "*") {
|
||||||
|
// * matches all
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// First match the host part.
|
// First match the host part.
|
||||||
$keyparts = \array_reverse(\explode(".",$keyurl->host));
|
$keyparts = \array_reverse(\explode(".",$keyurl->host));
|
||||||
$siteparts = \array_reverse(\explode(".",$siteurl->host));
|
$siteparts = \array_reverse(\explode(".",$siteurl->host));
|
||||||
|
@ -386,7 +414,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
||||||
if ($status->website != "*") {
|
if ($status->website != "*") {
|
||||||
$msg->sitestatus = \get_string("premium:onsite",'local_treestudyplan',$status);
|
$msg->sitestatus = \get_string("premium:onsite",'local_treestudyplan',$status);
|
||||||
} else {
|
} else {
|
||||||
$msg->sitestatus = \get_string("premium:anywhere",'local_treestudyplan');;
|
$msg->sitestatus = \get_string("premium:anywhere",'local_treestudyplan');
|
||||||
}
|
}
|
||||||
|
|
||||||
if($status->enabled) {
|
if($status->enabled) {
|
||||||
|
|
|
@ -412,10 +412,9 @@ class studyplan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = studyplanpage::add($pageinfo);
|
$page = studyplanpage::add($pageinfo,$bare);
|
||||||
$plan->page_cache = [$page];
|
$plan->page_cache = [$page];
|
||||||
}
|
}
|
||||||
// End temporary skräpp code.
|
|
||||||
|
|
||||||
return $plan;
|
return $plan;
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,8 +266,9 @@ class studyplanpage {
|
||||||
/**
|
/**
|
||||||
* Add new study plan page
|
* Add new study plan page
|
||||||
* @param mixed $fields Parameter for new study plan page
|
* @param mixed $fields Parameter for new study plan page
|
||||||
|
* @param bool $bare If true, do not create a first page with copy of studyplan names
|
||||||
*/
|
*/
|
||||||
public static function add($fields) : self {
|
public static function add($fields, $bare = false) : self {
|
||||||
global $DB;
|
global $DB;
|
||||||
|
|
||||||
if (!isset($fields['studyplan_id'])) {
|
if (!isset($fields['studyplan_id'])) {
|
||||||
|
@ -293,7 +294,19 @@ class studyplanpage {
|
||||||
$id = $DB->insert_record(self::TABLE, $info);
|
$id = $DB->insert_record(self::TABLE, $info);
|
||||||
// Refresh the page cache for the studyplan
|
// Refresh the page cache for the studyplan
|
||||||
$plan->pages(true);
|
$plan->pages(true);
|
||||||
return self::find_by_id($id); // Make sure the new page is immediately cached.
|
$page = self::find_by_id($id); // Make sure the new page is immediately cached.
|
||||||
|
|
||||||
|
if (!$bare) {
|
||||||
|
// Add an empty study line
|
||||||
|
$lineinfo = ['page_id' => $id,
|
||||||
|
'name' => get_string("default_line_name","local_treestudyplan"),
|
||||||
|
'shortname' => get_string("default_line_shortname","local_treestudyplan"),
|
||||||
|
"color" => "#DDDDDD",
|
||||||
|
];
|
||||||
|
studyline::add($lineinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -142,9 +142,7 @@ class utilityservice extends \external_api {
|
||||||
* Return value description for webservice function submit_cm_editform
|
* Return value description for webservice function submit_cm_editform
|
||||||
*/
|
*/
|
||||||
public static function submit_mform_returns() : \external_description {
|
public static function submit_mform_returns() : \external_description {
|
||||||
return new \external_multiple_structure(new \external_single_structure([
|
return success::structure(); // Success structure includes data component which encodes date in json format.
|
||||||
"id" => new \external_value(PARAM_INT, 'id of studyline'),
|
|
||||||
]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,6 +163,7 @@ class utilityservice extends \external_api {
|
||||||
$mform = self::load_mform($formname, $params, $ajaxformdata);
|
$mform = self::load_mform($formname, $params, $ajaxformdata);
|
||||||
|
|
||||||
$return = $mform->process_submission();
|
$return = $mform->process_submission();
|
||||||
|
// Pass form processing result as success data component.
|
||||||
return success::success($return)->model();
|
return success::success($return)->model();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
coach.php
34
coach.php
|
@ -82,24 +82,22 @@ print $OUTPUT->header();
|
||||||
v-if="displayedstudyplan.description"
|
v-if="displayedstudyplan.description"
|
||||||
></s-studyplan-details>
|
></s-studyplan-details>
|
||||||
<div class="flex-grow-1"><!-- Spacer to align student selector right --></div>
|
<div class="flex-grow-1"><!-- Spacer to align student selector right --></div>
|
||||||
<div v-if="displayedstudyplan.description">
|
<span><?php t('selectstudent_btn') ?></span>
|
||||||
<span><?php t('selectstudent_btn') ?></span>
|
<s-prevnext-selector
|
||||||
<s-prevnext-selector
|
:options="associatedstudents"
|
||||||
:options="associatedstudents"
|
title="firstname"
|
||||||
title="firstname"
|
v-model="selectedstudent"
|
||||||
v-model="selectedstudent"
|
defaultselectable
|
||||||
defaultselectable
|
grouped
|
||||||
grouped
|
optionsfield='users'
|
||||||
optionsfield='users'
|
arrows
|
||||||
arrows
|
@change="showStudentView"
|
||||||
@change="showStudentView"
|
class="ml-2"
|
||||||
class="ml-2"
|
variant="primary"
|
||||||
variant="primary"
|
>
|
||||||
>
|
<template v-slot="{value}">{{value.firstname}} {{value.lastname}}</template>
|
||||||
<template v-slot="{value}">{{value.firstname}} {{value.lastname}}</template>
|
<template #defaultlabel><span class='text-primary'><?php t("coacheditmode"); ?></span></template>
|
||||||
<template #defaultlabel><span class='text-primary'><?php t("coacheditmode"); ?></span></template>
|
</s-prevnext-selector>
|
||||||
</s-prevnext-selector>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class='t-studyplan-container'>
|
<div class='t-studyplan-container'>
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>local/treestudyplan:forcescales</td>
|
<td>local/treestudyplan:forcescales</td>
|
||||||
<td>Allow studyplan managers with this right to push scales for grading to all selected grable activities (see above)<br>
|
<td><b>(DEPRECATED)</b>Allow studyplan managers with this right to push scales for grading to all selected grable activities (see above)<br>
|
||||||
(Effective only when Manual aggregation method is selected in the study plan)</td>
|
(Effective only when Manual aggregation method is selected in the study plan)</td>
|
||||||
<td>manager</td>
|
<td>manager</td>
|
||||||
<td>System and/or category</td>
|
<td>System and/or category</td>
|
||||||
|
@ -125,13 +125,27 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>local/treestudyplan:configure</td>
|
<td>local/treestudyplan:configure</td>
|
||||||
<td>Users with this right can configure global interpretation of scales and point grades </td>
|
<td>Users with this right can configure global interpretation of scales and point grades <br>
|
||||||
|
This is used when a per-activity passed grade is not set.
|
||||||
|
(Effective only when Manual aggregation method is selected in the study plan)</td>
|
||||||
<td>manager</td>
|
<td>manager</td>
|
||||||
<td>System</td>
|
<td>System</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>local/treestudyplan:viewuserreports</td>
|
<td>local/treestudyplan:viewuserreports</td>
|
||||||
<td></td>
|
<td>Users with this right can view the student's studyplans in all contexts in which this permission is granted</td>
|
||||||
|
<td>manager</td>
|
||||||
|
<td>System and/or category</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>local/treestudyplan:lineunenrol</td>
|
||||||
|
<td>(Premium feature related) Users with this right in addition to <i>viewuserreports</i> can unregister students from an registerable line</td>
|
||||||
|
<td>manager</td>
|
||||||
|
<td>System and/or category</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>local/treestudyplan:coach</td>
|
||||||
|
<td>(Premium feature related) Users with this right can be selected as coaches in the given context</td>
|
||||||
<td>manager</td>
|
<td>manager</td>
|
||||||
<td>System and/or category</td>
|
<td>System and/or category</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -61,6 +61,17 @@ Manage Study plans|/local/treestudyplan/edit-plan.php||en
|
||||||
If you already have a role that you hand out to all teachers/faculty in specific categories, you may want to integrate this role with that one
|
If you already have a role that you hand out to all teachers/faculty in specific categories, you may want to integrate this role with that one
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li><b>Full Name:</b> <i>Studyplan Coach</i><br>
|
||||||
|
<b>Short Name:</b> <i>studyplancoach</i><br>
|
||||||
|
<b>Context types:</b> <i>System</i>, <i>Category</i><br>
|
||||||
|
<b>Capabilities</b>
|
||||||
|
<ul>
|
||||||
|
<li><b>local/treestudyplan:coach</b> <i>Available as coach</i></li>
|
||||||
|
</ul>
|
||||||
|
<div class="generalbox alert alert-success"><b>TIP:</b><br>
|
||||||
|
If you already have a role that you hand out to coaches of a limited group of students, you may want to integrate this role with that one
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p> Then assign the role <b>studyplanmanager</b> in a specific category context, or the system context to all users who should be able to create and edit studyplans
|
<p> Then assign the role <b>studyplanmanager</b> in a specific category context, or the system context to all users who should be able to create and edit studyplans
|
||||||
in that specific context</p>
|
in that specific context</p>
|
||||||
|
|
|
@ -200,6 +200,8 @@ $string["studyline_shortname_ph"] = '';
|
||||||
$string["studyline_color"] = 'Background color';
|
$string["studyline_color"] = 'Background color';
|
||||||
$string["studyline_enrollable"] = 'Registration';
|
$string["studyline_enrollable"] = 'Registration';
|
||||||
$string["studyline_enrolroles"] = 'Allowed roles';
|
$string["studyline_enrolroles"] = 'Allowed roles';
|
||||||
|
$string["default_line_name"] = 'Courses';
|
||||||
|
$string["default_line_shortname"] = 'Courses';
|
||||||
|
|
||||||
$string["studyitem_confirm_remove"] = 'Are you sure you want to remove module {$a}?';
|
$string["studyitem_confirm_remove"] = 'Are you sure you want to remove module {$a}?';
|
||||||
$string["editmode_modules_hidden"] = 'Modules hidden in edit mode';
|
$string["editmode_modules_hidden"] = 'Modules hidden in edit mode';
|
||||||
|
@ -291,6 +293,7 @@ $string["coaches"] = 'Coaches';
|
||||||
$string["selected"] = 'Select';
|
$string["selected"] = 'Select';
|
||||||
$string["name"] = 'Name';
|
$string["name"] = 'Name';
|
||||||
$string["context"] = 'Category';
|
$string["context"] = 'Category';
|
||||||
|
$string["search"] = "Search";
|
||||||
|
|
||||||
$string["error"] = "Error";
|
$string["error"] = "Error";
|
||||||
$string["ungraded"] = 'Needs grading';
|
$string["ungraded"] = 'Needs grading';
|
||||||
|
@ -487,7 +490,9 @@ $string["settingdesc_premium_heading"] = 'To access premium features, you need a
|
||||||
</ul>';
|
</ul>';
|
||||||
$string["setting_premium_status"] = 'Current premium status';
|
$string["setting_premium_status"] = 'Current premium status';
|
||||||
$string["setting_premium_key"] = 'Activation key';
|
$string["setting_premium_key"] = 'Activation key';
|
||||||
$string["settingdesc_premium_key"] = 'Paste the premium key you received in the box above.';
|
$string["settingdesc_premium_key"] = 'Paste the premium key you received in the box above.<br> <b>Attention!</b> The lines <i>----- BEGIN ACTIVATION KEY -----</i> and <i>----- END ACTIVATION KEY -----</i> are part of the key.';
|
||||||
|
$string["setting_premium_debug"] = 'Debug info for premium key';
|
||||||
|
|
||||||
|
|
||||||
$string["premiumfeature:morestudyplans"] = 'Creating more than 5 studyplans in a single category is a premium feature.';
|
$string["premiumfeature:morestudyplans"] = 'Creating more than 5 studyplans in a single category is a premium feature.';
|
||||||
$string["premiumfeature:morecategories"] = 'Creating studyplans in more than 20 categories is a premium feature.';
|
$string["premiumfeature:morecategories"] = 'Creating studyplans in more than 20 categories is a premium feature.';
|
||||||
|
|
|
@ -129,7 +129,7 @@ $string["settingdesc_infofields_heading"] = 'Kies tot 5 extra velden om in het c
|
||||||
$string["setting_hivizdropslots"] = 'Extra zichtbare sleepvelden';
|
$string["setting_hivizdropslots"] = 'Extra zichtbare sleepvelden';
|
||||||
$string["settingdesc_hivizdropslots"] = 'Maak de velden waar cursussen heen gesleept kunnen worden extra goed zichtbaar.';
|
$string["settingdesc_hivizdropslots"] = 'Maak de velden waar cursussen heen gesleept kunnen worden extra goed zichtbaar.';
|
||||||
|
|
||||||
$string["setting_toolboxleft"] = 'Toolcox standaard links';
|
$string["setting_toolboxleft"] = 'Toolbox standaard links';
|
||||||
$string["settingdesc_toolboxleft"] = 'Toon de toolbox met cursussen en componenten standaard links in plaats van rechts.';
|
$string["settingdesc_toolboxleft"] = 'Toon de toolbox met cursussen en componenten standaard links in plaats van rechts.';
|
||||||
|
|
||||||
$string["infofield_position_above"] = 'Boven cursusresultaten';
|
$string["infofield_position_above"] = 'Boven cursusresultaten';
|
||||||
|
@ -201,6 +201,8 @@ $string["studyline_shortname_ph"] = '';
|
||||||
$string["studyline_color"] = 'Achtergrondkleur';
|
$string["studyline_color"] = 'Achtergrondkleur';
|
||||||
$string["studyline_enrollable"] = 'Inschrijven';
|
$string["studyline_enrollable"] = 'Inschrijven';
|
||||||
$string["studyline_enrolroles"] = 'Rollen mogen inschrijven';
|
$string["studyline_enrolroles"] = 'Rollen mogen inschrijven';
|
||||||
|
$string["default_line_name"] = 'Cursussen';
|
||||||
|
$string["default_line_shortname"] = 'Cursussen';
|
||||||
|
|
||||||
$string["studyitem_confirm_remove"] = 'Weet je zeker dat je module {$a} wilt verwijderen?';
|
$string["studyitem_confirm_remove"] = 'Weet je zeker dat je module {$a} wilt verwijderen?';
|
||||||
$string["editmode_modules_hidden"] = 'Modules verborgen tijdens bewerken';
|
$string["editmode_modules_hidden"] = 'Modules verborgen tijdens bewerken';
|
||||||
|
@ -292,6 +294,7 @@ $string["coaches"] = 'Coaches';
|
||||||
$string["selected"] = 'Kies';
|
$string["selected"] = 'Kies';
|
||||||
$string["name"] = 'Naam';
|
$string["name"] = 'Naam';
|
||||||
$string["context"] = 'Categorie';
|
$string["context"] = 'Categorie';
|
||||||
|
$string["search"] = "Zoek";
|
||||||
|
|
||||||
$string["error"] = "Fout";
|
$string["error"] = "Fout";
|
||||||
$string["ungraded"] = 'Nog beoordelen';
|
$string["ungraded"] = 'Nog beoordelen';
|
||||||
|
@ -476,7 +479,7 @@ $string["premium:notregistered"] = 'Premium toegang staat <b>uitgeschakeld</n>';
|
||||||
$string["premium:invalidactivationcontent"] = 'Premium activeringssleutel niet herkend';
|
$string["premium:invalidactivationcontent"] = 'Premium activeringssleutel niet herkend';
|
||||||
$string["premium:siteinvalid"] = 'Premium toegang staat <b>uitgeschakeld</n>. Activeringssleutel is alleen voor gebruik op <b>{$a}</b>';
|
$string["premium:siteinvalid"] = 'Premium toegang staat <b>uitgeschakeld</n>. Activeringssleutel is alleen voor gebruik op <b>{$a}</b>';
|
||||||
$string["premium:expired"] = 'Premium toegang is <b class="text-danger">verlopen</b> op <b>{$a->expires}</b><br>Was uitgegeven aan <b>{$a->name}</b> {$a->sitestatus}';
|
$string["premium:expired"] = 'Premium toegang is <b class="text-danger">verlopen</b> op <b>{$a->expires}</b><br>Was uitgegeven aan <b>{$a->name}</b> {$a->sitestatus}';
|
||||||
$string["settingspage_premium"] = 'Premium registration';
|
$string["settingspage_premium"] = 'Premium registratie';
|
||||||
$string["setting_premium_heading"] = 'Premium features';
|
$string["setting_premium_heading"] = 'Premium features';
|
||||||
$string["settingdesc_premium_heading"] = 'Voor premium toegang is een activeringssleutel vereist.
|
$string["settingdesc_premium_heading"] = 'Voor premium toegang is een activeringssleutel vereist.
|
||||||
<br>Premium toegang bevat onder andere:
|
<br>Premium toegang bevat onder andere:
|
||||||
|
@ -487,8 +490,9 @@ $string["settingdesc_premium_heading"] = 'Voor premium toegang is een activering
|
||||||
<li>Leerlijnen die student kan ontsluiten</li>
|
<li>Leerlijnen die student kan ontsluiten</li>
|
||||||
</ul>';
|
</ul>';
|
||||||
$string["setting_premium_status"] = 'Premium status';
|
$string["setting_premium_status"] = 'Premium status';
|
||||||
$string["setting_premium_key"] = 'Activation key';
|
$string["setting_premium_key"] = 'Activatiesleutel';
|
||||||
$string["settingdesc_premium_key"] = 'Premium activation key';
|
$string["settingdesc_premium_key"] = 'Plak de activatiesleutel in het tekstvak hierboven.<br> <b>Let op!</b> De regels <i>----- BEGIN ACTIVATION KEY -----</i> en <i>----- END ACTIVATION KEY -----</i> zijn onderdeel van de sleutel.';
|
||||||
|
$string["setting_premium_debug"] = 'Debug info voor premium key';
|
||||||
|
|
||||||
$string["premiumfeature:morestudyplans"] = 'Meer dan 5 studieplannen in één categorie aanmaken kan alleen met premium toegang.';
|
$string["premiumfeature:morestudyplans"] = 'Meer dan 5 studieplannen in één categorie aanmaken kan alleen met premium toegang.';
|
||||||
$string["premiumfeature:morecategories"] = 'In meer dan 20 categoriën een studieplan aanmaken kan alleen met premium toegang.';
|
$string["premiumfeature:morecategories"] = 'In meer dan 20 categoriën een studieplan aanmaken kan alleen met premium toegang.';
|
||||||
|
|
11
settings.php
11
settings.php
|
@ -373,7 +373,7 @@ if ($hassiteconfig) {
|
||||||
* Settings page: Premium registration
|
* Settings page: Premium registration
|
||||||
*
|
*
|
||||||
*************************************/
|
*************************************/
|
||||||
if (\local_treestudyplan\premium::supported()) {
|
if (\local_treestudyplan\premium::supported() || $CFG->debugdeveloper) {
|
||||||
$pagepremium = new admin_settingpage('local_treestudyplan_settings_premium',
|
$pagepremium = new admin_settingpage('local_treestudyplan_settings_premium',
|
||||||
get_string('settingspage_premium', 'local_treestudyplan', null, true));
|
get_string('settingspage_premium', 'local_treestudyplan', null, true));
|
||||||
|
|
||||||
|
@ -396,6 +396,15 @@ if ($hassiteconfig) {
|
||||||
PARAM_RAW
|
PARAM_RAW
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if ($CFG->debugdeveloper) {
|
||||||
|
// show decrypted key data
|
||||||
|
$pagepremium->add(new admin_setting_description('local_treestudyplan/premium_debug',
|
||||||
|
get_string('setting_premium_debug', 'local_treestudyplan'),
|
||||||
|
premium::debuginfo() . "<br> <br>" // Add empty row at end.
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add settings page2 to the admin settings category.
|
// Add settings page2 to the admin settings category.
|
||||||
$ADMIN->add('local_treestudyplan', $pagepremium);
|
$ADMIN->add('local_treestudyplan', $pagepremium);
|
||||||
}
|
}
|
||||||
|
|
83
test.php
Normal file
83
test.php
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
function sitematch($key,$site){
|
||||||
|
// Add double slashes to key and site if no scheme is set.
|
||||||
|
// Basically: if no double slashes present before any dots,shashes or @s.
|
||||||
|
if(!\preg_match_all('#^[^./@]*?//#',$key )) {
|
||||||
|
$key = "//".$key;
|
||||||
|
}
|
||||||
|
if(!\preg_match_all('#^[^./@]*?//#',$site)) {
|
||||||
|
$site = "//".$site;
|
||||||
|
}
|
||||||
|
// Use parse_url() to split path and host.
|
||||||
|
$keyurl = (object)\parse_url($key);
|
||||||
|
$siteurl = (object)\parse_url($site);
|
||||||
|
|
||||||
|
// No match if host is empty on key or site
|
||||||
|
if (empty($keyurl->host) || empty($siteurl->host)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($keyurl->host == "*") {
|
||||||
|
// * matches all
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First match the host part.
|
||||||
|
$keyparts = \array_reverse(\explode(".",$keyurl->host));
|
||||||
|
$siteparts = \array_reverse(\explode(".",$siteurl->host));
|
||||||
|
|
||||||
|
// Trim starting www from both parts, since site.domain and www.site.domain should be treated as the same.
|
||||||
|
if (($x = \array_pop($keyparts)) != "www") {\array_push($keyparts,$x);}
|
||||||
|
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts,$x);}
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($keyparts); $i++) {
|
||||||
|
// No match if the site does not have a part, but the key does. Unless the key part is *
|
||||||
|
if (!isset($siteparts[$i]) ) {
|
||||||
|
if($keyparts[$i] != "*") {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$i++; //increment $i by one before break, to make sure the comparison following this loop holds.
|
||||||
|
break; // Stop comparison. Host part matches.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now do a proper case insensitive check for matching.
|
||||||
|
// Uses fnmatch to easily handle shell type wildcards.
|
||||||
|
if ( ! \fnmatch($keyparts[$i],$siteparts[$i],\FNM_CASEFOLD)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fail if the site has a deeper subdomain than the key, unless the deepest key subdomain is *
|
||||||
|
if ($keyparts[$i-1] != '*' && count($siteparts) > ($i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we made it here then the host part matches. Now check the path.
|
||||||
|
// If path is /*, matches all subpaths including /
|
||||||
|
$keypath = empty($keyurl->path)?"/":$keyurl->path;
|
||||||
|
$sitepath = empty($siteurl->path)?"/":$siteurl->path;
|
||||||
|
|
||||||
|
// Trim trailing / from both paths before comparison
|
||||||
|
if (\strlen($sitepath) > 1) {
|
||||||
|
$sitepath = \rtrim($sitepath,"/");
|
||||||
|
}
|
||||||
|
if (\strlen($keypath) > 1) {
|
||||||
|
$keypath = \rtrim($keypath,"/");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a case insensitive fnmatch on the site so wildcards are matched too.
|
||||||
|
return \fnmatch($keypath,$sitepath,\FNM_CASEFOLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tests = [
|
||||||
|
["*", "https://www.miqra.nl"],
|
||||||
|
["*/*", "https://www.miqra.nl"],
|
||||||
|
["*", "https://clients.openedu.nl/fith"],
|
||||||
|
["clients.openedu.nl/fith", "https://clients.openedu.nl/fith/"],
|
||||||
|
["clients.openedu.nl/fith/", "https://clients.openedu.nl/fith"]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach($tests as $test) {
|
||||||
|
[$key, $site] = $test;
|
||||||
|
print("Checking key '{$key}' on site '{$site}': " . (sitematch($key,$site)?"MATCH":"FAIL") . "\n");
|
||||||
|
}
|
|
@ -22,7 +22,7 @@
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494).
|
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494).
|
||||||
$plugin->version = 2024042100; // YYYYMMDDHH (year, month, day, iteration).
|
$plugin->version = 2024051000; // YYYYMMDDHH (year, month, day, iteration).
|
||||||
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
|
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
|
||||||
|
|
||||||
$plugin->release = "1.2.0";
|
$plugin->release = "1.2.0";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user