mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-70795 reportbuilder: add interface for creating reports.
Implement elements for creating/editing reports, along with new system report for listing and accompanying JS modules for user interaction. Create "Users" datasource as proof-of-concept. Co-authored-By: Paul Holden <paulh@moodle.com>
This commit is contained in:
parent
95967d62d5
commit
22d896e063
44
admin/settings/reportbuilder.php
Normal file
44
admin/settings/reportbuilder.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/>.
|
||||
|
||||
/**
|
||||
* Report builder related settings.
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use core_admin\local\externalpage\accesscallback;
|
||||
use core_reportbuilder\permission;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
/** @var admin_root $ADMIN */
|
||||
$ADMIN->add('reports', new admin_category('reportbuilder', new lang_string('reportbuilder', 'core_reportbuilder')));
|
||||
|
||||
$ADMIN->add(
|
||||
'reportbuilder', new accesscallback(
|
||||
'customreports',
|
||||
get_string('customreports', 'core_reportbuilder'),
|
||||
(new moodle_url('/reportbuilder/index.php'))->out(),
|
||||
static function(accesscallback $accesscallback): bool {
|
||||
return permission::can_view_reports_list();
|
||||
}
|
||||
)
|
||||
);
|
@ -28,6 +28,11 @@ $string['coursefullnamewithlink'] = 'Course full name with link';
|
||||
$string['courseidnumberewithlink'] = 'Course ID number with link';
|
||||
$string['courseshortnamewithlink'] = 'Course short name with link';
|
||||
$string['customfieldcolumn'] = '{$a}';
|
||||
$string['deletereport'] = 'Delete report';
|
||||
$string['deletereportconfirm'] = 'Are you sure you want to delete the report \'{$a}\' and all associated data?';
|
||||
$string['editreportdetails'] = 'Edit report details';
|
||||
$string['editreportname'] = 'Edit report name';
|
||||
$string['customreports'] = 'Custom reports';
|
||||
$string['entitycourse'] = 'Course';
|
||||
$string['entityuser'] = 'User';
|
||||
$string['errorreportaccess'] = 'You can not view this report';
|
||||
@ -66,6 +71,9 @@ $string['filtersapplied'] = 'Filters applied';
|
||||
$string['filtersappliedx'] = 'Filters ({$a})';
|
||||
$string['filtersreset'] = 'Filters reset';
|
||||
$string['filterstartswith'] = 'Starts with';
|
||||
$string['includedefaultsetup'] = 'Include default setup';
|
||||
$string['includedefaultsetup_help'] = 'Populate report with default layout as defined by the selected source. These include pre-defined columns, filters and conditions.';
|
||||
$string['newreport'] = 'New report';
|
||||
$string['privacy:metadata:column'] = 'Report column definitions';
|
||||
$string['privacy:metadata:column:uniqueidentifier'] = 'Unique identifier of the column';
|
||||
$string['privacy:metadata:column:usercreated'] = 'The ID of the user who created the column';
|
||||
@ -79,8 +87,18 @@ $string['privacy:metadata:report'] = 'Report definitions';
|
||||
$string['privacy:metadata:report:name'] = 'The name of the report';
|
||||
$string['privacy:metadata:report:usercreated'] = 'The ID of the user who created the report';
|
||||
$string['privacy:metadata:report:usermodified'] = 'The ID of the user who last modified the report';
|
||||
$string['reportbuilder'] = 'Report builder';
|
||||
$string['reportcreated'] = 'Report created';
|
||||
$string['reportdeleted'] = 'Report deleted';
|
||||
$string['reportsource'] = 'Report source';
|
||||
$string['reportsource_help'] = 'The report source defines where the data for the report will come from';
|
||||
$string['reportupdated'] = 'Report updated';
|
||||
$string['resetall'] = 'Reset all';
|
||||
$string['selectareportsource'] = 'Select a report source';
|
||||
$string['selectcourses'] = 'Select courses';
|
||||
$string['timeadded'] = 'Time added';
|
||||
$string['timecreated'] = 'Time created';
|
||||
$string['timemodified'] = 'Time modified';
|
||||
$string['userfullnamewithlink'] = 'Full name with link';
|
||||
$string['userfullnamewithpicture'] = 'Full name with picture';
|
||||
$string['userfullnamewithpicturelink'] = 'Full name with picture and link';
|
||||
|
@ -371,6 +371,9 @@ $string['rating:rate'] = 'Add ratings to items';
|
||||
$string['rating:view'] = 'View the total rating you received';
|
||||
$string['rating:viewany'] = 'View total ratings that anyone received';
|
||||
$string['rating:viewall'] = 'View all raw ratings given by individuals';
|
||||
$string['reportbuilder:edit'] = 'Create/edit custom reports';
|
||||
$string['reportbuilder:editall'] = 'Create/edit all custom reports';
|
||||
$string['reportbuilder:view'] = 'View custom reports';
|
||||
$string['resetrole'] = 'Reset';
|
||||
$string['resettingrole'] = 'Resetting role \'{$a}\'';
|
||||
$string['restore:configure'] = 'Configure restore options';
|
||||
|
@ -2627,4 +2627,31 @@ $capabilities = array(
|
||||
'coursecreator' => CAP_ALLOW,
|
||||
]
|
||||
],
|
||||
|
||||
// Allow users to view custom reports.
|
||||
'moodle/reportbuilder:view' => [
|
||||
'captype' => 'read',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'user' => CAP_ALLOW,
|
||||
],
|
||||
],
|
||||
|
||||
// Allow users to create/edit their own custom reports.
|
||||
'moodle/reportbuilder:edit' => [
|
||||
'captype' => 'write',
|
||||
'riskbitmap' => RISK_PERSONAL,
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'manager' => CAP_ALLOW,
|
||||
],
|
||||
],
|
||||
|
||||
// Allow users to create/edit all custom reports.
|
||||
'moodle/reportbuilder:editall' => [
|
||||
'captype' => 'write',
|
||||
'riskbitmap' => RISK_PERSONAL,
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [],
|
||||
],
|
||||
);
|
||||
|
@ -2798,6 +2798,12 @@ $functions = array(
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
'core_reportbuilder_reports_delete' => [
|
||||
'classname' => 'core_reportbuilder\external\reports\delete',
|
||||
'description' => 'Delete report',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
);
|
||||
|
||||
$services = array(
|
||||
|
2
reportbuilder/amd/build/local/repository/modals.min.js
vendored
Normal file
2
reportbuilder/amd/build/local/repository/modals.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
define ("core_reportbuilder/local/repository/modals",["exports","core_form/modalform","core/str"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.createReportModal=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var d=function(a,d){var e=2<arguments.length&&arguments[2]!==void 0?arguments[2]:0;return new b.default({modalConfig:{title:d},formClass:"core_reportbuilder\\form\\report",args:{id:e},saveButtonText:(0,c.get_string)("save","moodle"),returnFocus:a})};a.createReportModal=d});
|
||||
//# sourceMappingURL=modals.min.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/local/repository/modals.js"],"names":["createReportModal","triggerElement","modalTitle","reportId","ModalForm","modalConfig","title","formClass","args","id","saveButtonText","returnFocus"],"mappings":"2MAwBA,uDAWO,GAAMA,CAAAA,CAAiB,CAAG,SAACC,CAAD,CAAiBC,CAAjB,CAA8C,IAAjBC,CAAAA,CAAiB,wDAAN,CAAM,CAC3E,MAAO,IAAIC,UAAJ,CAAc,CACjBC,WAAW,CAAE,CACTC,KAAK,CAAEJ,CADE,CADI,CAIjBK,SAAS,CAAE,kCAJM,CAKjBC,IAAI,CAAE,CACFC,EAAE,CAAEN,CADF,CALW,CAQjBO,cAAc,CAAE,iBAAU,MAAV,CAAkB,QAAlB,CARC,CASjBC,WAAW,CAAEV,CATI,CAAd,CAWV,CAZM,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle modal form requests\n *\n * @module core_reportbuilder/local/repository/modals\n * @package core_reportbuilder\n * @copyright 2021 David Matamoros <davidmc@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Open the New Report modal form\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @return {ModalForm}\n */\nexport const createReportModal = (triggerElement, modalTitle, reportId = 0) => {\n return new ModalForm({\n modalConfig: {\n title: modalTitle,\n },\n formClass: 'core_reportbuilder\\\\form\\\\report',\n args: {\n id: reportId,\n },\n saveButtonText: getString('save', 'moodle'),\n returnFocus: triggerElement,\n });\n};\n"],"file":"modals.min.js"}
|
2
reportbuilder/amd/build/local/repository/reports.min.js
vendored
Normal file
2
reportbuilder/amd/build/local/repository/reports.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
define ("core_reportbuilder/local/repository/reports",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.deleteReport=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"core_reportbuilder_reports_delete",args:{reportid:a}}])[0]};a.deleteReport=c});
|
||||
//# sourceMappingURL=reports.min.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/local/repository/reports.js"],"names":["deleteReport","reportId","Ajax","call","methodname","args","reportid"],"mappings":"gLAwBA,uDAQO,GAAMA,CAAAA,CAAY,CAAG,SAAAC,CAAQ,CAAI,CAMpC,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,mCADA,CAEZC,IAAI,CAAE,CAACC,QAAQ,CAAEL,CAAX,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle report AJAX requests\n *\n * @module core_reportbuilder/local/repository/reports\n * @package core_reportbuilder\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Delete given report\n *\n * @param {Number} reportId\n * @return {Promise}\n */\nexport const deleteReport = reportId => {\n const request = {\n methodname: 'core_reportbuilder_reports_delete',\n args: {reportid: reportId}\n };\n\n return Ajax.call([request])[0];\n};\n\n"],"file":"reports.min.js"}
|
@ -1,2 +1,2 @@
|
||||
define ("core_reportbuilder/local/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b={regions:{systemReport:"[data-region=\"core_reportbuilder/system-report\"]",filterButtonLabel:"[data-region=\"filter-button-label\"]",filtersForm:"[data-region=\"filters-form\"]"},actions:{reportActionPopup:"[data-action=\"report-action-popup\"]"}};b.forSystemReport=function(a){return"".concat(b.regions.systemReport,"[data-reportid=\"").concat(a,"\"]")};a.default=b;return a.default});
|
||||
define ("core_reportbuilder/local/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b={regions:{systemReport:"[data-region=\"core_reportbuilder/system-report\"]",filterButtonLabel:"[data-region=\"filter-button-label\"]",filtersForm:"[data-region=\"filters-form\"]"},actions:{reportActionPopup:"[data-action=\"report-action-popup\"]",reportCreate:"[data-action=\"report-create\"]",reportEdit:"[data-action=\"report-edit\"]",reportDelete:"[data-action=\"report-delete\"]"}};b.forSystemReport=function(a){return"".concat(b.regions.systemReport,"[data-reportid=\"").concat(a,"\"]")};a.default=b;return a.default});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"sources":["../../src/local/selectors.js"],"names":["SELECTORS","regions","systemReport","filterButtonLabel","filtersForm","actions","reportActionPopup","forSystemReport","reportId"],"mappings":"oJA+BA,GAAMA,CAAAA,CAAS,CAAG,CACdC,OAAO,CAAE,CACLC,YAAY,CAAE,oDADT,CAELC,iBAAiB,CAAE,uCAFd,CAGLC,WAAW,CAAE,gCAHR,CADK,CAMdC,OAAO,CAAE,CACLC,iBAAiB,CAAE,uCADd,CANK,CAAlB,CAkBAN,CAAS,CAACO,eAAV,CAA4B,SAAAC,CAAQ,kBAAOR,CAAS,CAACC,OAAV,CAAkBC,YAAzB,6BAAwDM,CAAxD,QAApC,C,UAEeR,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Report builder selectors\n *\n * @module core_reportbuilder/local/selectors\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Selectors for the Report builder subsystem\n *\n * @property {Object} regions\n * @property {String} regions.systemReport System report page region\n * @property {String} regions.filterButtonLabel Filters form toggle region\n * @property {String} regions.filtersForm Filters form page region\n */\nconst SELECTORS = {\n regions: {\n systemReport: '[data-region=\"core_reportbuilder/system-report\"]',\n filterButtonLabel: '[data-region=\"filter-button-label\"]',\n filtersForm: '[data-region=\"filters-form\"]',\n },\n actions: {\n reportActionPopup: '[data-action=\"report-action-popup\"]',\n }\n};\n\n/**\n * Selector for given report\n *\n * @method forSystemReport\n * @param {Number} reportId\n * @return {String}\n */\nSELECTORS.forSystemReport = reportId => `${SELECTORS.regions.systemReport}[data-reportid=\"${reportId}\"]`;\n\nexport default SELECTORS;\n"],"file":"selectors.min.js"}
|
||||
{"version":3,"sources":["../../src/local/selectors.js"],"names":["SELECTORS","regions","systemReport","filterButtonLabel","filtersForm","actions","reportActionPopup","reportCreate","reportEdit","reportDelete","forSystemReport","reportId"],"mappings":"oJA+BA,GAAMA,CAAAA,CAAS,CAAG,CACdC,OAAO,CAAE,CACLC,YAAY,CAAE,oDADT,CAELC,iBAAiB,CAAE,uCAFd,CAGLC,WAAW,CAAE,gCAHR,CADK,CAMdC,OAAO,CAAE,CACLC,iBAAiB,CAAE,uCADd,CAELC,YAAY,CAAE,iCAFT,CAGLC,UAAU,CAAE,+BAHP,CAILC,YAAY,CAAE,iCAJT,CANK,CAAlB,CAqBAT,CAAS,CAACU,eAAV,CAA4B,SAAAC,CAAQ,kBAAOX,CAAS,CAACC,OAAV,CAAkBC,YAAzB,6BAAwDS,CAAxD,QAApC,C,UAEeX,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Report builder selectors\n *\n * @module core_reportbuilder/local/selectors\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Selectors for the Report builder subsystem\n *\n * @property {Object} regions\n * @property {String} regions.systemReport System report page region\n * @property {String} regions.filterButtonLabel Filters form toggle region\n * @property {String} regions.filtersForm Filters form page region\n */\nconst SELECTORS = {\n regions: {\n systemReport: '[data-region=\"core_reportbuilder/system-report\"]',\n filterButtonLabel: '[data-region=\"filter-button-label\"]',\n filtersForm: '[data-region=\"filters-form\"]',\n },\n actions: {\n reportActionPopup: '[data-action=\"report-action-popup\"]',\n reportCreate: '[data-action=\"report-create\"]',\n reportEdit: '[data-action=\"report-edit\"]',\n reportDelete: '[data-action=\"report-delete\"]',\n },\n};\n\n/**\n * Selector for given report\n *\n * @method forSystemReport\n * @param {Number} reportId\n * @return {String}\n */\nSELECTORS.forSystemReport = reportId => `${SELECTORS.regions.systemReport}[data-reportid=\"${reportId}\"]`;\n\nexport default SELECTORS;\n"],"file":"selectors.min.js"}
|
2
reportbuilder/amd/build/reports_list.min.js
vendored
Normal file
2
reportbuilder/amd/build/reports_list.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_reportbuilder/reports_list",["exports","core/event_dispatcher","core/notification","core/pending","core/str","core/toast","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core_reportbuilder/local/repository/reports","core_reportbuilder/local/repository/modals"],function(a,b,c,d,e,f,g,h,i,j){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=m(c);d=m(d);g=l(g);h=l(h);function k(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;k=function(){return a};return a}function l(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=k();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 m(a){return a&&a.__esModule?a:{default:a}}function n(a,b){return s(a)||r(a,b)||p(a,b)||o()}function o(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function p(a,b){if(!a)return;if("string"==typeof a)return q(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return q(a,b)}function q(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c<b;c++){d[c]=a[c]}return d}function r(a,b){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(a)))return;var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function s(a){if(Array.isArray(a))return a}a.init=function init(){document.addEventListener("click",function(a){var k=a.target.closest(h.actions.reportCreate);if(k){a.preventDefault();var o=(0,j.createReportModal)(a.target,(0,e.get_string)("newreport","core_reportbuilder"));o.addEventListener(o.events.FORM_SUBMITTED,function(a){window.location.href=a.detail});o.show()}var l=a.target.closest(h.actions.reportEdit);if(l){a.preventDefault();var p=(0,j.createReportModal)(a.target,(0,e.get_string)("editreportdetails","core_reportbuilder"),l.dataset.reportId);p.addEventListener(p.events.FORM_SUBMITTED,function(){var d=a.target.closest(h.regions.report);(0,e.get_string)("reportupdated","core_reportbuilder").then(f.add).then(function(){(0,b.dispatchEvent)(g.tableReload,{preservePagination:!0},d)}).catch(c.default.exception)});p.show()}var m=a.target.closest(h.actions.reportDelete);if(m){a.preventDefault();(0,e.get_strings)([{key:"deletereport",component:"core_reportbuilder"},{key:"deletereportconfirm",component:"core_reportbuilder",param:m.dataset.reportName},{key:"delete",component:"moodle"}]).then(function(j){var k=n(j,3),l=k[0],o=k[1],p=k[2];c.default.confirm(l,o,p,null,function(){var j=new d.default("core_reportbuilder/reports:delete"),k=a.target.closest(h.regions.report);(0,i.deleteReport)(m.dataset.reportId).then(function(){return(0,e.get_string)("reportdeleted","core_reportbuilder")}).then(f.add).then(function(){j.resolve();(0,b.dispatchEvent)(g.tableReload,{preservePagination:!0},k)}).catch(c.default.exception)})}).catch(c.default.exception)}})}});
|
||||
//# sourceMappingURL=reports_list.min.js.map
|
1
reportbuilder/amd/build/reports_list.min.js.map
Normal file
1
reportbuilder/amd/build/reports_list.min.js.map
Normal file
File diff suppressed because one or more lines are too long
48
reportbuilder/amd/src/local/repository/modals.js
Normal file
48
reportbuilder/amd/src/local/repository/modals.js
Normal file
@ -0,0 +1,48 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Module to handle modal form requests
|
||||
*
|
||||
* @module core_reportbuilder/local/repository/modals
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import ModalForm from 'core_form/modalform';
|
||||
import {get_string as getString} from 'core/str';
|
||||
|
||||
/**
|
||||
* Open the New Report modal form
|
||||
*
|
||||
* @param {EventTarget} triggerElement
|
||||
* @param {Promise} modalTitle
|
||||
* @param {Number} reportId
|
||||
* @return {ModalForm}
|
||||
*/
|
||||
export const createReportModal = (triggerElement, modalTitle, reportId = 0) => {
|
||||
return new ModalForm({
|
||||
modalConfig: {
|
||||
title: modalTitle,
|
||||
},
|
||||
formClass: 'core_reportbuilder\\form\\report',
|
||||
args: {
|
||||
id: reportId,
|
||||
},
|
||||
saveButtonText: getString('save', 'moodle'),
|
||||
returnFocus: triggerElement,
|
||||
});
|
||||
};
|
41
reportbuilder/amd/src/local/repository/reports.js
Normal file
41
reportbuilder/amd/src/local/repository/reports.js
Normal file
@ -0,0 +1,41 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Module to handle report AJAX requests
|
||||
*
|
||||
* @module core_reportbuilder/local/repository/reports
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import Ajax from 'core/ajax';
|
||||
|
||||
/**
|
||||
* Delete given report
|
||||
*
|
||||
* @param {Number} reportId
|
||||
* @return {Promise}
|
||||
*/
|
||||
export const deleteReport = reportId => {
|
||||
const request = {
|
||||
methodname: 'core_reportbuilder_reports_delete',
|
||||
args: {reportid: reportId}
|
||||
};
|
||||
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
@ -37,7 +37,10 @@ const SELECTORS = {
|
||||
},
|
||||
actions: {
|
||||
reportActionPopup: '[data-action="report-action-popup"]',
|
||||
}
|
||||
reportCreate: '[data-action="report-create"]',
|
||||
reportEdit: '[data-action="report-edit"]',
|
||||
reportDelete: '[data-action="report-delete"]',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
104
reportbuilder/amd/src/reports_list.js
Normal file
104
reportbuilder/amd/src/reports_list.js
Normal file
@ -0,0 +1,104 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Report builder reports list management
|
||||
*
|
||||
* @module core_reportbuilder/reports_list
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
import {dispatchEvent} from 'core/event_dispatcher';
|
||||
import Notification from 'core/notification';
|
||||
import Pending from 'core/pending';
|
||||
import {get_string as getString, get_strings as getStrings} from 'core/str';
|
||||
import {add as addToast} from 'core/toast';
|
||||
import * as reportEvents from 'core_reportbuilder/local/events';
|
||||
import * as reportSelectors from 'core_reportbuilder/local/selectors';
|
||||
import {deleteReport} from 'core_reportbuilder/local/repository/reports';
|
||||
import {createReportModal} from 'core_reportbuilder/local/repository/modals';
|
||||
|
||||
/**
|
||||
* Initialise module
|
||||
*/
|
||||
export const init = () => {
|
||||
document.addEventListener('click', event => {
|
||||
const reportCreate = event.target.closest(reportSelectors.actions.reportCreate);
|
||||
if (reportCreate) {
|
||||
event.preventDefault();
|
||||
|
||||
// Redirect user to editing interface for the report after submission.
|
||||
const reportModal = createReportModal(event.target, getString('newreport', 'core_reportbuilder'));
|
||||
reportModal.addEventListener(reportModal.events.FORM_SUBMITTED, event => {
|
||||
window.location.href = event.detail;
|
||||
});
|
||||
|
||||
reportModal.show();
|
||||
}
|
||||
|
||||
const reportEdit = event.target.closest(reportSelectors.actions.reportEdit);
|
||||
if (reportEdit) {
|
||||
event.preventDefault();
|
||||
|
||||
// Reload current report page after submission.
|
||||
const reportModal = createReportModal(event.target, getString('editreportdetails', 'core_reportbuilder'),
|
||||
reportEdit.dataset.reportId);
|
||||
reportModal.addEventListener(reportModal.events.FORM_SUBMITTED, () => {
|
||||
const reportElement = event.target.closest(reportSelectors.regions.report);
|
||||
|
||||
getString('reportupdated', 'core_reportbuilder')
|
||||
.then(addToast)
|
||||
.then(() => {
|
||||
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
|
||||
return;
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
});
|
||||
|
||||
reportModal.show();
|
||||
}
|
||||
|
||||
const reportDelete = event.target.closest(reportSelectors.actions.reportDelete);
|
||||
if (reportDelete) {
|
||||
event.preventDefault();
|
||||
|
||||
getStrings([
|
||||
{key: 'deletereport', component: 'core_reportbuilder'},
|
||||
{key: 'deletereportconfirm', component: 'core_reportbuilder', param: reportDelete.dataset.reportName},
|
||||
{key: 'delete', component: 'moodle'},
|
||||
]).then(([confirmTitle, confirmText, confirmButton]) => {
|
||||
Notification.confirm(confirmTitle, confirmText, confirmButton, null, () => {
|
||||
const pendingPromise = new Pending('core_reportbuilder/reports:delete');
|
||||
const reportElement = event.target.closest(reportSelectors.regions.report);
|
||||
|
||||
deleteReport(reportDelete.dataset.reportId)
|
||||
.then(() => getString('reportdeleted', 'core_reportbuilder'))
|
||||
.then(addToast)
|
||||
.then(() => {
|
||||
pendingPromise.resolve();
|
||||
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
|
||||
return;
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
});
|
||||
return;
|
||||
}).catch(Notification.exception);
|
||||
}
|
||||
});
|
||||
};
|
43
reportbuilder/classes/datasource.php
Normal file
43
reportbuilder/classes/datasource.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder;
|
||||
|
||||
use coding_exception;
|
||||
use core_reportbuilder\local\helpers\report;
|
||||
use core_reportbuilder\local\models\filter as filter_model;
|
||||
use core_reportbuilder\local\report\base;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
|
||||
/**
|
||||
* Class datasource
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class datasource extends base {
|
||||
|
||||
/**
|
||||
* Return user friendly name of the datasource
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public static function get_name(): string;
|
||||
}
|
96
reportbuilder/classes/event/report_created.php
Normal file
96
reportbuilder/classes/event/report_created.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\event;
|
||||
|
||||
use core\event\base;
|
||||
use core_reportbuilder\local\models\report;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Report builder custom report created event class.
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - string name: The name of the report
|
||||
* - string source: The report source class
|
||||
* }
|
||||
*/
|
||||
class report_created extends base {
|
||||
|
||||
/**
|
||||
* Initialise the event data.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['objecttable'] = report::TABLE;
|
||||
$this->data['crud'] = 'c';
|
||||
$this->data['edulevel'] = self::LEVEL_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance from a report object
|
||||
*
|
||||
* @param report $report
|
||||
* @return self
|
||||
*/
|
||||
public static function create_from_object(report $report): self {
|
||||
$eventparams = [
|
||||
'context' => $report->get_context(),
|
||||
'objectid' => $report->get('id'),
|
||||
'other' => [
|
||||
'name' => $report->get('name'),
|
||||
'source' => $report->get('source'),
|
||||
]
|
||||
];
|
||||
$event = self::create($eventparams);
|
||||
$event->add_record_snapshot($event->objecttable, $report->to_record());
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('reportcreated', 'core_reportbuilder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised description of what happened.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id '$this->userid' created the custom report with id '$this->objectid'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_url(): moodle_url {
|
||||
return new moodle_url('/reportbuilder/edit.php', ['id' => $this->objectid]);
|
||||
}
|
||||
}
|
86
reportbuilder/classes/event/report_deleted.php
Normal file
86
reportbuilder/classes/event/report_deleted.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\event;
|
||||
|
||||
use core\event\base;
|
||||
use core_reportbuilder\local\models\report;
|
||||
|
||||
/**
|
||||
* Report builder custom report deleted event class.
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - string name: The name of the report
|
||||
* - string source: The report source class
|
||||
* }
|
||||
*/
|
||||
class report_deleted extends base {
|
||||
|
||||
/**
|
||||
* Initialise the event data.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['objecttable'] = report::TABLE;
|
||||
$this->data['crud'] = 'd';
|
||||
$this->data['edulevel'] = self::LEVEL_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance from a report object
|
||||
*
|
||||
* @param report $report
|
||||
* @return self
|
||||
*/
|
||||
public static function create_from_object(report $report): self {
|
||||
$eventparams = [
|
||||
'context' => $report->get_context(),
|
||||
'objectid' => $report->get('id'),
|
||||
'other' => [
|
||||
'name' => $report->get('name'),
|
||||
'source' => $report->get('source'),
|
||||
]
|
||||
];
|
||||
$event = self::create($eventparams);
|
||||
$event->add_record_snapshot($event->objecttable, $report->to_record());
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('reportdeleted', 'core_reportbuilder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised description of what happened.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id '$this->userid' deleted the custom report with id '$this->objectid'.";
|
||||
}
|
||||
}
|
96
reportbuilder/classes/event/report_updated.php
Normal file
96
reportbuilder/classes/event/report_updated.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\event;
|
||||
|
||||
use core\event\base;
|
||||
use core_reportbuilder\local\models\report;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Report builder custom report updated event class.
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - string name: The name of the report
|
||||
* - string source: The report source class
|
||||
* }
|
||||
*/
|
||||
class report_updated extends base {
|
||||
|
||||
/**
|
||||
* Initialise the event data.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['objecttable'] = report::TABLE;
|
||||
$this->data['crud'] = 'u';
|
||||
$this->data['edulevel'] = self::LEVEL_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance from a report object
|
||||
*
|
||||
* @param report $report
|
||||
* @return self
|
||||
*/
|
||||
public static function create_from_object(report $report): self {
|
||||
$eventparams = [
|
||||
'context' => $report->get_context(),
|
||||
'objectid' => $report->get('id'),
|
||||
'other' => [
|
||||
'name' => $report->get('name'),
|
||||
'source' => $report->get('source'),
|
||||
]
|
||||
];
|
||||
$event = self::create($eventparams);
|
||||
$event->add_record_snapshot($event->objecttable, $report->to_record());
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('reportupdated', 'core_reportbuilder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised description of what happened.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id '$this->userid' updated the custom report with id '$this->objectid'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_url(): moodle_url {
|
||||
return new moodle_url('/reportbuilder/edit.php', ['id' => $this->objectid]);
|
||||
}
|
||||
}
|
150
reportbuilder/classes/form/report.php
Normal file
150
reportbuilder/classes/form/report.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\form;
|
||||
|
||||
use context;
|
||||
use context_system;
|
||||
use core_reportbuilder\permission;
|
||||
use moodle_url;
|
||||
use core_form\dynamic_form;
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\local\helpers\report as reporthelper;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("$CFG->libdir/formslib.php");
|
||||
|
||||
/**
|
||||
* Report details form
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class report extends dynamic_form {
|
||||
|
||||
/**
|
||||
* Return instance of the custom report we are editing, or null when creating a new report
|
||||
*
|
||||
* @return datasource|null
|
||||
*/
|
||||
protected function get_custom_report(): ?datasource {
|
||||
if ($reportid = $this->optional_param('id', 0, PARAM_INT)) {
|
||||
/** @var datasource $customreport */
|
||||
$customreport = manager::get_report_from_id($reportid);
|
||||
|
||||
return $customreport;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the context for the form, it should be that of the custom report itself, or system when creating a new report
|
||||
*
|
||||
* @return context
|
||||
*/
|
||||
public function get_context_for_dynamic_submission(): context {
|
||||
if ($report = $this->get_custom_report()) {
|
||||
return $report->get_context();
|
||||
} else {
|
||||
return context_system::instance();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure current user is able to use this form
|
||||
*
|
||||
* A {@see \core_reportbuilder\report_access_exception} will be thrown if they can't
|
||||
*/
|
||||
protected function check_access_for_dynamic_submission(): void {
|
||||
$report = $this->get_custom_report();
|
||||
|
||||
if ($report) {
|
||||
permission::require_can_edit_report($report->get_report_persistent());
|
||||
} else {
|
||||
permission::require_can_create_report();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form definition
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
$mform->addElement('hidden', 'id');
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$mform->addElement('text', 'name', get_string('name'));
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
$mform->addRule('name', null, 'required', null, 'client');
|
||||
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255);
|
||||
|
||||
// Allow user to select report source if creating a new report.
|
||||
if (!$this->get_custom_report()) {
|
||||
$default = ['' => ['' => get_string('selectareportsource', 'core_reportbuilder')]];
|
||||
$mform->addElement('selectgroups', 'source', get_string('reportsource', 'core_reportbuilder'),
|
||||
array_merge($default, manager::get_report_datasources()));
|
||||
$mform->addRule('source', null, 'required', null, 'client');
|
||||
$mform->addHelpButton('source', 'reportsource', 'core_reportbuilder');
|
||||
|
||||
$mform->addElement('advcheckbox', 'includedefaultsetup', get_string('includedefaultsetup', 'core_reportbuilder'));
|
||||
$mform->setDefault('includedefaultsetup', 1);
|
||||
$mform->addHelpButton('includedefaultsetup', 'includedefaultsetup', 'core_reportbuilder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the form submission
|
||||
*
|
||||
* @return string The URL to advance to upon completion
|
||||
*/
|
||||
public function process_dynamic_submission() {
|
||||
$data = $this->get_data();
|
||||
|
||||
if ($data->id) {
|
||||
$reportpersistent = reporthelper::update_report($data);
|
||||
} else {
|
||||
$reportpersistent = reporthelper::create_report($data, (bool)$data->includedefaultsetup);
|
||||
}
|
||||
|
||||
return (new moodle_url('/reportbuilder/edit.php', ['id' => $reportpersistent->get('id')]))->out(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load in existing data as form defaults
|
||||
*/
|
||||
public function set_data_for_dynamic_submission(): void {
|
||||
if ($report = $this->get_custom_report()) {
|
||||
$this->set_data($report->get_report_persistent()->to_record());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL of the page using this form
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_page_url_for_dynamic_submission(): moodle_url {
|
||||
return new moodle_url('/reportbuilder/index.php');
|
||||
}
|
||||
}
|
98
reportbuilder/classes/local/helpers/report.php
Normal file
98
reportbuilder/classes/local/helpers/report.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\local\helpers;
|
||||
|
||||
use stdClass;
|
||||
use invalid_parameter_exception;
|
||||
use core\persistent;
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\local\models\column;
|
||||
use core_reportbuilder\local\models\filter;
|
||||
use core_reportbuilder\local\models\report as report_model;
|
||||
|
||||
/**
|
||||
* Helper class for manipulating custom reports and their elements (columns, filters, conditions, etc)
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class report {
|
||||
|
||||
/**
|
||||
* Create custom report
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @param bool $default If $default is set to true it will populate report with default layout as defined by the selected
|
||||
* source. These include pre-defined columns, filters and conditions.
|
||||
* @return report_model
|
||||
*/
|
||||
public static function create_report(stdClass $data, bool $default = true): report_model {
|
||||
// TODO move this properties_definition validation into the persistents, or resolve MDL-71086.
|
||||
$data = (object) array_merge(array_intersect_key((array) $data, report_model::properties_definition()), [
|
||||
'type' => datasource::TYPE_CUSTOM_REPORT,
|
||||
]);
|
||||
|
||||
$reportpersistent = manager::create_report_persistent($data);
|
||||
|
||||
// Add datasource default columns, filters and conditions to the report.
|
||||
if ($default) {
|
||||
$source = $reportpersistent->get('source');
|
||||
/** @var datasource $datasource */
|
||||
$datasource = new $source($reportpersistent, []);
|
||||
}
|
||||
|
||||
return $reportpersistent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update custom report
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return report_model
|
||||
*/
|
||||
public static function update_report(stdClass $data): report_model {
|
||||
$report = report_model::get_record(['id' => $data->id, 'type' => datasource::TYPE_CUSTOM_REPORT]);
|
||||
if ($report === false) {
|
||||
throw new invalid_parameter_exception('Invalid report');
|
||||
}
|
||||
|
||||
$report->set('name', $data->name)
|
||||
->update();
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete custom report
|
||||
*
|
||||
* @param int $reportid
|
||||
* @return bool
|
||||
* @throws invalid_parameter_exception
|
||||
*/
|
||||
public static function delete_report(int $reportid): bool {
|
||||
$report = report_model::get_record(['id' => $reportid, 'type' => datasource::TYPE_CUSTOM_REPORT]);
|
||||
if ($report === false) {
|
||||
throw new invalid_parameter_exception('Invalid report');
|
||||
}
|
||||
|
||||
return $report->delete();
|
||||
}
|
||||
}
|
@ -21,6 +21,9 @@ namespace core_reportbuilder\local\models;
|
||||
use context;
|
||||
use context_system;
|
||||
use core\persistent;
|
||||
use core_reportbuilder\event\report_created;
|
||||
use core_reportbuilder\event\report_deleted;
|
||||
use core_reportbuilder\event\report_updated;
|
||||
use core_reportbuilder\local\report\base;
|
||||
|
||||
/**
|
||||
@ -91,6 +94,56 @@ class report extends persistent {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger report created event when persistent is created
|
||||
*/
|
||||
protected function after_create(): void {
|
||||
if ($this->get('type') === base::TYPE_CUSTOM_REPORT) {
|
||||
report_created::create_from_object($this)->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cascade report deletion, first deleting any linked persistents
|
||||
*/
|
||||
protected function before_delete(): void {
|
||||
$reportparams = ['reportid' => $this->get('id')];
|
||||
|
||||
// Columns.
|
||||
foreach (column::get_records($reportparams) as $column) {
|
||||
$column->delete();
|
||||
}
|
||||
|
||||
// Filters.
|
||||
foreach (filter::get_records($reportparams) as $filter) {
|
||||
$filter->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw report deleted event when persistent is deleted
|
||||
*
|
||||
* @param bool $result
|
||||
*/
|
||||
protected function after_delete($result): void {
|
||||
if (!$result || $this->get('type') === base::TYPE_SYSTEM_REPORT) {
|
||||
return;
|
||||
}
|
||||
report_deleted::create_from_object($this)->trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw report updated event when persistent is updated
|
||||
*
|
||||
* @param bool $result
|
||||
*/
|
||||
protected function after_update($result): void {
|
||||
if (!$result || $this->get('type') === base::TYPE_SYSTEM_REPORT) {
|
||||
return;
|
||||
}
|
||||
report_updated::create_from_object($this)->trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return report context, used by exporters
|
||||
*
|
||||
|
@ -119,13 +119,6 @@ abstract class base {
|
||||
*/
|
||||
abstract protected function initialise(): void;
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function output(): string;
|
||||
|
||||
/**
|
||||
* Get the report availability. Sub-classes should override this method to declare themselves unavailable, for example if
|
||||
* they require classes that aren't present due to missing plugin
|
||||
@ -258,6 +251,21 @@ abstract class base {
|
||||
$this->entities[$entityname] = $entity->initialise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity added to the report from the given entity name
|
||||
*
|
||||
* @param string $name
|
||||
* @return entity_base
|
||||
* @throws coding_exception
|
||||
*/
|
||||
final protected function get_entity(string $name): entity_base {
|
||||
if (!array_key_exists($name, $this->entities)) {
|
||||
throw new coding_exception('Invalid entity name', $name);
|
||||
}
|
||||
|
||||
return $this->entities[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a new entity for the report
|
||||
*
|
||||
@ -300,6 +308,20 @@ abstract class base {
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given column to the report from an entity
|
||||
*
|
||||
* The entity must have already been added to the report before calling this method
|
||||
*
|
||||
* @param string $uniqueidentifier
|
||||
* @return column
|
||||
*/
|
||||
final protected function add_column_from_entity(string $uniqueidentifier): column {
|
||||
[$entityname, $columnname] = explode(':', $uniqueidentifier, 2);
|
||||
|
||||
return $this->add_column($this->get_entity($entityname)->get_column($columnname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given columns to the report from one or more entities
|
||||
*
|
||||
|
276
reportbuilder/classes/local/systemreports/reports_list.php
Normal file
276
reportbuilder/classes/local/systemreports/reports_list.php
Normal file
@ -0,0 +1,276 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\local\systemreports;
|
||||
|
||||
use html_writer;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use pix_icon;
|
||||
use stdClass;
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\system_report;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
use core_reportbuilder\local\report\action;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use core_reportbuilder\output\report_name_editable;
|
||||
use core_reportbuilder\local\models\report;
|
||||
use core_reportbuilder\permission;
|
||||
|
||||
/**
|
||||
* Reports list
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class reports_list extends system_report {
|
||||
|
||||
/**
|
||||
* The name of our internal report entity
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_report_entity_name(): string {
|
||||
return 'report';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
$this->set_main_table('reportbuilder_report', 'rb');
|
||||
|
||||
$this->add_base_condition_simple('rb.type', self::TYPE_CUSTOM_REPORT);
|
||||
$this->add_base_fields('rb.id, rb.name, rb.source, rb.type, rb.usercreated'); // Necessary for actions/row class.
|
||||
|
||||
// Join user entity for "User modified" column.
|
||||
$entityuser = new user();
|
||||
$entityuseralias = $entityuser->get_table_alias('user');
|
||||
|
||||
$this->add_entity($entityuser
|
||||
->add_join("JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = rb.usermodified")
|
||||
);
|
||||
|
||||
// Define our internal entity for report elements.
|
||||
$this->annotate_entity($this->get_report_entity_name(),
|
||||
new lang_string('customreports', 'core_reportbuilder'));
|
||||
|
||||
$this->add_columns();
|
||||
$this->add_filters();
|
||||
$this->add_actions();
|
||||
|
||||
$this->set_downloadable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can view the report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return permission::can_view_reports_list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dim the table row for invalid datasource
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function get_row_class(stdClass $row): string {
|
||||
return $this->report_source_valid($row->source) ? '' : 'dimmed_text';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to report
|
||||
*/
|
||||
protected function add_columns(): void {
|
||||
$tablealias = $this->get_main_table_alias();
|
||||
|
||||
// Report name column.
|
||||
$this->add_column((new column(
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_report_entity_name()
|
||||
))
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$tablealias}.name, {$tablealias}.id")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(function(string $value, stdClass $row) {
|
||||
global $PAGE;
|
||||
|
||||
$reportid = (int) $row->id;
|
||||
|
||||
$editable = new report_name_editable($reportid);
|
||||
return $editable->render($PAGE->get_renderer('core'));
|
||||
})
|
||||
);
|
||||
|
||||
// Report source column.
|
||||
$this->add_column((new column(
|
||||
'source',
|
||||
new lang_string('reportsource', 'core_reportbuilder'),
|
||||
$this->get_report_entity_name()
|
||||
))
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$tablealias}.source")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(function(string $value, stdClass $row) {
|
||||
if (!$this->report_source_valid($value)) {
|
||||
// Add danger badge if report source is not valid (either it's missing, or has errors).
|
||||
return html_writer::span(get_string('errorsourceinvalid', 'core_reportbuilder'), 'badge badge-danger');
|
||||
}
|
||||
|
||||
return call_user_func([$value, 'get_name']);
|
||||
})
|
||||
);
|
||||
|
||||
// Time created column.
|
||||
$this->add_column((new column(
|
||||
'timecreated',
|
||||
new lang_string('timecreated', 'core_reportbuilder'),
|
||||
$this->get_report_entity_name()
|
||||
))
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_fields("{$tablealias}.timecreated")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate'])
|
||||
);
|
||||
|
||||
// Time modified column.
|
||||
$this->add_column((new column(
|
||||
'timemodified',
|
||||
new lang_string('timemodified', 'core_reportbuilder'),
|
||||
$this->get_report_entity_name()
|
||||
))
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_fields("{$tablealias}.timemodified")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate'])
|
||||
);
|
||||
|
||||
// The user who modified the report.
|
||||
$this->add_column_from_entity('user:fullname');
|
||||
|
||||
// Initial sorting.
|
||||
$this->set_initial_sort_column('report:timecreated', SORT_DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filters to report
|
||||
*/
|
||||
protected function add_filters(): void {
|
||||
$tablealias = $this->get_main_table_alias();
|
||||
|
||||
// Name filter.
|
||||
$this->add_filter((new filter(
|
||||
text::class,
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_report_entity_name(),
|
||||
"{$tablealias}.name"
|
||||
)));
|
||||
|
||||
// Source filter.
|
||||
$this->add_filter((new filter(
|
||||
select::class,
|
||||
'source',
|
||||
new lang_string('reportsource', 'core_reportbuilder'),
|
||||
$this->get_report_entity_name(),
|
||||
"{$tablealias}.source"
|
||||
))
|
||||
->set_options_callback(static function(): array {
|
||||
return manager::get_report_datasources();
|
||||
})
|
||||
);
|
||||
|
||||
// Time created filter.
|
||||
$this->add_filter((new filter(
|
||||
date::class,
|
||||
'timecreated',
|
||||
new lang_string('timecreated', 'core_reportbuilder'),
|
||||
$this->get_report_entity_name(),
|
||||
"{$tablealias}.timecreated"
|
||||
))
|
||||
->set_limited_operators([
|
||||
date::DATE_ANY,
|
||||
date::DATE_RANGE,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add actions to report
|
||||
*/
|
||||
protected function add_actions(): void {
|
||||
$this->add_action((new action(
|
||||
new moodle_url('#'),
|
||||
new pix_icon('t/edit', get_string('editreportdetails', 'core_reportbuilder')),
|
||||
['data-action' => 'report-edit', 'data-report-id' => ':id']
|
||||
))
|
||||
->add_callback(function(stdClass $row): bool {
|
||||
return $this->report_source_valid($row->source) && permission::can_edit_report($this->get_report_from_row($row));
|
||||
})
|
||||
);
|
||||
|
||||
$this->add_action((new action(
|
||||
new moodle_url('#'),
|
||||
new pix_icon('t/delete', get_string('deletereport', 'core_reportbuilder')),
|
||||
['data-action' => 'report-delete', 'data-report-id' => ':id', 'data-report-name' => ':name']
|
||||
))
|
||||
->add_callback(function(stdClass $row): bool {
|
||||
// We don't check whether report is valid to ensure editor can always delete them.
|
||||
return permission::can_edit_report($this->get_report_from_row($row));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to determine whether given report source is valid (it both exists, and is available)
|
||||
*
|
||||
* @param string $source
|
||||
* @return bool
|
||||
*/
|
||||
private function report_source_valid(string $source): bool {
|
||||
return manager::report_source_exists($source, datasource::class) && manager::report_source_available($source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to return the report persistent from the row object.
|
||||
*
|
||||
* Note that this persistent, for performance reasons, is not complete and only contains id/type/usercreated fields, which
|
||||
* are needed for the permission methods.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return report
|
||||
*/
|
||||
private function get_report_from_row(stdClass $row): report {
|
||||
return new report(0, (object)[
|
||||
'id' => $row->id,
|
||||
'type' => $row->type,
|
||||
'usercreated' => $row->usercreated,
|
||||
]);
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder;
|
||||
|
||||
use core_component;
|
||||
use core_plugin_manager;
|
||||
use stdClass;
|
||||
use core_reportbuilder\local\models\report;
|
||||
use core_reportbuilder\local\report\base;
|
||||
@ -53,6 +55,19 @@ class manager {
|
||||
return new $source($report, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of a report class from the given report ID
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param array $parameters
|
||||
* @return base
|
||||
*/
|
||||
public static function get_report_from_id(int $reportid, array $parameters = []): base {
|
||||
$report = new report($reportid);
|
||||
|
||||
return self::get_report_from_persistent($report, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that report source exists and extends appropriate base classes
|
||||
*
|
||||
@ -84,4 +99,30 @@ class manager {
|
||||
public static function create_report_persistent(stdClass $reportdata): report {
|
||||
return (new report(0, $reportdata))->create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of all valid report sources across the site
|
||||
*
|
||||
* @return array[][] Indexed by [component => [class => name]]
|
||||
*/
|
||||
public static function get_report_datasources(): array {
|
||||
$sources = array();
|
||||
|
||||
$datasources = core_component::get_component_classes_in_namespace(null, 'reportbuilder\\datasource');
|
||||
foreach ($datasources as $class => $path) {
|
||||
if (self::report_source_exists($class, datasource::class) && self::report_source_available($class)) {
|
||||
[$component] = explode('\\', $class);
|
||||
|
||||
if ($plugininfo = core_plugin_manager::instance()->get_plugin_info($component)) {
|
||||
$componentname = $plugininfo->displayname;
|
||||
} else {
|
||||
$componentname = get_string('site');
|
||||
}
|
||||
|
||||
$sources[$componentname][$class] = call_user_func([$class, 'get_name']);
|
||||
}
|
||||
}
|
||||
|
||||
return $sources;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\output;
|
||||
|
||||
use html_writer;
|
||||
use plugin_renderer_base;
|
||||
use core_reportbuilder\table\system_report_table;
|
||||
|
||||
@ -56,4 +57,16 @@ class renderer extends plugin_renderer_base {
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the New report button
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render_new_report_button(): string {
|
||||
return html_writer::tag('button', get_string('newreport', 'core_reportbuilder'), [
|
||||
'class' => 'btn btn-primary my-auto',
|
||||
'data-action' => 'report-create',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
82
reportbuilder/classes/output/report_name_editable.php
Normal file
82
reportbuilder/classes/output/report_name_editable.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\output;
|
||||
|
||||
use core_external;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use core\output\inplace_editable;
|
||||
use core_reportbuilder\permission;
|
||||
use core_reportbuilder\local\models\report;
|
||||
|
||||
/**
|
||||
* Report name editable component
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class report_name_editable extends inplace_editable {
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param report|null $report
|
||||
*/
|
||||
public function __construct(int $reportid, ?report $report = null) {
|
||||
if ($report === null) {
|
||||
$report = new report($reportid);
|
||||
}
|
||||
|
||||
$editable = permission::can_edit_report($report);
|
||||
|
||||
$url = $editable
|
||||
? new moodle_url('/reportbuilder/edit.php', ['id' => $report->get('id')])
|
||||
: new moodle_url('/reportbuilder/view.php', ['id' => $report->get('id')]);
|
||||
|
||||
$displayvalue = html_writer::link($url, $report->get_formatted_name());
|
||||
|
||||
parent::__construct('core_reportbuilder', 'reportname', $report->get('id'), $editable, $displayvalue, $report->get('name'),
|
||||
get_string('editreportname', 'core_reportbuilder'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update report persistent and return self, called from inplace_editable callback
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param string $value
|
||||
* @return self
|
||||
*/
|
||||
public static function update(int $reportid, string $value): self {
|
||||
$report = new report($reportid);
|
||||
|
||||
core_external::validate_context($report->get_context());
|
||||
permission::require_can_edit_report($report);
|
||||
|
||||
$value = clean_param($value, PARAM_TEXT);
|
||||
if ($value !== '') {
|
||||
$report
|
||||
->set('name', $value)
|
||||
->update();
|
||||
}
|
||||
|
||||
return new self(0, $report);
|
||||
}
|
||||
}
|
115
reportbuilder/classes/permission.php
Normal file
115
reportbuilder/classes/permission.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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder;
|
||||
|
||||
use context_system;
|
||||
use core_reportbuilder\local\models\report;
|
||||
use core_reportbuilder\local\report\base;
|
||||
|
||||
/**
|
||||
* Report permission class
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class permission {
|
||||
|
||||
/**
|
||||
* Require given user can view reports list
|
||||
*
|
||||
* @param int|null $userid User ID to check, or the current user if omitted
|
||||
* @throws report_access_exception
|
||||
*/
|
||||
public static function require_can_view_reports_list(?int $userid = null): void {
|
||||
if (!static::can_view_reports_list($userid)) {
|
||||
throw new report_access_exception();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether given user can view reports list
|
||||
*
|
||||
* @param int|null $userid User ID to check, or the current user if omitted
|
||||
* @return bool
|
||||
*/
|
||||
public static function can_view_reports_list(?int $userid = null): bool {
|
||||
return has_capability('moodle/reportbuilder:view', context_system::instance(), $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Require given user can edit report
|
||||
*
|
||||
* @param report $report
|
||||
* @param int|null $userid User ID to check, or the current user if omitted
|
||||
* @return void
|
||||
* @throws report_access_exception
|
||||
*/
|
||||
public static function require_can_edit_report(report $report, ?int $userid = null): void {
|
||||
if (!static::can_edit_report($report, $userid)) {
|
||||
throw new report_access_exception('errorreportedit');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether given user can edit report
|
||||
*
|
||||
* @param report $report
|
||||
* @param int|null $userid User ID to check, or the current user if omitted
|
||||
* @return bool
|
||||
*/
|
||||
public static function can_edit_report(report $report, ?int $userid = null): bool {
|
||||
global $USER;
|
||||
|
||||
// We can only edit custom reports.
|
||||
if ($report->get('type') !== base::TYPE_CUSTOM_REPORT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$userid = $userid ?: (int) $USER->id;
|
||||
if ($report->get('usercreated') === $userid) {
|
||||
return has_capability('moodle/reportbuilder:edit', context_system::instance(), $userid);
|
||||
} else {
|
||||
return has_capability('moodle/reportbuilder:editall', context_system::instance(), $userid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether given user can create a new report
|
||||
*
|
||||
* @param int|null $userid User ID to check, or the current user if omitted
|
||||
* @return bool
|
||||
*/
|
||||
public static function can_create_report(?int $userid = null): bool {
|
||||
$capabilities = ['moodle/reportbuilder:edit', 'moodle/reportbuilder:editall'];
|
||||
return has_any_capability($capabilities, context_system::instance(), $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Require given user can create a new report
|
||||
*
|
||||
* @param int|null $userid User ID to check, or the current user if omitted
|
||||
* @throws report_access_exception
|
||||
*/
|
||||
public static function require_can_create_report(?int $userid = null): void {
|
||||
if (!static::can_create_report($userid)) {
|
||||
throw new report_access_exception('errorreportcreate');
|
||||
}
|
||||
}
|
||||
}
|
53
reportbuilder/index.php
Normal file
53
reportbuilder/index.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/>.
|
||||
|
||||
/**
|
||||
* List of custom reports
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use core_reportbuilder\permission;
|
||||
use core_reportbuilder\system_report_factory;
|
||||
use core_reportbuilder\local\systemreports\reports_list;
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
admin_externalpage_setup('customreports');
|
||||
|
||||
$PAGE->requires->js_call_amd('core_reportbuilder/reports_list', 'init');
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo html_writer::start_div('d-flex justify-content-between mb-2');
|
||||
echo $OUTPUT->heading(get_string('customreports', 'core_reportbuilder'));
|
||||
|
||||
if (permission::can_create_report()) {
|
||||
/** @var \core_reportbuilder\output\renderer $renderer */
|
||||
$renderer = $PAGE->get_renderer('core_reportbuilder');
|
||||
echo $renderer->render_new_report_button();
|
||||
}
|
||||
|
||||
echo html_writer::end_div();
|
||||
|
||||
$report = system_report_factory::create(reports_list::class, context_system::instance());
|
||||
echo $report->output();
|
||||
|
||||
echo $OUTPUT->footer();
|
@ -42,3 +42,23 @@ function core_reportbuilder_output_fragment_filters_form(array $params): string
|
||||
|
||||
return $filtersform->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin inplace editable implementation
|
||||
*
|
||||
* @param string $itemtype
|
||||
* @param int $itemid
|
||||
* @param string $newvalue
|
||||
* @return \core\output\inplace_editable|bool
|
||||
*/
|
||||
function core_reportbuilder_inplace_editable($itemtype, $itemid, $newvalue) {
|
||||
$itemid = (int) $itemid;
|
||||
|
||||
switch ($itemtype) {
|
||||
case 'reportname':
|
||||
return \core_reportbuilder\output\report_name_editable::update($itemid, $newvalue);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
62
user/classes/reportbuilder/datasource/users.php
Normal file
62
user/classes/reportbuilder/datasource/users.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_user\reportbuilder\datasource;
|
||||
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\helpers\database;
|
||||
|
||||
/**
|
||||
* Users datasource
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class users extends datasource {
|
||||
|
||||
/**
|
||||
* Return user friendly name of the datasource
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('users');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
global $CFG;
|
||||
|
||||
$userentity = new user();
|
||||
$usertablealias = $userentity->get_table_alias('user');
|
||||
|
||||
$this->set_main_table('user', $usertablealias);
|
||||
|
||||
$userparamguest = database::generate_param_name();
|
||||
$this->add_base_condition_sql("{$usertablealias}.id != :{$userparamguest} AND {$usertablealias}.deleted = 0", [
|
||||
$userparamguest => $CFG->siteguest,
|
||||
]);
|
||||
|
||||
// Add all columns from entities to be available in custom reports.
|
||||
$this->add_entity($userentity);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user