├── README.md
├── version.php
├── db
├── hooks.php
└── services.php
├── lang
└── en
│ └── tool_bulkactiondemo.php
├── classes
├── local
│ └── hooks
│ │ └── extend_bulk_user_actions.php
└── external
│ └── action.php
├── amd
├── build
│ ├── actions.min.js
│ └── actions.min.js.map
└── src
│ └── actions.js
├── action.php
└── .github
└── workflows
└── gha.yml
/README.md:
--------------------------------------------------------------------------------
1 | # Bulk user action example
2 |
3 | This plugin is an example of how to add bulk user actions to Moodle 4.4
4 |
5 | Commit 1: Implement hook and add actions "Suspend" and "Unsuspend" that work from
6 | both "Bulk user actions" and "Browse user list" pages and work without any Javascript.
7 |
8 | Commit 2: Add web service and JS module to listen to form submit event, intercept it
9 | and perform action using AJAX requests (only for "Browse user list" page).
10 |
--------------------------------------------------------------------------------
/version.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Version information for Bulk user action demo
19 | *
20 | * @package tool_bulkactiondemo
21 | * @copyright 2024 Marina Glancy
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | defined('MOODLE_INTERNAL') || die();
26 |
27 | $plugin->component = 'tool_bulkactiondemo';
28 | $plugin->release = '1.1';
29 | $plugin->version = 2024011801;
30 | $plugin->requires = 2024011200.00;
31 | $plugin->maturity = MATURITY_STABLE;
32 |
--------------------------------------------------------------------------------
/db/hooks.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Hook callbacks for Bulk user action demo
19 | *
20 | * @package tool_bulkactiondemo
21 | * @copyright 2024 Marina Glancy
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | defined('MOODLE_INTERNAL') || die();
26 |
27 | $callbacks = [
28 | [
29 | 'hook' => core_user\hook\extend_bulk_user_actions::class,
30 | 'callback' => 'tool_bulkactiondemo\local\hooks\extend_bulk_user_actions::callback',
31 | 'priority' => 0,
32 | ],
33 | ];
34 |
--------------------------------------------------------------------------------
/lang/en/tool_bulkactiondemo.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * English language pack for Bulk user action demo
19 | *
20 | * @package tool_bulkactiondemo
21 | * @category string
22 | * @copyright 2024 Marina Glancy
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | defined('MOODLE_INTERNAL') || die();
27 |
28 | $string['confirmsuspend'] = 'Are you absolutely sure you want to suspend {$a}';
29 | $string['confirmunsuspend'] = 'Are you absolutely sure you want to unsuspend {$a}';
30 | $string['pluginname'] = 'Bulk user action demo';
31 | $string['suspend'] = 'Suspend';
32 | $string['unrecognisedaction'] = 'Unrecognised action';
33 | $string['unsuspend'] = 'Unsuspend';
34 |
--------------------------------------------------------------------------------
/db/services.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * External functions and service declaration for Bulk user action demo
19 | *
20 | * Documentation: {@link https://moodledev.io/docs/apis/subsystems/external/description}
21 | *
22 | * @package tool_bulkactiondemo
23 | * @category webservice
24 | * @copyright 2024 Marina Glancy
25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 | */
27 |
28 | defined('MOODLE_INTERNAL') || die();
29 |
30 | $functions = [
31 |
32 | 'tool_bulkactiondemo_action' => [
33 | 'classname' => tool_bulkactiondemo\external\action::class,
34 | 'description' => 'Perform bulk user action',
35 | 'type' => 'write',
36 | 'ajax' => true,
37 | ],
38 | ];
39 |
40 | $services = [
41 | ];
42 |
--------------------------------------------------------------------------------
/classes/local/hooks/extend_bulk_user_actions.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace tool_bulkactiondemo\local\hooks;
18 |
19 | use action_link;
20 | use moodle_url;
21 |
22 | /**
23 | * Hook callbacks for tool_bulkactiondemo
24 | *
25 | * @package tool_bulkactiondemo
26 | * @copyright 2024 Marina Glancy
27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 | */
29 | class extend_bulk_user_actions {
30 |
31 | /**
32 | * Extend bulk user actions menu
33 | *
34 | * @param \core_user\hook\extend_bulk_user_actions $hook
35 | */
36 | public static function callback(\core_user\hook\extend_bulk_user_actions $hook): void {
37 | global $PAGE;
38 | $category = 'Added by plugin';
39 |
40 | $syscontext = \context_system::instance();
41 | if (has_capability('moodle/user:update', $syscontext)) {
42 | $hook->add_action('tool_bulkactiondemo_suspend', new action_link(
43 | new moodle_url('/admin/tool/bulkactiondemo/action.php', ['action' => 'suspend']),
44 | get_string('suspend', 'tool_bulkactiondemo')),
45 | $category);
46 | $hook->add_action('tool_bulkactiondemo_unsuspend', new action_link(
47 | new moodle_url('/admin/tool/bulkactiondemo/action.php', ['action' => 'unsuspend']),
48 | get_string('unsuspend', 'tool_bulkactiondemo')),
49 | $category);
50 | $PAGE->requires->js_call_amd('tool_bulkactiondemo/actions', 'init');
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/amd/build/actions.min.js:
--------------------------------------------------------------------------------
1 | define("tool_bulkactiondemo/actions",["exports","core/notification","core/str","core/ajax","core_reportbuilder/local/events","core/event_dispatcher","core_reportbuilder/local/selectors","core/toast","core_form/changechecker"],(function(_exports,_notification,_str,_ajax,reportEvents,_event_dispatcher,reportSelectors,_toast,FormChangeChecker){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}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
2 | /**
3 | * Perform bulk user action in AJAX request
4 | *
5 | * @module tool_bulkactiondemo/actions
6 | * @copyright 2024 Marina Glancy
7 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8 | */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors),FormChangeChecker=_interopRequireWildcard(FormChangeChecker);const SELECTORS_bulkActionForm="body#page-admin-user form#user-bulk-action-form";_exports.init=()=>{const form=document.querySelector(SELECTORS_bulkActionForm);form&&form.addEventListener("submit",(e=>{var _form$querySelector;let action=null===(_form$querySelector=form.querySelector('select[name="action"]'))||void 0===_form$querySelector?void 0:_form$querySelector.value;if(!action.startsWith("tool_bulkactiondemo_"))return;e.preventDefault(),FormChangeChecker.markFormSubmitted(e.target),action=action.replace("tool_bulkactiondemo_","");const userlist=e.target.data.usernames.join(", "),userids=e.target.data.userids;let key;if("suspend"===action)key="confirmsuspend";else{if("unsuspend"!==action)return;key="confirmunsuspend"}(0,_str.getStrings)([{key:"confirm"},{key:key,component:"tool_bulkactiondemo",param:userlist},{key:"yes"},{key:"no"},{key:"changessaved",component:"moodle"}]).then((strings=>(form.querySelector('select[name="action"]').value="0",_notification.default.confirm(strings[0],strings[1],strings[2],strings[3],(()=>function(action,userids,successMessage){const reportElement=document.querySelector('[data-region="report-user-list-wrapper"] '+reportSelectors.regions.report);_ajax.default.call([{methodname:"tool_bulkactiondemo_action",args:{action:action,userids:userids},done:()=>{(0,_toast.add)(successMessage,{}),reportElement&&(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement)},fail:error=>_notification.default.exception(error)}])}(action,userids,strings[4])))))).catch(_notification.default.exception)}))}}));
9 |
10 | //# sourceMappingURL=actions.min.js.map
--------------------------------------------------------------------------------
/classes/external/action.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace tool_bulkactiondemo\external;
18 |
19 | use core_external\external_function_parameters;
20 | use core_external\external_single_structure;
21 | use core_external\external_api;
22 | use core_external\external_value;
23 | use core_external\external_multiple_structure;
24 | use moodle_exception;
25 |
26 | /**
27 | * Implementation of web service tool_bulkactiondemo_action
28 | *
29 | * @package tool_bulkactiondemo
30 | * @copyright 2024 Marina Glancy
31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 | */
33 | class action extends external_api {
34 |
35 | /**
36 | * Describes the parameters for tool_bulkactiondemo_action
37 | *
38 | * @return external_function_parameters
39 | */
40 | public static function execute_parameters(): external_function_parameters {
41 | return new external_function_parameters([
42 | 'action' => new external_value(PARAM_ALPHANUMEXT, 'Action'),
43 | 'userids' => new external_multiple_structure(
44 | new external_value(PARAM_INT, 'user id'), 'Array of user ids'
45 | ),
46 | ]);
47 | }
48 |
49 | /**
50 | * Implementation of web service tool_bulkactiondemo_action
51 | *
52 | * @param string $action
53 | * @param array $userids
54 | */
55 | public static function execute($action, $userids) {
56 | global $DB, $USER, $CFG;
57 | require_once($CFG->dirroot . '/user/lib.php');
58 |
59 | // Parameter validation.
60 | ['action' => $action, 'userids' => $userids] = self::validate_parameters(
61 | self::execute_parameters(),
62 | ['action' => $action, 'userids' => $userids]
63 | );
64 |
65 | $context = \context_system::instance();
66 | self::validate_context($context);
67 | require_capability('moodle/user:update', $context);
68 |
69 | list($in, $params) = $DB->get_in_or_equal($userids);
70 | $rs = $DB->get_recordset_select('user', "id $in", $params, '', 'id, suspended');
71 | foreach ($rs as $user) {
72 | if ($action === 'suspend') {
73 | if (!is_siteadmin($user) && $USER->id != $user->id && $user->suspended != 1) {
74 | $user->suspended = 1;
75 | // Force logout.
76 | \core\session\manager::kill_user_sessions($user->id);
77 | user_update_user($user, false);
78 | }
79 | } else if ($action === 'unsuspend') {
80 | if ($user->suspended != 0) {
81 | $user->suspended = 0;
82 | user_update_user($user, false);
83 | }
84 | } else {
85 | throw new moodle_exception(get_string('unrecognisedaction', 'tool_bulkactiondemo'));
86 | }
87 | }
88 |
89 | return [];
90 | }
91 |
92 | /**
93 | * Describe the return structure for tool_bulkactiondemo_action
94 | *
95 | * @return external_single_structure
96 | */
97 | public static function execute_returns(): external_single_structure {
98 | return new external_single_structure([]);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/amd/src/actions.js:
--------------------------------------------------------------------------------
1 | // This file is part of Moodle - http://moodle.org/
2 | //
3 | // Moodle is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Moodle is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Moodle. If not, see .
15 |
16 | /**
17 | * Perform bulk user action in AJAX request
18 | *
19 | * @module tool_bulkactiondemo/actions
20 | * @copyright 2024 Marina Glancy
21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 | */
23 |
24 | import Notification from 'core/notification';
25 | import {getStrings} from 'core/str';
26 | import Ajax from 'core/ajax';
27 | import * as reportEvents from 'core_reportbuilder/local/events';
28 | import {dispatchEvent} from 'core/event_dispatcher';
29 | import * as reportSelectors from 'core_reportbuilder/local/selectors';
30 | import {add as addToast} from 'core/toast';
31 | import * as FormChangeChecker from 'core_form/changechecker';
32 |
33 | const SELECTORS = {
34 | bulkActionForm: 'body#page-admin-user form#user-bulk-action-form',
35 | };
36 |
37 | /**
38 | * Initialise module
39 | */
40 | export const init = () => {
41 | const form = document.querySelector(SELECTORS.bulkActionForm);
42 |
43 | if (!form) {
44 | return;
45 | }
46 |
47 | form.addEventListener('submit', (e) => {
48 | let action = form.querySelector('select[name="action"]')?.value;
49 | if (!action.startsWith('tool_bulkactiondemo_')) {
50 | return;
51 | }
52 |
53 | e.preventDefault();
54 | FormChangeChecker.markFormSubmitted(e.target);
55 |
56 | action = action.replace('tool_bulkactiondemo_', '');
57 | const userlist = e.target.data.usernames.join(', ');
58 | const userids = e.target.data.userids;
59 |
60 | let key;
61 | if (action === 'suspend') {
62 | key = 'confirmsuspend';
63 | } else if (action === 'unsuspend') {
64 | key = 'confirmunsuspend';
65 | } else {
66 | return;
67 | }
68 |
69 | getStrings([
70 | {'key': 'confirm'},
71 | {'key': key, component: 'tool_bulkactiondemo', param: userlist},
72 | {'key': 'yes'},
73 | {'key': 'no'},
74 | {'key': 'changessaved', component: 'moodle'}
75 | ])
76 | .then(strings => {
77 | form.querySelector('select[name="action"]').value = '0';
78 | return Notification.confirm(strings[0], strings[1], strings[2], strings[3],
79 | () => performAction(action, userids, strings[4]));
80 | })
81 | .catch(Notification.exception);
82 | });
83 | };
84 |
85 | /**
86 | * Perform action
87 | *
88 | * @param {String} action
89 | * @param {Array} userids
90 | * @param {String} successMessage
91 | */
92 | function performAction(action, userids, successMessage) {
93 | const reportElement = document.querySelector('[data-region="report-user-list-wrapper"] ' + reportSelectors.regions.report);
94 |
95 | Ajax.call([{
96 | methodname: 'tool_bulkactiondemo_action',
97 | args: {
98 | action: action,
99 | userids: userids,
100 | },
101 | done: () => {
102 | addToast(successMessage, {});
103 | if (reportElement) {
104 | dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
105 | }
106 | },
107 | fail: (error) => Notification.exception(error),
108 | }]);
109 | }
--------------------------------------------------------------------------------
/action.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Perform a bulk user action
19 | *
20 | * @package tool_bulkactiondemo
21 | * @copyright 2024 Marina Glancy
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | require('../../../config.php');
26 |
27 | $action = optional_param('action', '', PARAM_ALPHANUMEXT);
28 | $confirm = optional_param('confirm', 0, PARAM_BOOL);
29 |
30 | require_login();
31 |
32 | $url = new moodle_url('/admin/tool/bulkactiondemo/action.php', []);
33 | $PAGE->set_url($url);
34 | $PAGE->set_context(context_system::instance());
35 | require_capability('moodle/user:update', context_system::instance());
36 |
37 | $returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
38 | $return = new moodle_url($returnurl ?: '/admin/user/user_bulk.php');
39 |
40 | if (empty($SESSION->bulk_users)) {
41 | redirect($return);
42 | }
43 |
44 | $PAGE->set_heading($SITE->fullname);
45 | echo $OUTPUT->header();
46 |
47 | if ($confirm && confirm_sesskey()) {
48 | $notifications = '';
49 | list($in, $params) = $DB->get_in_or_equal($SESSION->bulk_users);
50 | $rs = $DB->get_recordset_select('user', "id $in", $params, '', 'id, suspended');
51 | foreach ($rs as $user) {
52 | if ($action === 'suspend') {
53 | if (!is_siteadmin($user) && $USER->id != $user->id && $user->suspended != 1) {
54 | $user->suspended = 1;
55 | // Force logout.
56 | \core\session\manager::kill_user_sessions($user->id);
57 | user_update_user($user, false);
58 | }
59 | } else if ($action === 'unsuspend') {
60 | if ($user->suspended != 0) {
61 | $user->suspended = 0;
62 | user_update_user($user, false);
63 | }
64 | } else {
65 | throw new moodle_exception(get_string('unrecognisedaction', 'tool_bulkactiondemo'));
66 | }
67 | }
68 | $rs->close();
69 | echo $OUTPUT->box_start('generalbox', 'notice');
70 | if (!empty($notifications)) {
71 | echo $notifications;
72 | } else {
73 | echo $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
74 | }
75 | $continue = new single_button($return, get_string('continue'), 'post');
76 | echo $OUTPUT->render($continue);
77 | echo $OUTPUT->box_end();
78 | } else {
79 | list($in, $params) = $DB->get_in_or_equal($SESSION->bulk_users);
80 | $userlist = $DB->get_records_select_menu('user', "id $in", $params, 'fullname', 'id,'.$DB->sql_fullname().' AS fullname');
81 | $usernames = implode(', ', $userlist);
82 | echo $OUTPUT->heading(get_string('confirmation', 'admin'));
83 | $formcontinue = new single_button(new moodle_url('/admin/tool/bulkactiondemo/action.php',
84 | ['action' => $action, 'confirm' => 1, 'returnurl' => $returnurl]), get_string('yes'));
85 | $formcancel = new single_button($return, get_string('no'), 'get');
86 | if ($action === 'suspend') {
87 | echo $OUTPUT->confirm(get_string('confirmsuspend', 'tool_bulkactiondemo', $usernames), $formcontinue, $formcancel);
88 | } else if ($action === 'unsuspend') {
89 | echo $OUTPUT->confirm(get_string('confirmunsuspend', 'tool_bulkactiondemo', $usernames), $formcontinue, $formcancel);
90 | } else if ($action === 'unlock') {
91 | throw new moodle_exception(get_string('unrecognisedaction', 'tool_bulkactiondemo'));
92 | }
93 | }
94 |
95 | echo $OUTPUT->footer();
96 |
--------------------------------------------------------------------------------
/.github/workflows/gha.yml:
--------------------------------------------------------------------------------
1 | name: Moodle Plugin CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | test:
7 | runs-on: ubuntu-22.04
8 |
9 | services:
10 | postgres:
11 | image: postgres:13
12 | env:
13 | POSTGRES_USER: 'postgres'
14 | POSTGRES_HOST_AUTH_METHOD: 'trust'
15 | ports:
16 | - 5432:5432
17 | options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3
18 |
19 | mariadb:
20 | image: mariadb:10
21 | env:
22 | MYSQL_USER: 'root'
23 | MYSQL_ALLOW_EMPTY_PASSWORD: "true"
24 | MYSQL_CHARACTER_SET_SERVER: "utf8mb4"
25 | MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci"
26 | ports:
27 | - 3306:3306
28 | options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3
29 |
30 | strategy:
31 | fail-fast: false
32 | matrix:
33 | include:
34 | - php: '8.2'
35 | # Main job. Run all checks that do not require setup and only need to be run once.
36 | runchecks: 'all'
37 | moodle-branch: 'main'
38 | database: 'pgsql'
39 | - php: '8.1'
40 | moodle-branch: 'main'
41 | database: 'mariadb'
42 |
43 | steps:
44 | - name: Check out repository code
45 | uses: actions/checkout@v4
46 | with:
47 | path: plugin
48 |
49 | - name: Setup PHP ${{ matrix.php }}
50 | uses: shivammathur/setup-php@v2
51 | with:
52 | php-version: ${{ matrix.php }}
53 | extensions: ${{ matrix.extensions }}
54 | ini-values: max_input_vars=5000
55 | # If you are not using code coverage, keep "none". Otherwise, use "pcov" (Moodle 3.10 and up) or "xdebug".
56 | # If you try to use code coverage with "none", it will fallback to phpdbg (which has known problems).
57 | coverage: none
58 |
59 | - name: Initialise moodle-plugin-ci
60 | run: |
61 | composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4
62 | echo $(cd ci/bin; pwd) >> $GITHUB_PATH
63 | echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
64 | sudo locale-gen en_AU.UTF-8
65 | echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
66 |
67 | - name: Install moodle-plugin-ci
68 | run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
69 | env:
70 | DB: ${{ matrix.database }}
71 | MOODLE_BRANCH: ${{ matrix.moodle-branch }}
72 | # Uncomment this to run Behat tests using the Moodle App.
73 | # MOODLE_APP: 'true'
74 |
75 | - name: PHP Lint
76 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
77 | run: moodle-plugin-ci phplint
78 |
79 | - name: PHP Copy/Paste Detector
80 | continue-on-error: true # This step will show errors but will not fail
81 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
82 | run: moodle-plugin-ci phpcpd
83 |
84 | - name: PHP Mess Detector
85 | continue-on-error: true # This step will show errors but will not fail
86 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
87 | run: moodle-plugin-ci phpmd
88 |
89 | - name: Moodle Code Checker
90 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
91 | run: moodle-plugin-ci phpcs --max-warnings 0
92 |
93 | - name: Moodle PHPDoc Checker
94 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
95 | run: moodle-plugin-ci phpdoc --max-warnings 0
96 |
97 | - name: Validating
98 | if: ${{ !cancelled() }}
99 | run: moodle-plugin-ci validate
100 |
101 | - name: Check upgrade savepoints
102 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
103 | run: moodle-plugin-ci savepoints
104 |
105 | - name: Mustache Lint
106 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
107 | run: moodle-plugin-ci mustache
108 |
109 | - name: Grunt
110 | if: ${{ !cancelled() && matrix.runchecks == 'all' }}
111 | run: moodle-plugin-ci grunt --max-lint-warnings 0
112 |
113 | - name: PHPUnit tests
114 | if: ${{ !cancelled() }}
115 | run: moodle-plugin-ci phpunit --fail-on-warning
116 |
117 | - name: Behat features
118 | if: ${{ !cancelled() }}
119 | run: moodle-plugin-ci behat --profile chrome
120 |
121 | - name: Mark cancelled jobs as failed.
122 | if: ${{ cancelled() }}
123 | run: exit 1
124 |
--------------------------------------------------------------------------------
/amd/build/actions.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"actions.min.js","sources":["../src/actions.js"],"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 .\n\n/**\n * Perform bulk user action in AJAX request\n *\n * @module tool_bulkactiondemo/actions\n * @copyright 2024 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport {getStrings} from 'core/str';\nimport Ajax from 'core/ajax';\nimport * as reportEvents from 'core_reportbuilder/local/events';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport * as reportSelectors from 'core_reportbuilder/local/selectors';\nimport {add as addToast} from 'core/toast';\nimport * as FormChangeChecker from 'core_form/changechecker';\n\nconst SELECTORS = {\n bulkActionForm: 'body#page-admin-user form#user-bulk-action-form',\n};\n\n/**\n * Initialise module\n */\nexport const init = () => {\n const form = document.querySelector(SELECTORS.bulkActionForm);\n\n if (!form) {\n return;\n }\n\n form.addEventListener('submit', (e) => {\n let action = form.querySelector('select[name=\"action\"]')?.value;\n if (!action.startsWith('tool_bulkactiondemo_')) {\n return;\n }\n\n e.preventDefault();\n FormChangeChecker.markFormSubmitted(e.target);\n\n action = action.replace('tool_bulkactiondemo_', '');\n const userlist = e.target.data.usernames.join(', ');\n const userids = e.target.data.userids;\n\n let key;\n if (action === 'suspend') {\n key = 'confirmsuspend';\n } else if (action === 'unsuspend') {\n key = 'confirmunsuspend';\n } else {\n return;\n }\n\n getStrings([\n {'key': 'confirm'},\n {'key': key, component: 'tool_bulkactiondemo', param: userlist},\n {'key': 'yes'},\n {'key': 'no'},\n {'key': 'changessaved', component: 'moodle'}\n ])\n .then(strings => {\n form.querySelector('select[name=\"action\"]').value = '0';\n return Notification.confirm(strings[0], strings[1], strings[2], strings[3],\n () => performAction(action, userids, strings[4]));\n })\n .catch(Notification.exception);\n });\n};\n\n/**\n * Perform action\n *\n * @param {String} action\n * @param {Array} userids\n * @param {String} successMessage\n */\nfunction performAction(action, userids, successMessage) {\n const reportElement = document.querySelector('[data-region=\"report-user-list-wrapper\"] ' + reportSelectors.regions.report);\n\n Ajax.call([{\n methodname: 'tool_bulkactiondemo_action',\n args: {\n action: action,\n userids: userids,\n },\n done: () => {\n addToast(successMessage, {});\n if (reportElement) {\n dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);\n }\n },\n fail: (error) => Notification.exception(error),\n }]);\n}"],"names":["SELECTORS","form","document","querySelector","addEventListener","e","action","_form$querySelector","value","startsWith","preventDefault","FormChangeChecker","markFormSubmitted","target","replace","userlist","data","usernames","join","userids","key","component","param","then","strings","Notification","confirm","successMessage","reportElement","reportSelectors","regions","report","call","methodname","args","done","reportEvents","tableReload","preservePagination","fail","error","exception","performAction","catch"],"mappings":";;;;;;;yVAgCMA,yBACc,gEAMA,WACVC,KAAOC,SAASC,cAAcH,0BAE/BC,MAILA,KAAKG,iBAAiB,UAAWC,gCACzBC,mCAASL,KAAKE,cAAc,+DAAnBI,oBAA6CC,UACrDF,OAAOG,WAAW,+BAIvBJ,EAAEK,iBACFC,kBAAkBC,kBAAkBP,EAAEQ,QAEtCP,OAASA,OAAOQ,QAAQ,uBAAwB,UAC1CC,SAAWV,EAAEQ,OAAOG,KAAKC,UAAUC,KAAK,MACxCC,QAAUd,EAAEQ,OAAOG,KAAKG,YAE1BC,OACW,YAAXd,OACAc,IAAM,qBACH,CAAA,GAAe,cAAXd,cACPc,IAAM,uCAKC,CACP,KAAQ,WACR,KAAQA,IAAKC,UAAW,sBAAuBC,MAAOP,UACtD,KAAQ,OACR,KAAQ,MACR,KAAQ,eAAgBM,UAAW,YAEtCE,MAAKC,UACFvB,KAAKE,cAAc,yBAAyBK,MAAQ,IAC7CiB,sBAAaC,QAAQF,QAAQ,GAAIA,QAAQ,GAAIA,QAAQ,GAAIA,QAAQ,IACpE,aAaOlB,OAAQa,QAASQ,sBAC9BC,cAAgB1B,SAASC,cAAc,4CAA8C0B,gBAAgBC,QAAQC,sBAE9GC,KAAK,CAAC,CACPC,WAAY,6BACZC,KAAM,CACF5B,OAAQA,OACRa,QAASA,SAEbgB,KAAM,oBACOR,eAAgB,IACrBC,mDACcQ,aAAaC,YAAa,CAACC,oBAAoB,GAAOV,gBAG5EW,KAAOC,OAAUf,sBAAagB,UAAUD,UA5B1BE,CAAcpC,OAAQa,QAASK,QAAQ,SAEpDmB,MAAMlB,sBAAagB"}
--------------------------------------------------------------------------------