mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 16:04:25 +02:00
MDL-67883 tool_moodlenet: Add MoodleNet to core
This commit is contained in:
parent
16d77f1884
commit
b1e6d8b86f
2
admin/tool/moodlenet/amd/build/instance_form.min.js
vendored
Normal file
2
admin/tool/moodlenet/amd/build/instance_form.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
define ("tool_moodlenet/instance_form",["tool_moodlenet/validator","tool_moodlenet/selectors","core/loadingicon","core/templates","core/notification","jquery"],function(a,b,c,d,e,f){var g=function(d){d.addEventListener("click",function(f){if(f.target.matches(b.action.submit)){var e=d.querySelector("[data-var=\"mnet-link\"]"),g=d.querySelector(b.region.spinner),h=document.querySelector(b.region.validationArea);g.classList.remove("d-none");var i=c.addIconToContainerWithPromise(g);a.validation(e).then(function(a){i.resolve();g.classList.add("d-none");if(a.result){e.classList.remove("is-invalid");e.classList.add("is-valid");h.innerText=a.message;h.classList.remove("text-error");h.classList.add("text-success");setTimeout(function(){window.location=a.domain},1e3)}else{e.classList.add("is-invalid");h.innerText=a.message;h.classList.add("text-error")}}).catch()}})},h=function(a,b,h,i){a.innerHTML="";var j=c.addIconToContainer(a),k=null,l=new Promise(function(a){k=a});f.when(j,l).then(function(){d.replaceNodeContents(a,b.customcarouseltemplate,"")}).catch(e.exception);g(a);h.one("slid.bs.carousel",function(){k()});h.carousel(2);i.setFooter(d.render("tool_moodlenet/chooser_footer_close_mnet",{}))},i=function(a,b,c){a.carousel(0);b.setFooter(c.customfootertemplate)};return{footerClickListener:function footerClickListener(a,c,d){if(a.target.matches(b.action.showMoodleNet)||a.target.closest(b.action.showMoodleNet)){a.preventDefault();var e=f(d.getBody()[0].querySelector(b.region.carousel)),g=e.find(b.region.moodleNet)[0];h(g,c,e,d)}if(a.target.matches(b.action.closeOption)){var j=f(d.getBody()[0].querySelector(b.region.carousel));i(j,d,c)}}}});
|
||||
//# sourceMappingURL=instance_form.min.js.map
|
1
admin/tool/moodlenet/amd/build/instance_form.min.js.map
Normal file
1
admin/tool/moodlenet/amd/build/instance_form.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
admin/tool/moodlenet/amd/build/select_page.min.js
vendored
Normal file
2
admin/tool/moodlenet/amd/build/select_page.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
define ("tool_moodlenet/select_page",["core/ajax","core/templates","tool_moodlenet/selectors","core/notification"],function(a,b,c,d){var e,f=function(a){return b.renderPix("courses","tool_moodlenet").then(function(a){return a}).then(function(a){var c=document.createElement("div");c.innerHTML=a.trim();return b.render("core_course/no-courses",{nocoursesimg:c.firstChild.src})}).then(function(c,d){b.replaceNodeContents(a,c,d);a.classList.add("mx-auto");a.classList.add("w-25")})},g=function(a,c){return b.render("tool_moodlenet/view-cards",{courses:c}).then(function(c,d){b.replaceNodeContents(a,c,d);a.classList.remove("mx-auto");a.classList.remove("w-25")})},h=function(b,h,i){var j=h.querySelector(c.region.searchIcon),k=h.querySelector(c.region.clearIcon);if(""!==b){j.classList.add("d-none");k.parentElement.classList.remove("d-none")}else{j.classList.remove("d-none");k.parentElement.classList.add("d-none")}a.call([{methodname:"tool_moodlenet_search_courses",args:{searchvalue:b}}])[0].then(function(a){if(0===a.courses.length){return f(i)}else{a.courses.forEach(function(a){a.viewurl+="&id="+e});return g(i,a.courses)}}).catch(d.exception)},i=function(a){var b=a.querySelector(c.region.searchInput),d=a.querySelector(c.region.courses),e=a.querySelector(c.region.clearIcon);e.addEventListener("click",function(){b.value="";h("",a,d)});b.addEventListener("input",k(function(){h(b.value,a,d)},300))},j=function(a){var b=a.querySelector(c.region.courses);h("",a,b)},k=function(a,b,c){var d;return function(){var e=this,f=arguments,g=c&&!d;clearTimeout(d);d=setTimeout(function later(){d=null;if(!c){a.apply(e,f)}},b);if(g){a.apply(e,f)}}};return{init:function init(a){e=a;var b=document.querySelector(c.region.selectPage);i(b);j(b)}}});
|
||||
//# sourceMappingURL=select_page.min.js.map
|
1
admin/tool/moodlenet/amd/build/select_page.min.js.map
Normal file
1
admin/tool/moodlenet/amd/build/select_page.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
admin/tool/moodlenet/amd/build/selectors.min.js
vendored
Normal file
2
admin/tool/moodlenet/amd/build/selectors.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
define ("tool_moodlenet/selectors",[],function(){return{action:{browse:"[data-action=\"browse\"]",submit:"[data-action=\"submit\"]",showMoodleNet:"[data-action=\"show-moodlenet\"]",closeOption:"[data-action=\"close-chooser-option-summary\"]"},region:{clearIcon:"[data-region=\"clear-icon\"]",courses:"[data-region=\"mnet-courses\"]",instancePage:"[data-region=\"moodle-net\"]",searchInput:"[data-region=\"search-input\"]",searchIcon:"[data-region=\"search-icon\"]",selectPage:"[data-region=\"moodle-net-select\"]",spinner:"[data-region=\"spinner\"]",validationArea:"[data-region=\"validation-area\"]",carousel:"[data-region=\"carousel\"]",moodleNet:"[data-region=\"pluginCarousel\"]"}}});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
1
admin/tool/moodlenet/amd/build/selectors.min.js.map
Normal file
1
admin/tool/moodlenet/amd/build/selectors.min.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/selectors.js"],"names":["define","action","browse","submit","showMoodleNet","closeOption","region","clearIcon","courses","instancePage","searchInput","searchIcon","selectPage","spinner","validationArea","carousel","moodleNet"],"mappings":"AAuBAA,OAAM,4BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,MAAM,CAAE,CACJC,MAAM,CAAE,0BADJ,CAEJC,MAAM,CAAE,0BAFJ,CAGJC,aAAa,CAAE,kCAHX,CAIJC,WAAW,CAAE,gDAJT,CADL,CAOHC,MAAM,CAAE,CACJC,SAAS,CAAE,8BADP,CAEJC,OAAO,CAAE,gCAFL,CAGJC,YAAY,CAAE,8BAHV,CAIJC,WAAW,CAAE,gCAJT,CAKJC,UAAU,CAAE,+BALR,CAMJC,UAAU,CAAE,qCANR,CAOJC,OAAO,CAAE,2BAPL,CAQJC,cAAc,CAAE,mCARZ,CASJC,QAAQ,CAAE,4BATN,CAUJC,SAAS,CAAE,kCAVP,CAPL,CAoBV,CArBK,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 * Define all of the selectors we will be using within MoodleNet plugin.\n *\n * @module tool_moodlenet/selectors\n * @package tool_moodlenet\n * @copyright 2020 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n action: {\n browse: '[data-action=\"browse\"]',\n submit: '[data-action=\"submit\"]',\n showMoodleNet: '[data-action=\"show-moodlenet\"]',\n closeOption: '[data-action=\"close-chooser-option-summary\"]',\n },\n region: {\n clearIcon: '[data-region=\"clear-icon\"]',\n courses: '[data-region=\"mnet-courses\"]',\n instancePage: '[data-region=\"moodle-net\"]',\n searchInput: '[data-region=\"search-input\"]',\n searchIcon: '[data-region=\"search-icon\"]',\n selectPage: '[data-region=\"moodle-net-select\"]',\n spinner: '[data-region=\"spinner\"]',\n validationArea: '[data-region=\"validation-area\"]',\n carousel: '[data-region=\"carousel\"]',\n moodleNet: '[data-region=\"pluginCarousel\"]',\n },\n };\n});\n"],"file":"selectors.min.js"}
|
2
admin/tool/moodlenet/amd/build/validator.min.js
vendored
Normal file
2
admin/tool/moodlenet/amd/build/validator.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
define ("tool_moodlenet/validator",["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){return{validation:function(e){var f=e.value;if(""===f||!f.includes("@")){a.when(c.get_string("profilevalidationerror","tool_moodlenet")).then(function(a){return Promise.reject().catch(function(){return{result:!1,message:a[0]}})}).fail(d.exception)}return b.call([{methodname:"tool_moodlenet_verify_webfinger",args:{profileurl:f,course:e.dataset.courseid,section:e.dataset.sectionid}}])[0].then(function(a){return a}).catch()}}});
|
||||
//# sourceMappingURL=validator.min.js.map
|
1
admin/tool/moodlenet/amd/build/validator.min.js.map
Normal file
1
admin/tool/moodlenet/amd/build/validator.min.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/validator.js"],"names":["define","$","Ajax","Str","Notification","validation","inputElement","inputValue","value","includes","when","get_string","then","strings","Promise","reject","catch","result","message","fail","exception","call","methodname","args","profileurl","course","dataset","courseid","section","sectionid"],"mappings":"AAuBAA,OAAM,4BAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,UAAxB,CAAoC,mBAApC,CAAD,CAA2D,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAAuBC,CAAvB,CAAqC,CAgClG,MAAO,CACHC,UAAU,CAzBG,SAAoBC,CAApB,CAAkC,CAC/C,GAAIC,CAAAA,CAAU,CAAGD,CAAY,CAACE,KAA9B,CAGA,GAAmB,EAAf,GAAAD,CAAU,EAAW,CAACA,CAAU,CAACE,QAAX,CAAoB,GAApB,CAA1B,CAAoD,CAEhDR,CAAC,CAACS,IAAF,CAAOP,CAAG,CAACQ,UAAJ,CAAe,wBAAf,CAAyC,gBAAzC,CAAP,EAAmEC,IAAnE,CAAwE,SAASC,CAAT,CAAkB,CACtF,MAAOC,CAAAA,OAAO,CAACC,MAAR,GAAiBC,KAAjB,CAAuB,UAAW,CACrC,MAAO,CAACC,MAAM,GAAP,CAAgBC,OAAO,CAAEL,CAAO,CAAC,CAAD,CAAhC,CACV,CAFM,CAGV,CAJD,EAIGM,IAJH,CAIQf,CAAY,CAACgB,SAJrB,CAKH,CAED,MAAOlB,CAAAA,CAAI,CAACmB,IAAL,CAAU,CAAC,CACdC,UAAU,CAAE,iCADE,CAEdC,IAAI,CAAE,CACFC,UAAU,CAAEjB,CADV,CAEFkB,MAAM,CAAEnB,CAAY,CAACoB,OAAb,CAAqBC,QAF3B,CAGFC,OAAO,CAAEtB,CAAY,CAACoB,OAAb,CAAqBG,SAH5B,CAFQ,CAAD,CAAV,EAOH,CAPG,EAOAjB,IAPA,CAOK,SAASK,CAAT,CAAiB,CACzB,MAAOA,CAAAA,CACV,CATM,EASJD,KATI,EAUV,CACM,CAGV,CAnCK,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 * Our validator that splits the user's input then fires off to a webservice\n *\n * @module tool_moodlenet/validator\n * @package tool_moodlenet\n * @copyright 2020 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'core/notification'], function($, Ajax, Str, Notification) {\n /**\n * Handle form validation\n *\n * @method validation\n * @param {HTMLElement} inputElement The element the user entered text into.\n * @return {Promise} Was the users' entry a valid profile URL?\n */\n var validation = function validation(inputElement) {\n var inputValue = inputElement.value;\n\n // They didn't submit anything or they gave us a simple string that we can't do anything with.\n if (inputValue === \"\" || !inputValue.includes(\"@\")) {\n // Create a promise and immediately reject it.\n $.when(Str.get_string('profilevalidationerror', 'tool_moodlenet')).then(function(strings) {\n return Promise.reject().catch(function() {\n return {result: false, message: strings[0]};\n });\n }).fail(Notification.exception);\n }\n\n return Ajax.call([{\n methodname: 'tool_moodlenet_verify_webfinger',\n args: {\n profileurl: inputValue,\n course: inputElement.dataset.courseid,\n section: inputElement.dataset.sectionid\n }\n }])[0].then(function(result) {\n return result;\n }).catch();\n };\n return {\n validation: validation,\n };\n});\n"],"file":"validator.min.js"}
|
169
admin/tool/moodlenet/amd/src/instance_form.js
Normal file
169
admin/tool/moodlenet/amd/src/instance_form.js
Normal file
@ -0,0 +1,169 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Our basic form manager for when a user either enters
|
||||
* their profile url or just wants to browse.
|
||||
*
|
||||
* This file is a mishmash of JS functions we need for both the standalone (M3.7, M3.8)
|
||||
* plugin & Moodle 3.9 functions. The 3.9 Functions have a base understanding that certain
|
||||
* things exist i.e. directory structures for templates. When this feature goes 3.9+ only
|
||||
* The goal is that we can quickly gut all AMD modules into bare JS files and use ES6 guidelines.
|
||||
* Till then this will have to do.
|
||||
*
|
||||
* @module tool_moodlenet/instance_form
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define(['tool_moodlenet/validator',
|
||||
'tool_moodlenet/selectors',
|
||||
'core/loadingicon',
|
||||
'core/templates',
|
||||
'core/notification',
|
||||
'jquery'],
|
||||
function(Validator,
|
||||
Selectors,
|
||||
LoadingIcon,
|
||||
Templates,
|
||||
Notification,
|
||||
$) {
|
||||
|
||||
/**
|
||||
* Add the event listeners to our form.
|
||||
*
|
||||
* @method registerListenerEvents
|
||||
* @param {HTMLElement} page The whole page element for our form area
|
||||
*/
|
||||
var registerListenerEvents = function registerListenerEvents(page) {
|
||||
page.addEventListener('click', function(e) {
|
||||
|
||||
// Our fake submit button / browse button.
|
||||
if (e.target.matches(Selectors.action.submit)) {
|
||||
var input = page.querySelector('[data-var="mnet-link"]');
|
||||
var overlay = page.querySelector(Selectors.region.spinner);
|
||||
var validationArea = document.querySelector(Selectors.region.validationArea);
|
||||
|
||||
overlay.classList.remove('d-none');
|
||||
var spinner = LoadingIcon.addIconToContainerWithPromise(overlay);
|
||||
Validator.validation(input)
|
||||
.then(function(result) {
|
||||
spinner.resolve();
|
||||
overlay.classList.add('d-none');
|
||||
if (result.result) {
|
||||
input.classList.remove('is-invalid'); // Just in case the class has been applied already.
|
||||
input.classList.add('is-valid');
|
||||
validationArea.innerText = result.message;
|
||||
validationArea.classList.remove('text-error');
|
||||
validationArea.classList.add('text-success');
|
||||
// Give the user some time to see their input is valid.
|
||||
setTimeout(function() {
|
||||
window.location = result.domain;
|
||||
}, 1000);
|
||||
} else {
|
||||
input.classList.add('is-invalid');
|
||||
validationArea.innerText = result.message;
|
||||
validationArea.classList.add('text-error');
|
||||
}
|
||||
return;
|
||||
}).catch();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a user wishes to see the MoodleNet profile url form transition them there.
|
||||
*
|
||||
* @method chooserNavigateToMnet
|
||||
* @param {HTMLElement} showMoodleNet The chooser's area for ment
|
||||
* @param {Object} footerData Our footer object to render out
|
||||
* @param {jQuery} carousel Our carousel instance to manage
|
||||
* @param {jQuery} modal Our modal instance to manage
|
||||
*/
|
||||
var chooserNavigateToMnet = function(showMoodleNet, footerData, carousel, modal) {
|
||||
showMoodleNet.innerHTML = '';
|
||||
|
||||
// Add a spinner.
|
||||
var spinnerPromise = LoadingIcon.addIconToContainer(showMoodleNet);
|
||||
|
||||
// Used later...
|
||||
var transitionPromiseResolver = null;
|
||||
var transitionPromise = new Promise(resolve => {
|
||||
transitionPromiseResolver = resolve;
|
||||
});
|
||||
|
||||
$.when(
|
||||
spinnerPromise,
|
||||
transitionPromise
|
||||
).then(function() {
|
||||
Templates.replaceNodeContents(showMoodleNet, footerData.customcarouseltemplate, '');
|
||||
return;
|
||||
}).catch(Notification.exception);
|
||||
|
||||
// We apply our handlers in here to minimise plugin dependency in the Chooser.
|
||||
registerListenerEvents(showMoodleNet);
|
||||
|
||||
// Move to the next slide, and resolve the transition promise when it's done.
|
||||
carousel.one('slid.bs.carousel', function() {
|
||||
transitionPromiseResolver();
|
||||
});
|
||||
// Trigger the transition between 'pages'.
|
||||
carousel.carousel(2);
|
||||
// eslint-disable-next-line max-len
|
||||
modal.setFooter(Templates.render('tool_moodlenet/chooser_footer_close_mnet', {}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a user no longer wishes to see the MoodleNet profile url form transition them from there.
|
||||
*
|
||||
* @method chooserNavigateFromMnet
|
||||
* @param {jQuery} carousel Our carousel instance to manage
|
||||
* @param {jQuery} modal Our modal instance to manage
|
||||
* @param {Object} footerData Our footer object to render out
|
||||
*/
|
||||
var chooserNavigateFromMnet = function(carousel, modal, footerData) {
|
||||
// Trigger the transition between 'pages'.
|
||||
carousel.carousel(0);
|
||||
modal.setFooter(footerData.customfootertemplate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the custom listener that would handle anything in the footer.
|
||||
*
|
||||
* @param {Event} e The event being triggered.
|
||||
* @param {Object} footerData The data generated from the exporter.
|
||||
* @param {Object} modal The chooser modal.
|
||||
*/
|
||||
var footerClickListener = function(e, footerData, modal) {
|
||||
if (e.target.matches(Selectors.action.showMoodleNet) || e.target.closest(Selectors.action.showMoodleNet)) {
|
||||
e.preventDefault();
|
||||
const carousel = $(modal.getBody()[0].querySelector(Selectors.region.carousel));
|
||||
const showMoodleNet = carousel.find(Selectors.region.moodleNet)[0];
|
||||
|
||||
chooserNavigateToMnet(showMoodleNet, footerData, carousel, modal);
|
||||
}
|
||||
// From the help screen go back to the module overview.
|
||||
if (e.target.matches(Selectors.action.closeOption)) {
|
||||
const carousel = $(modal.getBody()[0].querySelector(Selectors.region.carousel));
|
||||
|
||||
chooserNavigateFromMnet(carousel, modal, footerData);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
footerClickListener: footerClickListener
|
||||
};
|
||||
});
|
198
admin/tool/moodlenet/amd/src/select_page.js
Normal file
198
admin/tool/moodlenet/amd/src/select_page.js
Normal file
@ -0,0 +1,198 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* When returning to Moodle let the user select which course to add the resource to.
|
||||
*
|
||||
* @module tool_moodlenet/select_page
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define([
|
||||
'core/ajax',
|
||||
'core/templates',
|
||||
'tool_moodlenet/selectors',
|
||||
'core/notification'
|
||||
], function(
|
||||
Ajax,
|
||||
Templates,
|
||||
Selectors,
|
||||
Notification
|
||||
) {
|
||||
/**
|
||||
* @var {string} The id corresponding to the import.
|
||||
*/
|
||||
var importId;
|
||||
|
||||
/**
|
||||
* Set up the page.
|
||||
*
|
||||
* @method init
|
||||
* @param {string} importIdString the string ID of the import.
|
||||
*/
|
||||
var init = function(importIdString) {
|
||||
importId = importIdString;
|
||||
var page = document.querySelector(Selectors.region.selectPage);
|
||||
registerListenerEvents(page);
|
||||
addCourses(page);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the 'no-courses' template.
|
||||
*
|
||||
* @param {HTMLElement} areaReplace the DOM node to replace.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
var renderNoCourses = function(areaReplace) {
|
||||
return Templates.renderPix('courses', 'tool_moodlenet').then(function(img) {
|
||||
return img;
|
||||
}).then(function(img) {
|
||||
var temp = document.createElement('div');
|
||||
temp.innerHTML = img.trim();
|
||||
return Templates.render('core_course/no-courses', {
|
||||
nocoursesimg: temp.firstChild.src
|
||||
});
|
||||
}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(areaReplace, html, js);
|
||||
areaReplace.classList.add('mx-auto');
|
||||
areaReplace.classList.add('w-25');
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the course cards for those supplied courses.
|
||||
*
|
||||
* @param {HTMLElement} areaReplace the DOM node to replace.
|
||||
* @param {Array<courses>} courses the courses to render.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
var renderCourses = function(areaReplace, courses) {
|
||||
return Templates.render('tool_moodlenet/view-cards', {
|
||||
courses: courses
|
||||
}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(areaReplace, html, js);
|
||||
areaReplace.classList.remove('mx-auto');
|
||||
areaReplace.classList.remove('w-25');
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* For a given input, the page & what to replace fetch courses and manage icons too.
|
||||
*
|
||||
* @method searchCourses
|
||||
* @param {string} inputValue What to search for
|
||||
* @param {HTMLElement} page The whole page element for our page
|
||||
* @param {HTMLElement} areaReplace The Element to replace the contents of
|
||||
*/
|
||||
var searchCourses = function(inputValue, page, areaReplace) {
|
||||
var searchIcon = page.querySelector(Selectors.region.searchIcon);
|
||||
var clearIcon = page.querySelector(Selectors.region.clearIcon);
|
||||
|
||||
if (inputValue !== '') {
|
||||
searchIcon.classList.add('d-none');
|
||||
clearIcon.parentElement.classList.remove('d-none');
|
||||
} else {
|
||||
searchIcon.classList.remove('d-none');
|
||||
clearIcon.parentElement.classList.add('d-none');
|
||||
}
|
||||
var args = {
|
||||
searchvalue: inputValue,
|
||||
};
|
||||
Ajax.call([{
|
||||
methodname: 'tool_moodlenet_search_courses',
|
||||
args: args
|
||||
}])[0].then(function(result) {
|
||||
if (result.courses.length === 0) {
|
||||
return renderNoCourses(areaReplace);
|
||||
} else {
|
||||
// Add the importId to the course link
|
||||
result.courses.forEach(function(course) {
|
||||
course.viewurl += '&id=' + importId;
|
||||
});
|
||||
return renderCourses(areaReplace, result.courses);
|
||||
}
|
||||
}).catch(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the event listeners to our page.
|
||||
*
|
||||
* @method registerListenerEvents
|
||||
* @param {HTMLElement} page The whole page element for our page
|
||||
*/
|
||||
var registerListenerEvents = function(page) {
|
||||
var input = page.querySelector(Selectors.region.searchInput);
|
||||
var courseArea = page.querySelector(Selectors.region.courses);
|
||||
var clearIcon = page.querySelector(Selectors.region.clearIcon);
|
||||
clearIcon.addEventListener('click', function() {
|
||||
input.value = '';
|
||||
searchCourses('', page, courseArea);
|
||||
});
|
||||
|
||||
input.addEventListener('input', debounce(function() {
|
||||
searchCourses(input.value, page, courseArea);
|
||||
}, 300));
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch the courses to show the user. We use the same WS structure & template as the search for consistency.
|
||||
*
|
||||
* @method addCourses
|
||||
* @param {HTMLElement} page The whole page element for our course page
|
||||
*/
|
||||
var addCourses = function(page) {
|
||||
var courseArea = page.querySelector(Selectors.region.courses);
|
||||
searchCourses('', page, courseArea);
|
||||
};
|
||||
|
||||
/**
|
||||
* Define our own debounce function as Moodle 3.7 does not have it.
|
||||
*
|
||||
* @method debounce
|
||||
* @from underscore.js
|
||||
* @copyright 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
* @licence MIT
|
||||
* @param {function} func The function we want to keep calling
|
||||
* @param {number} wait Our timeout
|
||||
* @param {boolean} immediate Do we want to apply the function immediately
|
||||
* @return {function}
|
||||
*/
|
||||
var debounce = function(func, wait, immediate) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (!immediate) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
};
|
||||
});
|
45
admin/tool/moodlenet/amd/src/selectors.js
Normal file
45
admin/tool/moodlenet/amd/src/selectors.js
Normal file
@ -0,0 +1,45 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Define all of the selectors we will be using within MoodleNet plugin.
|
||||
*
|
||||
* @module tool_moodlenet/selectors
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([], function() {
|
||||
return {
|
||||
action: {
|
||||
browse: '[data-action="browse"]',
|
||||
submit: '[data-action="submit"]',
|
||||
showMoodleNet: '[data-action="show-moodlenet"]',
|
||||
closeOption: '[data-action="close-chooser-option-summary"]',
|
||||
},
|
||||
region: {
|
||||
clearIcon: '[data-region="clear-icon"]',
|
||||
courses: '[data-region="mnet-courses"]',
|
||||
instancePage: '[data-region="moodle-net"]',
|
||||
searchInput: '[data-region="search-input"]',
|
||||
searchIcon: '[data-region="search-icon"]',
|
||||
selectPage: '[data-region="moodle-net-select"]',
|
||||
spinner: '[data-region="spinner"]',
|
||||
validationArea: '[data-region="validation-area"]',
|
||||
carousel: '[data-region="carousel"]',
|
||||
moodleNet: '[data-region="pluginCarousel"]',
|
||||
},
|
||||
};
|
||||
});
|
59
admin/tool/moodlenet/amd/src/validator.js
Normal file
59
admin/tool/moodlenet/amd/src/validator.js
Normal file
@ -0,0 +1,59 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Our validator that splits the user's input then fires off to a webservice
|
||||
*
|
||||
* @module tool_moodlenet/validator
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/str', 'core/notification'], function($, Ajax, Str, Notification) {
|
||||
/**
|
||||
* Handle form validation
|
||||
*
|
||||
* @method validation
|
||||
* @param {HTMLElement} inputElement The element the user entered text into.
|
||||
* @return {Promise} Was the users' entry a valid profile URL?
|
||||
*/
|
||||
var validation = function validation(inputElement) {
|
||||
var inputValue = inputElement.value;
|
||||
|
||||
// They didn't submit anything or they gave us a simple string that we can't do anything with.
|
||||
if (inputValue === "" || !inputValue.includes("@")) {
|
||||
// Create a promise and immediately reject it.
|
||||
$.when(Str.get_string('profilevalidationerror', 'tool_moodlenet')).then(function(strings) {
|
||||
return Promise.reject().catch(function() {
|
||||
return {result: false, message: strings[0]};
|
||||
});
|
||||
}).fail(Notification.exception);
|
||||
}
|
||||
|
||||
return Ajax.call([{
|
||||
methodname: 'tool_moodlenet_verify_webfinger',
|
||||
args: {
|
||||
profileurl: inputValue,
|
||||
course: inputElement.dataset.courseid,
|
||||
section: inputElement.dataset.sectionid
|
||||
}
|
||||
}])[0].then(function(result) {
|
||||
return result;
|
||||
}).catch();
|
||||
};
|
||||
return {
|
||||
validation: validation,
|
||||
};
|
||||
});
|
189
admin/tool/moodlenet/classes/external.php
Normal file
189
admin/tool/moodlenet/classes/external.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* This is the external API for this component.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_moodlenet;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir .'/externallib.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
require_once(__DIR__ . '/../lib.php');
|
||||
|
||||
use core_course\external\course_summary_exporter;
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_value;
|
||||
use external_single_structure;
|
||||
|
||||
/**
|
||||
* This is the external API for this component.
|
||||
*
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class external extends external_api {
|
||||
|
||||
/**
|
||||
* verify_webfinger parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function verify_webfinger_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'profileurl' => new external_value(PARAM_RAW, 'The profile url that the user has given us', VALUE_REQUIRED),
|
||||
'course' => new external_value(PARAM_INT, 'The course we are adding to', VALUE_REQUIRED),
|
||||
'section' => new external_value(PARAM_INT, 'The section within the course we are adding to', VALUE_REQUIRED),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out if the passed content resolves with a WebFinger account.
|
||||
*
|
||||
* @param string $profileurl The profile url that the user states exists
|
||||
* @param int $course The course we are adding to
|
||||
* @param int $section The section within the course we are adding to
|
||||
* @return array Contains the result and domain if any
|
||||
* @throws \invalid_parameter_exception
|
||||
*/
|
||||
public static function verify_webfinger(string $profileurl, int $course, int $section) {
|
||||
global $USER;
|
||||
|
||||
$params = self::validate_parameters(self::verify_webfinger_parameters(), [
|
||||
'profileurl' => $profileurl,
|
||||
'section' => $section,
|
||||
'course' => $course
|
||||
]
|
||||
);
|
||||
try {
|
||||
$mnetprofile = new moodlenet_user_profile($params['profileurl'], $USER->id);
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'result' => false,
|
||||
'message' => get_string('profilevalidationfail', 'tool_moodlenet'),
|
||||
];
|
||||
}
|
||||
|
||||
$userlink = profile_manager::get_moodlenet_profile_link($mnetprofile);
|
||||
|
||||
// There were no problems verifying the account so lets store it.
|
||||
if ($userlink['result'] === true) {
|
||||
profile_manager::save_moodlenet_user_profile($mnetprofile);
|
||||
$userlink['domain'] = generate_mnet_endpoint($mnetprofile->get_profile_name(), $course, $section);
|
||||
}
|
||||
|
||||
return $userlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* verify_webfinger return.
|
||||
*
|
||||
* @return \external_description
|
||||
*/
|
||||
public static function verify_webfinger_returns() {
|
||||
return new external_single_structure([
|
||||
'result' => new external_value(PARAM_BOOL, 'Was the passed content a valid WebFinger?'),
|
||||
'message' => new external_value(PARAM_TEXT, 'Our message for the user'),
|
||||
'domain' => new external_value(PARAM_RAW, 'Domain to redirect the user to', VALUE_OPTIONAL),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* search_courses_parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function search_courses_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'searchvalue' => new external_value(PARAM_RAW, 'search value'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* For some given input find and return any course that matches it.
|
||||
*
|
||||
* @param string $searchvalue The profile url that the user states exists
|
||||
* @return array Contains the result set of courses for the value
|
||||
*/
|
||||
public static function search_courses(string $searchvalue) {
|
||||
global $OUTPUT;
|
||||
|
||||
$params = self::validate_parameters(
|
||||
self::search_courses_parameters(),
|
||||
['searchvalue' => $searchvalue]
|
||||
);
|
||||
self::validate_context(\context_system::instance());
|
||||
|
||||
$courses = array();
|
||||
|
||||
if ($arrcourses = \core_course_category::search_courses(array('search' => $params['searchvalue']))) {
|
||||
foreach ($arrcourses as $course) {
|
||||
if (has_capability('moodle/course:manageactivities', \context_course::instance($course->id))) {
|
||||
$data = new \stdClass();
|
||||
$data->id = $course->id;
|
||||
$data->fullname = $course->fullname;
|
||||
$data->hidden = $course->visible;
|
||||
$options = [
|
||||
'course' => $course->id,
|
||||
];
|
||||
$viewurl = new \moodle_url('/admin/tool/moodlenet/options.php', $options);
|
||||
$data->viewurl = $viewurl->out(false);
|
||||
$category = \core_course_category::get($course->category);
|
||||
$data->coursecategory = $category->name;
|
||||
$courseimage = course_summary_exporter::get_course_image($data);
|
||||
if (!$courseimage) {
|
||||
$courseimage = $OUTPUT->get_generated_image_for_id($data->id);
|
||||
}
|
||||
$data->courseimage = $courseimage;
|
||||
$courses[] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array(
|
||||
'courses' => $courses
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* search_courses_returns.
|
||||
*
|
||||
* @return \external_description
|
||||
*/
|
||||
public static function search_courses_returns() {
|
||||
return new external_single_structure([
|
||||
'courses' => new \external_multiple_structure(
|
||||
new external_single_structure([
|
||||
'id' => new external_value(PARAM_INT, 'course id'),
|
||||
'fullname' => new external_value(PARAM_TEXT, 'course full name'),
|
||||
'hidden' => new external_value(PARAM_INT, 'is the course visible'),
|
||||
'viewurl' => new external_value(PARAM_URL, 'Next step of import'),
|
||||
'coursecategory' => new external_value(PARAM_TEXT, 'Category name'),
|
||||
'courseimage' => new external_value(PARAM_RAW, 'course image'),
|
||||
]))
|
||||
]);
|
||||
}
|
||||
}
|
194
admin/tool/moodlenet/classes/local/import_backup_helper.php
Normal file
194
admin/tool/moodlenet/classes/local/import_backup_helper.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_backup_helper class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The import_backup_helper class.
|
||||
*
|
||||
* The import_backup_helper objects provide a means to prepare a backup for for restoration of a course or activity backup file.
|
||||
*
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_backup_helper {
|
||||
|
||||
/** @var remote_resource $remoteresource A file resource to be restored. */
|
||||
protected $remoteresource;
|
||||
|
||||
/** @var user $user The user trying to restore a file. */
|
||||
protected $user;
|
||||
|
||||
/** @var context $context The context we are trying to restore this file into. */
|
||||
protected $context;
|
||||
|
||||
/** @var int $useruploadlimit The size limit that this user can upload in this context. */
|
||||
protected $useruploadlimit;
|
||||
|
||||
/**
|
||||
* Constructor for the import backup helper.
|
||||
*
|
||||
* @param remote_resource $remoteresource A remote file resource
|
||||
* @param \stdClass $user The user importing a file.
|
||||
* @param \context $context Context to restore into.
|
||||
*/
|
||||
public function __construct(remote_resource $remoteresource, \stdClass $user, \context $context) {
|
||||
$this->remoteresource = $remoteresource;
|
||||
$this->user = $user;
|
||||
$this->context = $context;
|
||||
|
||||
$maxbytes = 0;
|
||||
if ($this->context->contextlevel == CONTEXT_COURSE) {
|
||||
$course = get_course($this->context->instanceid);
|
||||
$maxbytes = $course->maxbytes;
|
||||
}
|
||||
$this->useruploadlimit = get_user_max_upload_file_size($this->context, get_config('core', 'maxbytes'),
|
||||
$maxbytes, 0, $this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a stored user draft file for processing.
|
||||
*
|
||||
* @return \stored_file The imported file to ultimately be restored.
|
||||
*/
|
||||
public function get_stored_file(): \stored_file {
|
||||
|
||||
// Check if the user can upload a backup to this context.
|
||||
require_capability('moodle/restore:uploadfile', $this->context, $this->user->id);
|
||||
|
||||
// Before starting a potentially lengthy download, try to ensure the file size does not exceed the upload size restrictions
|
||||
// for the user. This is a time saving measure.
|
||||
// This is a naive check, that serves only to catch files if they provide the content length header.
|
||||
// Because of potential content encoding (compression), the stored file will be checked again after download as well.
|
||||
$size = $this->remoteresource->get_download_size() ?? -1;
|
||||
if ($this->size_exceeds_upload_limit($size)) {
|
||||
throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $size,
|
||||
'uploadlimit' => $this->useruploadlimit]);
|
||||
}
|
||||
|
||||
[$filepath, $filename] = $this->remoteresource->download_to_requestdir();
|
||||
\core\antivirus\manager::scan_file($filepath, $filename, true);
|
||||
|
||||
// Check the final size of file against the user upload limits.
|
||||
$localsize = filesize(sprintf('%s/%s', $filepath, $filename));
|
||||
if ($this->size_exceeds_upload_limit($localsize)) {
|
||||
throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $localsize,
|
||||
'uploadlimit' => $this->useruploadlimit]);
|
||||
}
|
||||
|
||||
return $this->create_user_draft_stored_file($filename, $filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the size exceed the upload limit for the current import, taking into account user and core settings.
|
||||
*
|
||||
* @param int $sizeinbytes
|
||||
* @return bool true if exceeded, false otherwise.
|
||||
*/
|
||||
protected function size_exceeds_upload_limit(int $sizeinbytes): bool {
|
||||
$maxbytes = 0;
|
||||
if ($this->context->contextlevel == CONTEXT_COURSE) {
|
||||
$course = get_course($this->context->instanceid);
|
||||
$maxbytes = $course->maxbytes;
|
||||
}
|
||||
$maxbytes = get_user_max_upload_file_size($this->context, get_config('core', 'maxbytes'), $maxbytes, 0,
|
||||
$this->user);
|
||||
if ($maxbytes != USER_CAN_IGNORE_FILE_SIZE_LIMITS && $sizeinbytes > $maxbytes) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file in the user drafts ready for use by plugins implementing dndupload_handle().
|
||||
*
|
||||
* @param string $filename the name of the file on disk
|
||||
* @param string $path the path where the file is stored on disk
|
||||
* @return \stored_file
|
||||
*/
|
||||
protected function create_user_draft_stored_file(string $filename, string $path): \stored_file {
|
||||
global $CFG;
|
||||
|
||||
$record = new \stdClass();
|
||||
$record->filearea = 'draft';
|
||||
$record->component = 'user';
|
||||
$record->filepath = '/';
|
||||
$record->itemid = file_get_unused_draft_itemid();
|
||||
$record->license = $CFG->sitedefaultlicense;
|
||||
$record->author = '';
|
||||
$record->filename = clean_param($filename, PARAM_FILE);
|
||||
$record->contextid = \context_user::instance($this->user->id)->id;
|
||||
$record->userid = $this->user->id;
|
||||
|
||||
$fullpathwithname = sprintf('%s/%s', $path, $filename);
|
||||
|
||||
$fs = get_file_storage();
|
||||
|
||||
return $fs->create_file_from_pathname($record, $fullpathwithname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for a context that this user has permission to upload backup files to.
|
||||
* This gets a list of roles that the user has, checks for the restore:uploadfile capability and then sends back a context
|
||||
* that has this permission if available.
|
||||
*
|
||||
* This starts with the highest context level and moves down i.e. system -> category -> course.
|
||||
*
|
||||
* @param int $userid The user ID that we are looking for a working context for.
|
||||
* @return \context A context that allows the upload of backup files.
|
||||
*/
|
||||
public static function get_context_for_user(int $userid): ?\context {
|
||||
global $DB;
|
||||
|
||||
if (is_siteadmin()) {
|
||||
return \context_system::instance();
|
||||
}
|
||||
|
||||
$sql = "SELECT ctx.id, ctx.contextlevel, ctx.instanceid, ctx.path, ctx.depth, ctx.locked
|
||||
FROM {context} ctx
|
||||
JOIN {role_assignments} r ON ctx.id = r.contextid
|
||||
WHERE r.userid = :userid AND ctx.contextlevel IN (:contextsystem, :contextcategory, :contextcourse)
|
||||
ORDER BY ctx.contextlevel ASC";
|
||||
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'contextsystem' => CONTEXT_SYSTEM,
|
||||
'contextcategory' => CONTEXT_COURSECAT,
|
||||
'contextcourse' => CONTEXT_COURSE
|
||||
];
|
||||
$records = $DB->get_records_sql($sql, $params);
|
||||
foreach ($records as $record) {
|
||||
\context_helper::preload_from_record($record);
|
||||
if ($record->contextlevel == CONTEXT_COURSECAT) {
|
||||
$context = \context_coursecat::instance($record->instanceid);
|
||||
} else if ($record->contextlevel == CONTEXT_COURSE) {
|
||||
$context = \context_course::instance($record->instanceid);
|
||||
} else {
|
||||
$context = \context_system::instance();
|
||||
}
|
||||
if (has_capability('moodle/restore:uploadfile', $context, $userid)) {
|
||||
return $context;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
91
admin/tool/moodlenet/classes/local/import_handler_info.php
Normal file
91
admin/tool/moodlenet/classes/local/import_handler_info.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_handler_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The import_handler_info class.
|
||||
*
|
||||
* An import_handler_info object represent an resource import handler for a particular module.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_handler_info {
|
||||
|
||||
/** @var string $modulename the name of the module. */
|
||||
protected $modulename;
|
||||
|
||||
/** @var string $description the description. */
|
||||
protected $description;
|
||||
|
||||
/** @var import_strategy $importstrategy the strategy which will be used to import resources handled by this handler */
|
||||
protected $importstrategy;
|
||||
|
||||
/**
|
||||
* The import_handler_info constructor.
|
||||
*
|
||||
* @param string $modulename the name of the module handling the file extension. E.g. 'label'.
|
||||
* @param string $description A description of how the module handles files of this extension type.
|
||||
* @param import_strategy $strategy the strategy which will be used to import the resource.
|
||||
* @throws \coding_exception
|
||||
*/
|
||||
public function __construct(string $modulename, string $description, import_strategy $strategy) {
|
||||
if (empty($modulename)) {
|
||||
throw new \coding_exception("Module name cannot be empty.");
|
||||
}
|
||||
if (empty($description)) {
|
||||
throw new \coding_exception("Description cannot be empty.");
|
||||
}
|
||||
$this->modulename = $modulename;
|
||||
$this->description = $description;
|
||||
$this->importstrategy = $strategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the module.
|
||||
*
|
||||
* @return string the module name, e.g. 'label'.
|
||||
*/
|
||||
public function get_module_name(): string {
|
||||
return $this->modulename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a human readable, localised description of how the file is handled by the module.
|
||||
*
|
||||
* @return string the localised description.
|
||||
*/
|
||||
public function get_description(): string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import strategy used by this handler.
|
||||
*
|
||||
* @return import_strategy the import strategy object.
|
||||
*/
|
||||
public function get_strategy(): import_strategy {
|
||||
return $this->importstrategy;
|
||||
}
|
||||
}
|
188
admin/tool/moodlenet/classes/local/import_handler_registry.php
Normal file
188
admin/tool/moodlenet/classes/local/import_handler_registry.php
Normal file
@ -0,0 +1,188 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_handler_registry class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The import_handler_registry class.
|
||||
*
|
||||
* The import_handler_registry objects represent a register of modules handling various file extensions for a given course and user.
|
||||
* Only modules which are available to the user in the course are included in the register for that user.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_handler_registry {
|
||||
|
||||
/**
|
||||
* @var array array containing the names and messages of all modules handling import of resources as a 'file' type.
|
||||
*/
|
||||
protected $filehandlers = [];
|
||||
|
||||
/**
|
||||
* @var array $typehandlers the array of modules registering as handlers of other, non-file types, indexed by typename.
|
||||
*/
|
||||
protected $typehandlers = [];
|
||||
|
||||
/**
|
||||
* @var array $registry the aggregate of all registrations made by plugins, indexed by 'file' and 'type'.
|
||||
*/
|
||||
protected $registry = [];
|
||||
|
||||
/**
|
||||
* @var \context_course the course context object.
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* @var \stdClass a course object.
|
||||
*/
|
||||
protected $course;
|
||||
|
||||
/**
|
||||
* @var \stdClass a user object.
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* The import_handler_registry constructor.
|
||||
*
|
||||
* @param \stdClass $course the course, which impacts available handlers.
|
||||
* @param \stdClass $user the user, which impacts available handlers.
|
||||
*/
|
||||
public function __construct(\stdClass $course, \stdClass $user) {
|
||||
$this->course = $course;
|
||||
$this->user = $user;
|
||||
$this->context = \context_course::instance($course->id);
|
||||
|
||||
// Generate the full list of handlers for all extensions for this user and course.
|
||||
$this->populate_handlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all handlers for the remote resource, depending on the strategy being used to import the resource.
|
||||
*
|
||||
* @param remote_resource $resource the remote resource.
|
||||
* @param import_strategy $strategy an import_strategy instance.
|
||||
* @return import_handler_info[] the array of import_handler_info handlers.
|
||||
*/
|
||||
public function get_resource_handlers_for_strategy(remote_resource $resource, import_strategy $strategy): array {
|
||||
return $strategy->get_handlers($this->registry, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific handler for the resource, belonging to a specific module and for a specific strategy.
|
||||
*
|
||||
* @param remote_resource $resource the remote resource.
|
||||
* @param string $modname the name of the module, e.g. 'label'.
|
||||
* @param import_strategy $strategy a string representing how to treat the resource. e.g. 'file', 'link'.
|
||||
* @return import_handler_info|null the import_handler_info object, if found, otherwise null.
|
||||
*/
|
||||
public function get_resource_handler_for_mod_and_strategy(remote_resource $resource, string $modname,
|
||||
import_strategy $strategy): ?import_handler_info {
|
||||
foreach ($strategy->get_handlers($this->registry, $resource) as $handler) {
|
||||
if ($handler->get_module_name() === $modname) {
|
||||
return $handler;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up a list of extension handlers by leveraging the dndupload_register callbacks.
|
||||
*/
|
||||
protected function populate_handlers() {
|
||||
// Generate a dndupload_handler object, just so we can call ->is_known_type() on the types being registered by plugins.
|
||||
// We must vet each type which is reported to be handled against the list of known, supported types.
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/course/dnduploadlib.php');
|
||||
$dndhandlers = new \dndupload_handler($this->course);
|
||||
|
||||
// Get the list of mods enabled at site level first. We need to cross check this.
|
||||
$pluginman = \core_plugin_manager::instance();
|
||||
$sitemods = $pluginman->get_plugins_of_type('mod');
|
||||
$sitedisabledmods = array_filter($sitemods, function(\core\plugininfo\mod $modplugininfo){
|
||||
return !$modplugininfo->is_enabled();
|
||||
});
|
||||
$sitedisabledmods = array_map(function($modplugininfo) {
|
||||
return $modplugininfo->name;
|
||||
}, $sitedisabledmods);
|
||||
|
||||
// Loop through all modules to find the registered handlers.
|
||||
$mods = get_plugin_list_with_function('mod', 'dndupload_register');
|
||||
foreach ($mods as $component => $funcname) {
|
||||
list($modtype, $modname) = \core_component::normalize_component($component);
|
||||
if (!empty($sitedisabledmods) && array_key_exists($modname, $sitedisabledmods)) {
|
||||
continue; // Module is disabled at the site level.
|
||||
}
|
||||
if (!course_allowed_module($this->course, $modname, $this->user)) {
|
||||
continue; // User does not have permission to add this module to the course.
|
||||
}
|
||||
|
||||
if (!$resp = component_callback($component, 'dndupload_register')) {
|
||||
continue;
|
||||
};
|
||||
|
||||
if (isset($resp['files'])) {
|
||||
foreach ($resp['files'] as $file) {
|
||||
$this->register_file_handler($file['extension'], $modname, $file['message']);
|
||||
}
|
||||
}
|
||||
if (isset($resp['types'])) {
|
||||
foreach ($resp['types'] as $type) {
|
||||
if (!$dndhandlers->is_known_type($type['identifier'])) {
|
||||
throw new \coding_exception("Trying to add handler for unknown type $type");
|
||||
}
|
||||
$this->register_type_handler($type['identifier'], $modname, $type['message']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->registry = [
|
||||
'files' => $this->filehandlers,
|
||||
'types' => $this->typehandlers
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a type handler to the list.
|
||||
*
|
||||
* @param string $identifier the name of the type.
|
||||
* @param string $module the name of the module, e.g. 'label'.
|
||||
* @param string $message the message describing how the module handles the type.
|
||||
*/
|
||||
protected function register_type_handler(string $identifier, string $module, string $message) {
|
||||
$this->typehandlers[$identifier][] = ['module' => $module, 'message' => $message];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file extension handler to the list.
|
||||
*
|
||||
* @param string $extension the extension, e.g. 'png'.
|
||||
* @param string $module the name of the module handling this extension
|
||||
* @param string $message the message describing how the module handles the extension.
|
||||
*/
|
||||
protected function register_file_handler(string $extension, string $module, string $message) {
|
||||
$extension = strtolower($extension);
|
||||
$this->filehandlers[$extension][] = ['module' => $module, 'message' => $message];
|
||||
}
|
||||
}
|
||||
|
126
admin/tool/moodlenet/classes/local/import_info.php
Normal file
126
admin/tool/moodlenet/classes/local/import_info.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* Class import_info, describing objects which represent a resource being imported by a user.
|
||||
*
|
||||
* Objects of this class encapsulate both:
|
||||
* - information about the resource (remote_resource).
|
||||
* - config data pertaining to the import process, such as the destination course and section
|
||||
* and how the resource should be treated (i.e. the type and the name of the module selected as the import handler)
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_info {
|
||||
|
||||
/** @var int $userid the user conducting this import. */
|
||||
protected $userid;
|
||||
|
||||
/** @var remote_resource $resource the resource being imported. */
|
||||
protected $resource;
|
||||
|
||||
/** @var \stdClass $config config data pertaining to the import process, e.g. course, section, type. */
|
||||
protected $config;
|
||||
|
||||
/** @var string $id string identifier for this object. */
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The import_controller constructor.
|
||||
*
|
||||
* @param int $userid the id of the user performing the import.
|
||||
* @param remote_resource $resource the resource being imported.
|
||||
* @param \stdClass $config import config like 'course', 'section', 'type'.
|
||||
*/
|
||||
public function __construct(int $userid, remote_resource $resource, \stdClass $config) {
|
||||
$this->userid = $userid;
|
||||
$this->resource = $resource;
|
||||
$this->config = $config;
|
||||
$this->id = md5($resource->get_url()->get_value());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of this object.
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remote resource being imported.
|
||||
*
|
||||
* @return remote_resource the remote resource being imported.
|
||||
*/
|
||||
public function get_resource(): remote_resource {
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration data pertaining to the import.
|
||||
*
|
||||
* @return \stdClass the import configuration data.
|
||||
*/
|
||||
public function get_config(): \stdClass {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration data pertaining to the import.
|
||||
*
|
||||
* @param \stdClass $config the configuration data to set.
|
||||
*/
|
||||
public function set_config(\stdClass $config): void {
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an import_info object by id.
|
||||
*
|
||||
* @param string $id the id of the import_info object to load.
|
||||
* @return mixed an import_info object if found, otherwise null.
|
||||
*/
|
||||
public static function load(string $id): ?import_info {
|
||||
// This currently lives in the session, so we don't need userid.
|
||||
// It might be useful if we ever move to another storage mechanism however, where we would need it.
|
||||
global $SESSION;
|
||||
return isset($SESSION->moodlenetimports[$id]) ? unserialize($SESSION->moodlenetimports[$id]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save this object to a store which is accessible across requests.
|
||||
*/
|
||||
public function save(): void {
|
||||
global $SESSION;
|
||||
$SESSION->moodlenetimports[$this->id] = serialize($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all information about an import from the store.
|
||||
*/
|
||||
public function purge(): void {
|
||||
global $SESSION;
|
||||
unset($SESSION->moodlenetimports[$this->id]);
|
||||
}
|
||||
}
|
206
admin/tool/moodlenet/classes/local/import_processor.php
Normal file
206
admin/tool/moodlenet/classes/local/import_processor.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_processor class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The import_processor class.
|
||||
*
|
||||
* The import_processor objects provide a means to import a remote resource into a course section, delegating the handling of
|
||||
* content to the relevant module, via its dndupload_handler callback.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_processor {
|
||||
|
||||
/** @var object The course that we are uploading to */
|
||||
protected $course = null;
|
||||
|
||||
/** @var int The section number we are uploading to */
|
||||
protected $section = null;
|
||||
|
||||
/** @var import_handler_registry $handlerregistry registry object to use for cross checking the supplied handler.*/
|
||||
protected $handlerregistry;
|
||||
|
||||
/** @var import_handler_info $handlerinfo information about the module handling the import.*/
|
||||
protected $handlerinfo;
|
||||
|
||||
/** @var \stdClass $user the user conducting the import.*/
|
||||
protected $user;
|
||||
|
||||
/** @var remote_resource $remoteresource the remote resource being imported.*/
|
||||
protected $remoteresource;
|
||||
|
||||
/** @var string[] $descriptionoverrides list of modules which support having their descriptions updated, post-import. */
|
||||
protected $descriptionoverrides = ['folder', 'page', 'resource', 'scorm', 'url'];
|
||||
|
||||
/**
|
||||
* The import_processor constructor.
|
||||
*
|
||||
* @param \stdClass $course the course object.
|
||||
* @param int $section the section number in the course, starting at 0.
|
||||
* @param remote_resource $remoteresource the remote resource to import.
|
||||
* @param import_handler_info $handlerinfo information about which module is handling the import.
|
||||
* @param import_handler_registry $handlerregistry A registry of import handlers, to use for validation.
|
||||
* @throws \coding_exception If any of the params are invalid.
|
||||
*/
|
||||
public function __construct(\stdClass $course, int $section, remote_resource $remoteresource, import_handler_info $handlerinfo,
|
||||
import_handler_registry $handlerregistry) {
|
||||
|
||||
global $DB, $USER;
|
||||
|
||||
if ($section < 0) {
|
||||
throw new \coding_exception("Invalid section number $section. Must be > 0.");
|
||||
}
|
||||
if (!$DB->record_exists('modules', array('name' => $handlerinfo->get_module_name()))) {
|
||||
throw new \coding_exception("Module {$handlerinfo->get_module_name()} does not exist");
|
||||
}
|
||||
|
||||
$this->course = $course;
|
||||
$this->section = $section;
|
||||
$this->handlerregistry = $handlerregistry;
|
||||
$this->user = $USER;
|
||||
$this->remoteresource = $remoteresource;
|
||||
$this->handlerinfo = $handlerinfo;
|
||||
|
||||
// ALL handlers must have a strategy and ANY strategy can process ANY resource.
|
||||
// It is therefore NOT POSSIBLE to have a resource that CANNOT be processed by a handler.
|
||||
// So, there's no need to verify that the remote_resource CAN be handled by the handler. It always can.
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the import process, including file download, module creation and cleanup (cache purge, etc).
|
||||
*/
|
||||
public function process(): void {
|
||||
// Allow the strategy to do setup for this file import.
|
||||
$moduledata = $this->handlerinfo->get_strategy()->import($this->remoteresource, $this->user, $this->course, $this->section);
|
||||
|
||||
// Create the course module, and add that information to the data to be sent to the plugin handling the resource.
|
||||
$cmdata = $this->create_course_module($this->course, $this->section, $this->handlerinfo->get_module_name());
|
||||
$moduledata->coursemodule = $cmdata->id;
|
||||
|
||||
// Now, send the data to the handling plugin to let it set up.
|
||||
$instanceid = plugin_callback('mod', $this->handlerinfo->get_module_name(), 'dndupload', 'handle', [$moduledata],
|
||||
'invalidfunction');
|
||||
if ($instanceid == 'invalidfunction') {
|
||||
$name = $this->handlerinfo->get_module_name();
|
||||
throw new \coding_exception("$name does not support drag and drop upload (missing {$name}_dndupload_handle function)");
|
||||
}
|
||||
|
||||
// Now, update the module description if the module supports it and only if it's not currently set.
|
||||
$this->update_module_description($instanceid);
|
||||
|
||||
// Finish setting up the course module.
|
||||
$this->finish_setup_course_module($instanceid, $cmdata->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the module's description (intro), if that feature is supported.
|
||||
*
|
||||
* @param int $instanceid the instance id of the module to update.
|
||||
*/
|
||||
protected function update_module_description(int $instanceid): void {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->libdir . '/moodlelib.php');
|
||||
|
||||
if (plugin_supports('mod', $this->handlerinfo->get_module_name(), FEATURE_MOD_INTRO, true)) {
|
||||
require_once($CFG->libdir . '/editorlib.php');
|
||||
require_once($CFG->libdir . '/modinfolib.php');
|
||||
|
||||
$rec = $DB->get_record($this->handlerinfo->get_module_name(), ['id' => $instanceid]);
|
||||
|
||||
if (empty($rec->intro) || in_array($this->handlerinfo->get_module_name(), $this->descriptionoverrides)) {
|
||||
$updatedata = (object)[
|
||||
'id' => $instanceid,
|
||||
'intro' => clean_param($this->remoteresource->get_description(), PARAM_TEXT),
|
||||
'introformat' => editors_get_preferred_format()
|
||||
];
|
||||
|
||||
$DB->update_record($this->handlerinfo->get_module_name(), $updatedata);
|
||||
|
||||
rebuild_course_cache($this->course->id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the course module to hold the file/content that has been uploaded.
|
||||
* @param \stdClass $course the course object.
|
||||
* @param int $section the section.
|
||||
* @param string $modname the name of the module, e.g. 'label'.
|
||||
* @return \stdClass the course module data.
|
||||
*/
|
||||
protected function create_course_module(\stdClass $course, int $section, string $modname): \stdClass {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/course/modlib.php');
|
||||
list($module, $context, $cw, $cm, $data) = prepare_new_moduleinfo_data($course, $modname, $section);
|
||||
$data->visible = false; // The module is created in a hidden state.
|
||||
$data->coursemodule = $data->id = add_course_module($data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish off any course module setup, such as adding to the course section and firing events.
|
||||
*
|
||||
* @param int $instanceid id returned by the mod when it was created.
|
||||
* @param int $cmid the course module record id, for removal if something went wrong.
|
||||
*/
|
||||
protected function finish_setup_course_module($instanceid, int $cmid): void {
|
||||
global $DB;
|
||||
|
||||
if (!$instanceid) {
|
||||
// Something has gone wrong - undo everything we can.
|
||||
course_delete_module($cmid);
|
||||
throw new \moodle_exception('errorcreatingactivity', 'moodle', '', $this->handlerinfo->get_module_name());
|
||||
}
|
||||
|
||||
// Note the section visibility.
|
||||
$visible = get_fast_modinfo($this->course)->get_section_info($this->section)->visible;
|
||||
|
||||
$DB->set_field('course_modules', 'instance', $instanceid, array('id' => $cmid));
|
||||
|
||||
// Rebuild the course cache after update action.
|
||||
rebuild_course_cache($this->course->id, true);
|
||||
|
||||
course_add_cm_to_section($this->course, $cmid, $this->section);
|
||||
|
||||
set_coursemodule_visible($cmid, $visible);
|
||||
if (!$visible) {
|
||||
$DB->set_field('course_modules', 'visibleold', 1, array('id' => $cmid));
|
||||
}
|
||||
|
||||
// Retrieve the final info about this module.
|
||||
$info = get_fast_modinfo($this->course, $this->user->id);
|
||||
if (!isset($info->cms[$cmid])) {
|
||||
// The course module has not been properly created in the course - undo everything.
|
||||
course_delete_module($cmid);
|
||||
throw new \moodle_exception('errorcreatingactivity', 'moodle', '', $this->handlerinfo->get_module_name());
|
||||
}
|
||||
$mod = $info->get_cm($cmid);
|
||||
|
||||
// Trigger course module created event.
|
||||
$event = \core\event\course_module_created::create_from_cm($mod);
|
||||
$event->trigger();
|
||||
}
|
||||
}
|
||||
|
69
admin/tool/moodlenet/classes/local/import_strategy.php
Normal file
69
admin/tool/moodlenet/classes/local/import_strategy.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_strategy interface.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The import_strategy interface.
|
||||
*
|
||||
* This provides a contract allowing different import strategies to be implemented.
|
||||
*
|
||||
* An import_strategy encapsulates the logic used to prepare a remote_resource for import into Moodle in some way and is used by the
|
||||
* import_processor (to perform aforementioned preparations) before it hands control of the import over to a course module plugin.
|
||||
*
|
||||
* We may wish to have many strategies because the preparation steps may vary depending on how the resource is to be treated.
|
||||
* E.g. We may wish to import as a file in which case download steps will be required, or we may simply wish to import the remote
|
||||
* resource as a link, in which cases setup steps will not require any file download.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface import_strategy {
|
||||
|
||||
/**
|
||||
* Get an array of import_handler_info objects supported by this import strategy, based on the registrydata and resource.
|
||||
*
|
||||
* Implementations should check the registry data for any entries which align with their import strategy and should create
|
||||
* import_handler_info objects to represent each relevant entry. If an entry represents a module, or handling type which does
|
||||
* not align with the strategy, that item should simply be skipped.
|
||||
*
|
||||
* E.g. If one strategy aims to import all remote resources as files (e.g. import_strategy_file), it would only generate a list
|
||||
* of import_handler_info objects created from those registry entries of type 'file', as those entries represent the modules
|
||||
* which have said they can handle resources as files.
|
||||
*
|
||||
* @param array $registrydata The fully populated handler registry.
|
||||
* @param remote_resource $resource the remote resource.
|
||||
* @return import_handler_info[] the array of import_handler_info objects, or an empty array if none were matched.
|
||||
*/
|
||||
public function get_handlers(array $registrydata, remote_resource $resource): array;
|
||||
|
||||
/**
|
||||
* Called during import to perform required import setup steps.
|
||||
*
|
||||
* @param remote_resource $resource the resource to import.
|
||||
* @param \stdClass $user the user to import on behalf of.
|
||||
* @param \stdClass $course the course into which the remote resource is being imported.
|
||||
* @param int $section the section into which the remote resource is being imported.
|
||||
* @return \stdClass the module data which will be passed on to the course module plugin.
|
||||
*/
|
||||
public function import(remote_resource $resource, \stdClass $user, \stdClass $course, int $section): \stdClass;
|
||||
}
|
170
admin/tool/moodlenet/classes/local/import_strategy_file.php
Normal file
170
admin/tool/moodlenet/classes/local/import_strategy_file.php
Normal file
@ -0,0 +1,170 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_strategy_file class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use core\antivirus\manager as avmanager;
|
||||
|
||||
/**
|
||||
* The import_strategy_file class.
|
||||
*
|
||||
* The import_strategy_file objects contains the setup steps needed to prepare a resource for import as a file into Moodle. This
|
||||
* ensures the remote_resource is first downloaded and put in a draft file area, ready for use as a file by the handling module.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_strategy_file implements import_strategy {
|
||||
|
||||
/**
|
||||
* Get an array of import_handler_info objects representing modules supporting import of this file type.
|
||||
*
|
||||
* @param array $registrydata the fully populated registry.
|
||||
* @param remote_resource $resource the remote resource.
|
||||
* @return import_handler_info[] the array of import_handler_info objects.
|
||||
*/
|
||||
public function get_handlers(array $registrydata, remote_resource $resource): array {
|
||||
$handlers = [];
|
||||
foreach ($registrydata['files'] as $index => $items) {
|
||||
foreach ($items as $item) {
|
||||
if ($index === $resource->get_extension() || $index === '*') {
|
||||
$handlers[] = new import_handler_info($item['module'], $item['message'], $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the remote resource according to the rules of this strategy.
|
||||
*
|
||||
* @param remote_resource $resource the resource to import.
|
||||
* @param \stdClass $user the user to import on behalf of.
|
||||
* @param \stdClass $course the course into which the remote_resource is being imported.
|
||||
* @param int $section the section into which the remote_resource is being imported.
|
||||
* @return \stdClass the module data.
|
||||
* @throws \moodle_exception if the file size means the upload limit is exceeded for the user.
|
||||
*/
|
||||
public function import(remote_resource $resource, \stdClass $user, \stdClass $course, int $section): \stdClass {
|
||||
// Before starting a potentially lengthy download, try to ensure the file size does not exceed the upload size restrictions
|
||||
// for the user. This is a time saving measure.
|
||||
// This is a naive check, that serves only to catch files if they provide the content length header.
|
||||
// Because of potential content encoding (compression), the stored file will be checked again after download as well.
|
||||
$size = $resource->get_download_size() ?? -1;
|
||||
$useruploadlimit = $this->get_user_upload_limit($user, $course);
|
||||
if ($this->size_exceeds_upload_limit($size, $useruploadlimit)) {
|
||||
throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $size,
|
||||
'uploadlimit' => $useruploadlimit]);
|
||||
}
|
||||
|
||||
// Download the file into a request directory and scan it.
|
||||
[$filepath, $filename] = $resource->download_to_requestdir();
|
||||
avmanager::scan_file($filepath, $filename, true);
|
||||
|
||||
// Check the final size of file against the user upload limits.
|
||||
$localsize = filesize(sprintf('%s/%s', $filepath, $filename));
|
||||
if ($this->size_exceeds_upload_limit($localsize, $useruploadlimit)) {
|
||||
throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $localsize,
|
||||
'uploadlimit' => $useruploadlimit]);
|
||||
}
|
||||
|
||||
// Store in the user draft file area.
|
||||
$storedfile = $this->create_user_draft_stored_file($user, $filename, $filepath);
|
||||
|
||||
// Prepare the data to be sent to the modules dndupload_handle hook.
|
||||
return $this->prepare_module_data($course, $resource, $storedfile->get_itemid());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the data to pass to the dndupload_handle() hooks.
|
||||
*
|
||||
* @param \stdClass $course the course record.
|
||||
* @param remote_resource $resource the resource being imported as a file.
|
||||
* @param int $draftitemid the itemid of the draft file.
|
||||
* @return \stdClass the data object.
|
||||
*/
|
||||
protected function prepare_module_data(\stdClass $course, remote_resource $resource, int $draftitemid): \stdClass {
|
||||
$data = new \stdClass();
|
||||
$data->type = 'Files';
|
||||
$data->course = $course;
|
||||
$data->draftitemid = $draftitemid;
|
||||
$data->displayname = $resource->get_name();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max file size limit for the user in the course.
|
||||
*
|
||||
* @param \stdClass $user the user to check.
|
||||
* @param \stdClass $course the course to check in.
|
||||
* @return int the file size limit, in bytes.
|
||||
*/
|
||||
protected function get_user_upload_limit(\stdClass $user, \stdClass $course): int {
|
||||
return get_user_max_upload_file_size(\context_course::instance($course->id), get_config('core', 'maxbytes'),
|
||||
$course->maxbytes, 0, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the size exceed the upload limit for the current import, taking into account user and core settings.
|
||||
*
|
||||
* @param int $sizeinbytes the size, in bytes.
|
||||
* @param int $useruploadlimit the upload limit, in bytes.
|
||||
* @return bool true if exceeded, false otherwise.
|
||||
* @throws \dml_exception
|
||||
*/
|
||||
protected function size_exceeds_upload_limit(int $sizeinbytes, int $useruploadlimit): bool {
|
||||
if ($useruploadlimit != USER_CAN_IGNORE_FILE_SIZE_LIMITS && $sizeinbytes > $useruploadlimit) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file in the user drafts ready for use by plugins implementing dndupload_handle().
|
||||
*
|
||||
* @param \stdClass $user the user object.
|
||||
* @param string $filename the name of the file on disk
|
||||
* @param string $path the path where the file is stored on disk
|
||||
* @return \stored_file
|
||||
*/
|
||||
protected function create_user_draft_stored_file(\stdClass $user, string $filename, string $path): \stored_file {
|
||||
global $CFG;
|
||||
|
||||
$record = new \stdClass();
|
||||
$record->filearea = 'draft';
|
||||
$record->component = 'user';
|
||||
$record->filepath = '/';
|
||||
$record->itemid = file_get_unused_draft_itemid();
|
||||
$record->license = $CFG->sitedefaultlicense;
|
||||
$record->author = '';
|
||||
$record->filename = clean_param($filename, PARAM_FILE);
|
||||
$record->contextid = \context_user::instance($user->id)->id;
|
||||
$record->userid = $user->id;
|
||||
|
||||
$fullpathwithname = sprintf('%s/%s', $path, $filename);
|
||||
|
||||
$fs = get_file_storage();
|
||||
|
||||
return $fs->create_file_from_pathname($record, $fullpathwithname);
|
||||
}
|
||||
}
|
71
admin/tool/moodlenet/classes/local/import_strategy_link.php
Normal file
71
admin/tool/moodlenet/classes/local/import_strategy_link.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the import_strategy_link class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The import_strategy_link class.
|
||||
*
|
||||
* The import_strategy_link objects contains the setup steps needed to prepare a resource for import as a URL into Moodle.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_strategy_link implements import_strategy {
|
||||
|
||||
/**
|
||||
* Get an array of import_handler_info objects representing modules supporting import of the resource.
|
||||
*
|
||||
* @param array $registrydata the fully populated registry.
|
||||
* @param remote_resource $resource the remote resource.
|
||||
* @return import_handler_info[] the array of import_handler_info objects.
|
||||
*/
|
||||
public function get_handlers(array $registrydata, remote_resource $resource): array {
|
||||
$handlers = [];
|
||||
foreach ($registrydata['types'] as $identifier => $items) {
|
||||
foreach ($items as $item) {
|
||||
if ($identifier === 'url') {
|
||||
$handlers[] = new import_handler_info($item['module'], $item['message'], $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the remote resource according to the rules of this strategy.
|
||||
*
|
||||
* @param remote_resource $resource the resource to import.
|
||||
* @param \stdClass $user the user to import on behalf of.
|
||||
* @param \stdClass $course the course into which the remote_resource is being imported.
|
||||
* @param int $section the section into which the remote_resource is being imported.
|
||||
* @return \stdClass the module data.
|
||||
*/
|
||||
public function import(remote_resource $resource, \stdClass $user, \stdClass $course, int $section): \stdClass {
|
||||
$data = new \stdClass();
|
||||
$data->type = 'url';
|
||||
$data->course = $course;
|
||||
$data->content = $resource->get_url()->get_value();
|
||||
$data->displayname = $resource->get_name();
|
||||
return $data;
|
||||
}
|
||||
}
|
169
admin/tool/moodlenet/classes/local/remote_resource.php
Normal file
169
admin/tool/moodlenet/classes/local/remote_resource.php
Normal file
@ -0,0 +1,169 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Contains the remote_resource class definition.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The remote_resource class.
|
||||
*
|
||||
* Objects of type remote_resource provide a means of interacting with resources over HTTP.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class remote_resource {
|
||||
|
||||
/** @var \curl $curl the curl http helper.*/
|
||||
protected $curl;
|
||||
|
||||
/** @var url $url the url to the remote resource.*/
|
||||
protected $url;
|
||||
|
||||
/** @var string $filename the name of this remote file.*/
|
||||
protected $filename;
|
||||
|
||||
/** @var string $extension the file extension of this remote file.*/
|
||||
protected $extension;
|
||||
|
||||
/** @var array $headinfo the array of information for the most recent HEAD request.*/
|
||||
protected $headinfo = [];
|
||||
|
||||
/** @var \stdClass $metadata information about the resource. */
|
||||
protected $metadata;
|
||||
|
||||
/**
|
||||
* The remote_resource constructor.
|
||||
*
|
||||
* @param \curl $curl a curl object for HTTP requests.
|
||||
* @param url $url the URL of the remote resource.
|
||||
* @param \stdClass $metadata resource metadata such as name, summary, license, etc.
|
||||
*/
|
||||
public function __construct(\curl $curl, url $url, \stdClass $metadata) {
|
||||
$this->curl = $curl;
|
||||
$this->url = $url;
|
||||
$this->filename = pathinfo($this->url->get_path(), PATHINFO_FILENAME);
|
||||
$this->extension = pathinfo($this->url->get_path(), PATHINFO_EXTENSION);
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL for this remote resource.
|
||||
*
|
||||
* @return url the url object.
|
||||
*/
|
||||
public function get_url(): url {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the file as taken from the metadata.
|
||||
*/
|
||||
public function get_name(): string {
|
||||
return $this->metadata->name ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource metadata.
|
||||
*
|
||||
* @return \stdClass the metadata.
|
||||
*/
|
||||
public function get_metadata(): \stdClass {
|
||||
return$this->metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of the resource as taken from the metadata.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description(): string {
|
||||
return $this->metadata->description ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the extension of the file, if found.
|
||||
*
|
||||
* @return string the extension of the file, if found.
|
||||
*/
|
||||
public function get_extension(): string {
|
||||
return $this->extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file size of the remote file, in bytes, or null if it cannot be determined.
|
||||
*
|
||||
* @return int|null the content length, if able to be determined, otherwise null.
|
||||
*/
|
||||
public function get_download_size(): ?int {
|
||||
$this->get_resource_info();
|
||||
return $this->headinfo['download_content_length'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the remote resource to a local requestdir, returning the path and name of the resulting file.
|
||||
*
|
||||
* @return array an array containing filepath adn filename, e.g. [filepath, filename].
|
||||
* @throws \moodle_exception if the file cannot be downloaded.
|
||||
*/
|
||||
public function download_to_requestdir(): array {
|
||||
$filename = sprintf('%s.%s', $this->filename, $this->get_extension());
|
||||
$path = make_request_directory();
|
||||
$fullpathwithname = sprintf('%s/%s', $path, $filename);
|
||||
|
||||
// In future, use a timeout (download and/or connection) controlled by a tool_moodlenet setting.
|
||||
$downloadtimeout = 30;
|
||||
|
||||
$result = $this->curl->download_one($this->url->get_value(), null, ['filepath' => $fullpathwithname,
|
||||
'timeout' => $downloadtimeout]);
|
||||
if ($result !== true) {
|
||||
throw new \moodle_exception('errorduringdownload', 'tool_moodlenet', '', $result);
|
||||
}
|
||||
|
||||
return [$path, $filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches information about the remote resource via a HEAD request.
|
||||
*
|
||||
* @throws \coding_exception if any connection problems occur.
|
||||
*/
|
||||
protected function get_resource_info() {
|
||||
if (!empty($this->headinfo)) {
|
||||
return;
|
||||
}
|
||||
$options['CURLOPT_RETURNTRANSFER'] = 1;
|
||||
$options['CURLOPT_FOLLOWLOCATION'] = 1;
|
||||
$options['CURLOPT_MAXREDIRS'] = 5;
|
||||
$options['CURLOPT_FAILONERROR'] = 1; // We want to consider http error codes as errors to report, not just status codes.
|
||||
|
||||
$this->curl->head($this->url->get_value(), $options);
|
||||
$errorno = $this->curl->get_errno();
|
||||
$this->curl->resetopt();
|
||||
|
||||
if ($errorno !== 0) {
|
||||
$message = 'Problem during HEAD request for remote resource \''.$this->url->get_value().'\'. Curl Errno: ' . $errorno;
|
||||
throw new \coding_exception($message);
|
||||
}
|
||||
$this->headinfo = $this->curl->get_info();
|
||||
}
|
||||
|
||||
}
|
84
admin/tool/moodlenet/classes/local/url.php
Normal file
84
admin/tool/moodlenet/classes/local/url.php
Normal file
@ -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/>.
|
||||
/**
|
||||
* Contains the url class, providing a representation of a url and operations on its component parts.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
/**
|
||||
* The url class, providing a representation of a url and operations on its component parts.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class url {
|
||||
|
||||
/** @var string $url the full URL string.*/
|
||||
protected $url;
|
||||
|
||||
/** @var string|null $path the path component of this URL.*/
|
||||
protected $path;
|
||||
|
||||
/** @var host|null $host the host component of this URL.*/
|
||||
protected $host;
|
||||
|
||||
/**
|
||||
* The url constructor.
|
||||
*
|
||||
* @param string $url the URL string.
|
||||
* @throws \coding_exception if the URL does not pass syntax validation.
|
||||
*/
|
||||
public function __construct(string $url) {
|
||||
// This object supports URLs as per the spec, so non-ascii chars must be encoded as per IDNA rules.
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
throw new \coding_exception('Malformed URL');
|
||||
}
|
||||
$this->url = $url;
|
||||
$this->path = parse_url($url, PHP_URL_PATH);
|
||||
$this->host = parse_url($url, PHP_URL_HOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path component of the URL.
|
||||
*
|
||||
* @return string|null the path component of the URL.
|
||||
*/
|
||||
public function get_path(): ?string {
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the domain component of the URL.
|
||||
*
|
||||
* @return string|null the domain component of the URL.
|
||||
*/
|
||||
public function get_host(): ?string {
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full URL string.
|
||||
*
|
||||
* @return string the full URL string.
|
||||
*/
|
||||
public function get_value() {
|
||||
return $this->url;
|
||||
}
|
||||
}
|
107
admin/tool/moodlenet/classes/moodlenet_user_profile.php
Normal file
107
admin/tool/moodlenet/classes/moodlenet_user_profile.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Moodle net user profile class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_moodlenet;
|
||||
|
||||
/**
|
||||
* A class to represent the moodlenet profile.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class moodlenet_user_profile {
|
||||
|
||||
/** @var string $profile The full profile name. */
|
||||
protected $profile;
|
||||
|
||||
/** @var int $userid The user ID that this profile belongs to. */
|
||||
protected $userid;
|
||||
|
||||
/** @var string $username The username from $userprofile */
|
||||
protected $username;
|
||||
|
||||
/** @var string $domain The domain from $domain */
|
||||
protected $domain;
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
*
|
||||
* @param string $userprofile The moodle net user profile string.
|
||||
* @param int $userid The user ID that this profile belongs to.
|
||||
*/
|
||||
public function __construct(string $userprofile, int $userid) {
|
||||
$this->profile = $userprofile;
|
||||
$this->userid = $userid;
|
||||
|
||||
$explodedprofile = explode('@', $this->profile);
|
||||
if (count($explodedprofile) === 2) {
|
||||
// It'll either be an email or WebFinger entry.
|
||||
$this->username = $explodedprofile[0];
|
||||
$this->domain = $explodedprofile[1];
|
||||
} else if (count($explodedprofile) === 3) {
|
||||
// We may have a profile link as MoodleNet gives to the user.
|
||||
$this->username = $explodedprofile[1];
|
||||
$this->domain = $explodedprofile[2];
|
||||
} else {
|
||||
throw new \moodle_exception('invalidmoodlenetprofile', 'tool_moodlenet');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full moodle net profile.
|
||||
*
|
||||
* @return string The moodle net profile.
|
||||
*/
|
||||
public function get_profile_name(): string {
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user ID that this profile belongs to.
|
||||
*
|
||||
* @return int The user ID.
|
||||
*/
|
||||
public function get_userid(): int {
|
||||
return $this->userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the username for this profile.
|
||||
*
|
||||
* @return string The username.
|
||||
*/
|
||||
public function get_username(): string {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the domain for this profile.
|
||||
*
|
||||
* @return string The domain.
|
||||
*/
|
||||
public function get_domain(): string {
|
||||
return $this->domain;
|
||||
}
|
||||
}
|
52
admin/tool/moodlenet/classes/output/renderer.php
Normal file
52
admin/tool/moodlenet/classes/output/renderer.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Renderer.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_moodlenet\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use plugin_renderer_base;
|
||||
|
||||
/**
|
||||
* Renderer class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class renderer extends plugin_renderer_base {
|
||||
|
||||
/**
|
||||
* Defer to template.
|
||||
*
|
||||
* @param select_page $selectpage
|
||||
* @return string HTML
|
||||
*/
|
||||
protected function render_select_page(select_page $selectpage): string {
|
||||
|
||||
$this->page->requires->js_call_amd('tool_moodlenet/select_page', 'init', [$selectpage->get_import_info()->get_id()]);
|
||||
$data = $selectpage->export_for_template($this);
|
||||
return parent::render_from_template('tool_moodlenet/select_page', $data);
|
||||
}
|
||||
}
|
76
admin/tool/moodlenet/classes/output/select_page.php
Normal file
76
admin/tool/moodlenet/classes/output/select_page.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Select page renderable.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_moodlenet\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
use tool_moodlenet\local\import_info;
|
||||
|
||||
/**
|
||||
* Select page renderable.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class select_page implements \renderable, \templatable {
|
||||
|
||||
/** @var import_info $importinfo resource and config information pertaining to an import. */
|
||||
protected $importinfo;
|
||||
|
||||
/**
|
||||
* Inits the Select page renderable.
|
||||
*
|
||||
* @param import_info $importinfo resource and config information pertaining to an import.
|
||||
*/
|
||||
public function __construct(import_info $importinfo) {
|
||||
$this->importinfo = $importinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the import info.
|
||||
*
|
||||
* @return import_info the import information.
|
||||
*/
|
||||
public function get_import_info(): import_info {
|
||||
return $this->importinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the data.
|
||||
*
|
||||
* @param \renderer_base $output
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output): \stdClass {
|
||||
|
||||
// Prepare the context object.
|
||||
return (object) [
|
||||
'name' => $this->importinfo->get_resource()->get_name(),
|
||||
'type' => $this->importinfo->get_config()->type,
|
||||
'cancellink' => new \moodle_url('/my'),
|
||||
];
|
||||
}
|
||||
}
|
44
admin/tool/moodlenet/classes/privacy/provider.php
Normal file
44
admin/tool/moodlenet/classes/privacy/provider.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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/>.
|
||||
/**
|
||||
* Privacy class for tool_moodlenet.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy class for tool_moodlenet.
|
||||
*
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
350
admin/tool/moodlenet/classes/profile_manager.php
Normal file
350
admin/tool/moodlenet/classes/profile_manager.php
Normal file
@ -0,0 +1,350 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Profile manager class
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_moodlenet;
|
||||
|
||||
/**
|
||||
* Class for handling interaction with the moodlenet profile.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class profile_manager {
|
||||
|
||||
/**
|
||||
* Get the mnet profile for a user.
|
||||
*
|
||||
* @param int $userid The ID for the user to get the profile form
|
||||
* @return moodlenet_user_profile or null.
|
||||
*/
|
||||
public static function get_moodlenet_user_profile(int $userid): ?moodlenet_user_profile {
|
||||
global $CFG;
|
||||
// Check for official profile.
|
||||
if (self::official_profile_exists()) {
|
||||
$user = \core_user::get_user($userid, 'moodlenetprofile');
|
||||
try {
|
||||
$userprofile = $user->moodlenetprofile ? $user->moodlenetprofile : '';
|
||||
return (isset($user)) ? new moodlenet_user_profile($userprofile, $userid) : null;
|
||||
} catch (\moodle_exception $e) {
|
||||
// If an exception is thrown, means there isn't a valid profile set. No need to log exception.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Otherwise get hacked in user profile field.
|
||||
require_once($CFG->dirroot . '/user/profile/lib.php');
|
||||
$profilefields = profile_get_user_fields_with_data($userid);
|
||||
foreach ($profilefields as $key => $field) {
|
||||
if ($field->get_category_name() == self::get_category_name()
|
||||
&& $field->inputname == 'profile_field_mnetprofile') {
|
||||
try {
|
||||
return new moodlenet_user_profile($field->display_data(), $userid);
|
||||
} catch (\moodle_exception $e) {
|
||||
// If an exception is thrown, means there isn't a valid profile set. No need to log exception.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the moodlenet profile.
|
||||
*
|
||||
* @param moodlenet_user_profile $moodlenetprofile The moodlenet profile to save.
|
||||
*/
|
||||
public static function save_moodlenet_user_profile(moodlenet_user_profile $moodlenetprofile): void {
|
||||
global $CFG, $DB;
|
||||
// Do some cursory checks first to see if saving is possible.
|
||||
if (self::official_profile_exists()) {
|
||||
// All good. Let's save.
|
||||
$user = \core_user::get_user($moodlenetprofile->get_userid());
|
||||
$user->moodlenetprofile = $moodlenetprofile->get_profile_name();
|
||||
|
||||
require_once($CFG->dirroot . '/user/lib.php');
|
||||
|
||||
\user_update_user($user, false, true);
|
||||
return;
|
||||
}
|
||||
$fielddata = self::get_user_profile_field();
|
||||
$fielddata = self::validate_and_fix_missing_profile_items($fielddata);
|
||||
// Everything should be back to normal. Let's save.
|
||||
require_once($CFG->dirroot . '/user/profile/lib.php');
|
||||
\profile_save_custom_fields($moodlenetprofile->get_userid(),
|
||||
[$fielddata->shortname => $moodlenetprofile->get_profile_name()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the required user profile fields and categories are in place. If not it regenerates them.
|
||||
*
|
||||
* @param stdClass $fielddata The moodlenet profile field.
|
||||
* @return stdClass The same moodlenet profile field, with any necessary updates made.
|
||||
*/
|
||||
private static function validate_and_fix_missing_profile_items(\stdClass $fielddata): \stdClass {
|
||||
global $DB;
|
||||
|
||||
if (empty((array) $fielddata)) {
|
||||
// We need to regenerate the category and field to store this data.
|
||||
if (!self::check_profile_category()) {
|
||||
$categoryid = self::create_user_profile_category();
|
||||
self::create_user_profile_text_field($categoryid);
|
||||
} else {
|
||||
// We need the category id.
|
||||
$category = $DB->get_record('user_info_category', ['name' => self::get_category_name()]);
|
||||
self::create_user_profile_text_field($category->id);
|
||||
}
|
||||
$fielddata = self::get_user_profile_field();
|
||||
} else {
|
||||
if (!self::check_profile_category($fielddata->categoryid)) {
|
||||
$categoryid = self::create_user_profile_category();
|
||||
// Update the field to put it back into this category.
|
||||
$fielddata->categoryid = $categoryid;
|
||||
$DB->update_record('user_info_field', $fielddata);
|
||||
}
|
||||
}
|
||||
return $fielddata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user profile field table object.
|
||||
*
|
||||
* @return stdClass the moodlenet profile table object. False if no record found.
|
||||
*/
|
||||
private static function get_user_profile_field(): \stdClass {
|
||||
global $DB;
|
||||
$fieldname = self::get_profile_field_name();
|
||||
$record = $DB->get_record('user_info_field', ['shortname' => $fieldname]);
|
||||
return ($record) ? $record : (object) [];
|
||||
}
|
||||
|
||||
/**
|
||||
* This reports back if the category has been deleted or the config value is different.
|
||||
*
|
||||
* @param int $categoryid The category id to check against.
|
||||
* @return bool True is the category checks out, otherwise false.
|
||||
*/
|
||||
private static function check_profile_category(int $categoryid = null): bool {
|
||||
global $DB;
|
||||
$categoryname = self::get_category_name();
|
||||
$categorydata = $DB->get_record('user_info_category', ['name' => $categoryname]);
|
||||
if (empty($categorydata)) {
|
||||
return false;
|
||||
}
|
||||
if (isset($categoryid) && $categorydata->id != $categoryid) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we using the proper user profile field to hold the mnet profile?
|
||||
*
|
||||
* @return bool True if we are using a user table field for the mnet profile. False means we are using costom profile fields.
|
||||
*/
|
||||
public static function official_profile_exists(): bool {
|
||||
global $DB;
|
||||
|
||||
$usertablecolumns = $DB->get_columns('user', false);
|
||||
if (isset($usertablecolumns['moodlenetprofile'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the category name that is set for this site.
|
||||
*
|
||||
* @return string The category used to hold the moodle net profile field.
|
||||
*/
|
||||
public static function get_category_name(): string {
|
||||
return get_config('tool_moodlenet', 'profile_category');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the a unique category to hold the moodle net user profile.
|
||||
*
|
||||
* @param string $categoryname The base category name to use.
|
||||
* @return string The actual name of the category to use.
|
||||
*/
|
||||
private static function set_category_name(string $categoryname): string {
|
||||
global $DB;
|
||||
|
||||
$attemptname = $categoryname;
|
||||
|
||||
// Check if this category already exists.
|
||||
$foundcategoryname = false;
|
||||
$i = 0;
|
||||
do {
|
||||
$category = $DB->count_records('user_info_category', ['name' => $attemptname]);
|
||||
if ($category > 0) {
|
||||
$i++;
|
||||
$attemptname = $categoryname . $i;
|
||||
} else {
|
||||
set_config('profile_category', $attemptname, 'tool_moodlenet');
|
||||
$foundcategoryname = true;
|
||||
}
|
||||
} while (!$foundcategoryname);
|
||||
return $attemptname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom user profile category to hold our custom field.
|
||||
*
|
||||
* @return int The id of the created category.
|
||||
*/
|
||||
public static function create_user_profile_category(): int {
|
||||
global $DB;
|
||||
// No nice API to do this, so direct DB calls it is.
|
||||
$data = new \stdClass();
|
||||
$data->sortorder = $DB->count_records('user_info_category') + 1;
|
||||
$data->name = self::set_category_name(get_string('pluginname', 'tool_moodlenet'));
|
||||
$data->id = $DB->insert_record('user_info_category', $data, true);
|
||||
|
||||
$createdcategory = $DB->get_record('user_info_category', array('id' => $data->id));
|
||||
\core\event\user_info_category_created::create_from_category($createdcategory)->trigger();
|
||||
return $createdcategory->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a unique name to be used for the moodle net profile.
|
||||
*
|
||||
* @param string $fieldname The base fieldname to use.
|
||||
* @return string The actual profile field name.
|
||||
*/
|
||||
private static function set_profile_field_name(string $fieldname): string {
|
||||
global $DB;
|
||||
|
||||
$attemptname = $fieldname;
|
||||
|
||||
// Check if this profilefield already exists.
|
||||
$foundfieldname = false;
|
||||
$i = 0;
|
||||
do {
|
||||
$profilefield = $DB->count_records('user_info_field', ['shortname' => $attemptname]);
|
||||
if ($profilefield > 0) {
|
||||
$i++;
|
||||
$attemptname = $fieldname . $i;
|
||||
} else {
|
||||
set_config('profile_field_name', $attemptname, 'tool_moodlenet');
|
||||
$foundfieldname = true;
|
||||
}
|
||||
} while (!$foundfieldname);
|
||||
return $attemptname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique profile field used to hold the moodle net profile.
|
||||
*
|
||||
* @return string The profile field name being used on this site.
|
||||
*/
|
||||
public static function get_profile_field_name(): string {
|
||||
return get_config('tool_moodlenet', 'profile_field_name');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a user profile field to hold the moodlenet profile information.
|
||||
*
|
||||
* @param int $categoryid The category to put this field into.
|
||||
*/
|
||||
public static function create_user_profile_text_field(int $categoryid): void {
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->dirroot . '/user/profile/definelib.php');
|
||||
require_once($CFG->dirroot . '/user/profile/field/text/define.class.php');
|
||||
|
||||
// Add our moodlenet profile field.
|
||||
$profileclass = new \profile_define_text();
|
||||
$data = (object) [
|
||||
'shortname' => self::set_profile_field_name('mnetprofile'),
|
||||
'name' => get_string('mnetprofile', 'tool_moodlenet'),
|
||||
'datatype' => 'text',
|
||||
'description' => get_string('mnetprofiledesc', 'tool_moodlenet'),
|
||||
'descriptionformat' => 1,
|
||||
'categoryid' => $categoryid,
|
||||
'signup' => 1,
|
||||
'forceunique' => 1,
|
||||
'visible' => 2,
|
||||
'param1' => 30,
|
||||
'param2' => 2048
|
||||
];
|
||||
$profileclass->define_save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given our $moodlenetprofile let's cURL the domains' WebFinger endpoint
|
||||
*
|
||||
* @param moodlenet_user_profile $moodlenetprofile The moodlenet profile to get info from.
|
||||
* @return array [bool, text, raw]
|
||||
*/
|
||||
public static function get_moodlenet_profile_link(moodlenet_user_profile $moodlenetprofile): array {
|
||||
$domain = $moodlenetprofile->get_domain();
|
||||
$username = $moodlenetprofile->get_username();
|
||||
|
||||
// Assumption: All MoodleNet instance's will contain a WebFinger validation script.
|
||||
$url = "https://".$domain."/.well-known/webfinger?resource=acct:".$username."@".$domain;
|
||||
|
||||
$curl = new \curl();
|
||||
$options = [
|
||||
'CURLOPT_HEADER' => 0,
|
||||
];
|
||||
$content = $curl->get($url, null, $options);
|
||||
$errno = $curl->get_errno();
|
||||
$info = $curl->get_info();
|
||||
|
||||
// The base cURL seems fine, let's press on.
|
||||
if (!$errno) {
|
||||
// WebFinger gave us a 404 back so the user has no droids here.
|
||||
if ($info['http_code'] >= 400) {
|
||||
if ($info['http_code'] === 404) {
|
||||
// User not found.
|
||||
return [
|
||||
'result' => false,
|
||||
'message' => get_string('profilevalidationfail', 'tool_moodlenet'),
|
||||
];
|
||||
} else {
|
||||
// There was some other error that was not a missing account.
|
||||
return [
|
||||
'result' => false,
|
||||
'message' => get_string('profilevalidationerror', 'tool_moodlenet'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// We must have a valid link so give it back to the user.
|
||||
$data = json_decode($content);
|
||||
return [
|
||||
'result' => true,
|
||||
'message' => get_string('profilevalidationpass', 'tool_moodlenet'),
|
||||
'domain' => $data->aliases[0]
|
||||
];
|
||||
} else {
|
||||
// There was some failure in curl so report it back.
|
||||
return [
|
||||
'result' => false,
|
||||
'message' => get_string('profilevalidationerror', 'tool_moodlenet'),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
44
admin/tool/moodlenet/db/services.php
Normal file
44
admin/tool/moodlenet/db/services.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Tool Moodle.Net webservice definitions.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$functions = [
|
||||
'tool_moodlenet_verify_webfinger' => [
|
||||
'classname' => 'tool_moodlenet\external',
|
||||
'methodname' => 'verify_webfinger',
|
||||
'description' => 'Verify if the passed information resolves into a WebFinger profile URL',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE]
|
||||
],
|
||||
'tool_moodlenet_search_courses' => [
|
||||
'classname' => 'tool_moodlenet\external',
|
||||
'methodname' => 'search_courses',
|
||||
'description' => 'For some given input search for a course that matches',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE]
|
||||
],
|
||||
];
|
81
admin/tool/moodlenet/db/upgrade.php
Normal file
81
admin/tool/moodlenet/db/upgrade.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Upgrade script for tool_moodlenet.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Upgrade the plugin.
|
||||
*
|
||||
* @param int $oldversion
|
||||
* @return bool always true
|
||||
*/
|
||||
function xmldb_tool_moodlenet_upgrade(int $oldversion) {
|
||||
global $CFG, $DB;
|
||||
if ($oldversion < 2020060500) {
|
||||
|
||||
// Grab some of the old settings.
|
||||
$categoryname = get_config('tool_moodlenet', 'profile_category');
|
||||
$profilefield = get_config('tool_moodlenet', 'profile_field_name');
|
||||
|
||||
// Master version only!
|
||||
|
||||
// Find out if we have a custom profile field for moodle.net.
|
||||
$sql = "SELECT f.*
|
||||
FROM {user_info_field} f
|
||||
JOIN {user_info_category} c ON c.id = f.categoryid and c.name = :categoryname
|
||||
WHERE f.shortname = :name";
|
||||
|
||||
$params = [
|
||||
'categoryname' => $categoryname,
|
||||
'name' => $profilefield
|
||||
];
|
||||
|
||||
$record = $DB->get_record_sql($sql, $params);
|
||||
|
||||
if (!empty($record)) {
|
||||
$userentries = $DB->get_recordset('user_info_data', ['fieldid' => $record->id]);
|
||||
$recordstodelete = [];
|
||||
foreach ($userentries as $userentry) {
|
||||
$data = (object) [
|
||||
'id' => $userentry->userid,
|
||||
'moodlenetprofile' => $userentry->data
|
||||
];
|
||||
$DB->update_record('user', $data, true);
|
||||
$recordstodelete[] = $userentry->id;
|
||||
}
|
||||
$userentries->close();
|
||||
|
||||
// Remove the user profile data, fields, and category.
|
||||
$DB->delete_records_list('user_info_data', 'id', $recordstodelete);
|
||||
$DB->delete_records('user_info_field', ['id' => $record->id]);
|
||||
$DB->delete_records('user_info_category', ['name' => $categoryname]);
|
||||
unset_config('profile_field_name', 'tool_moodlenet');
|
||||
unset_config('profile_category', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
upgrade_plugin_savepoint(true, 2020060500, 'tool', 'moodlenet');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
85
admin/tool/moodlenet/import.php
Normal file
85
admin/tool/moodlenet/import.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* This is the main endpoint which MoodleNet instances POST to.
|
||||
*
|
||||
* MoodleNet instances send the user agent to this endpoint via a form POST.
|
||||
* Then:
|
||||
* 1. The POSTed resource information is put in a session store for cross-request access.
|
||||
* 2. This page makes a GET request for admin/tool/moodlenet/index.php (the import confirmation page).
|
||||
* 3. Then, depending on whether the user is authenticated, the user will either:
|
||||
* - If not authenticated, they will be asked to login, after which they will see the confirmation page (leveraging $wantsurl).
|
||||
* - If authenticated, they will see the confirmation page immediately.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_moodlenet\local\import_info;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
|
||||
// The integration must be enabled for this import endpoint to be active.
|
||||
if (!get_config('tool_moodlenet', 'enablemoodlenet')) {
|
||||
print_error('moodlenetnotenabled', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
$resourceurl = required_param('resourceurl', PARAM_URL);
|
||||
$resourceinfo = required_param('resource_info', PARAM_RAW);
|
||||
$resourceinfo = json_decode($resourceinfo);
|
||||
$type = optional_param('type', 'link', PARAM_TEXT);
|
||||
$course = optional_param('course', 0, PARAM_INT);
|
||||
$section = optional_param('section', 0, PARAM_INT);
|
||||
// If course isn't provided, course and section are null.
|
||||
if (empty($course)) {
|
||||
$course = null;
|
||||
$section = null;
|
||||
}
|
||||
$name = validate_param($resourceinfo->name, PARAM_TEXT);
|
||||
$description = validate_param($resourceinfo->summary, PARAM_TEXT);
|
||||
|
||||
// Only accept POSTs.
|
||||
if (!empty($_POST)) {
|
||||
// Store information about the import of the resource for the current user.
|
||||
$importconfig = (object) [
|
||||
'course' => $course,
|
||||
'section' => $section,
|
||||
'type' => $type,
|
||||
];
|
||||
$metadata = (object) [
|
||||
'name' => $name,
|
||||
'description' => $description ?? ''
|
||||
];
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
$importinfo = new import_info(
|
||||
$USER->id,
|
||||
new remote_resource(new \curl(), new url($resourceurl), $metadata),
|
||||
$importconfig
|
||||
);
|
||||
$importinfo->save();
|
||||
|
||||
// Redirect to the import confirmation page, detouring via the log in page if required.
|
||||
redirect(new moodle_url('/admin/tool/moodlenet/index.php', ['id' => $importinfo->get_id()]));
|
||||
|
||||
}
|
||||
|
||||
// Invalid or missing POST data. Show an error to the user.
|
||||
print_error('missinginvalidpostdata', 'tool_moodlenet');
|
136
admin/tool/moodlenet/index.php
Normal file
136
admin/tool/moodlenet/index.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Landing page for all imports from MoodleNet.
|
||||
*
|
||||
* This page asks the user to confirm the import process, and takes them to the relevant next step.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_moodlenet\local\import_info;
|
||||
use tool_moodlenet\local\import_backup_helper;
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->dirroot .'/course/lib.php');
|
||||
|
||||
$cancel = optional_param('cancel', null, PARAM_TEXT);
|
||||
$continue = optional_param('continue', null, PARAM_TEXT);
|
||||
$id = required_param('id', PARAM_ALPHANUM);
|
||||
|
||||
if (is_null($importinfo = import_info::load($id))) {
|
||||
throw new moodle_exception('missinginvalidpostdata', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
// Access control.
|
||||
require_login($importinfo->get_config()->course, false); // Course may be null here - that's ok.
|
||||
if ($importinfo->get_config()->course) {
|
||||
require_capability('moodle/course:manageactivities', context_course::instance($importinfo->get_config()->course));
|
||||
}
|
||||
if (!get_config('tool_moodlenet', 'enablemoodlenet')) {
|
||||
print_error('moodlenetnotenabled', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
// Handle the form submits.
|
||||
// This page POSTs to self to verify the sesskey for the confirm action.
|
||||
// The next page will either be:
|
||||
// - 1. The restore process for a course or module, if the file is an mbz file.
|
||||
// - 2. The 'select a course' tool page, if course and section are not provided.
|
||||
// - 3. The 'select what to do with the content' tool page, provided course and section are present.
|
||||
// - 4. The dashboard, if the user decides to cancel and course or section is not found.
|
||||
// - 5. The course home, if the user decides to cancel but the course and section are found.
|
||||
if ($cancel) {
|
||||
if (!empty($importinfo->get_config()->course)) {
|
||||
$url = new \moodle_url('/course/view.php', ['id' => $importinfo->get_config()->course]);
|
||||
} else {
|
||||
$url = new \moodle_url('/');
|
||||
}
|
||||
redirect($url);
|
||||
} else if ($continue) {
|
||||
confirm_sesskey();
|
||||
|
||||
// Handle backups.
|
||||
if (strtolower($importinfo->get_resource()->get_extension()) == 'mbz') {
|
||||
if (empty($importinfo->get_config()->course)) {
|
||||
// Find a course that the user has permission to upload a backup file.
|
||||
// This is likely to be very slow on larger sites.
|
||||
$context = import_backup_helper::get_context_for_user($USER->id);
|
||||
|
||||
if (is_null($context)) {
|
||||
print_error('nopermissions', 'error', '', get_string('restore:uploadfile', 'core_role'));
|
||||
}
|
||||
} else {
|
||||
$context = context_course::instance($importinfo->get_config()->course);
|
||||
}
|
||||
|
||||
$importbackuphelper = new import_backup_helper($importinfo->get_resource(), $USER, $context);
|
||||
$storedfile = $importbackuphelper->get_stored_file();
|
||||
|
||||
$url = new \moodle_url('/backup/restorefile.php', [
|
||||
'component' => $storedfile->get_component(),
|
||||
'filearea' => $storedfile->get_filearea(),
|
||||
'itemid' => $storedfile->get_itemid(),
|
||||
'filepath' => $storedfile->get_filepath(),
|
||||
'filename' => $storedfile->get_filename(),
|
||||
'filecontextid' => $storedfile->get_contextid(),
|
||||
'contextid' => $context->id,
|
||||
'action' => 'choosebackupfile'
|
||||
]);
|
||||
redirect($url);
|
||||
}
|
||||
|
||||
// Handle adding files to a course.
|
||||
// Course and section data present and confirmed. Redirect to the option select view.
|
||||
if (!is_null($importinfo->get_config()->course) && !is_null($importinfo->get_config()->section)) {
|
||||
redirect(new \moodle_url('/admin/tool/moodlenet/options.php', ['id' => $id]));
|
||||
}
|
||||
|
||||
if (is_null($importinfo->get_config()->course)) {
|
||||
redirect(new \moodle_url('/admin/tool/moodlenet/select.php', ['id' => $id]));
|
||||
}
|
||||
}
|
||||
|
||||
// Display the page.
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('base');
|
||||
$PAGE->set_title(get_string('addingaresource', 'tool_moodlenet'));
|
||||
$PAGE->set_heading(get_string('addingaresource', 'tool_moodlenet'));
|
||||
$url = new moodle_url('/admin/tool/moodlenet/index.php');
|
||||
$PAGE->set_url($url);
|
||||
$renderer = $PAGE->get_renderer('core');
|
||||
|
||||
// Relevant confirmation form.
|
||||
$context = $context = [
|
||||
'resourceurl' => $importinfo->get_resource()->get_url()->get_value(),
|
||||
'resourcename' => $importinfo->get_resource()->get_name(),
|
||||
'resourcetype' => $importinfo->get_config()->type,
|
||||
'sesskey' => sesskey()
|
||||
];
|
||||
if (!is_null($importinfo->get_config()->course) && !is_null($importinfo->get_config()->section)) {
|
||||
$course = get_course($importinfo->get_config()->course);
|
||||
$context = array_merge($context, [
|
||||
'course' => $course->id,
|
||||
'coursename' => $course->shortname,
|
||||
'section' => $importinfo->get_config()->section
|
||||
]);
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $renderer->render_from_template('tool_moodlenet/import_confirmation', $context);
|
||||
echo $OUTPUT->footer();
|
69
admin/tool/moodlenet/lang/en/tool_moodlenet.php
Normal file
69
admin/tool/moodlenet/lang/en/tool_moodlenet.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?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 the tool_moodlenet component.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category string
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['addingaresource'] = 'Adding content from MoodleNet';
|
||||
$string['aria:enterprofile'] = "Enter your MoodleNet profile URL";
|
||||
$string['aria:footermessage'] = "Browse for content on MoodleNet";
|
||||
$string['browsecontentmoodlenet'] = "Or browse for content on MoodleNet";
|
||||
$string['clearsearch'] = "Clear search";
|
||||
$string['connectandbrowse'] = "Connect to and browse:";
|
||||
$string['defaultmoodlenet'] = "Default MoodleNet URL";
|
||||
$string['defaultmoodlenet_desc'] = "The URL to either Moodle HQ's MoodleNet instance, or your preferred instance.";
|
||||
$string['defaultmoodlenetname'] = "MoodleNet instance name";
|
||||
$string['defaultmoodlenetname_desc'] = 'The name of either Moodle HQ\'s MoodleNet instance or your preferred MoodleNet instance to browse on.';
|
||||
$string['enablemoodlenet'] = 'Enable MoodleNet integration';
|
||||
$string['enablemoodlenet_desc'] = 'Enabling the integration allows users with the \'xx\' capability to browse MoodleNet from the
|
||||
activity chooser and import MoodleNet resources into their course. It also allows users to push backups from MoodleNet into Moodle.
|
||||
';
|
||||
$string['errorduringdownload'] = 'An error occurred while downloading the file: {$a}';
|
||||
$string['forminfo'] = "It will be automatically saved on your moodle profile.";
|
||||
$string['footermessage'] = "Or browse for content on";
|
||||
$string['instancedescription'] = "MoodleNet is an open social media platform for educators, with a focus on the collaborative curation of collections of open resources. ";
|
||||
$string['instanceplaceholder'] = '@yourprofile@moodle.net';
|
||||
$string['inputhelp'] = 'Or if you have a MoodleNet account already, enter your MoodleNet profile:';
|
||||
$string['invalidmoodlenetprofile'] = '$userprofile is not correctly formatted';
|
||||
$string['importconfirm'] = 'You are about to import the content "{$a->resourcename} ({$a->resourcetype})" into the course "{$a->coursename}". Are you sure you want to continue?';
|
||||
$string['importconfirmnocourse'] = 'You are about to import the content "{$a->resourcename} ({$a->resourcetype})" into your site. Are you sure you want to continue?';
|
||||
$string['importformatselectguidingtext'] = 'In which format would you like this content "{$a->name} ({$a->type})" to be added to your course?';
|
||||
$string['importformatselectheader'] = 'Choose the content display format';
|
||||
$string['missinginvalidpostdata'] = 'The resource information from MoodleNet is either missing, or is in an incorrect format.
|
||||
If this happens repeatedly, please contact the site administrator.';
|
||||
$string['mnetprofile'] = 'MoodleNet profile';
|
||||
$string['mnetprofiledesc'] = '<p>Enter in your MoodleNet profile details here to be redirected to your profile while visiting MoodleNet.</p>';
|
||||
$string['moodlenetsettings'] = 'MoodleNet settings';
|
||||
$string['moodlenetnotenabled'] = 'The MoodleNet integration must be enabled before resource imports can be processed.
|
||||
To enable this feature, see the \'enablemoodlenet\' setting.';
|
||||
$string['notification'] = 'You are about to import the content "{$a->name} ({$a->type})" into your site. Select the course in which it should be added, or <a href="{$a->cancellink}">cancel</a>.';
|
||||
$string['searchcourses'] = "Search courses";
|
||||
$string['selectpagetitle'] = 'Select page';
|
||||
$string['pluginname'] = 'MoodleNet';
|
||||
$string['privacy:metadata'] = "The MoodleNet tool only facilitates communication with MoodleNet. It stores no data.";
|
||||
$string['profilevalidationerror'] = 'There was a problem trying to validate your profile';
|
||||
$string['profilevalidationfail'] = 'Please enter a valid MoodleNet profile';
|
||||
$string['profilevalidationpass'] = 'Looks good!';
|
||||
$string['saveandgo'] = "Save and go";
|
||||
$string['uploadlimitexceeded'] = 'The file size {$a->filesize} exceeds the user upload limit of {$a->uploadlimit} bytes.';
|
104
admin/tool/moodlenet/lib.php
Normal file
104
admin/tool/moodlenet/lib.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* This page lists public api for tool_moodlenet plugin.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Peter Dias
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
use \core_course\local\entity\activity_chooser_footer;
|
||||
|
||||
/**
|
||||
* The default endpoint to MoodleNet.
|
||||
*/
|
||||
define('MOODLENET_DEFAULT_ENDPOINT', "lms/moodle/search");
|
||||
|
||||
/**
|
||||
* Generate the endpoint url to the user's moodlenet site.
|
||||
*
|
||||
* @param string $profileurl The user's moodlenet profile page
|
||||
* @param int $course The moodle course the mnet resource will be added to
|
||||
* @param int $section The section of the course will be added to. Defaults to the 0th element.
|
||||
* @return string the resulting endpoint
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
function generate_mnet_endpoint(string $profileurl, int $course, int $section = 0) {
|
||||
global $CFG;
|
||||
$urlportions = explode('@', $profileurl);
|
||||
$domain = end($urlportions);
|
||||
$parsedurl = parse_url($domain);
|
||||
$params = [
|
||||
'site' => $CFG->wwwroot,
|
||||
'course' => $course,
|
||||
'section' => $section
|
||||
];
|
||||
$endpoint = new moodle_url(MOODLENET_DEFAULT_ENDPOINT, $params);
|
||||
return (isset($parsedurl['scheme']) ? $domain : "https://$domain")."/{$endpoint->out(false)}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooking function to build up the initial Activity Chooser footer information for MoodleNet
|
||||
*
|
||||
* @param int $courseid The course the user is currently in and wants to add resources to
|
||||
* @param int $sectionid The section the user is currently in and wants to add resources to
|
||||
* @return activity_chooser_footer
|
||||
* @throws dml_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
function tool_moodlenet_custom_chooser_footer(int $courseid, int $sectionid): activity_chooser_footer {
|
||||
global $CFG, $USER, $OUTPUT;
|
||||
$defaultlink = get_config('tool_moodlenet', 'defaultmoodlenet');
|
||||
$enabled = get_config('tool_moodlenet', 'enablemoodlenet');
|
||||
|
||||
$advanced = false;
|
||||
// We are in the MoodleNet lib. It is safe assume we have our own functions here.
|
||||
$mnetprofile = \tool_moodlenet\profile_manager::get_moodlenet_user_profile($USER->id);
|
||||
if ($mnetprofile !== null) {
|
||||
$advanced = $mnetprofile->get_domain() ?? false;
|
||||
}
|
||||
|
||||
$defaultlink = generate_mnet_endpoint($defaultlink, $courseid, $sectionid);
|
||||
if ($advanced !== false) {
|
||||
$advanced = generate_mnet_endpoint($advanced, $courseid, $sectionid);
|
||||
}
|
||||
|
||||
$renderedfooter = $OUTPUT->render_from_template('tool_moodlenet/chooser_footer', (object)[
|
||||
'enabled' => (bool)$enabled,
|
||||
'generic' => $defaultlink,
|
||||
'advanced' => $advanced,
|
||||
'courseID' => $courseid,
|
||||
'sectionID' => $sectionid,
|
||||
'img' => $OUTPUT->image_url('MoodleNet', 'tool_moodlenet')->out(false),
|
||||
]);
|
||||
|
||||
$renderedcarousel = $OUTPUT->render_from_template('tool_moodlenet/chooser_moodlenet', (object)[
|
||||
'buttonName' => get_config('tool_moodlenet', 'defaultmoodlenetname'),
|
||||
'generic' => $defaultlink,
|
||||
'courseID' => $courseid,
|
||||
'sectionID' => $sectionid,
|
||||
'img' => $OUTPUT->image_url('MoodleNet', 'tool_moodlenet')->out(false),
|
||||
]);
|
||||
return new activity_chooser_footer(
|
||||
'tool_moodlenet/instance_form',
|
||||
$renderedfooter,
|
||||
$renderedcarousel
|
||||
);
|
||||
}
|
128
admin/tool/moodlenet/options.php
Normal file
128
admin/tool/moodlenet/options.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Page to select WHAT to do with a given resource stored on MoodleNet.
|
||||
*
|
||||
* This collates and presents the same options as a user would see for a drag and drop upload.
|
||||
* That is, it leverages the dndupload_register() hooks and delegates the resource handling to the dndupload_handle hooks.
|
||||
*
|
||||
* This page requires a course, section an resourceurl to be provided via import_info.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
use tool_moodlenet\local\import_handler_registry;
|
||||
use tool_moodlenet\local\import_processor;
|
||||
use tool_moodlenet\local\import_info;
|
||||
use tool_moodlenet\local\import_strategy_file;
|
||||
use tool_moodlenet\local\import_strategy_link;
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->dirroot . '/course/lib.php');
|
||||
|
||||
$module = optional_param('module', null, PARAM_PLUGIN);
|
||||
$import = optional_param('import', null, PARAM_ALPHA);
|
||||
$cancel = optional_param('cancel', null, PARAM_ALPHA);
|
||||
$id = required_param('id', PARAM_ALPHANUM);
|
||||
|
||||
if (is_null($importinfo = import_info::load($id))) {
|
||||
throw new moodle_exception('missinginvalidpostdata', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
// Resolve course and section params.
|
||||
// If course is not already set in the importinfo, we require it in the URL params.
|
||||
$config = $importinfo->get_config();
|
||||
if (!isset($config->course)) {
|
||||
$course = required_param('course', PARAM_INT);
|
||||
$config->course = $course;
|
||||
$config->section = 0;
|
||||
$importinfo->set_config($config);
|
||||
$importinfo->save();
|
||||
}
|
||||
|
||||
// Access control.
|
||||
require_login($config->course, false);
|
||||
require_capability('moodle/course:manageactivities', context_course::instance($config->course));
|
||||
if (!get_config('tool_moodlenet', 'enablemoodlenet')) {
|
||||
print_error('moodlenetnotenabled', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
// If the user cancelled, break early.
|
||||
if ($cancel) {
|
||||
redirect(new moodle_url('/course/view.php', ['id' => $config->course]));
|
||||
}
|
||||
|
||||
// Set up required objects.
|
||||
$course = get_course($config->course);
|
||||
$handlerregistry = new import_handler_registry($course, $USER);
|
||||
switch ($config->type) {
|
||||
case 'file':
|
||||
$strategy = new import_strategy_file();
|
||||
break;
|
||||
case 'link':
|
||||
default:
|
||||
$strategy = new import_strategy_link();
|
||||
break;
|
||||
}
|
||||
|
||||
if ($import && $module) {
|
||||
confirm_sesskey();
|
||||
|
||||
$handlerinfo = $handlerregistry->get_resource_handler_for_mod_and_strategy($importinfo->get_resource(), $module, $strategy);
|
||||
if (is_null($handlerinfo)) {
|
||||
throw new coding_exception("Invalid handler '$module'. The import handler could not be found.");
|
||||
}
|
||||
$importproc = new import_processor($course, $config->section, $importinfo->get_resource(), $handlerinfo, $handlerregistry);
|
||||
$importproc->process();
|
||||
|
||||
$importinfo->purge(); // We don't need information about the import any more.
|
||||
|
||||
redirect(new moodle_url('/course/view.php', ['id' => $course->id]));
|
||||
}
|
||||
|
||||
// Setup the page and display the form.
|
||||
$PAGE->set_context(context_course::instance($course->id));
|
||||
$PAGE->set_pagelayout('base');
|
||||
$PAGE->set_title(get_string('coursetitle', 'moodle', array('course' => $course->fullname)));
|
||||
$PAGE->set_heading($course->fullname);
|
||||
$PAGE->set_url(new moodle_url('/admin/tool/moodlenet/options.php'));
|
||||
|
||||
// Fetch the handlers supporting this resource. We'll display each of these as an option in the form.
|
||||
$handlercontext = [];
|
||||
foreach ($handlerregistry->get_resource_handlers_for_strategy($importinfo->get_resource(), $strategy) as $handler) {
|
||||
$handlercontext[] = [
|
||||
'module' => $handler->get_module_name(),
|
||||
'message' => $handler->get_description(),
|
||||
];
|
||||
}
|
||||
|
||||
// Template context.
|
||||
$context = [
|
||||
'resourcename' => $importinfo->get_resource()->get_name(),
|
||||
'resourcetype' => $importinfo->get_config()->type,
|
||||
'resourceurl' => urlencode($importinfo->get_resource()->get_url()->get_value()),
|
||||
'course' => $course->id,
|
||||
'section' => $config->section,
|
||||
'sesskey' => sesskey(),
|
||||
'handlers' => $handlercontext,
|
||||
'oneoption' => sizeof($handlercontext) === 1
|
||||
];
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $PAGE->get_renderer('core')->render_from_template('tool_moodlenet/import_options_select', $context);
|
||||
echo $OUTPUT->footer();
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
52
admin/tool/moodlenet/pix/courses.svg
Normal file
52
admin/tool/moodlenet/pix/courses.svg
Normal file
@ -0,0 +1,52 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="157 -1305 148 125" preserveAspectRatio="xMinYMid meet">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
clip-path: url(#clip-Courses);
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #eee;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #c4c8cc;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
<clipPath id="clip-Courses">
|
||||
<rect x="157" y="-1305" width="148" height="125"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="Courses" class="cls-1">
|
||||
<g id="Group_44" data-name="Group 44" transform="translate(-268 -1781)">
|
||||
<ellipse id="Ellipse_41" data-name="Ellipse 41" class="cls-2" cx="74" cy="14.785" rx="74" ry="14.785" transform="translate(425 571.43)"/>
|
||||
<rect id="Rectangle_87" data-name="Rectangle 87" class="cls-3" width="95.097" height="110.215" transform="translate(451.909 476)"/>
|
||||
<g id="Group_43" data-name="Group 43" transform="translate(464.04 494)">
|
||||
<rect id="Rectangle_88" data-name="Rectangle 88" class="cls-4" width="31.043" height="34" transform="translate(0)"/>
|
||||
<rect id="Rectangle_89" data-name="Rectangle 89" class="cls-4" width="31.043" height="34" transform="translate(0 42)"/>
|
||||
<rect id="Rectangle_90" data-name="Rectangle 90" class="cls-4" width="31.067" height="34" transform="translate(39.005)"/>
|
||||
<rect id="Rectangle_91" data-name="Rectangle 91" class="cls-4" width="31.067" height="34" transform="translate(39.005 42)"/>
|
||||
<rect id="Rectangle_92" data-name="Rectangle 92" class="cls-3" width="23.023" height="3.18" transform="translate(3.081 16.549)"/>
|
||||
<rect id="Rectangle_93" data-name="Rectangle 93" class="cls-3" width="23.023" height="3.18" transform="translate(3.081 58.549)"/>
|
||||
<rect id="Rectangle_94" data-name="Rectangle 94" class="cls-3" width="23.023" height="3.18" transform="translate(43.122 16.549)"/>
|
||||
<rect id="Rectangle_95" data-name="Rectangle 95" class="cls-3" width="23.023" height="3.18" transform="translate(43.122 58.549)"/>
|
||||
<rect id="Rectangle_96" data-name="Rectangle 96" class="cls-3" width="14.014" height="3.18" transform="translate(3.081 21.825)"/>
|
||||
<rect id="Rectangle_97" data-name="Rectangle 97" class="cls-3" width="18.845" height="3.18" transform="translate(3.081 26.825)"/>
|
||||
<rect id="Rectangle_98" data-name="Rectangle 98" class="cls-3" width="14.014" height="3.18" transform="translate(3.081 63.825)"/>
|
||||
<rect id="Rectangle_99" data-name="Rectangle 99" class="cls-3" width="18.845" height="3.18" transform="translate(3.081 68.825)"/>
|
||||
<rect id="Rectangle_100" data-name="Rectangle 100" class="cls-3" width="14.014" height="3.18" transform="translate(43.122 21.825)"/>
|
||||
<rect id="Rectangle_101" data-name="Rectangle 101" class="cls-3" width="18.845" height="3.18" transform="translate(43.122 26.825)"/>
|
||||
<rect id="Rectangle_102" data-name="Rectangle 102" class="cls-3" width="14.014" height="3.18" transform="translate(43.122 63.825)"/>
|
||||
<rect id="Rectangle_103" data-name="Rectangle 103" class="cls-3" width="18.845" height="3.18" transform="translate(43.122 68.825)"/>
|
||||
<ellipse id="Ellipse_42" data-name="Ellipse 42" class="cls-3" cx="5.658" cy="5.652" rx="5.658" ry="5.652" transform="translate(3.003 3.55)"/>
|
||||
<ellipse id="Ellipse_43" data-name="Ellipse 43" class="cls-3" cx="5.658" cy="5.652" rx="5.658" ry="5.652" transform="translate(3.003 45.55)"/>
|
||||
<ellipse id="Ellipse_44" data-name="Ellipse 44" class="cls-3" cx="5.658" cy="5.652" rx="5.658" ry="5.652" transform="translate(43.044 3.55)"/>
|
||||
<ellipse id="Ellipse_45" data-name="Ellipse 45" class="cls-3" cx="5.658" cy="5.652" rx="5.658" ry="5.652" transform="translate(43.044 45.55)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
53
admin/tool/moodlenet/select.php
Normal file
53
admin/tool/moodlenet/select.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Select page.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Mathew May {@link https://mathew.solutions}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
use tool_moodlenet\local\import_info;
|
||||
use tool_moodlenet\output\select_page;
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
|
||||
$id = required_param('id', PARAM_ALPHANUM);
|
||||
|
||||
// Access control.
|
||||
require_login();
|
||||
if (!get_config('tool_moodlenet', 'enablemoodlenet')) {
|
||||
print_error('moodlenetnotenabled', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
if (is_null($importinfo = import_info::load($id))) {
|
||||
throw new moodle_exception('missinginvalidpostdata', 'tool_moodlenet');
|
||||
}
|
||||
|
||||
$PAGE->set_url('/admin/tool/moodlenet/select.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('standard');
|
||||
$PAGE->set_title(get_string('selectpagetitle', 'tool_moodlenet'));
|
||||
$PAGE->set_heading(format_string($SITE->fullname));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$renderable = new select_page($importinfo);
|
||||
$renderer = $PAGE->get_renderer('tool_moodlenet');
|
||||
echo $renderer->render($renderable);
|
||||
|
||||
echo $OUTPUT->footer();
|
46
admin/tool/moodlenet/settings.php
Normal file
46
admin/tool/moodlenet/settings.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Puts the plugin actions into the admin settings tree.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if ($hassiteconfig) {
|
||||
// Create a MoodleNet category.
|
||||
$ADMIN->add('root', new admin_category('moodlenet', get_string('pluginname', 'tool_moodlenet')));
|
||||
// Our settings page.
|
||||
$settings = new admin_settingpage('tool_moodlenet', get_string('moodlenetsettings', 'tool_moodlenet'));
|
||||
$ADMIN->add('moodlenet', $settings);
|
||||
|
||||
$temp = new admin_setting_configcheckbox('tool_moodlenet/enablemoodlenet', get_string('enablemoodlenet', 'tool_moodlenet'),
|
||||
new lang_string('enablemoodlenet_desc', 'tool_moodlenet'), 1, 1, 0);
|
||||
$settings->add($temp);
|
||||
|
||||
$temp = new admin_setting_configtext('tool_moodlenet/defaultmoodlenetname',
|
||||
get_string('defaultmoodlenetname', 'tool_moodlenet'), new lang_string('defaultmoodlenetname_desc', 'tool_moodlenet'),
|
||||
'Moodle HQ MoodleNet');
|
||||
$settings->add($temp);
|
||||
|
||||
$temp = new admin_setting_configtext('tool_moodlenet/defaultmoodlenet', get_string('defaultmoodlenet', 'tool_moodlenet'),
|
||||
new lang_string('defaultmoodlenet_desc', 'tool_moodlenet'), 'https://home.moodle.net');
|
||||
$settings->add($temp);
|
||||
}
|
46
admin/tool/moodlenet/templates/chooser_footer.mustache
Normal file
46
admin/tool/moodlenet/templates/chooser_footer.mustache
Normal file
@ -0,0 +1,46 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/chooser_footer
|
||||
|
||||
Chooser favourite template partial.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
{{#enabled}}
|
||||
<div class="w-100 d-flex px-2">
|
||||
<a aria-label="{{#str}}aria:footermessage, tool_moodlenet{{/str}}"
|
||||
class="d-inline my-auto mr-1"
|
||||
{{#advanced}}
|
||||
href="{{advanced}}"
|
||||
target="_self"
|
||||
{{/advanced}}
|
||||
{{^advanced}}
|
||||
href="#"
|
||||
data-action="show-moodlenet"
|
||||
data-courseid="{{courseID}}"
|
||||
data-sectionID="{{sectionID}}"
|
||||
{{/advanced}}
|
||||
>
|
||||
{{#str}} footermessage , tool_moodlenet{{/str}}
|
||||
|
||||
<span class="moodlenet-logo" aria-hidden="true">{{#pix}} MoodleNet, tool_moodlenet {{/pix}}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{/enabled}}
|
@ -0,0 +1,28 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/chooser_footer_close_mnet
|
||||
|
||||
Chooser favourite template partial.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<button data-action="close-chooser-option-summary" class="closeoptionsummary btn btn-secondary mr-auto" tabindex="0">
|
||||
{{#str}} back {{/str}}
|
||||
</button>
|
67
admin/tool/moodlenet/templates/chooser_moodlenet.mustache
Normal file
67
admin/tool/moodlenet/templates/chooser_moodlenet.mustache
Normal 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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/chooser_moodlenet
|
||||
|
||||
Chooser favourite template partial.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div class="optionsummary" tabindex="-1" data-region="chooser-option-summary-container">
|
||||
<div class="content text-left mb-5 px-5 py-4" data-region="chooser-option-summary-content-container">
|
||||
<div data-region="moodle-net">
|
||||
<div class="overlay-icon-container z-index-1 d-none" data-region="spinner"></div>
|
||||
<img class="w-25 mb-4" aria-hidden="true" src="{{{img}}}">
|
||||
<p>{{#str}} instancedescription, tool_moodlenet {{/str}}</p>
|
||||
<p class="w-75 mx-auto mb-1 mt-5">{{#str}} connectandbrowse, tool_moodlenet {{/str}}</p>
|
||||
<a class="btn btn-secondary d-block w-75 mx-auto mb-4"
|
||||
data-action="browse"
|
||||
href="{{{generic}}}"
|
||||
>
|
||||
{{{buttonName}}}
|
||||
</a>
|
||||
<div id="mnet-instance-form-{{uniqid}}" data-region="mnet-form">
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">
|
||||
<div class="w-75 mx-auto my-3">
|
||||
<p class="text-left">{{#str}}inputhelp, tool_moodlenet{{/str}}</p>
|
||||
<div class="input-group">
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
data-var="mnet-link"
|
||||
data-courseid="{{courseID}}"
|
||||
data-sectionid="{{sectionID}}"
|
||||
placeholder="{{#str}} instanceplaceholder, tool_moodlenet {{/str}}"
|
||||
aria-label="{{#str}} aria:enterprofile, tool_moodlenet {{/str}}"
|
||||
autocomplete="off"
|
||||
>
|
||||
<div class="input-group-append z-index-0">
|
||||
<button class="btn btn-secondary"
|
||||
data-action="submit" id="button-addon2"
|
||||
>
|
||||
{{#str}} saveandgo, tool_moodlenet {{/str}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-left" aria-live="assertive" data-region="validation-area"></p>
|
||||
<p class="text-left">{{#str}} forminfo, tool_moodlenet {{/str}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
76
admin/tool/moodlenet/templates/import_confirmation.mustache
Normal file
76
admin/tool/moodlenet/templates/import_confirmation.mustache
Normal file
@ -0,0 +1,76 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/import_confirmation
|
||||
|
||||
MoodleNet import confirmation template.
|
||||
|
||||
The purpose of this template is to present the user with a confirm/cancel dialog-like page.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* resourceurl The URL to the remote resource on MoodleNet.
|
||||
* resourcename The name of the remote resource on MoodleNet.
|
||||
* sesskey The CSRF token, as per sesskey()
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"course": 33,
|
||||
"coursename": "Introduction to quantum physics",
|
||||
"section": 0,
|
||||
"resourceurl": "http://example.com/test.png",
|
||||
"resourcename": "test.png",
|
||||
"sesskey": "abc123"
|
||||
}
|
||||
}}
|
||||
<div class="generalbox modal modal-dialog modal-in-page show">
|
||||
<div class="box py-3 modal-content">
|
||||
<form action="#" method="post">
|
||||
{{#course}}
|
||||
<input type="hidden" name="course" value="{{course}}">
|
||||
{{/course}}
|
||||
|
||||
<input type="hidden" name="section" value="{{section}}">
|
||||
|
||||
<input type="hidden" name="resourceurl" value="{{resourceurl}}">
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">
|
||||
<div class="box py-3 modal-header p-x-1">
|
||||
<h4>{{#str}}confirm, core{{/str}}</h4>
|
||||
</div>
|
||||
<div class="box py-3 modal-body">
|
||||
{{#course}}
|
||||
{{#str}}importconfirm, tool_moodlenet, {"resourcename": {{#quote}}{{resourcename}}{{/quote}}, "resourcetype": {{#quote}}{{resourcetype}}{{/quote}}, "coursename": {{#quote}}{{coursename}}{{/quote}} }{{/str}}
|
||||
{{/course}}
|
||||
{{^course}}
|
||||
{{#str}}importconfirmnocourse, tool_moodlenet, {"resourcename": {{#quote}}{{resourcename}}{{/quote}}, "resourcetype": {{#quote}}{{resourcetype}}{{/quote}} }{{/str}}
|
||||
{{/course}}
|
||||
|
||||
</div>
|
||||
<div class="box py-3 modal-footer">
|
||||
<div class="buttons">
|
||||
<input class="btn btn-secondary" type="submit" name="cancel" value="{{#str}}cancel, core{{/str}}">
|
||||
<input class="btn btn-primary" type="submit" name="continue" value="{{#str}}confirm, core{{/str}}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,80 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/import_options_select
|
||||
|
||||
MoodleNet import options template.
|
||||
|
||||
The purpose of this template is to render an list of import options as radio-button-like controls.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* course The course id.
|
||||
* section The sectio id.
|
||||
* resourceurl The URL to the remote resource on MoodleNet.
|
||||
* resourcename The name of the remote resource on MoodleNet.
|
||||
* sesskey The CSRF token, as per sesskey()
|
||||
* handlers The array of handler options to present the user with
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"course": 33,
|
||||
"coursename": "Introduction to quantum physics",
|
||||
"section": 0,
|
||||
"resourceurl": "http://example.com/test.png",
|
||||
"resourcename": "A test image",
|
||||
"sesskey": "abc123",
|
||||
"handlers": [
|
||||
{
|
||||
"module": "label",
|
||||
"message": "Add media to the course page"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
<div class="generalbox modal modal-dialog modal-in-page show">
|
||||
<div class="box py-3 modal-content">
|
||||
<form action="#" method="post">
|
||||
<input type="hidden" name="course" value="{{course}}">
|
||||
<input type="hidden" name="section" value="{{section}}">
|
||||
<input type="hidden" name="resourceurl" value="{{resourceurl}}">
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">
|
||||
<div class="box py-3 modal-header p-x-1">
|
||||
<h4>{{#str}}importformatselectheader, tool_moodlenet{{/str}}</h4>
|
||||
</div>
|
||||
<div class="box py-3 modal-body">
|
||||
{{#str}}importformatselectguidingtext, tool_moodlenet, {"name": {{#quote}}{{resourcename}}{{/quote}}, "type": {{#quote}}{{resourcetype}}{{/quote}} }{{/str}}
|
||||
<br><br>
|
||||
{{#handlers}}
|
||||
<input id="{{module}}_option" name="module" type="radio" value="{{module}}" {{#oneoption}}checked="checked"{{/oneoption}}> <label for="{{module}}_option">{{message}}</label>
|
||||
<br>
|
||||
{{/handlers}}
|
||||
</div>
|
||||
<div class="box py-3 modal-footer">
|
||||
<div class="buttons">
|
||||
<input class="btn btn-secondary" type="submit" name="cancel" value="Cancel">
|
||||
<input class="btn btn-primary" type="submit" name="import" value="Continue">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
58
admin/tool/moodlenet/templates/select_page.mustache
Normal file
58
admin/tool/moodlenet/templates/select_page.mustache
Normal file
@ -0,0 +1,58 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/select_page
|
||||
|
||||
This template renders the course selection page for the MoodleNet tool.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"name": "A cat picture",
|
||||
"cancellink": "https://moodlesite/my"
|
||||
}
|
||||
}}
|
||||
<div data-region="moodle-net-select">
|
||||
<div class="alert alert-primary" role="alert">
|
||||
{{#str}} notification, tool_moodlenet, {"name": {{#quote}}{{name}}{{/quote}}, "cancellink": {{#quote}}{{cancellink}}{{/quote}}, "type": {{#quote}}{{type}}{{/quote}} } {{/str}}
|
||||
</div>
|
||||
<h3>{{#str}} selectacourse {{/str}}</h3>
|
||||
<div class="searchbar input-group w-50" role="search">
|
||||
<label for="searchinput">
|
||||
<span class="sr-only">{{#str}} searchcourses, tool_moodlenet {{/str}}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
data-region="search-input"
|
||||
id="searchinput"
|
||||
class="form-control form-control-lg searchinput border-right-0 px-3 py-2"
|
||||
placeholder="{{#str}} search, core {{/str}}"
|
||||
name="search"
|
||||
autocomplete="off"
|
||||
>
|
||||
<div class="searchbar-append d-flex border border-secondary border-left-0 px-3 py-2">
|
||||
<div data-region="search-icon">
|
||||
{{#pix}} a/search, core {{/pix}}
|
||||
</div>
|
||||
<div class="clear d-none">
|
||||
<button class="btn p-0" data-region="clear-icon">
|
||||
<span class="d-flex" aria-hidden="true">{{#pix}} e/cancel, core {{/pix}}</span>
|
||||
<span class="sr-only">{{#str}} clearsearch, tool_moodlenet {{/str}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-4" data-region="mnet-courses" aria-live="polite"></div>
|
||||
</div>
|
54
admin/tool/moodlenet/templates/view-cards.mustache
Normal file
54
admin/tool/moodlenet/templates/view-cards.mustache
Normal file
@ -0,0 +1,54 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_moodlenet/view-cards
|
||||
|
||||
This template renders the cards view for the MoodleNet tool.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"courses": [
|
||||
{
|
||||
"name": "Assignment due 1",
|
||||
"viewurl": "https://moodlesite/course/view.php?id=2",
|
||||
"courseimage": "https://moodlesite/pluginfile/123/course/overviewfiles/123.jpg",
|
||||
"fullname": "course 3",
|
||||
"coursecategory": "Miscellaneous",
|
||||
"visible": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
{{< core_course/coursecards }}
|
||||
{{$coursename}}
|
||||
<span class="multiline">
|
||||
{{#shortentext}}50, {{{fullname}}} {{/shortentext}}
|
||||
</span>
|
||||
{{/coursename}}
|
||||
{{$coursecategory}}
|
||||
<span class="sr-only">
|
||||
{{#str}}aria:coursecategory, core_course{{/str}}
|
||||
</span>
|
||||
<span class="categoryname text-truncate">
|
||||
{{{coursecategory}}}
|
||||
</span>
|
||||
{{/coursecategory}}
|
||||
{{$divider}}
|
||||
<div class="pl-1 pr-1">|</div>
|
||||
{{/divider}}
|
||||
{{/ core_course/coursecards }}
|
84
admin/tool/moodlenet/tests/import_backup_helper_test.php
Normal file
84
admin/tool/moodlenet/tests/import_backup_helper_test.php
Normal file
@ -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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_backup_helper
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
/**
|
||||
* Class import_backup_helper tests
|
||||
*/
|
||||
class tool_moodlenet_import_backup_helper_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test that the first available context with the capability to upload backup files is returned.
|
||||
*/
|
||||
public function test_get_context_for_user() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
$user4 = $this->getDataGenerator()->create_user();
|
||||
$user5 = $this->getDataGenerator()->create_user();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
|
||||
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'editingteacher');
|
||||
$this->getDataGenerator()->enrol_user($user5->id, $course->id, 'student');
|
||||
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$rolerecord = $DB->get_record('role', ['shortname' => 'manager']);
|
||||
$categorycontext = context_coursecat::instance($category->id);
|
||||
$this->getDataGenerator()->role_assign($rolerecord->id, $user3->id, $categorycontext->id);
|
||||
$this->getDataGenerator()->role_assign($rolerecord->id, $user5->id, $categorycontext->id);
|
||||
|
||||
$roleid = $this->getDataGenerator()->create_role();
|
||||
$sitecontext = context_system::instance();
|
||||
assign_capability('moodle/restore:uploadfile', CAP_ALLOW, $roleid, $sitecontext->id, true);
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
$this->getDataGenerator()->role_assign($roleid, $user4->id, $sitecontext->id);
|
||||
|
||||
$result = \tool_moodlenet\local\import_backup_helper::get_context_for_user($user1->id);
|
||||
$this->assertNull($result);
|
||||
$result = \tool_moodlenet\local\import_backup_helper::get_context_for_user($user2->id);
|
||||
$this->assertEquals($result, $coursecontext);
|
||||
$this->assertEquals(CONTEXT_COURSE, $result->contextlevel);
|
||||
$result = \tool_moodlenet\local\import_backup_helper::get_context_for_user($user3->id);
|
||||
$this->assertEquals($result, $categorycontext);
|
||||
$this->assertEquals(CONTEXT_COURSECAT, $result->contextlevel);
|
||||
$result = \tool_moodlenet\local\import_backup_helper::get_context_for_user($user4->id);
|
||||
$this->assertEquals($result, $sitecontext);
|
||||
$this->assertEquals(CONTEXT_SYSTEM, $result->contextlevel);
|
||||
$result = \tool_moodlenet\local\import_backup_helper::get_context_for_user($user5->id);
|
||||
$this->assertEquals($result, $categorycontext);
|
||||
$this->assertEquals(CONTEXT_COURSECAT, $result->contextlevel);
|
||||
}
|
||||
|
||||
}
|
75
admin/tool/moodlenet/tests/import_handler_info_test.php
Normal file
75
admin/tool/moodlenet/tests/import_handler_info_test.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_handler_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\import_handler_info;
|
||||
use tool_moodlenet\local\import_strategy;
|
||||
use tool_moodlenet\local\import_strategy_file;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_handler_info_testcase, providing test cases for the import_handler_info class.
|
||||
*/
|
||||
class tool_moodlenet_import_handler_info_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test init and the getters.
|
||||
*
|
||||
* @dataProvider handler_info_data_provider
|
||||
* @param string $modname the name of the mod.
|
||||
* @param string $description description of the mod.
|
||||
* @param bool $expectexception whether we expect an exception during init or not.
|
||||
*/
|
||||
public function test_initialisation($modname, $description, $expectexception) {
|
||||
$this->resetAfterTest();
|
||||
// Skip those cases we cannot init.
|
||||
if ($expectexception) {
|
||||
$this->expectException(\coding_exception::class);
|
||||
$handlerinfo = new import_handler_info($modname, $description, new import_strategy_file());
|
||||
}
|
||||
|
||||
$handlerinfo = new import_handler_info($modname, $description, new import_strategy_file());
|
||||
|
||||
$this->assertEquals($modname, $handlerinfo->get_module_name());
|
||||
$this->assertEquals($description, $handlerinfo->get_description());
|
||||
$this->assertInstanceOf(import_strategy::class, $handlerinfo->get_strategy());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Data provider for creation of import_handler_info objects.
|
||||
*
|
||||
* @return array the data for creation of the info object.
|
||||
*/
|
||||
public function handler_info_data_provider() {
|
||||
return [
|
||||
'All data present' => ['label', 'Add a label to the course', false],
|
||||
'Empty module name' => ['', 'Add a file resource to the course', true],
|
||||
'Empty description' => ['resource', '', true],
|
||||
|
||||
];
|
||||
}
|
||||
}
|
119
admin/tool/moodlenet/tests/import_handler_registry_test.php
Normal file
119
admin/tool/moodlenet/tests/import_handler_registry_test.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_handler_registry class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\import_handler_registry;
|
||||
use tool_moodlenet\local\import_handler_info;
|
||||
use tool_moodlenet\local\import_strategy_file;
|
||||
use tool_moodlenet\local\import_strategy_link;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_handler_registry_testcase, providing test cases for the import_handler_registry class.
|
||||
*/
|
||||
class tool_moodlenet_import_handler_registry_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test confirming the behaviour of get_resource_handlers_for_strategy with different params.
|
||||
*/
|
||||
public function test_get_resource_handlers_for_strategy() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$ihr = new import_handler_registry($course, $teacher);
|
||||
$resource = new remote_resource(
|
||||
new \curl(),
|
||||
new url('http://example.org'),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource description'
|
||||
]
|
||||
);
|
||||
|
||||
$handlers = $ihr->get_resource_handlers_for_strategy($resource, new import_strategy_file());
|
||||
$this->assertIsArray($handlers);
|
||||
foreach ($handlers as $handler) {
|
||||
$this->assertInstanceOf(import_handler_info::class, $handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming that the results are scoped to the provided user.
|
||||
*/
|
||||
public function test_get_resource_handlers_for_strategy_user_scoping() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
|
||||
$studentihr = new import_handler_registry($course, $student);
|
||||
$teacherihr = new import_handler_registry($course, $teacher);
|
||||
$resource = new remote_resource(
|
||||
new \curl(),
|
||||
new url('http://example.org'),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource description'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEmpty($studentihr->get_resource_handlers_for_strategy($resource, new import_strategy_file()));
|
||||
$this->assertNotEmpty($teacherihr->get_resource_handlers_for_strategy($resource, new import_strategy_file()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming that we can find a unique handler based on the module and strategy name.
|
||||
*/
|
||||
public function test_get_resource_handler_for_module_and_strategy() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$ihr = new import_handler_registry($course, $teacher);
|
||||
$resource = new remote_resource(
|
||||
new \curl(),
|
||||
new url('http://example.org'),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource description'
|
||||
]
|
||||
);
|
||||
|
||||
// Resource handles every file type, so we'll always be able to find that unique handler when looking.
|
||||
$handler = $ihr->get_resource_handler_for_mod_and_strategy($resource, 'resource', new import_strategy_file());
|
||||
$this->assertInstanceOf(import_handler_info::class, $handler);
|
||||
|
||||
// URL handles every resource, so we'll always be able to find that unique handler when looking with a link strategy.
|
||||
$handler = $ihr->get_resource_handler_for_mod_and_strategy($resource, 'url', new import_strategy_link());
|
||||
$this->assertInstanceOf(import_handler_info::class, $handler);
|
||||
$this->assertEquals('url', $handler->get_module_name());
|
||||
$this->assertInstanceOf(import_strategy_link::class, $handler->get_strategy());
|
||||
}
|
||||
}
|
105
admin/tool/moodlenet/tests/import_info_test.php
Normal file
105
admin/tool/moodlenet/tests/import_info_test.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\import_info;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_info_testcase, providing test cases for the import_info class.
|
||||
*/
|
||||
class tool_moodlenet_import_info_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Create some test objects.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function create_test_info(): array {
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$resource = new remote_resource(new \curl(),
|
||||
new url('http://example.org'),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource summary'
|
||||
]
|
||||
);
|
||||
$importinfo = new import_info($user->id, $resource, (object)[]);
|
||||
|
||||
return [$user, $resource, $importinfo];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for creation and getters.
|
||||
*/
|
||||
public function test_getters() {
|
||||
$this->resetAfterTest();
|
||||
[$user, $resource, $importinfo] = $this->create_test_info();
|
||||
|
||||
$this->assertEquals($resource, $importinfo->get_resource());
|
||||
$this->assertEquals(new \stdClass(), $importinfo->get_config());
|
||||
$this->assertNotEmpty($importinfo->get_id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for setters.
|
||||
*/
|
||||
public function test_set_config() {
|
||||
$this->resetAfterTest();
|
||||
[$user, $resource, $importinfo] = $this->create_test_info();
|
||||
|
||||
$config = $importinfo->get_config();
|
||||
$this->assertEquals(new \stdClass(), $config);
|
||||
$config->course = 3;
|
||||
$config->section = 1;
|
||||
$importinfo->set_config($config);
|
||||
$this->assertEquals((object) ['course' => 3, 'section' => 1], $importinfo->get_config());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the object can be stored and loaded.
|
||||
*/
|
||||
public function test_persistence() {
|
||||
$this->resetAfterTest();
|
||||
[$user, $resource, $importinfo] = $this->create_test_info();
|
||||
|
||||
// Nothing to load initially since nothing has been saved.
|
||||
$loadedinfo = import_info::load($importinfo->get_id());
|
||||
$this->assertNull($loadedinfo);
|
||||
|
||||
// Now, save and confirm we can load the data into a new object.
|
||||
$importinfo->save();
|
||||
$loadedinfo2 = import_info::load($importinfo->get_id());
|
||||
$this->assertEquals($importinfo, $loadedinfo2);
|
||||
|
||||
// Purge and confirm the load returns null now.
|
||||
$importinfo->purge();
|
||||
$loadedinfo3 = import_info::load($importinfo->get_id());
|
||||
$this->assertNull($loadedinfo3);
|
||||
}
|
||||
}
|
156
admin/tool/moodlenet/tests/import_processor_test.php
Normal file
156
admin/tool/moodlenet/tests/import_processor_test.php
Normal file
@ -0,0 +1,156 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_processor class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\import_handler_registry;
|
||||
use tool_moodlenet\local\import_processor;
|
||||
use tool_moodlenet\local\import_strategy_file;
|
||||
use tool_moodlenet\local\import_strategy_link;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_processor_testcase, providing test cases for the import_processor class.
|
||||
*/
|
||||
class tool_moodlenet_import_processor_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* An integration test, this confirms the ability to construct an import processor and run the import for the current user.
|
||||
*/
|
||||
public function test_process_valid_resource() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Set up a user as a teacher in a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$section = 0;
|
||||
$this->setUser($teacher);
|
||||
|
||||
// Set up the import, using a mod_resource handler for the html extension.
|
||||
$resourceurl = $this->getExternalTestFileUrl('/test.html');
|
||||
$remoteresource = new remote_resource(
|
||||
new \curl(),
|
||||
new url($resourceurl),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource description'
|
||||
]
|
||||
);
|
||||
$handlerregistry = new import_handler_registry($course, $teacher);
|
||||
$handlerinfo = $handlerregistry->get_resource_handler_for_mod_and_strategy($remoteresource, 'resource',
|
||||
new import_strategy_file());
|
||||
$importproc = new import_processor($course, $section, $remoteresource, $handlerinfo, $handlerregistry);
|
||||
|
||||
// Import the file.
|
||||
$importproc->process();
|
||||
|
||||
// Verify there is a new mod_resource created with correct name, description and containing the test.html file.
|
||||
$modinfo = get_fast_modinfo($course, $teacher->id);
|
||||
$cms = $modinfo->get_instances();
|
||||
$this->assertArrayHasKey('resource', $cms);
|
||||
$cminfo = array_shift($cms['resource']);
|
||||
$this->assertEquals('Resource name', $cminfo->get_formatted_name());
|
||||
$cm = get_coursemodule_from_id('', $cminfo->id, 0, false, MUST_EXIST);
|
||||
list($cm, $context, $module, $data, $cw) = get_moduleinfo_data($cminfo, $course);
|
||||
$this->assertEquals($remoteresource->get_description(), $data->intro);
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files(\context_module::instance($cminfo->id)->id, 'mod_resource', 'content', false,
|
||||
'sortorder DESC, id ASC', false);
|
||||
$file = reset($files);
|
||||
$this->assertEquals('test.html', $file->get_filename());
|
||||
$this->assertEquals('text/html', $file->get_mimetype());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming that an exception is thrown when trying to process a resource which does not exist.
|
||||
*/
|
||||
public function test_process_invalid_resource() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Set up a user as a teacher in a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$section = 0;
|
||||
$this->setUser($teacher);
|
||||
|
||||
// Set up the import, using a mod_resource handler for the html extension.
|
||||
$resourceurl = $this->getExternalTestFileUrl('/test.htmlzz');
|
||||
$remoteresource = new remote_resource(
|
||||
new \curl(),
|
||||
new url($resourceurl),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource description'
|
||||
]
|
||||
);
|
||||
$handlerregistry = new import_handler_registry($course, $teacher);
|
||||
$handlerinfo = $handlerregistry->get_resource_handler_for_mod_and_strategy($remoteresource, 'resource',
|
||||
new import_strategy_file());
|
||||
$importproc = new import_processor($course, $section, $remoteresource, $handlerinfo, $handlerregistry);
|
||||
|
||||
// Import the file.
|
||||
$this->expectException(\coding_exception::class);
|
||||
$importproc->process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming that imports can be completed using alternative import strategies.
|
||||
*/
|
||||
public function test_process_alternative_import_strategies() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Set up a user as a teacher in a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$section = 0;
|
||||
$this->setUser($teacher);
|
||||
|
||||
// Set up the import, using a mod_url handler and the link import strategy.
|
||||
$remoteresource = new remote_resource(
|
||||
new \curl(),
|
||||
new url('http://example.com/cats.pdf'),
|
||||
(object) [
|
||||
'name' => 'Resource name',
|
||||
'description' => 'Resource description'
|
||||
]
|
||||
);
|
||||
$handlerregistry = new import_handler_registry($course, $teacher);
|
||||
$handlerinfo = $handlerregistry->get_resource_handler_for_mod_and_strategy($remoteresource, 'url',
|
||||
new import_strategy_link());
|
||||
$importproc = new import_processor($course, $section, $remoteresource, $handlerinfo, $handlerregistry);
|
||||
|
||||
// Import the resource as a link.
|
||||
$importproc->process();
|
||||
|
||||
// Verify there is a new mod_url created with name 'cats' and containing the URL of the resource.
|
||||
$modinfo = get_fast_modinfo($course, $teacher->id);
|
||||
$cms = $modinfo->get_instances();
|
||||
$this->assertArrayHasKey('url', $cms);
|
||||
$cminfo = array_shift($cms['url']);
|
||||
$this->assertEquals('Resource name', $cminfo->get_formatted_name());
|
||||
}
|
||||
}
|
80
admin/tool/moodlenet/tests/lib_test.php
Normal file
80
admin/tool/moodlenet/tests/lib_test.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for tool_moodlenet lib
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Peter Dias
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/admin/tool/moodlenet/lib.php');
|
||||
|
||||
/**
|
||||
* Test moodlenet functions
|
||||
*/
|
||||
class tool_moodlenet_lib_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the generate_mnet_endpoint function
|
||||
*
|
||||
* @dataProvider get_endpoints_provider
|
||||
* @param string $profileurl
|
||||
* @param int $course
|
||||
* @param int $section
|
||||
* @param string $expected
|
||||
*/
|
||||
public function test_generate_mnet_endpoint($profileurl, $course, $section, $expected) {
|
||||
$endpoint = generate_mnet_endpoint($profileurl, $course, $section);
|
||||
$this->assertEquals($expected, $endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dataprovider for test_generate_mnet_endpoint
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_endpoints_provider() {
|
||||
global $CFG;
|
||||
return [
|
||||
[
|
||||
'@name@domain.name',
|
||||
1,
|
||||
2,
|
||||
'https://domain.name/' . MOODLENET_DEFAULT_ENDPOINT . '?site=' . urlencode($CFG->wwwroot)
|
||||
. '&course=1§ion=2'
|
||||
],
|
||||
[
|
||||
'@profile@name@domain.name',
|
||||
1,
|
||||
2,
|
||||
'https://domain.name/' . MOODLENET_DEFAULT_ENDPOINT . '?site=' . urlencode($CFG->wwwroot)
|
||||
. '&course=1§ion=2'
|
||||
],
|
||||
[
|
||||
'https://domain.name',
|
||||
1,
|
||||
2,
|
||||
'https://domain.name/' . MOODLENET_DEFAULT_ENDPOINT . '?site=' . urlencode($CFG->wwwroot)
|
||||
. '&course=1§ion=2'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
142
admin/tool/moodlenet/tests/profile_manager_test.php
Normal file
142
admin/tool/moodlenet/tests/profile_manager_test.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the profile manager
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Adrian Greeve <adrian@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
/**
|
||||
* Class profile_manager tests
|
||||
*/
|
||||
class tool_moodlenet_profile_manager_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test that on this site we use the user table to hold moodle net profile information.
|
||||
*/
|
||||
public function test_official_profile_exists() {
|
||||
$this->assertTrue(\tool_moodlenet\profile_manager::official_profile_exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a null is returned when the user's mnet profile field is not set.
|
||||
*/
|
||||
public function test_get_moodlenet_user_profile_no_profile_set() {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
|
||||
$result = \tool_moodlenet\profile_manager::get_moodlenet_user_profile($user->id);
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a null is returned when the user's mnet profile field is not set.
|
||||
*/
|
||||
public function test_moodlenet_user_profile_creation_no_profile_set() {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
|
||||
$this->expectException(moodle_exception::class);
|
||||
$this->expectExceptionMessage(get_string('invalidmoodlenetprofile', 'tool_moodlenet'));
|
||||
$result = new \tool_moodlenet\moodlenet_user_profile("", $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the return of a moodle net profile.
|
||||
*/
|
||||
public function test_get_moodlenet_user_profile() {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user(['moodlenetprofile' => '@matt@hq.mnet']);
|
||||
|
||||
$result = \tool_moodlenet\profile_manager::get_moodlenet_user_profile($user->id);
|
||||
$this->assertEquals($user->moodlenetprofile, $result->get_profile_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the creation of a user profile category.
|
||||
*/
|
||||
public function test_create_user_profile_category() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$basecategoryname = get_string('pluginname', 'tool_moodlenet');
|
||||
|
||||
\tool_moodlenet\profile_manager::create_user_profile_category();
|
||||
$categoryname = \tool_moodlenet\profile_manager::get_category_name();
|
||||
$this->assertEquals($basecategoryname, $categoryname);
|
||||
\tool_moodlenet\profile_manager::create_user_profile_category();
|
||||
|
||||
$recordcount = $DB->count_records('user_info_category', ['name' => $basecategoryname]);
|
||||
$this->assertEquals(1, $recordcount);
|
||||
|
||||
// Test the duplication of categories to ensure a unique name is always used.
|
||||
$categoryname = \tool_moodlenet\profile_manager::get_category_name();
|
||||
$this->assertEquals($basecategoryname . 1, $categoryname);
|
||||
\tool_moodlenet\profile_manager::create_user_profile_category();
|
||||
$categoryname = \tool_moodlenet\profile_manager::get_category_name();
|
||||
$this->assertEquals($basecategoryname . 2, $categoryname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the creating of the custom user profile field to hold the moodle net profile.
|
||||
*/
|
||||
public function test_create_user_profile_text_field() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$shortname = 'mnetprofile';
|
||||
|
||||
$categoryid = \tool_moodlenet\profile_manager::create_user_profile_category();
|
||||
\tool_moodlenet\profile_manager::create_user_profile_text_field($categoryid);
|
||||
|
||||
$record = $DB->get_record('user_info_field', ['shortname' => $shortname]);
|
||||
$this->assertEquals($shortname, $record->shortname);
|
||||
$this->assertEquals($categoryid, $record->categoryid);
|
||||
|
||||
// Test for a unique name if 'mnetprofile' is already in use.
|
||||
\tool_moodlenet\profile_manager::create_user_profile_text_field($categoryid);
|
||||
$profilename = \tool_moodlenet\profile_manager::get_profile_field_name();
|
||||
$this->assertEquals($shortname . 1, $profilename);
|
||||
\tool_moodlenet\profile_manager::create_user_profile_text_field($categoryid);
|
||||
$profilename = \tool_moodlenet\profile_manager::get_profile_field_name();
|
||||
$this->assertEquals($shortname . 2, $profilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the user moodlenet profile is saved.
|
||||
*/
|
||||
public function test_save_moodlenet_user_profile() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$profilename = '@matt@hq.mnet';
|
||||
|
||||
$moodlenetprofile = new \tool_moodlenet\moodlenet_user_profile($profilename, $user->id);
|
||||
|
||||
\tool_moodlenet\profile_manager::save_moodlenet_user_profile($moodlenetprofile);
|
||||
|
||||
$userdata = \core_user::get_user($user->id);
|
||||
$this->assertEquals($profilename, $userdata->moodlenetprofile);
|
||||
}
|
||||
}
|
115
admin/tool/moodlenet/tests/remote_resource_test.php
Normal file
115
admin/tool/moodlenet/tests/remote_resource_test.php
Normal file
@ -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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the remote_resource class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_remote_resource_testcase, providing test cases for the remote_resource class.
|
||||
*/
|
||||
class tool_moodlenet_remote_resource_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test getters.
|
||||
*
|
||||
* @dataProvider remote_resource_data_provider
|
||||
* @param string $url the url of the resource.
|
||||
* @param string $metadata the resource metadata like name, description, etc.
|
||||
* @param string $expectedextension the extension we expect to find when querying the remote resource.
|
||||
*/
|
||||
public function test_getters($url, $metadata, $expectedextension) {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$remoteres = new remote_resource(new \curl(), new url($url), $metadata);
|
||||
|
||||
$this->assertEquals(new url($url), $remoteres->get_url());
|
||||
$this->assertEquals($metadata->name, $remoteres->get_name());
|
||||
$this->assertEquals($metadata->description, $remoteres->get_description());
|
||||
$this->assertEquals($expectedextension, $remoteres->get_extension());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider generating remote urls.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function remote_resource_data_provider() {
|
||||
return [
|
||||
'With filename and extension' => [
|
||||
$this->getExternalTestFileUrl('/test.html'),
|
||||
(object) [
|
||||
'name' => 'Test html file',
|
||||
'description' => 'Full description of the html file'
|
||||
],
|
||||
'html'
|
||||
],
|
||||
'With filename only' => [
|
||||
'http://example.com/path/file',
|
||||
(object) [
|
||||
'name' => 'Test html file',
|
||||
'description' => 'Full description of the html file'
|
||||
],
|
||||
''
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming the network based operations of a remote_resource.
|
||||
*/
|
||||
public function test_network_features() {
|
||||
$url = $this->getExternalTestFileUrl('/test.html');
|
||||
$nonexistenturl = $this->getExternalTestFileUrl('/test.htmlzz');
|
||||
|
||||
$remoteres = new remote_resource(
|
||||
new \curl(),
|
||||
new url($url),
|
||||
(object) [
|
||||
'name' => 'Test html file',
|
||||
'description' => 'Some description'
|
||||
]
|
||||
);
|
||||
$nonexistentremoteres = new remote_resource(
|
||||
new \curl(),
|
||||
new url($nonexistenturl),
|
||||
(object) [
|
||||
'name' => 'Test html file',
|
||||
'description' => 'Some description'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertGreaterThan(0, $remoteres->get_download_size());
|
||||
[$path, $name] = $remoteres->download_to_requestdir();
|
||||
$this->assertIsString($path);
|
||||
$this->assertEquals('test.html', $name);
|
||||
$this->assertFileExists($path . '/' . $name);
|
||||
|
||||
$this->expectException(\coding_exception::class);
|
||||
$nonexistentremoteres->get_download_size();
|
||||
}
|
||||
}
|
103
admin/tool/moodlenet/tests/url_test.php
Normal file
103
admin/tool/moodlenet/tests/url_test.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the url class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_url_testcase, providing test cases for the url class.
|
||||
*/
|
||||
class tool_moodlenet_url_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the parsing to host + path components.
|
||||
*
|
||||
* @dataProvider url_provider
|
||||
* @param string $urlstring The full URL string
|
||||
* @param string $host the expected host component of the URL.
|
||||
* @param string $path the expected path component of the URL.
|
||||
* @param bool $exception whether or not an exception is expected during construction.
|
||||
*/
|
||||
public function test_parsing($urlstring, $host, $path, $exception) {
|
||||
if ($exception) {
|
||||
$this->expectException(\coding_exception::class);
|
||||
$url = new url($urlstring);
|
||||
return;
|
||||
}
|
||||
|
||||
$url = new url($urlstring);
|
||||
$this->assertEquals($urlstring, $url->get_value());
|
||||
$this->assertEquals($host, $url->get_host());
|
||||
$this->assertEquals($path, $url->get_path());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function url_provider() {
|
||||
return [
|
||||
'No path' => [
|
||||
'url' => 'https://example.moodle.net',
|
||||
'host' => 'example.moodle.net',
|
||||
'path' => null,
|
||||
'exception' => false,
|
||||
],
|
||||
'Slash path' => [
|
||||
'url' => 'https://example.moodle.net/',
|
||||
'host' => 'example.moodle.net',
|
||||
'path' => '/',
|
||||
'exception' => false,
|
||||
],
|
||||
'Path includes file and extension' => [
|
||||
'url' => 'https://example.moodle.net/uploads/123456789/pic.png',
|
||||
'host' => 'example.moodle.net',
|
||||
'path' => '/uploads/123456789/pic.png',
|
||||
'exception' => false,
|
||||
],
|
||||
'Path includes file, extension and params' => [
|
||||
'url' => 'https://example.moodle.net/uploads/123456789/pic.png?option=1&option2=test',
|
||||
'host' => 'example.moodle.net',
|
||||
'path' => '/uploads/123456789/pic.png',
|
||||
'exception' => false,
|
||||
],
|
||||
'Malformed - invalid' => [
|
||||
'url' => 'invalid',
|
||||
'host' => null,
|
||||
'path' => null,
|
||||
'exception' => true,
|
||||
],
|
||||
'Direct, non-encoded utf8 - invalid' => [
|
||||
'url' => 'http://москва.рф/services/',
|
||||
'host' => 'москва.рф',
|
||||
'path' => '/services/',
|
||||
'exception' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
30
admin/tool/moodlenet/version.php
Normal file
30
admin/tool/moodlenet/version.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?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 file for tool_moodlenet
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = 'tool_moodlenet';
|
||||
$plugin->version = 2020060500;
|
||||
$plugin->requires = 2020022800.01;
|
||||
$plugin->maturity = MATURITY_ALPHA;
|
@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{^showFooter}}
|
||||
<div class="fixed-bottom position-absolute py-3 px-4 border-top">
|
||||
<div class="fixed-bottom position-absolute py-3 px-4 border-top modal-footer">
|
||||
{{>core_course/local/activitychooser/footer_partial}}
|
||||
</div>
|
||||
{{/showFooter}}
|
||||
|
@ -1639,6 +1639,7 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
|
||||
.modchooser .modal-footer {
|
||||
height: 70px;
|
||||
background: $modal-content-bg;
|
||||
.moodlenet-logo {
|
||||
.icon {
|
||||
height: 2.5rem;
|
||||
|
@ -11002,7 +11002,8 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
margin: 1em auto; }
|
||||
|
||||
.modchooser .modal-footer {
|
||||
height: 70px; }
|
||||
height: 70px;
|
||||
background: #fff; }
|
||||
.modchooser .modal-footer .moodlenet-logo .icon {
|
||||
height: 2.5rem;
|
||||
width: 6rem;
|
||||
|
@ -11209,7 +11209,8 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
margin: 1em auto; }
|
||||
|
||||
.modchooser .modal-footer {
|
||||
height: 70px; }
|
||||
height: 70px;
|
||||
background: #fff; }
|
||||
.modchooser .modal-footer .moodlenet-logo .icon {
|
||||
height: 2.5rem;
|
||||
width: 6rem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user