public function find_users($search) {
        global $DB, $USER;

        $mailmaxusers = (isset($CFG->maxusersperpage) ? $CFG->maxusersperpage : $this->maxusersperpage);

        $context = context_course::instance($this->courseid);

        $mailsamerole = has_capability('local/mail:mailsamerole', $context);
        $userroleids = local_mail_get_user_roleids($USER->id, $context);

        list($wherecondition, $params) = $this->search_sql($search, 'u');
        list($enrolledsql, $enrolledparams) = get_enrolled_sql($context, '', $this->groupid, true);
        list($parentsql, $parentparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED);

        $params = array_merge($params, $enrolledparams, $parentparams);
        $params['courseid'] = $this->courseid;

        if (!$mailsamerole) {
            list($relctxsql, $reldctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relctx');
            list($samerolesql, $sameroleparams) = $DB->get_in_or_equal($userroleids, SQL_PARAMS_NAMED, 'samerole' , false);
            $wherecondition .= " AND u.id IN (SELECT userid FROM {role_assignments} WHERE roleid $samerolesql AND contextid $relctxsql)";
            $params = array_merge($params, $sameroleparams, $reldctxparams);
        }

        $fields = 'SELECT r.id AS roleid, '
            . 'r.shortname AS roleshortname, '
            . 'r.name AS rolename, '
            . 'u.id AS userid, '
            . $this->required_fields_sql('u');

        $countfields = 'SELECT COUNT(1)';

        $sql = ' FROM {user} u JOIN (' . $enrolledsql . ') e ON e.id = u.id'
            . ' LEFT JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.contextid '
            . $parentsql . ')'
            . ' LEFT JOIN {role} r ON r.id = ra.roleid'
            . ' WHERE ' . $wherecondition;

        $order = ' ORDER BY r.sortorder, u.lastname ASC, u.firstname ASC';

        if (!$this->is_validating()) {
            $count = $DB->count_records_sql($countfields . $sql, $params);
            if ($count > $mailmaxusers) {
                return $this->too_many_results($search, $count);
            }
        }

        $rs = $DB->get_recordset_sql($fields . $sql . $order, $params);
        $roles = groups_calculate_role_people($rs, $context);

        return $this->convert_array_format($roles, $search);
    }
    public function recipientsform($courseid, $userid) {
        global $COURSE, $DB;

        $options = array();

        $owngroups = groups_get_user_groups($courseid, $userid);
        $content = html_writer::start_tag('div', array('id' => 'local_mail_recipients_form', 'class' => 'local_mail_form mail_hidden'));

        if ($COURSE->groupmode == SEPARATEGROUPS and empty($owngroups[0])) {
            return '';
        }
        $content .= html_writer::start_tag('div', array('class' => 'mail_recipients_toolbar'));

        // Roles
        $context = context_course::instance($courseid);
        $roles = role_get_names($context);
        $userroles = local_mail_get_user_roleids($userid, $context);
        $mailsamerole = has_capability('local/mail:mailsamerole', $context);
        foreach ($roles as $key => $role) {
            $count = $DB->count_records_select('role_assignments', "contextid = :contextid AND roleid = :roleid AND userid <> :userid",
                array('contextid' => $context->id, 'roleid' => $role->id, 'userid' => $userid));
            if (($count && $mailsamerole)
                || ($count && !$mailsamerole && !in_array($role->id, $userroles))) {
                $options[$key] = $role->localname;
            }
        }
        $text = get_string('role', 'moodle');
        $content .= html_writer::start_tag('span', array('class' => 'roleselector'));
        $content .= html_writer::label($text, 'local_mail_roles');
        $text = get_string('all', 'local_mail');
        $content .= html_writer::select($options, 'local_mail_roles', '', array('' => $text), array('id' => 'local_mail_recipients_roles', 'class' => ''));
        $content .= html_writer::end_tag('span');
        // Groups
        $groups = groups_get_all_groups($courseid);
        if ($COURSE->groupmode == NOGROUPS or ($COURSE->groupmode == VISIBLEGROUPS and empty($groups))) {
            $content .= html_writer::tag('span', get_string('allparticipants', 'moodle'), array('class' => 'groupselector groupname'));
        } else {
            if ($COURSE->groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
                unset($options);
                foreach ($groups as $key => $group) {
                    $options[$key] = $group->name;
                }
                $text = get_string('group', 'moodle');
                $content .= html_writer::start_tag('span', array('class' => 'groupselector'));
                $content .= html_writer::label($text, 'local_mail_recipients_groups');
                $text = get_string('allparticipants', 'moodle');
                $content .= html_writer::select($options, 'local_mail_recipients_groups', '', array('' => $text), array('id' => 'local_mail_recipients_groups', 'class' => ''));
                $content .= html_writer::end_tag('span');
            } else if (count($owngroups[0]) == 1) {// SEPARATEGROUPS and user in only one group
                $text = get_string('group', 'moodle');
                $content .= html_writer::start_tag('span', array('class' => 'groupselector'));
                $content .= html_writer::label("$text: ", null);
                $content .= html_writer::tag('span', groups_get_group_name($owngroups[0][0]), array('class' => 'groupname'));
                $content .= html_writer::end_tag('span');
            } else if (count($owngroups[0]) > 1) {// SEPARATEGROUPS and user in several groups
                unset($options);
                foreach ($owngroups[0] as $key => $group) {
                    $options[$group] = groups_get_group_name($group);
                }
                $text = get_string('group', 'moodle');
                $content .= html_writer::start_tag('span', array('class' => 'groupselector'));
                $content .= html_writer::label($text, 'local_mail_recipients_groups');
                $text = get_string('allparticipants', 'moodle');
                $content .= html_writer::select($options, 'local_mail_recipients_groups', '',
                    array(key($options) => current($options)), array('id' => 'local_mail_recipients_groups', 'class' => ''));
                $content .= html_writer::end_tag('span');
            }
        }
        $content .= html_writer::tag('div', '', array('class' => 'mail_separator'));
        // Search
        $content .= html_writer::start_tag('div', array('class' => 'mail_recipients_search'));
        $attributes = array(
                'type'  => 'text',
                'name'  => 'recipients_search',
                'value' => '',
                'maxlength' => '100',
                'class' => 'mail_search'
        );
        $text = get_string('search', 'local_mail');
        $content .= html_writer::label($text, 'recipients_search');
        $content .= html_writer::empty_tag('input', $attributes);
        // Select all recipients
        $content .= html_writer::start_tag('span', array('class' => 'mail_all_recipients_actions'));
        $attributes = array(
           'type' => 'button',
           'name' => "to_all",
           'value' => get_string('to', 'local_mail')
        );
        $content .= html_writer::empty_tag('input', $attributes);
        $attributes = array(
           'type' => 'button',
           'name' => "cc_all",
           'value' => get_string('cc', 'local_mail')
        );
        $content .= html_writer::empty_tag('input', $attributes);
        $attributes = array(
           'type' => 'button',
           'name' => "bcc_all",
           'value' => get_string('bcc', 'local_mail')
        );
        $content .= html_writer::empty_tag('input', $attributes);
        $attributes = array('type' => 'image',
                                'name' => "remove_all",
                                'src' => $this->output->pix_url('t/delete'),
                                'alt' => get_string('remove'));
        $content .= html_writer::empty_tag('input', $attributes);
        $content .= html_writer::end_tag('span');
        $content .= html_writer::end_tag('div');

        $content .= html_writer::end_tag('div');
        $content .= html_writer::tag('div', '', array('id' => 'local_mail_recipients_list', 'class' => 'mail_form_recipients'));
        $content .= html_writer::start_tag('div', array('class' => 'mail_recipients_loading'));
        $content .= $this->output->pix_icon('i/loading', get_string('actions'), 'moodle', array('class' => 'loading_icon'));
        $content .= html_writer::end_tag('div');
        $content .= html_writer::end_tag('div');
        return $content;
    }
function local_mail_getsqlrecipients($courseid, $search, $groupid, $roleid, $recipients = false) {
    global $CFG, $USER, $DB;

    $context = context_course::instance($courseid);

    $mailsamerole = has_capability('local/mail:mailsamerole', $context);

    list($esql, $params) = get_enrolled_sql($context, null, $groupid, true);
    $joins = array("FROM {user} u");
    $wheres = array();

    $mainuserfields = user_picture::fields('u', array('username', 'email', 'city', 'country', 'lang', 'timezone', 'maildisplay'));

    $extrasql = get_extra_user_fields_sql($context, 'u', '', array(
            'id', 'firstname', 'lastname'));
    $select = "SELECT $mainuserfields$extrasql";
    $joins[] = "JOIN ($esql) e ON e.id = u.id";

    // Performance hacks - we preload user contexts together with accounts.
    $ccselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
    $ccjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel)";
    $params['contextlevel'] = CONTEXT_USER;
    $select .= $ccselect;
    $joins[] = $ccjoin;

    if (!$mailsamerole) {
        $userroleids = local_mail_get_user_roleids($USER->id, $context);
        list($relctxsql, $reldctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relctx');
        list($samerolesql, $sameroleparams) = $DB->get_in_or_equal($userroleids, SQL_PARAMS_NAMED, 'samerole' , false);
        $wheres[] = "u.id IN (SELECT userid FROM {role_assignments} WHERE roleid $samerolesql AND contextid $relctxsql)";
        $params = array_merge($params, array('roleid' => $roleid), $sameroleparams, $reldctxparams);
    }

    if ($roleid) {
        // We want to query both the current context and parent contexts.
        list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
        $wheres[] = "u.id IN (SELECT userid FROM {role_assignments} WHERE roleid = :roleid AND contextid $relatedctxsql)";
        $params = array_merge($params, array('roleid' => $roleid), $relatedctxparams);
    }

    $from = implode("\n", $joins);

    if (!empty($search)) {
        $fullname = $DB->sql_fullname('u.firstname', 'u.lastname');
        $wheres[] = "(". $DB->sql_like($fullname, ':search1', false, false) .") ";
        $params['search1'] = "%$search%";
    }

    $from = implode("\n", $joins);

    $wheres[] = 'u.id <> :guestid AND u.deleted = 0 AND u.confirmed = 1 AND u.id <> :userid';
    $params['userid'] = $USER->id;
    $params['guestid'] = $CFG->siteguest;

    if ($recipients) {
        $wheres[] = 'u.id IN ('.preg_replace('/^,|,$/', '', $recipients).')';
    }

    $where = "WHERE " . implode(" AND ", $wheres);

    $sort = 'ORDER BY u.lastname ASC, u.firstname ASC';

    return array($select, $from, $where, $sort, $params);
}