From 7154d8171a242dcb7da400edfaaa059fa5ada770 Mon Sep 17 00:00:00 2001
From: Nikolai Jahreis <63058688+NJahreis@users.noreply.github.com>
Date: Tue, 19 Nov 2024 07:12:30 +0100
Subject: [PATCH] Improvement: Add restriction for site admins to
smartmenu(item), resolves #421 . (#656)
---
CHANGES.md | 1 +
README.md | 1 +
classes/form/smartmenu_edit_form.php | 18 ++++++++++++++
classes/form/smartmenu_item_edit_form.php | 18 ++++++++++++++
classes/smartmenu.php | 18 ++++++++++++++
db/install.xml | 2 ++
db/upgrade.php | 24 +++++++++++++++++++
lang/en/theme_boost_union.php | 6 +++++
smartmenus/menulib.php | 24 +++++++++++++++++++
..._smartmenusettings_menuitems_rules.feature | 21 ++++++++++++++++
...nion_smartmenusettings_menus_rules.feature | 20 ++++++++++++++++
version.php | 2 +-
12 files changed, 154 insertions(+), 1 deletion(-)
diff --git a/CHANGES.md b/CHANGES.md
index 02d9b67a029..18b21ff4eb1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -6,6 +6,7 @@ Changes
### Unreleased
+* 2024-11-18 - Improvement: Add the possibility to restrict smart menus and smart menu items to site admins and non-site admins only, resolves #421.
* 2024-11-18 - Bugfix: Footer displacement on pages with minimal content, resolves #655.
* 2024-11-18 - Upstream change: Adopt changes from MDL-77732 ('Custom menu items do not receive active behaviour'), resolves #436 #620 #384 #715.
* 2024-11-13 - Upstream change: Adopt changes from MDL-78999 ('Site logo does not appear in mobile view'), resolves #753.
diff --git a/README.md b/README.md
index a8f7541fc48..b36b66a5fd7 100644
--- a/README.md
+++ b/README.md
@@ -854,6 +854,7 @@ Moodle an Hochschulen e.V. would like to thank these main contributors (in alpha
* Solent University, Mark Sharp: Code
* ssystems GmbH, Alexander Bias: Code, Peer Review, Ideating, Funding
* Technische Universität Berlin, Lars Bonczek: Code
+* University of Bayreuth, Nikolai Jahreis: Code
* University of Graz, André Menrath: Code
* University of Lübeck, Christian Wolters: Code, Peer Review, Ideating
* Zurich University of Applied Sciences (ZHAW): Funding, Ideating
diff --git a/classes/form/smartmenu_edit_form.php b/classes/form/smartmenu_edit_form.php
index c8768d6c0dc..c7ae6d4471e 100644
--- a/classes/form/smartmenu_edit_form.php
+++ b/classes/form/smartmenu_edit_form.php
@@ -208,6 +208,24 @@ public function definition() {
$mform->setType('rolecontext', PARAM_INT);
$mform->addHelpButton('rolecontext', 'smartmenusrolecontext', 'theme_boost_union');
+ // Add restrict visibility by admin as header element.
+ $mform->addElement('header', 'restrictbyadminheader',
+ get_string('smartmenusrestrictbyadminheader', 'theme_boost_union'));
+ if (isset($this->_customdata['menu']) && $this->_customdata['menu']->byadmin) {
+ $mform->setExpanded('restrictbyadminheader');
+ }
+
+ // Add restriction as select element.
+ $rolecontext = [
+ smartmenu::BYADMIN_ALL => get_string('smartmenusbyadmin_all', 'theme_boost_union'),
+ smartmenu::BYADMIN_ADMINS => get_string('smartmenusbyadmin_admins', 'theme_boost_union'),
+ smartmenu::BYADMIN_NONADMINS => get_string('smartmenusbyadmin_nonadmins', 'theme_boost_union'),
+ ];
+ $mform->addElement('select', 'byadmin', get_string('smartmenusbyadmin', 'theme_boost_union'), $rolecontext);
+ $mform->setDefault('byadmin', smartmenu::BYADMIN_ALL);
+ $mform->setType('byadmin', PARAM_INT);
+ $mform->addHelpButton('byadmin', 'smartmenusbyadmin', 'theme_boost_union');
+
// Add restrict visibility by cohorts as header element.
$mform->addElement('header', 'restrictbycohortsheader',
get_string('smartmenusrestrictbycohortsheader', 'theme_boost_union'));
diff --git a/classes/form/smartmenu_item_edit_form.php b/classes/form/smartmenu_item_edit_form.php
index 6ae779396d5..7ada173ec4b 100644
--- a/classes/form/smartmenu_item_edit_form.php
+++ b/classes/form/smartmenu_item_edit_form.php
@@ -377,6 +377,24 @@ public function definition() {
$mform->setType('rolecontext', PARAM_INT);
$mform->addHelpButton('rolecontext', 'smartmenusrolecontext', 'theme_boost_union');
+ // Add restrict visibility by admin as header element.
+ $mform->addElement('header', 'restrictbyadminheader',
+ get_string('smartmenusrestrictbyadminheader', 'theme_boost_union'));
+ if (isset($this->_customdata['menuitem']) && $this->_customdata['menuitem']->byadmin) {
+ $mform->setExpanded('restrictbyadminheader');
+ }
+
+ // Add restriction as select element.
+ $rolecontext = [
+ smartmenu::BYADMIN_ALL => get_string('smartmenusbyadmin_all', 'theme_boost_union'),
+ smartmenu::BYADMIN_ADMINS => get_string('smartmenusbyadmin_admins', 'theme_boost_union'),
+ smartmenu::BYADMIN_NONADMINS => get_string('smartmenusbyadmin_nonadmins', 'theme_boost_union'),
+ ];
+ $mform->addElement('select', 'byadmin', get_string('smartmenusbyadmin', 'theme_boost_union'), $rolecontext);
+ $mform->setDefault('byadmin', smartmenu::BYADMIN_ALL);
+ $mform->setType('byadmin', PARAM_INT);
+ $mform->addHelpButton('byadmin', 'smartmenusbyadmin', 'theme_boost_union');
+
// Add restrict visibility by cohorts as header element.
$mform->addElement('header', 'restrictbycohortsheader',
get_string('smartmenusrestrictbycohortsheader', 'theme_boost_union'));
diff --git a/classes/smartmenu.php b/classes/smartmenu.php
index 71ed75624fc..6c6f1be27f0 100644
--- a/classes/smartmenu.php
+++ b/classes/smartmenu.php
@@ -259,6 +259,24 @@ class smartmenu {
*/
public const MODE_SUBMENU = 1;
+ /**
+ * Restrict to admins: Show to all users.
+ * @var int
+ */
+ public const BYADMIN_ALL = 0;
+
+ /**
+ * Restrict to admins: Show only to admins.
+ * @var int
+ */
+ public const BYADMIN_ADMINS = 1;
+
+ /**
+ * Restrict to admins: Show only to non-admins.
+ * @var int
+ */
+ public const BYADMIN_NONADMINS = 2;
+
/**
* Cache key for the menus list.
*/
diff --git a/db/install.xml b/db/install.xml
index 5abf6d15d74..a1bb583694c 100644
--- a/db/install.xml
+++ b/db/install.xml
@@ -50,6 +50,7 @@
+
@@ -93,6 +94,7 @@
+
diff --git a/db/upgrade.php b/db/upgrade.php
index 8ae375c810c..8ada2daee60 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -324,5 +324,29 @@ function xmldb_theme_boost_union_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2023102027, 'theme', 'boost_union');
}
+ if ($oldversion < 2024100702) {
+
+ // Define field byadmin to be added to theme_boost_union_menus.
+ $table = new xmldb_table('theme_boost_union_menus');
+ $field = new xmldb_field('byadmin', XMLDB_TYPE_INTEGER, '9', null, XMLDB_NOTNULL, null, '0', 'visible');
+
+ // Conditionally launch add field byadmin.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Define field byadmin to be added to theme_boost_union_menuitems.
+ $table = new xmldb_table('theme_boost_union_menuitems');
+ $field = new xmldb_field('byadmin', XMLDB_TYPE_INTEGER, '9', null, XMLDB_NOTNULL, null, '0', 'timemodified');
+
+ // Conditionally launch add field byadmin.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Boost_union savepoint reached.
+ upgrade_plugin_savepoint(true, 2024100702, 'theme', 'boost_union');
+ }
+
return true;
}
diff --git a/lang/en/theme_boost_union.php b/lang/en/theme_boost_union.php
index c748fd2b20b..0109cc5dcd2 100644
--- a/lang/en/theme_boost_union.php
+++ b/lang/en/theme_boost_union.php
@@ -1120,6 +1120,11 @@
$string['smartmenusbylanguage_help'] = 'Restrict the visibility based on the user\'s language';
$string['smartmenusbyrole'] = 'By role';
$string['smartmenusbyrole_help'] = 'Restrict the visibility based on the user\'s roles.';
+$string['smartmenusbyadmin'] = 'Show to';
+$string['smartmenusbyadmin_help'] = 'Restrict the visibility based on the fact if the user is a site admin or not.';
+$string['smartmenusbyadmin_all'] = 'All users';
+$string['smartmenusbyadmin_admins'] = 'Site admins only';
+$string['smartmenusbyadmin_nonadmins'] = 'Non-admins only';
$string['smartmenusdynamiccoursescompletionstatus'] = 'Completion status';
$string['smartmenusdynamiccoursescompletionstatus_help'] = 'The dynamic courses menu item list will contain all courses of the user which match the selected completion status. For example, if you select \'In progress\' as the completion status, the dynamic courses menu item list will only contain courses that the current user is currently working on.';
$string['smartmenusdynamiccoursescompletionstatuscompleted'] = 'Completed';
@@ -1277,6 +1282,7 @@
$string['smartmenusrestrictbydateheader'] = 'Restrict visibility by date';
$string['smartmenusrestrictbylanguageheader'] = 'Restrict visibility by language';
$string['smartmenusrestrictbyrolesheader'] = 'Restrict visibility by roles';
+$string['smartmenusrestrictbyadminheader'] = 'Restrict visibility by site admin status';
$string['smartmenusrolecontext'] = 'Context';
$string['smartmenusrolecontext_help'] = 'Select the context for which the user\'s role should be checked (Any context or system context only)';
$string['smartmenussavechangesandconfigure'] = 'Save and configure items';
diff --git a/smartmenus/menulib.php b/smartmenus/menulib.php
index 6703d401509..6945e814102 100644
--- a/smartmenus/menulib.php
+++ b/smartmenus/menulib.php
@@ -97,6 +97,11 @@ public function verify_access_restrictions() {
// Restriction by roles.
$this->restriction_byroles($query);
+ // Restricted by site admin status.
+ if (!$this->restriction_byadmin()) {
+ return false;
+ }
+
// Restriction by cohorts.
$this->restriction_bycohorts($query);
@@ -180,6 +185,25 @@ public function restriction_byroles(&$query) {
$query->params += array_merge($params, $inparam);
}
+ /**
+ * Verify if the menu is restricted to site admins.
+ *
+ * @return bool True if the menu is available for this user, otherwise false.
+ */
+ public function restriction_byadmin() {
+ // If the item is restricted to site admins only.
+ if ($this->data->byadmin == smartmenu::BYADMIN_ADMINS) {
+ return is_siteadmin($this->userid);
+
+ // Otherwise, if the item is restricted to non-site admins only.
+ } else if ($this->data->byadmin == smartmenu::BYADMIN_NONADMINS) {
+ return !is_siteadmin($this->userid);
+ }
+
+ // Allow the item to be viewed by the user.
+ return true;
+ }
+
/**
* The purpose of this function is to check if a user is assigned to one or more cohorts that are specified in a menu.
* For the operator "ALL" it gets the count of records and verfiy the records count is same as count of selected cohorts.
diff --git a/tests/behat/theme_boost_union_smartmenusettings_menuitems_rules.feature b/tests/behat/theme_boost_union_smartmenusettings_menuitems_rules.feature
index 992b849d7de..a19c3ae615a 100644
--- a/tests/behat/theme_boost_union_smartmenusettings_menuitems_rules.feature
+++ b/tests/behat/theme_boost_union_smartmenusettings_menuitems_rules.feature
@@ -101,6 +101,27 @@ Feature: Configuring the theme_boost_union plugin on the "Smart menus" page, app
| Guest | Any | should not | should not | should not | should | should not | should not | should not |
| Visitor | Any | should not | should not | should not | should not | should not | should not | should |
+ @javascript
+ Scenario Outline: Smartmenu: Menu items: Rules - Show smart menu item based on being site admin
+ When I navigate to smart menus
+ And I should see "Quick links" in the "smartmenus" "table"
+ And I should see smart menu "Quick links" item "Resources" in location "Main, Menu, User, Bottom"
+ And I click on ".action-list-items" "css_element" in the "Quick links" "table_row"
+ And I click on ".action-edit" "css_element" in the "Resources" "table_row"
+ And I expand all fieldsets
+ And I set the field "Show to" to ""
+ And I click on "Save changes" "button"
+ And I see smart menu "Quick links" item "Resources" in location "Main, Menu, User, Bottom"
+ And I log out
+ And I log in as "student1"
+ Then I see smart menu "Quick links" item "Resources" in location "Main, Menu, User, Bottom"
+
+ Examples:
+ | byadmin | adminshouldorshouldnot | student1shouldorshouldnot |
+ | 0 | should | should |
+ | 1 | should | should not |
+ | 2 | should not | should |
+
@javascript
Scenario Outline: Smartmenu: Menu items: Rules - Show smart menu item based on the user assignment in single cohorts
When I navigate to smart menus
diff --git a/tests/behat/theme_boost_union_smartmenusettings_menus_rules.feature b/tests/behat/theme_boost_union_smartmenusettings_menus_rules.feature
index 8020396328f..40436a28918 100644
--- a/tests/behat/theme_boost_union_smartmenusettings_menus_rules.feature
+++ b/tests/behat/theme_boost_union_smartmenusettings_menus_rules.feature
@@ -96,6 +96,26 @@ Feature: Configuring the theme_boost_union plugin on the "Smart menus" page, app
| Guest | Any | should not | should not | should not | should | should not | should not | should not |
| Visitor | Any | should not | should not | should not | should not | should not | should not | should |
+ @javascript
+ Scenario Outline: Smartmenu: Menus: Rules - Show smart menu based on being site admin
+ When I navigate to smart menus
+ And I should see "Quick links" in the "smartmenus" "table"
+ And I should see smart menu "Quick links" item "Resources" in location "Main, Menu, User, Bottom"
+ And I click on ".action-edit" "css_element" in the "Quick links" "table_row"
+ And I expand all fieldsets
+ And I set the field "Show to" to ""
+ And I click on "Save and return" "button"
+ And I see smart menu "Quick links" in location "Main, Menu, User, Bottom"
+ And I log out
+ And I log in as "student1"
+ Then I see smart menu "Quick links" in location "Main, Menu, User, Bottom"
+
+ Examples:
+ | byadmin | adminshouldorshouldnot | student1shouldorshouldnot |
+ | 0 | should | should |
+ | 1 | should | should not |
+ | 2 | should not | should |
+
@javascript
Scenario Outline: Smartmenu: Menus: Rules - Show smart menu based on the user assignment in single cohorts
When I navigate to smart menus
diff --git a/version.php b/version.php
index 352fb08bc8f..04e98603984 100644
--- a/version.php
+++ b/version.php
@@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'theme_boost_union';
-$plugin->version = 2024100701;
+$plugin->version = 2024100702;
$plugin->release = 'v4.5-r2';
$plugin->requires = 2024100700;
$plugin->supported = [405, 405];