Merge branch 'master_MDL-71641-tagquestion' of https://github.com/catalyst/moodle-MDL-70329
This commit is contained in:
Vendored
+1
-1
@@ -1,2 +1,2 @@
|
||||
define ("core_question/edit_tags",["jquery","core/fragment","core/str","core/modal_events","core/modal_factory","core/notification","core/custom_interaction_events","core_question/repository","core_question/selectors"],function(a,b,c,d,e,f,g,h,i){var j=function(a){a.find(i.actions.save).prop("disabled",!1)},k=function(a){a.find(i.actions.save).prop("disabled",!0)},l=function(a){return a.getBody().find("form").serialize()},m=function(a){var b=a.find(i.containers.loadingIcon);b.removeClass("hidden")},n=function(a){var b=a.find(i.containers.loadingIcon);b.addClass("hidden")},o=function(a,b){a.getBody().attr("data-contextid",b)},p=function(a){return a.getBody().data("contextid")},q=function(a,b){a.getBody().attr("data-questionid",b)},r=function(a){return a.getBody().data("questionid")},s=function(h){var l=e.create({type:e.types.SAVE_CANCEL,large:!1},[h,i.actions.edittags]).then(function(a){c.get_string("questiontags","question").then(function(b){a.setTitle(b);return b}).fail(f.exception);a.getRoot().on(d.save,function(b){var c=a.getBody().find("form");c.submit();b.preventDefault()});a.getRoot().on("submit","form",function(b){t(a,h).then(function(){a.hide();location.reload()}).fail(f.exception);b.preventDefault();b.stopPropagation()});return a});h.on(g.events.activate,i.actions.edittags,function(c){var d=a(c.currentTarget),e=d.data("questionid"),g=!!d.data("cantag"),p=d.data("contextid");l.then(function(a){k(h);m(h);var c=b.loadFragment("question","tags_form",p,{id:e});a.setBody(c);c.then(function(){j(h)}).always(function(){n(h)}).fail(f.exception);if(g){a.getRoot().find(i.actions.save).show()}else{a.getRoot().find(i.actions.save).hide()}q(a,e);o(a,p);return a}).fail(f.exception);c.preventDefault()})},t=function(a,b){k(b);m(b);var c=l(a),d=r(a),e=p(a);return h.submitTagCreateUpdateForm(d,e,c).always(function(){n(b);j(b)}).fail(f.exception)};return{init:function init(b){b=a(b);s(b)}}});
|
||||
define ("core_question/edit_tags",["jquery","core/fragment","core/str","core/modal_events","core/modal_factory","core/notification","core/custom_interaction_events","core_question/repository","core_question/selectors"],function(a,b,c,d,e,f,g,h,i){var j=function(a){a.find(i.actions.save).prop("disabled",!1)},k=function(a){a.find(i.actions.save).prop("disabled",!0)},l=function(a){return a.getBody().find("form").serialize()},m=function(a){var b=a.find(i.containers.loadingIcon);b.removeClass("hidden")},n=function(a){var b=a.find(i.containers.loadingIcon);b.addClass("hidden")},o=function(a,b){a.getBody().attr("data-contextid",b)},p=function(a){return a.getBody().data("contextid")},q=function(a,b){a.getBody().attr("data-questionid",b)},r=function(a){return a.getBody().data("questionid")},s=function(h){var l=e.create({type:e.types.SAVE_CANCEL,large:!1},[h,i.actions.edittags]).then(function(a){c.get_string("questiontags","question").then(function(b){a.setTitle(b);return b}).fail(f.exception);a.getRoot().on(d.save,function(b){var c=a.getBody().find("form");c.submit();b.preventDefault()});a.getRoot().on("submit","form",function(b){t(a,h).then(function(){a.hide();location.reload()}).fail(f.exception);b.preventDefault();b.stopPropagation()});return a});h.on(g.events.activate,i.actions.edittags,function(c){var d=a(c.currentTarget),e=d.data("questionid"),g=!!d.data("cantag"),p=d.data("contextid");l.then(function(a){k(h);m(h);var c=b.loadFragment("question","tags_form",p,{id:e});a.setBody(c);c.then(function(){j(h)}).always(function(){n(h)}).fail(f.exception);if(g){a.getRoot().find(i.actions.save).show()}else{a.getRoot().find(i.actions.save).hide()}q(a,e);o(a,p);return a}).fail(f.exception);c.preventDefault()})},t=function(a,b){k(b);m(b);var c=l(a),d=r(a),e=p(a);return h.submitTagCreateUpdateForm(d,e,c).always(function(){n(b);j(b)}).fail(f.exception)};return{init:function init(b){window.console.warn("warn: The core_question/repository has been deprecated.Please use qbank_tagquestion/repository instead.");b=a(b);s(b)}}});
|
||||
//# sourceMappingURL=edit_tags.min.js.map
|
||||
|
||||
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1,2 +1,2 @@
|
||||
define ("core_question/repository",["jquery","core/ajax"],function(a,b){return{submitTagCreateUpdateForm:function submitTagCreateUpdateForm(a,c,d){return b.call([{methodname:"core_question_submit_tags_form",args:{questionid:a,contextid:c,formdata:d}}])[0]}}});
|
||||
define ("core_question/repository",["jquery","core/ajax"],function(a,b){return{submitTagCreateUpdateForm:function submitTagCreateUpdateForm(a,c,d){window.console.warn("warn: The core_question/repository has been deprecated.Please use qbank_tagquestion/repository instead.");return b.call([{methodname:"core_question_submit_tags_form",args:{questionid:a,contextid:c,formdata:d}}])[0]}}});
|
||||
//# sourceMappingURL=repository.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["../src/repository.js"],"names":["define","$","Ajax","submitTagCreateUpdateForm","questionId","contextId","formdata","call","methodname","args","questionid","contextid"],"mappings":"AAsBAA,OAAM,4BAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAsB9C,MAAO,CACHC,yBAAyB,CAdG,QAA5BA,CAAAA,yBAA4B,CAASC,CAAT,CAAqBC,CAArB,CAAgCC,CAAhC,CAA0C,CAUtE,MAAOJ,CAAAA,CAAI,CAACK,IAAL,CAAU,CATH,CACVC,UAAU,CAAE,gCADF,CAEVC,IAAI,CAAE,CACFC,UAAU,CAAEN,CADV,CAEFO,SAAS,CAAEN,CAFT,CAGFC,QAAQ,CAAEA,CAHR,CAFI,CASG,CAAV,EAAqB,CAArB,CACV,CAEM,CAGV,CAzBK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to handle question ajax actions.\n *\n * @module core_question/repository\n * @copyright 2017 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n /**\n * Submit the form data for the question tags form.\n *\n * @method submitTagCreateUpdateForm\n * @param {string} formdata The URL encoded values from the form\n * @return {promise}\n */\n var submitTagCreateUpdateForm = function(questionId, contextId, formdata) {\n var request = {\n methodname: 'core_question_submit_tags_form',\n args: {\n questionid: questionId,\n contextid: contextId,\n formdata: formdata\n }\n };\n\n return Ajax.call([request])[0];\n };\n\n return {\n submitTagCreateUpdateForm: submitTagCreateUpdateForm\n };\n});\n"],"file":"repository.min.js"}
|
||||
{"version":3,"sources":["../src/repository.js"],"names":["define","$","Ajax","submitTagCreateUpdateForm","questionId","contextId","formdata","window","console","warn","call","methodname","args","questionid","contextid"],"mappings":"AAwBAA,OAAM,4BAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAwB9C,MAAO,CACHC,yBAAyB,CAhBG,QAA5BA,CAAAA,yBAA4B,CAASC,CAAT,CAAqBC,CAArB,CAAgCC,CAAhC,CAA0C,CACtEC,MAAM,CAACC,OAAP,CAAeC,IAAf,4GAWA,MAAOP,CAAAA,CAAI,CAACQ,IAAL,CAAU,CATH,CACVC,UAAU,CAAE,gCADF,CAEVC,IAAI,CAAE,CACFC,UAAU,CAAET,CADV,CAEFU,SAAS,CAAET,CAFT,CAGFC,QAAQ,CAAEA,CAHR,CAFI,CASG,CAAV,EAAqB,CAArB,CACV,CAEM,CAGV,CA3BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to handle question ajax actions.\n *\n * @deprecated since Moodle 4.0\n * @todo Final deprecation on Moodle 4.4 MDL-72438\n * @module core_question/repository\n * @copyright 2017 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n /**\n * Submit the form data for the question tags form.\n *\n * @method submitTagCreateUpdateForm\n * @param {string} formdata The URL encoded values from the form\n * @return {promise}\n */\n var submitTagCreateUpdateForm = function(questionId, contextId, formdata) {\n window.console.warn('warn: The core_question/repository has been deprecated.' +\n 'Please use qbank_tagquestion/repository instead.');\n var request = {\n methodname: 'core_question_submit_tags_form',\n args: {\n questionid: questionId,\n contextid: contextId,\n formdata: formdata\n }\n };\n\n return Ajax.call([request])[0];\n };\n\n return {\n submitTagCreateUpdateForm: submitTagCreateUpdateForm\n };\n});\n"],"file":"repository.min.js"}
|
||||
Vendored
+1
-1
@@ -1,2 +1,2 @@
|
||||
define ("core_question/selectors",[],function(){return{actions:{save:"[data-action=\"save\"]",edittags:"[data-action=\"edittags\"]"},containers:{loadingIcon:"[data-region=\"overlay-icon-container\"]"}}});
|
||||
define ("core_question/selectors",[],function(){window.console.warn("warn: The core_question/selectors has been deprecated. Please use qbank_tagquestion/selectors instead.");return{actions:{save:"[data-action=\"save\"]",edittags:"[data-action=\"edittags\"]"},containers:{loadingIcon:"[data-region=\"overlay-icon-container\"]"}}});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["../src/selectors.js"],"names":["define","actions","save","edittags","containers","loadingIcon"],"mappings":"AAsBAA,OAAM,2BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,OAAO,CAAE,CACLC,IAAI,CAAE,wBADD,CAELC,QAAQ,CAAE,4BAFL,CADN,CAKHC,UAAU,CAAE,CACRC,WAAW,CAAE,0CADL,CALT,CASV,CAVK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * The purpose of this module is to centralize selectors related to question.\n *\n * @module core_question/question_selectors\n * @copyright 2018 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"file":"selectors.min.js"}
|
||||
{"version":3,"sources":["../src/selectors.js"],"names":["define","window","console","warn","actions","save","edittags","containers","loadingIcon"],"mappings":"AAwBAA,OAAM,2BAAC,EAAD,CAAK,UAAW,CAClBC,MAAM,CAACC,OAAP,CAAeC,IAAf,CAAoB,wGAApB,EACA,MAAO,CACHC,OAAO,CAAE,CACLC,IAAI,CAAE,wBADD,CAELC,QAAQ,CAAE,4BAFL,CADN,CAKHC,UAAU,CAAE,CACRC,WAAW,CAAE,0CADL,CALT,CASV,CAXK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * The purpose of this module is to centralize selectors related to question.\n *\n * @deprecated since Moodle 4.0\n * @todo Final deprecation on Moodle 4.4 MDL-72438\n * @module core_question/question_selectors\n * @copyright 2018 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n window.console.warn('warn: The core_question/selectors has been deprecated. Please use qbank_tagquestion/selectors instead.');\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"file":"selectors.min.js"}
|
||||
@@ -16,6 +16,8 @@
|
||||
/**
|
||||
* A javascript module to handle question tags editing.
|
||||
*
|
||||
* @deprecated since Moodle 4.0
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
* @module core_question/edit_tags
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
@@ -268,6 +270,8 @@ define([
|
||||
|
||||
return {
|
||||
init: function(root) {
|
||||
window.console.warn('warn: The core_question/repository has been deprecated.' +
|
||||
'Please use qbank_tagquestion/repository instead.');
|
||||
root = $(root);
|
||||
registerEventListeners(root);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
/**
|
||||
* A javascript module to handle question ajax actions.
|
||||
*
|
||||
* @deprecated since Moodle 4.0
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
* @module core_question/repository
|
||||
* @copyright 2017 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
@@ -30,6 +32,8 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
|
||||
* @return {promise}
|
||||
*/
|
||||
var submitTagCreateUpdateForm = function(questionId, contextId, formdata) {
|
||||
window.console.warn('warn: The core_question/repository has been deprecated.' +
|
||||
'Please use qbank_tagquestion/repository instead.');
|
||||
var request = {
|
||||
methodname: 'core_question_submit_tags_form',
|
||||
args: {
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
/**
|
||||
* The purpose of this module is to centralize selectors related to question.
|
||||
*
|
||||
* @deprecated since Moodle 4.0
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
* @module core_question/question_selectors
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([], function() {
|
||||
window.console.warn('warn: The core_question/selectors has been deprecated. Please use qbank_tagquestion/selectors instead.');
|
||||
return {
|
||||
actions: {
|
||||
save: '[data-action="save"]',
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
define ("qbank_tagquestion/edit_tags",["jquery","core/fragment","core/str","core/modal_events","core/modal_factory","core/notification","core/custom_interaction_events","qbank_tagquestion/repository","qbank_tagquestion/selectors"],function(a,b,c,d,e,f,g,h,i){var j=function(a){a.find(i.actions.save).prop("disabled",!1)},k=function(a){a.find(i.actions.save).prop("disabled",!0)},l=function(a){return a.getBody().find("form").serialize()},m=function(a){var b=a.find(i.containers.loadingIcon);b.removeClass("hidden")},n=function(a){var b=a.find(i.containers.loadingIcon);b.addClass("hidden")},o=function(a,b){a.getBody().attr("data-contextid",b)},p=function(a){return a.getBody().data("contextid")},q=function(a,b){a.getBody().attr("data-questionid",b)},r=function(a){return a.getBody().data("questionid")},s=function(h){var l=e.create({type:e.types.SAVE_CANCEL,large:!1},[h,i.actions.edittags]).then(function(a){c.get_string("questiontags","question").then(function(b){a.setTitle(b);return b}).fail(f.exception);a.getRoot().on(d.save,function(b){var c=a.getBody().find("form");c.submit();b.preventDefault()});a.getRoot().on("submit","form",function(b){t(a,h).then(function(){a.hide();location.reload()}).fail(f.exception);b.preventDefault();b.stopPropagation()});return a});h.on(g.events.activate,i.actions.edittags,function(c){var d=a(c.currentTarget),e=d.data("questionid"),g=!!d.data("cantag"),p=d.data("contextid");l.then(function(a){k(h);m(h);var c=b.loadFragment("qbank_tagquestion","tags_form",p,{id:e});a.setBody(c);c.then(function(){j(h)}).always(function(){n(h)}).fail(f.exception);if(g){a.getRoot().find(i.actions.save).show()}else{a.getRoot().find(i.actions.save).hide()}q(a,e);o(a,p);return a}).fail(f.exception);c.preventDefault()})},t=function(a,b){k(b);m(b);var c=l(a),d=r(a),e=p(a);return h.submitTagCreateUpdateForm(d,e,c).always(function(){n(b);j(b)}).fail(f.exception)};return{init:function init(b){b=a(b);s(b)}}});
|
||||
//# sourceMappingURL=edit_tags.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
define ("qbank_tagquestion/repository",["jquery","core/ajax"],function(a,b){return{submitTagCreateUpdateForm:function submitTagCreateUpdateForm(a,c,d){return b.call([{methodname:"qbank_tagquestion_submit_tags_form",args:{questionid:a,contextid:c,formdata:d}}])[0]}}});
|
||||
//# sourceMappingURL=repository.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/repository.js"],"names":["define","$","Ajax","submitTagCreateUpdateForm","questionId","contextId","formdata","call","methodname","args","questionid","contextid"],"mappings":"AAwBAA,OAAM,gCAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAwB9C,MAAO,CACHC,yBAAyB,CAdG,QAA5BA,CAAAA,yBAA4B,CAASC,CAAT,CAAqBC,CAArB,CAAgCC,CAAhC,CAA0C,CAUtE,MAAOJ,CAAAA,CAAI,CAACK,IAAL,CAAU,CATH,CACVC,UAAU,CAAE,oCADF,CAEVC,IAAI,CAAE,CACFC,UAAU,CAAEN,CADV,CAEFO,SAAS,CAAEN,CAFT,CAGFC,QAAQ,CAAEA,CAHR,CAFI,CASG,CAAV,EAAqB,CAArB,CACV,CAEM,CAGV,CA3BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to handle question ajax actions.\n *\n * @module qbank_tagquestion/repository\n * @class repository\n * @package qbank_tagquestion\n * @copyright 2017 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n /**\n * Submit the form data for the question tags form.\n *\n * @method submitTagCreateUpdateForm\n * @param {int} questionId\n * @param {int} contextId\n * @param {string} formdata The URL encoded values from the form\n * @return {promise}\n */\n var submitTagCreateUpdateForm = function(questionId, contextId, formdata) {\n var request = {\n methodname: 'qbank_tagquestion_submit_tags_form',\n args: {\n questionid: questionId,\n contextid: contextId,\n formdata: formdata\n }\n };\n\n return Ajax.call([request])[0];\n };\n\n return {\n submitTagCreateUpdateForm: submitTagCreateUpdateForm\n };\n});\n"],"file":"repository.min.js"}
|
||||
@@ -0,0 +1,2 @@
|
||||
define ("qbank_tagquestion/selectors",[],function(){return{actions:{save:"[data-action=\"save\"]",edittags:"[data-action=\"edittags\"]"},containers:{loadingIcon:"[data-region=\"overlay-icon-container\"]"}}});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/selectors.js"],"names":["define","actions","save","edittags","containers","loadingIcon"],"mappings":"AAuBAA,OAAM,+BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,OAAO,CAAE,CACLC,IAAI,CAAE,wBADD,CAELC,QAAQ,CAAE,4BAFL,CADN,CAKHC,UAAU,CAAE,CACRC,WAAW,CAAE,0CADL,CALT,CASV,CAVK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * The purpose of this module is to centralize selectors related to question.\n *\n * @module qbank_tagquestion/question_selectors\n * @package qbank_tagquestion\n * @copyright 2018 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"file":"selectors.min.js"}
|
||||
@@ -0,0 +1,275 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A javascript module to handle question tags editing.
|
||||
*
|
||||
* @module qbank_tagquestion/edit_tags
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/fragment',
|
||||
'core/str',
|
||||
'core/modal_events',
|
||||
'core/modal_factory',
|
||||
'core/notification',
|
||||
'core/custom_interaction_events',
|
||||
'qbank_tagquestion/repository',
|
||||
'qbank_tagquestion/selectors',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
Fragment,
|
||||
Str,
|
||||
ModalEvents,
|
||||
ModalFactory,
|
||||
Notification,
|
||||
CustomEvents,
|
||||
Repository,
|
||||
QuestionSelectors
|
||||
) {
|
||||
|
||||
/**
|
||||
* Enable the save button in the footer.
|
||||
*
|
||||
* @param {object} root The container element.
|
||||
* @method enableSaveButton
|
||||
*/
|
||||
var enableSaveButton = function(root) {
|
||||
root.find(QuestionSelectors.actions.save).prop('disabled', false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable the save button in the footer.
|
||||
*
|
||||
* @param {object} root The container element.
|
||||
* @method disableSaveButton
|
||||
*/
|
||||
var disableSaveButton = function(root) {
|
||||
root.find(QuestionSelectors.actions.save).prop('disabled', true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the serialised form data.
|
||||
*
|
||||
* @method getFormData
|
||||
* @param {object} modal The modal object.
|
||||
* @return {string} serialised form data
|
||||
*/
|
||||
var getFormData = function(modal) {
|
||||
return modal.getBody().find('form').serialize();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the element state to loading.
|
||||
*
|
||||
* @param {object} root The container element
|
||||
* @method startLoading
|
||||
*/
|
||||
var startLoading = function(root) {
|
||||
var loadingIconContainer = root.find(QuestionSelectors.containers.loadingIcon);
|
||||
|
||||
loadingIconContainer.removeClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the loading state from the element.
|
||||
*
|
||||
* @param {object} root The container element
|
||||
* @method stopLoading
|
||||
*/
|
||||
var stopLoading = function(root) {
|
||||
var loadingIconContainer = root.find(QuestionSelectors.containers.loadingIcon);
|
||||
|
||||
loadingIconContainer.addClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the context Id data attribute on the modal.
|
||||
*
|
||||
* @param {Promise} modal The modal promise.
|
||||
* @param {int} contextId The context id.
|
||||
*/
|
||||
var setContextId = function(modal, contextId) {
|
||||
modal.getBody().attr('data-contextid', contextId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the context Id data attribute value from the modal body.
|
||||
*
|
||||
* @param {Promise} modal The modal promise.
|
||||
* @return {int} The context id.
|
||||
*/
|
||||
var getContextId = function(modal) {
|
||||
return modal.getBody().data('contextid');
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the question Id data attribute on the modal.
|
||||
*
|
||||
* @param {Promise} modal The modal promise.
|
||||
* @param {int} questionId The question Id.
|
||||
*/
|
||||
var setQuestionId = function(modal, questionId) {
|
||||
modal.getBody().attr('data-questionid', questionId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the question Id data attribute value from the modal body.
|
||||
*
|
||||
* @param {Promise} modal The modal promise.
|
||||
* @return {int} The question Id.
|
||||
*/
|
||||
var getQuestionId = function(modal) {
|
||||
return modal.getBody().data('questionid');
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners for the module.
|
||||
*
|
||||
* @param {object} root The calendar root element
|
||||
*/
|
||||
var registerEventListeners = function(root) {
|
||||
var modalPromise = ModalFactory.create(
|
||||
{
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
large: false
|
||||
},
|
||||
[root, QuestionSelectors.actions.edittags]
|
||||
).then(function(modal) {
|
||||
// All of this code only executes once, when the modal is
|
||||
// first created. This allows us to add any code that should
|
||||
// only be run once, such as adding event handlers to the modal.
|
||||
Str.get_string('questiontags', 'question')
|
||||
.then(function(string) {
|
||||
modal.setTitle(string);
|
||||
return string;
|
||||
})
|
||||
.fail(Notification.exception);
|
||||
|
||||
modal.getRoot().on(ModalEvents.save, function(e) {
|
||||
var form = modal.getBody().find('form');
|
||||
form.submit();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
modal.getRoot().on('submit', 'form', function(e) {
|
||||
save(modal, root).then(function() {
|
||||
modal.hide();
|
||||
location.reload();
|
||||
return;
|
||||
}).fail(Notification.exception);
|
||||
|
||||
// Stop the form from actually submitting and prevent it's
|
||||
// propagation because we have already handled the event.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
return modal;
|
||||
});
|
||||
|
||||
// We need to add an event handler to the tags link because there are
|
||||
// multiple links on the page and without adding a listener we don't know
|
||||
// which one the user clicked on the show the modal.
|
||||
root.on(CustomEvents.events.activate, QuestionSelectors.actions.edittags, function(e) {
|
||||
var currentTarget = $(e.currentTarget);
|
||||
|
||||
var questionId = currentTarget.data('questionid'),
|
||||
canTag = !!currentTarget.data('cantag'),
|
||||
contextId = currentTarget.data('contextid');
|
||||
|
||||
// This code gets called each time the user clicks the tag link
|
||||
// so we can use it to reload the contents of the tag modal.
|
||||
modalPromise.then(function(modal) {
|
||||
// Display spinner and disable save button.
|
||||
disableSaveButton(root);
|
||||
startLoading(root);
|
||||
|
||||
var args = {
|
||||
id: questionId
|
||||
};
|
||||
|
||||
var tagsFragment = Fragment.loadFragment('qbank_tagquestion', 'tags_form', contextId, args);
|
||||
modal.setBody(tagsFragment);
|
||||
|
||||
tagsFragment.then(function() {
|
||||
enableSaveButton(root);
|
||||
return;
|
||||
})
|
||||
.always(function() {
|
||||
// Always hide the loading spinner when the request
|
||||
// has completed.
|
||||
stopLoading(root);
|
||||
return;
|
||||
})
|
||||
.fail(Notification.exception);
|
||||
|
||||
// Show or hide the save button depending on whether the user
|
||||
// has the capability to edit the tags.
|
||||
if (canTag) {
|
||||
modal.getRoot().find(QuestionSelectors.actions.save).show();
|
||||
} else {
|
||||
modal.getRoot().find(QuestionSelectors.actions.save).hide();
|
||||
}
|
||||
|
||||
setQuestionId(modal, questionId);
|
||||
setContextId(modal, contextId);
|
||||
|
||||
return modal;
|
||||
}).fail(Notification.exception);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Send the form data to the server to save question tags.
|
||||
*
|
||||
* @method save
|
||||
* @param {object} modal The modal object.
|
||||
* @param {object} root The container element.
|
||||
* @return {object} A promise
|
||||
*/
|
||||
var save = function(modal, root) {
|
||||
// Display spinner and disable save button.
|
||||
disableSaveButton(root);
|
||||
startLoading(root);
|
||||
|
||||
var formData = getFormData(modal);
|
||||
var questionId = getQuestionId(modal);
|
||||
var contextId = getContextId(modal);
|
||||
|
||||
// Send the form data to the server for processing.
|
||||
return Repository.submitTagCreateUpdateForm(questionId, contextId, formData)
|
||||
.always(function() {
|
||||
// Regardless of success or error we should always stop
|
||||
// the loading icon and re-enable the buttons.
|
||||
stopLoading(root);
|
||||
enableSaveButton(root);
|
||||
return;
|
||||
})
|
||||
.fail(Notification.exception);
|
||||
};
|
||||
|
||||
return {
|
||||
init: function(root) {
|
||||
root = $(root);
|
||||
registerEventListeners(root);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A javascript module to handle question ajax actions.
|
||||
*
|
||||
* @module qbank_tagquestion/repository
|
||||
* @class repository
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2017 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax'], function($, Ajax) {
|
||||
|
||||
/**
|
||||
* Submit the form data for the question tags form.
|
||||
*
|
||||
* @method submitTagCreateUpdateForm
|
||||
* @param {int} questionId
|
||||
* @param {int} contextId
|
||||
* @param {string} formdata The URL encoded values from the form
|
||||
* @return {promise}
|
||||
*/
|
||||
var submitTagCreateUpdateForm = function(questionId, contextId, formdata) {
|
||||
var request = {
|
||||
methodname: 'qbank_tagquestion_submit_tags_form',
|
||||
args: {
|
||||
questionid: questionId,
|
||||
contextid: contextId,
|
||||
formdata: formdata
|
||||
}
|
||||
};
|
||||
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
return {
|
||||
submitTagCreateUpdateForm: submitTagCreateUpdateForm
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* The purpose of this module is to centralize selectors related to question.
|
||||
*
|
||||
* @module qbank_tagquestion/question_selectors
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([], function() {
|
||||
return {
|
||||
actions: {
|
||||
save: '[data-action="save"]',
|
||||
edittags: '[data-action="edittags"]',
|
||||
},
|
||||
containers: {
|
||||
loadingIcon: '[data-region="overlay-icon-container"]',
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace qbank_tagquestion\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/externallib.php');
|
||||
require_once($CFG->dirroot . '/question/engine/lib.php');
|
||||
require_once($CFG->dirroot . '/question/engine/datalib.php');
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
|
||||
use core_tag_tag;
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use qbank_tagquestion\form\tags_form;
|
||||
|
||||
/**
|
||||
* External qbank_tagquestion API.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2016 Pau Ferrer <[email protected]>
|
||||
* @author 2021 Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class submit_tags extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters.
|
||||
*
|
||||
* @return external_function_parameters.
|
||||
*/
|
||||
public static function execute_parameters() {
|
||||
return new external_function_parameters([
|
||||
'questionid' => new external_value(PARAM_INT, 'The question id'),
|
||||
'contextid' => new external_value(PARAM_INT, 'The editing context id'),
|
||||
'formdata' => new external_value(PARAM_RAW, 'The data from the tag form'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the tags form submission.
|
||||
*
|
||||
* @param int $questionid The question id.
|
||||
* @param int $contextid The editing context id.
|
||||
* @param string $formdata The question tag form data in a URI encoded param string
|
||||
* @return array The created or modified question tag
|
||||
*/
|
||||
public static function execute($questionid, $contextid, $formdata) {
|
||||
global $DB, $CFG;
|
||||
|
||||
$data = [];
|
||||
$result = ['status' => false];
|
||||
|
||||
// Parameter validation.
|
||||
$params = self::validate_parameters(self::execute_parameters(), [
|
||||
'questionid' => $questionid,
|
||||
'contextid' => $contextid,
|
||||
'formdata' => $formdata
|
||||
]);
|
||||
|
||||
$editingcontext = \context::instance_by_id($params['contextid']);
|
||||
self::validate_context($editingcontext);
|
||||
parse_str($params['formdata'], $data);
|
||||
|
||||
if (!$question = $DB->get_record_sql('
|
||||
SELECT q.*, qc.contextid
|
||||
FROM {question} q
|
||||
JOIN {question_categories} qc ON qc.id = q.category
|
||||
WHERE q.id = ?', [$params['questionid']])) {
|
||||
throw new \moodle_exception('questiondoesnotexist', 'question');
|
||||
}
|
||||
|
||||
$cantag = question_has_capability_on($question, 'tag');
|
||||
$questioncontext = \context::instance_by_id($question->contextid);
|
||||
$contexts = new \question_edit_contexts($editingcontext);
|
||||
|
||||
$formoptions = [
|
||||
'editingcontext' => $editingcontext,
|
||||
'questioncontext' => $questioncontext,
|
||||
'contexts' => $contexts->all()
|
||||
];
|
||||
|
||||
$mform = new tags_form(null, $formoptions, 'post', '', null, $cantag, $data);
|
||||
|
||||
if ($validateddata = $mform->get_data()) {
|
||||
if ($cantag) {
|
||||
if (isset($validateddata->tags)) {
|
||||
// Due to a mform bug, if there's no tags set on the tag element, it submits the name as the value.
|
||||
// The only way to discover is checking if the tag element is an array.
|
||||
$tags = is_array($validateddata->tags) ? $validateddata->tags : [];
|
||||
|
||||
core_tag_tag::set_item_tags('core_question', 'question', $validateddata->id,
|
||||
$questioncontext, $tags);
|
||||
|
||||
$result['status'] = true;
|
||||
}
|
||||
|
||||
if (isset($validateddata->coursetags)) {
|
||||
$coursetags = is_array($validateddata->coursetags) ? $validateddata->coursetags : [];
|
||||
core_tag_tag::set_item_tags('core_question', 'question', $validateddata->id,
|
||||
$editingcontext->get_course_context(false), $coursetags);
|
||||
|
||||
$result['status'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value.
|
||||
*/
|
||||
public static function execute_returns() {
|
||||
return new external_single_structure([
|
||||
'status' => new external_value(PARAM_BOOL, 'status: true if success')
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace qbank_tagquestion\form;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/lib/formslib.php');
|
||||
require_once($CFG->dirroot . '/lib/questionlib.php');
|
||||
|
||||
/**
|
||||
* The mform class for manage question tags.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @author 2021 Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tags_form extends \moodleform {
|
||||
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
$customdata = $this->_customdata;
|
||||
|
||||
$mform->disable_form_change_checker();
|
||||
|
||||
$mform->addElement('hidden', 'id');
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'categoryid');
|
||||
$mform->setType('categoryid', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'contextid');
|
||||
$mform->setType('contextid', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'questionname', get_string('questionname', 'question'));
|
||||
$mform->addElement('static', 'questioncategory', get_string('categorycurrent', 'question'));
|
||||
$mform->addElement('static', 'context', '');
|
||||
|
||||
if (\core_tag_tag::is_enabled('core_question', 'question')) {
|
||||
$tags = \core_tag_tag::get_tags_by_area_in_contexts('core_question', 'question', $customdata['contexts']);
|
||||
$tagstrings = [];
|
||||
foreach ($tags as $tag) {
|
||||
$tagstrings[$tag->name] = $tag->name;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'tags' => true,
|
||||
'multiple' => true,
|
||||
'noselectionstring' => get_string('anytags', 'quiz'),
|
||||
];
|
||||
$mform->addElement('autocomplete', 'tags', get_string('tags'), $tagstrings, $options);
|
||||
|
||||
// Is the question category in a course context?
|
||||
$qcontext = $customdata['questioncontext'];
|
||||
$qcoursecontext = $qcontext->get_course_context(false);
|
||||
$iscourseoractivityquestion = !empty($qcoursecontext);
|
||||
// Is the current context we're editing in a course context?
|
||||
$editingcontext = $customdata['editingcontext'];
|
||||
$editingcoursecontext = $editingcontext->get_course_context(false);
|
||||
$iseditingcontextcourseoractivity = !empty($editingcoursecontext);
|
||||
|
||||
if ($iseditingcontextcourseoractivity && !$iscourseoractivityquestion) {
|
||||
// If the question is being edited in a course or activity context
|
||||
// and the question isn't a course or activity level question then
|
||||
// allow course tags to be added to the course.
|
||||
$coursetagheader = get_string('questionformtagheader', 'core_question',
|
||||
$editingcoursecontext->get_context_name(true));
|
||||
$mform->addElement('autocomplete', 'coursetags', $coursetagheader, $tagstrings, $options);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace qbank_tagquestion;
|
||||
|
||||
use core_question\local\bank\plugin_features_base;
|
||||
|
||||
/**
|
||||
* Class columns is the entrypoint for the columns.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class plugin_feature extends plugin_features_base{
|
||||
|
||||
public function get_question_columns($qbank): array {
|
||||
return [
|
||||
new tags_action_column($qbank),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace qbank_tagquestion\privacy;
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for qbank_tagquestion implementing null_provider.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
public static function get_reason(): string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace qbank_tagquestion;
|
||||
|
||||
use core_question\local\bank\action_column_base;
|
||||
use core_question\local\bank\menuable_action;
|
||||
|
||||
/**
|
||||
* Action to add and remove tags to questions.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @author 2021 Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tags_action_column extends action_column_base implements menuable_action {
|
||||
|
||||
/**
|
||||
* @var string store this lang string for performance.
|
||||
*/
|
||||
protected $managetags;
|
||||
|
||||
/**
|
||||
* @var bool tags enabled or not from config.
|
||||
*/
|
||||
protected $tagsenabled = true;
|
||||
|
||||
public function init(): void {
|
||||
parent::init();
|
||||
$this->check_tags_status();
|
||||
if ($this->tagsenabled) {
|
||||
global $PAGE;
|
||||
$PAGE->requires->js_call_amd('qbank_tagquestion/edit_tags', 'init', ['#questionscontainer']);
|
||||
}
|
||||
$this->managetags = get_string('managetags', 'tag');
|
||||
}
|
||||
|
||||
protected function check_tags_status(): void {
|
||||
global $CFG;
|
||||
if (!$CFG->usetags) {
|
||||
$this->tagsenabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_name(): string {
|
||||
return 'tagsaction';
|
||||
}
|
||||
|
||||
protected function display_content($question, $rowclasses): void {
|
||||
global $OUTPUT;
|
||||
|
||||
if (\core_tag_tag::is_enabled('core_question', 'question') &&
|
||||
question_has_capability_on($question, 'view') && $this->tagsenabled) {
|
||||
|
||||
[$url, $attributes] = $this->get_link_url_and_attributes($question);
|
||||
echo \html_writer::link($url, $OUTPUT->pix_icon('t/tags',
|
||||
$this->managetags), $attributes);
|
||||
}
|
||||
}
|
||||
|
||||
protected function get_link_url_and_attributes($question): array {
|
||||
$url = new \moodle_url($this->qbank->returnurl);
|
||||
|
||||
$attributes = [
|
||||
'data-action' => 'edittags',
|
||||
'data-cantag' => question_has_capability_on($question, 'tag'),
|
||||
'data-contextid' => $this->qbank->get_most_specific_context()->id,
|
||||
'data-questionid' => $question->id
|
||||
];
|
||||
|
||||
return [$url, $attributes];
|
||||
}
|
||||
|
||||
public function get_action_menu_link(\stdClass $question): ?\action_menu_link {
|
||||
if (!\core_tag_tag::is_enabled('core_question', 'question') ||
|
||||
!question_has_capability_on($question, 'view') || !$this->tagsenabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
[$url, $attributes] = $this->get_link_url_and_attributes($question);
|
||||
return new \action_menu_link_secondary($url, new \pix_icon('t/tags', ''),
|
||||
$this->managetags, $attributes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* External services definition for qbank_tagquestion.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$functions = [
|
||||
'qbank_tagquestion_submit_tags_form' => [
|
||||
'classname' => 'qbank_tagquestion\external\submit_tags',
|
||||
'description' => 'Update the question tags.',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Strings for component qbank_tagquestion, language 'en'.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['pluginname'] = 'Tag question';
|
||||
$string['privacy:metadata'] = 'Tag question plugin does not store any user data.';
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Question related functions.
|
||||
*
|
||||
* This file was created just because Fragment API expects callbacks to be defined on lib.php.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @author 2021 Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use qbank_tagquestion\form\tags_form;
|
||||
|
||||
/**
|
||||
* Question tags fragment callback.
|
||||
*
|
||||
* @param array $args Arguments to the form.
|
||||
* @return null|string The rendered form.
|
||||
*/
|
||||
function qbank_tagquestion_output_fragment_tags_form($args) {
|
||||
|
||||
if (!empty($args['id'])) {
|
||||
global $CFG, $DB;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
$id = clean_param($args['id'], PARAM_INT);
|
||||
$editingcontext = $args['context'];
|
||||
|
||||
// Load the question and some related information.
|
||||
$question = $DB->get_record('question', ['id' => $id]);
|
||||
|
||||
if ($coursecontext = $editingcontext->get_course_context(false)) {
|
||||
$course = $DB->get_record('course', ['id' => $coursecontext->instanceid]);
|
||||
$filtercourses = [$course];
|
||||
} else {
|
||||
$filtercourses = null;
|
||||
}
|
||||
|
||||
$category = $DB->get_record('question_categories', ['id' => $question->category]);
|
||||
$questioncontext = \context::instance_by_id($category->contextid);
|
||||
$contexts = new \question_edit_contexts($editingcontext);
|
||||
|
||||
// Load the question tags and filter the course tags by the current course.
|
||||
if (core_tag_tag::is_enabled('core_question', 'question')) {
|
||||
$tagobjectsbyquestion = core_tag_tag::get_items_tags('core_question', 'question', [$question->id]);
|
||||
if (!empty($tagobjectsbyquestion[$question->id])) {
|
||||
$tagobjects = $tagobjectsbyquestion[$question->id];
|
||||
$sortedtagobjects = question_sort_tags($tagobjects,
|
||||
context::instance_by_id($category->contextid), $filtercourses);
|
||||
}
|
||||
}
|
||||
$formoptions = [
|
||||
'editingcontext' => $editingcontext,
|
||||
'questioncontext' => $questioncontext,
|
||||
'contexts' => $contexts->all()
|
||||
];
|
||||
$data = [
|
||||
'id' => $question->id,
|
||||
'questioncategory' => $category->name,
|
||||
'questionname' => $question->name,
|
||||
'categoryid' => $category->id,
|
||||
'contextid' => $category->contextid,
|
||||
'context' => $questioncontext->get_context_name(),
|
||||
'tags' => $sortedtagobjects->tags ?? [],
|
||||
'coursetags' => $sortedtagobjects->coursetags ?? [],
|
||||
];
|
||||
|
||||
$cantag = question_has_capability_on($question, 'tag');
|
||||
$mform = new tags_form(null, $formoptions, 'post', '', null, $cantag, $data);
|
||||
$mform->set_data($data);
|
||||
|
||||
return $mform->render();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
@qbank @qbank_tagquestion
|
||||
Feature: Use the qbank plugin manager page for tagquestion
|
||||
In order to check the plugin behaviour with enable and disable
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| quiz | Test quiz | C1 | quiz1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | First question | Answer the first question |
|
||||
|
||||
Scenario: Enable/disable tagquestion column from the base view
|
||||
Given I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
|
||||
And I should see "Tag question"
|
||||
And I click on "Disable" "link" in the "Tag question" "table_row"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I click on "#action-menu-toggle-2" "css_element" in the "First question" "table_row"
|
||||
Then I should not see "Manage tags"
|
||||
And I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
|
||||
And I click on "Enable" "link" in the "Tag question" "table_row"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I click on "#action-menu-toggle-2" "css_element" in the "First question" "table_row"
|
||||
And I should see "Manage tags"
|
||||
|
||||
Scenario: Enable/disable tagquestion section from question edit form
|
||||
Given I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
|
||||
And I should see "Tag question"
|
||||
And I click on "Disable" "link" in the "Tag question" "table_row"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I choose "Edit question" action for "First question" in the question bank
|
||||
Then I should not see "Tags"
|
||||
And I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
|
||||
And I click on "Enable" "link" in the "Tag question" "table_row"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I choose "Edit question" action for "First question" in the question bank
|
||||
And I should see "Tags"
|
||||
@@ -0,0 +1,420 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace qbank_tagquestion\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
|
||||
/**
|
||||
* Question external functions tests.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2016 Pau Ferrer <[email protected]>
|
||||
* @author 2021 Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class submit_tags_test extends \externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* Set up for every test
|
||||
*/
|
||||
public function setUp(): void {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
// Setup test data.
|
||||
$this->course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Create users.
|
||||
$this->student = self::getDataGenerator()->create_user();
|
||||
|
||||
// Users enrolments.
|
||||
$this->studentrole = $DB->get_record('role', ['shortname' => 'student']);
|
||||
$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should throw an exception when the question id doesn't match
|
||||
* a question.
|
||||
*/
|
||||
public function test_submit_tags_form_incorrect_question_id() {
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = \context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
// Generate an id for a question that doesn't exist.
|
||||
$missingquestionid = $questions[1]->id * 2;
|
||||
$question->id = $missingquestionid;
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string($question, $qcat, $questioncontext, [], []);
|
||||
|
||||
// We should receive an exception if the question doesn't exist.
|
||||
$this->expectException('moodle_exception');
|
||||
submit_tags::execute($missingquestionid, $editingcontext->id, $formdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should throw an exception when the context id doesn't match
|
||||
* a context.
|
||||
*/
|
||||
public function test_submit_tags_form_incorrect_context_id() {
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = \context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
// Generate an id for a context that doesn't exist.
|
||||
$missingcontextid = $editingcontext->id * 200;
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string($question, $qcat, $questioncontext, [], []);
|
||||
|
||||
// We should receive an exception if the question doesn't exist.
|
||||
$this->expectException('moodle_exception');
|
||||
submit_tags::execute($question->id, $missingcontextid, $formdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should return false when tags are disabled.
|
||||
*/
|
||||
public function test_submit_tags_form_tags_disabled() {
|
||||
global $CFG;
|
||||
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = \context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
$user = $this->create_user_can_tag($course);
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string($question, $qcat, $questioncontext, [], []);
|
||||
|
||||
$this->setUser($user);
|
||||
$CFG->usetags = false;
|
||||
$result = submit_tags::execute($question->id, $editingcontext->id, $formdata);
|
||||
$CFG->usetags = true;
|
||||
|
||||
$this->assertFalse($result['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should return false if the user does not have any capability
|
||||
* to tag the question.
|
||||
*/
|
||||
public function test_submit_tags_form_no_tag_permissions() {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
|
||||
$questiongenerator = $generator->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = \context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string(
|
||||
$question,
|
||||
$qcat,
|
||||
$questioncontext,
|
||||
['foo'],
|
||||
['bar']
|
||||
);
|
||||
|
||||
// Prohibit all of the tag capabilities.
|
||||
assign_capability('moodle/question:tagmine', CAP_PROHIBIT, $teacherrole->id, $questioncontext->id);
|
||||
assign_capability('moodle/question:tagall', CAP_PROHIBIT, $teacherrole->id, $questioncontext->id);
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, $teacherrole->id, 'manual');
|
||||
$user->ignoresesskey = true;
|
||||
$this->setUser($user);
|
||||
|
||||
$result = submit_tags::execute($question->id, $editingcontext->id, $formdata);
|
||||
|
||||
$this->assertFalse($result['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should return false if the user only has the capability to
|
||||
* tag their own questions and the question is not theirs.
|
||||
*/
|
||||
public function test_submit_tags_form_tagmine_permission_non_owner_question() {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
|
||||
$questiongenerator = $generator->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = \context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string(
|
||||
$question,
|
||||
$qcat,
|
||||
$questioncontext,
|
||||
['foo'],
|
||||
['bar']
|
||||
);
|
||||
|
||||
// Make sure the question isn't created by the user.
|
||||
$question->createdby = $user->id + 1;
|
||||
|
||||
// Prohibit all of the tag capabilities.
|
||||
assign_capability('moodle/question:tagmine', CAP_ALLOW, $teacherrole->id, $questioncontext->id);
|
||||
assign_capability('moodle/question:tagall', CAP_PROHIBIT, $teacherrole->id, $questioncontext->id);
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, $teacherrole->id, 'manual');
|
||||
$user->ignoresesskey = true;
|
||||
$this->setUser($user);
|
||||
|
||||
$result = submit_tags::execute($question->id, $editingcontext->id, $formdata);
|
||||
|
||||
$this->assertFalse($result['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provided for the submit_tags_form test to check that course tags are
|
||||
* only created in the correct editing and question context combinations.
|
||||
*
|
||||
* @return array Test cases
|
||||
*/
|
||||
public function get_submit_tags_form_testcases() {
|
||||
return [
|
||||
'course - course' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course - course - empty tags' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => [],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course - course category' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'category',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => true
|
||||
],
|
||||
'course - system' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'system',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => true
|
||||
],
|
||||
'course category - course' => [
|
||||
'editingcontext' => 'category',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course category - course category' => [
|
||||
'editingcontext' => 'category',
|
||||
'questioncontext' => 'category',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course category - system' => [
|
||||
'editingcontext' => 'category',
|
||||
'questioncontext' => 'system',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'system - course' => [
|
||||
'editingcontext' => 'system',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'system - course category' => [
|
||||
'editingcontext' => 'system',
|
||||
'questioncontext' => 'category',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'system - system' => [
|
||||
'editingcontext' => 'system',
|
||||
'questioncontext' => 'system',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that submit_tags_form only creates course tags when the correct combination
|
||||
* of editing context and question context is provided.
|
||||
*
|
||||
* Course tags can only be set on a course category or system context question that
|
||||
* is being editing in a course context.
|
||||
*
|
||||
* @dataProvider get_submit_tags_form_testcases()
|
||||
* @param string $editingcontext The type of the context the question is being edited in
|
||||
* @param string $questioncontext The type of the context the question belongs to
|
||||
* @param string[] $questiontags The tag names to set as question tags
|
||||
* @param string[] $coursetags The tag names to set as course tags
|
||||
* @param bool $expectcoursetags If the given course tags should have been set or not
|
||||
*/
|
||||
public function test_submit_tags_form_context_combinations(
|
||||
$editingcontext,
|
||||
$questioncontext,
|
||||
$questiontags,
|
||||
$coursetags,
|
||||
$expectcoursetags
|
||||
) {
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions($questioncontext);
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$questioncontext = \context::instance_by_id($qcat->contextid);
|
||||
|
||||
switch($editingcontext) {
|
||||
case 'system':
|
||||
$editingcontext = \context_system::instance();
|
||||
break;
|
||||
|
||||
case 'category':
|
||||
$editingcontext = \context_coursecat::instance($category->id);
|
||||
break;
|
||||
|
||||
default:
|
||||
$editingcontext = \context_course::instance($course->id);
|
||||
}
|
||||
|
||||
$user = $this->create_user_can_tag($course);
|
||||
$question = $questions[0];
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string(
|
||||
$question,
|
||||
$qcat,
|
||||
$questioncontext,
|
||||
$questiontags, // Question tags.
|
||||
$coursetags // Course tags.
|
||||
);
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
$result = submit_tags::execute($question->id, $editingcontext->id, $formdata);
|
||||
|
||||
$this->assertTrue($result['status']);
|
||||
|
||||
$tagobjects = \core_tag_tag::get_item_tags('core_question', 'question', $question->id);
|
||||
$coursetagobjects = [];
|
||||
$questiontagobjects = [];
|
||||
|
||||
if ($expectcoursetags) {
|
||||
// If the use case is expecting course tags to be created then split
|
||||
// the tags into course tags and question tags and ensure we have
|
||||
// the correct number of course tags.
|
||||
|
||||
while ($tagobject = array_shift($tagobjects)) {
|
||||
if ($tagobject->taginstancecontextid == $questioncontext->id) {
|
||||
$questiontagobjects[] = $tagobject;
|
||||
} else if ($tagobject->taginstancecontextid == $coursecontext->id) {
|
||||
$coursetagobjects[] = $tagobject;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertCount(count($coursetags), $coursetagobjects);
|
||||
} else {
|
||||
$questiontagobjects = $tagobjects;
|
||||
}
|
||||
|
||||
// Ensure the expected number of question tags was created.
|
||||
$this->assertCount(count($questiontags), $questiontagobjects);
|
||||
|
||||
foreach ($questiontagobjects as $tagobject) {
|
||||
// If we have any question tags then make sure they are in the list
|
||||
// of expected tags and have the correct context.
|
||||
$this->assertContains($tagobject->name, $questiontags);
|
||||
$this->assertEquals($questioncontext->id, $tagobject->taginstancecontextid);
|
||||
}
|
||||
|
||||
foreach ($coursetagobjects as $tagobject) {
|
||||
// If we have any course tags then make sure they are in the list
|
||||
// of expected course tags and have the correct context.
|
||||
$this->assertContains($tagobject->name, $coursetags);
|
||||
$this->assertEquals($coursecontext->id, $tagobject->taginstancecontextid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the encoded form data expected by the submit_tags_form external function.
|
||||
*
|
||||
* @param \stdClass $question The question record
|
||||
* @param \stdClass $questioncategory The question category record
|
||||
* @param \context $questioncontext Context for the question category
|
||||
* @param array $tags A list of tag names for the question
|
||||
* @param array $coursetags A list of course tag names for the question
|
||||
* @return string HTML encoded string of the data
|
||||
*/
|
||||
protected function generate_encoded_submit_tags_form_string($question, $questioncategory,
|
||||
$questioncontext, $tags = [], $coursetags = []) {
|
||||
|
||||
$data = [
|
||||
'id' => $question->id,
|
||||
'categoryid' => $questioncategory->id,
|
||||
'contextid' => $questioncontext->id,
|
||||
'questionname' => $question->name,
|
||||
'questioncategory' => $questioncategory->name,
|
||||
'context' => $questioncontext->get_context_name(false),
|
||||
'tags' => $tags,
|
||||
'coursetags' => $coursetags
|
||||
];
|
||||
$data = \qbank_tagquestion\form\tags_form::mock_generate_submit_keys($data);
|
||||
|
||||
return http_build_query($data, '', '&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a user, enrol them in the course, and give them the capability to
|
||||
* tag all questions in the system context.
|
||||
*
|
||||
* @param \stdClass $course The course record to enrol in
|
||||
* @return \stdClass The user record
|
||||
*/
|
||||
protected function create_user_can_tag($course) {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$roleid = $generator->create_role();
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
|
||||
$systemcontext = \context_system::instance();
|
||||
|
||||
$generator->role_assign($roleid, $user->id, $systemcontext->id);
|
||||
$generator->enrol_user($user->id, $course->id, $teacherrole->id, 'manual');
|
||||
|
||||
// Give the user global ability to tag questions.
|
||||
assign_capability('moodle/question:tagall', CAP_ALLOW, $roleid, $systemcontext, true);
|
||||
// Allow the user to submit form data.
|
||||
$user->ignoresesskey = true;
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Version information for qbank_tagquestion.
|
||||
*
|
||||
* @package qbank_tagquestion
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = 'qbank_tagquestion';
|
||||
$plugin->version = 2021090300;
|
||||
$plugin->requires = 2021052500;
|
||||
$plugin->maturity = MATURITY_STABLE;
|
||||
@@ -40,11 +40,12 @@ class tags_action_column extends action_column_base implements menuable_action {
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
global $CFG;
|
||||
if ($CFG->usetags) {
|
||||
global $PAGE;
|
||||
$PAGE->requires->js_call_amd('core_question/edit_tags', 'init', ['#questionscontainer']);
|
||||
}
|
||||
// Removed for conflicting js calls.
|
||||
// ...global $CFG;.
|
||||
// ...if ($CFG->usetags) {.
|
||||
// ...global $PAGE;.
|
||||
// ...$PAGE->requires->js_call_amd('core_question/edit_tags', 'init', ['#questionscontainer']);.
|
||||
// ...}.
|
||||
$this->managetags = get_string('managetags', 'tag');
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,9 @@ class core_question_external extends external_api {
|
||||
* Returns description of method parameters.
|
||||
*
|
||||
* @return external_function_parameters.
|
||||
* @deprecated since Moodle 4.0
|
||||
* @see \qbank_tagquestion\external\qbank_tagquestion_external
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
*/
|
||||
public static function submit_tags_form_parameters() {
|
||||
return new external_function_parameters([
|
||||
@@ -137,6 +140,9 @@ class core_question_external extends external_api {
|
||||
* @param int $contextid The editing context id.
|
||||
* @param string $formdata The question tag form data in a URI encoded param string
|
||||
* @return array The created or modified question tag
|
||||
* @deprecated since Moodle 4.0
|
||||
* @see \qbank_tagquestion\external\qbank_tagquestion_external
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
*/
|
||||
public static function submit_tags_form($questionid, $contextid, $formdata) {
|
||||
global $DB, $CFG;
|
||||
@@ -206,6 +212,10 @@ class core_question_external extends external_api {
|
||||
|
||||
/**
|
||||
* Returns description of method result value.
|
||||
*
|
||||
* @deprecated since Moodle 4.0
|
||||
* @see \qbank_tagquestion\external\qbank_tagquestion_external
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
*/
|
||||
public static function submit_tags_form_returns() {
|
||||
return new external_single_structure([
|
||||
@@ -213,6 +223,16 @@ class core_question_external extends external_api {
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marking the method as deprecated.
|
||||
*
|
||||
* @return bool
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
*/
|
||||
public static function submit_tags_form_is_deprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters.
|
||||
*
|
||||
|
||||
@@ -33,8 +33,13 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*
|
||||
* @param array $args Arguments to the form.
|
||||
* @return null|string The rendered form.
|
||||
* @deprecated since Moodle 4.0
|
||||
* @see /question/bank/qbank_tagquestion/lib.php
|
||||
* @todo Final deprecation on Moodle 4.4 MDL-72438
|
||||
*/
|
||||
function core_question_output_fragment_tags_form($args) {
|
||||
debugging('Function core_question_output_fragment_tags_form() is deprecated,
|
||||
please use core_question_output_fragment_tags_form() from qbank_tagquestion instead.', DEBUG_DEVELOPER);
|
||||
|
||||
if (!empty($args['id'])) {
|
||||
global $CFG, $DB;
|
||||
|
||||
@@ -103,376 +103,6 @@ class core_question_external_testcase extends externallib_advanced_testcase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should throw an exception when the question id doesn't match
|
||||
* a question.
|
||||
*/
|
||||
public function test_submit_tags_form_incorrect_question_id() {
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
// Generate an id for a question that doesn't exist.
|
||||
$missingquestionid = $questions[1]->id * 2;
|
||||
$question->id = $missingquestionid;
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string($question, $qcat, $questioncontext, [], []);
|
||||
|
||||
// We should receive an exception if the question doesn't exist.
|
||||
$this->expectException('moodle_exception');
|
||||
core_question_external::submit_tags_form($missingquestionid, $editingcontext->id, $formdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should throw an exception when the context id doesn't match
|
||||
* a context.
|
||||
*/
|
||||
public function test_submit_tags_form_incorrect_context_id() {
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
// Generate an id for a context that doesn't exist.
|
||||
$missingcontextid = $editingcontext->id * 200;
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string($question, $qcat, $questioncontext, [], []);
|
||||
|
||||
// We should receive an exception if the question doesn't exist.
|
||||
$this->expectException('moodle_exception');
|
||||
core_question_external::submit_tags_form($question->id, $missingcontextid, $formdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should return false when tags are disabled.
|
||||
*/
|
||||
public function test_submit_tags_form_tags_disabled() {
|
||||
global $CFG;
|
||||
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
$user = $this->create_user_can_tag($course);
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string($question, $qcat, $questioncontext, [], []);
|
||||
|
||||
$this->setUser($user);
|
||||
$CFG->usetags = false;
|
||||
$result = core_question_external::submit_tags_form($question->id, $editingcontext->id, $formdata);
|
||||
$CFG->usetags = true;
|
||||
|
||||
$this->assertFalse($result['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should return false if the user does not have any capability
|
||||
* to tag the question.
|
||||
*/
|
||||
public function test_submit_tags_form_no_tag_permissions() {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
|
||||
$questiongenerator = $generator->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string(
|
||||
$question,
|
||||
$qcat,
|
||||
$questioncontext,
|
||||
['foo'],
|
||||
['bar']
|
||||
);
|
||||
|
||||
// Prohibit all of the tag capabilities.
|
||||
assign_capability('moodle/question:tagmine', CAP_PROHIBIT, $teacherrole->id, $questioncontext->id);
|
||||
assign_capability('moodle/question:tagall', CAP_PROHIBIT, $teacherrole->id, $questioncontext->id);
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, $teacherrole->id, 'manual');
|
||||
$user->ignoresesskey = true;
|
||||
$this->setUser($user);
|
||||
|
||||
$result = core_question_external::submit_tags_form($question->id, $editingcontext->id, $formdata);
|
||||
|
||||
$this->assertFalse($result['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* submit_tags_form should return false if the user only has the capability to
|
||||
* tag their own questions and the question is not theirs.
|
||||
*/
|
||||
public function test_submit_tags_form_tagmine_permission_non_owner_question() {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
|
||||
$questiongenerator = $generator->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions();
|
||||
$questioncontext = context::instance_by_id($qcat->contextid);
|
||||
$editingcontext = $questioncontext;
|
||||
$question = $questions[0];
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string(
|
||||
$question,
|
||||
$qcat,
|
||||
$questioncontext,
|
||||
['foo'],
|
||||
['bar']
|
||||
);
|
||||
|
||||
// Make sure the question isn't created by the user.
|
||||
$question->createdby = $user->id + 1;
|
||||
|
||||
// Prohibit all of the tag capabilities.
|
||||
assign_capability('moodle/question:tagmine', CAP_ALLOW, $teacherrole->id, $questioncontext->id);
|
||||
assign_capability('moodle/question:tagall', CAP_PROHIBIT, $teacherrole->id, $questioncontext->id);
|
||||
|
||||
$generator->enrol_user($user->id, $course->id, $teacherrole->id, 'manual');
|
||||
$user->ignoresesskey = true;
|
||||
$this->setUser($user);
|
||||
|
||||
$result = core_question_external::submit_tags_form($question->id, $editingcontext->id, $formdata);
|
||||
|
||||
$this->assertFalse($result['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provided for the submit_tags_form test to check that course tags are
|
||||
* only created in the correct editing and question context combinations.
|
||||
*
|
||||
* @return array Test cases
|
||||
*/
|
||||
public function get_submit_tags_form_testcases() {
|
||||
return [
|
||||
'course - course' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course - course - empty tags' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => [],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course - course category' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'category',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => true
|
||||
],
|
||||
'course - system' => [
|
||||
'editingcontext' => 'course',
|
||||
'questioncontext' => 'system',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => true
|
||||
],
|
||||
'course category - course' => [
|
||||
'editingcontext' => 'category',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course category - course category' => [
|
||||
'editingcontext' => 'category',
|
||||
'questioncontext' => 'category',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'course category - system' => [
|
||||
'editingcontext' => 'category',
|
||||
'questioncontext' => 'system',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'system - course' => [
|
||||
'editingcontext' => 'system',
|
||||
'questioncontext' => 'course',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'system - course category' => [
|
||||
'editingcontext' => 'system',
|
||||
'questioncontext' => 'category',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
'system - system' => [
|
||||
'editingcontext' => 'system',
|
||||
'questioncontext' => 'system',
|
||||
'questiontags' => ['foo'],
|
||||
'coursetags' => ['bar'],
|
||||
'expectcoursetags' => false
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that submit_tags_form only creates course tags when the correct combination
|
||||
* of editing context and question context is provided.
|
||||
*
|
||||
* Course tags can only be set on a course category or system context question that
|
||||
* is being editing in a course context.
|
||||
*
|
||||
* @dataProvider get_submit_tags_form_testcases()
|
||||
* @param string $editingcontext The type of the context the question is being edited in
|
||||
* @param string $questioncontext The type of the context the question belongs to
|
||||
* @param string[] $questiontags The tag names to set as question tags
|
||||
* @param string[] $coursetags The tag names to set as course tags
|
||||
* @param bool $expectcoursetags If the given course tags should have been set or not
|
||||
*/
|
||||
public function test_submit_tags_form_context_combinations(
|
||||
$editingcontext,
|
||||
$questioncontext,
|
||||
$questiontags,
|
||||
$coursetags,
|
||||
$expectcoursetags
|
||||
) {
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
list ($category, $course, $qcat, $questions) = $questiongenerator->setup_course_and_questions($questioncontext);
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
$questioncontext = context::instance_by_id($qcat->contextid);
|
||||
|
||||
switch($editingcontext) {
|
||||
case 'system':
|
||||
$editingcontext = context_system::instance();
|
||||
break;
|
||||
|
||||
case 'category':
|
||||
$editingcontext = context_coursecat::instance($category->id);
|
||||
break;
|
||||
|
||||
default:
|
||||
$editingcontext = context_course::instance($course->id);
|
||||
}
|
||||
|
||||
$user = $this->create_user_can_tag($course);
|
||||
$question = $questions[0];
|
||||
$formdata = $this->generate_encoded_submit_tags_form_string(
|
||||
$question,
|
||||
$qcat,
|
||||
$questioncontext,
|
||||
$questiontags, // Question tags.
|
||||
$coursetags // Course tags.
|
||||
);
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
$result = core_question_external::submit_tags_form($question->id, $editingcontext->id, $formdata);
|
||||
|
||||
$this->assertTrue($result['status']);
|
||||
|
||||
$tagobjects = core_tag_tag::get_item_tags('core_question', 'question', $question->id);
|
||||
$coursetagobjects = [];
|
||||
$questiontagobjects = [];
|
||||
|
||||
if ($expectcoursetags) {
|
||||
// If the use case is expecting course tags to be created then split
|
||||
// the tags into course tags and question tags and ensure we have
|
||||
// the correct number of course tags.
|
||||
|
||||
while ($tagobject = array_shift($tagobjects)) {
|
||||
if ($tagobject->taginstancecontextid == $questioncontext->id) {
|
||||
$questiontagobjects[] = $tagobject;
|
||||
} else if ($tagobject->taginstancecontextid == $coursecontext->id) {
|
||||
$coursetagobjects[] = $tagobject;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertCount(count($coursetags), $coursetagobjects);
|
||||
} else {
|
||||
$questiontagobjects = $tagobjects;
|
||||
}
|
||||
|
||||
// Ensure the expected number of question tags was created.
|
||||
$this->assertCount(count($questiontags), $questiontagobjects);
|
||||
|
||||
foreach ($questiontagobjects as $tagobject) {
|
||||
// If we have any question tags then make sure they are in the list
|
||||
// of expected tags and have the correct context.
|
||||
$this->assertContains($tagobject->name, $questiontags);
|
||||
$this->assertEquals($questioncontext->id, $tagobject->taginstancecontextid);
|
||||
}
|
||||
|
||||
foreach ($coursetagobjects as $tagobject) {
|
||||
// If we have any course tags then make sure they are in the list
|
||||
// of expected course tags and have the correct context.
|
||||
$this->assertContains($tagobject->name, $coursetags);
|
||||
$this->assertEquals($coursecontext->id, $tagobject->taginstancecontextid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the encoded form data expected by the submit_tags_form external function.
|
||||
*
|
||||
* @param stdClass $question The question record
|
||||
* @param stdClass $questioncategory The question category record
|
||||
* @param context $questioncontext Context for the question category
|
||||
* @param array $tags A list of tag names for the question
|
||||
* @param array $coursetags A list of course tag names for the question
|
||||
* @return string HTML encoded string of the data
|
||||
*/
|
||||
protected function generate_encoded_submit_tags_form_string($question, $questioncategory,
|
||||
$questioncontext, $tags = [], $coursetags = []) {
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/tags_form.php');
|
||||
|
||||
$data = [
|
||||
'id' => $question->id,
|
||||
'categoryid' => $questioncategory->id,
|
||||
'contextid' => $questioncontext->id,
|
||||
'questionname' => $question->name,
|
||||
'questioncategory' => $questioncategory->name,
|
||||
'context' => $questioncontext->get_context_name(false),
|
||||
'tags' => $tags,
|
||||
'coursetags' => $coursetags
|
||||
];
|
||||
$data = core_question\form\tags::mock_generate_submit_keys($data);
|
||||
|
||||
return http_build_query($data, '', '&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a user, enrol them in the course, and give them the capability to
|
||||
* tag all questions in the system context.
|
||||
*
|
||||
* @param stdClass $course The course record to enrol in
|
||||
* @return stdClass The user record
|
||||
*/
|
||||
protected function create_user_can_tag($course) {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$user = $generator->create_user();
|
||||
$roleid = $generator->create_role();
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
|
||||
$systemcontext = context_system::instance();
|
||||
|
||||
$generator->role_assign($roleid, $user->id, $systemcontext->id);
|
||||
$generator->enrol_user($user->id, $course->id, $teacherrole->id, 'manual');
|
||||
|
||||
// Give the user global ability to tag questions.
|
||||
assign_capability('moodle/question:tagall', CAP_ALLOW, $roleid, $systemcontext, true);
|
||||
// Allow the user to submit form data.
|
||||
$user->ignoresesskey = true;
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the get_random_question_summaries test.
|
||||
*/
|
||||
|
||||
@@ -216,7 +216,9 @@ abstract class question_edit_form extends question_wizard_form {
|
||||
// Any questiontype specific fields.
|
||||
$this->definition_inner($mform);
|
||||
|
||||
if (core_tag_tag::is_enabled('core_question', 'question')) {
|
||||
if (core_tag_tag::is_enabled('core_question', 'question')
|
||||
&& class_exists('qbank_tagquestion\\tags_action_column')
|
||||
&& \core\plugininfo\qbank::is_plugin_enabled('qbank_tagquestion')) {
|
||||
$this->add_tag_fields($mform);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ require_once($CFG->dirroot . '/lib/questionlib.php');
|
||||
*
|
||||
* @copyright 2018 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @deprecated since Moodle 4.0
|
||||
* @see \qbank_tagquestion\form\tags_form
|
||||
* @todo MDL-71679 class renaming
|
||||
*/
|
||||
class tags extends \moodleform {
|
||||
|
||||
@@ -40,6 +43,8 @@ class tags extends \moodleform {
|
||||
* The form definition
|
||||
*/
|
||||
public function definition() {
|
||||
debugging('Class column_base in core_question\form\tags is deprecated,
|
||||
please use qbank_tagquestion\form\tags_form instead.', DEBUG_DEVELOPER);
|
||||
$mform = $this->_form;
|
||||
$customdata = $this->_customdata;
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ This files describes API changes for code that uses the question API.
|
||||
are divided in two different parts, base classes and feature classes. All the base
|
||||
classes are moved classes/local/bank and all the feature classes will be moved to
|
||||
the plugin for that feature.
|
||||
2) submit_tags_form and associated external services for question tag, tags_form in question/type,
|
||||
core_question_output_fragment_tags_form method in lib is deprecated and moved to the tagquestion plugin.
|
||||
|
||||
2) Function question_get_export_single_question_url() in questionlib has been deprecated
|
||||
and moved to qbank_exporttoxml plugin, the new location is:
|
||||
|
||||
Reference in New Issue
Block a user