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

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

View file

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

View file

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

View file

@ -777,12 +777,13 @@ class badgeinfo {
*/
public static function find_badges_by_course_relation($course, $search='', $active=false) {
global $DB;
if (is_int($course)) {
$courseid = $course;
if (is_numeric($course)) {
$courseid = (int)$course;
} else if (is_object($course)) {
$courseid = $course->id;
} 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);
@ -804,6 +805,7 @@ class badgeinfo {
SQL_PARAMS_NAMED);
$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
INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid
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
INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid
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";
$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) {
global $DB;
$badgeids = [];
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) {
if (true) {
$coursesql =
"SELECT DISTINCT i.course_id
FROM {local_treestudyplan_item} i
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;
}
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;
}
if ($includecoursebadges) {
$coursebadges = self::find_course_badges($courseid, $search, $active);
foreach ($coursebadges as $id) {
$badgeids[] = $id;
}
}
}
}
}