From 5788bf4dcdd5dedfcc46c042fd75a669d7396168 Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Fri, 20 Oct 2023 15:18:51 +1100 Subject: [PATCH 1/2] Issue #88 Add new capabilities for mass functionalities --- action.php | 19 +++++++-- block_massaction.php | 32 +++++++++------ db/access.php | 77 ++++++++++++++++++++++++++++++++++++ lang/en/block_massaction.php | 7 ++++ 4 files changed, 121 insertions(+), 14 deletions(-) diff --git a/action.php b/action.php index f0748d6..e9f13ab 100644 --- a/action.php +++ b/action.php @@ -38,13 +38,13 @@ require_login(); // Check capability. -$context = context_block::instance($instanceid); -require_capability('block/massaction:use', $context); +$blockcontext = context_block::instance($instanceid); +require_capability('block/massaction:use', $blockcontext); $data = block_massaction\massactionutils::extract_modules_from_json($massactionrequest); $modulerecords = $data->modulerecords; -$context = $context->get_course_context(); +$context = $blockcontext->get_course_context(); // Dispatch the submitted action. // Redirect to course by default. @@ -53,22 +53,27 @@ switch ($data->action) { case 'moveleft': require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:indent', $blockcontext); block_massaction\actions::adjust_indentation($modulerecords, -1); break; case 'moveright': require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:indent', $blockcontext); block_massaction\actions::adjust_indentation($modulerecords, 1); break; case 'hide': require_capability('moodle/course:activityvisibility', $context); + require_capability('block/massaction:activityshowhide', $blockcontext); block_massaction\actions::set_visibility($modulerecords, false); break; case 'show': require_capability('moodle/course:activityvisibility', $context); + require_capability('block/massaction:activityshowhide', $blockcontext); block_massaction\actions::set_visibility($modulerecords, true); break; case 'makeavailable': require_capability('moodle/course:activityvisibility', $context); + require_capability('block/massaction:activityshowhide', $blockcontext); if (empty($CFG->allowstealth)) { throw new invalid_parameter_exception('The "makeavailable" action is deactivated.'); } @@ -77,6 +82,7 @@ case 'duplicate': require_capability('moodle/backup:backuptargetimport', $context); require_capability('moodle/restore:restoretargetimport', $context); + require_capability('block/massaction:duplicate', $blockcontext); if (get_config('block_massaction', 'duplicatemaxactivities') < count($modulerecords)) { $duplicatetask = new duplicate_task(); $duplicatetask->set_userid($USER->id); @@ -90,6 +96,7 @@ break; case 'delete': require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:delete', $blockcontext); if (!$deletionconfirmed) { $redirect = false; block_massaction\actions::print_deletion_confirmation($modulerecords, $massactionrequest, $instanceid, $returnurl); @@ -99,14 +106,17 @@ break; case 'showdescription': require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:descriptionshowhide', $blockcontext); block_massaction\actions::show_description($modulerecords, true); break; case 'hidedescription': require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:descriptionshowhide', $blockcontext); block_massaction\actions::show_description($modulerecords, false); break; case 'contentchangednotification': require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:sendcontentchangednotifications', $blockcontext); block_massaction\actions::send_content_changed_notifications($modulerecords); break; case 'moveto': @@ -114,6 +124,7 @@ throw new moodle_exception('missingparam', 'block_massaction'); } require_capability('moodle/course:manageactivities', $context); + require_capability('block/massaction:movetosection', $blockcontext); block_massaction\actions::perform_moveto($modulerecords, $data->moveToTarget); break; case 'duplicateto': @@ -122,6 +133,7 @@ } require_capability('moodle/backup:backuptargetimport', $context); require_capability('moodle/restore:restoretargetimport', $context); + require_capability('block/massaction:movetosection', $blockcontext); if (get_config('block_massaction', 'duplicatemaxactivities') < count($modulerecords)) { $duplicatetask = new duplicate_task(); $duplicatetask->set_userid($USER->id); @@ -157,6 +169,7 @@ require_capability('moodle/backup:backuptargetimport', $context); require_capability('moodle/restore:restoretargetimport', context_course::instance($targetcourseid)); + require_capability('block/massaction:duplicatetocourse', $blockcontext); $sectionselectform = new block_massaction\form\section_select_form(null, $options); if ($sectionselectform->is_cancelled()) { diff --git a/block_massaction.php b/block_massaction.php index 7192b49..383d3e1 100644 --- a/block_massaction.php +++ b/block_massaction.php @@ -92,6 +92,7 @@ public function get_content(): stdClass { $this->content->footer = ''; if ($this->page->user_is_editing()) { + $blockcontext = context_block::instance($this->instance->id); $applicableformatkey = 'course-view-' . $COURSE->format; $iscoursecompatible = in_array($applicableformatkey, array_keys($this->applicable_formats())) @@ -126,7 +127,8 @@ public function get_content(): stdClass { $context = context_course::instance($COURSE->id); // Actions to be rendered later on. $actionicons = []; - if (has_capability('moodle/course:activityvisibility', $context)) { + if (has_capability('moodle/course:activityvisibility', $context) + && has_capability('block/massaction:activityshowhide', $blockcontext)) { // As we want to use this symbol for the *operation*, not the state, we switch the icons hide/show. $actionicons['show'] = 't/hide'; $actionicons['hide'] = 't/show'; @@ -135,24 +137,30 @@ public function get_content(): stdClass { } } if (has_capability('moodle/backup:backuptargetimport', $context) - && has_capability('moodle/restore:restoretargetimport', $context)) { + && has_capability('moodle/restore:restoretargetimport', $context) + && has_capability('block/massaction:duplicate', $blockcontext)) { $actionicons['duplicate'] = 't/copy'; } - if (has_capability('moodle/backup:backuptargetimport', $context)) { + if (has_capability('moodle/backup:backuptargetimport', $context) + && has_capability('block/massaction:duplicatetocourse', $blockcontext)) { $actionicons['duplicatetocourse'] = 't/copy'; } if (has_capability('moodle/course:manageactivities', $context)) { - $actionicons['delete'] = 't/delete'; - if (course_get_format($COURSE->id)->uses_indentation()) { + if (has_capability('block/massaction:delete', $blockcontext)) { + $actionicons['delete'] = 't/delete'; + } + if (course_get_format($COURSE->id)->uses_indentation() + && has_capability('block/massaction:indent', $blockcontext)) { // From Moodle 4.0 on the course format has to declare if it supports indentation or not. $actionicons['moveright'] = 't/right'; $actionicons['moveleft'] = 't/left'; } - $actionicons['showdescription'] = 't/more'; - $actionicons['hidedescription'] = 't/less'; + if (has_capability('block/massaction:descriptionshowhide', $blockcontext)) { + $actionicons['showdescription'] = 't/more'; + $actionicons['hidedescription'] = 't/less'; + } } - if (has_capability('block/massaction:sendcontentchangednotifications', - context_block::instance($this->instance->id))) { + if (has_capability('block/massaction:sendcontentchangednotifications', $blockcontext)) { $actionicons['contentchangednotification'] = 't/email'; } @@ -166,9 +174,11 @@ public function get_content(): stdClass { ['actions' => $actions, 'formaction' => $CFG->wwwroot . '/blocks/massaction/action.php', 'instanceid' => $this->instance->id, 'requesturi' => $_SERVER['REQUEST_URI'], 'helpicon' => $OUTPUT->help_icon('usage', 'block_massaction'), - 'show_moveto_select' => has_capability('moodle/course:manageactivities', $context), + 'show_moveto_select' => (has_capability('moodle/course:manageactivities', $context) + && has_capability('block/massaction:movetosection', $context)), 'show_duplicateto_select' => (has_capability('moodle/backup:backuptargetimport', $context) && - has_capability('moodle/restore:restoretargetimport', $context)), + has_capability('moodle/restore:restoretargetimport', $context) + && has_capability('block/massaction:movetosection', $context)), 'sectionselecthelpicon' => $OUTPUT->help_icon('sectionselect', 'block_massaction') ]); } diff --git a/db/access.php b/db/access.php index 533a711..d72c6b7 100644 --- a/db/access.php +++ b/db/access.php @@ -46,6 +46,72 @@ 'clonepermissionsfrom' => 'moodle/site:manageblocks' ], + 'block/massaction:activityshowhide' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], + + 'block/massaction:duplicate' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], + + 'block/massaction:duplicatetocourse' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], + + 'block/massaction:delete' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], + + 'block/massaction:indent' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], + + 'block/massaction:descriptionshowhide' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], + 'block/massaction:sendcontentchangednotifications' => [ 'riskbitmask' => RISK_SPAM, 'captype' => 'write', @@ -56,4 +122,15 @@ ], 'clonepermissionsfrom' => 'moodle/course:manageactivities' ], + + 'block/massaction:movetosection' => [ + 'riskbitmask' => RISK_SPAM, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ], ]; diff --git a/lang/en/block_massaction.php b/lang/en/block_massaction.php index 4728fb9..0d52cf9 100644 --- a/lang/en/block_massaction.php +++ b/lang/en/block_massaction.php @@ -24,7 +24,14 @@ */ $string['pluginname'] = 'Mass Actions'; +$string['massaction:activityshowhide'] = 'Mass show/hide'; $string['massaction:addinstance'] = 'Add a new Mass Actions Block'; +$string['massaction:delete'] = 'Mass delete'; +$string['massaction:descriptionshowhide'] = 'Mass description show/hide'; +$string['massaction:duplicate'] = 'Mass duplicate'; +$string['massaction:duplicatetocourse'] = 'Mass duplicate to course'; +$string['massaction:indent'] = 'Mass indent'; +$string['massaction:movetosection'] = 'Mass move to section'; $string['massaction:use'] = 'Use the Mass Actions block'; $string['massaction:sendcontentchangednotifications'] = 'Send content changed notifications'; $string['blockname'] = 'Mass Actions'; From c2b17ca2e0b2ed30c635868caf0f061ba96cb965 Mon Sep 17 00:00:00 2001 From: Matt Davidson Date: Wed, 10 Jan 2024 09:37:14 -0500 Subject: [PATCH 2/2] Update block_massaction.php --- lang/en/block_massaction.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lang/en/block_massaction.php b/lang/en/block_massaction.php index 0d52cf9..24bf250 100644 --- a/lang/en/block_massaction.php +++ b/lang/en/block_massaction.php @@ -24,16 +24,18 @@ */ $string['pluginname'] = 'Mass Actions'; -$string['massaction:activityshowhide'] = 'Mass show/hide'; + +$string['massaction:activityshowhide'] = 'MassAction: Show/Hide modules'; $string['massaction:addinstance'] = 'Add a new Mass Actions Block'; -$string['massaction:delete'] = 'Mass delete'; -$string['massaction:descriptionshowhide'] = 'Mass description show/hide'; -$string['massaction:duplicate'] = 'Mass duplicate'; -$string['massaction:duplicatetocourse'] = 'Mass duplicate to course'; -$string['massaction:indent'] = 'Mass indent'; -$string['massaction:movetosection'] = 'Mass move to section'; +$string['massaction:delete'] = 'MassAction: Delete modules'; +$string['massaction:descriptionshowhide'] = 'MassAction: Show/Hide Descriptions'; +$string['massaction:duplicate'] = 'MassAction: Duplicate modules'; +$string['massaction:duplicatetocourse'] = 'MassAction: Duplicate to Course'; +$string['massaction:indent'] = 'MassAction: Indent modules'; +$string['massaction:movetosection'] = 'MassAction: Move to Section'; $string['massaction:use'] = 'Use the Mass Actions block'; $string['massaction:sendcontentchangednotifications'] = 'Send content changed notifications'; + $string['blockname'] = 'Mass Actions'; $string['blocktitle'] = 'Mass Actions'; $string['privacy:metadata'] = 'This block only offers the possibility to apply standard operations on multiple course modules at the same time.