Merge branch 'MDL-67914-master' of git://github.com/lameze/moodle
This commit is contained in:
@@ -2744,6 +2744,14 @@ $functions = array(
|
||||
'capabilities' => '',
|
||||
'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE],
|
||||
],
|
||||
'core_table_dynamic_fetch' => [
|
||||
'classname' => 'core_table\external\dynamic\fetch',
|
||||
'methodname' => 'execute',
|
||||
'description' => 'Fetch a dynamic table view raw html',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE],
|
||||
],
|
||||
);
|
||||
|
||||
$services = array(
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
define ("core_table/dynamic",["exports","core_table/local/dynamic/repository","core_table/local/dynamic/selectors"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=a.setSortOrder=a.setFilters=a.updateTable=a.refreshTableContent=void 0;c=function(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}(c);function d(a){return g(a)||f(a)||e()}function e(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function f(a){if(Symbol.iterator in Object(a)||"[object Arguments]"===Object.prototype.toString.call(a))return Array.from(a)}function g(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b<a.length;b++){c[b]=a[b]}return c}}var h=!1,i=function(a){if(!a){throw new Error("The table specified is not a dynamic table and cannot be updated")}if(!a.matches(c.table.region)){throw new Error("The table specified is not a dynamic table and cannot be updated")}return!0},j=function(a){return JSON.parse(a.dataset.tableFilters)},k=function(a){var c=j(a);return(0,b.fetch)(a.dataset.tableHandler,a.dataset.tableUniqueid,{sortBy:a.dataset.tableSortBy,sortOrder:a.dataset.tableSortOrder,joinType:c.jointype,filters:c.filters}).then(function(b){var c=document.createElement("div");c.innerHTML=b.html;a.replaceWith.apply(a,d(c.childNodes));return b})};a.refreshTableContent=k;var l=function(a){var b=1<arguments.length&&arguments[1]!==void 0?arguments[1]:{},c=b.sortBy,d=void 0===c?null:c,e=b.sortOrder,f=void 0===e?null:e,g=b.filters,h=void 0===g?null:g,j=2<arguments.length&&arguments[2]!==void 0?arguments[2]:!0;i(a);if(d&&f){a.dataset.tableSortBy=d;a.dataset.tableSortOrder=f}if(h){a.dataset.tableFilters=JSON.stringify(h)}if(j){return k(a)}else{return Promise.resolve()}};a.updateTable=l;a.setFilters=function setFilters(a,b){var c=2<arguments.length&&arguments[2]!==void 0?arguments[2]:!0;return l(a,{filters:b},c)};var m=function(a,b,c){var d=3<arguments.length&&arguments[3]!==void 0?arguments[3]:!0;return l(a,{sortBy:b,sortOrder:c},d)};a.setSortOrder=m;var n=function(){if(h){return}h=!0;document.addEventListener("click",function(a){var b=a.target.closest(c.table.region);if(!b){return}var d=a.target.closest(c.table.links.sortableColumn);if(d){a.preventDefault();m(b,d.dataset.sortby,d.dataset.sortorder)}})};a.init=n});
|
||||
//# sourceMappingURL=dynamic.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
define ("core_table/local/dynamic/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.fetch=void 0;a.fetch=function fetch(a,c){var d=2<arguments.length&&arguments[2]!==void 0?arguments[2]:{},e=d.sortBy,f=void 0===e?null:e,g=d.sortOrder,h=void 0===g?null:g,i=d.joinType,j=void 0===i?null:i,k=d.filters,l=void 0===k?{}:k;return(0,b.call)([{methodname:"core_table_dynamic_fetch",args:{handler:a,uniqueid:c,sortby:f,sortorder:h,jointype:j,filters:l}}])[0]}});
|
||||
//# sourceMappingURL=repository.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/local/dynamic/repository.js"],"names":["fetch","handler","uniqueid","sortBy","sortOrder","joinType","filters","methodname","args","sortby","sortorder","jointype"],"mappings":"yKAmCqB,QAARA,CAAAA,KAAQ,CAACC,CAAD,CAAUC,CAAV,CAMhB,8DADG,EACH,KALGC,MAKH,CALGA,CAKH,YALY,IAKZ,OAJGC,SAIH,CAJGA,CAIH,YAJe,IAIf,OAHGC,QAGH,CAHGA,CAGH,YAHc,IAGd,OAFGC,OAEH,CAFGA,CAEH,YAFa,EAEb,GACD,MAAO,WAAU,CAAC,CACdC,UAAU,2BADI,CAEdC,IAAI,CAAE,CACFP,OAAO,CAAPA,CADE,CAEFC,QAAQ,CAARA,CAFE,CAGFO,MAAM,CAAEN,CAHN,CAIFO,SAAS,CAAEN,CAJT,CAKFO,QAAQ,CAAEN,CALR,CAMFC,OAAO,CAAPA,CANE,CAFQ,CAAD,CAAV,EAUH,CAVG,CAWV,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 * A javascript module to handle calendar ajax actions.\n *\n * @module core_calendar/repository\n * @class repository\n * @package core_calendar\n * @copyright 2017 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * Fetch table view.\n *\n * @method fetch\n * @param {String} handler The name of the handler\n * @param {String} uniqueid The unique id of the table\n * @param {Number} params parameters to request table\n * @return {Promise} Resolved with requested table view\n */\nexport const fetch = (handler, uniqueid, {\n sortBy = null,\n sortOrder = null,\n joinType = null,\n filters = {}\n } = {}\n) => {\n return fetchMany([{\n methodname: `core_table_dynamic_fetch`,\n args: {\n handler,\n uniqueid,\n sortby: sortBy,\n sortorder: sortOrder,\n jointype: joinType,\n filters,\n },\n }])[0];\n};\n"],"file":"repository.min.js"}
|
||||
@@ -0,0 +1,2 @@
|
||||
define ("core_table/local/dynamic/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={table:{region:"[data-region=\"core_table/dynamic\"]",links:{sortableColumn:"a[data-sortable=\"1\"]"}}};return a.default});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/local/dynamic/selectors.js"],"names":["table","region","links","sortableColumn"],"mappings":"8JAuBe,CACXA,KAAK,CAAE,CACHC,MAAM,CAAE,sCADL,CAEHC,KAAK,CAAE,CACHC,cAAc,CAAE,wBADb,CAFJ,CADI,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 * Dynamic table selectors.\n *\n * @module core_table/selectors\n * @package core_table\n * @copyright 2020 Simey Lameze <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n table: {\n region: '[data-region=\"core_table/dynamic\"]',\n links: {\n sortableColumn: 'a[data-sortable=\"1\"]',\n },\n },\n};\n"],"file":"selectors.min.js"}
|
||||
@@ -0,0 +1,160 @@
|
||||
// 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 dynamic table features.
|
||||
*
|
||||
* @module core_table/dynamic
|
||||
* @package core_table
|
||||
* @copyright 2020 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
import {fetch as fetchTableData} from 'core_table/local/dynamic/repository';
|
||||
import * as Selectors from 'core_table/local/dynamic/selectors';
|
||||
|
||||
let watching = false;
|
||||
|
||||
/**
|
||||
* Ensure that a table is a dynamic table.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @returns {Bool}
|
||||
*/
|
||||
const checkTableIsDynamic = tableRoot => {
|
||||
if (!tableRoot) {
|
||||
// The table is not a dynamic table.
|
||||
throw new Error("The table specified is not a dynamic table and cannot be updated");
|
||||
}
|
||||
|
||||
if (!tableRoot.matches(Selectors.table.region)) {
|
||||
// The table is not a dynamic table.
|
||||
throw new Error("The table specified is not a dynamic table and cannot be updated");
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the filterset data from a known dynamic table.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @returns {Object}
|
||||
*/
|
||||
const getFiltersetFromTable = tableRoot => {
|
||||
return JSON.parse(tableRoot.dataset.tableFilters);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the specified table based on its current values.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const refreshTableContent = tableRoot => {
|
||||
const filterset = getFiltersetFromTable(tableRoot);
|
||||
|
||||
return fetchTableData(
|
||||
tableRoot.dataset.tableHandler,
|
||||
tableRoot.dataset.tableUniqueid,
|
||||
{
|
||||
sortBy: tableRoot.dataset.tableSortBy,
|
||||
sortOrder: tableRoot.dataset.tableSortOrder,
|
||||
joinType: filterset.jointype,
|
||||
filters: filterset.filters,
|
||||
}
|
||||
)
|
||||
.then(data => {
|
||||
const placeholder = document.createElement('div');
|
||||
placeholder.innerHTML = data.html;
|
||||
tableRoot.replaceWith(...placeholder.childNodes);
|
||||
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
export const updateTable = (tableRoot, {
|
||||
sortBy = null,
|
||||
sortOrder = null,
|
||||
filters = null,
|
||||
} = {}, refreshContent = true) => {
|
||||
checkTableIsDynamic(tableRoot);
|
||||
|
||||
// Update sort fields.
|
||||
if (sortBy && sortOrder) {
|
||||
tableRoot.dataset.tableSortBy = sortBy;
|
||||
tableRoot.dataset.tableSortOrder = sortOrder;
|
||||
}
|
||||
|
||||
// Update filters.
|
||||
if (filters) {
|
||||
tableRoot.dataset.tableFilters = JSON.stringify(filters);
|
||||
}
|
||||
|
||||
// Refresh.
|
||||
if (refreshContent) {
|
||||
return refreshTableContent(tableRoot);
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the specified table using the new filters.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @param {Object} filters
|
||||
* @param {Bool} refreshContent
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const setFilters = (tableRoot, filters, refreshContent = true) =>
|
||||
updateTable(tableRoot, {filters}, refreshContent);
|
||||
|
||||
/**
|
||||
* Update the sort order.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @param {String} sortBy
|
||||
* @param {Number} sortOrder
|
||||
* @param {Bool} refreshContent
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const setSortOrder = (tableRoot, sortBy, sortOrder, refreshContent = true) =>
|
||||
updateTable(tableRoot, {sortBy, sortOrder}, refreshContent);
|
||||
|
||||
/**
|
||||
* Set up listeners to handle table updates.
|
||||
*/
|
||||
export const init = () => {
|
||||
if (watching) {
|
||||
// Already watching.
|
||||
return;
|
||||
}
|
||||
watching = true;
|
||||
|
||||
document.addEventListener('click', e => {
|
||||
const tableRoot = e.target.closest(Selectors.table.region);
|
||||
|
||||
if (!tableRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sortableLink = e.target.closest(Selectors.table.links.sortableColumn);
|
||||
if (sortableLink) {
|
||||
e.preventDefault();
|
||||
|
||||
setSortOrder(tableRoot, sortableLink.dataset.sortby, sortableLink.dataset.sortorder);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A javascript module to handle calendar ajax actions.
|
||||
*
|
||||
* @module core_calendar/repository
|
||||
* @class repository
|
||||
* @package core_calendar
|
||||
* @copyright 2017 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
import {call as fetchMany} from 'core/ajax';
|
||||
|
||||
/**
|
||||
* Fetch table view.
|
||||
*
|
||||
* @method fetch
|
||||
* @param {String} handler The name of the handler
|
||||
* @param {String} uniqueid The unique id of the table
|
||||
* @param {Number} params parameters to request table
|
||||
* @return {Promise} Resolved with requested table view
|
||||
*/
|
||||
export const fetch = (handler, uniqueid, {
|
||||
sortBy = null,
|
||||
sortOrder = null,
|
||||
joinType = null,
|
||||
filters = {}
|
||||
} = {}
|
||||
) => {
|
||||
return fetchMany([{
|
||||
methodname: `core_table_dynamic_fetch`,
|
||||
args: {
|
||||
handler,
|
||||
uniqueid,
|
||||
sortby: sortBy,
|
||||
sortorder: sortOrder,
|
||||
jointype: joinType,
|
||||
filters,
|
||||
},
|
||||
}])[0];
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Dynamic table selectors.
|
||||
*
|
||||
* @module core_table/selectors
|
||||
* @package core_table
|
||||
* @copyright 2020 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
export default {
|
||||
table: {
|
||||
region: '[data-region="core_table/dynamic"]',
|
||||
links: {
|
||||
sortableColumn: 'a[data-sortable="1"]',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -30,6 +30,7 @@ namespace core_table;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use moodle_url;
|
||||
use context;
|
||||
use core_table\local\filter\filterset;
|
||||
|
||||
/**
|
||||
@@ -57,7 +58,7 @@ interface dynamic {
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public static function get_base_url(): moodle_url;
|
||||
public function get_base_url(): moodle_url;
|
||||
|
||||
/**
|
||||
* Set the filterset filters build table object.
|
||||
@@ -66,4 +67,20 @@ interface dynamic {
|
||||
* @return void
|
||||
*/
|
||||
public function set_filterset(filterset $filterset): void;
|
||||
|
||||
/**
|
||||
* Get the currently defined filterset.
|
||||
*
|
||||
* @return filterset
|
||||
*/
|
||||
public function get_filterset(): ?filterset;
|
||||
|
||||
/**
|
||||
* Get the context of the current table.
|
||||
*
|
||||
* Note: This function should not be called until after the filterset has been provided.
|
||||
*
|
||||
* @return context
|
||||
*/
|
||||
public function get_context(): ?context;
|
||||
}
|
||||
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Table external API.
|
||||
*
|
||||
* @package core_table
|
||||
* @category external
|
||||
* @copyright 2020 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_table\external\dynamic;
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_multiple_structure;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use external_warnings;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Core table external functions.
|
||||
*
|
||||
* @package core_table
|
||||
* @category external
|
||||
* @copyright 2020 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class fetch extends external_api {
|
||||
|
||||
/**
|
||||
* Describes the parameters for fetching the table html.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.9
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters ([
|
||||
'handler' => new external_value(
|
||||
// Note: We do not have a PARAM_CLASSNAME which would have been ideal.
|
||||
PARAM_RAW,
|
||||
'Handler',
|
||||
VALUE_REQUIRED
|
||||
),
|
||||
'uniqueid' => new external_value(
|
||||
PARAM_ALPHANUMEXT,
|
||||
'Unique ID for the container',
|
||||
VALUE_REQUIRED
|
||||
),
|
||||
'sortby' => new external_value(
|
||||
PARAM_ALPHANUMEXT,
|
||||
'The name of a sortable column',
|
||||
VALUE_REQUIRED
|
||||
),
|
||||
'sortorder' => new external_value(
|
||||
PARAM_ALPHANUMEXT,
|
||||
'The sort order',
|
||||
VALUE_REQUIRED
|
||||
),
|
||||
'filters' => new external_multiple_structure(
|
||||
new external_single_structure([
|
||||
'name' => new external_value(PARAM_ALPHANUM, 'Name of the filter', VALUE_REQUIRED),
|
||||
'jointype' => new external_value(PARAM_INT, 'Type of join for filter values', VALUE_REQUIRED),
|
||||
'values' => new external_multiple_structure(
|
||||
new external_value(PARAM_RAW, 'Filter value'),
|
||||
'The value to filter on',
|
||||
VALUE_REQUIRED
|
||||
)
|
||||
]),
|
||||
'The filters that will be applied in the request',
|
||||
VALUE_OPTIONAL
|
||||
),
|
||||
'jointype' => new external_value(PARAM_INT, 'Type of join to join all filters together', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* External function to fetch a table view.
|
||||
*
|
||||
* @param string $handler Dynamic table class name.
|
||||
* @param string $uniqueid Unique ID for the container.
|
||||
* @param string $sortby The name of a sortable column.
|
||||
* @param string $sortorder The sort order.
|
||||
* @param array $filters The filters that will be applied in the request.
|
||||
* @param string $jointype The join type.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(string $handler, string $uniqueid, string $sortby, string $sortorder,
|
||||
array $filters = [], string $jointype = null) {
|
||||
|
||||
global $PAGE;
|
||||
|
||||
if (!class_exists($handler) || !is_subclass_of($handler, \core_table\dynamic::class)) {
|
||||
throw new \UnexpectedValueException('Unknown table handler, or table handler does not support dynamic updating.');
|
||||
}
|
||||
|
||||
[
|
||||
'handler' => $handler,
|
||||
'uniqueid' => $uniqueid,
|
||||
'sortby' => $sortby,
|
||||
'sortorder' => $sortorder,
|
||||
'filters' => $filters,
|
||||
'jointype' => $jointype,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'handler' => $handler,
|
||||
'uniqueid' => $uniqueid,
|
||||
'sortby' => $sortby,
|
||||
'sortorder' => $sortorder,
|
||||
'filters' => $filters,
|
||||
'jointype' => $jointype,
|
||||
]);
|
||||
|
||||
$filterset = new \core_user\table\participants_filterset();
|
||||
foreach ($filters as $rawfilter) {
|
||||
$filterset->add_filter_from_params(
|
||||
$rawfilter['name'],
|
||||
$rawfilter['jointype'],
|
||||
$rawfilter['values']
|
||||
);
|
||||
}
|
||||
|
||||
$instance = new $handler($uniqueid);
|
||||
$instance->set_filterset($filterset);
|
||||
$instance->set_sorting($sortby, $sortorder);
|
||||
|
||||
$context = $instance->get_context();
|
||||
|
||||
self::validate_context($context);
|
||||
$PAGE->set_url($instance->get_base_url());
|
||||
|
||||
ob_start();
|
||||
$instance->out(20, true);
|
||||
$participanttablehtml = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return [
|
||||
'html' => $participanttablehtml,
|
||||
'warnings' => []
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the data returned from the external function.
|
||||
*
|
||||
* @return external_single_structure
|
||||
* @since Moodle 3.9
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([
|
||||
'html' => new external_value(PARAM_RAW, 'The raw html of the requested table.'),
|
||||
'warnings' => new external_warnings()
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ declare(strict_types=1);
|
||||
namespace core_table\local\filter;
|
||||
|
||||
use Countable;
|
||||
use JsonSerializable;
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
|
||||
@@ -38,7 +39,7 @@ use Iterator;
|
||||
* @copyright 2020 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class filter implements Countable, Iterator {
|
||||
class filter implements Countable, Iterator, JsonSerializable {
|
||||
|
||||
/** @var in The default filter type (ANY) */
|
||||
const JOINTYPE_DEFAULT = 1;
|
||||
@@ -251,4 +252,17 @@ class filter implements Countable, Iterator {
|
||||
$this->sort_filter_values();
|
||||
return $this->filtervalues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize filter.
|
||||
*
|
||||
* @return mixed|object
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return (object) [
|
||||
'name' => $this->get_name(),
|
||||
'jointype' => $this->get_join_type(),
|
||||
'values' => $this->get_filter_values(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ declare(strict_types=1);
|
||||
namespace core_table\local\filter;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use JsonSerializable;
|
||||
use UnexpectedValueException;
|
||||
use moodle_exception;
|
||||
|
||||
@@ -38,7 +39,7 @@ use moodle_exception;
|
||||
* @copyright 2020 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class filterset {
|
||||
abstract class filterset implements JsonSerializable {
|
||||
/** @var in The default filter type (ANY) */
|
||||
const JOINTYPE_DEFAULT = 1;
|
||||
|
||||
@@ -285,4 +286,16 @@ abstract class filterset {
|
||||
|
||||
return $this->filtertypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize filterset.
|
||||
*
|
||||
* @return mixed|object
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return (object) [
|
||||
'jointype' => $this->get_join_type(),
|
||||
'filters' => $this->get_filters(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_table\external\fetch;
|
||||
*
|
||||
* @package core_table
|
||||
* @category test
|
||||
* @copyright 2020 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace core_table\external\dynamic;
|
||||
|
||||
use core_table\local\filter\filter;
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for core_table\external\fetch;
|
||||
*
|
||||
* @package core_table
|
||||
* @category test
|
||||
* @copyright 2020 Simey Lameze <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class fetch_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Setup before class.
|
||||
*/
|
||||
public static function setUpBeforeClass(): void {
|
||||
global $CFG;
|
||||
require_once("{$CFG->libdir}/externallib.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute invalid handler.
|
||||
*/
|
||||
public function test_execute_invalid_handler(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->expectException('UnexpectedValueException');
|
||||
$this->expectExceptionMessage("Unknown table handler, or table handler does not support dynamic updating.");
|
||||
|
||||
// Tests that invalid users_participants_table class gets an exception.
|
||||
fetch::execute("core_user\users_participants_table", "", "email", "4", [], "1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute invalid filter.
|
||||
*/
|
||||
public function test_execute_invalid_filter(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Filter with an invalid name.
|
||||
$filter = [
|
||||
[
|
||||
'fullname' => 'courseid',
|
||||
'jointype' => filter::JOINTYPE_ANY,
|
||||
'values' => [(int)$course->id]
|
||||
]
|
||||
];
|
||||
$this->expectException('invalid_parameter_exception');
|
||||
$this->expectExceptionMessage("Invalid parameter value detected (filters => Invalid parameter value detected " .
|
||||
"(Missing required key in single structure: name): Missing required key in single structure: name");
|
||||
|
||||
fetch::execute("core_user\participants_table",
|
||||
"user-index-participants-{$course->id}", "firstname", "4", $filter, (string)filter::JOINTYPE_ANY);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute fetch table.
|
||||
*/
|
||||
public function test_execute_fetch_table(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user1 = $this->getDataGenerator()->create_and_enrol($course, 'student', ['email' => '[email protected]']);
|
||||
$user2 = $this->getDataGenerator()->create_and_enrol($course, 'student', ['email' => '[email protected]']);
|
||||
$user3 = $this->getDataGenerator()->create_user(['email' => '[email protected]']);
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher', ['email' => '[email protected]']);
|
||||
|
||||
$this->setUser($teacher);
|
||||
|
||||
$filter = [
|
||||
[
|
||||
'name' => 'courseid',
|
||||
'jointype' => filter::JOINTYPE_ANY,
|
||||
'values' => [(int)$course->id]
|
||||
]
|
||||
];
|
||||
|
||||
$participantstable = fetch::execute("core_user\participants_table",
|
||||
"user-index-participants-{$course->id}", "firstname", "4", $filter, (string)filter::JOINTYPE_ANY);
|
||||
$html = $participantstable['html'];
|
||||
|
||||
$this->assertStringContainsString($user1->email, $html);
|
||||
$this->assertStringContainsString($user2->email, $html);
|
||||
$this->assertStringContainsString($teacher->email, $html);
|
||||
$this->assertStringNotContainsString($user3->email, $html);
|
||||
}
|
||||
}
|
||||
+105
-34
@@ -84,6 +84,17 @@ class flexible_table {
|
||||
private $persistent = false;
|
||||
var $is_collapsible = false;
|
||||
var $is_sortable = false;
|
||||
|
||||
/**
|
||||
* @var string The field name to sort by.
|
||||
*/
|
||||
protected $sortby;
|
||||
|
||||
/**
|
||||
* @var string $sortorder The direction for sorting.
|
||||
*/
|
||||
protected $sortorder;
|
||||
|
||||
var $use_pages = false;
|
||||
var $use_initials = false;
|
||||
|
||||
@@ -513,35 +524,7 @@ class flexible_table {
|
||||
}
|
||||
}
|
||||
|
||||
if (($sortcol = optional_param($this->request[TABLE_VAR_SORT], '', PARAM_ALPHANUMEXT)) &&
|
||||
$this->is_sortable($sortcol) && empty($this->prefs['collapse'][$sortcol]) &&
|
||||
(isset($this->columns[$sortcol]) || in_array($sortcol, get_all_user_name_fields())
|
||||
&& isset($this->columns['fullname']))) {
|
||||
|
||||
$sortdir = optional_param($this->request[TABLE_VAR_DIR], $this->sort_default_order, PARAM_INT);
|
||||
|
||||
if (array_key_exists($sortcol, $this->prefs['sortby'])) {
|
||||
// This key already exists somewhere. Change its sortorder and bring it to the top.
|
||||
$sortorder = $this->prefs['sortby'][$sortcol] = $sortdir;
|
||||
unset($this->prefs['sortby'][$sortcol]);
|
||||
$this->prefs['sortby'] = array_merge(array($sortcol => $sortorder), $this->prefs['sortby']);
|
||||
} else {
|
||||
// Key doesn't exist, so just add it to the beginning of the array, ascending order
|
||||
$this->prefs['sortby'] = array_merge(array($sortcol => $sortdir), $this->prefs['sortby']);
|
||||
}
|
||||
|
||||
// Finally, make sure that no more than $this->maxsortkeys are present into the array
|
||||
$this->prefs['sortby'] = array_slice($this->prefs['sortby'], 0, $this->maxsortkeys);
|
||||
}
|
||||
|
||||
// MDL-35375 - If a default order is defined and it is not in the current list of order by columns, add it at the end.
|
||||
// This prevents results from being returned in a random order if the only order by column contains equal values.
|
||||
if (!empty($this->sort_default_column)) {
|
||||
if (!array_key_exists($this->sort_default_column, $this->prefs['sortby'])) {
|
||||
$defaultsort = array($this->sort_default_column => $this->sort_default_order);
|
||||
$this->prefs['sortby'] = array_merge($this->prefs['sortby'], $defaultsort);
|
||||
}
|
||||
}
|
||||
$this->set_sorting_preferences();
|
||||
|
||||
$ilast = optional_param($this->request[TABLE_VAR_ILAST], null, PARAM_RAW);
|
||||
if (!is_null($ilast) && ($ilast ==='' || strpos(get_string('alphabet', 'langconfig'), $ilast) !== false)) {
|
||||
@@ -1158,7 +1141,8 @@ class flexible_table {
|
||||
* This function is not part of the public api.
|
||||
*/
|
||||
function finish_html() {
|
||||
global $OUTPUT;
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
if (!$this->started_output) {
|
||||
//no data has been added to the table.
|
||||
$this->print_nothing_to_display();
|
||||
@@ -1187,6 +1171,13 @@ class flexible_table {
|
||||
$pagingbar->pagevar = $this->request[TABLE_VAR_PAGE];
|
||||
echo $OUTPUT->render($pagingbar);
|
||||
}
|
||||
|
||||
// Dynamic Table content.
|
||||
if (is_a($this, \core_table\dynamic::class)) {
|
||||
echo html_writer::end_tag('div');
|
||||
|
||||
$PAGE->requires->js_call_amd('core_table/dynamic', 'init');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1322,6 +1313,57 @@ class flexible_table {
|
||||
echo html_writer::end_tag('thead');
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the preferences for sort order based on user-supplied values and get params.
|
||||
*/
|
||||
protected function set_sorting_preferences(): void {
|
||||
$sortorder = $this->sortorder;
|
||||
$sortby = $this->sortby;
|
||||
|
||||
if ($sortorder === null || $sortby === null) {
|
||||
$sortorder = optional_param($this->request[TABLE_VAR_DIR], $this->sort_default_order, PARAM_INT);
|
||||
$sortby = optional_param($this->request[TABLE_VAR_SORT], '', PARAM_ALPHANUMEXT);
|
||||
}
|
||||
|
||||
$isvalidsort = $sortby && $this->is_sortable($sortby);
|
||||
$isvalidsort = $isvalidsort && empty($this->prefs['collapse'][$sortby]);
|
||||
$isrealcolumn = isset($this->columns[$sortby]);
|
||||
$isfullnamefield = isset($this->columns['fullname']) && in_array($sortby, get_all_user_name_fields());
|
||||
|
||||
if ($isvalidsort && ($isrealcolumn || $isfullnamefield)) {
|
||||
if (array_key_exists($sortby, $this->prefs['sortby'])) {
|
||||
// This key already exists somewhere. Change its sortorder and bring it to the top.
|
||||
$sortorder = $this->prefs['sortby'][$sortby] = $sortorder;
|
||||
unset($this->prefs['sortby'][$sortby]);
|
||||
$this->prefs['sortby'] = array_merge(array($sortby => $sortorder), $this->prefs['sortby']);
|
||||
} else {
|
||||
// Key doesn't exist, so just add it to the beginning of the array, ascending order.
|
||||
$this->prefs['sortby'] = array_merge(array($sortby => $sortorder), $this->prefs['sortby']);
|
||||
}
|
||||
|
||||
// Finally, make sure that no more than $this->maxsortkeys are present into the array.
|
||||
$this->prefs['sortby'] = array_slice($this->prefs['sortby'], 0, $this->maxsortkeys);
|
||||
}
|
||||
|
||||
// If a default order is defined and it is not in the current list of order by columns, add it at the end.
|
||||
// This prevents results from being returned in a random order if the only order by column contains equal values.
|
||||
if (!empty($this->sort_default_column) && !array_key_exists($this->sort_default_column, $this->prefs['sortby'])) {
|
||||
$defaultsort = array($this->sort_default_column => $this->sort_default_order);
|
||||
$this->prefs['sortby'] = array_merge($this->prefs['sortby'], $defaultsort);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the preferred table sorting attributes.
|
||||
*
|
||||
* @param string $sortby The field to sort by.
|
||||
* @param int $sortorder The sort order.
|
||||
*/
|
||||
public function set_sorting(string $sortby, int $sortorder): void {
|
||||
$this->sortby = $sortby;
|
||||
$this->sortorder = $sortorder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the HTML for the sort icon. This is a helper method used by {@link sort_link()}.
|
||||
* @param bool $isprimary whether an icon is needed (it is only needed for the primary sort column.)
|
||||
@@ -1380,8 +1422,27 @@ class flexible_table {
|
||||
|
||||
return html_writer::link($this->baseurl->out(false, $params),
|
||||
$text . get_accesshide(get_string('sortby') . ' ' .
|
||||
$text . ' ' . $this->sort_order_name($isprimary, $order))) . ' ' .
|
||||
$this->sort_icon($isprimary, $order);
|
||||
$text . ' ' . $this->sort_order_name($isprimary, $order)),
|
||||
[
|
||||
'data-sortable' => $this->is_sortable($column),
|
||||
'data-sortby' => $column,
|
||||
'data-sortorder' => $sortorder,
|
||||
]) . ' ' . $this->sort_icon($isprimary, $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return sorting attributes values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_sort_order(): array {
|
||||
$sortbys = $this->prefs['sortby'];
|
||||
$sortby = key($sortbys);
|
||||
|
||||
return [
|
||||
'sortby' => $sortby,
|
||||
'sortorder' => $sortbys[$sortby],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1390,6 +1451,18 @@ class flexible_table {
|
||||
function start_html() {
|
||||
global $OUTPUT;
|
||||
|
||||
if (is_a($this, \core_table\dynamic::class)) {
|
||||
$sortdata = $this->get_sort_order();
|
||||
echo html_writer::start_tag('div', [
|
||||
'data-region' => 'core_table/dynamic',
|
||||
'data-table-handler' => get_class($this),
|
||||
'data-table-uniqueid' => $this->uniqueid,
|
||||
'data-table-filters' => json_encode($this->get_filterset()),
|
||||
'data-table-sort-by' => $sortdata['sortby'],
|
||||
'data-table-sort-order' => $sortdata['sortorder'],
|
||||
]);
|
||||
}
|
||||
|
||||
// Render button to allow user to reset table preferences.
|
||||
echo $this->render_reset_button();
|
||||
|
||||
@@ -1460,10 +1533,8 @@ class flexible_table {
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_be_reset() {
|
||||
|
||||
// Loop through preferences and make sure they are empty or set to the default value.
|
||||
foreach ($this->prefs as $prefname => $prefval) {
|
||||
|
||||
if ($prefname === 'sortby' and !empty($this->sort_default_column)) {
|
||||
// Check if the actual sorting differs from the default one.
|
||||
if (empty($prefval) or $prefval !== array($this->sort_default_column => $this->sort_default_order)) {
|
||||
|
||||
+132
-116
@@ -135,6 +135,9 @@ class participants_table extends \table_sql implements dynamic_table {
|
||||
/** @var \stdClass[] $viewableroles */
|
||||
private $viewableroles;
|
||||
|
||||
/** @var moodle_url $baseurl The base URL for the report. */
|
||||
public $baseurl;
|
||||
|
||||
/**
|
||||
* Render the participants table.
|
||||
*
|
||||
@@ -143,7 +146,91 @@ class participants_table extends \table_sql implements dynamic_table {
|
||||
* @param string $downloadhelpbutton
|
||||
*/
|
||||
public function out($pagesize, $useinitialsbar, $downloadhelpbutton = '') {
|
||||
global $PAGE;
|
||||
global $CFG, $OUTPUT, $PAGE;
|
||||
|
||||
// Define the headers and columns.
|
||||
$headers = [];
|
||||
$columns = [];
|
||||
|
||||
$bulkoperations = has_capability('moodle/course:bulkmessaging', $this->context);
|
||||
if ($bulkoperations) {
|
||||
$mastercheckbox = new \core\output\checkbox_toggleall('participants-table', true, [
|
||||
'id' => 'select-all-participants',
|
||||
'name' => 'select-all-participants',
|
||||
'label' => $this->selectall ? get_string('deselectall') : get_string('selectall'),
|
||||
'labelclasses' => 'sr-only',
|
||||
'classes' => 'm-1',
|
||||
'checked' => $this->selectall
|
||||
]);
|
||||
$headers[] = $OUTPUT->render($mastercheckbox);
|
||||
$columns[] = 'select';
|
||||
}
|
||||
|
||||
$headers[] = get_string('fullname');
|
||||
$columns[] = 'fullname';
|
||||
|
||||
$extrafields = get_extra_user_fields($this->context);
|
||||
foreach ($extrafields as $field) {
|
||||
$headers[] = get_user_field_name($field);
|
||||
$columns[] = $field;
|
||||
}
|
||||
|
||||
$headers[] = get_string('roles');
|
||||
$columns[] = 'roles';
|
||||
|
||||
// Get the list of fields we have to hide.
|
||||
$hiddenfields = array();
|
||||
if (!has_capability('moodle/course:viewhiddenuserfields', $this->context)) {
|
||||
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
|
||||
}
|
||||
|
||||
// Add column for groups if the user can view them.
|
||||
$canseegroups = !isset($hiddenfields['groups']);
|
||||
if ($canseegroups) {
|
||||
$headers[] = get_string('groups');
|
||||
$columns[] = 'groups';
|
||||
}
|
||||
|
||||
// Do not show the columns if it exists in the hiddenfields array.
|
||||
if (!isset($hiddenfields['lastaccess'])) {
|
||||
if ($this->courseid == SITEID) {
|
||||
$headers[] = get_string('lastsiteaccess');
|
||||
} else {
|
||||
$headers[] = get_string('lastcourseaccess');
|
||||
}
|
||||
$columns[] = 'lastaccess';
|
||||
}
|
||||
|
||||
$canreviewenrol = has_capability('moodle/course:enrolreview', $this->context);
|
||||
if ($canreviewenrol && $this->courseid != SITEID) {
|
||||
$columns[] = 'status';
|
||||
$headers[] = get_string('participationstatus', 'enrol');
|
||||
$this->no_sorting('status');
|
||||
};
|
||||
|
||||
$this->define_columns($columns);
|
||||
$this->define_headers($headers);
|
||||
|
||||
// Make this table sorted by last name by default.
|
||||
$this->sortable(true, 'lastname');
|
||||
|
||||
$this->no_sorting('select');
|
||||
$this->no_sorting('roles');
|
||||
if ($canseegroups) {
|
||||
$this->no_sorting('groups');
|
||||
}
|
||||
|
||||
$this->set_attribute('id', 'participants');
|
||||
|
||||
$this->countries = get_string_manager()->get_list_of_countries(true);
|
||||
$this->extrafields = $extrafields;
|
||||
if ($canseegroups) {
|
||||
$this->groups = groups_get_all_groups($this->courseid, 0, 0, 'g.*', true);
|
||||
}
|
||||
$this->allroles = role_fix_names(get_all_roles($this->context), $this->context);
|
||||
$this->assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false);
|
||||
$this->profileroles = get_profile_roles($this->context);
|
||||
$this->viewableroles = get_viewable_roles($this->context);
|
||||
|
||||
parent::out($pagesize, $useinitialsbar, $downloadhelpbutton);
|
||||
|
||||
@@ -401,141 +488,46 @@ class participants_table extends \table_sql implements dynamic_table {
|
||||
* @param filterset $filterset The filterset object to get the filters from.
|
||||
*/
|
||||
public function set_filterset(filterset $filterset): void {
|
||||
global $CFG, $OUTPUT;
|
||||
// Store the filterset for later.
|
||||
$this->filterset = $filterset;
|
||||
|
||||
$courseid = $filterset->get_filter('courseid')->current();
|
||||
// Get the context.
|
||||
$this->courseid = $filterset->get_filter('courseid')->current();
|
||||
$this->course = get_course($this->courseid);
|
||||
$this->context = \context_course::instance($this->courseid, MUST_EXIST);
|
||||
|
||||
// Process the filterset.
|
||||
$currentgroup = null;
|
||||
$this->currentgroup = null;
|
||||
if ($filterset->has_filter('groups')) {
|
||||
$currentgroup = $filterset->get_filter('groups')->current();
|
||||
$this->currentgroup = $filterset->get_filter('groups')->current();
|
||||
}
|
||||
|
||||
$contextid = null;
|
||||
if ($filterset->has_filter('contextid')) {
|
||||
$contextid = $filterset->get_filter('contextid')->current();
|
||||
}
|
||||
|
||||
$roleid = null;
|
||||
$this->roleid = null;
|
||||
if ($filterset->has_filter('roles')) {
|
||||
$roleid = $filterset->get_filter('roles')->current();
|
||||
$this->roleid = $filterset->get_filter('roles')->current();
|
||||
}
|
||||
|
||||
$enrolid = null;
|
||||
$this->enrolid = null;
|
||||
if ($filterset->has_filter('enrolments')) {
|
||||
$enrolid = $filterset->get_filter('enrolments')->current();
|
||||
$this->enrolid = $filterset->get_filter('enrolments')->current();
|
||||
}
|
||||
|
||||
$status = -1;
|
||||
$this->status = -1;
|
||||
if ($filterset->has_filter('status')) {
|
||||
$status = $filterset->get_filter('status')->current();
|
||||
$this->status = $filterset->get_filter('status')->current();
|
||||
}
|
||||
|
||||
$accesssince = null;
|
||||
$this->accesssince = null;
|
||||
if ($filterset->has_filter('accesssince')) {
|
||||
$accesssince = $filterset->get_filter('accesssince')->current();
|
||||
$this->accesssince = $filterset->get_filter('accesssince')->current();
|
||||
}
|
||||
|
||||
$keywords = null;
|
||||
$this->search = null;
|
||||
if ($filterset->has_filter('keywords')) {
|
||||
$this->search = $filterset->get_filter('keywords')->get_filter_values();
|
||||
}
|
||||
|
||||
// Get the context.
|
||||
$this->course = get_course($courseid);
|
||||
$context = \context_course::instance($courseid, MUST_EXIST);
|
||||
$this->context = $context;
|
||||
|
||||
// Define the headers and columns.
|
||||
$headers = [];
|
||||
$columns = [];
|
||||
|
||||
$bulkoperations = has_capability('moodle/course:bulkmessaging', $context);
|
||||
if ($bulkoperations) {
|
||||
$mastercheckbox = new \core\output\checkbox_toggleall('participants-table', true, [
|
||||
'id' => 'select-all-participants',
|
||||
'name' => 'select-all-participants',
|
||||
'label' => $this->selectall ? get_string('deselectall') : get_string('selectall'),
|
||||
'labelclasses' => 'sr-only',
|
||||
'classes' => 'm-1',
|
||||
'checked' => $this->selectall
|
||||
]);
|
||||
$headers[] = $OUTPUT->render($mastercheckbox);
|
||||
$columns[] = 'select';
|
||||
}
|
||||
|
||||
$headers[] = get_string('fullname');
|
||||
$columns[] = 'fullname';
|
||||
|
||||
$extrafields = get_extra_user_fields($context);
|
||||
foreach ($extrafields as $field) {
|
||||
$headers[] = get_user_field_name($field);
|
||||
$columns[] = $field;
|
||||
}
|
||||
|
||||
$headers[] = get_string('roles');
|
||||
$columns[] = 'roles';
|
||||
|
||||
// Get the list of fields we have to hide.
|
||||
$hiddenfields = array();
|
||||
if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
|
||||
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
|
||||
}
|
||||
|
||||
// Add column for groups if the user can view them.
|
||||
$canseegroups = !isset($hiddenfields['groups']);
|
||||
if ($canseegroups) {
|
||||
$headers[] = get_string('groups');
|
||||
$columns[] = 'groups';
|
||||
}
|
||||
|
||||
// Do not show the columns if it exists in the hiddenfields array.
|
||||
if (!isset($hiddenfields['lastaccess'])) {
|
||||
if ($courseid == SITEID) {
|
||||
$headers[] = get_string('lastsiteaccess');
|
||||
} else {
|
||||
$headers[] = get_string('lastcourseaccess');
|
||||
}
|
||||
$columns[] = 'lastaccess';
|
||||
}
|
||||
|
||||
$canreviewenrol = has_capability('moodle/course:enrolreview', $context);
|
||||
if ($canreviewenrol && $courseid != SITEID) {
|
||||
$columns[] = 'status';
|
||||
$headers[] = get_string('participationstatus', 'enrol');
|
||||
$this->no_sorting('status');
|
||||
};
|
||||
|
||||
$this->define_columns($columns);
|
||||
$this->define_headers($headers);
|
||||
|
||||
// Make this table sorted by last name by default.
|
||||
$this->sortable(true, 'lastname');
|
||||
|
||||
$this->no_sorting('select');
|
||||
$this->no_sorting('roles');
|
||||
if ($canseegroups) {
|
||||
$this->no_sorting('groups');
|
||||
}
|
||||
|
||||
$this->set_attribute('id', 'participants');
|
||||
|
||||
// Set the variables we need to use later.
|
||||
$this->currentgroup = $currentgroup;
|
||||
$this->accesssince = $accesssince;
|
||||
$this->roleid = $roleid;
|
||||
$this->enrolid = $enrolid;
|
||||
$this->status = $status;
|
||||
$this->countries = get_string_manager()->get_list_of_countries(true);
|
||||
$this->extrafields = $extrafields;
|
||||
$this->context = $context;
|
||||
if ($canseegroups) {
|
||||
$this->groups = groups_get_all_groups($courseid, 0, 0, 'g.*', true);
|
||||
}
|
||||
$this->allroles = role_fix_names(get_all_roles($this->context), $this->context);
|
||||
$this->assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false);
|
||||
$this->profileroles = get_profile_roles($this->context);
|
||||
$this->viewableroles = get_viewable_roles($this->context);
|
||||
$this->define_baseurl($this->get_base_url());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,7 +544,31 @@ class participants_table extends \table_sql implements dynamic_table {
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public static function get_base_url(): moodle_url {
|
||||
return new moodle_url('');
|
||||
public function get_base_url(): moodle_url {
|
||||
if ($this->baseurl === null) {
|
||||
return new moodle_url('/user/index.php', ['id' => $this->courseid]);
|
||||
}
|
||||
|
||||
return $this->baseurl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context of the current table.
|
||||
*
|
||||
* Note: This function should not be called until after the filterset has been provided.
|
||||
*
|
||||
* @return context
|
||||
*/
|
||||
public function get_context(): ?context {
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently defined filterset.
|
||||
*
|
||||
* @return filterset
|
||||
*/
|
||||
public function get_filterset(): ?filterset {
|
||||
return $this->filterset;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2020032700.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2020032700.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '3.9dev (Build: 20200327)'; // Human-friendly version name
|
||||
|
||||
Reference in New Issue
Block a user