mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 05:28:30 +01:00
MDL-80548 admin: Add bulk user actions also to user list
This commit is contained in:
parent
debed3eace
commit
d395925a40
10
admin/amd/build/bulk_user_actions.min.js
vendored
Normal file
10
admin/amd/build/bulk_user_actions.min.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
define("core_admin/bulk_user_actions",["exports","core_reportbuilder/local/selectors","core_table/local/dynamic/events","core_form/changechecker","core/custom_interaction_events","jquery"],(function(_exports,reportSelectors,tableEvents,FormChangeChecker,CustomEvents,_jquery){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}
|
||||
/**
|
||||
* Add bulk actions to the users list report
|
||||
*
|
||||
* @module core_admin/bulk_user_actions
|
||||
* @copyright 2024 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,reportSelectors=_interopRequireWildcard(reportSelectors),tableEvents=_interopRequireWildcard(tableEvents),FormChangeChecker=_interopRequireWildcard(FormChangeChecker),CustomEvents=_interopRequireWildcard(CustomEvents),_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj};const Selectors_bulkActionsForm="form#user-bulk-action-form",Selectors_userReportWrapper='[data-region="report-user-list-wrapper"]',Selectors_checkbox='input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="slave"]',Selectors_masterCheckbox='input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="master"]',Selectors_checkedRows='[data-togglegroup="report-select-all"][data-toggle="slave"]:checked';_exports.init=()=>{var _userBulkForm$closest;const userBulkForm=document.querySelector(Selectors_bulkActionsForm),userReport=null==userBulkForm||null===(_userBulkForm$closest=userBulkForm.closest(Selectors_userReportWrapper))||void 0===_userBulkForm$closest?void 0:_userBulkForm$closest.querySelector(reportSelectors.regions.report);if(!userBulkForm||!userReport)return;const actionSelect=userBulkForm.querySelector("select");CustomEvents.define(actionSelect,[CustomEvents.events.accessibleChange]),(0,_jquery.default)(actionSelect).on(CustomEvents.events.accessibleChange,(event=>{if(event.target.value&&"0"!=="".concat(event.target.value)){const e=new Event("submit",{cancelable:!0});userBulkForm.dispatchEvent(e),e.defaultPrevented||(FormChangeChecker.markFormSubmitted(userBulkForm),userBulkForm.submit())}}));const updateUserIds=()=>{const selectedUsers=[...userReport.querySelectorAll(Selectors_checkedRows)],selectedUserIds=selectedUsers.map((check=>parseInt(check.value)));userBulkForm.querySelector('[name="userids"]').value=selectedUserIds.join(","),actionSelect.disabled=0===selectedUsers.length;const selectedUsersNames=selectedUsers.map((check=>document.querySelector('label[for="'.concat(check.id,'"]')).textContent));userBulkForm.data={userids:selectedUserIds,usernames:selectedUsersNames}};updateUserIds(),document.addEventListener("change",(event=>{(event.target.matches(Selectors_checkbox)||event.target.matches(Selectors_masterCheckbox))&&userReport.contains(event.target)&&updateUserIds()})),document.addEventListener(tableEvents.tableContentRefreshed,(event=>{userReport.contains(event.target)&&updateUserIds()}))}}));
|
||||
|
||||
//# sourceMappingURL=bulk_user_actions.min.js.map
|
1
admin/amd/build/bulk_user_actions.min.js.map
Normal file
1
admin/amd/build/bulk_user_actions.min.js.map
Normal file
File diff suppressed because one or more lines are too long
91
admin/amd/src/bulk_user_actions.js
Normal file
91
admin/amd/src/bulk_user_actions.js
Normal file
@ -0,0 +1,91 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Add bulk actions to the users list report
|
||||
*
|
||||
* @module core_admin/bulk_user_actions
|
||||
* @copyright 2024 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import * as reportSelectors from 'core_reportbuilder/local/selectors';
|
||||
import * as tableEvents from 'core_table/local/dynamic/events';
|
||||
import * as FormChangeChecker from 'core_form/changechecker';
|
||||
import * as CustomEvents from 'core/custom_interaction_events';
|
||||
import jQuery from 'jquery';
|
||||
|
||||
const Selectors = {
|
||||
bulkActionsForm: 'form#user-bulk-action-form',
|
||||
userReportWrapper: '[data-region="report-user-list-wrapper"]',
|
||||
checkbox: 'input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="slave"]',
|
||||
masterCheckbox: 'input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="master"]',
|
||||
checkedRows: '[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise module
|
||||
*/
|
||||
export const init = () => {
|
||||
|
||||
const userBulkForm = document.querySelector(Selectors.bulkActionsForm);
|
||||
const userReport = userBulkForm?.closest(Selectors.userReportWrapper)?.querySelector(reportSelectors.regions.report);
|
||||
if (!userBulkForm || !userReport) {
|
||||
return;
|
||||
}
|
||||
const actionSelect = userBulkForm.querySelector('select');
|
||||
CustomEvents.define(actionSelect, [CustomEvents.events.accessibleChange]);
|
||||
|
||||
jQuery(actionSelect).on(CustomEvents.events.accessibleChange, event => {
|
||||
if (event.target.value && `${event.target.value}` !== "0") {
|
||||
const e = new Event('submit', {cancelable: true});
|
||||
userBulkForm.dispatchEvent(e);
|
||||
if (!e.defaultPrevented) {
|
||||
FormChangeChecker.markFormSubmitted(userBulkForm);
|
||||
userBulkForm.submit();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Every time the checkboxes in the report are changed, update the list of users in the form values
|
||||
// and enable/disable the action select.
|
||||
const updateUserIds = () => {
|
||||
const selectedUsers = [...userReport.querySelectorAll(Selectors.checkedRows)];
|
||||
const selectedUserIds = selectedUsers.map(check => parseInt(check.value));
|
||||
userBulkForm.querySelector('[name="userids"]').value = selectedUserIds.join(',');
|
||||
actionSelect.disabled = selectedUsers.length === 0;
|
||||
const selectedUsersNames = selectedUsers.map(check => document.querySelector(`label[for="${check.id}"]`).textContent);
|
||||
// Add the user ids and names to the form data attributes so they can be available from the
|
||||
// other JS modules that listen to the form submit event.
|
||||
userBulkForm.data = {userids: selectedUserIds, usernames: selectedUsersNames};
|
||||
};
|
||||
|
||||
updateUserIds();
|
||||
|
||||
document.addEventListener('change', event => {
|
||||
// When checkboxes are checked next to individual users or the master toggle (Select all/none).
|
||||
if ((event.target.matches(Selectors.checkbox) || event.target.matches(Selectors.masterCheckbox))
|
||||
&& userReport.contains(event.target)) {
|
||||
updateUserIds();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener(tableEvents.tableContentRefreshed, event => {
|
||||
// When the report contents is updated (i.e. page is changed, filters applied, etc).
|
||||
if (userReport.contains(event.target)) {
|
||||
updateUserIds();
|
||||
}
|
||||
});
|
||||
};
|
@ -67,6 +67,13 @@ class users extends system_report {
|
||||
$this->add_base_fields("{$entityuseralias}.id, {$entityuseralias}.confirmed, {$entityuseralias}.mnethostid,
|
||||
{$entityuseralias}.suspended, {$entityuseralias}.username, " . implode(', ', $fullnamefields));
|
||||
|
||||
if ($this->get_parameter('withcheckboxes', false, PARAM_BOOL)) {
|
||||
$canviewfullnames = has_capability('moodle/site:viewfullnames', \context_system::instance());
|
||||
$this->set_checkbox_toggleall(static function(\stdClass $row) use ($canviewfullnames): array {
|
||||
return [$row->id, fullname($row, $canviewfullnames)];
|
||||
});
|
||||
}
|
||||
|
||||
$paramguest = database::generate_param_name();
|
||||
$this->add_base_condition_sql("{$entityuseralias}.deleted <> 1 AND {$entityuseralias}.id <> :{$paramguest}",
|
||||
[$paramguest => $CFG->siteguest]);
|
||||
|
@ -195,3 +195,29 @@ Feature: An administrator can browse user accounts
|
||||
Then I should see "Username"
|
||||
And I should see "User picture"
|
||||
And I should see "Additional names"
|
||||
|
||||
@javascript
|
||||
Scenario: Browse user list as a person with limited capabilities
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| manager | Max | Manager | manager@example.com |
|
||||
And the following "roles" exist:
|
||||
| name | shortname | description | archetype |
|
||||
| Custom manager | custom1 | My custom role 1 | |
|
||||
And the following "permission overrides" exist:
|
||||
| capability | permission | role | contextlevel | reference |
|
||||
| moodle/site:configview | Allow | custom1 | System | |
|
||||
| moodle/user:update | Allow | custom1 | System | |
|
||||
And the following "role assigns" exist:
|
||||
| user | role | contextlevel | reference |
|
||||
| manager | custom1 | System | |
|
||||
When I log in as "manager"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I click on "User One" "checkbox"
|
||||
And the "Bulk user actions" select box should contain "Confirm"
|
||||
And the "Bulk user actions" select box should not contain "Delete"
|
||||
And I set the field "Bulk user actions" to "Force password change"
|
||||
And I should see "Are you absolutely sure you want to force a password change to User One ?"
|
||||
And I press "Yes"
|
||||
And I press "Continue"
|
||||
And I should see "Browse list of users"
|
||||
|
@ -40,6 +40,9 @@ class reset_factor extends \moodleform {
|
||||
$mform->addElement('hidden', 'bulkaction', $bulkaction);
|
||||
$mform->setType('bulkaction', PARAM_BOOL);
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$factors = array_map(function ($element) {
|
||||
return $element->get_display_name();
|
||||
}, $factors);
|
||||
|
@ -112,6 +112,9 @@ function tool_mfa_after_config(): void {
|
||||
* @return array
|
||||
*/
|
||||
function tool_mfa_bulk_user_actions(): array {
|
||||
if (!has_capability('moodle/site:config', context_system::instance())) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
'tool_mfa_reset_factors' => new action_link(
|
||||
new moodle_url('/admin/tool/mfa/reset_factor.php'),
|
||||
|
@ -28,17 +28,19 @@ require_once($CFG->libdir . '/adminlib.php');
|
||||
admin_externalpage_setup('tool_mfa_resetfactor');
|
||||
|
||||
$bulk = !empty($SESSION->bulk_users);
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
|
||||
$factors = \tool_mfa\plugininfo\factor::get_factors();
|
||||
$form = new \tool_mfa\local\form\reset_factor(null, ['factors' => $factors, 'bulk' => $bulk]);
|
||||
if ($bulk) {
|
||||
$form->set_data(['returnurl' => $returnurl]);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
} else {
|
||||
$return = new moodle_url('/admin/category.php', ['category' => 'toolmfafolder']);
|
||||
}
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
if ($bulk) {
|
||||
$url = new moodle_url('/admin/user/user_bulk.php');
|
||||
} else {
|
||||
$url = new moodle_url('/admin/category.php', ['category' => 'toolmfafolder']);
|
||||
}
|
||||
redirect($url);
|
||||
redirect($return);
|
||||
} else if ($fromform = $form->get_data()) {
|
||||
// Get factor from select index.
|
||||
if ($fromform->factor !== 'all') {
|
||||
@ -82,7 +84,7 @@ if ($form->is_cancelled()) {
|
||||
\core\notification::success(get_string('resetsuccessbulk', 'tool_mfa', $stringvar));
|
||||
unset($SESSION->bulk_users);
|
||||
// Redirect to bulk actions page.
|
||||
redirect(new moodle_url('/admin/user/user_bulk.php'));
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
@ -4,6 +4,7 @@
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/authlib.php');
|
||||
require_once($CFG->dirroot.'/user/lib.php');
|
||||
require_once($CFG->dirroot.'/'.$CFG->admin.'/user/user_bulk_forms.php');
|
||||
|
||||
$delete = optional_param('delete', 0, PARAM_INT);
|
||||
$confirm = optional_param('confirm', '', PARAM_ALPHANUM); //md5 confirmation hash
|
||||
@ -172,8 +173,23 @@
|
||||
echo html_writer::end_div();
|
||||
}
|
||||
|
||||
echo html_writer::start_div('', ['data-region' => 'report-user-list-wrapper']);
|
||||
|
||||
$bulkactions = new user_bulk_action_form(new moodle_url('/admin/user/user_bulk.php'),
|
||||
['excludeactions' => ['displayonpage'], 'passuserids' => true, 'hidesubmit' => true],
|
||||
'post', '',
|
||||
['id' => 'user-bulk-action-form']);
|
||||
$bulkactions->set_data(['returnurl' => $PAGE->url->out_as_local_url(false)]);
|
||||
|
||||
$report = \core_reportbuilder\system_report_factory::create(\core_admin\reportbuilder\local\systemreports\users::class,
|
||||
context_system::instance());
|
||||
context_system::instance(), parameters: ['withcheckboxes' => $bulkactions->has_bulk_actions()]);
|
||||
echo $report->output();
|
||||
|
||||
if ($bulkactions->has_bulk_actions()) {
|
||||
$PAGE->requires->js_call_amd('core_admin/bulk_user_actions', 'init');
|
||||
$bulkactions->display();
|
||||
}
|
||||
|
||||
echo html_writer::end_div();
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
@ -37,11 +37,18 @@ $ufiltering = new user_filtering();
|
||||
|
||||
// Create the bulk operations form.
|
||||
$actionform = new user_bulk_action_form();
|
||||
$actionform->set_data(['returnurl' => $PAGE->url->out_as_local_url(false)]);
|
||||
if ($data = $actionform->get_data()) {
|
||||
if ($data->passuserids) {
|
||||
// This means we called the form from /admin/user.php or similar and the userids should be taken from the form
|
||||
// data and not from $SESSION->bulk_users. For backwards compatibility we still set $SESSION->bulk_users.
|
||||
$users = preg_split('/,/', $data->userids, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$SESSION->bulk_users = array_combine($users, $users);
|
||||
}
|
||||
// Check if an action should be performed and do so.
|
||||
$bulkactions = $actionform->get_actions();
|
||||
if (array_key_exists($data->action, $bulkactions)) {
|
||||
redirect($bulkactions[$data->action]->url);
|
||||
redirect(new moodle_url($bulkactions[$data->action]->url, ['returnurl' => $data->returnurl ?: null]));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ $dir = optional_param('dir', 'asc', PARAM_ALPHA);
|
||||
admin_externalpage_setup('userbulk');
|
||||
require_capability('moodle/cohort:assign', context_system::instance());
|
||||
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
$users = $SESSION->bulk_users;
|
||||
|
||||
$strnever = get_string('never');
|
||||
@ -60,7 +63,7 @@ foreach ($allcohorts as $c) {
|
||||
unset($allcohorts);
|
||||
|
||||
if (count($cohorts) < 2) {
|
||||
redirect(new moodle_url('/admin/user/user_bulk.php'), get_string('bulknocohort', 'core_cohort'));
|
||||
redirect($return, get_string('bulknocohort', 'core_cohort'));
|
||||
}
|
||||
|
||||
$countries = get_string_manager()->get_list_of_countries(true);
|
||||
@ -78,9 +81,10 @@ foreach ($users as $key => $id) {
|
||||
unset($countries);
|
||||
|
||||
$mform = new user_bulk_cohortadd_form(null, $cohorts);
|
||||
$mform->set_data(['returnurl' => $returnurl]);
|
||||
|
||||
if (empty($users) or $mform->is_cancelled()) {
|
||||
redirect(new moodle_url('/admin/user/user_bulk.php'));
|
||||
redirect($return);
|
||||
|
||||
} else if ($data = $mform->get_data()) {
|
||||
// process request
|
||||
@ -89,7 +93,7 @@ if (empty($users) or $mform->is_cancelled()) {
|
||||
cohort_add_member($data->cohort, $user->id);
|
||||
}
|
||||
}
|
||||
redirect(new moodle_url('/admin/user/user_bulk.php'));
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
// Need to sort by date
|
||||
|
@ -31,6 +31,9 @@ class user_bulk_cohortadd_form extends moodleform {
|
||||
$mform = $this->_form;
|
||||
$cohorts = $this->_customdata;
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$mform->addElement('select', 'cohort', get_string('cohort', 'core_cohort'), $cohorts);
|
||||
$mform->addRule('cohort', get_string('required'), 'required', null, 'client');
|
||||
|
||||
|
@ -11,7 +11,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
admin_externalpage_setup('userbulk');
|
||||
require_capability('moodle/user:update', context_system::instance());
|
||||
|
||||
$return = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
if (empty($SESSION->bulk_users)) {
|
||||
redirect($return);
|
||||
@ -45,7 +46,7 @@ if ($confirm and confirm_sesskey()) {
|
||||
} else {
|
||||
echo $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
|
||||
}
|
||||
$continue = new single_button(new moodle_url($return), get_string('continue'), 'post');
|
||||
$continue = new single_button($return, get_string('continue'), 'post');
|
||||
echo $OUTPUT->render($continue);
|
||||
echo $OUTPUT->box_end();
|
||||
} else {
|
||||
@ -53,8 +54,9 @@ if ($confirm and confirm_sesskey()) {
|
||||
$userlist = $DB->get_records_select_menu('user', "id $in", $params, 'fullname', 'id,'.$DB->sql_fullname().' AS fullname');
|
||||
$usernames = implode(', ', $userlist);
|
||||
echo $OUTPUT->heading(get_string('confirmation', 'admin'));
|
||||
$formcontinue = new single_button(new moodle_url('user_bulk_confirm.php', array('confirm' => 1)), get_string('yes'));
|
||||
$formcancel = new single_button(new moodle_url('user_bulk.php'), get_string('no'), 'get');
|
||||
$formcontinue = new single_button(new moodle_url('user_bulk_confirm.php',
|
||||
['confirm' => 1, 'returnurl' => $returnurl]), get_string('yes'));
|
||||
$formcancel = new single_button($return, get_string('no'), 'get');
|
||||
echo $OUTPUT->confirm(get_string('confirmcheckfull', '', $usernames), $formcontinue, $formcancel);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
admin_externalpage_setup('userbulk');
|
||||
require_capability('moodle/user:delete', context_system::instance());
|
||||
|
||||
$return = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
if (empty($SESSION->bulk_users)) {
|
||||
redirect($return);
|
||||
@ -43,7 +44,7 @@ if ($confirm and confirm_sesskey()) {
|
||||
} else {
|
||||
echo $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
|
||||
}
|
||||
$continue = new single_button(new moodle_url($return), get_string('continue'), 'post');
|
||||
$continue = new single_button($return, get_string('continue'), 'post');
|
||||
echo $OUTPUT->render($continue);
|
||||
echo $OUTPUT->box_end();
|
||||
} else {
|
||||
@ -51,8 +52,9 @@ if ($confirm and confirm_sesskey()) {
|
||||
$userlist = $DB->get_records_select_menu('user', "id $in", $params, 'fullname', 'id,'.$DB->sql_fullname().' AS fullname');
|
||||
$usernames = implode(', ', $userlist);
|
||||
echo $OUTPUT->heading(get_string('confirmation', 'admin'));
|
||||
$formcontinue = new single_button(new moodle_url('user_bulk_delete.php', array('confirm' => 1)), get_string('yes'));
|
||||
$formcancel = new single_button(new moodle_url('user_bulk.php'), get_string('no'), 'get');
|
||||
$formcontinue = new single_button(new moodle_url('user_bulk_delete.php',
|
||||
['confirm' => 1, 'returnurl' => $returnurl]), get_string('yes'));
|
||||
$formcancel = new single_button($return, get_string('no'), 'get');
|
||||
echo $OUTPUT->confirm(get_string('deletecheckfull', '', $usernames), $formcontinue, $formcancel);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,8 @@ $dir = optional_param('dir', 'asc', PARAM_ALPHA);
|
||||
|
||||
admin_externalpage_setup('userbulk');
|
||||
|
||||
$return = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
if (empty($SESSION->bulk_users)) {
|
||||
redirect($return);
|
||||
|
@ -34,8 +34,11 @@ $dataformat = optional_param('dataformat', '', PARAM_ALPHA);
|
||||
admin_externalpage_setup('userbulk');
|
||||
require_capability('moodle/user:update', context_system::instance());
|
||||
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
if (empty($SESSION->bulk_users)) {
|
||||
redirect(new moodle_url('/admin/user/user_bulk.php'));
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
if ($dataformat) {
|
||||
|
@ -12,7 +12,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
admin_externalpage_setup('userbulk');
|
||||
require_capability('moodle/user:update', context_system::instance());
|
||||
|
||||
$return = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
if (empty($SESSION->bulk_users)) {
|
||||
redirect($return);
|
||||
@ -62,8 +63,9 @@ if ($confirm and confirm_sesskey()) {
|
||||
$usernames .= ', ...';
|
||||
}
|
||||
echo $OUTPUT->heading(get_string('confirmation', 'admin'));
|
||||
$formcontinue = new single_button(new moodle_url('/admin/user/user_bulk_forcepasswordchange.php', array('confirm' => 1)), get_string('yes'));
|
||||
$formcancel = new single_button(new moodle_url('/admin/user/user_bulk.php'), get_string('no'), 'get');
|
||||
$formcontinue = new single_button(new moodle_url('/admin/user/user_bulk_forcepasswordchange.php',
|
||||
['confirm' => 1, 'returnurl' => $returnurl]), get_string('yes'));
|
||||
$formcancel = new single_button($return, get_string('no'), 'get');
|
||||
echo $OUTPUT->confirm(get_string('forcepasswordchangecheckfull', '', $usernames), $formcontinue, $formcancel);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,9 @@ require_once($CFG->libdir.'/datalib.php');
|
||||
*/
|
||||
class user_bulk_action_form extends moodleform {
|
||||
|
||||
/** @var bool */
|
||||
protected $hasbulkactions = false;
|
||||
|
||||
/**
|
||||
* Returns an array of action_link's of all bulk actions available for this user.
|
||||
*
|
||||
@ -44,6 +47,8 @@ class user_bulk_action_form extends moodleform {
|
||||
|
||||
global $CFG;
|
||||
|
||||
$canaccessbulkactions = has_any_capability(['moodle/user:update', 'moodle/user:delete'], context_system::instance());
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$actions = [];
|
||||
if (has_capability('moodle/user:update', $syscontext)) {
|
||||
@ -51,7 +56,7 @@ class user_bulk_action_form extends moodleform {
|
||||
new moodle_url('/admin/user/user_bulk_confirm.php'),
|
||||
get_string('confirm'));
|
||||
}
|
||||
if (has_capability('moodle/site:readallmessages', $syscontext) && !empty($CFG->messaging)) {
|
||||
if ($canaccessbulkactions && has_capability('moodle/site:readallmessages', $syscontext) && !empty($CFG->messaging)) {
|
||||
$actions['message'] = new action_link(
|
||||
new moodle_url('/admin/user/user_bulk_message.php'),
|
||||
get_string('messageselectadd'));
|
||||
@ -61,9 +66,11 @@ class user_bulk_action_form extends moodleform {
|
||||
new moodle_url('/admin/user/user_bulk_delete.php'),
|
||||
get_string('delete'));
|
||||
}
|
||||
$actions['displayonpage'] = new action_link(
|
||||
if ($canaccessbulkactions) {
|
||||
$actions['displayonpage'] = new action_link(
|
||||
new moodle_url('/admin/user/user_bulk_display.php'),
|
||||
get_string('displayonpage'));
|
||||
}
|
||||
|
||||
if (has_capability('moodle/user:update', $syscontext)) {
|
||||
$actions['download'] = new action_link(
|
||||
@ -76,7 +83,7 @@ class user_bulk_action_form extends moodleform {
|
||||
new moodle_url('/admin/user/user_bulk_forcepasswordchange.php'),
|
||||
get_string('forcepasswordchange'));
|
||||
}
|
||||
if (has_capability('moodle/cohort:assign', $syscontext)) {
|
||||
if ($canaccessbulkactions && has_capability('moodle/cohort:assign', $syscontext)) {
|
||||
$actions['addtocohort'] = new action_link(
|
||||
new moodle_url('/admin/user/user_bulk_cohortadd.php'),
|
||||
get_string('bulkadd', 'core_cohort'));
|
||||
@ -93,6 +100,15 @@ class user_bulk_action_form extends moodleform {
|
||||
}
|
||||
}
|
||||
|
||||
// This method may be called from 'Bulk actions' and 'Browse user list' pages. Some actions
|
||||
// may be irrelevant in one of the contexts and they can be excluded by specifying the
|
||||
// 'excludeactions' customdata.
|
||||
$excludeactions = $this->_customdata['excludeactions'] ?? [];
|
||||
foreach ($excludeactions as $excludeaction) {
|
||||
unset($actions[$excludeaction]);
|
||||
}
|
||||
|
||||
$this->hasbulkactions = !empty($actions);
|
||||
return $actions;
|
||||
|
||||
}
|
||||
@ -101,20 +117,42 @@ class user_bulk_action_form extends moodleform {
|
||||
* Form definition
|
||||
*/
|
||||
public function definition() {
|
||||
global $CFG;
|
||||
|
||||
$mform =& $this->_form;
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
// When 'passuserids' is specified in the customdata, the user ids are expected in the form
|
||||
// data rather than in the $SESSION->bulk_users .
|
||||
$passuserids = !empty($this->_customdata['passuserids']);
|
||||
$mform->addElement('hidden', 'passuserids', $passuserids);
|
||||
$mform->setType('passuserids', PARAM_BOOL);
|
||||
|
||||
$mform->addElement('hidden', 'userids');
|
||||
$mform->setType('userids', PARAM_SEQUENCE);
|
||||
|
||||
$actions = [0 => get_string('choose') . '...'];
|
||||
$bulkactions = $this->get_actions();
|
||||
foreach ($bulkactions as $key => $action) {
|
||||
$actions[$key] = $action->text;
|
||||
}
|
||||
$objs = array();
|
||||
$objs[] =& $mform->createElement('select', 'action', null, $actions);
|
||||
$objs[] =& $mform->createElement('submit', 'doaction', get_string('go'));
|
||||
$objs[] = $selectel = $mform->createElement('select', 'action', get_string('userbulk', 'admin'), $actions);
|
||||
$selectel->setHiddenLabel(true);
|
||||
if (empty($this->_customdata['hidesubmit'])) {
|
||||
$objs[] =& $mform->createElement('submit', 'doaction', get_string('go'));
|
||||
}
|
||||
$mform->addElement('group', 'actionsgrp', get_string('withselectedusers'), $objs, ' ', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there at least one available bulk action in this form
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_bulk_actions(): bool {
|
||||
return $this->hasbulkactions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
admin_externalpage_setup('userbulk');
|
||||
require_capability('moodle/site:manageallmessaging', context_system::instance());
|
||||
|
||||
$return = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
$return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
|
||||
|
||||
if (empty($SESSION->bulk_users)) {
|
||||
redirect($return);
|
||||
@ -39,6 +40,7 @@ if ($confirm and !empty($msg) and confirm_sesskey()) {
|
||||
}
|
||||
|
||||
$msgform = new user_message_form('user_bulk_message.php');
|
||||
$msgform->set_data(['returnurl' => $returnurl]);
|
||||
|
||||
if ($msgform->is_cancelled()) {
|
||||
redirect($return);
|
||||
@ -58,8 +60,10 @@ if ($msgform->is_cancelled()) {
|
||||
echo $OUTPUT->heading(get_string('confirmation', 'admin'));
|
||||
echo $OUTPUT->box($msg, 'boxwidthnarrow boxaligncenter generalbox', 'preview'); //TODO: clean once we start using proper text formats here
|
||||
|
||||
$formcontinue = new single_button(new moodle_url('user_bulk_message.php', array('confirm' => 1, 'msg' => $msg)), get_string('yes')); //TODO: clean once we start using proper text formats here
|
||||
$formcancel = new single_button(new moodle_url('user_bulk.php'), get_string('no'), 'get');
|
||||
$formcontinue = new single_button(new moodle_url('user_bulk_message.php',
|
||||
['confirm' => 1, 'msg' => $msg, 'returnurl' => $returnurl]),
|
||||
get_string('yes')); // TODO: clean once we start using proper text formats here.
|
||||
$formcancel = new single_button($return, get_string('no'), 'get');
|
||||
echo $OUTPUT->confirm(get_string('confirmmessage', 'bulkusers', $usernames), $formcontinue, $formcancel);
|
||||
echo $OUTPUT->footer();
|
||||
die;
|
||||
|
@ -12,6 +12,8 @@ class user_message_form extends moodleform {
|
||||
$mform =& $this->_form;
|
||||
$mform->addElement('header', 'general', get_string('message', 'message'));
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$mform->addElement('editor', 'messagebody', get_string('messagebody'), null, null);
|
||||
$mform->addRule('messagebody', '', 'required', null, 'server');
|
||||
|
@ -100,6 +100,24 @@ Feature: Add cohorts of users
|
||||
And the "Current users" select box should contain "Forth User (forth@example.com)"
|
||||
And the "Current users" select box should not contain "First User (first@example.com)"
|
||||
|
||||
@javascript
|
||||
Scenario: Add users to a cohort using a user list bulk action
|
||||
When I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I click on "Third User" "checkbox"
|
||||
And I click on "Forth User" "checkbox"
|
||||
And I set the field "Bulk user actions" to "Add to cohort"
|
||||
And I set the field "Cohort" to "Test cohort name [333]"
|
||||
And I press "Add to cohort"
|
||||
And I should see "Browse list of users"
|
||||
And I navigate to "Users > Accounts > Cohorts" in site administration
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| Name | Cohort size |
|
||||
| Test cohort name | 2 |
|
||||
And I press "Assign" action in the "Test cohort name" report row
|
||||
And the "Current users" select box should contain "Third User (third@example.com)"
|
||||
And the "Current users" select box should contain "Forth User (forth@example.com)"
|
||||
And the "Current users" select box should not contain "First User (first@example.com)"
|
||||
|
||||
@javascript
|
||||
Scenario: Edit cohort name in-place
|
||||
When I navigate to "Users > Accounts > Cohorts" in site administration
|
||||
|
@ -64,6 +64,8 @@ information provided here is intended especially for developers.
|
||||
- $numtasks
|
||||
- $mode
|
||||
* Removed \zip_writer::sanitise_filepath and \zipwriter::sanitise_filename as they are now automatically sanitised in the zipstream.
|
||||
* Plugins implementing callback `bulk_user_actions()` should be aware that bulk user actions can be executed
|
||||
from /admin/user.php as well as from the bulk actions page. The 'returnurl' parameter will be passed in the request.
|
||||
|
||||
=== 4.3 ===
|
||||
|
||||
|
@ -57,6 +57,22 @@ Feature: Deleting users
|
||||
And the "Available" select box should not contain "User Three"
|
||||
And the "Available" select box should contain "User One"
|
||||
|
||||
@javascript
|
||||
Scenario: Deleting users from bulk actions in the user list
|
||||
When I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I click on "User Four" "checkbox"
|
||||
And I click on "User Three" "checkbox"
|
||||
And I set the field "Bulk user actions" to "Delete"
|
||||
And I should see "Are you absolutely sure you want to completely delete the user User Four, User Three, including their enrolments, activity and other user data?"
|
||||
And I press "Yes"
|
||||
And I should see "Changes saved"
|
||||
And I press "Continue"
|
||||
And I should see "Browse list of users"
|
||||
And I should not see "User Four"
|
||||
And I should not see "User Three"
|
||||
And I should see "User One"
|
||||
|
||||
@javascript @core_message
|
||||
Scenario: Deleting users who have unread messages sent or received
|
||||
When I log in as "user1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user