Fixed collation problem when casting int to varchar(255)

This commit is contained in:
PMKuipers 2024-12-31 16:44:50 +01:00
parent f98fa8623c
commit 3a478d3960
10 changed files with 85 additions and 77 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/settings",["exports","core/ajax","core/notification"],(function(_exports,_ajax,_notification){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.settings=function(key){const settings=loadsettings();return key in settings?settings[key]:null},_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};let settingcache={};function loadsettings(){return settingcache||(0,_ajax.call)([{methodname:"local_treestudyplan_getsettings",args:{}}])[0].then((response=>{settingcache=response})).catch(_notification.default.exception),settingcache}loadsettings()})); define("local_treestudyplan/util/settings",["exports","core/ajax","core/notification"],(function(_exports,_ajax,_notification){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.refreshsettings=refreshsettings,_exports.settings=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};const settings={hivizdropslots:!1,toolboxleft:!1,toolboxcoursesonly:!1,enablebadges:!1,badges_allowcoursebadges:!1,showprevnextarrows:!1,enableplansharing:!1};function refreshsettings(){(0,_ajax.call)([{methodname:"local_treestudyplan_getsettings",args:{}}])[0].then((response=>{for(const key in response)settings[key]=response[key]})).catch(_notification.default.exception)}_exports.settings=settings,refreshsettings()}));
//# sourceMappingURL=settings.min.js.map //# sourceMappingURL=settings.min.js.map

View file

@ -1 +1 @@
{"version":3,"file":"settings.min.js","sources":["../../src/util/settings.js"],"sourcesContent":["/* eslint no-var: \"error\" */\n/* eslint-env es6*/\n\nimport {call} from 'core/ajax';\nimport notification from 'core/notification';\n\n// Prepare default value.\nlet settingcache = {};\n\n/**\n * Retrieve settings.\n * @param {String} key\n * @returns {*}\n */\nexport function settings(key) {\n const settings = loadsettings();\n if (key in settings) {\n return settings[key];\n } else {\n return null;\n }\n}\n\n/**\n * Get settings from server or cache\n * @returns {Object} The settings object\n */\nfunction loadsettings() {\n if (!settingcache) {\n // Retrieve setting cache if needed.\n call([{\n methodname: 'local_treestudyplan_getsettings',\n args: {}\n }])[0].then((response) => {\n settingcache = response;\n return;\n }).catch(notification.exception);\n }\n return settingcache;\n}\n\n// Preload settings.\nloadsettings();"],"names":["key","settings","loadsettings","settingcache","methodname","args","then","response","catch","notification","exception"],"mappings":"0NAcyBA,WACfC,SAAWC,sBACbF,OAAOC,SACAA,SAASD,KAET,8EAZXG,aAAe,YAoBVD,sBACAC,6BAEI,CAAC,CACFC,WAAY,kCACZC,KAAM,MACN,GAAGC,MAAMC,WACTJ,aAAeI,YAEhBC,MAAMC,sBAAaC,WAEnBP,aAIXD"} {"version":3,"file":"settings.min.js","sources":["../../src/util/settings.js"],"sourcesContent":["/* eslint no-var: \"error\" */\n/* eslint-env es6*/\n\nimport {call} from 'core/ajax';\nimport notification from 'core/notification';\n\n// Prepare default values\nexport const settings = {\n \"hivizdropslots\" : false,\n \"toolboxleft\" : false,\n \"toolboxcoursesonly\" : false,\n \"enablebadges\" : false,\n \"badges_allowcoursebadges\" : false,\n \"showprevnextarrows\" : false,\n \"enableplansharing\" : false,\n};\n\n/**\n * Refresh settings from server\n * @returns {Object} The settings object\n */\nexport function refreshsettings() {\n call([{\n methodname: 'local_treestudyplan_getsettings',\n args: {}\n }])[0].then((response) => {\n for ( const key in response) {\n settings[key] = response[key];\n }\n }).catch(notification.exception);\n}\n\n// Preload settings.\nrefreshsettings();"],"names":["settings","refreshsettings","methodname","args","then","response","key","catch","notification","exception"],"mappings":"2UAOaA,SAAW,iBACD,eACH,sBACO,gBACN,4BACY,sBACN,qBACD,YAOVC,iCACP,CAAC,CACFC,WAAY,kCACZC,KAAM,MACN,GAAGC,MAAMC,eACH,MAAMC,OAAOD,SACfL,SAASM,KAAOD,SAASC,QAE9BC,MAAMC,sBAAaC,sCAI1BR"}

View file

@ -1383,6 +1383,7 @@ export default {
}, },
data() { data() {
return { return {
settings: settings,
config: { config: {
userfields: [ userfields: [
{key: "selected"}, {key: "selected"},
@ -1516,9 +1517,6 @@ export default {
selectedpage() { selectedpage() {
return this.value.pages[this.selectedpageindex]; return this.value.pages[this.selectedpageindex];
}, },
hivizdrop() {
return settings("hivizdropslots");
},
}, },
methods: { methods: {
columns(page) { columns(page) {
@ -1870,7 +1868,7 @@ export default {
}, },
checkTypeCourse(type) { checkTypeCourse(type) {
if (type.type == "gradable") { if (type.type == "gradable") {
if (settings("hivizdropslots") && !type.item) { if (settings.hivizdropslots && !type.item) {
return true; return true;
} else { } else {
return false; return false;
@ -1881,7 +1879,7 @@ export default {
}, },
checkTypeFilter(type) { checkTypeFilter(type) {
if (type.type == "filter") { if (type.type == "filter") {
if (settings("hivizdropslots") && !type.item) { if (settings.hivizdropslots && !type.item) {
return true; return true;
} else { } else {
return false; return false;
@ -2091,7 +2089,7 @@ export default {
></template ></template
></template ></template
></template ></template
><template v-if="hivizdrop" ><template v-if="settings.hivizdropslots"
><template v-for="(line,lineindex) in page.studylines" ><template v-for="(line,lineindex) in page.studylines"
><template v-for="(n,index) in (page.periods+1)" ><template v-for="(n,index) in (page.periods+1)"
><drop v-if="index > 0" ><drop v-if="index > 0"
@ -2489,6 +2487,7 @@ export default {
}, },
data() { data() {
return { return {
settings: settings,
text: strings.courseTiming, text: strings.courseTiming,
plantext: strings.studyplanText, plantext: strings.studyplanText,
resizeListener: null, resizeListener: null,
@ -2506,9 +2505,6 @@ export default {
}; };
}, },
methods: { methods: {
hivizdrop() {
return settings("hivizdropslots");
},
onDrop(event) { onDrop(event) {
this.hover.component = null; this.hover.component = null;
this.hover.type = null; this.hover.type = null;
@ -2636,7 +2632,7 @@ export default {
}, },
checkType(type) { checkType(type) {
if (type.type == this.type) { if (type.type == this.type) {
if (settings("hivizdropslots") && !type.item) { if (settings.hivizdropslots && !type.item) {
return false; return false;
} else { } else {
if (type == 'filter') { if (type == 'filter') {
@ -2676,7 +2672,7 @@ export default {
></t-item ></t-item
></drag ></drag
><drop v-else ><drop v-else
:class="'t-slot-drop '+type + (layer > 0?' secondary':' primary') + (hivizdrop()?' hiviz':'')" :class="'t-slot-drop '+type + (layer > 0?' secondary':' primary') + (settings.hivizdropslots?' hiviz':'')"
:accepts-type="checkType" :accepts-type="checkType"
@drop="onDrop" @drop="onDrop"
mode="cut" mode="cut"
@ -2704,7 +2700,7 @@ export default {
class="t-slot-item feedback" class="t-slot-item feedback"
:key="hover.type">--{{ hover.type }}--</div :key="hover.type">--{{ hover.type }}--</div
></template ></template
><span v-else-if="hivizdrop()">{{plantext.drophere}}</span></drop> ><span v-else-if="settings.hivizdropslots">{{plantext.drophere}}</span></drop>
<t-item-timing-checker hidden <t-item-timing-checker hidden
v-if="value && value[itemidx] && value[itemidx].course" v-if="value && value[itemidx] && value[itemidx].course"
ref="timingChecker" ref="timingChecker"
@ -4420,10 +4416,8 @@ export default {
}, },
data() { data() {
return { return {
toolboxright: !(settings("toolboxleft")), settings: settings,
toolboxcoursesonly: settings("toolboxcoursesonly"), toolboxright: !settings.toolboxleft, // Note that this default may not load correctly over lazyload.
enablebadges: settings("enablebadges"),
allowcoursebadges: settings("badges_allowcoursebadges"),
text: strings.toolbox, text: strings.toolbox,
relatedbadges: [], relatedbadges: [],
systembadges: [], systembadges: [],
@ -4474,9 +4468,6 @@ export default {
} }
}, },
methods: { methods: {
hivizdrop() {
return settings("hivizdropslots");
},
filterCategories(catlist) { filterCategories(catlist) {
const self = this; const self = this;
const list = []; const list = [];
@ -4550,9 +4541,9 @@ export default {
return; return;
}).catch(notification.exception); }).catch(notification.exception);
if (!this.toolboxcoursesonly && this.enablebadges) { if (!settings.toolboxcoursesonly && settings.enablebadges) {
this.filterSystembadges(); this.filterSystembadges();
if (this.allowcoursebadges) { if (settings.badges_allowcoursebadges) {
this.filterRelatedbadges(); this.filterRelatedbadges();
} }
} }
@ -4623,7 +4614,7 @@ export default {
</div> </div>
</div> </div>
</b-tab> </b-tab>
<b-tab :title="text.flow" v-if="!toolboxcoursesonly" class="t-toolbox-tab"> <b-tab :title="text.flow" v-if="!settings.toolboxcoursesonly" class="t-toolbox-tab">
<ul class="t-flow"> <ul class="t-flow">
<li><drag <li><drag
:type="filterComponentType" :type="filterComponentType"
@ -4648,10 +4639,10 @@ export default {
</drag></li> </drag></li>
</ul> </ul>
</b-tab> </b-tab>
<b-tab :title="text.badges" v-if="!toolboxcoursesonly && enablebadges" class="t-toolbox-tab"> <b-tab :title="text.badges" v-if="!settings.toolboxcoursesonly && settings.enablebadges" class="t-toolbox-tab">
<b-tabs content-class='mt-2 ml-2' class="t-toolbox-badges"> <b-tabs content-class='mt-2 ml-2' class="t-toolbox-badges">
<b-tab :title="text.relatedbadges" v-if="allowcoursebadges"> <b-tab :title="text.relatedbadges" v-if="settings.badges_allowcoursebadges">
<div class="t-toolbox-badges-filter"> <div class="t-toolbox-badges-filter">
<input v-model="filters.relatedbadges" @input="filterRelatedbadges" :placeholder="text.filter"></input> <input v-model="filters.relatedbadges" @input="filterRelatedbadges" :placeholder="text.filter"></input>
&nbsp;<a @click="resetRelatedbadges" v-if="filters.relatedbadges" href='#' &nbsp;<a @click="resetRelatedbadges" v-if="filters.relatedbadges" href='#'

View file

@ -498,7 +498,7 @@ export default {
}, },
data() { data() {
return { return {
showarrows: settings("showprevnextarrows"), settings: settings,
text: strings.prevnext, text: strings.prevnext,
}; };
}, },
@ -572,14 +572,14 @@ export default {
}, },
template: ` template: `
<div :class="'s-prevnext-selector '"> <div :class="'s-prevnext-selector '">
<template v-if="showarrows" <template v-if="settings.showprevnextarrows"
><b-button :variant='variant' @click="prev" :disabled="atFirst()" ><b-button :variant='variant' @click="prev" :disabled="atFirst()"
><i v-if='arrows' class='fa fa-caret-left s-prevnext-arrow'></i ><i v-if='arrows' class='fa fa-caret-left s-prevnext-arrow'></i
><template v-else>{{text.prev}}</template></b-button ><template v-else>{{text.prev}}</template></b-button
>&nbsp;</template >&nbsp;</template
><b-form-select v-model="bubblevalue" ><b-form-select v-model="bubblevalue"
@change='selectedchanged' @change='selectedchanged'
><b-form-select-option ><b-form-select-option
:disabled="!defaultselectable" :disabled="!defaultselectable"
:value="null" :value="null"
:class="(defaultselectable)?'font-italic text-primary ':'font-italic'" :class="(defaultselectable)?'font-italic text-primary ':'font-italic'"
@ -605,7 +605,7 @@ export default {
><slot :value="o">{{o[titlefield]}}</slot></b-form-select-option ><slot :value="o">{{o[titlefield]}}</slot></b-form-select-option
></template ></template
></b-form-select ></b-form-select
><template v-if="showarrows" ><template v-if="settings.showprevnextarrows"
>&nbsp;<b-button :variant='variant' @click="next" :disabled="atLast()" >&nbsp;<b-button :variant='variant' @click="next" :disabled="atLast()"
><i v-if='arrows' class='fa fa-caret-right s-prevnext-arrow'></i ><i v-if='arrows' class='fa fa-caret-right s-prevnext-arrow'></i
><template v-else>{{text.next}}</template></b-button ><template v-else>{{text.next}}</template></b-button

View file

@ -4,40 +4,31 @@
import {call} from 'core/ajax'; import {call} from 'core/ajax';
import notification from 'core/notification'; import notification from 'core/notification';
// Prepare default value. // Prepare default values
let settingcache = {}; export const settings = {
"hivizdropslots" : false,
"toolboxleft" : false,
"toolboxcoursesonly" : false,
"enablebadges" : false,
"badges_allowcoursebadges" : false,
"showprevnextarrows" : false,
"enableplansharing" : false,
};
/** /**
* Retrieve settings. * Refresh settings from server
* @param {String} key
* @returns {*}
*/
export function settings(key) {
const settings = loadsettings();
if (key in settings) {
return settings[key];
} else {
return null;
}
}
/**
* Get settings from server or cache
* @returns {Object} The settings object * @returns {Object} The settings object
*/ */
function loadsettings() { export function refreshsettings() {
if (!settingcache) { call([{
// Retrieve setting cache if needed. methodname: 'local_treestudyplan_getsettings',
call([{ args: {}
methodname: 'local_treestudyplan_getsettings', }])[0].then((response) => {
args: {} for ( const key in response) {
}])[0].then((response) => { settings[key] = response[key];
settingcache = response; }
return; }).catch(notification.exception);
}).catch(notification.exception);
}
return settingcache;
} }
// Preload settings. // Preload settings.
loadsettings(); refreshsettings();

View file

@ -777,12 +777,13 @@ class badgeinfo {
*/ */
public static function find_badges_by_course_relation($course, $search='', $active=false) { public static function find_badges_by_course_relation($course, $search='', $active=false) {
global $DB; global $DB;
if (is_int($course)) { if (is_numeric($course)) {
$courseid = $course; $courseid = (int)$course;
} else if (is_object($course)) { } else if (is_object($course)) {
$courseid = $course->id; $courseid = $course->id;
} else { } else {
throw new \moodle_exception("\$course argument must be course id or course object", "local_treestudyplan"); throw new \moodle_exception("\$course argument must be course id or course object", "local_treestudyplan",
'', null, var_export($course,true));
} }
$search = trim($search); $search = trim($search);
@ -804,6 +805,7 @@ class badgeinfo {
SQL_PARAMS_NAMED); SQL_PARAMS_NAMED);
$sqlparams = array_merge($basesqlparams, $ctypeinparams); $sqlparams = array_merge($basesqlparams, $ctypeinparams);
// IMPORTANT: p.value in query below is varchar(255), but contains an int.
$sql = "SELECT DISTINCT b.id from {badge} b $sql = "SELECT DISTINCT b.id from {badge} b
INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid
INNER JOIN {badge_criteria_param} p on p.critid = crit.id INNER JOIN {badge_criteria_param} p on p.critid = crit.id
@ -816,7 +818,7 @@ class badgeinfo {
$sql = "SELECT DISTINCT b.id from {badge} b $sql = "SELECT DISTINCT b.id from {badge} b
INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid
INNER JOIN {badge_criteria_param} p on p.critid = crit.id INNER JOIN {badge_criteria_param} p on p.critid = crit.id
INNER JOIN {competency_coursecomp} cc on CAST(cc.competencyid as VARCHAR(255)) = p.value INNER JOIN {competency_coursecomp} cc on cc.competencyid = CAST(COALESCE(p.value, 0) as INTEGER)
WHERE cc.courseid = :courseid AND crit.criteriatype $ctypesql $conditions"; WHERE cc.courseid = :courseid AND crit.criteriatype $ctypesql $conditions";
$competencyrelids = $DB->get_fieldset_sql($sql, $sqlparams); $competencyrelids = $DB->get_fieldset_sql($sql, $sqlparams);
@ -882,20 +884,44 @@ class badgeinfo {
* *
*/ */
public static function find_page_related_badges(studyplanpage $page, $search="", $active=false, $includecoursebadges=true) { public static function find_page_related_badges(studyplanpage $page, $search="", $active=false, $includecoursebadges=true) {
global $DB;
$badgeids = []; $badgeids = [];
foreach (studyline::find_page_children($page) as $line) {
foreach (studyitem::find_studyline_children($line) as $item) { if (true) {
if ($item->type() == studyitem::COURSE && $item->courseid()) { $coursesql =
$courseid = $item->courseid(); "SELECT DISTINCT i.course_id
$relatedbadges = self::find_badges_by_course_relation($courseid, $search, $active); FROM {local_treestudyplan_item} i
foreach ($relatedbadges as $id) { INNER JOIN {local_treestudyplan_line} l ON l.id = i.line_id
WHERE l.page_id = :pageid AND i.type = :coursetype
";
$courseids = $DB->get_fieldset_sql($coursesql, ["pageid" => $page->id(), "coursetype" => studyitem::COURSE]);
foreach ($courseids as $courseid) {
$relatedbadges = self::find_badges_by_course_relation($courseid, $search, $active);
foreach ($relatedbadges as $id) {
$badgeids[] = $id;
}
if ($includecoursebadges) {
$coursebadges = self::find_course_badges($courseid, $search, $active);
foreach ($coursebadges as $id) {
$badgeids[] = $id; $badgeids[] = $id;
} }
if ($includecoursebadges) { }
$coursebadges = self::find_course_badges($courseid, $search, $active); }
foreach ($coursebadges as $id) { } else {
foreach (studyline::find_page_children($page) as $line) {
foreach (studyitem::find_studyline_children($line) as $item) {
if ($item->type() == studyitem::COURSE && $item->courseid()) {
$courseid = $item->courseid();
$relatedbadges = self::find_badges_by_course_relation($courseid, $search, $active);
foreach ($relatedbadges as $id) {
$badgeids[] = $id; $badgeids[] = $id;
} }
if ($includecoursebadges) {
$coursebadges = self::find_course_badges($courseid, $search, $active);
foreach ($coursebadges as $id) {
$badgeids[] = $id;
}
}
} }
} }
} }