MDL-71466 admin: Add custom user field support to role screens
authorsam marshall <s.marshall@open.ac.uk>
Tue, 27 Apr 2021 14:46:51 +0000 (15:46 +0100)
committersam marshall <s.marshall@open.ac.uk>
Tue, 11 May 2021 11:00:46 +0000 (12:00 +0100)
Implements custom user field support within the 'check capabilities'
and 'assign roles' screens.

admin/roles/classes/assign_user_selector_base.php
admin/roles/classes/check_users_selector.php
admin/roles/classes/existing_role_holders.php
admin/roles/classes/potential_assignees_below_course.php
admin/roles/classes/potential_assignees_course_and_above.php
admin/tests/behat/assign.feature [new file with mode: 0644]
admin/tests/behat/check.feature [new file with mode: 0644]

index e1fcf00..84cd423 100644 (file)
@@ -45,6 +45,7 @@ abstract class core_role_assign_user_selector_base extends user_selector_base {
             $this->context = context::instance_by_id($options['contextid']);
         }
         $options['accesscontext'] = $this->context;
+        $options['includecustomfields'] = true;
         parent::__construct($name, $options);
         $this->roleid = $options['roleid'];
         require_once($CFG->dirroot . '/group/lib.php');
index 31929bd..b6e2330 100644 (file)
@@ -46,6 +46,7 @@ class core_role_check_users_selector extends user_selector_base {
         if (!isset($options['multiselect'])) {
             $options['multiselect'] = false;
         }
+        $options['includecustomfields'] = true;
         parent::__construct($name, $options);
 
         $coursecontext = $this->accesscontext->get_course_context(false);
@@ -61,8 +62,9 @@ class core_role_check_users_selector extends user_selector_base {
         global $DB;
 
         list($wherecondition, $params) = $this->search_sql($search, 'u');
+        $params = array_merge($params, $this->userfieldsparams);
 
-        $fields      = 'SELECT ' . $this->required_fields_sql('u');
+        $fields      = 'SELECT u.id, ' . $this->userfieldsselects;
         $countfields = 'SELECT COUNT(1)';
 
         $coursecontext = $this->accesscontext->get_course_context(false);
@@ -74,6 +76,7 @@ class core_role_check_users_selector extends user_selector_base {
                               JOIN {user_enrolments} ue ON (ue.userid = subu.id)
                               JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid1)
                            ) subq ON subq.id = u.id
+                           $this->userfieldsjoin
                      WHERE $wherecondition";
             $params['courseid1'] = $coursecontext->instanceid;
 
@@ -83,6 +86,7 @@ class core_role_check_users_selector extends user_selector_base {
                 $sql2 = " FROM {user} u
                      LEFT JOIN ({user_enrolments} ue
                                 JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid2)) ON (ue.userid = u.id)
+                               $this->userfieldsjoin
                          WHERE $wherecondition
                                AND ue.id IS NULL";
                 $params['courseid2'] = $coursecontext->instanceid;
@@ -95,12 +99,13 @@ class core_role_check_users_selector extends user_selector_base {
             }
             $sql1 = null;
             $sql2 = " FROM {user} u
+                           $this->userfieldsjoin
                      WHERE $wherecondition";
         }
 
         $params['contextid'] = $this->accesscontext->id;
 
-        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
+        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext, $this->userfieldsmappings);
         $order = ' ORDER BY ' . $sort;
 
         $result = array();
index fd867d6..38794d7 100644 (file)
@@ -35,17 +35,18 @@ class core_role_existing_role_holders extends core_role_assign_user_selector_bas
 
         list($wherecondition, $params) = $this->search_sql($search, 'u');
         list($ctxcondition, $ctxparams) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
-        $params = array_merge($params, $ctxparams);
+        $params = array_merge($params, $ctxparams, $this->userfieldsparams);
         $params['roleid'] = $this->roleid;
 
-        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
+        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext, $this->userfieldsmappings);
         $params = array_merge($params, $sortparams);
 
-        $fields = "SELECT ra.id AS raid," . $this->required_fields_sql('u') . ",ra.contextid,ra.component ";
+        $fields = "SELECT ra.id AS raid, u.id, " . $this->userfieldsselects . ", ra.contextid, ra.component ";
         $countfields = "SELECT COUNT(1) ";
         $sql = "FROM {role_assignments} ra
                   JOIN {user} u ON u.id = ra.userid
                   JOIN {context} ctx ON ra.contextid = ctx.id
+                       $this->userfieldsjoin
                  WHERE $wherecondition
                        AND ctx.id $ctxcondition
                        AND ra.roleid = :roleid";
index ce60366..4c755f0 100644 (file)
@@ -39,25 +39,26 @@ class core_role_potential_assignees_below_course extends core_role_assign_user_s
 
         // Now we have to go to the database.
         list($wherecondition, $params) = $this->search_sql($search, 'u');
-        $params = array_merge($params, $eparams);
+        $params = array_merge($params, $eparams, $this->userfieldsparams);
 
         if ($wherecondition) {
             $wherecondition = ' AND ' . $wherecondition;
         }
 
-        $fields      = 'SELECT ' . $this->required_fields_sql('u');
+        $fields      = 'SELECT u.id, ' . $this->userfieldsselects;
         $countfields = 'SELECT COUNT(u.id)';
 
         $sql   = " FROM ($enrolsql) enrolled_users_view
                    JOIN {user} u ON u.id = enrolled_users_view.id
               LEFT JOIN {role_assignments} ra ON (ra.userid = enrolled_users_view.id AND
                                             ra.roleid = :roleid AND ra.contextid = :contextid)
+                        $this->userfieldsjoin
                   WHERE ra.id IS NULL
                         $wherecondition";
         $params['contextid'] = $this->context->id;
         $params['roleid'] = $this->roleid;
 
-        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
+        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext, $this->userfieldsmappings);
         $order = ' ORDER BY ' . $sort;
 
         // Check to see if there are too many to show sensibly.
index ed3a184..2ede8b7 100644 (file)
@@ -33,20 +33,22 @@ class core_role_potential_assignees_course_and_above extends core_role_assign_us
     public function find_users($search) {
         global $DB;
 
-        list($wherecondition, $params) = $this->search_sql($search, '');
+        list($wherecondition, $params) = $this->search_sql($search, 'u');
+        $params = array_merge($params, $this->userfieldsparams);
 
-        $fields      = 'SELECT ' . $this->required_fields_sql('');
+        $fields      = 'SELECT u.id, ' . $this->userfieldsselects;
         $countfields = 'SELECT COUNT(1)';
 
-        $sql = " FROM {user}
+        $sql = " FROM {user} u
+                      $this->userfieldsjoin
                 WHERE $wherecondition
-                      AND id NOT IN (
+                      AND u.id NOT IN (
                          SELECT r.userid
                            FROM {role_assignments} r
                           WHERE r.contextid = :contextid
                                 AND r.roleid = :roleid)";
 
-        list($sort, $sortparams) = users_order_by_sql('', $search, $this->accesscontext);
+        list($sort, $sortparams) = users_order_by_sql('', $search, $this->accesscontext, $this->userfieldsmappings);
         $order = ' ORDER BY ' . $sort;
 
         $params['contextid'] = $this->context->id;
diff --git a/admin/tests/behat/assign.feature b/admin/tests/behat/assign.feature
new file mode 100644 (file)
index 0000000..a56e761
--- /dev/null
@@ -0,0 +1,80 @@
+@core @core_admin
+Feature: Staff can assign user roles
+  In order to assign users to roles at site or activity module level
+  As an admin
+  I can add and remove users from the roles
+
+  Background:
+    Given the following "custom profile fields" exist:
+      | datatype | shortname | name           |
+      | text     | frog      | Favourite frog |
+    And the following config values are set as admin:
+      | showuseridentity | email,profile_field_frog |
+    And the following "users" exist:
+      | username | firstname | lastname | email           | profile_field_frog |
+      | user1    | User      | One      | one@example.com | Kermit             |
+      | user2    | User      | Two      | two@example.com | Tree               |
+    And the following "courses" exist:
+      | shortname | fullname |
+      | C1        | Course 1 |
+    And the following "course enrolments" exist:
+      | user  | course | role    |
+      | user1 | C1     | student |
+      | user2 | C1     | student |
+    And the following "activities" exist:
+      | activity | name     | course | idnumber |
+      | page     | TestPage | C1     | page1    |
+
+  @javascript
+  Scenario: Enrol at system level using custom field search
+    When I am on the "C1" "Course" page logged in as "admin"
+    And I navigate to "Users > Permissions > Assign system roles" in site administration
+    And I follow "Manager"
+    And I set the field "addselect_searchtext" to "Kermit"
+    # The Behat 'I should see' step doesn't work for optgroup labels.
+    Then "optgroup[label*='Potential users matching'][label*=' (1)']" "css_element" should exist
+    And I set the field "addselect" to "User One (one@example.com, Kermit)"
+    And I press "Add"
+    And I should see "User One" in the "#removeselect" "css_element"
+
+  @javascript
+  Scenario: Unenrol at system level using custom field search
+    Given the following "role assigns" exist:
+      | user  | role    | contextlevel | reference |
+      | user1 | manager | System       |           |
+    When I am on the "C1" "Course" page logged in as "admin"
+    And I navigate to "Users > Permissions > Assign system roles" in site administration
+    And I follow "Manager"
+    And I set the field "removeselect_searchtext" to "Kermit"
+    # The Behat 'I should see' step doesn't work for optgroup labels.
+    Then "optgroup[label*='Existing users matching'][label*=' (1)']" "css_element" should exist
+    And I set the field "removeselect" to "User One (one@example.com, Kermit)"
+    And I press "Remove"
+    And I should not see "User One" in the "#removeselect" "css_element"
+
+  @javascript
+  Scenario: Enrol at activity level using custom field search
+    When I am on the "page1" "Activity" page logged in as "admin"
+    And I navigate to "Locally assigned roles" in current page administration
+    And I follow "Teacher"
+    And I set the field "addselect_searchtext" to "Kermit"
+    # The Behat 'I should see' step doesn't work for optgroup labels.
+    Then "optgroup[label*='Potential users matching'][label*=' (1)']" "css_element" should exist
+    And I set the field "addselect" to "User One (one@example.com, Kermit)"
+    And I press "Add"
+    And I should see "User One" in the "#removeselect" "css_element"
+
+  @javascript
+  Scenario: Unenrol at activity level using custom field search
+    Given the following "role assigns" exist:
+      | user  | role           | contextlevel    | reference |
+      | user1 | editingteacher | Activity module | page1     |
+    When I am on the "page1" "Activity" page logged in as "admin"
+    And I navigate to "Locally assigned roles" in current page administration
+    And I follow "Teacher"
+    And I set the field "removeselect_searchtext" to "Kermit"
+    # The Behat 'I should see' step doesn't work for optgroup labels.
+    Then "optgroup[label*='Users in this Activity module matching'][label*=' (1)']" "css_element" should exist
+    And I set the field "removeselect" to "User One (one@example.com, Kermit)"
+    And I press "Remove"
+    And I should not see "User One" in the "#removeselect" "css_element"
diff --git a/admin/tests/behat/check.feature b/admin/tests/behat/check.feature
new file mode 100644 (file)
index 0000000..a881670
--- /dev/null
@@ -0,0 +1,54 @@
+@core @core_admin
+Feature: Staff can check user permissions
+  In order to find out whether a user can or can't do something
+  As an admin
+  I can check their permissions in a particular context
+
+  Background:
+    Given the following "custom profile fields" exist:
+      | datatype | shortname | name           |
+      | text     | frog      | Favourite frog |
+    And the following config values are set as admin:
+      | showuseridentity | email,profile_field_frog |
+    And the following "users" exist:
+      | username | firstname | lastname | email           | profile_field_frog |
+      | user1    | User      | One      | one@example.com | Kermit             |
+      | user2    | User      | Two      | two@example.com | Tree               |
+      | user3    | User      | Three    | thr@example.com | Kermit             |
+    And the following "courses" exist:
+      | shortname | fullname |
+      | C1        | Course 1 |
+      | C2        | Course 2 |
+    And the following "course enrolments" exist:
+      | user  | course | role           |
+      | user1 | C1     | editingteacher |
+      | user2 | C1     | editingteacher |
+      | user3 | C2     | editingteacher |
+
+  @javascript
+  Scenario: Search for a user (enrolled on the course) by custom field and select them to see permissions
+    When I am on the "C1" "Course" page logged in as "admin"
+    And I navigate to "Users > Permissions > Check permissions" in current page administration
+    And I set the field "Search" to "Kermit"
+    # The Behat 'I should see' step doesn't work for optgroup labels.
+    Then "optgroup[label='Matching enrolled users (1)']" "css_element" should exist
+    And I should see "User One (one@example.com, Kermit)"
+    And I should not see "User Two"
+    And I set the field "reportuser" to "User One (one@example.com, Kermit)"
+    And I press "Show this user's permissions"
+    And I should see "Permissions for user User One"
+    And I should see "Yes" in the "Add a new forum" "table_row"
+
+  @javascript
+  Scenario: Search for a user (not enrolled on the course) by custom field and select them to see permissions
+    When I am on the "C1" "Course" page logged in as "admin"
+    And I navigate to "Users > Permissions > Check permissions" in current page administration
+    And I set the field "Search" to "Kermit"
+    # The Behat 'I should see' step doesn't work for optgroup labels.
+    Then "optgroup[label*='Potential users matching'][label*=' (1)']" "css_element" should exist
+    And I should see "User Three (thr@example.com, Kermit)"
+    And I should not see "User Two"
+    And I set the field "reportuser" to "User Three (thr@example.com, Kermit)"
+    And I press "Show this user's permissions"
+    Then I should see "Permissions for user User Three"
+    And I should see "No" in the "Add a new forum" "table_row"