mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-71953 calendar: Accessibility improvement for manage subscription
- Create new web services for manage subscription (Update calendar subscription) - Modified delete subscription feature to use Web service. - Midified update subscription feature to use in-place editbale - Delete subscription feature now have a confirmation box before processing. - Fixed some accessibility issues - Used 'Delete' instead of 'Remove' for deleting subscriptions
This commit is contained in:
parent
8885e22a0b
commit
bca6b06a1c
2
calendar/amd/build/manage_subscriptions.min.js
vendored
Normal file
2
calendar/amd/build/manage_subscriptions.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_calendar/manage_subscriptions",["exports","core_calendar/selectors","core_calendar/repository","core/modal_factory","core/modal_events","core/notification","core/prefetch","core/str","core/local/inplace_editable/events"],function(a,b,c,d,e,f,g,h,i){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=k(b);c=k(c);d=k(d);e=k(e);g=function(a){return a&&a.__esModule?a:{default:a}}(g);function j(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;j=function(){return a};return a}function k(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=j();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function l(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function m(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){l(h,d,e,f,g,"next",a)}function g(a){l(h,d,e,f,g,"throw",a)}f(void 0)})}}var n=function(a){return parseInt(a.closest("tr").dataset.subid)},o=function(a){return a.closest("tr").dataset.subname},p=function(a){return document.querySelector("tr[data-subid=\"".concat(a,"\"]"))},q=function(a,b){var c=o(a);return d.create({type:d.types.SAVE_CANCEL,title:(0,h.get_string)("confirmation","admin"),body:(0,h.get_string)(b,"calendar",c),buttons:{save:(0,h.get_string)("yes")}}).then(function(b){b.getRoot().on(e.hidden,function(){a.focus()});b.show();return b})},r=function(){var a=m(regeneratorRuntime.mark(function a(b,c){var d,e,g;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:d=o(b);if(!c.status){a.next=7;break}a.next=4;return(0,h.get_string)("subscriptionremoved","calendar",d);case 4:a.t0=a.sent;a.next=8;break;case 7:a.t0=c.warnings[0].message;case 8:e=a.t0;g=c.status?"info":"error";return a.abrupt("return",(0,f.addNotification)({message:e,type:g}));case 11:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),s=function(){document.addEventListener("click",function(a){var d=a.target.closest(b.actions.deleteSubscription);if(d){a.preventDefault();var g=q(d,"confirmsubscriptiondelete");g.then(function(a){a.getRoot().on(e.save,function(){var a=n(d);c.deleteSubscription(a).then(function(b){var c=r(d,b);return c.then(function(){var b=p(a);return b.remove()})}).catch(f.displayException)});return a}).catch(f.displayException)}});document.addEventListener(i.eventTypes.elementUpdated,function(a){var b=a.target;if("core_calendar"==b.getAttribute("data-component")){(0,f.fetchNotifications)()}})},t=function(){g.default.prefetchStrings("moodle",["yes"]);g.default.prefetchStrings("core_admin",["confirmation"]);g.default.prefetchStrings("core_calendar",["confirmsubscriptiondelete","subscriptionremoved"]);s()};a.init=t});
|
||||
//# sourceMappingURL=manage_subscriptions.min.js.map
|
1
calendar/amd/build/manage_subscriptions.min.js.map
Normal file
1
calendar/amd/build/manage_subscriptions.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
calendar/amd/build/repository.min.js
vendored
2
calendar/amd/build/repository.min.js
vendored
@ -1,2 +1,2 @@
|
||||
define ("core_calendar/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.getCourseGroupsData=a.getCalendarUpcomingData=a.updateEventStartDay=a.getCalendarDayData=a.getCalendarMonthData=a.submitCreateUpdateForm=a.getEventById=a.deleteEvent=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){var c=1<arguments.length&&arguments[1]!==void 0?arguments[1]:!1;return b.default.call([{methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:a,repeat:c}]}}])[0]};a.deleteEvent=c;var d=function(a){return b.default.call([{methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}}])[0]};a.getEventById=d;var e=function(a){return b.default.call([{methodname:"core_calendar_submit_create_update_form",args:{formdata:a}}])[0]};a.submitCreateUpdateForm=e;var f=function(a,c,d,e,f,g){var h=6<arguments.length&&arguments[6]!==void 0?arguments[6]:1,i=7<arguments.length&&arguments[7]!==void 0?arguments[7]:"month";return b.default.call([{methodname:"core_calendar_get_calendar_monthly_view",args:{year:a,month:c,courseid:d,categoryid:e,includenavigation:f,mini:g,day:h,view:i}}])[0]};a.getCalendarMonthData=f;var g=function(a,c,d,e,f){return b.default.call([{methodname:"core_calendar_get_calendar_day_view",args:{year:a,month:c,day:d,courseid:e,categoryid:f}}])[0]};a.getCalendarDayData=g;var h=function(a,c){return b.default.call([{methodname:"core_calendar_update_event_start_day",args:{eventid:a,daytimestamp:c}}])[0]};a.updateEventStartDay=h;var i=function(a,c){return b.default.call([{methodname:"core_calendar_get_calendar_upcoming_view",args:{courseid:a,categoryid:c}}])[0]};a.getCalendarUpcomingData=i;var j=function(a){return b.default.call([{methodname:"core_group_get_course_groups",args:{courseid:a}}])[0]};a.getCourseGroupsData=j});
|
||||
define ("core_calendar/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.deleteSubscription=a.getCourseGroupsData=a.getCalendarUpcomingData=a.updateEventStartDay=a.getCalendarDayData=a.getCalendarMonthData=a.submitCreateUpdateForm=a.getEventById=a.deleteEvent=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){var c=1<arguments.length&&arguments[1]!==void 0?arguments[1]:!1;return b.default.call([{methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:a,repeat:c}]}}])[0]};a.deleteEvent=c;var d=function(a){return b.default.call([{methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}}])[0]};a.getEventById=d;var e=function(a){return b.default.call([{methodname:"core_calendar_submit_create_update_form",args:{formdata:a}}])[0]};a.submitCreateUpdateForm=e;var f=function(a,c,d,e,f,g){var h=6<arguments.length&&arguments[6]!==void 0?arguments[6]:1,i=7<arguments.length&&arguments[7]!==void 0?arguments[7]:"month";return b.default.call([{methodname:"core_calendar_get_calendar_monthly_view",args:{year:a,month:c,courseid:d,categoryid:e,includenavigation:f,mini:g,day:h,view:i}}])[0]};a.getCalendarMonthData=f;var g=function(a,c,d,e,f){return b.default.call([{methodname:"core_calendar_get_calendar_day_view",args:{year:a,month:c,day:d,courseid:e,categoryid:f}}])[0]};a.getCalendarDayData=g;var h=function(a,c){return b.default.call([{methodname:"core_calendar_update_event_start_day",args:{eventid:a,daytimestamp:c}}])[0]};a.updateEventStartDay=h;var i=function(a,c){return b.default.call([{methodname:"core_calendar_get_calendar_upcoming_view",args:{courseid:a,categoryid:c}}])[0]};a.getCalendarUpcomingData=i;var j=function(a){return b.default.call([{methodname:"core_group_get_course_groups",args:{courseid:a}}])[0]};a.getCourseGroupsData=j;var k=function(a){return b.default.call([{methodname:"core_calendar_delete_subscription",args:{subscriptionid:a}}])[0]};a.deleteSubscription=k});
|
||||
//# sourceMappingURL=repository.min.js.map
|
||||
|
File diff suppressed because one or more lines are too long
2
calendar/amd/build/selectors.min.js
vendored
2
calendar/amd/build/selectors.min.js
vendored
@ -1,2 +1,2 @@
|
||||
define ("core_calendar/selectors",[],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]",other:"[data-eventtype-other]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:"select[name=\"course\"]",viewSelector:"div[data-region=\"view-selector\"]",actions:{create:"[data-action=\"new-event-button\"]",edit:"[data-action=\"edit\"]",remove:"[data-action=\"delete\"]",viewEvent:"[data-action=\"view-event\"]"},elements:{courseSelector:"select[name=\"course\"]",dateContainer:".clickable.hasevent",dateContent:"[data-region=\"day-content\"]"},today:".today",day:"[data-region=\"day\"]",calendarMain:"[data-region=\"calendar\"]",wrapper:".calendarwrapper",eventItem:"[data-type=\"event\"]",links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']"},containers:{loadingIcon:"[data-region=\"overlay-icon-container\"]"},fullCalendarView:"page-calendar-view"}});
|
||||
define ("core_calendar/selectors",[],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]",other:"[data-eventtype-other]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:"select[name=\"course\"]",viewSelector:"div[data-region=\"view-selector\"]",actions:{create:"[data-action=\"new-event-button\"]",edit:"[data-action=\"edit\"]",remove:"[data-action=\"delete\"]",viewEvent:"[data-action=\"view-event\"]",deleteSubscription:"[data-action=\"delete-subscription\"]"},elements:{courseSelector:"select[name=\"course\"]",dateContainer:".clickable.hasevent",dateContent:"[data-region=\"day-content\"]"},today:".today",day:"[data-region=\"day\"]",calendarMain:"[data-region=\"calendar\"]",wrapper:".calendarwrapper",eventItem:"[data-type=\"event\"]",links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']"},containers:{loadingIcon:"[data-region=\"overlay-icon-container\"]"},fullCalendarView:"page-calendar-view"}});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"sources":["../src/selectors.js"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","elements","dateContainer","dateContent","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","fullCalendarView"],"mappings":"AAsBAA,OAAM,2BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,eAAe,CAAE,mCADd,CAEHC,SAAS,CAAE,CACPC,IAAI,CAAE,uBADC,CAEPC,QAAQ,CAAE,2BAFH,CAGPC,MAAM,CAAE,yBAHD,CAIPC,KAAK,CAAE,wBAJA,CAKPC,IAAI,CAAE,uBALC,CAMPC,KAAK,CAAE,wBANA,CAFR,CAUHC,WAAW,CAAE,CACTN,IAAI,CAAE,+BADG,CAETC,QAAQ,CAAE,mCAFD,CAGTC,MAAM,CAAE,iCAHC,CAITC,KAAK,CAAE,gCAJE,CAKTC,IAAI,CAAE,+BALG,CAMTC,KAAK,CAAE,gCANE,CAVV,CAkBHE,eAAe,CAAE,CACbC,KAAK,CAAE,uBADM,CAlBd,CAqBHC,cAAc,CAAE,yBArBb,CAsBHC,YAAY,CAAE,oCAtBX,CAuBHC,OAAO,CAAE,CACLC,MAAM,CAAE,oCADH,CAELC,IAAI,CAAE,wBAFD,CAGLC,MAAM,CAAE,0BAHH,CAILC,SAAS,CAAE,8BAJN,CAvBN,CA6BHC,QAAQ,CAAE,CACNP,cAAc,CAAE,yBADV,CAENQ,aAAa,CAAE,qBAFT,CAGNC,WAAW,CAAE,+BAHP,CA7BP,CAkCHC,KAAK,CAAE,QAlCJ,CAmCHC,GAAG,CAAE,uBAnCF,CAoCHC,YAAY,CAAE,4BApCX,CAqCHC,OAAO,CAAE,kBArCN,CAsCHC,SAAS,CAAE,uBAtCR,CAuCHC,KAAK,CAAE,CACHC,OAAO,CAAE,8BADN,CAEHC,SAAS,CAAE,4BAFR,CAGHC,WAAW,CAAE,+BAHV,CAvCJ,CA4CHC,UAAU,CAAE,CACRC,WAAW,CAAE,0CADL,CA5CT,CA+CHC,gBAAgB,CAAE,oBA/Cf,CAiDV,CAlDK,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 * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_selectors\n * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"file":"selectors.min.js"}
|
||||
{"version":3,"sources":["../src/selectors.js"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","fullCalendarView"],"mappings":"AAsBAA,OAAM,2BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,eAAe,CAAE,mCADd,CAEHC,SAAS,CAAE,CACPC,IAAI,CAAE,uBADC,CAEPC,QAAQ,CAAE,2BAFH,CAGPC,MAAM,CAAE,yBAHD,CAIPC,KAAK,CAAE,wBAJA,CAKPC,IAAI,CAAE,uBALC,CAMPC,KAAK,CAAE,wBANA,CAFR,CAUHC,WAAW,CAAE,CACTN,IAAI,CAAE,+BADG,CAETC,QAAQ,CAAE,mCAFD,CAGTC,MAAM,CAAE,iCAHC,CAITC,KAAK,CAAE,gCAJE,CAKTC,IAAI,CAAE,+BALG,CAMTC,KAAK,CAAE,gCANE,CAVV,CAkBHE,eAAe,CAAE,CACbC,KAAK,CAAE,uBADM,CAlBd,CAqBHC,cAAc,CAAE,yBArBb,CAsBHC,YAAY,CAAE,oCAtBX,CAuBHC,OAAO,CAAE,CACLC,MAAM,CAAE,oCADH,CAELC,IAAI,CAAE,wBAFD,CAGLC,MAAM,CAAE,0BAHH,CAILC,SAAS,CAAE,8BAJN,CAKLC,kBAAkB,CAAE,uCALf,CAvBN,CA8BHC,QAAQ,CAAE,CACNR,cAAc,CAAE,yBADV,CAENS,aAAa,CAAE,qBAFT,CAGNC,WAAW,CAAE,+BAHP,CA9BP,CAmCHC,KAAK,CAAE,QAnCJ,CAoCHC,GAAG,CAAE,uBApCF,CAqCHC,YAAY,CAAE,4BArCX,CAsCHC,OAAO,CAAE,kBAtCN,CAuCHC,SAAS,CAAE,uBAvCR,CAwCHC,KAAK,CAAE,CACHC,OAAO,CAAE,8BADN,CAEHC,SAAS,CAAE,4BAFR,CAGHC,WAAW,CAAE,+BAHV,CAxCJ,CA6CHC,UAAU,CAAE,CACRC,WAAW,CAAE,0CADL,CA7CT,CAgDHC,gBAAgB,CAAE,oBAhDf,CAkDV,CAnDK,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 * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_selectors\n * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"file":"selectors.min.js"}
|
145
calendar/amd/src/manage_subscriptions.js
Normal file
145
calendar/amd/src/manage_subscriptions.js
Normal file
@ -0,0 +1,145 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A module to handle Delete/Update operations of the manage subscription page.
|
||||
*
|
||||
* @module core_calendar/manage_subscriptions
|
||||
* @copyright 2021 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since 4.0
|
||||
*/
|
||||
|
||||
import * as CalendarSelectors from 'core_calendar/selectors';
|
||||
import * as CalendarRepository from 'core_calendar/repository';
|
||||
import * as Modal from 'core/modal_factory';
|
||||
import * as ModalEvents from 'core/modal_events';
|
||||
import {displayException, addNotification, fetchNotifications} from 'core/notification';
|
||||
import Prefetch from 'core/prefetch';
|
||||
import {get_string as getString} from 'core/str';
|
||||
import {eventTypes} from 'core/local/inplace_editable/events';
|
||||
|
||||
/**
|
||||
* Get subscription id for given element.
|
||||
*
|
||||
* @param {HTMLElement} element update/delete link
|
||||
* @return {Number}
|
||||
*/
|
||||
const getSubscriptionId = element => {
|
||||
return parseInt(element.closest('tr').dataset.subid);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get subscription name for given element.
|
||||
*
|
||||
* @param {HTMLElement} element update/delete link
|
||||
* @return {String}
|
||||
*/
|
||||
const getSubscriptionName = element => {
|
||||
return element.closest('tr').dataset.subname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get subscription table row for subscription id.
|
||||
*
|
||||
* @param {string} subscriptionId Subscription id
|
||||
* @return {Element}
|
||||
*/
|
||||
const getSubscriptionRow = subscriptionId => {
|
||||
return document.querySelector(`tr[data-subid="${subscriptionId}"]`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create modal.
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {string} messageCode Message code.
|
||||
* @return {promise} Promise for modal
|
||||
*/
|
||||
const createModal = (element, messageCode) => {
|
||||
const subscriptionName = getSubscriptionName(element);
|
||||
return Modal.create({
|
||||
type: Modal.types.SAVE_CANCEL,
|
||||
title: getString('confirmation', 'admin'),
|
||||
body: getString(messageCode, 'calendar', subscriptionName),
|
||||
buttons: {
|
||||
save: getString('yes')
|
||||
},
|
||||
}).then(modal => {
|
||||
modal.getRoot().on(ModalEvents.hidden, () => {
|
||||
element.focus();
|
||||
});
|
||||
modal.show();
|
||||
return modal;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Response handler for delete action.
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {Object} data
|
||||
* @return {Promise}
|
||||
*/
|
||||
const responseHandlerForDelete = async(element, data) => {
|
||||
const subscriptionName = getSubscriptionName(element);
|
||||
const message = data.status ? await getString('subscriptionremoved', 'calendar', subscriptionName) : data.warnings[0].message;
|
||||
const type = data.status ? 'info' : 'error';
|
||||
return addNotification({message, type});
|
||||
};
|
||||
|
||||
/**
|
||||
* Register events for update/delete links.
|
||||
*/
|
||||
const registerEventListeners = () => {
|
||||
document.addEventListener('click', e => {
|
||||
const deleteAction = e.target.closest(CalendarSelectors.actions.deleteSubscription);
|
||||
if (deleteAction) {
|
||||
e.preventDefault();
|
||||
const modalPromise = createModal(deleteAction, 'confirmsubscriptiondelete');
|
||||
modalPromise.then(modal => {
|
||||
modal.getRoot().on(ModalEvents.save, () => {
|
||||
const subscriptionId = getSubscriptionId(deleteAction);
|
||||
CalendarRepository.deleteSubscription(subscriptionId).then(data => {
|
||||
const response = responseHandlerForDelete(deleteAction, data);
|
||||
return response.then(() => {
|
||||
const subscriptionRow = getSubscriptionRow(subscriptionId);
|
||||
return subscriptionRow.remove();
|
||||
});
|
||||
}).catch(displayException);
|
||||
});
|
||||
|
||||
return modal;
|
||||
}).catch(displayException);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener(eventTypes.elementUpdated, e => {
|
||||
const inplaceEditable = e.target;
|
||||
if (inplaceEditable.getAttribute('data-component') == 'core_calendar') {
|
||||
fetchNotifications();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialises.
|
||||
*/
|
||||
export const init = () => {
|
||||
Prefetch.prefetchStrings('moodle', ['yes']);
|
||||
Prefetch.prefetchStrings('core_admin', ['confirmation']);
|
||||
Prefetch.prefetchStrings('core_calendar', ['confirmsubscriptiondelete', 'subscriptionremoved']);
|
||||
registerEventListeners();
|
||||
};
|
@ -196,3 +196,20 @@ export const getCourseGroupsData = (courseId) => {
|
||||
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete calendar subscription by id.
|
||||
*
|
||||
* @param {Number} subscriptionId The subscription id
|
||||
* @return {promise}
|
||||
*/
|
||||
export const deleteSubscription = (subscriptionId) => {
|
||||
const request = {
|
||||
methodname: 'core_calendar_delete_subscription',
|
||||
args: {
|
||||
subscriptionid: subscriptionId
|
||||
}
|
||||
};
|
||||
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
@ -49,6 +49,7 @@ define([], function() {
|
||||
edit: '[data-action="edit"]',
|
||||
remove: '[data-action="delete"]',
|
||||
viewEvent: '[data-action="view-event"]',
|
||||
deleteSubscription: '[data-action="delete-subscription"]',
|
||||
},
|
||||
elements: {
|
||||
courseSelector: 'select[name="course"]',
|
||||
|
@ -101,19 +101,6 @@ class event_exporter_base extends exporter {
|
||||
if ($cm = $event->get_course_module()) {
|
||||
$data->modulename = $cm->get('modname');
|
||||
$data->instance = $cm->get('id');
|
||||
$data->activityname = $cm->get('name');
|
||||
|
||||
$component = 'mod_' . $data->modulename;
|
||||
if (!component_callback_exists($component, 'core_calendar_get_event_action_string')) {
|
||||
$modulename = get_string('modulename', $data->modulename);
|
||||
$data->activitystr = get_string('requiresaction', 'calendar', $modulename);
|
||||
} else {
|
||||
$data->activitystr = component_callback(
|
||||
$component,
|
||||
'core_calendar_get_event_action_string',
|
||||
[$event->get_type()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($data, $related);
|
||||
@ -188,18 +175,6 @@ class event_exporter_base extends exporter {
|
||||
'default' => null,
|
||||
'null' => NULL_ALLOWED
|
||||
],
|
||||
'activityname' => [
|
||||
'type' => PARAM_TEXT,
|
||||
'optional' => true,
|
||||
'default' => null,
|
||||
'null' => NULL_ALLOWED
|
||||
],
|
||||
'activitystr' => [
|
||||
'type' => PARAM_TEXT,
|
||||
'optional' => true,
|
||||
'default' => null,
|
||||
'null' => NULL_ALLOWED
|
||||
],
|
||||
'instance' => [
|
||||
'type' => PARAM_INT,
|
||||
'optional' => true,
|
||||
|
104
calendar/classes/external/subscription/delete.php
vendored
Normal file
104
calendar/classes/external/subscription/delete.php
vendored
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/>.
|
||||
|
||||
/**
|
||||
* Calendar external API for deleting the subscription.
|
||||
*
|
||||
* @package core_calendar
|
||||
* @category external
|
||||
* @copyright 2021 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_calendar\external\subscription;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/calendar/lib.php');
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use external_warnings;
|
||||
|
||||
/**
|
||||
* Calendar external API for deleting the subscription.
|
||||
*
|
||||
* @package core_calendar
|
||||
* @category external
|
||||
* @copyright 2021 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class delete extends external_api {
|
||||
|
||||
/**
|
||||
* Describes the parameters for deleting the subscription.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 4.0
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'subscriptionid' => new external_value(PARAM_INT, 'The id of the subscription', VALUE_REQUIRED)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* External function to delete the calendar subscription.
|
||||
*
|
||||
* @param int $subscriptionid Subscription id.
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(int $subscriptionid): array {
|
||||
[
|
||||
'subscriptionid' => $subscriptionid
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'subscriptionid' => $subscriptionid
|
||||
]);
|
||||
$status = false;
|
||||
$warnings = [];
|
||||
if (calendar_can_edit_subscription($subscriptionid)) {
|
||||
// Fetch the subscription from the database making sure it exists.
|
||||
$sub = calendar_get_subscription($subscriptionid);
|
||||
calendar_delete_subscription($subscriptionid);
|
||||
$status = true;
|
||||
} else {
|
||||
$warnings = [
|
||||
'item' => $subscriptionid,
|
||||
'warningcode' => 'errordeletingsubscription',
|
||||
'message' => get_string('nopermissions', 'error')
|
||||
];
|
||||
}
|
||||
return [
|
||||
'status' => $status,
|
||||
'warnings' => $warnings
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the data returned from the external function.
|
||||
*
|
||||
* @return external_single_structure
|
||||
* @since Moodle 4.0
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([
|
||||
'status' => new external_value(PARAM_BOOL, 'status: true if success'),
|
||||
'warnings' => new external_warnings()
|
||||
]);
|
||||
}
|
||||
}
|
54
calendar/classes/output/refreshintervalcollection.php
Normal file
54
calendar/classes/output/refreshintervalcollection.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Class to display collection select for the refresh interval.
|
||||
*
|
||||
* @package core_calendar
|
||||
* @copyright 2021 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_calendar\output;
|
||||
|
||||
use core\output\inplace_editable;
|
||||
|
||||
class refreshintervalcollection extends inplace_editable {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \stdClass $subscription Subscription object
|
||||
*/
|
||||
public function __construct(\stdClass $subscription) {
|
||||
$collection = calendar_get_pollinterval_choices();
|
||||
parent::__construct('core_calendar', 'refreshinterval', $subscription->id, true, null, $subscription->pollinterval, null,
|
||||
get_string('pollinterval', 'calendar'));
|
||||
$this->set_type_select($collection);
|
||||
}
|
||||
|
||||
public static function update(int $subscriptionid, int $pollinterval) {
|
||||
if (calendar_can_edit_subscription($subscriptionid)) {
|
||||
$subscription = calendar_get_subscription($subscriptionid);
|
||||
$subscription->pollinterval = $pollinterval;
|
||||
calendar_update_subscription($subscription);
|
||||
$tmpl = new self($subscription);
|
||||
return $tmpl;
|
||||
} else {
|
||||
throw new \moodle_exception('nopermissions', 'error', '', get_string('managesubscriptions', 'calendar'));
|
||||
}
|
||||
}
|
||||
}
|
@ -90,6 +90,23 @@ if (!empty($groupcourseid)) {
|
||||
$data['eventtype'] = 'group';
|
||||
$pageurl->param('groupcourseid', $groupcourseid);
|
||||
}
|
||||
if (!empty($category)) {
|
||||
$pageurl->param('category', $category);
|
||||
$managesubscriptionsurl->param('category', $category);
|
||||
$data['category'] = $category;
|
||||
$data['eventtype'] = 'category';
|
||||
}
|
||||
|
||||
$heading = get_string('importcalendar', 'calendar');
|
||||
$pagetitle = $course->shortname . ': ' . get_string('calendar', 'calendar') . ': ' . $heading;
|
||||
|
||||
$PAGE->set_title($pagetitle);
|
||||
$PAGE->set_heading($heading);
|
||||
$PAGE->set_url($pageurl);
|
||||
$PAGE->set_pagelayout('admin');
|
||||
$PAGE->navbar->add(get_string('managesubscriptions', 'calendar'), $managesubscriptionsurl);
|
||||
$PAGE->navbar->add($heading);
|
||||
$renderer = $PAGE->get_renderer('core_calendar');
|
||||
|
||||
$customdata = [
|
||||
'courseid' => $course->id,
|
||||
@ -109,7 +126,7 @@ if (!empty($formdata)) {
|
||||
$calendar = $form->get_file_content('importfile');
|
||||
$ical = new iCalendar();
|
||||
$ical->unserialize($calendar);
|
||||
$importresults = calendar_import_icalendar_events($ical, null, $subscriptionid);
|
||||
$importresults = calendar_import_events_from_ical($ical, $subscriptionid);
|
||||
} else {
|
||||
try {
|
||||
$importresults = calendar_update_subscription_events($subscriptionid);
|
||||
@ -125,11 +142,9 @@ if (!empty($formdata)) {
|
||||
if (!empty($formdata->categoryid)) {
|
||||
$managesubscriptionsurl->param('category', $formdata->categoryid);
|
||||
}
|
||||
redirect($managesubscriptionsurl, $importresults);
|
||||
redirect($managesubscriptionsurl, $renderer->render_import_result($importresults));
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('core_calendar');
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $renderer->start_layout();
|
||||
echo $OUTPUT->heading($heading);
|
||||
|
118
calendar/lib.php
118
calendar/lib.php
@ -2721,12 +2721,12 @@ function calendar_add_event_allowed($event) {
|
||||
*/
|
||||
function calendar_get_pollinterval_choices() {
|
||||
return array(
|
||||
'0' => new \lang_string('never', 'calendar'),
|
||||
HOURSECS => new \lang_string('hourly', 'calendar'),
|
||||
DAYSECS => new \lang_string('daily', 'calendar'),
|
||||
WEEKSECS => new \lang_string('weekly', 'calendar'),
|
||||
'2628000' => new \lang_string('monthly', 'calendar'),
|
||||
YEARSECS => new \lang_string('annually', 'calendar')
|
||||
'0' => get_string('never', 'calendar'),
|
||||
HOURSECS => get_string('hourly', 'calendar'),
|
||||
DAYSECS => get_string('daily', 'calendar'),
|
||||
WEEKSECS => get_string('weekly', 'calendar'),
|
||||
'2628000' => get_string('monthly', 'calendar'),
|
||||
YEARSECS => get_string('annually', 'calendar')
|
||||
);
|
||||
}
|
||||
|
||||
@ -2964,42 +2964,6 @@ function calendar_add_icalendar_event($event, $unused, $subscriptionid, $timezon
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a subscription from the form data in one of the rows in the existing subscriptions table.
|
||||
*
|
||||
* @param int $subscriptionid The ID of the subscription we are acting upon.
|
||||
* @param int $pollinterval The poll interval to use.
|
||||
* @param int $action The action to be performed. One of update or remove.
|
||||
* @throws dml_exception if invalid subscriptionid is provided
|
||||
* @return string A log of the import progress, including errors
|
||||
*/
|
||||
function calendar_process_subscription_row($subscriptionid, $pollinterval, $action) {
|
||||
// Fetch the subscription from the database making sure it exists.
|
||||
$sub = calendar_get_subscription($subscriptionid);
|
||||
|
||||
// Update or remove the subscription, based on action.
|
||||
switch ($action) {
|
||||
case CALENDAR_SUBSCRIPTION_UPDATE:
|
||||
// Skip updating file subscriptions.
|
||||
if (empty($sub->url)) {
|
||||
break;
|
||||
}
|
||||
$sub->pollinterval = $pollinterval;
|
||||
calendar_update_subscription($sub);
|
||||
|
||||
// Update the events.
|
||||
return "<p>" . get_string('subscriptionupdated', 'calendar', $sub->name) . "</p>" .
|
||||
calendar_update_subscription_events($subscriptionid);
|
||||
case CALENDAR_SUBSCRIPTION_REMOVE:
|
||||
calendar_delete_subscription($subscriptionid);
|
||||
return get_string('subscriptionremoved', 'calendar', $sub->name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete subscription and all related events.
|
||||
*
|
||||
@ -3052,6 +3016,7 @@ function calendar_get_icalendar($url) {
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
require_once($CFG->libdir . '/bennu/bennu.inc.php');
|
||||
|
||||
$curl = new \curl();
|
||||
$curl->setopt(array('CURLOPT_FOLLOWLOCATION' => 1, 'CURLOPT_MAXREDIRS' => 5));
|
||||
@ -3072,17 +3037,17 @@ function calendar_get_icalendar($url) {
|
||||
* Import events from an iCalendar object into a course calendar.
|
||||
*
|
||||
* @param iCalendar $ical The iCalendar object.
|
||||
* @param int $unused Deprecated
|
||||
* @param int $subscriptionid The subscription ID.
|
||||
* @return string A log of the import progress, including errors.
|
||||
* @param int|null $subscriptionid The subscription ID.
|
||||
* @return array A log of the import progress, including errors.
|
||||
*/
|
||||
function calendar_import_icalendar_events($ical, $unused = null, $subscriptionid = null) {
|
||||
function calendar_import_events_from_ical(iCalendar $ical, int $subscriptionid = null): array {
|
||||
global $DB;
|
||||
|
||||
$return = '';
|
||||
$errors = [];
|
||||
$eventcount = 0;
|
||||
$updatecount = 0;
|
||||
$skippedcount = 0;
|
||||
$deletedcount = 0;
|
||||
|
||||
// Large calendars take a while...
|
||||
if (!CLI_SCRIPT) {
|
||||
@ -3111,18 +3076,15 @@ function calendar_import_icalendar_events($ical, $unused = null, $subscriptionid
|
||||
$skippedcount++;
|
||||
break;
|
||||
case 0:
|
||||
$return .= '<p>' . get_string('erroraddingevent', 'calendar') . ': ';
|
||||
if (empty($event->properties['SUMMARY'])) {
|
||||
$return .= '(' . get_string('notitle', 'calendar') . ')';
|
||||
$errors[] = '(' . get_string('notitle', 'calendar') . ')';
|
||||
} else {
|
||||
$return .= $event->properties['SUMMARY'][0]->value;
|
||||
$errors[] = $event->properties['SUMMARY'][0]->value;
|
||||
}
|
||||
$return .= "</p>\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$return .= html_writer::start_tag('ul');
|
||||
$existing = $DB->get_field('event_subscriptions', 'lastupdated', ['id' => $subscriptionid]);
|
||||
if (!empty($existing)) {
|
||||
$eventsuuids = $DB->get_records_menu('event', ['subscriptionid' => $subscriptionid], '', 'id, uuid');
|
||||
@ -3137,16 +3099,21 @@ function calendar_import_icalendar_events($ical, $unused = null, $subscriptionid
|
||||
}
|
||||
if (!empty($tobedeleted)) {
|
||||
$DB->delete_records_list('event', 'id', $tobedeleted);
|
||||
$return .= html_writer::tag('li', get_string('eventsdeleted', 'calendar', count($tobedeleted)));
|
||||
$deletedcount = count($tobedeleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return .= html_writer::tag('li', get_string('eventsimported', 'calendar', $eventcount));
|
||||
$return .= html_writer::tag('li', get_string('eventsskipped', 'calendar', $skippedcount));
|
||||
$return .= html_writer::tag('li', get_string('eventsupdated', 'calendar', $updatecount));
|
||||
$return .= html_writer::end_tag('ul');
|
||||
return $return;
|
||||
$result = [
|
||||
'eventsimported' => $eventcount,
|
||||
'eventsskipped' => $skippedcount,
|
||||
'eventsupdated' => $updatecount,
|
||||
'eventsdeleted' => $deletedcount,
|
||||
'haserror' => !empty($errors),
|
||||
'errors' => $errors,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3164,7 +3131,7 @@ function calendar_update_subscription_events($subscriptionid) {
|
||||
}
|
||||
|
||||
$ical = calendar_get_icalendar($sub->url);
|
||||
$return = calendar_import_icalendar_events($ical, null, $subscriptionid);
|
||||
$return = calendar_import_events_from_ical($ical, $subscriptionid);
|
||||
$sub->lastupdated = time();
|
||||
|
||||
calendar_update_subscription($sub);
|
||||
@ -3979,3 +3946,36 @@ function calendar_get_export_import_link_params(): array {
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the inplace editable feature.
|
||||
*
|
||||
* @param string $itemtype Type of the inplace editable element
|
||||
* @param int $itemid Id of the item to edit
|
||||
* @param int $newvalue New value of the item
|
||||
* @return \core\output\inplace_editable
|
||||
*/
|
||||
function calendar_inplace_editable(string $itemtype, int $itemid, int $newvalue): \core\output\inplace_editable {
|
||||
global $OUTPUT;
|
||||
|
||||
if ($itemtype === 'refreshinterval') {
|
||||
|
||||
$subscription = calendar_get_subscription($itemid);
|
||||
$context = calendar_get_calendar_context($subscription);
|
||||
\external_api::validate_context($context);
|
||||
|
||||
$updateresult = \core_calendar\output\refreshintervalcollection::update($itemid, $newvalue);
|
||||
|
||||
$refreshresults = calendar_update_subscription_events($itemid);
|
||||
\core\notification::add($OUTPUT->render_from_template(
|
||||
'core_calendar/subscription_update_result',
|
||||
array_merge($refreshresults, [
|
||||
'subscriptionname' => s($subscription->name),
|
||||
])
|
||||
), \core\notification::INFO);
|
||||
|
||||
return $updateresult;
|
||||
}
|
||||
|
||||
\external_api::validate_context(context_system::instance());
|
||||
}
|
||||
|
@ -30,10 +30,6 @@ require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
// Required use.
|
||||
$courseid = optional_param('course', null, PARAM_INT);
|
||||
$categoryid = optional_param('category', null, PARAM_INT);
|
||||
// Used for processing subscription actions.
|
||||
$subscriptionid = optional_param('id', 0, PARAM_INT);
|
||||
$pollinterval = optional_param('pollinterval', 0, PARAM_INT);
|
||||
$action = optional_param('action', '', PARAM_INT);
|
||||
|
||||
$url = new moodle_url('/calendar/managesubscriptions.php');
|
||||
if ($courseid != SITEID && !empty($courseid)) {
|
||||
@ -74,22 +70,6 @@ if (!calendar_user_can_add_event($course)) {
|
||||
|
||||
$PAGE->navbar->add(get_string('managesubscriptions', 'calendar'));
|
||||
|
||||
if (!empty($subscriptionid)) {
|
||||
// The user is wanting to perform an action upon an existing subscription.
|
||||
require_sesskey(); // Must have sesskey for all actions.
|
||||
if (calendar_can_edit_subscription($subscriptionid)) {
|
||||
try {
|
||||
$importresults = calendar_process_subscription_row($subscriptionid, $pollinterval, $action);
|
||||
redirect($PAGE->url, $importresults);
|
||||
} catch (moodle_exception $e) {
|
||||
// If exception caught, then user should be redirected to page where he/she came from.
|
||||
print_error($e->errorcode, $e->module, $PAGE->url);
|
||||
}
|
||||
} else {
|
||||
print_error('nopermissions', 'error', $PAGE->url, get_string('managesubscriptions', 'calendar'));
|
||||
}
|
||||
}
|
||||
|
||||
$types = calendar_get_allowed_event_types($courseid);
|
||||
|
||||
$searches = [];
|
||||
|
@ -371,8 +371,6 @@ class core_calendar_renderer extends plugin_renderer_base {
|
||||
get_string('colpoll', 'calendar'),
|
||||
get_string('colactions', 'calendar')
|
||||
);
|
||||
$table->align = array('left', 'left', 'left', 'left', 'left');
|
||||
$table->width = '100%';
|
||||
$table->data = array();
|
||||
$table->id = 'subscription_details_table';
|
||||
|
||||
@ -394,20 +392,29 @@ class core_calendar_renderer extends plugin_renderer_base {
|
||||
}
|
||||
|
||||
$type = $sub->eventtype . 'events';
|
||||
$calendarname = new html_table_cell($label);
|
||||
$calendarname->header = true;
|
||||
|
||||
$table->data[] = new html_table_row(array(
|
||||
new html_table_cell($label),
|
||||
$tablerow = new html_table_row(array(
|
||||
$calendarname,
|
||||
new html_table_cell($lastupdated),
|
||||
new html_table_cell(get_string($type, 'calendar')),
|
||||
new html_table_cell($this->render_subscription_update_interval($sub)),
|
||||
new html_table_cell($this->subscription_action_form($sub))
|
||||
new html_table_cell($this->subscription_action_links())
|
||||
));
|
||||
$tablerow->attributes += [
|
||||
'data-subid' => $sub->id,
|
||||
'data-subname' => $sub->name
|
||||
];
|
||||
$table->data[] = $tablerow;
|
||||
}
|
||||
|
||||
$out = $this->output->box_start('generalbox calendarsubs');
|
||||
|
||||
$out .= html_writer::table($table);
|
||||
$out .= $this->output->box_end();
|
||||
|
||||
$this->page->requires->js_call_amd('core_calendar/manage_subscriptions', 'init');
|
||||
return $out;
|
||||
}
|
||||
|
||||
@ -418,51 +425,24 @@ class core_calendar_renderer extends plugin_renderer_base {
|
||||
* @return string
|
||||
*/
|
||||
protected function render_subscription_update_interval(stdClass $subscription): string {
|
||||
// Assemble form for the subscription row.
|
||||
$output = html_writer::start_tag('form',
|
||||
['action' => new moodle_url('/calendar/managesubscriptions.php', calendar_get_export_import_link_params()),
|
||||
'method' => 'post']);
|
||||
if (empty($subscription->url)) {
|
||||
$output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'pollinterval', 'value' => '0']);
|
||||
} else {
|
||||
// Assemble pollinterval control.
|
||||
$output .= html_writer::start_div();
|
||||
$output .= html_writer::start_tag('select', ['name' => 'pollinterval', 'class' => 'custom-select']);
|
||||
foreach (calendar_get_pollinterval_choices() as $k => $v) {
|
||||
$attributes = array();
|
||||
if ($k == $subscription->pollinterval) {
|
||||
$attributes['selected'] = 'selected';
|
||||
}
|
||||
$attributes['value'] = $k;
|
||||
$output .= html_writer::tag('option', $v, $attributes);
|
||||
}
|
||||
$output .= html_writer::end_tag('select');
|
||||
$output .= html_writer::end_div();
|
||||
return '';
|
||||
}
|
||||
|
||||
return $output;
|
||||
$tmpl = new \core_calendar\output\refreshintervalcollection($subscription);
|
||||
return $this->output->render_from_template('core/inplace_editable', $tmpl->export_for_template($this->output));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a form to perform actions on a given subscription.
|
||||
*
|
||||
* @param stdClass $subscription
|
||||
* @return string
|
||||
*/
|
||||
protected function subscription_action_form($subscription) {
|
||||
$html = html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'id', 'value' => $subscription->id));
|
||||
$html .= html_writer::start_tag('div', array('class' => 'btn-group float-left'));
|
||||
if (!empty($subscription->url)) {
|
||||
$html .= html_writer::tag('button', get_string('update'), array('type' => 'submit', 'name' => 'action',
|
||||
'class' => 'btn btn-link',
|
||||
'value' => CALENDAR_SUBSCRIPTION_UPDATE));
|
||||
}
|
||||
$html .= html_writer::tag('button', get_string('remove'), array('type' => 'submit', 'name' => 'action',
|
||||
'class' => 'btn btn-link',
|
||||
'value' => CALENDAR_SUBSCRIPTION_REMOVE));
|
||||
protected function subscription_action_links(): string {
|
||||
$html = html_writer::start_tag('div', array('class' => 'btn-group float-left'));
|
||||
$html .= html_writer::span(html_writer::link('#', get_string('delete'),
|
||||
['data-action' => 'delete-subscription']), '');
|
||||
$html .= html_writer::end_tag('div');
|
||||
$html .= html_writer::end_tag('form');
|
||||
return $html;
|
||||
}
|
||||
|
||||
@ -477,4 +457,23 @@ class core_calendar_renderer extends plugin_renderer_base {
|
||||
];
|
||||
return $this->render_from_template('core_calendar/event_filter', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the calendar import result.
|
||||
*
|
||||
* @param array $result Import result
|
||||
* @return string|null
|
||||
*/
|
||||
public function render_import_result(array $result): ?string {
|
||||
$data = [
|
||||
'eventsimported' => $result['eventsimported'],
|
||||
'eventsskipped' => $result['eventsskipped'],
|
||||
'eventsupdated' => $result['eventsupdated'],
|
||||
'eventsdeleted' => $result['eventsdeleted'],
|
||||
'haserror' => $result['haserror'],
|
||||
'errors' => $result['errors']
|
||||
];
|
||||
|
||||
return $this->render_from_template('core_calendar/subscription_update_result', $data);
|
||||
}
|
||||
}
|
||||
|
61
calendar/templates/subscription_update_result.mustache
Normal file
61
calendar/templates/subscription_update_result.mustache
Normal file
@ -0,0 +1,61 @@
|
||||
{{!
|
||||
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 core_calendar/subscription_update_result
|
||||
|
||||
Calendar subscription update result.
|
||||
|
||||
The purpose of this template is to render the calendar subscription update result.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"subscriptionname": "Moodle",
|
||||
"eventsimported": 1,
|
||||
"eventsskipped": 2,
|
||||
"eventsupdated": 3,
|
||||
"deletedcount": 4,
|
||||
"errors": [
|
||||
"Event 1",
|
||||
"Event 2"
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
{{#subscriptionname}}
|
||||
<p>{{#str}} subscriptionupdated, calendar, {{subscriptionname}} {{/str}}</p>
|
||||
{{/subscriptionname}}
|
||||
<ul>
|
||||
<li>{{#str}} eventsimported, calendar, {{eventsimported}} {{/str}}</li>
|
||||
<li>{{#str}} eventsskipped, calendar, {{eventsskipped}} {{/str}}</li>
|
||||
<li>{{#str}} eventsupdated, calendar, {{eventsupdated}} {{/str}}</li>
|
||||
<li>{{#str}} eventsdeleted, calendar, {{eventsdeleted}} {{/str}}</li>
|
||||
</ul>
|
||||
{{#haserror}}
|
||||
<p>{{#str}} erroraddingevent, calendar {{/str}}</p>
|
||||
<ul>
|
||||
{{#eventserror}}
|
||||
<li>{{.}}</li>
|
||||
{{/eventserror}}
|
||||
</ul>
|
||||
{{/haserror}}
|
||||
|
@ -44,7 +44,9 @@ Feature: Import and edit calendar events
|
||||
And I should see "Event on 2-25-2017"
|
||||
And I should not see "Event on 2-15-2017"
|
||||
And I click on "Import or export calendars" "link"
|
||||
And I press "Remove"
|
||||
And I click on "Delete" "link"
|
||||
And I should see "Are you sure you want to delete the \"Test Import\" calendar subscription?" in the ".modal .modal-body" "css_element"
|
||||
And I click on "Yes" "button" in the ".modal.show" "css_element"
|
||||
And I view the calendar for "2" "2017"
|
||||
And I should not see "Event on 2-25-2017"
|
||||
And I should not see "Event on 2-20-2017"
|
||||
|
@ -190,7 +190,7 @@ class core_calendar_lib_testcase extends advanced_testcase {
|
||||
$this->assertEquals($ical->parser_errors, array());
|
||||
|
||||
$sub = calendar_get_subscription($id);
|
||||
calendar_import_icalendar_events($ical, null, $sub->id);
|
||||
calendar_import_events_from_ical($ical, $sub->id);
|
||||
$count = $DB->count_records('event', array('subscriptionid' => $sub->id));
|
||||
$this->assertEquals($count, 1);
|
||||
|
||||
@ -207,7 +207,7 @@ class core_calendar_lib_testcase extends advanced_testcase {
|
||||
$this->assertEquals($ical->parser_errors, array());
|
||||
|
||||
$sub = calendar_get_subscription($id);
|
||||
calendar_import_icalendar_events($ical, null, $sub->id);
|
||||
calendar_import_events_from_ical($ical, $sub->id);
|
||||
$count = $DB->count_records('event', array('subscriptionid' => $sub->id));
|
||||
$this->assertEquals($count, 1);
|
||||
|
||||
@ -224,7 +224,7 @@ class core_calendar_lib_testcase extends advanced_testcase {
|
||||
$this->assertEquals($ical->parser_errors, array());
|
||||
|
||||
$sub = calendar_get_subscription($id);
|
||||
calendar_import_icalendar_events($ical, null, $sub->id);
|
||||
calendar_import_events_from_ical($ical, $sub->id);
|
||||
$count = $DB->count_records('event', array('subscriptionid' => $sub->id));
|
||||
$this->assertEquals($count, 1);
|
||||
|
||||
@ -240,11 +240,15 @@ class core_calendar_lib_testcase extends advanced_testcase {
|
||||
$this->assertEquals($ical->parser_errors, []);
|
||||
|
||||
$sub = calendar_get_subscription($id);
|
||||
$output = calendar_import_icalendar_events($ical, null, $sub->id);
|
||||
$this->assertStringNotContainsString('Events deleted: 17', $output);
|
||||
$this->assertStringContainsString('1 events were imported', $output);
|
||||
$this->assertStringContainsString('0 events were skipped', $output);
|
||||
$this->assertStringContainsString('0 events were updated', $output);
|
||||
$output = calendar_import_events_from_ical($ical, $sub->id);
|
||||
$this->assertArrayHasKey('eventsimported', $output);
|
||||
$this->assertArrayHasKey('eventsskipped', $output);
|
||||
$this->assertArrayHasKey('eventsupdated', $output);
|
||||
$this->assertArrayHasKey('eventsdeleted', $output);
|
||||
$this->assertEquals(1, $output['eventsimported']);
|
||||
$this->assertEquals(0, $output['eventsskipped']);
|
||||
$this->assertEquals(0, $output['eventsupdated']);
|
||||
$this->assertEquals(0, $output['eventsdeleted']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,10 @@ information provided here is intended especially for developers.
|
||||
* The following external functions now accepts an optional parameter 'searchvalue' to search the events:
|
||||
- core_calendar_external::get_calendar_action_events_by_timesort
|
||||
- core_calendar_external::get_calendar_action_events_by_courses
|
||||
* Added core_calendar_delete_subscription, which allows to delete the calendar subscription.
|
||||
* The following functions have been deprecated because they were no longer used:
|
||||
- calendar_process_subscription_row()
|
||||
- calendar_import_icalendar_events()
|
||||
|
||||
=== 3.10 ===
|
||||
* The core_calendar\local\event\value_objects\times_interface class now has new method get_usermidnight_time() which
|
||||
|
@ -39,11 +39,12 @@ $string['clickhide'] = 'click to hide';
|
||||
$string['clickshow'] = 'click to show';
|
||||
$string['colcalendar'] = 'Calendar';
|
||||
$string['collastupdated'] = 'Last updated';
|
||||
$string['colpoll'] = 'Update';
|
||||
$string['colpoll'] = 'Refresh interval';
|
||||
$string['colactions'] = 'Actions';
|
||||
$string['commontasks'] = 'Options';
|
||||
$string['confirmeventdelete'] = 'Are you sure you want to delete the "{$a}" event?';
|
||||
$string['confirmeventseriesdelete'] = 'The "{$a->name}" event is part of a series. Do you want to delete just this event, or all {$a->count} events in the series?';
|
||||
$string['confirmsubscriptiondelete'] = 'Are you sure you want to delete the "{$a}" calendar subscription?';
|
||||
$string['copycalendarurl'] = 'Copy calendar URL';
|
||||
$string['copyurl'] = 'Copy URL';
|
||||
$string['course'] = 'Course';
|
||||
|
@ -60,7 +60,16 @@ class calendar_cron_task extends scheduled_task {
|
||||
mtrace("Updating calendar subscription {$sub->name} in course {$sub->courseid}");
|
||||
try {
|
||||
$log = calendar_update_subscription_events($sub->id);
|
||||
mtrace(trim(strip_tags($log)));
|
||||
mtrace($log['eventsimported'] . ' events were imported');
|
||||
mtrace($log['eventsskipped'] . ' events were skipped');
|
||||
mtrace($log['eventsupdated'] . ' events were updated');
|
||||
mtrace($log['eventsdeleted'] . ' events were deleted');
|
||||
if ($log['haserror']) {
|
||||
mtrace('Failed to add event');
|
||||
foreach ($log['errors'] as $error) {
|
||||
mtrace(trim(strip_tags($error)));
|
||||
}
|
||||
}
|
||||
} catch (\moodle_exception $ex) {
|
||||
mtrace('Error updating calendar subscription: ' . $ex->getMessage());
|
||||
}
|
||||
|
@ -293,6 +293,12 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
],
|
||||
'core_calendar_delete_subscription' => [
|
||||
'classname' => 'core_calendar\external\subscription\delete',
|
||||
'description' => 'Delete the calendar subscription',
|
||||
'type' => 'write',
|
||||
'ajax' => true
|
||||
],
|
||||
'core_cohort_add_cohort_members' => array(
|
||||
'classname' => 'core_cohort_external',
|
||||
'methodname' => 'add_cohort_members',
|
||||
|
@ -3428,3 +3428,124 @@ function get_all_user_name_fields($returnsql = false, $tableprefix = null, $pref
|
||||
}
|
||||
return $alternatenames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a subscription from the form data in one of the rows in the existing subscriptions table.
|
||||
*
|
||||
* @param int $subscriptionid The ID of the subscription we are acting upon.
|
||||
* @param int $pollinterval The poll interval to use.
|
||||
* @param int $action The action to be performed. One of update or remove.
|
||||
* @throws dml_exception if invalid subscriptionid is provided
|
||||
* @return string A log of the import progress, including errors
|
||||
* @deprecated since Moodle 4.0 MDL-71953
|
||||
*/
|
||||
function calendar_process_subscription_row($subscriptionid, $pollinterval, $action) {
|
||||
debugging('calendar_process_subscription_row() is deprecated.', DEBUG_DEVELOPER);
|
||||
// Fetch the subscription from the database making sure it exists.
|
||||
$sub = calendar_get_subscription($subscriptionid);
|
||||
|
||||
// Update or remove the subscription, based on action.
|
||||
switch ($action) {
|
||||
case CALENDAR_SUBSCRIPTION_UPDATE:
|
||||
// Skip updating file subscriptions.
|
||||
if (empty($sub->url)) {
|
||||
break;
|
||||
}
|
||||
$sub->pollinterval = $pollinterval;
|
||||
calendar_update_subscription($sub);
|
||||
|
||||
// Update the events.
|
||||
return "<p>" . get_string('subscriptionupdated', 'calendar', $sub->name) . "</p>" .
|
||||
calendar_update_subscription_events($subscriptionid);
|
||||
case CALENDAR_SUBSCRIPTION_REMOVE:
|
||||
calendar_delete_subscription($subscriptionid);
|
||||
return get_string('subscriptionremoved', 'calendar', $sub->name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Import events from an iCalendar object into a course calendar.
|
||||
*
|
||||
* @param iCalendar $ical The iCalendar object.
|
||||
* @param int $unused Deprecated
|
||||
* @param int $subscriptionid The subscription ID.
|
||||
* @return string A log of the import progress, including errors.
|
||||
*/
|
||||
function calendar_import_icalendar_events($ical, $unused = null, $subscriptionid = null) {
|
||||
debugging('calendar_import_icalendar_events() is deprecated. Please use calendar_import_events_from_ical() instead.',
|
||||
DEBUG_DEVELOPER);
|
||||
global $DB;
|
||||
|
||||
$return = '';
|
||||
$eventcount = 0;
|
||||
$updatecount = 0;
|
||||
$skippedcount = 0;
|
||||
|
||||
// Large calendars take a while...
|
||||
if (!CLI_SCRIPT) {
|
||||
\core_php_time_limit::raise(300);
|
||||
}
|
||||
|
||||
// Grab the timezone from the iCalendar file to be used later.
|
||||
if (isset($ical->properties['X-WR-TIMEZONE'][0]->value)) {
|
||||
$timezone = $ical->properties['X-WR-TIMEZONE'][0]->value;
|
||||
} else {
|
||||
$timezone = 'UTC';
|
||||
}
|
||||
|
||||
$icaluuids = [];
|
||||
foreach ($ical->components['VEVENT'] as $event) {
|
||||
$icaluuids[] = $event->properties['UID'][0]->value;
|
||||
$res = calendar_add_icalendar_event($event, null, $subscriptionid, $timezone);
|
||||
switch ($res) {
|
||||
case CALENDAR_IMPORT_EVENT_UPDATED:
|
||||
$updatecount++;
|
||||
break;
|
||||
case CALENDAR_IMPORT_EVENT_INSERTED:
|
||||
$eventcount++;
|
||||
break;
|
||||
case CALENDAR_IMPORT_EVENT_SKIPPED:
|
||||
$skippedcount++;
|
||||
break;
|
||||
case 0:
|
||||
$return .= '<p>' . get_string('erroraddingevent', 'calendar') . ': ';
|
||||
if (empty($event->properties['SUMMARY'])) {
|
||||
$return .= '(' . get_string('notitle', 'calendar') . ')';
|
||||
} else {
|
||||
$return .= $event->properties['SUMMARY'][0]->value;
|
||||
}
|
||||
$return .= "</p>\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$return .= html_writer::start_tag('ul');
|
||||
$existing = $DB->get_field('event_subscriptions', 'lastupdated', ['id' => $subscriptionid]);
|
||||
if (!empty($existing)) {
|
||||
$eventsuuids = $DB->get_records_menu('event', ['subscriptionid' => $subscriptionid], '', 'id, uuid');
|
||||
|
||||
$icaleventscount = count($icaluuids);
|
||||
$tobedeleted = [];
|
||||
if (count($eventsuuids) > $icaleventscount) {
|
||||
foreach ($eventsuuids as $eventid => $eventuuid) {
|
||||
if (!in_array($eventuuid, $icaluuids)) {
|
||||
$tobedeleted[] = $eventid;
|
||||
}
|
||||
}
|
||||
if (!empty($tobedeleted)) {
|
||||
$DB->delete_records_list('event', 'id', $tobedeleted);
|
||||
$return .= html_writer::tag('li', get_string('eventsdeleted', 'calendar', count($tobedeleted)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return .= html_writer::tag('li', get_string('eventsimported', 'calendar', $eventcount));
|
||||
$return .= html_writer::tag('li', get_string('eventsskipped', 'calendar', $skippedcount));
|
||||
$return .= html_writer::tag('li', get_string('eventsupdated', 'calendar', $updatecount));
|
||||
$return .= html_writer::end_tag('ul');
|
||||
return $return;
|
||||
}
|
||||
|
@ -58,9 +58,13 @@ class core_calendar_cron_task_testcase extends advanced_testcase {
|
||||
$subscription->lastupdated = 0;
|
||||
calendar_add_subscription($subscription);
|
||||
|
||||
$this->expectOutputRegex('/.* events were imported.* events were skipped.* events were updated/');
|
||||
$task = new \core\task\calendar_cron_task();
|
||||
ob_start();
|
||||
$task->execute();
|
||||
$output = ob_get_clean();
|
||||
$this->assertStringContainsString('events were imported', $output);
|
||||
$this->assertStringContainsString('events were skipped', $output);
|
||||
$this->assertStringContainsString('events were updated', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1276,7 +1276,7 @@ class upgradelib_test extends advanced_testcase {
|
||||
$ical->unserialize($calendar);
|
||||
|
||||
// Import subscription events.
|
||||
calendar_import_icalendar_events($ical, null, $id);
|
||||
calendar_import_events_from_ical($ical, $id);
|
||||
|
||||
// Subscription should have added 18 events.
|
||||
$eventscount = $DB->count_records('event');
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2021101900.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2021101900.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '4.0dev+ (Build: 20211019)'; // Human-friendly version name
|
||||
|
Loading…
x
Reference in New Issue
Block a user