Skip to content

Commit

Permalink
MDL-45242 Course: Enrol feature supports custom profile fields
Browse files Browse the repository at this point in the history
  • Loading branch information
sammarshallou committed Mar 10, 2021
1 parent e86ead1 commit 987e554
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 160 deletions.
3 changes: 2 additions & 1 deletion badges/criteria/award_criteria_profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public function get_options(&$mform) {
if (in_array($field, $existing)) {
$checked = true;
}
$this->config_options($mform, array('id' => $field, 'checked' => $checked, 'name' => \core\user_fields::get_display_name($field), 'error' => false));
$this->config_options($mform, array('id' => $field, 'checked' => $checked,
'name' => \core\user_fields::get_display_name($field), 'error' => false));
$none = false;
}
}
Expand Down
23 changes: 21 additions & 2 deletions enrol/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -558,17 +558,36 @@ public static function get_potential_users($courseid, $enrolid, $search, $search

$results = array();
// Add also extra user fields.
$identityfields = \core\user_fields::get_identity_fields($context, true);
$customprofilefields = [];
foreach ($identityfields as $key => $value) {
if ($fieldname = \core\user_fields::match_custom_field($value)) {
unset($identityfields[$key]);
$customprofilefields[$fieldname] = true;
}
}
if ($customprofilefields) {
$identityfields[] = 'customfields';
}
$requiredfields = array_merge(
['id', 'fullname', 'profileimageurl', 'profileimageurlsmall'],
// TODO Does not support custom user profile fields (MDL-70456).
\core\user_fields::get_identity_fields($context, false)
$identityfields
);
foreach ($users['users'] as $id => $user) {
// Note: We pass the course here to validate that the current user can at least view user details in this course.
// The user we are looking at is not in this course yet though - but we only fetch the minimal set of
// user records, and the user has been validated to have course:enrolreview in this course. Otherwise
// there is no way to find users who aren't in the course in order to enrol them.
if ($userdetails = user_get_user_details($user, $course, $requiredfields)) {
// For custom fields, only return the ones we actually need.
if ($customprofilefields && array_key_exists('customfields', $userdetails)) {
foreach ($userdetails['customfields'] as $key => $data) {
if (!array_key_exists($data['shortname'], $customprofilefields)) {
unset($userdetails['customfields'][$key]);
}
}
$userdetails['customfields'] = array_values($userdetails['customfields']);
}
$results[] = $userdetails;
}
}
Expand Down
89 changes: 52 additions & 37 deletions enrol/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

use core\user_fields;

defined('MOODLE_INTERNAL') || die();

/**
Expand Down Expand Up @@ -238,14 +240,15 @@ public function get_users($sort, $direction='ASC', $page=0, $perpage=25) {
list($instancessql, $params, $filter) = $this->get_instance_sql();
list($filtersql, $moreparams) = $this->get_filter_sql();
$params += $moreparams;
// TODO Does not support custom user profile fields (MDL-70456).
$extrafields = \core\user_fields::get_identity_fields($this->get_context(), false);
$extrafields[] = 'lastaccess';
$ufields = user_picture::fields('u', $extrafields);
$sql = "SELECT DISTINCT $ufields, COALESCE(ul.timeaccess, 0) AS lastcourseaccess
$userfields = user_fields::for_identity($this->get_context())->with_userpic()->excluding('lastaccess');
['selects' => $fieldselect, 'joins' => $fieldjoin, 'params' => $fieldjoinparams] =
(array)$userfields->get_sql('u', true, '', '', false);
$params += $fieldjoinparams;
$sql = "SELECT DISTINCT $fieldselect, COALESCE(ul.timeaccess, 0) AS lastcourseaccess
FROM {user} u
JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid $instancessql)
JOIN {enrol} e ON (e.id = ue.enrolid)
$fieldjoin
LEFT JOIN {user_lastaccess} ul ON (ul.courseid = e.courseid AND ul.userid = u.id)";
if ($this->groupfilter) {
$sql .= " LEFT JOIN ({groups_members} gm JOIN {groups} g ON (g.id = gm.groupid))
Expand All @@ -270,7 +273,7 @@ protected function get_filter_sql() {

// Search condition.
// TODO Does not support custom user profile fields (MDL-70456).
$extrafields = \core\user_fields::get_identity_fields($this->get_context(), false);
$extrafields = user_fields::get_identity_fields($this->get_context(), false);
list($sql, $params) = users_search_sql($this->searchfilter, 'u', true, $extrafields);

// Role condition.
Expand Down Expand Up @@ -343,23 +346,26 @@ public function get_other_users($sort, $direction='ASC', $page=0, $perpage=25) {
list($ctxcondition, $params) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
$params['courseid'] = $this->course->id;
$params['cid'] = $this->course->id;
// TODO Does not support custom user profile fields (MDL-70456).
$extrafields = \core\user_fields::get_identity_fields($this->get_context(), false);
$ufields = user_picture::fields('u', $extrafields);
$sql = "SELECT ra.id as raid, ra.contextid, ra.component, ctx.contextlevel, ra.roleid, $ufields,
coalesce(u.lastaccess,0) AS lastaccess
FROM {role_assignments} ra
JOIN {user} u ON u.id = ra.userid
JOIN {context} ctx ON ra.contextid = ctx.id
LEFT JOIN (
$userfields = user_fields::for_identity($this->get_context())->with_userpic();
['selects' => $fieldselect, 'joins' => $fieldjoin, 'params' => $fieldjoinparams] =
(array)$userfields->get_sql('u', true);
$params += $fieldjoinparams;
$sql = "SELECT ra.id as raid, ra.contextid, ra.component, ctx.contextlevel, ra.roleid,
coalesce(u.lastaccess,0) AS lastaccess
$fieldselect
FROM {role_assignments} ra
JOIN {user} u ON u.id = ra.userid
JOIN {context} ctx ON ra.contextid = ctx.id
$fieldjoin
LEFT JOIN (
SELECT ue.id, ue.userid
FROM {user_enrolments} ue
JOIN {enrol} e ON e.id = ue.enrolid
WHERE e.courseid = :courseid
) ue ON ue.userid=u.id
WHERE ctx.id $ctxcondition AND
ue.id IS NULL
ORDER BY $sort $direction, ctx.depth DESC";
WHERE ctx.id $ctxcondition AND
ue.id IS NULL
ORDER BY $sort $direction, ctx.depth DESC";
$this->otherusers[$key] = $DB->get_records_sql($sql, $params, $page*$perpage, $perpage);
}
return $this->otherusers[$key];
Expand All @@ -372,20 +378,33 @@ public function get_other_users($sort, $direction='ASC', $page=0, $perpage=25) {
* @param bool $searchanywhere Can the search term be anywhere, or must it be at the start.
* @return array with three elements:
* string list of fields to SELECT,
* string possible database joins for user fields
* string contents of SQL WHERE clause,
* array query params. Note that the SQL snippets use named parameters.
*/
protected function get_basic_search_conditions($search, $searchanywhere) {
global $DB, $CFG;

// Get custom user field SQL used for querying all the fields we need (identity, name, and
// user picture).
$userfields = user_fields::for_identity($this->context)->with_name()->with_userpic()
->excluding('username', 'lastaccess', 'maildisplay');
['selects' => $fieldselects, 'joins' => $fieldjoins, 'params' => $params, 'mappings' => $mappings] =
(array)$userfields->get_sql('u', true, '', '', false);

// Searchable fields are only the identity and name ones (not userpic).
$searchable = array_fill_keys($userfields->get_required_fields(
[user_fields::PURPOSE_IDENTITY, user_fields::PURPOSE_NAME]), true);

// Add some additional sensible conditions
$tests = array("u.id <> :guestid", 'u.deleted = 0', 'u.confirmed = 1');
$params = array('guestid' => $CFG->siteguest);
$params['guestid'] = $CFG->siteguest;
if (!empty($search)) {
// TODO Does not support custom user profile fields (MDL-70456).
$conditions = \core\user_fields::get_identity_fields($this->get_context(), false);
foreach (\core\user_fields::get_name_fields() as $field) {
$conditions[] = 'u.'.$field;
// Include identity and name fields as conditions.
foreach ($mappings as $fieldname => $fieldsql) {
if (array_key_exists($fieldname, $searchable)) {
$conditions[] = $fieldsql;
}
}
$conditions[] = $DB->sql_fullname('u.firstname', 'u.lastname');
if ($searchanywhere) {
Expand All @@ -403,15 +422,8 @@ protected function get_basic_search_conditions($search, $searchanywhere) {
}
$wherecondition = implode(' AND ', $tests);

// TODO Does not support custom user profile fields (MDL-70456).
$userfieldsapi = \core\user_fields::for_identity($this->get_context(), false)->excluding('username', 'lastaccess');
$extrafields = $userfieldsapi->get_required_fields();
$extrafields[] = 'username';
$extrafields[] = 'lastaccess';
$extrafields[] = 'maildisplay';
$ufields = user_picture::fields('u', $extrafields);

return array($ufields, $params, $wherecondition);
$selects = $fieldselects . ', u.username, u.lastaccess, u.maildisplay';
return [$selects, $fieldjoins, $params, $wherecondition];
}

/**
Expand Down Expand Up @@ -492,11 +504,12 @@ public function get_potential_users($enrolid, $search = '', $searchanywhere = fa
$addedenrollment = 0, $returnexactcount = false) {
global $DB;

list($ufields, $params, $wherecondition) = $this->get_basic_search_conditions($search, $searchanywhere);
[$ufields, $joins, $params, $wherecondition] = $this->get_basic_search_conditions($search, $searchanywhere);

$fields = 'SELECT '.$ufields;
$countfields = 'SELECT COUNT(1)';
$sql = " FROM {user} u
$joins
LEFT JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)
WHERE $wherecondition
AND ue.id IS NULL";
Expand Down Expand Up @@ -524,11 +537,12 @@ public function get_potential_users($enrolid, $search = '', $searchanywhere = fa
public function search_other_users($search = '', $searchanywhere = false, $page = 0, $perpage = 25, $returnexactcount = false) {
global $DB, $CFG;

list($ufields, $params, $wherecondition) = $this->get_basic_search_conditions($search, $searchanywhere);
[$ufields, $joins, $params, $wherecondition] = $this->get_basic_search_conditions($search, $searchanywhere);

$fields = 'SELECT ' . $ufields;
$countfields = 'SELECT COUNT(u.id)';
$sql = " FROM {user} u
$joins
LEFT JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.contextid = :contextid)
WHERE $wherecondition
AND ra.id IS NULL";
Expand All @@ -552,11 +566,12 @@ public function search_other_users($search = '', $searchanywhere = false, $page
*/
public function search_users(string $search = '', bool $searchanywhere = false, int $page = 0, int $perpage = 25,
bool $returnexactcount = false) {
list($ufields, $params, $wherecondition) = $this->get_basic_search_conditions($search, $searchanywhere);
[$ufields, $joins, $params, $wherecondition] = $this->get_basic_search_conditions($search, $searchanywhere);

$fields = 'SELECT ' . $ufields;
$countfields = 'SELECT COUNT(u.id)';
$sql = " FROM {user} u
$joins
JOIN {user_enrolments} ue ON ue.userid = u.id
JOIN {enrol} e ON ue.enrolid = e.id
WHERE $wherecondition
Expand Down Expand Up @@ -1053,7 +1068,7 @@ public function get_other_users_for_display(core_enrol_renderer $renderer, moodl
$context = $this->get_context();
$now = time();
// TODO Does not support custom user profile fields (MDL-70456).
$extrafields = \core\user_fields::get_identity_fields($context, false);
$extrafields = user_fields::get_identity_fields($context, false);

$users = array();
foreach ($userroles as $userrole) {
Expand Down Expand Up @@ -1132,7 +1147,7 @@ public function get_users_for_display(course_enrolment_manager $manager, $sort,

$url = new moodle_url($pageurl, $this->get_url_params());
// TODO Does not support custom user profile fields (MDL-70456).
$extrafields = \core\user_fields::get_identity_fields($context, false);
$extrafields = user_fields::get_identity_fields($context, false);

$enabledplugins = $this->get_enrolment_plugins(true);

Expand Down
2 changes: 1 addition & 1 deletion enrol/manual/amd/build/form-potential-user-selector.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 987e554

Please sign in to comment.