Merge branch 'MDL-26956' of git://github.com/timhunt/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 2 Apr 2013 11:49:02 +0000 (19:49 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 2 Apr 2013 11:49:02 +0000 (19:49 +0800)
enrol/locallib.php
enrol/renderer.php
enrol/users.php
enrol/users_forms.php
lib/datalib.php
lib/formslib.php
lib/tests/datalib_test.php
theme/base/style/core.css
user/selector/lib.php

index 3f6a506..e4ece1e 100644 (file)
@@ -53,6 +53,16 @@ class course_enrolment_manager {
      * @var string
      */
     protected $instancefilter = null;
+    /**
+     * Limits the focus of the manager to users with specified role
+     * @var int
+     */
+    protected $rolefilter = 0;
+    /**
+     * Limits the focus of the manager to users who match search string
+     * @var string
+     */
+    protected $searchfilter = '';
 
     /**
      * The total number of users enrolled in the course
@@ -110,12 +120,17 @@ class course_enrolment_manager {
      * @param moodle_page $moodlepage
      * @param stdClass $course
      * @param string $instancefilter
+     * @param int $rolefilter If non-zero, filters to users with specified role
+     * @param string $searchfilter If non-blank, filters to users with search text
      */
-    public function __construct(moodle_page $moodlepage, $course, $instancefilter = null) {
+    public function __construct(moodle_page $moodlepage, $course, $instancefilter = null,
+            $rolefilter = 0, $searchfilter = '') {
         $this->moodlepage = $moodlepage;
         $this->context = context_course::instance($course->id);
         $this->course = $course;
         $this->instancefilter = $instancefilter;
+        $this->rolefilter = $rolefilter;
+        $this->searchfilter = $searchfilter;
     }
 
     /**
@@ -139,10 +154,13 @@ class course_enrolment_manager {
         global $DB;
         if ($this->totalusers === null) {
             list($instancessql, $params, $filter) = $this->get_instance_sql();
+            list($filtersql, $moreparams) = $this->get_filter_sql();
+            $params += $moreparams;
             $sqltotal = "SELECT COUNT(DISTINCT u.id)
                            FROM {user} u
                            JOIN {user_enrolments} ue ON (ue.userid = u.id  AND ue.enrolid $instancessql)
-                           JOIN {enrol} e ON (e.id = ue.enrolid)";
+                           JOIN {enrol} e ON (e.id = ue.enrolid)
+                          WHERE $filtersql";
             $this->totalusers = (int)$DB->count_records_sql($sqltotal, $params);
         }
         return $this->totalusers;
@@ -183,7 +201,8 @@ class course_enrolment_manager {
      * Gets all of the users enrolled in this course.
      *
      * If a filter was specified this will be the users who were enrolled
-     * in this course by means of that instance.
+     * in this course by means of that instance. If role or search filters were
+     * specified then these will also be applied.
      *
      * @global moodle_database $DB
      * @param string $sort
@@ -200,6 +219,8 @@ class course_enrolment_manager {
         $key = md5("$sort-$direction-$page-$perpage");
         if (!array_key_exists($key, $this->users)) {
             list($instancessql, $params, $filter) = $this->get_instance_sql();
+            list($filtersql, $moreparams) = $this->get_filter_sql();
+            $params += $moreparams;
             $extrafields = get_extra_user_fields($this->get_context());
             $extrafields[] = 'lastaccess';
             $ufields = user_picture::fields('u', $extrafields);
@@ -207,7 +228,8 @@ class course_enrolment_manager {
                       FROM {user} u
                       JOIN {user_enrolments} ue ON (ue.userid = u.id  AND ue.enrolid $instancessql)
                       JOIN {enrol} e ON (e.id = ue.enrolid)
-                 LEFT JOIN {user_lastaccess} ul ON (ul.courseid = e.courseid AND ul.userid = u.id)";
+                 LEFT JOIN {user_lastaccess} ul ON (ul.courseid = e.courseid AND ul.userid = u.id)
+                     WHERE $filtersql";
             if ($sort === 'firstname') {
                 $sql .= " ORDER BY u.firstname $direction, u.lastname $direction";
             } else if ($sort === 'lastname') {
@@ -222,6 +244,37 @@ class course_enrolment_manager {
         return $this->users[$key];
     }
 
+    /**
+     * Obtains WHERE clause to filter results by defined search and role filter
+     * (instance filter is handled separately in JOIN clause, see
+     * get_instance_sql).
+     *
+     * @return array Two-element array with SQL and params for WHERE clause
+     */
+    protected function get_filter_sql() {
+        global $DB;
+
+        // Search condition.
+        $extrafields = get_extra_user_fields($this->get_context());
+        list($sql, $params) = users_search_sql($this->searchfilter, 'u', true, $extrafields);
+
+        // Role condition.
+        if ($this->rolefilter) {
+            // Get context SQL.
+            $contextids = $this->context->get_parent_context_ids();
+            $contextids[] = $this->context->id;
+            list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
+            $params += $contextparams;
+
+            // Role check condition.
+            $sql .= " AND (SELECT COUNT(1) FROM {role_assignments} ra WHERE ra.userid = u.id " .
+                    "AND ra.roleid = :roleid AND ra.contextid $contextsql) > 0";
+            $params['roleid'] = $this->rolefilter;
+        }
+
+        return array($sql, $params);
+    }
+
     /**
      * Gets and array of other users.
      *
@@ -795,6 +848,12 @@ class course_enrolment_manager {
         if (!empty($this->instancefilter)) {
             $args['ifilter'] = $this->instancefilter;
         }
+        if (!empty($this->rolefilter)) {
+            $args['role'] = $this->rolefilter;
+        }
+        if ($this->searchfilter !== '') {
+            $args['search'] = $this->searchfilter;
+        }
         return $args;
     }
 
index de8505c..3804a9f 100644 (file)
@@ -36,9 +36,11 @@ class core_enrol_renderer extends plugin_renderer_base {
      * Renders a course enrolment table
      *
      * @param course_enrolment_table $table
+     * @param moodleform $mform Form that contains filter controls
      * @return string
      */
-    protected function render_course_enrolment_users_table(course_enrolment_users_table $table) {
+    public function render_course_enrolment_users_table(course_enrolment_users_table $table,
+            moodleform $mform) {
 
         $table->initialise_javascript();
 
@@ -56,7 +58,8 @@ class core_enrol_renderer extends plugin_renderer_base {
         if (!empty($buttonhtml)) {
             $content .= $buttonhtml;
         }
-        $content .= $this->output->render($table->get_enrolment_type_filter());
+        $content .= $mform->render();
+
         $content .= $this->output->render($table->get_paging_bar());
 
         // Check if the table has any bulk operations. If it does we want to wrap the table in a
@@ -707,17 +710,6 @@ class course_enrolment_users_table extends course_enrolment_table {
      * @var array
      */
     protected static $sortablefields = array('firstname', 'lastname', 'email', 'lastaccess');
-
-    /**
-     * Gets the enrolment type filter control for this table
-     *
-     * @return single_select
-     */
-    public function get_enrolment_type_filter() {
-        $selector = new single_select($this->manager->get_moodlepage()->url, 'ifilter', array(0=>get_string('all')) + (array)$this->manager->get_enrolment_instance_names(), $this->manager->get_enrolment_filter(), array());
-        $selector->set_label( get_string('enrolmentinstances', 'enrol'));
-        return $selector;
-    }
 }
 
 /**
index d33174a..4b46be4 100644 (file)
@@ -32,6 +32,13 @@ require_once("$CFG->dirroot/group/lib.php");
 $id      = required_param('id', PARAM_INT); // course id
 $action  = optional_param('action', '', PARAM_ALPHANUMEXT);
 $filter  = optional_param('ifilter', 0, PARAM_INT);
+$search  = optional_param('search', '', PARAM_RAW);
+$role    = optional_param('role', 0, PARAM_INT);
+
+// When users reset the form, redirect back to first page without other params.
+if (optional_param('resetbutton', '', PARAM_RAW) !== '') {
+    redirect('users.php?id=' . $id);
+}
 
 $course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
 $context = context_course::instance($course->id, MUST_EXIST);
@@ -44,7 +51,7 @@ require_login($course);
 require_capability('moodle/course:enrolreview', $context);
 $PAGE->set_pagelayout('admin');
 
-$manager = new course_enrolment_manager($PAGE, $course, $filter);
+$manager = new course_enrolment_manager($PAGE, $course, $filter, $role, $search);
 $table = new course_enrolment_users_table($manager, $PAGE);
 $PAGE->set_url('/enrol/users.php', $manager->get_url_params()+$table->get_url_params());
 navigation_node::override_active_url(new moodle_url('/enrol/users.php', array('id' => $id)));
@@ -195,6 +202,10 @@ if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
     }
 }
 
+$filterform = new enrol_users_filter_form('users.php', array('manager' => $manager, 'id' => $id),
+        'get', '', array('id' => 'filterform'));
+$filterform->set_data(array('search' => $search, 'ifilter' => $filter, 'role' => $role));
+
 $table->set_fields($fields, $renderer);
 
 $canassign = has_capability('moodle/role:assign', $manager->get_context());
@@ -213,5 +224,5 @@ $PAGE->set_heading($PAGE->title);
 
 echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('enrolledusers', 'enrol'));
-echo $renderer->render($table);
+echo $renderer->render_course_enrolment_users_table($table, $filterform);
 echo $OUTPUT->footer();
index 390774c..2127935 100644 (file)
@@ -131,4 +131,50 @@ class enrol_users_addmember_form extends moodleform {
 
         $this->set_data(array('action'=>'addmember', 'user'=>$user->id));
     }
-}
\ No newline at end of file
+}
+
+
+/**
+ * Form that lets users filter the enrolled user list.
+ */
+class enrol_users_filter_form extends moodleform {
+    function definition() {
+        global $CFG, $DB;
+
+        $manager = $this->_customdata['manager'];
+
+        $mform = $this->_form;
+
+        // Text search box.
+        $mform->addElement('text', 'search', get_string('search'));
+        $mform->setType('search', PARAM_RAW);
+
+        // Filter by enrolment plugin type.
+        $mform->addElement('select', 'ifilter', get_string('enrolmentinstances', 'enrol'),
+                array(0 => get_string('all')) + (array)$manager->get_enrolment_instance_names());
+
+        // Role select dropdown includes all roles, but using course-specific
+        // names if applied. The reason for not restricting to roles that can
+        // be assigned at course level is that upper-level roles display in the
+        // enrolments table so it makes sense to let users filter by them.
+        $allroles = get_all_roles($manager->get_context());
+        $rolenames = array();
+        foreach ($allroles as $id => $role) {
+            $rolenames[$id] = $role->name;
+        }
+        $mform->addElement('select', 'role', get_string('role'),
+                array(0 => get_string('all')) + $rolenames);
+
+        // Submit button does not use add_action_buttons because that adds
+        // another fieldset which causes the CSS style to break in an unfixable
+        // way due to fieldset quirks.
+        $group = array();
+        $group[] = $mform->createElement('submit', 'submitbutton', get_string('filter'));
+        $group[] = $mform->createElement('submit', 'resetbutton', get_string('reset'));
+        $mform->addGroup($group, 'buttons', '', ' ', false);
+
+        // Add hidden fields required by page.
+        $mform->addElement('hidden', 'id', $this->_customdata['id']);
+        $mform->setType('id', PARAM_INT);
+    }
+}
index 9d25748..c9f096a 100644 (file)
@@ -190,6 +190,95 @@ function search_users($courseid, $groupid, $searchtext, $sort='', array $excepti
     }
 }
 
+/**
+ * Returns SQL used to search through user table to find users (in a query
+ * which may also join and apply other conditions).
+ *
+ * You can combine this SQL with an existing query by adding 'AND $sql' to the
+ * WHERE clause of your query (where $sql is the first element in the array
+ * returned by this function), and merging in the $params array to the parameters
+ * of your query (where $params is the second element). Your query should use
+ * named parameters such as :param, rather than the question mark style.
+ *
+ * There are examples of basic usage in the unit test for this function.
+ *
+ * @param string $search the text to search for (empty string = find all)
+ * @param string $u the table alias for the user table in the query being
+ *     built. May be ''.
+ * @param bool $searchanywhere If true (default), searches in the middle of
+ *     names, otherwise only searches at start
+ * @param array $extrafields Array of extra user fields to include in search
+ * @param array $exclude Array of user ids to exclude (empty = don't exclude)
+ * @param array $includeonly If specified, only returns users that have ids
+ *     incldued in this array (empty = don't restrict)
+ * @return array an array with two elements, a fragment of SQL to go in the
+ *     where clause the query, and an associative array containing any required
+ *     parameters (using named placeholders).
+ */
+function users_search_sql($search, $u = 'u', $searchanywhere = true, array $extrafields = array(),
+        array $exclude = array(), array $includeonly = array()) {
+    global $DB, $CFG;
+    $params = array();
+    $tests = array();
+
+    if ($u) {
+        $u .= '.';
+    }
+
+    // If we have a $search string, put a field LIKE '$search%' condition on each field.
+    if ($search) {
+        $conditions = array(
+            $DB->sql_fullname($u . 'firstname', $u . 'lastname'),
+            $conditions[] = $u . 'lastname'
+        );
+        foreach ($extrafields as $field) {
+            $conditions[] = $u . $field;
+        }
+        if ($searchanywhere) {
+            $searchparam = '%' . $search . '%';
+        } else {
+            $searchparam = $search . '%';
+        }
+        $i = 0;
+        foreach ($conditions as $key => $condition) {
+            $conditions[$key] = $DB->sql_like($condition, ":con{$i}00", false, false);
+            $params["con{$i}00"] = $searchparam;
+            $i++;
+        }
+        $tests[] = '(' . implode(' OR ', $conditions) . ')';
+    }
+
+    // Add some additional sensible conditions.
+    $tests[] = $u . "id <> :guestid";
+    $params['guestid'] = $CFG->siteguest;
+    $tests[] = $u . 'deleted = 0';
+    $tests[] = $u . 'confirmed = 1';
+
+    // If we are being asked to exclude any users, do that.
+    if (!empty($exclude)) {
+        list($usertest, $userparams) = $DB->get_in_or_equal($exclude, SQL_PARAMS_NAMED, 'ex', false);
+        $tests[] = $u . 'id ' . $usertest;
+        $params = array_merge($params, $userparams);
+    }
+
+    // If we are validating a set list of userids, add an id IN (...) test.
+    if (!empty($includeonly)) {
+        list($usertest, $userparams) = $DB->get_in_or_equal($includeonly, SQL_PARAMS_NAMED, 'val');
+        $tests[] = $u . 'id ' . $usertest;
+        $params = array_merge($params, $userparams);
+    }
+
+    // In case there are no tests, add one result (this makes it easier to combine
+    // this with an existing query as you can always add AND $sql).
+    if (empty($tests)) {
+        $tests[] = '1 = 1';
+    }
+
+    // Combing the conditions and return.
+    return array(implode(' AND ', $tests), $params);
+}
+
+
 /**
  * This function generates the standard ORDER BY clause for use when generating
  * lists of users. If you don't have a reason to use a different order, then
index b193f67..d1b1869 100644 (file)
@@ -921,6 +921,22 @@ abstract class moodleform {
         $this->_form->display();
     }
 
+    /**
+     * Renders the html form (same as display, but returns the result).
+     *
+     * Note that you can only output this rendered result once per page, as
+     * it contains IDs which must be unique.
+     *
+     * @return string HTML code for the form
+     */
+    public function render() {
+        ob_start();
+        $this->display();
+        $out = ob_get_contents();
+        ob_end_clean();
+        return $out;
+    }
+
     /**
      * Form definition. Abstract method - always override!
      */
index e758c74..cce2090 100644 (file)
@@ -43,6 +43,121 @@ class datalib_testcase extends advanced_testcase {
         $this->assertEquals($this->normalise_sql($expected), $this->normalise_sql($actual));
     }
 
+    /**
+     * Do a test of the user search SQL with database users.
+     */
+    public function test_users_search_sql() {
+        global $DB;
+
+        // Set up test users.
+        $this->resetAfterTest(true);
+        $user1 = array(
+            'username' => 'usernametest1',
+            'idnumber' => 'idnumbertest1',
+            'firstname' => 'First Name User Test 1',
+            'lastname' => 'Last Name User Test 1',
+            'email' => 'usertest1@email.com',
+            'address' => '2 Test Street Perth 6000 WA',
+            'phone1' => '01010101010',
+            'phone2' => '02020203',
+            'icq' => 'testuser1',
+            'skype' => 'testuser1',
+            'yahoo' => 'testuser1',
+            'aim' => 'testuser1',
+            'msn' => 'testuser1',
+            'department' => 'Department of user 1',
+            'institution' => 'Institution of user 1',
+            'description' => 'This is a description for user 1',
+            'descriptionformat' => FORMAT_MOODLE,
+            'city' => 'Perth',
+            'url' => 'http://moodle.org',
+            'country' => 'au'
+            );
+        $user1 = self::getDataGenerator()->create_user($user1);
+        $user2 = array(
+            'username' => 'usernametest2',
+            'idnumber' => 'idnumbertest2',
+            'firstname' => 'First Name User Test 2',
+            'lastname' => 'Last Name User Test 2',
+            'email' => 'usertest2@email.com',
+            'address' => '222 Test Street Perth 6000 WA',
+            'phone1' => '01010101010',
+            'phone2' => '02020203',
+            'icq' => 'testuser1',
+            'skype' => 'testuser1',
+            'yahoo' => 'testuser1',
+            'aim' => 'testuser1',
+            'msn' => 'testuser1',
+            'department' => 'Department of user 2',
+            'institution' => 'Institution of user 2',
+            'description' => 'This is a description for user 2',
+            'descriptionformat' => FORMAT_MOODLE,
+            'city' => 'Perth',
+            'url' => 'http://moodle.org',
+            'country' => 'au'
+            );
+        $user2 = self::getDataGenerator()->create_user($user2);
+
+        // Search by name (anywhere in text).
+        list($sql, $params) = users_search_sql('User Test 2', '');
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertFalse(array_key_exists($user1->id, $results));
+        $this->assertTrue(array_key_exists($user2->id, $results));
+
+        // Search by (most of) full name.
+        list($sql, $params) = users_search_sql('First Name User Test 2 Last Name User', '');
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertFalse(array_key_exists($user1->id, $results));
+        $this->assertTrue(array_key_exists($user2->id, $results));
+
+        // Search by name (start of text) valid or not.
+        list($sql, $params) = users_search_sql('User Test 2', '', false);
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertEquals(0, count($results));
+        list($sql, $params) = users_search_sql('First Name User Test 2', '', false);
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertFalse(array_key_exists($user1->id, $results));
+        $this->assertTrue(array_key_exists($user2->id, $results));
+
+        // Search by extra fields included or not (address).
+        list($sql, $params) = users_search_sql('Test Street', '', true);
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertEquals(0, count($results));
+        list($sql, $params) = users_search_sql('Test Street', '', true, array('address'));
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertEquals(2, count($results));
+
+        // Exclude user.
+        list($sql, $params) = users_search_sql('User Test', '', true, array(), array($user1->id));
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertFalse(array_key_exists($user1->id, $results));
+        $this->assertTrue(array_key_exists($user2->id, $results));
+
+        // Include only user.
+        list($sql, $params) = users_search_sql('User Test', '', true, array(), array(), array($user1->id));
+        $results = $DB->get_records_sql("SELECT id FROM {user} WHERE $sql ORDER BY username", $params);
+        $this->assertTrue(array_key_exists($user1->id, $results));
+        $this->assertFalse(array_key_exists($user2->id, $results));
+
+        // Join with another table and use different prefix.
+        set_user_preference('amphibian', 'frog', $user1);
+        set_user_preference('amphibian', 'salamander', $user2);
+        list($sql, $params) = users_search_sql('User Test 1', 'qq');
+        $results = $DB->get_records_sql("
+                SELECT
+                    up.id, up.value
+                FROM
+                    {user} qq
+                    JOIN {user_preferences} up ON up.userid = qq.id
+                WHERE
+                    up.name = :prefname
+                    AND $sql", array_merge(array('prefname' => 'amphibian'), $params));
+        $this->assertEquals(1, count($results));
+        foreach ($results as $record) {
+            $this->assertEquals('frog', $record->value);
+        }
+    }
+
     public function test_users_order_by_sql_simple() {
         list($sort, $params) = users_order_by_sql();
         $this->assert_same_sql('lastname, firstname, id', $sort);
index 7eee2ea..41409c0 100644 (file)
@@ -615,11 +615,22 @@ body.tag .managelink {padding: 5px;}
 .userenrolment .col_enrol .enrolment {float:left;padding:3px;margin:3px;}
 .userenrolment .col_enrol .enrolment a {float:right;margin-left:3px;}
 #page-enrol-users .enrol_user_buttons {float:right;}
+#page-enrol-users .enrol_user_buttons .singlebutton {margin-top: 2px; line-height: 2;}
 #page-enrol-users .enrol_user_buttons .enrolusersbutton {margin-left:1em;display:inline;}
 #page-enrol-users .enrol_user_buttons .enrolusersbutton div,
 #page-enrol-users .enrol_user_buttons .enrolusersbutton form {display:inline;}
 #page-enrol-users .enrol_user_buttons .enrolusersbutton input {padding-left:6px;padding-right:6px;}
 #page-enrol-users.dir-rtl .col_userdetails .subfield_picture {float: right;}
+#page-enrol-users #filterform div,
+#page-enrol-users #filterform fieldset {display:inline;float:none;clear:none;width:auto;margin:0;line-height:2;}
+#page-enrol-users #filterform .fitem {white-space:nowrap;}
+#page-enrol-users #filterform fieldset > div {display:block;float:left;background:#f2f2f2;padding:2px;}
+#page-enrol-users #filterform select,
+#page-enrol-users #filterform .ftext input {width:8em;}
+#page-enrol-users #filterform #fitem_id_role,
+#page-enrol-users #filterform #fitem_id_ifilter,
+#page-enrol-users #filterform #fgroup_id_buttons {margin-left:0.5em;}
+#page-enrol-users .paging { clear: right; }
 
 /**
 * Overide for RTL layout
index 18e9dfc..1483f6f 100644 (file)
@@ -434,63 +434,8 @@ abstract class user_selector_base {
      *      this uses ? style placeholders.
      */
     protected function search_sql($search, $u) {
-        global $DB, $CFG;
-        $params = array();
-        $tests = array();
-
-        if ($u) {
-            $u .= '.';
-        }
-
-        // If we have a $search string, put a field LIKE '$search%' condition on each field.
-        if ($search) {
-            $conditions = array(
-                $DB->sql_fullname($u . 'firstname', $u . 'lastname'),
-                $conditions[] = $u . 'lastname'
-            );
-            foreach ($this->extrafields as $field) {
-                $conditions[] = $u . $field;
-            }
-            if ($this->searchanywhere) {
-                $searchparam = '%' . $search . '%';
-            } else {
-                $searchparam = $search . '%';
-            }
-            $i = 0;
-            foreach ($conditions as $key=>$condition) {
-                $conditions[$key] = $DB->sql_like($condition, ":con{$i}00", false, false);
-                $params["con{$i}00"] = $searchparam;
-                $i++;
-            }
-            $tests[] = '(' . implode(' OR ', $conditions) . ')';
-        }
-
-        // Add some additional sensible conditions
-        $tests[] = $u . "id <> :guestid";
-        $params['guestid'] = $CFG->siteguest;
-        $tests[] = $u . 'deleted = 0';
-        $tests[] = $u . 'confirmed = 1';
-
-        // If we are being asked to exclude any users, do that.
-        if (!empty($this->exclude)) {
-            list($usertest, $userparams) = $DB->get_in_or_equal($this->exclude, SQL_PARAMS_NAMED, 'ex', false);
-            $tests[] = $u . 'id ' . $usertest;
-            $params = array_merge($params, $userparams);
-        }
-
-        // If we are validating a set list of userids, add an id IN (...) test.
-        if (!empty($this->validatinguserids)) {
-            list($usertest, $userparams) = $DB->get_in_or_equal($this->validatinguserids, SQL_PARAMS_NAMED, 'val');
-            $tests[] = $u . 'id ' . $usertest;
-            $params = array_merge($params, $userparams);
-        }
-
-        if (empty($tests)) {
-            $tests[] = '1 = 1';
-        }
-
-        // Combing the conditions and return.
-        return array(implode(' AND ', $tests), $params);
+        return users_search_sql($search, 'u', $this->searchanywhere, $this->extrafields,
+                $this->exclude, $this->validatinguserids);
     }
 
     /**