Merge branch 'MDL-69092-master_lti_pagination' of https://github.com/andrewmadden/moodle

This commit is contained in:
Ilya Tregubov
2021-11-18 08:57:12 +02:00
26 changed files with 1043 additions and 74 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core/paged_content_factory",["jquery","core/templates","core/notification","core/paged_content","core/paged_content_events","core/pubsub","core/ajax"],function(a,b,c,d,e,f,g){var h={PAGED_CONTENT:"core/paged_content"},j={ITEMS_PER_PAGE_SINGLE:25,ITEMS_PER_PAGE_ARRAY:[25,50,100,0],MAX_PAGES:3},k=function(){return{pagingbar:!1,pagingdropdown:!1,skipjs:!0,ignorecontrolwhileloading:!0,controlplacementbottom:!1}},l=function(){return{showitemsperpageselector:!1,itemsperpage:35,previous:!0,next:!0,activepagenumber:1,hidecontrolonsinglepage:!0,pages:[]}},m=function(a,b){var c=1;if(0<a){var d=a%b;if(d){a-=d;c=a/b+1}else{c=a/b}}return c},n=function(b,c){if(null===c){c=j.ITEMS_PER_PAGE_SINGLE}if(a.isArray(c)){c=c[0]}var d=l();d.itemsperpage=c;for(var e=m(b,c),f=1,g;f<=e;f++){g={number:f,page:""+f};if(1==f){g.active=!0}d.pages.push(g)}d.barsize=10;return d},o=function(b){var c=[];if(a.isArray(b)){c=b.map(function(a){if("number"==typeof a){return{value:a,active:!1}}else{return a}});var d=c.filter(function(a){return a.active});if(!d.length){c[0].active=!0}}else{c=[{value:b,active:!0}]}return c},p=function(b){if(null===b){b=j.ITEMS_PER_PAGE_ARRAY}var c=l();c.itemsperpage=o(b);c.showitemsperpageselector=a.isArray(b)&&1<b.length;return c},q=function(a,b){if(a){return n(a,b)}else{return p(b)}},r=function(b,c){if(null===b){b=j.ITEMS_PER_PAGE_SINGLE}if(a.isArray(b)){return{options:b}}var d={options:[]},e=0,f=0,g=j.MAX_PAGES;if(c.hasOwnProperty("maxPages")){g=c.maxPages}for(var h=1,k;h<=g;h++){k=0;if(2>=h){k=b;f=b}else{f=2*f;k=f}e+=k;var l={itemcount:k,content:e};if(1==h){l.active=!0}d.options.push(l)}return d},s=function(a,b,c){var d=k();if(c.hasOwnProperty("ignoreControlWhileLoading")){d.ignorecontrolwhileloading=c.ignoreControlWhileLoading}if(c.hasOwnProperty("controlPlacementBottom")){d.controlplacementbottom=c.controlPlacementBottom}if(c.hasOwnProperty("hideControlOnSinglePage")){d.hidecontrolonsinglepage=c.hideControlOnSinglePage}if(c.hasOwnProperty("ariaLabels")){d.arialabels=c.ariaLabels}if(c.hasOwnProperty("dropdown")&&c.dropdown){d.pagingdropdown=r(b,c)}else{d.pagingbar=q(a,b)}return d},t=function(e,f,g,i){i=i||{};var j=a.Deferred(),k=s(e,f,i);b.render(h.PAGED_CONTENT,k).then(function(b,c){b=a(b);var e=b.attr("id");if(i.hasOwnProperty("eventNamespace")){e=i.eventNamespace}var f=b;d.init(f,g,e);v(e,i);j.resolve(b,c)}).fail(function(a){j.reject(a)}).fail(c.exception);return j.promise()},u=function(a){return function callback(b){g.call([{methodname:"core_user_update_user_preferences",args:{preferences:[{type:a,value:b}]}}])}},v=function(a,b){if(b.hasOwnProperty("persistentLimitKey")){f.subscribe(a+e.SET_ITEMS_PER_PAGE_LIMIT,u(b.persistentLimitKey))}};return{create:function create(a,b){return t(null,null,a,b)},createWithLimit:function createWithLimit(a,b,c){return t(null,a,b,c)},createWithTotalAndLimit:t,createFromStaticList:function createFromStaticList(a,b,c,d){if("undefined"==typeof d){d={}}var e=a.length;return t(e,b,function(b){var d=[];b.forEach(function(b){var c=b.offset,f=b.limit?c+b.limit:e,g=a.slice(c,f);d.push(g)});return c(d)},d)},createFromAjax:t,resetLastPageNumber:function resetLastPageNumber(a,b){f.publish(a+e.ALL_ITEMS_LOADED,b)}}});
define ("core/paged_content_factory",["jquery","core/templates","core/notification","core/paged_content","core/paged_content_events","core/pubsub","core/ajax"],function(a,b,c,d,e,f,g){var h={PAGED_CONTENT:"core/paged_content"},j={ITEMS_PER_PAGE_SINGLE:25,ITEMS_PER_PAGE_ARRAY:[25,50,100,0],MAX_PAGES:3},k=function(){return{pagingbar:!1,pagingdropdown:!1,skipjs:!0,ignorecontrolwhileloading:!0,controlplacementbottom:!1}},l=function(){return{showitemsperpageselector:!1,itemsperpage:[{value:35,active:!0}],previous:!0,next:!0,activepagenumber:1,hidecontrolonsinglepage:!0,pages:[]}},m=function(a,b){var c=1;if(0<a){var d=a%b;if(d){a-=d;c=a/b+1}else{c=a/b}}return c},n=function(b,c){if(null===c){c=j.ITEMS_PER_PAGE_SINGLE}if(a.isArray(c)){c=c[0]}var d=l();d.itemsperpage=o(c);for(var e=m(b,c),f=1,g;f<=e;f++){g={number:f,page:""+f};if(1==f){g.active=!0}d.pages.push(g)}d.barsize=10;return d},o=function(b){var c=[];if(a.isArray(b)){c=b.map(function(a){if("number"==typeof a){return{value:a,active:!1}}else{return a}});var d=c.filter(function(a){return a.active});if(!d.length){c[0].active=!0}}else{c=[{value:b,active:!0}]}return c},p=function(b){if(null===b){b=j.ITEMS_PER_PAGE_ARRAY}var c=l();c.itemsperpage=o(b);c.showitemsperpageselector=a.isArray(b)&&1<b.length;return c},q=function(a,b){if(a){return n(a,b)}else{return p(b)}},r=function(b,c){if(null===b){b=j.ITEMS_PER_PAGE_SINGLE}if(a.isArray(b)){return{options:b}}var d={options:[]},e=0,f=0,g=j.MAX_PAGES;if(c.hasOwnProperty("maxPages")){g=c.maxPages}for(var h=1,k;h<=g;h++){k=0;if(2>=h){k=b;f=b}else{f=2*f;k=f}e+=k;var l={itemcount:k,content:e};if(1==h){l.active=!0}d.options.push(l)}return d},s=function(a,b,c){var d=k();if(c.hasOwnProperty("ignoreControlWhileLoading")){d.ignorecontrolwhileloading=c.ignoreControlWhileLoading}if(c.hasOwnProperty("controlPlacementBottom")){d.controlplacementbottom=c.controlPlacementBottom}if(c.hasOwnProperty("hideControlOnSinglePage")){d.hidecontrolonsinglepage=c.hideControlOnSinglePage}if(c.hasOwnProperty("ariaLabels")){d.arialabels=c.ariaLabels}if(c.hasOwnProperty("dropdown")&&c.dropdown){d.pagingdropdown=r(b,c)}else{d.pagingbar=q(a,b);if(c.hasOwnProperty("showFirstLast")&&c.showFirstLast){d.pagingbar.first=!0;d.pagingbar.last=!0}}return d},t=function(e,f,g,i){i=i||{};var j=a.Deferred(),k=s(e,f,i);b.render(h.PAGED_CONTENT,k).then(function(b,c){b=a(b);var e=b.attr("id");if(i.hasOwnProperty("eventNamespace")){e=i.eventNamespace}var f=b;d.init(f,g,e);v(e,i);j.resolve(b,c)}).fail(function(a){j.reject(a)}).fail(c.exception);return j.promise()},u=function(a){return function callback(b){g.call([{methodname:"core_user_update_user_preferences",args:{preferences:[{type:a,value:b}]}}])}},v=function(a,b){if(b.hasOwnProperty("persistentLimitKey")){f.subscribe(a+e.SET_ITEMS_PER_PAGE_LIMIT,u(b.persistentLimitKey))}};return{create:function create(a,b){return t(null,null,a,b)},createWithLimit:function createWithLimit(a,b,c){return t(null,a,b,c)},createWithTotalAndLimit:t,createFromStaticList:function createFromStaticList(a,b,c,d){if("undefined"==typeof d){d={}}var e=a.length;return t(e,b,function(b){var d=[];b.forEach(function(b){var c=b.offset,f=b.limit?c+b.limit:e,g=a.slice(c,f);d.push(g)});return c(d)},d)},createFromAjax:t,resetLastPageNumber:function resetLastPageNumber(a,b){f.publish(a+e.ALL_ITEMS_LOADED,b)}}});
//# sourceMappingURL=paged_content_factory.min.js.map
File diff suppressed because one or more lines are too long
+6 -2
View File
@@ -73,7 +73,7 @@ function(
var getDefaultPagingBarTemplateContext = function() {
return {
showitemsperpageselector: false,
itemsperpage: 35,
itemsperpage: [{value: 35, active: true}],
previous: true,
next: true,
activepagenumber: 1,
@@ -127,7 +127,7 @@ function(
}
var context = getDefaultPagingBarTemplateContext();
context.itemsperpage = itemsPerPage;
context.itemsperpage = buildItemsPerPagePagingBarContext(itemsPerPage);
var numberOfPages = calculateNumberOfPages(numberOfItems, itemsPerPage);
for (var i = 1; i <= numberOfPages; i++) {
@@ -347,6 +347,10 @@ function(
context.pagingdropdown = buildPagingDropdownTemplateContext(itemsPerPage, config);
} else {
context.pagingbar = buildPagingBarTemplateContext(numberOfItems, itemsPerPage);
if (config.hasOwnProperty('showFirstLast') && config.showFirstLast) {
context.pagingbar.first = true;
context.pagingbar.last = true;
}
}
return context;
+28
View File
@@ -92,6 +92,34 @@ class behat_data_generators extends behat_base {
$this->get_instance_for_component($component)->generate_items($entity, $data);
}
/**
* Create multiple entities of one entity type.
*
* @Given :count :entitytype exist with the following data:
*
* @param string $entitytype The name of the type entity to add
* @param int $count
* @param TableNode $data
*/
public function the_following_repeated_entities_exist(string $entitytype, int $count, TableNode $data): void {
$rows = $data->getRowsHash();
$tabledata = [array_keys($rows)];
for ($current = 1; $current < $count + 1; $current++) {
$rowdata = [];
foreach ($rows as $fieldname => $fieldtemplate) {
$rowdata[$fieldname] = str_replace('[count]', $current, $fieldtemplate);
}
$tabledata[] = $rowdata;
}
if (isset($this->movedentitytypes[$entitytype])) {
$entitytype = $this->movedentitytypes[$entitytype];
}
list($component, $entity) = $this->parse_entity_type($entitytype);
$this->get_instance_for_component($component)->generate_items($entity, new TableNode($tabledata), false);
}
/**
* Creates the specified element.
*
+1 -1
View File
@@ -1,2 +1,2 @@
define ("mod_lti/tool_configure_controller",["jquery","core/ajax","core/notification","core/templates","mod_lti/events","mod_lti/keys","mod_lti/tool_type","mod_lti/tool_proxy","core/str","core/config"],function(a,b,c,d,e,f,g,h,i,j){var k={EXTERNAL_REGISTRATION_CONTAINER:"#external-registration-container",EXTERNAL_REGISTRATION_PAGE_CONTAINER:"#external-registration-page-container",EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER:"#external-registration-template-container",CARTRIDGE_REGISTRATION_CONTAINER:"#cartridge-registration-container",CARTRIDGE_REGISTRATION_FORM:"#cartridge-registration-form",ADD_TOOL_FORM:"#add-tool-form",TOOL_LIST_CONTAINER:"#tool-list-container",TOOL_CREATE_BUTTON:"#tool-create-button",TOOL_CREATE_LTILEGACY_BUTTON:"#tool-createltilegacy-button",REGISTRATION_CHOICE_CONTAINER:"#registration-choice-container",TOOL_URL:"#tool-url"},l=function(){return a(k.TOOL_LIST_CONTAINER)},m=function(){return a(k.EXTERNAL_REGISTRATION_CONTAINER)},n=function(){return a(k.CARTRIDGE_REGISTRATION_CONTAINER)},o=function(){return a(k.REGISTRATION_CHOICE_CONTAINER)},p=function(b){if(b.data&&"org.imsglobal.lti.close"===b.data.subject){a(k.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER).empty();s();x();A();x();E()}},q=function(b){a(k.EXTERNAL_REGISTRATION_PAGE_CONTAINER).removeClass("hidden");var c=a(k.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER);c.append(a("<iframe src='startltiadvregistration.php?url="+encodeURIComponent(b)+"&sesskey="+j.sesskey+"'></iframe>"));v();window.addEventListener("message",p,!1)},r=function(){return a(k.TOOL_URL).val()},s=function(){m().addClass("hidden")},t=function(){n().addClass("hidden")},u=function(){o().addClass("hidden")},v=function(){t();u();m().removeClass("hidden");y(m())},w=function(a){s();u();var b=n();b.find("input").val("");b.removeClass("hidden");b.find(k.CARTRIDGE_REGISTRATION_FORM).attr("data-cartridge-url",a);y(b)},x=function(){s();t();o().removeClass("hidden");y(o())},y=function(a){var b=a.children().detach();b.appendTo(a)},z=function(){l().addClass("hidden")},A=function(){l().removeClass("hidden")},B=function(a){var b=a.error?"error":"success";c.addNotification({message:a.message,type:b})},C=function(a){a.addClass("loading")},D=function(a){a.removeClass("loading")},E=function(){var b=a.Deferred(),e=l();C(e);a.when(g.query(),h.query({orphanedonly:!0})).done(function(a,c){d.render("mod_lti/tool_list",{tools:a,proxies:c}).done(function(a,c){e.empty();e.append(a);d.runTemplateJS(c);b.resolve()}).fail(b.reject)}).fail(b.reject);b.fail(c.exception).always(function(){D(e)})},F=function(){var b=r().trim();if(b){a(k.TOOL_URL).val("");z();q(b)}},G=function(){var b=r().trim();if(""===b){return a.Deferred().resolve()}var d=a(k.TOOL_CREATE_LTILEGACY_BUTTON);C(d);var f=g.isCartridge(b);f.always(function(){D(d)});f.done(function(c){if(c.iscartridge){a(k.TOOL_URL).val("");a(document).trigger(e.START_CARTRIDGE_REGISTRATION,b)}else{a(document).trigger(e.START_EXTERNAL_REGISTRATION,{url:b})}});f.fail(function(){i.get_string("errorbadurl","mod_lti").done(function(b){a(document).trigger(e.REGISTRATION_FEEDBACK,{message:b,error:!0})}).fail(c.exception)});return f},H=function(){a(document).on(e.NEW_TOOL_TYPE,function(){E()});a(document).on(e.START_EXTERNAL_REGISTRATION,function(){v();a(k.TOOL_URL).val("");z()});a(document).on(e.STOP_EXTERNAL_REGISTRATION,function(){A();x()});a(document).on(e.START_CARTRIDGE_REGISTRATION,function(a,b){w(b)});a(document).on(e.STOP_CARTRIDGE_REGISTRATION,function(){n().find(k.CARTRIDGE_REGISTRATION_FORM).removeAttr("data-cartridge-url");x()});a(document).on(e.REGISTRATION_FEEDBACK,function(a,b){B(b)});var b=a(k.TOOL_CREATE_LTILEGACY_BUTTON);b.click(function(a){a.preventDefault();G()});var c=a(k.TOOL_CREATE_BUTTON);c.click(function(a){a.preventDefault();F()})};return{init:function init(){H();E()}}});
define ("mod_lti/tool_configure_controller",["jquery","core/ajax","core/paged_content_factory","core/notification","core/templates","mod_lti/events","mod_lti/keys","mod_lti/tool_types_and_proxies","mod_lti/tool_type","mod_lti/tool_proxy","core/str","core/config"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m={EXTERNAL_REGISTRATION_CONTAINER:"#external-registration-container",EXTERNAL_REGISTRATION_PAGE_CONTAINER:"#external-registration-page-container",EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER:"#external-registration-template-container",CARTRIDGE_REGISTRATION_CONTAINER:"#cartridge-registration-container",CARTRIDGE_REGISTRATION_FORM:"#cartridge-registration-form",ADD_TOOL_FORM:"#add-tool-form",TOOL_CARD_CONTAINER:"#tool-card-container",TOOL_LIST_CONTAINER:"#tool-list-container",TOOL_CREATE_BUTTON:"#tool-create-button",TOOL_CREATE_LTILEGACY_BUTTON:"#tool-createltilegacy-button",REGISTRATION_CHOICE_CONTAINER:"#registration-choice-container",TOOL_URL:"#tool-url"},n=function(){return a(m.TOOL_LIST_CONTAINER)},o=function(){return a(m.TOOL_CARD_CONTAINER)},p=function(){return a(m.EXTERNAL_REGISTRATION_CONTAINER)},q=function(){return a(m.CARTRIDGE_REGISTRATION_CONTAINER)},r=function(){return a(m.REGISTRATION_CHOICE_CONTAINER)},s=function(b){if(b.data&&"org.imsglobal.lti.close"===b.data.subject){a(m.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER).empty();v();A();D();A();H()}},t=function(b){a(m.EXTERNAL_REGISTRATION_PAGE_CONTAINER).removeClass("hidden");var c=a(m.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER);c.append(a("<iframe src='startltiadvregistration.php?url="+encodeURIComponent(b)+"&sesskey="+l.sesskey+"'></iframe>"));y();window.addEventListener("message",s,!1)},u=function(){return a(m.TOOL_URL).val()},v=function(){p().addClass("hidden")},w=function(){q().addClass("hidden")},x=function(){r().addClass("hidden")},y=function(){w();x();p().removeClass("hidden");B(p())},z=function(a){v();x();var b=q();b.find("input").val("");b.removeClass("hidden");b.find(m.CARTRIDGE_REGISTRATION_FORM).attr("data-cartridge-url",a);B(b)},A=function(){v();w();r().removeClass("hidden");B(r())},B=function(a){var b=a.children().detach();b.appendTo(a)},C=function(){n().addClass("hidden")},D=function(){n().removeClass("hidden")},E=function(a){var b=a.error?"error":"success";d.addNotification({message:a.message,type:b})},F=function(a){a.addClass("loading")},G=function(a){a.removeClass("loading")},H=function(){var a=o(),b=n();I().done(function(d){c.createWithTotalAndLimit(d.count,60,function(a){return a.map(function(a){return J(a.limit,a.offset).then(function(a){return K(a)})})},{showFirstLast:!0}).done(function(b,c){e.replaceNodeContents(a,b,c)}).always(G(b))});F(b)},I=function(){return h.count({orphanedonly:!0}).done(function(a){return a}).catch(function(a){d.exception(a);return{count:0}})},J=function(a,b){var c={orphanedonly:!0};if(null!==a&&!Number.isNaN(a)){c.limit=a}if(null!==b&&!Number.isNaN(b)){c.offset=b}return h.query(c).done(function(a){return a}).catch(function(c){d.exception(c);return{types:[],proxies:[],limit:a,offset:b}})},K=function(a){var b={tools:a.types,proxies:a.proxies};return e.render("mod_lti/tool_list",b).done(function(a,b){return{html:a,js:b}})},L=function(){var b=u().trim();if(b){a(m.TOOL_URL).val("");C();t(b)}},M=function(){var b=u().trim();if(""===b){return a.Deferred().resolve()}var c=a(m.TOOL_CREATE_LTILEGACY_BUTTON);F(c);var e=i.isCartridge(b);e.always(function(){G(c)});e.done(function(c){if(c.iscartridge){a(m.TOOL_URL).val("");a(document).trigger(f.START_CARTRIDGE_REGISTRATION,b)}else{a(document).trigger(f.START_EXTERNAL_REGISTRATION,{url:b})}});e.fail(function(){k.get_string("errorbadurl","mod_lti").done(function(b){a(document).trigger(f.REGISTRATION_FEEDBACK,{message:b,error:!0})}).fail(d.exception)});return e},N=function(){a(document).on(f.NEW_TOOL_TYPE,function(){H()});a(document).on(f.START_EXTERNAL_REGISTRATION,function(){y();a(m.TOOL_URL).val("");C()});a(document).on(f.STOP_EXTERNAL_REGISTRATION,function(){D();A()});a(document).on(f.START_CARTRIDGE_REGISTRATION,function(a,b){z(b)});a(document).on(f.STOP_CARTRIDGE_REGISTRATION,function(){q().find(m.CARTRIDGE_REGISTRATION_FORM).removeAttr("data-cartridge-url");A()});a(document).on(f.REGISTRATION_FEEDBACK,function(a,b){E(b)});var b=a(m.TOOL_CREATE_LTILEGACY_BUTTON);b.click(function(a){a.preventDefault();M()});var c=a(m.TOOL_CREATE_BUTTON);c.click(function(a){a.preventDefault();L()})};return{init:function init(){N();H()}}});
//# sourceMappingURL=tool_configure_controller.min.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
define ("mod_lti/tool_types_and_proxies",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.count=a.query=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"mod_lti_get_tool_types_and_proxies",args:a||{}}])[0]};a.query=c;var d=function(a){return b.default.call([{methodname:"mod_lti_get_tool_types_and_proxies_count",args:a||{}}])[0]};a.count=d});
//# sourceMappingURL=tool_types_and_proxies.min.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../src/tool_types_and_proxies.js"],"names":["query","args","ajax","call","methodname","count"],"mappings":"oKAwBA,uDAcO,GAAMA,CAAAA,CAAK,CAAG,SAACC,CAAD,CAAU,CAM3B,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,oCADA,CAEZH,IAAI,CAAEA,CAAI,EAAI,EAFF,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C,UAqBA,GAAMI,CAAAA,CAAK,CAAG,SAACJ,CAAD,CAAU,CAM3B,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,0CADA,CAEZH,IAAI,CAAEA,CAAI,EAAI,EAFF,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C","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 * Provides an interface for external tools in the Moodle server.\n *\n * @module mod_lti/tool_types_and_proxies\n * @class tool_types_and_proxies\n * @copyright 2020 Andrew Madden <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\nimport ajax from 'core/ajax';\n\n/**\n * Get a list of LTI tool types and tool proxies from Moodle for the given\n * search args.\n *\n * See also:\n * mod/lti/classes/external.php get_tool_types_and_proxies()\n *\n * @method query\n * @public\n * @param {Object} args Search parameters\n * @return {Promise} Promise that will be resolved when the ajax call returns.\n */\nexport const query = (args) => {\n const request = {\n methodname: 'mod_lti_get_tool_types_and_proxies',\n args: args || {}\n };\n\n return ajax.call([request])[0];\n};\n\n/**\n * Get a count of LTI tool types and tool proxies from Moodle for the given\n * search args.\n *\n * See also:\n * mod/lti/classes/external.php get_tool_types_and_proxies_count()\n *\n * @method count\n * @public\n * @param {Object} args Search parameters\n * @return {Promise} Promise that will be resolved when the ajax call returns.\n */\nexport const count = (args) => {\n const request = {\n methodname: 'mod_lti_get_tool_types_and_proxies_count',\n args: args || {}\n };\n\n return ajax.call([request])[0];\n};\n"],"file":"tool_types_and_proxies.min.js"}
+108 -24
View File
@@ -23,9 +23,11 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/events', 'mod_lti/keys', 'mod_lti/tool_type',
'mod_lti/tool_proxy', 'core/str', 'core/config'],
function($, ajax, notification, templates, ltiEvents, KEYS, toolType, toolProxy, str, config) {
define(['jquery', 'core/ajax', 'core/paged_content_factory', 'core/notification', 'core/templates', 'mod_lti/events',
'mod_lti/keys', 'mod_lti/tool_types_and_proxies', 'mod_lti/tool_type', 'mod_lti/tool_proxy', 'core/str', 'core/config'],
function($, ajax,
pagedContentFactory, notification, templates, ltiEvents, KEYS,
toolTypesAndProxies, toolType, toolProxy, str, config) {
var SELECTORS = {
EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-container',
@@ -34,6 +36,7 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e
CARTRIDGE_REGISTRATION_CONTAINER: '#cartridge-registration-container',
CARTRIDGE_REGISTRATION_FORM: '#cartridge-registration-form',
ADD_TOOL_FORM: '#add-tool-form',
TOOL_CARD_CONTAINER: '#tool-card-container',
TOOL_LIST_CONTAINER: '#tool-list-container',
TOOL_CREATE_BUTTON: '#tool-create-button',
TOOL_CREATE_LTILEGACY_BUTTON: '#tool-createltilegacy-button',
@@ -52,6 +55,17 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e
return $(SELECTORS.TOOL_LIST_CONTAINER);
};
/**
* Get the tool card container element.
*
* @method getToolCardContainer
* @private
* @return {Object} jQuery object
*/
const getToolCardContainer = function() {
return $(SELECTORS.TOOL_CARD_CONTAINER);
};
/**
* Get the external registration container element.
*
@@ -285,29 +299,99 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e
* @private
*/
var reloadToolList = function() {
var promise = $.Deferred();
var container = getToolListContainer();
startLoading(container);
$.when(
toolType.query(),
toolProxy.query({'orphanedonly': true})
)
.done(function(types, proxies) {
templates.render('mod_lti/tool_list', {tools: types, proxies: proxies})
.done(function(html, js) {
container.empty();
container.append(html);
templates.runTemplateJS(js);
promise.resolve();
}).fail(promise.reject);
const cardContainer = getToolCardContainer();
const listContainer = getToolListContainer();
const limit = 60;
// Get initial data with zero limit and offset.
fetchToolCount().done(function(data) {
pagedContentFactory.createWithTotalAndLimit(
data.count,
limit,
function(pagesData) {
return pagesData.map(function(pageData) {
return fetchToolData(pageData.limit, pageData.offset)
.then(function(data) {
return renderToolData(data);
});
});
},
{
'showFirstLast': true
})
.fail(promise.reject);
.done(function(html, js) {
// Add the paged content into the page.
templates.replaceNodeContents(cardContainer, html, js);
})
.always(stopLoading(listContainer));
});
startLoading(listContainer);
};
promise.fail(notification.exception)
.always(function() {
stopLoading(container);
});
/**
* Fetch the count of tool type and proxy datasets.
*
* @return {*|void}
*/
const fetchToolCount = function() {
return toolTypesAndProxies.count({'orphanedonly': true})
.done(function(data) {
return data;
}).catch(function(error) {
// Add debug message, then return empty data.
notification.exception(error);
return {
'count': 0
};
});
};
/**
* Fetch the data for tool type and proxy cards.
*
* @param {number} limit Maximum number of datasets to get.
* @param {number} offset Offset count for fetching the data.
* @return {*|void}
*/
const fetchToolData = function(limit, offset) {
const args = {'orphanedonly': true};
// Only add limit and offset to args if they are integers and not null, otherwise defaults will be used.
if (limit !== null && !Number.isNaN(limit)) {
args.limit = limit;
}
if (offset !== null && !Number.isNaN(offset)) {
args.offset = offset;
}
return toolTypesAndProxies.query(args)
.done(function(data) {
return data;
}).catch(function(error) {
// Add debug message, then return empty data.
notification.exception(error);
return {
'types': [],
'proxies': [],
'limit': limit,
'offset': offset
};
});
};
/**
* Render Tool and Proxy cards from data.
*
* @param {Object} data Contains arrays of data objects to populate cards.
* @return {*}
*/
const renderToolData = function(data) {
const context = {
tools: data.types,
proxies: data.proxies,
};
return templates.render('mod_lti/tool_list', context)
.done(function(html, js) {
return {html, js};
}
);
};
/**
+67
View File
@@ -0,0 +1,67 @@
// 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/>.
/**
* Provides an interface for external tools in the Moodle server.
*
* @module mod_lti/tool_types_and_proxies
* @class tool_types_and_proxies
* @copyright 2020 Andrew Madden <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/
import ajax from 'core/ajax';
/**
* Get a list of LTI tool types and tool proxies from Moodle for the given
* search args.
*
* See also:
* mod/lti/classes/external.php get_tool_types_and_proxies()
*
* @method query
* @public
* @param {Object} args Search parameters
* @return {Promise} Promise that will be resolved when the ajax call returns.
*/
export const query = (args) => {
const request = {
methodname: 'mod_lti_get_tool_types_and_proxies',
args: args || {}
};
return ajax.call([request])[0];
};
/**
* Get a count of LTI tool types and tool proxies from Moodle for the given
* search args.
*
* See also:
* mod/lti/classes/external.php get_tool_types_and_proxies_count()
*
* @method count
* @public
* @param {Object} args Search parameters
* @return {Promise} Promise that will be resolved when the ajax call returns.
*/
export const count = (args) => {
const request = {
methodname: 'mod_lti_get_tool_types_and_proxies_count',
args: args || {}
};
return ajax.call([request])[0];
};
+100
View File
@@ -0,0 +1,100 @@
<?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 mod_lti\external;
defined('MOODLE_INTERNAL') || die();
/**
* External function for fetching all tool types and proxies.
*
* @package mod_lti
* @author Andrew Madden <[email protected]>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_tool_types_and_proxies extends \external_api {
/**
* Get parameter definition for get_tool_types_and_proxies().
*
* @return \external_function_parameters
*/
public static function execute_parameters(): \external_function_parameters {
return new \external_function_parameters(
[
'toolproxyid' => new \external_value(PARAM_INT, 'Tool proxy id',
VALUE_DEFAULT, 0),
'orphanedonly' => new \external_value(PARAM_BOOL, 'Orphaned tool types only',
VALUE_DEFAULT, 0),
'limit' => new \external_value(PARAM_INT, 'How many tool types displayed per page',
VALUE_DEFAULT, 60, NULL_NOT_ALLOWED),
'offset' => new \external_value(PARAM_INT, 'Current offset of tool elements',
VALUE_DEFAULT, 0, NULL_NOT_ALLOWED),
]
);
}
/**
* Get data for all tool types and tool proxies.
*
* @param int $toolproxyid The tool proxy id
* @param bool $orphanedonly Whether to get orphaned proxies only.
* @param int $limit How many elements to return if using pagination.
* @param int $offset Which chunk of elements to return is using pagination.
* @return array
*/
public static function execute($toolproxyid, $orphanedonly, $limit, $offset): array {
$params = self::validate_parameters(self::execute_parameters(),
[
'toolproxyid' => $toolproxyid,
'orphanedonly' => $orphanedonly,
'limit' => $limit,
'offset' => $offset,
]);
$toolproxyid = $params['toolproxyid'] !== null ? $params['toolproxyid'] : 0;
$orphanedonly = $params['orphanedonly'] !== null ? $params['orphanedonly'] : false;
$limit = $params['limit'] !== null ? $params['limit'] : 0;
$offset = $params['offset'] !== null ? $params['offset'] : 0;
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
list($proxies, $types) = lti_get_lti_types_and_proxies($limit, $offset, $orphanedonly, $toolproxyid);
return [
'types' => $types,
'proxies' => $proxies,
'limit' => $limit,
'offset' => $offset,
];
}
/**
* Get return definition for get_tool_types_and_proxies.
*
* @return \external_single_structure
*/
public static function execute_returns(): \external_single_structure {
return new \external_single_structure([
'types' => \mod_lti_external::get_tool_types_returns(),
'proxies' => \mod_lti_external::get_tool_proxies_returns(),
'limit' => new \external_value(PARAM_INT, 'Limit of how many tool types to show', VALUE_OPTIONAL),
'offset' => new \external_value(PARAM_INT, 'Offset of tool types', VALUE_OPTIONAL),
]);
}
}
@@ -0,0 +1,84 @@
<?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 mod_lti\external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/lti/locallib.php');
/**
* External function for fetching the count of all tool types and proxies.
*
* @package mod_lti
* @author Andrew Madden <[email protected]>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_tool_types_and_proxies_count extends \external_api {
/**
* Get parameter definition for get_tool_types_and_proxies_count().
*
* @return \external_function_parameters
*/
public static function execute_parameters(): \external_function_parameters {
return new \external_function_parameters(
[
'toolproxyid' => new \external_value(PARAM_INT, 'Tool proxy id', VALUE_DEFAULT, 0),
'orphanedonly' => new \external_value(PARAM_BOOL, 'Orphaned tool types only', VALUE_DEFAULT, 0),
]
);
}
/**
* Get count of every tool type and tool proxy.
*
* @param int $toolproxyid The tool proxy id
* @param bool $orphanedonly Whether to get orphaned proxies only.
* @return array
*/
public static function execute($toolproxyid, $orphanedonly): array {
$params = self::validate_parameters(self::execute_parameters(),
[
'toolproxyid' => $toolproxyid,
'orphanedonly' => $orphanedonly,
]);
$toolproxyid = $params['toolproxyid'];
$orphanedonly = $params['orphanedonly'];
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
return [
'count' => lti_get_lti_types_and_proxies_count($orphanedonly, $toolproxyid),
];
}
/**
* Get return definition for get_tool_types_and_proxies_count.
*
* @return \external_single_structure
*/
public static function execute_returns(): \external_single_structure {
return new \external_single_structure([
'count' => new \external_value(PARAM_INT, 'Total number of tool types and proxies', VALUE_REQUIRED),
]);
}
}
+60
View File
@@ -0,0 +1,60 @@
<?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 mod_lti;
defined('MOODLE_INTERNAL') || die();
/**
* Helper class for LTI activity.
*
* @package mod_lti
* @author Andrew Madden <[email protected]>
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* Get SQL to query DB for LTI tool proxy records.
*
* @param bool $orphanedonly If true, return SQL to get orphaned proxies only.
* @param bool $count If true, return SQL to get the count of the records instead of the records themselves.
* @return string SQL.
*/
public static function get_tool_proxy_sql(bool $orphanedonly = false, bool $count = false): string {
if ($count) {
$select = "SELECT count(*) as type_count";
$sort = "";
} else {
// We only want the fields from lti_tool_proxies table. Must define every column to be compatible with mysqli.
$select = "SELECT ltp.id, ltp.name, ltp.regurl, ltp.state, ltp.guid, ltp.secret, ltp.vendorcode,
ltp.capabilityoffered, ltp.serviceoffered, ltp.toolproxy, ltp.createdby,
ltp.timecreated, ltp.timemodified";
$sort = " ORDER BY ltp.name ASC, ltp.state DESC, ltp.timemodified DESC";
}
$from = " FROM {lti_tool_proxies} ltp";
if ($orphanedonly) {
$join = " LEFT JOIN {lti_types} lt ON ltp.id = lt.toolproxyid";
$where = " WHERE lt.toolproxyid IS null";
} else {
$join = "";
$where = "";
}
return $select . $from . $join . $where . $sort;
}
}
+18
View File
@@ -101,6 +101,24 @@ $functions = array(
'ajax' => true
),
'mod_lti_get_tool_types_and_proxies' => [
'classname' => 'mod_lti\external\get_tool_types_and_proxies',
'methodname' => 'execute',
'description' => 'Get a list of the tool types and tool proxies',
'type' => 'read',
'capabilities' => 'moodle/site:config',
'ajax' => true
],
'mod_lti_get_tool_types_and_proxies_count' => [
'classname' => 'mod_lti\external\get_tool_types_and_proxies_count',
'methodname' => 'execute',
'description' => 'Get total number of the tool types and tool proxies',
'type' => 'read',
'capabilities' => 'moodle/site:config',
'ajax' => true
],
'mod_lti_create_tool_type' => array(
'classname' => 'mod_lti_external',
'methodname' => 'create_tool_type',
+68
View File
@@ -51,6 +51,7 @@
defined('MOODLE_INTERNAL') || die;
// TODO: Switch to core oauthlib once implemented - MDL-30149.
use mod_lti\helper;
use moodle\mod\lti as lti;
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
@@ -3095,6 +3096,73 @@ function lti_delete_tool_proxy($id) {
$DB->delete_records('lti_tool_proxies', array('id' => $id));
}
/**
* Get both LTI tool proxies and tool types.
*
* If limit and offset are not zero, a subset of the tools will be returned. Tool proxies will be counted before tool
* types.
* For example: If 10 tool proxies and 10 tool types exist, and the limit is set to 15, then 10 proxies and 5 types
* will be returned.
*
* @param int $limit Maximum number of tools returned.
* @param int $offset Do not return tools before offset index.
* @param bool $orphanedonly If true, only return orphaned proxies.
* @param int $toolproxyid If not 0, only return tool types that have this tool proxy id.
* @return array list(proxies[], types[]) List containing array of tool proxies and array of tool types.
*/
function lti_get_lti_types_and_proxies(int $limit = 0, int $offset = 0, bool $orphanedonly = false, int $toolproxyid = 0): array {
global $DB;
if ($orphanedonly) {
$orphanedproxiessql = helper::get_tool_proxy_sql($orphanedonly, false);
$countsql = helper::get_tool_proxy_sql($orphanedonly, true);
$proxies = $DB->get_records_sql($orphanedproxiessql, null, $offset, $limit);
$totalproxiescount = $DB->count_records_sql($countsql);
} else {
$proxies = $DB->get_records('lti_tool_proxies', null, 'name ASC, state DESC, timemodified DESC',
'*', $offset, $limit);
$totalproxiescount = $DB->count_records('lti_tool_proxies');
}
// Find new offset and limit for tool types after getting proxies and set up query.
$typesoffset = max($offset - $totalproxiescount, 0); // Set to 0 if negative.
$typeslimit = max($limit - count($proxies), 0); // Set to 0 if negative.
$typesparams = [];
if (!empty($toolproxyid)) {
$typesparams['toolproxyid'] = $toolproxyid;
}
$types = $DB->get_records('lti_types', $typesparams, 'name ASC, state DESC, timemodified DESC',
'*', $typesoffset, $typeslimit);
return [$proxies, array_map('serialise_tool_type', $types)];
}
/**
* Get the total number of LTI tool types and tool proxies.
*
* @param bool $orphanedonly If true, only count orphaned proxies.
* @param int $toolproxyid If not 0, only count tool types that have this tool proxy id.
* @return int Count of tools.
*/
function lti_get_lti_types_and_proxies_count(bool $orphanedonly = false, int $toolproxyid = 0): int {
global $DB;
$typessql = "SELECT count(*)
FROM {lti_types}";
$typesparams = [];
if (!empty($toolproxyid)) {
$typessql .= " WHERE toolproxyid = :toolproxyid";
$typesparams['toolproxyid'] = $toolproxyid;
}
$proxiessql = helper::get_tool_proxy_sql($orphanedonly, true);
$countsql = "SELECT ($typessql) + ($proxiessql) as total";
return $DB->count_records_sql($countsql, $typesparams);
}
/**
* Add a tool configuration in the database
*
@@ -79,6 +79,10 @@
</div>
<div id="tool-list-container" class="loading">
<h3>{{#str}} tooltypes, mod_lti {{/str}}</h3>
<div id="tool-list-loader-container">
{{> mod_lti/loader }}
</div>
{{> mod_lti/tool_list }}
</div>
</div>
+3 -7
View File
@@ -33,14 +33,10 @@
}
}}
<h3>{{#str}} tooltypes, mod_lti {{/str}}</h3>
<div id="tool-list-loader-container">
{{> mod_lti/loader }}
</div>
{{^proxies}}{{^tools}}
<div id="tool-notools-text">{{#str}} no_lti_tools, mod_lti {{/str}}</div>
{{/tools}}{{/proxies}}
<div id="tool-card-container">
{{^proxies}}{{^tools}}
<p>{{#str}} no_lti_tools, mod_lti {{/str}}</p>
{{/tools}}{{/proxies}}
{{#proxies}}
{{> mod_lti/tool_proxy_card }}
{{/proxies}}
+34
View File
@@ -0,0 +1,34 @@
@mod @mod_lti
Feature: Navigate existing LTI tool types using pagination
In order to manage reusable activities for teachers
As an admin
I need to view existing tools
Background:
Given 100 "mod_lti > tool types" exist with the following data:
|name |Test tool [count] |
|description |Example description [count] |
|baseurl |https://www.example.com/tool[count]|
@javascript
Scenario: View first page of tool types.
Given I log in as "admin"
When I navigate to "Plugins > Activity modules > External tool > Manage tools" in site administration
Then I should see "Test tool 30"
And "Test tool 70" "text" should not be visible
@javascript
Scenario: View second page of tool types using page 2 button.
Given I log in as "admin"
When I navigate to "Plugins > Activity modules > External tool > Manage tools" in site administration
And I click on "2" "link"
Then I should see "Test tool 70"
And "Test tool 30" "text" should not be visible
@javascript
Scenario: View last page of tool types using page 2 button.
Given I log in as "admin"
When I navigate to "Plugins > Activity modules > External tool > Manage tools" in site administration
And I click on "Last" "link"
Then I should see "Test tool 70"
And "Test tool 30" "text" should not be visible
@@ -0,0 +1,65 @@
<?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/>.
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/lti/tests/mod_lti_testcase.php');
/**
* PHPUnit tests for get_tool_types_and_proxies_count external function.
*
* @package mod_lti
* @author Andrew Madden <[email protected]>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_lti_get_tool_types_and_proxies_count_testcase extends mod_lti_testcase {
/**
* This method runs before every test.
*/
public function setUp(): void {
$this->resetAfterTest();
$this->setAdminUser();
}
/**
* Test get_tool_types_and_proxies_count returns the correct number.
*/
public function test_mod_lti_get_tool_types_and_proxies_count() {
for ($i = 0; $i < 10; $i++) {
$proxy = $this->generate_tool_proxy($i);
$this->generate_tool_type($i, $proxy->id);
}
$data = \mod_lti\external\get_tool_types_and_proxies_count::execute(0, false);
$data = external_api::clean_returnvalue(\mod_lti\external\get_tool_types_and_proxies_count::execute_returns(), $data);
$this->assertEquals(20, $data['count']);
}
/**
* Test get_tool_types_and_proxies_count returns the correct number.
*/
public function test_mod_lti_get_tool_types_and_proxies_count_with_no_tools_configured() {
$data = \mod_lti\external\get_tool_types_and_proxies_count::execute(0, false);
$data = external_api::clean_returnvalue(\mod_lti\external\get_tool_types_and_proxies_count::execute_returns(), $data);
$this->assertEquals(0, $data['count']);
}
}
@@ -0,0 +1,115 @@
<?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/>.
use mod_lti\external\get_tool_types_and_proxies;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/lti/tests/mod_lti_testcase.php');
/**
* PHPUnit tests for get_tool_types_and_proxies external function.
*
* @package mod_lti
* @author Andrew Madden <[email protected]>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_lti_get_tool_types_and_proxies_testcase extends mod_lti_testcase {
/**
* This method runs before every test.
*/
public function setUp(): void {
$this->resetAfterTest();
$this->setAdminUser();
}
/**
* Test get_tool_types_and_proxies.
*/
public function test_mod_lti_get_tool_types_and_proxies() {
$proxy = $this->generate_tool_proxy(1);
$this->generate_tool_type(1, $proxy->id);
$data = get_tool_types_and_proxies::execute(0, false, 50, 0);
$data = external_api::clean_returnvalue(get_tool_types_and_proxies::execute_returns(), $data);
$this->assertCount(1, $data['types']);
$type = $data['types'][0];
$this->assertEquals('Test tool 1', $type['name']);
$this->assertEquals('Example description 1', $type['description']);
$this->assertCount(1, $data['proxies']);
$proxy = $data['proxies'][0];
$this->assertEquals('Test proxy 1', $proxy['name']);
$this->assertEquals(50, $data['limit']);
$this->assertEquals(0, $data['offset']);
}
/**
* Test get_tool_types_and_proxies with multiple pages of tool types.
*/
public function test_mod_lti_get_tool_types_and_proxies_with_multiple_pages() {
for ($i = 0; $i < 3; $i++) {
$proxy = $this->generate_tool_proxy($i);
$this->generate_tool_type($i, $proxy->id);
}
$data = get_tool_types_and_proxies::execute(0, false, 5, 0);
$data = external_api::clean_returnvalue(get_tool_types_and_proxies::execute_returns(), $data);
$this->assertCount(2, $data['types']);
$this->assertCount(3, $data['proxies']);
$this->assertEquals(5, $data['limit']);
$this->assertEquals(0, $data['offset']);
}
/**
* Test get_tool_types_and_proxies with multiple pages of tool types and offset.
*/
public function test_mod_lti_get_tool_types_and_proxies_with_multiple_pages_last_page() {
for ($i = 0; $i < 6; $i++) {
$proxy = $this->generate_tool_proxy($i);
$this->generate_tool_type($i, $proxy->id);
}
$data = get_tool_types_and_proxies::execute(0, false, 5, 10);
$data = external_api::clean_returnvalue(get_tool_types_and_proxies::execute_returns(), $data);
$this->assertCount(2, $data['types']);
$this->assertCount(0, $data['proxies']);
$this->assertEquals(5, $data['limit']);
$this->assertEquals(10, $data['offset']);
}
/**
* Test get_tool_types_and_proxies without pagination.
*/
public function test_mod_lti_get_tool_types_and_proxies_without_pagination() {
for ($i = 0; $i < 10; $i++) {
$proxy = $this->generate_tool_proxy($i);
$this->generate_tool_type($i, $proxy->id);
}
$data = get_tool_types_and_proxies::execute(0, false, 0, 0);
$data = external_api::clean_returnvalue(get_tool_types_and_proxies::execute_returns(), $data);
$this->assertCount(10, $data['types']);
$this->assertCount(10, $data['proxies']);
}
}
+2 -35
View File
@@ -30,6 +30,7 @@ global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/mod/lti/lib.php');
require_once($CFG->dirroot . '/mod/lti/tests/mod_lti_testcase.php');
/**
* External tool module external functions tests
@@ -40,7 +41,7 @@ require_once($CFG->dirroot . '/mod/lti/lib.php');
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class mod_lti_external_testcase extends externallib_advanced_testcase {
class mod_lti_external_testcase extends mod_lti_testcase {
/**
* Set up for every test
@@ -88,39 +89,6 @@ class mod_lti_external_testcase extends externallib_advanced_testcase {
];
}
/**
* Generate a tool type.
*
* @param string $uniqueid Each tool type needs a different base url. Provide a unique string for every tool type created.
* @param int|null $toolproxyid Optional proxy to associate with tool type.
* @return stdClass A tool type.
*/
protected function generate_tool_type(string $uniqueid, int $toolproxyid = null) : stdClass {
// Create a tool type.
$type = new stdClass();
$type->state = LTI_TOOL_STATE_CONFIGURED;
$type->name = "Test tool $uniqueid";
$type->description = "Example description $uniqueid";
$type->toolproxyid = $toolproxyid;
$type->baseurl = $this->getExternalTestFileUrl("/test$uniqueid.html");
lti_add_type($type, new stdClass());
return $type;
}
/**
* Generate a tool proxy.
*
* @param string $uniqueid Each tool proxy needs a different reg url. Provide a unique string for every tool proxy created.
* @return stdClass A tool proxy.
*/
protected function generate_tool_proxy(string $uniqueid) : stdClass {
// Create a tool proxy.
$proxy = mod_lti_external::create_tool_proxy("Test proxy $uniqueid",
$this->getExternalTestFileUrl("/proxy$uniqueid.html"), array(), array());
$proxy = (object)external_api::clean_returnvalue(mod_lti_external::create_tool_proxy_returns(), $proxy);
return $proxy;
}
/**
* Test get_tool_proxies.
*/
@@ -479,7 +447,6 @@ class mod_lti_external_testcase extends externallib_advanced_testcase {
* Test get_tool_types.
*/
public function test_mod_lti_get_tool_types() {
// Create a tool proxy.
$this->setAdminUser();
$proxy = mod_lti_external::create_tool_proxy('Test proxy', $this->getExternalTestFileUrl('/test.html'), array(), array());
$proxy = (object) external_api::clean_returnvalue(mod_lti_external::create_tool_proxy_returns(), $proxy);
@@ -0,0 +1,50 @@
<?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/>.
defined('MOODLE_INTERNAL') || die();
/**
* Define behat generator for mod_lti.
*
* @package mod_lti
* @category test
* @author Andrew Madden <[email protected]>
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_mod_lti_generator extends behat_generator_base {
/**
* Get list of entities for mod_lti behat tests.
*
* @return array[] List of entity definitions.
*/
protected function get_creatable_entities(): array {
return [
'tool proxies' => [
'singular' => 'tool proxy',
'datagenerator' => 'tool_proxies',
'required' => [],
],
'tool types' => [
'singular' => 'tool type',
'datagenerator' => 'tool_types',
'required' => ['baseurl'],
],
];
}
}
+31
View File
@@ -26,6 +26,9 @@
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/lti/locallib.php');
/**
* LTI module data generator class
*
@@ -66,4 +69,32 @@ class mod_lti_generator extends testing_module_generator {
}
return parent::create_instance($record, (array)$options);
}
/**
* Create a tool proxy.
*
* @param array $config
*/
public function create_tool_proxies(array $config) {
if (!isset($config['capabilityoffered'])) {
$config['capabilityoffered'] = '';
}
if (!isset($config['serviceoffered'])) {
$config['serviceoffered'] = '';
}
lti_add_tool_proxy((object) $config);
}
/**
* Create a tool type.
*
* @param array $type
* @param array|null $config
*/
public function create_tool_types(array $type, ?array $config = null) {
if (!isset($type['baseurl'])) {
throw new coding_exception('Must specify baseurl when creating a LTI tool type.');
}
lti_add_type((object) $type, (object) $config);
}
}
+128 -1
View File
@@ -52,6 +52,7 @@ defined('MOODLE_INTERNAL') || die;
global $CFG;
require_once($CFG->dirroot . '/mod/lti/locallib.php');
require_once($CFG->dirroot . '/mod/lti/servicelib.php');
require_once($CFG->dirroot . '/mod/lti/tests/mod_lti_testcase.php');
/**
* Local library tests
@@ -60,7 +61,7 @@ require_once($CFG->dirroot . '/mod/lti/servicelib.php');
* @copyright Copyright (c) 2012 Moodlerooms Inc. (http://www.moodlerooms.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_lti_locallib_testcase extends advanced_testcase {
class mod_lti_locallib_testcase extends mod_lti_testcase {
public function test_split_custom_parameters() {
$this->resetAfterTest();
@@ -1837,6 +1838,109 @@ MwIDAQAB
];
}
/**
* Test lti_get_lti_types_and_proxies with no limit or offset.
*/
public function test_lti_get_lti_types_and_proxies_with_no_limit() {
$this->resetAfterTest();
$this->setAdminUser();
$this->generate_tool_types_and_proxies(10);
list($proxies, $types) = lti_get_lti_types_and_proxies();
$this->assertCount(10, $proxies);
$this->assertCount(10, $types);
}
/**
* Test lti_get_lti_types_and_proxies with limits.
*/
public function test_lti_get_lti_types_and_proxies_with_limit() {
$this->resetAfterTest();
$this->setAdminUser();
$this->generate_tool_types_and_proxies(10);
// Get the middle 10 data sets (of 20 total).
list($proxies, $types) = lti_get_lti_types_and_proxies(10, 5);
$this->assertCount(5, $proxies);
$this->assertCount(5, $types);
// Get the last 5 data sets with large limit (of 20 total).
list($proxies, $types) = lti_get_lti_types_and_proxies(50, 15);
$this->assertCount(0, $proxies);
$this->assertCount(5, $types);
// Get the last 13 data sets with large limit (of 20 total).
list($proxies, $types) = lti_get_lti_types_and_proxies(50, 7);
$this->assertCount(3, $proxies);
$this->assertCount(10, $types);
}
/**
* Test lti_get_lti_types_and_proxies with limits and only fetching orphaned proxies.
*/
public function test_lti_get_lti_types_and_proxies_with_limit_and_orphaned_proxies() {
$this->resetAfterTest();
$this->setAdminUser();
$this->generate_tool_types_and_proxies(10, 5);
// Get the first 10 data sets (of 15 total).
list($proxies, $types) = lti_get_lti_types_and_proxies(10, 0, true);
$this->assertCount(5, $proxies);
$this->assertCount(5, $types);
// Get the middle 10 data sets with large limit (of 15 total).
list($proxies, $types) = lti_get_lti_types_and_proxies(10, 2, true);
$this->assertCount(3, $proxies);
$this->assertCount(7, $types);
// Get the last 5 data sets with large limit (of 15 total).
list($proxies, $types) = lti_get_lti_types_and_proxies(50, 10, true);
$this->assertCount(0, $proxies);
$this->assertCount(5, $types);
}
/**
* Test lti_get_lti_types_and_proxies_count.
*/
public function test_lti_get_lti_types_and_proxies_count_with_no_filters() {
$this->resetAfterTest();
$this->setAdminUser();
$this->generate_tool_types_and_proxies(10, 5);
$totalcount = lti_get_lti_types_and_proxies_count();
$this->assertEquals(25, $totalcount); // 10 types, 15 proxies.
}
/**
* Test lti_get_lti_types_and_proxies_count only counting orphaned proxies.
*/
public function test_lti_get_lti_types_and_proxies_count_with_only_orphaned_proxies() {
$this->resetAfterTest();
$this->setAdminUser();
$this->generate_tool_types_and_proxies(10, 5);
$orphanedcount = lti_get_lti_types_and_proxies_count(true);
$this->assertEquals(15, $orphanedcount); // 10 types, 5 proxies.
}
/**
* Test lti_get_lti_types_and_proxies_count only matching tool type with toolproxyid.
*/
public function test_lti_get_lti_types_and_proxies_count_type_with_proxyid() {
$this->resetAfterTest();
$this->setAdminUser();
['proxies' => $proxies, 'types' => $types] = $this->generate_tool_types_and_proxies(10, 5);
$countwithproxyid = lti_get_lti_types_and_proxies_count(false, $proxies[0]->id);
$this->assertEquals(16, $countwithproxyid); // 1 type, 15 proxies.
}
/**
* Create an LTI Tool.
*
@@ -1876,4 +1980,27 @@ MwIDAQAB
'typeid' => $type->id
), array());
}
/**
* Generate a number of LTI tool types and proxies.
*
* @param int $toolandproxycount How many tool types and associated proxies to create. E.g. Value of 10 will create 10 types
* and 10 proxies.
* @param int $orphanproxycount How many orphaned proxies to create.
* @return array[]
*/
private function generate_tool_types_and_proxies(int $toolandproxycount = 0, int $orphanproxycount = 0) {
$proxies = [];
$types = [];
for ($i = 0; $i < $toolandproxycount; $i++) {
$proxies[$i] = $this->generate_tool_proxy($i);
$types[$i] = $this->generate_tool_type($i, $proxies[$i]->id);
}
for ($i = $toolandproxycount; $i < ($toolandproxycount + $orphanproxycount); $i++) {
$proxies[$i] = $this->generate_tool_proxy($i);
}
return ['proxies' => $proxies, 'types' => $types];
}
}
+64
View File
@@ -0,0 +1,64 @@
<?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/>.
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Abstract base testcase for mod_lti unit tests.
*
* @package mod_lti
* @author Andrew Madden <[email protected]>
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class mod_lti_testcase extends externallib_advanced_testcase {
/**
* Generate a tool type.
*
* @param string $uniqueid Each tool type needs a different base url. Provide a unique string for every tool type created.
* @param int|null $toolproxyid Optional proxy to associate with tool type.
* @return stdClass A tool type.
*/
protected function generate_tool_type(string $uniqueid, ?int $toolproxyid = null): stdClass {
// Create a tool type.
$type = new stdClass();
$type->state = LTI_TOOL_STATE_CONFIGURED;
$type->name = "Test tool $uniqueid";
$type->description = "Example description $uniqueid";
$type->toolproxyid = $toolproxyid;
$type->baseurl = $this->getExternalTestFileUrl("/test$uniqueid.html");
lti_add_type($type, new stdClass());
return $type;
}
/**
* Generate a tool proxy.
*
* @param string $uniqueid Each tool proxy needs a different reg url. Provide a unique string for every tool proxy created.
* @return stdClass A tool proxy.
*/
protected function generate_tool_proxy(string $uniqueid): stdClass {
// Create a tool proxy.
$proxy = mod_lti_external::create_tool_proxy("Test proxy $uniqueid",
$this->getExternalTestFileUrl("/proxy$uniqueid.html"), [], []);
return (object)external_api::clean_returnvalue(mod_lti_external::create_tool_proxy_returns(), $proxy);
}
}
+1 -1
View File
@@ -48,7 +48,7 @@
defined('MOODLE_INTERNAL') || die;
$plugin->version = 2021052501; // The current module version (Date: YYYYMMDDXX).
$plugin->version = 2021052502; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021052500; // Requires this Moodle version.
$plugin->component = 'mod_lti'; // Full name of the plugin (used for diagnostics).
$plugin->cron = 0;