@@ -159,6 +159,9 @@ private function enhance_question_metadata($question) {
159159 $ tags = $ this ->get_question_tags ($ question ->id );
160160 $ usedin = $ this ->usagemap [$ question ->id ] ?? [];
161161
162+ // Get question bank URL parameters (handles Moodle 5's cmid vs courseid).
163+ $ qbankparams = \qtype_coderunner_util::make_question_bank_url_params ($ question );
164+
162165 $ enhanced = [
163166 'type ' => 'coderunner ' ,
164167 'id ' => (string )$ question ->id ,
@@ -168,10 +171,12 @@ private function enhance_question_metadata($question) {
168171 'coderunnertype ' => $ question ->coderunnertype ,
169172 'category ' => bulk_tester::get_category_path ($ question ->category ),
170173 'categoryid ' => (string )$ question ->category ,
174+ 'contextid ' => (string )$ question ->contextid ,
171175 'version ' => (int )$ question ->version ,
172176 'courseid ' => (string )$ courseid ,
173177 'tags ' => $ tags ,
174178 'usedin ' => $ usedin ,
179+ 'qbankparams ' => $ qbankparams ,
175180 ];
176181
177182 $ enhanced ['lines_of_code ' ] = $ this ->count_lines_of_code ($ answer );
@@ -938,18 +943,12 @@ function toggleDisplay(type, content, isHTML = false) {
938943 });
939944
940945 bankBtn.addEventListener('click', () => {
941- if (q.id && q.courseid && q.categoryid) {
942- const params = new URLSearchParams({
943- 'qperpage': '1000',
944- 'category': q.categoryid + ',' + <?php echo $ contextid ; ?> ,
945- 'lastchanged': q.id,
946- 'courseid': q.courseid,
947- 'showhidden': '1'
948- });
946+ if (q.qbankparams) {
947+ const params = new URLSearchParams(q.qbankparams);
949948 const bankUrl = `${moodleBaseUrl}/question/edit.php?${params.toString()}`;
950949 window.open(bankUrl, '_blank');
951950 } else {
952- alert('Missing question data for question bank link ');
951+ alert('Missing question bank parameters ');
953952 }
954953 });
955954
@@ -1044,7 +1043,8 @@ function buildFilters(data){
10441043 kwField.innerHTML = '';
10451044 const keys = Array.from(new Set(data.flatMap(obj => Object.keys(obj))));
10461045 const optAny = document.createElement('option'); optAny.textContent = 'Any'; kwField.appendChild(optAny);
1047- keys.filter(k => k !== 'version' && k !== 'timemodified' && k !== 'type' && k !== 'courseid' && k !== 'lines_of_code').forEach(k => {
1046+ const excludedKeys = ['version', 'timemodified', 'type', 'courseid', 'lines_of_code'];
1047+ keys.filter(k => !excludedKeys.includes(k)).forEach(k => {
10481048 const o = document.createElement('option'); o.textContent = k; kwField.appendChild(o);
10491049 });
10501050
@@ -1129,7 +1129,8 @@ function getNumericFilterRanges(){
11291129 // Advanced filter functions
11301130 function getAvailableFields() {
11311131 const keys = Array.from(new Set(rawData.flatMap(obj => Object.keys(obj))));
1132- return keys.filter(k => k !== 'version' && k !== 'timemodified' && k !== 'type' && k !== 'courseid' && k !== 'lines_of_code').sort();
1132+ const excludedKeys = ['version', 'timemodified', 'type', 'courseid', 'lines_of_code'];
1133+ return keys.filter(k => !excludedKeys.includes(k)).sort();
11331134 }
11341135
11351136 function getOperatorsForField(field) {
@@ -1147,7 +1148,10 @@ function getOperatorsForField(field) {
11471148 } else if (typeof firstValue === 'number') {
11481149 return ['equals', 'does not equal', 'greater than', 'less than', 'greater or equal', 'less or equal'];
11491150 } else {
1150- return ['contains', 'does not contain', 'equals', 'does not equal', 'starts with', 'ends with', 'is empty', 'is not empty', 'matches regex', 'does not match regex'];
1151+ return [
1152+ 'contains', 'does not contain', 'equals', 'does not equal', 'starts with', 'ends with',
1153+ 'is empty', 'is not empty', 'matches regex', 'does not match regex'
1154+ ];
11511155 }
11521156 }
11531157
0 commit comments