Added option to remove timing from periods

This commit is contained in:
PMKuipers 2024-03-10 23:09:33 +01:00
parent 3002a866bb
commit 310f042772
17 changed files with 117 additions and 62 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
define("local_treestudyplan/util/date-helper",["exports"],(function(_exports){function format_date(d,short){d instanceof Date||("number"==typeof d&&(d*=1e3),d=new Date(d));let monthformat="short";return!0===short?monthformat="numeric":!1===short&&(monthformat="long"),d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})}function studyplanDates(plan){let earliestStart=null,latestEnd=null,openEnded=!1;for(const ix in plan.pages){const page=plan.pages[ix],s=new Date(page.startdate);if(page.enddate||(openEnded=!0),(!earliestStart||s<earliestStart)&&(earliestStart=s),page.enddate){const e=new Date(page.enddate);(!latestEnd||e>latestEnd)&&(latestEnd=e)}}return{start:earliestStart,end:openEnded?null:latestEnd}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.add_days=function(datestr,days){const date=new Date(datestr);return function(date){const d=new Date(date);let month=""+(d.getMonth()+1),day=""+d.getDate();const year=d.getFullYear();month.length<2&&(month="0"+month);day.length<2&&(day="0"+day);return[year,month,day].join("-")}(new Date(date.getTime()+864e5*days))},_exports.datespaninfo=function(first,last){first instanceof Date||(first=new Date(first));last instanceof Date||(last=new Date(last));first.setHours(0),first.setMinutes(0),first.setSeconds(0),first.setMilliseconds(0),last.setHours(23),last.setMinutes(59),last.setSeconds(59),last.setMilliseconds(999);const dayspan=Math.round((last-first+1)/864e5),years=Math.floor(dayspan/365),ydaysleft=dayspan%365,weeks=Math.floor(ydaysleft/7);return{first:first,last:last,totaldays:dayspan,years:years,weeks:weeks,days:ydaysleft%7,formatted:{first:format_date(first),last:format_date(last)}}},_exports.format_date=format_date,_exports.format_datetime=function(d,short){d instanceof Date||("number"==typeof d&&(d*=1e3),d=new Date(d));let monthformat="short";!0===short?monthformat="numeric":!1===short&&(monthformat="long");return d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})+" "+d.toLocaleTimeString(document.documentElement.lang,{timeStyle:"short"})},_exports.studyplanDates=studyplanDates,_exports.studyplanPageTiming=function(page){const now=(new Date).getTime(),start=new Date(page.startdate),end=page.enddate?new Date(page.enddate):null;return start<now?end&&now>end?"past":"present":"future"},_exports.studyplanTiming=function(plan){const now=(new Date).getTime(),dates=studyplanDates(plan);return dates.start<now?dates.end&&now>dates.end?"past":"present":"future"}})); define("local_treestudyplan/util/date-helper",["exports"],(function(_exports){function format_date(d,short){d instanceof Date||("number"==typeof d&&(d*=1e3),d=new Date(d));let monthformat="short";return!0===short?monthformat="numeric":!1===short&&(monthformat="long"),d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})}function studyplanDates(plan){let earliestStart=null,latestEnd=null,openEnded=!1;for(const ix in plan.pages){const page=plan.pages[ix],s=new Date(page.startdate);if(page.enddate||(openEnded=!0),(!earliestStart||s<earliestStart)&&(earliestStart=s),page.enddate){const e=new Date(page.enddate);(!latestEnd||e>latestEnd)&&(latestEnd=e)}}return{start:earliestStart,end:openEnded?null:latestEnd}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.add_days=function(datestr,days){const date=new Date(datestr);return function(date){const d=new Date(date);let month=""+(d.getMonth()+1),day=""+d.getDate();const year=d.getFullYear();month.length<2&&(month="0"+month);day.length<2&&(day="0"+day);return[year,month,day].join("-")}(new Date(date.getTime()+864e5*days))},_exports.datespaninfo=function(first,last){first instanceof Date||(first=new Date(first));last instanceof Date||(last=new Date(last));first.setHours(0),first.setMinutes(0),first.setSeconds(0),first.setMilliseconds(0),last.setHours(23),last.setMinutes(59),last.setSeconds(59),last.setMilliseconds(999);const dayspan=Math.round((last-first+1)/864e5),years=Math.floor(dayspan/365),ydaysleft=dayspan%365,weeks=Math.floor(ydaysleft/7);return{first:first,last:last,totaldays:dayspan,years:years,weeks:weeks,days:ydaysleft%7,formatted:{first:format_date(first),last:format_date(last)}}},_exports.format_date=format_date,_exports.format_datetime=function(d,short){d instanceof Date||("number"==typeof d&&(d*=1e3),d=new Date(d));let monthformat="short";!0===short?monthformat="numeric":!1===short&&(monthformat="long");return d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})+" "+d.toLocaleTimeString(document.documentElement.lang,{timeStyle:"short"})},_exports.studyplanDates=studyplanDates,_exports.studyplanPageTiming=function(page){const now=(new Date).getTime();if(page.timeless)return"present";const start=new Date(page.startdate),end=page.enddate?new Date(page.enddate):null;return start<now?end&&now>end?"past":"present":"future"},_exports.studyplanTiming=function(plan){const now=(new Date).getTime();if(!plan.pages&&0==plan.pages.length||plan.pages[0].timeless)return"present";const dates=studyplanDates(plan);return dates.start<now?dates.end&&now>dates.end?"past":"present":"future"}}));
//# sourceMappingURL=date-helper.min.js.map //# sourceMappingURL=date-helper.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -1318,7 +1318,7 @@ export default {
></b-form-input> ></b-form-input>
</b-col> </b-col>
</b-row> </b-row>
<b-row> <b-row v-if="!value.timeless">
<b-col cols="4">{{ text.studyplan_startdate}}</b-col> <b-col cols="4">{{ text.studyplan_startdate}}</b-col>
<b-col cols="8"> <b-col cols="8">
<b-form-datepicker <b-form-datepicker
@ -1329,7 +1329,7 @@ export default {
></b-form-datepicker> ></b-form-datepicker>
</b-col> </b-col>
</b-row> </b-row>
<b-row> <b-row v-if="!value.timeless">
<b-col cols="4">{{ text.studyplan_enddate}}</b-col> <b-col cols="4">{{ text.studyplan_enddate}}</b-col>
<b-col cols="8"> <b-col cols="8">
<b-form-datepicker <b-form-datepicker
@ -1708,13 +1708,13 @@ export default {
return show; return show;
}, },
periodEdited(pi) { periodEdited(pi) {
const prev = this.$refs["periodeditor-" + (pi.period - 1)][0]; const prev = this.$refs["periodeditor-" + (pi.period - 1)];
if(prev) { if(prev && prev[0]) {
prev.refresh(); prev[0].refresh();
} }
const next = this.$refs["periodeditor-" + (pi.period + 1)][0]; const next = this.$refs["periodeditor-" + (pi.period + 1)];
if(next) { if(next && next[0]) {
next.refresh(); next[0].refresh();
} }
}, },
add_day(date,days) { add_day(date,days) {
@ -2544,6 +2544,10 @@ export default {
}, },
course_period_matches() { course_period_matches() {
const self=this; const self=this;
if (self.page.timeless) {
// Always return true in timeless mode.
return true ;
}
if(self.value && self.value.type == 'course'){ if(self.value && self.value.type == 'course'){
self.datechanger.coursespan = datespaninfo(self.value.course.startdate,self.value.course.enddate); self.datechanger.coursespan = datespaninfo(self.value.course.startdate,self.value.course.enddate);
self.datechanger.periodspan = datespaninfo(self.period.startdate,self.endperiod.enddate); self.datechanger.periodspan = datespaninfo(self.period.startdate,self.endperiod.enddate);
@ -2576,6 +2580,7 @@ export default {
validate_course_period() { validate_course_period() {
const self = this; const self = this;
if (! self.page.timeless) {
debug.info("Validating course and period"); debug.info("Validating course and period");
if(!(self.course_period_matches)){ if(!(self.course_period_matches)){
debug.info("Course timing does not match period timing"); debug.info("Course timing does not match period timing");
@ -2599,6 +2604,10 @@ export default {
else { else {
debug.info("Course timing matches period",self.datechanger); debug.info("Course timing matches period",self.datechanger);
} }
}
else {
debug.info("Skipping course timing check because of timeless mode",self.datechanger);
}
}, },
has_filter() { has_filter() {
const slots = this.page.slots; const slots = this.page.slots;
@ -4202,7 +4211,7 @@ export default {
self.loadingcourses = true; self.loadingcourses = true;
call([{ call([{
methodname: 'local_treestudyplan_map_categories', methodname: 'local_treestudyplan_map_categories',
args: { studyplanid: self.studyplanid} args: { studyplan_id: self.studyplanid}
}])[0].then(function(response){ }])[0].then(function(response){
self.courses = response; self.courses = response;
self.loadingcourses = false; self.loadingcourses = false;

View File

@ -59,6 +59,14 @@ export default {
}; };
}, },
computed: { computed: {
timeless() {
const plan = this.value;
if (!plan.pages || plan.pages.length == 0 || plan.pages[0].timeless) {
return true;
} else {
return false;
}
},
timing(){ timing(){
return studyplanTiming(this.value); return studyplanTiming(this.value);
}, },
@ -110,7 +118,7 @@ export default {
</div> </div>
<slot></slot> <slot></slot>
<template #footer> <template #footer>
<span :class="'t-timing-'+timing" v-html="dates.start + ' - '+ dates.end"></span> <span v-if="!timeless" :class="'t-timing-'+timing" v-html="dates.start + ' - '+ dates.end"></span>
<span class="s-studyplan-card-buttons"> <span class="s-studyplan-card-buttons">
<slot name='footer'></slot> <slot name='footer'></slot>
<s-studyplan-details <s-studyplan-details
@ -290,7 +298,8 @@ export default {
</span> </span>
</b-tooltip> </b-tooltip>
<slot></slot <slot></slot
><p class="s-studyline-header-period-datespan small"> ><p v-if="value.startdate > 0"
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">{{ enddate }}</span>
</p> </p>
<div v-if="current" class='s-studyline-period-highlight'></div> <div v-if="current" class='s-studyline-period-highlight'></div>

View File

@ -134,6 +134,7 @@ export function studyplanDates(plan) {
let earliestStart = null; let earliestStart = null;
let latestEnd = null; let latestEnd = null;
let openEnded = false; let openEnded = false;
for(const ix in plan.pages) { for(const ix in plan.pages) {
const page = plan.pages[ix]; const page = plan.pages[ix];
const s = new Date(page.startdate); const s = new Date(page.startdate);
@ -165,6 +166,12 @@ export function studyplanDates(plan) {
*/ */
export function studyplanTiming(plan) { export function studyplanTiming(plan) {
const now = new Date().getTime(); const now = new Date().getTime();
// If timeless or no timing info is available, all plans are present
if (!plan.pages && plan.pages.length == 0 || plan.pages[0].timeless) {
return 'present';
}
const dates = studyplanDates(plan); const dates = studyplanDates(plan);
if(dates.start < now){ if(dates.start < now){
@ -185,6 +192,10 @@ export function studyplanTiming(plan) {
*/ */
export function studyplanPageTiming(page) { export function studyplanPageTiming(page) {
const now = new Date().getTime(); const now = new Date().getTime();
if (page.timeless) {
return "present";
}
const start = new Date(page.startdate); const start = new Date(page.startdate);
const end = (page.enddate)?(new Date(page.enddate)):null; const end = (page.enddate)?(new Date(page.enddate)):null;

View File

@ -195,6 +195,8 @@ class studyplan_editform extends formbase {
); );
if ($customdata->create) { if ($customdata->create) {
$timeless = \get_config("local_treestudyplan","timelessperiods");
if ( !$timeless) {
// Only add these fields if a new studyplan is created, to easily initialize the first page // Only add these fields if a new studyplan is created, to easily initialize the first page
$field = 'startdate'; $field = 'startdate';
$mform->addElement('date_selector',$field, $mform->addElement('date_selector',$field,
@ -207,7 +209,7 @@ class studyplan_editform extends formbase {
get_string('studyplan_startdate','local_treestudyplan'), get_string('studyplan_startdate','local_treestudyplan'),
[]); []);
$mform->addRule($field, null, 'required', null, 'client'); $mform->addRule($field, null, 'required', null, 'client');
}
$field = 'periods'; $field = 'periods';
$mform->addElement('text_integer',$field, $mform->addElement('text_integer',$field,
get_string('studyplan_slots','local_treestudyplan'), get_string('studyplan_slots','local_treestudyplan'),

View File

@ -159,6 +159,8 @@ class studyplanpage_editform extends formbase {
[]); []);
$mform->addRule($field, null, 'required', null, 'client'); $mform->addRule($field, null, 'required', null, 'client');
$timeless = \get_config("local_treestudyplan","timelessperiods");
if ( !$timeless) {
$field = 'startdate'; $field = 'startdate';
$mform->addElement('date_selector',$field, $mform->addElement('date_selector',$field,
get_string('studyplan_startdate','local_treestudyplan'), get_string('studyplan_startdate','local_treestudyplan'),
@ -170,10 +172,11 @@ class studyplanpage_editform extends formbase {
get_string('studyplan_startdate','local_treestudyplan'), get_string('studyplan_startdate','local_treestudyplan'),
[]); []);
$mform->addRule($field, null, 'required', null, 'client'); $mform->addRule($field, null, 'required', null, 'client');
}
$field = 'periods'; $field = 'periods';
$mform->addElement('text_integer',$field, $mform->addElement('text_integer',$field,
get_string('studyplan_slots','local_treestudyplan'), get_string( ($timeless)?'studyplan_slots':'studyplan_periods','local_treestudyplan'),
["unsigned" => true, "nonzero" => true]); ["unsigned" => true, "nonzero" => true]);
$mform->setType($field, PARAM_INT); $mform->setType($field, PARAM_INT);
$mform->addRule($field, null, 'required', null, 'client'); $mform->addRule($field, null, 'required', null, 'client');

View File

@ -238,6 +238,7 @@ class period {
"period" => new \external_value(PARAM_INT, 'period sequence'), "period" => new \external_value(PARAM_INT, 'period sequence'),
"startdate" => new \external_value(PARAM_TEXT, 'start date of period'), "startdate" => new \external_value(PARAM_TEXT, 'start date of period'),
"enddate" => new \external_value(PARAM_TEXT, 'end date of period'), "enddate" => new \external_value(PARAM_TEXT, 'end date of period'),
"timeless" => new \external_value(PARAM_BOOL, 'Page does not include time information'),
], 'Period info', $value); ], 'Period info', $value);
} }
@ -246,13 +247,15 @@ class period {
* @return array Webservice data model * @return array Webservice data model
*/ */
public function model() { public function model() {
$timeless = get_config("local_treestudyplan","timelessperiods");
return [ return [
'id' => $this->r->id, 'id' => $this->r->id,
'fullname' => $this->r->fullname, 'fullname' => $this->r->fullname,
'shortname' => $this->r->shortname, 'shortname' => $this->r->shortname,
'period' => $this->r->period, 'period' => $this->r->period,
'startdate' => $this->r->startdate, 'startdate' => ($timeless)?0:$this->r->startdate,
'enddate' => $this->r->enddate, 'enddate' => ($timeless)?0:$this->r->enddate,
'timeless' => $timeless,
]; ];
} }

View File

@ -192,6 +192,7 @@ class studyplanpage {
"enddate" => new \external_value(PARAM_TEXT, 'end date of studyplan'), "enddate" => new \external_value(PARAM_TEXT, 'end date of studyplan'),
"timing" => new \external_value(PARAM_TEXT, '(past|present|future)'), "timing" => new \external_value(PARAM_TEXT, '(past|present|future)'),
"perioddesc" => period::page_structure(), "perioddesc" => period::page_structure(),
"timeless" => new \external_value(PARAM_BOOL, 'Page does not in'),
], 'Studyplan page basic info', $value); ], 'Studyplan page basic info', $value);
} }
@ -210,6 +211,7 @@ class studyplanpage {
'enddate' => $this->r->enddate, 'enddate' => $this->r->enddate,
'timing' => $this->timing(), 'timing' => $this->timing(),
"perioddesc" => period::page_model($this), "perioddesc" => period::page_model($this),
'timeless' => \get_config("local_treestudyplan","timelessperiods"),
]; ];
} }
@ -229,6 +231,7 @@ class studyplanpage {
"timing" => new \external_value(PARAM_TEXT, '(past|present|future)'), "timing" => new \external_value(PARAM_TEXT, '(past|present|future)'),
"studylines" => new \external_multiple_structure(studyline::editor_structure()), "studylines" => new \external_multiple_structure(studyline::editor_structure()),
"perioddesc" => period::page_structure(), "perioddesc" => period::page_structure(),
"timeless" => new \external_value(PARAM_BOOL, 'Page does not include time information'),
], 'Studyplan page full structure', $value); ], 'Studyplan page full structure', $value);
} }
@ -250,6 +253,7 @@ class studyplanpage {
'timing' => $this->timing(), 'timing' => $this->timing(),
'studylines' => [], 'studylines' => [],
"perioddesc" => period::page_model($this), "perioddesc" => period::page_model($this),
'timeless' => \get_config("local_treestudyplan","timelessperiods"),
]; ];
$children = studyline::find_page_children($this); $children = studyline::find_page_children($this);

View File

@ -114,8 +114,10 @@ $string["settingdesc_enableplansharing"] = 'Allow students to share access to th
$string["setting_limitcourselist"] = 'Limit course list to studyplan category'; $string["setting_limitcourselist"] = 'Limit course list to studyplan category';
$string["settingdesc_limitcourselist"] = 'Limit the list of available courses for a studyplan to the category the studyplan is located in.'; $string["settingdesc_limitcourselist"] = 'Limit the list of available courses for a studyplan to the category the studyplan is located in.';
$string["setting_enablecoach"] = 'Enable coach rolae'; $string["setting_enablecoach"] = 'Enable coach role';
$string["settingdesc_enablecoach"] = 'The coach role allows one coach specific access to one studyplan with limited access to modify it.'; $string["settingdesc_enablecoach"] = 'The coach role allows one coach specific access to one studyplan with limited access to modify it.';
$string["setting_timelessperiods"] = 'Timeless periods and pages';
$string["settingdesc_timelessperiods"] = 'Do not include timing info in periods or pages';
$string["setting_courseprogressbar"] = 'Show progress bar in course'; $string["setting_courseprogressbar"] = 'Show progress bar in course';
$string["settingdesc_courseprogressbar"] = 'Show a progress bar in the course popup'; $string["settingdesc_courseprogressbar"] = 'Show a progress bar in the course popup';
@ -123,6 +125,7 @@ $string["settingdesc_courseprogressbar"] = 'Show a progress bar in the course po
$string["setting_infofields_heading"] = 'Extra course information fields'; $string["setting_infofields_heading"] = 'Extra course information fields';
$string["settingdesc_infofields_heading"] = 'Select up to 5 fields or custom fields to add to the course popup'; $string["settingdesc_infofields_heading"] = 'Select up to 5 fields or custom fields to add to the course popup';
$string["infofield_position_above"] = 'Above course results'; $string["infofield_position_above"] = 'Above course results';
$string["infofield_position_below"] = 'Below course results'; $string["infofield_position_below"] = 'Below course results';
$string["infofield_position_header"] = 'Header '; $string["infofield_position_header"] = 'Header ';
@ -165,7 +168,8 @@ $string["studyplan_idnumber_ph"] = '';
$string["studyplan_description"] = 'Description'; $string["studyplan_description"] = 'Description';
$string["studyplan_description_ph"] = ''; $string["studyplan_description_ph"] = '';
$string["studyplan_details"] = 'About'; $string["studyplan_details"] = 'About';
$string["studyplan_slots"] = 'Number of periods in plan'; $string["studyplan_slots"] = 'Number of columns in plan';
$string["studyplan_periods"] = 'Number of periods in plan';
$string["studyplan_startdate"] = 'Start date of plan'; $string["studyplan_startdate"] = 'Start date of plan';
$string["studyplan_enddate"] = 'End date of plan'; $string["studyplan_enddate"] = 'End date of plan';
$string["studyplan_noneselected"] = "Pick a study plan to start editing"; $string["studyplan_noneselected"] = "Pick a study plan to start editing";

View File

@ -117,6 +117,8 @@ $string["setting_limitcourselist"] = 'Cursusenlijst beperken tot categorie';
$string["settingdesc_limitcourselist"] = 'Beperk de lijst met beschikbare cursussen om in een studieplan te slepen tot de cateogrie waarin het studieplan zich bevindt.'; $string["settingdesc_limitcourselist"] = 'Beperk de lijst met beschikbare cursussen om in een studieplan te slepen tot de cateogrie waarin het studieplan zich bevindt.';
$string["setting_enablecoach"] = 'Coach rol inschakelen'; $string["setting_enablecoach"] = 'Coach rol inschakelen';
$string["settingdesc_enablecoach"] = 'Een coach kan aan een specifiek studieplan gekoppeld worden om deze te bewerken en studentresultaten te bekijken.'; $string["settingdesc_enablecoach"] = 'Een coach kan aan een specifiek studieplan gekoppeld worden om deze te bewerken en studentresultaten te bekijken.';
$string["setting_timelessperiods"] = 'Tabbladen en periodes zonder tijd';
$string["settingdesc_timelessperiods"] = 'Gebruik geen tijdinformatie in perioden en tabbladen';
$string["setting_courseprogressbar"] = 'Toon voortgangsbalk in cursus'; $string["setting_courseprogressbar"] = 'Toon voortgangsbalk in cursus';
$string["settingdesc_courseprogressbar"] = 'Laat een voortgangsbalk zien in de cursuspopup'; $string["settingdesc_courseprogressbar"] = 'Laat een voortgangsbalk zien in de cursuspopup';
@ -166,7 +168,8 @@ $string["studyplan_idnumber_ph"] = '';
$string["studyplan_description"] = 'Beschrijving'; $string["studyplan_description"] = 'Beschrijving';
$string["studyplan_details"] = 'Meer info'; $string["studyplan_details"] = 'Meer info';
$string["studyplan_description_ph"] = ''; $string["studyplan_description_ph"] = '';
$string["studyplan_slots"] = 'Aantal periodes in studieplan'; $string["studyplan_slots"] = 'Aantal kolommen in studieplan';
$string["studyplan_periods"] = 'Aantal periodes in studieplan';
$string["studyplan_startdate"] = 'Startdatum'; $string["studyplan_startdate"] = 'Startdatum';
$string["studyplan_enddate"] = 'Einddatum'; $string["studyplan_enddate"] = 'Einddatum';
$string["studyplan_noneselected"] = "Kies een studieplan uit de lijst"; $string["studyplan_noneselected"] = "Kies een studieplan uit de lijst";

View File

@ -113,6 +113,13 @@ if ($hassiteconfig) {
true, true,
)); ));
//get_config("local_treestudyplan","timelessperiods")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/timelessperiods',
get_string('setting_timelessperiods', 'local_treestudyplan'),
get_string('settingdesc_timelessperiods', 'local_treestudyplan'),
false,
));
//get_config("local_treestudyplan","limitcourselist") //get_config("local_treestudyplan","limitcourselist")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/limitcourselist', $page->add(new admin_setting_configcheckbox('local_treestudyplan/limitcourselist',
get_string('setting_limitcourselist', 'local_treestudyplan'), get_string('setting_limitcourselist', 'local_treestudyplan'),

View File

@ -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 = 2024031002; // YYYYMMDDHH (year, month, day, iteration). $plugin->version = 2024031003; // 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.1.6"; $plugin->release = "1.1.6";