diff --git a/badges/criteria/award_criteria_profile.php b/badges/criteria/award_criteria_profile.php
index bd887db96d1..dbba62aae38 100644
--- a/badges/criteria/award_criteria_profile.php
+++ b/badges/criteria/award_criteria_profile.php
@@ -88,7 +88,8 @@ class award_criteria_profile extends award_criteria {
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;
}
}
diff --git a/enrol/externallib.php b/enrol/externallib.php
index e2cfb216587..26dee5065d1 100644
--- a/enrol/externallib.php
+++ b/enrol/externallib.php
@@ -558,10 +558,20 @@ class core_enrol_external extends external_api {
$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.
@@ -569,6 +579,15 @@ class core_enrol_external extends external_api {
// 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;
}
}
diff --git a/enrol/locallib.php b/enrol/locallib.php
index cd6f9fd8788..ba49c560265 100644
--- a/enrol/locallib.php
+++ b/enrol/locallib.php
@@ -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();
/**
@@ -238,14 +240,15 @@ class course_enrolment_manager {
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))
@@ -270,7 +273,7 @@ class course_enrolment_manager {
// 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.
@@ -343,23 +346,26 @@ class course_enrolment_manager {
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];
@@ -372,20 +378,33 @@ class course_enrolment_manager {
* @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) {
@@ -403,15 +422,8 @@ class course_enrolment_manager {
}
$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];
}
/**
@@ -492,11 +504,12 @@ class course_enrolment_manager {
$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";
@@ -524,11 +537,12 @@ class course_enrolment_manager {
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";
@@ -552,11 +566,12 @@ class course_enrolment_manager {
*/
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
@@ -1053,7 +1068,7 @@ class course_enrolment_manager {
$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) {
@@ -1132,7 +1147,7 @@ class course_enrolment_manager {
$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);
diff --git a/enrol/manual/amd/build/form-potential-user-selector.min.js b/enrol/manual/amd/build/form-potential-user-selector.min.js
index 70944792b30..520f6313a69 100644
--- a/enrol/manual/amd/build/form-potential-user-selector.min.js
+++ b/enrol/manual/amd/build/form-potential-user-selector.min.js
@@ -1,2 +1,2 @@
-define ("enrol_manual/form-potential-user-selector",["jquery","core/ajax","core/templates","core/str"],function(a,b,c,d){return{processResults:function processResults(b,c){var d=[];if(a.isArray(c)){a.each(c,function(a,b){d.push({value:b.id,label:b._label})});return d}else{return c}},transport:function transport(e,f,g,h){var i,j=a(e).attr("courseid"),k=a(e).attr("userfields").split(",");if("undefined"==typeof j){j="1"}var l=a(e).attr("enrolid");if("undefined"==typeof l){l=""}var m=parseInt(a(e).attr("perpage"));if(isNaN(m)){m=100}i=b.call([{methodname:"core_enrol_get_potential_users",args:{courseid:j,enrolid:l,search:f,searchanywhere:!0,page:0,perpage:m+1}}]);i[0].then(function(b){var e=[],f=0;if(b.length<=m){a.each(b,function(b,d){var f=d,g=[];a.each(k,function(a,b){if("undefined"!=typeof d[b]&&""!==d[b]){f.hasidentity=!0;g.push(d[b])}});f.identity=g.join(", ");e.push(c.render("enrol_manual/form-user-selector-suggestion",f))});return a.when.apply(a.when,e).then(function(){var c=arguments;a.each(b,function(a,b){b._label=c[f];f++});g(b)})}else{return d.get_string("toomanyuserstoshow","core",">"+m).then(function(a){g(a)})}}).fail(h)}}});
+define ("enrol_manual/form-potential-user-selector",["jquery","core/ajax","core/templates","core/str"],function(a,b,c,d){return{processResults:function processResults(b,c){var d=[];if(a.isArray(c)){a.each(c,function(a,b){d.push({value:b.id,label:b._label})});return d}else{return c}},transport:function transport(e,f,g,h){var i,j=a(e).attr("courseid"),k=a(e).attr("userfields").split(",");if("undefined"==typeof j){j="1"}var l=a(e).attr("enrolid");if("undefined"==typeof l){l=""}var m=parseInt(a(e).attr("perpage"));if(isNaN(m)){m=100}i=b.call([{methodname:"core_enrol_get_potential_users",args:{courseid:j,enrolid:l,search:f,searchanywhere:!0,page:0,perpage:m+1}}]);i[0].then(function(b){var e=[],f=0;if(b.length<=m){a.each(b,function(b,d){var f=d,g=[];a.each(k,function(a,b){var c=/^profile_field_(.*)$/.exec(b);if(c){if(d.customfields){d.customfields.forEach(function(a){if(a.shortname===c[1]){f.hasidentity=!0;g.push(a.value)}})}}else{if("undefined"!=typeof d[b]&&""!==d[b]){f.hasidentity=!0;g.push(d[b])}}});f.identity=g.join(", ");e.push(c.render("enrol_manual/form-user-selector-suggestion",f))});return a.when.apply(a.when,e).then(function(){var c=arguments;a.each(b,function(a,b){b._label=c[f];f++});g(b)})}else{return d.get_string("toomanyuserstoshow","core",">"+m).then(function(a){g(a)})}}).fail(h)}}});
//# sourceMappingURL=form-potential-user-selector.min.js.map
diff --git a/enrol/manual/amd/build/form-potential-user-selector.min.js.map b/enrol/manual/amd/build/form-potential-user-selector.min.js.map
index 3f9f5baa2cd..33ca074160c 100644
--- a/enrol/manual/amd/build/form-potential-user-selector.min.js.map
+++ b/enrol/manual/amd/build/form-potential-user-selector.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/form-potential-user-selector.js"],"names":["define","$","Ajax","Templates","Str","processResults","selector","results","users","isArray","each","index","user","push","value","id","label","_label","transport","query","success","failure","promise","courseid","attr","userfields","split","enrolid","perpage","parseInt","isNaN","call","methodname","args","search","searchanywhere","page","then","promises","i","length","ctx","identity","k","hasidentity","join","render","when","apply","arguments","get_string","toomanyuserstoshow","fail"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Potential user selector module.\n *\n * @module enrol_manual/form-potential-user-selector\n * @class form-potential-user-selector\n * @package enrol_manual\n * @copyright 2016 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates', 'core/str'], function($, Ajax, Templates, Str) {\n\n return /** @alias module:enrol_manual/form-potential-user-selector */ {\n\n processResults: function(selector, results) {\n var users = [];\n if ($.isArray(results)) {\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n var courseid = $(selector).attr('courseid');\n var userfields = $(selector).attr('userfields').split(',');\n if (typeof courseid === \"undefined\") {\n courseid = '1';\n }\n var enrolid = $(selector).attr('enrolid');\n if (typeof enrolid === \"undefined\") {\n enrolid = '';\n }\n var perpage = parseInt($(selector).attr('perpage'));\n if (isNaN(perpage)) {\n perpage = 100;\n }\n\n promise = Ajax.call([{\n methodname: 'core_enrol_get_potential_users',\n args: {\n courseid: courseid,\n enrolid: enrolid,\n search: query,\n searchanywhere: true,\n page: 0,\n perpage: perpage + 1\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n if (results.length <= perpage) {\n // Render the label.\n $.each(results, function(index, user) {\n var ctx = user,\n identity = [];\n $.each(userfields, function(i, k) {\n if (typeof user[k] !== 'undefined' && user[k] !== '') {\n ctx.hasidentity = true;\n identity.push(user[k]);\n }\n });\n ctx.identity = identity.join(', ');\n promises.push(Templates.render('enrol_manual/form-user-selector-suggestion', ctx));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results);\n return;\n });\n\n } else {\n return Str.get_string('toomanyuserstoshow', 'core', '>' + perpage).then(function(toomanyuserstoshow) {\n success(toomanyuserstoshow);\n return;\n });\n }\n\n }).fail(failure);\n }\n\n };\n\n});\n"],"file":"form-potential-user-selector.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/form-potential-user-selector.js"],"names":["define","$","Ajax","Templates","Str","processResults","selector","results","users","isArray","each","index","user","push","value","id","label","_label","transport","query","success","failure","promise","courseid","attr","userfields","split","enrolid","perpage","parseInt","isNaN","call","methodname","args","search","searchanywhere","page","then","promises","i","length","ctx","identity","k","result","exec","customfields","forEach","customfield","shortname","hasidentity","join","render","when","apply","arguments","get_string","toomanyuserstoshow","fail"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Potential user selector module.\n *\n * @module enrol_manual/form-potential-user-selector\n * @class form-potential-user-selector\n * @package enrol_manual\n * @copyright 2016 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates', 'core/str'], function($, Ajax, Templates, Str) {\n\n return /** @alias module:enrol_manual/form-potential-user-selector */ {\n\n processResults: function(selector, results) {\n var users = [];\n if ($.isArray(results)) {\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n var courseid = $(selector).attr('courseid');\n var userfields = $(selector).attr('userfields').split(',');\n if (typeof courseid === \"undefined\") {\n courseid = '1';\n }\n var enrolid = $(selector).attr('enrolid');\n if (typeof enrolid === \"undefined\") {\n enrolid = '';\n }\n var perpage = parseInt($(selector).attr('perpage'));\n if (isNaN(perpage)) {\n perpage = 100;\n }\n\n promise = Ajax.call([{\n methodname: 'core_enrol_get_potential_users',\n args: {\n courseid: courseid,\n enrolid: enrolid,\n search: query,\n searchanywhere: true,\n page: 0,\n perpage: perpage + 1\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n if (results.length <= perpage) {\n // Render the label.\n const profileRegex = /^profile_field_(.*)$/;\n $.each(results, function(index, user) {\n var ctx = user,\n identity = [];\n $.each(userfields, function(i, k) {\n const result = profileRegex.exec(k);\n if (result) {\n if (user.customfields) {\n user.customfields.forEach(function(customfield) {\n if (customfield.shortname === result[1]) {\n ctx.hasidentity = true;\n identity.push(customfield.value);\n }\n\n });\n }\n } else {\n if (typeof user[k] !== 'undefined' && user[k] !== '') {\n ctx.hasidentity = true;\n identity.push(user[k]);\n }\n }\n });\n ctx.identity = identity.join(', ');\n promises.push(Templates.render('enrol_manual/form-user-selector-suggestion', ctx));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results);\n return;\n });\n\n } else {\n return Str.get_string('toomanyuserstoshow', 'core', '>' + perpage).then(function(toomanyuserstoshow) {\n success(toomanyuserstoshow);\n return;\n });\n }\n\n }).fail(failure);\n }\n\n };\n\n});\n"],"file":"form-potential-user-selector.min.js"}
\ No newline at end of file
diff --git a/enrol/manual/amd/src/form-potential-user-selector.js b/enrol/manual/amd/src/form-potential-user-selector.js
index c2e53d82fd5..f485cbf38c4 100644
--- a/enrol/manual/amd/src/form-potential-user-selector.js
+++ b/enrol/manual/amd/src/form-potential-user-selector.js
@@ -77,13 +77,27 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/str'], function($, Ajax,
if (results.length <= perpage) {
// Render the label.
+ const profileRegex = /^profile_field_(.*)$/;
$.each(results, function(index, user) {
var ctx = user,
identity = [];
$.each(userfields, function(i, k) {
- if (typeof user[k] !== 'undefined' && user[k] !== '') {
- ctx.hasidentity = true;
- identity.push(user[k]);
+ const result = profileRegex.exec(k);
+ if (result) {
+ if (user.customfields) {
+ user.customfields.forEach(function(customfield) {
+ if (customfield.shortname === result[1]) {
+ ctx.hasidentity = true;
+ identity.push(customfield.value);
+ }
+
+ });
+ }
+ } else {
+ if (typeof user[k] !== 'undefined' && user[k] !== '') {
+ ctx.hasidentity = true;
+ identity.push(user[k]);
+ }
}
});
ctx.identity = identity.join(', ');
diff --git a/enrol/manual/classes/enrol_users_form.php b/enrol/manual/classes/enrol_users_form.php
index 8fde2485872..959cf7224b8 100644
--- a/enrol/manual/classes/enrol_users_form.php
+++ b/enrol/manual/classes/enrol_users_form.php
@@ -93,8 +93,7 @@ class enrol_manual_enrol_users_form extends moodleform {
'courseid' => $course->id,
'enrolid' => $instance->id,
'perpage' => $CFG->maxusersperpage,
- // TODO Does not support custom user profile fields (MDL-70456).
- 'userfields' => implode(',', \core\user_fields::get_identity_fields($context, false))
+ 'userfields' => implode(',', \core\user_fields::get_identity_fields($context, true))
);
$mform->addElement('autocomplete', 'userlist', get_string('selectusers', 'enrol_manual'), array(), $options);
diff --git a/enrol/manual/tests/behat/quickenrolment.feature b/enrol/manual/tests/behat/quickenrolment.feature
index 564f69f02e5..d0b720abc67 100644
--- a/enrol/manual/tests/behat/quickenrolment.feature
+++ b/enrol/manual/tests/behat/quickenrolment.feature
@@ -5,108 +5,111 @@ Feature: Teacher can search and enrol users one by one into the course
I can search for the students and enrol them into the course
Background:
- Given the following "users" exist:
- | username | firstname | lastname | email |
- | teacher001 | Teacher | 001 | teacher001@example.com |
- | student001 | Student | 001 | student001@example.com |
- | student002 | Student | 002 | student002@example.com |
- | student003 | Student | 003 | student003@example.com |
- | student004 | Student | 004 | student004@example.com |
- | student005 | Student | 005 | student005@example.com |
- | student006 | Student | 006 | student006@example.com |
- | student007 | Student | 007 | student007@example.com |
- | student008 | Student | 008 | student008@example.com |
- | student009 | Student | 009 | student009@example.com |
- | student010 | Student | 010 | student010@example.com |
- | student011 | Student | 011 | student011@example.com |
- | student012 | Student | 012 | student012@example.com |
- | student013 | Student | 013 | student013@example.com |
- | student014 | Student | 014 | student014@example.com |
- | student015 | Student | 015 | student015@example.com |
- | student016 | Student | 016 | student016@example.com |
- | student017 | Student | 017 | student017@example.com |
- | student018 | Student | 018 | student018@example.com |
- | student019 | Student | 019 | student019@example.com |
- | student020 | Student | 020 | student020@example.com |
- | student021 | Student | 021 | student021@example.com |
- | student022 | Student | 022 | student022@example.com |
- | student023 | Student | 023 | student023@example.com |
- | student024 | Student | 024 | student024@example.com |
- | student025 | Student | 025 | student025@example.com |
- | student026 | Student | 026 | student026@example.com |
- | student027 | Student | 027 | student027@example.com |
- | student028 | Student | 028 | student028@example.com |
- | student029 | Student | 029 | student029@example.com |
- | student030 | Student | 030 | student030@example.com |
- | student031 | Student | 031 | student031@example.com |
- | student032 | Student | 032 | student032@example.com |
- | student033 | Student | 033 | student033@example.com |
- | student034 | Student | 034 | student034@example.com |
- | student035 | Student | 035 | student035@example.com |
- | student036 | Student | 036 | student036@example.com |
- | student037 | Student | 037 | student037@example.com |
- | student038 | Student | 038 | student038@example.com |
- | student039 | Student | 039 | student039@example.com |
- | student040 | Student | 040 | student040@example.com |
- | student041 | Student | 041 | student041@example.com |
- | student042 | Student | 042 | student042@example.com |
- | student043 | Student | 043 | student043@example.com |
- | student044 | Student | 044 | student044@example.com |
- | student045 | Student | 045 | student045@example.com |
- | student046 | Student | 046 | student046@example.com |
- | student047 | Student | 047 | student047@example.com |
- | student048 | Student | 048 | student048@example.com |
- | student049 | Student | 049 | student049@example.com |
- | student050 | Student | 050 | student050@example.com |
- | student051 | Student | 051 | student051@example.com |
- | student052 | Student | 052 | student052@example.com |
- | student053 | Student | 053 | student053@example.com |
- | student054 | Student | 054 | student054@example.com |
- | student055 | Student | 055 | student055@example.com |
- | student056 | Student | 056 | student056@example.com |
- | student057 | Student | 057 | student057@example.com |
- | student058 | Student | 058 | student058@example.com |
- | student059 | Student | 059 | student059@example.com |
- | student060 | Student | 060 | student060@example.com |
- | student061 | Student | 061 | student061@example.com |
- | student062 | Student | 062 | student062@example.com |
- | student063 | Student | 063 | student063@example.com |
- | student064 | Student | 064 | student064@example.com |
- | student065 | Student | 065 | student065@example.com |
- | student066 | Student | 066 | student066@example.com |
- | student067 | Student | 067 | student067@example.com |
- | student068 | Student | 068 | student068@example.com |
- | student069 | Student | 069 | student069@example.com |
- | student070 | Student | 070 | student070@example.com |
- | student071 | Student | 071 | student071@example.com |
- | student072 | Student | 072 | student072@example.com |
- | student073 | Student | 073 | student073@example.com |
- | student074 | Student | 074 | student074@example.com |
- | student075 | Student | 075 | student075@example.com |
- | student076 | Student | 076 | student076@example.com |
- | student077 | Student | 077 | student077@example.com |
- | student078 | Student | 078 | student078@example.com |
- | student079 | Student | 079 | student079@example.com |
- | student080 | Student | 080 | student080@example.com |
- | student081 | Student | 081 | student081@example.com |
- | student082 | Student | 082 | student082@example.com |
- | student083 | Student | 083 | student083@example.com |
- | student084 | Student | 084 | student084@example.com |
- | student085 | Student | 085 | student085@example.com |
- | student086 | Student | 086 | student086@example.com |
- | student087 | Student | 087 | student087@example.com |
- | student088 | Student | 088 | student088@example.com |
- | student089 | Student | 089 | student089@example.com |
- | student090 | Student | 090 | student090@example.com |
- | student091 | Student | 091 | student091@example.com |
- | student092 | Student | 092 | student092@example.com |
- | student093 | Student | 093 | student093@example.com |
- | student094 | Student | 094 | student094@example.com |
- | student095 | Student | 095 | student095@example.com |
- | student096 | Student | 096 | student096@example.com |
- | student097 | Student | 097 | student097@example.com |
- | student098 | Student | 098 | student098@example.com |
- | student099 | Student | 099 | student099@example.com |
+ Given the following "custom profile fields" exist:
+ | datatype | shortname | name |
+ | text | customid | Custom user id |
+ And the following "users" exist:
+ | username | firstname | lastname | email | profile_field_customid |
+ | teacher001 | Teacher | 001 | teacher001@example.com | |
+ | student001 | Student | 001 | student001@example.com | Q994 |
+ | student002 | Student | 002 | student002@example.com | Q008 |
+ | student003 | Student | 003 | student003@example.com | Z442 |
+ | student004 | Student | 004 | student004@example.com | |
+ | student005 | Student | 005 | student005@example.com | |
+ | student006 | Student | 006 | student006@example.com | |
+ | student007 | Student | 007 | student007@example.com | |
+ | student008 | Student | 008 | student008@example.com | |
+ | student009 | Student | 009 | student009@example.com | |
+ | student010 | Student | 010 | student010@example.com | |
+ | student011 | Student | 011 | student011@example.com | |
+ | student012 | Student | 012 | student012@example.com | |
+ | student013 | Student | 013 | student013@example.com | |
+ | student014 | Student | 014 | student014@example.com | |
+ | student015 | Student | 015 | student015@example.com | |
+ | student016 | Student | 016 | student016@example.com | |
+ | student017 | Student | 017 | student017@example.com | |
+ | student018 | Student | 018 | student018@example.com | |
+ | student019 | Student | 019 | student019@example.com | |
+ | student020 | Student | 020 | student020@example.com | |
+ | student021 | Student | 021 | student021@example.com | |
+ | student022 | Student | 022 | student022@example.com | |
+ | student023 | Student | 023 | student023@example.com | |
+ | student024 | Student | 024 | student024@example.com | |
+ | student025 | Student | 025 | student025@example.com | |
+ | student026 | Student | 026 | student026@example.com | |
+ | student027 | Student | 027 | student027@example.com | |
+ | student028 | Student | 028 | student028@example.com | |
+ | student029 | Student | 029 | student029@example.com | |
+ | student030 | Student | 030 | student030@example.com | |
+ | student031 | Student | 031 | student031@example.com | |
+ | student032 | Student | 032 | student032@example.com | |
+ | student033 | Student | 033 | student033@example.com | |
+ | student034 | Student | 034 | student034@example.com | |
+ | student035 | Student | 035 | student035@example.com | |
+ | student036 | Student | 036 | student036@example.com | |
+ | student037 | Student | 037 | student037@example.com | |
+ | student038 | Student | 038 | student038@example.com | |
+ | student039 | Student | 039 | student039@example.com | |
+ | student040 | Student | 040 | student040@example.com | |
+ | student041 | Student | 041 | student041@example.com | |
+ | student042 | Student | 042 | student042@example.com | |
+ | student043 | Student | 043 | student043@example.com | |
+ | student044 | Student | 044 | student044@example.com | |
+ | student045 | Student | 045 | student045@example.com | |
+ | student046 | Student | 046 | student046@example.com | |
+ | student047 | Student | 047 | student047@example.com | |
+ | student048 | Student | 048 | student048@example.com | |
+ | student049 | Student | 049 | student049@example.com | |
+ | student050 | Student | 050 | student050@example.com | |
+ | student051 | Student | 051 | student051@example.com | |
+ | student052 | Student | 052 | student052@example.com | |
+ | student053 | Student | 053 | student053@example.com | |
+ | student054 | Student | 054 | student054@example.com | |
+ | student055 | Student | 055 | student055@example.com | |
+ | student056 | Student | 056 | student056@example.com | |
+ | student057 | Student | 057 | student057@example.com | |
+ | student058 | Student | 058 | student058@example.com | |
+ | student059 | Student | 059 | student059@example.com | |
+ | student060 | Student | 060 | student060@example.com | |
+ | student061 | Student | 061 | student061@example.com | |
+ | student062 | Student | 062 | student062@example.com | |
+ | student063 | Student | 063 | student063@example.com | |
+ | student064 | Student | 064 | student064@example.com | |
+ | student065 | Student | 065 | student065@example.com | |
+ | student066 | Student | 066 | student066@example.com | |
+ | student067 | Student | 067 | student067@example.com | |
+ | student068 | Student | 068 | student068@example.com | |
+ | student069 | Student | 069 | student069@example.com | |
+ | student070 | Student | 070 | student070@example.com | |
+ | student071 | Student | 071 | student071@example.com | |
+ | student072 | Student | 072 | student072@example.com | |
+ | student073 | Student | 073 | student073@example.com | |
+ | student074 | Student | 074 | student074@example.com | |
+ | student075 | Student | 075 | student075@example.com | |
+ | student076 | Student | 076 | student076@example.com | |
+ | student077 | Student | 077 | student077@example.com | |
+ | student078 | Student | 078 | student078@example.com | |
+ | student079 | Student | 079 | student079@example.com | |
+ | student080 | Student | 080 | student080@example.com | |
+ | student081 | Student | 081 | student081@example.com | |
+ | student082 | Student | 082 | student082@example.com | |
+ | student083 | Student | 083 | student083@example.com | |
+ | student084 | Student | 084 | student084@example.com | |
+ | student085 | Student | 085 | student085@example.com | |
+ | student086 | Student | 086 | student086@example.com | |
+ | student087 | Student | 087 | student087@example.com | |
+ | student088 | Student | 088 | student088@example.com | |
+ | student089 | Student | 089 | student089@example.com | |
+ | student090 | Student | 090 | student090@example.com | |
+ | student091 | Student | 091 | student091@example.com | |
+ | student092 | Student | 092 | student092@example.com | |
+ | student093 | Student | 093 | student093@example.com | |
+ | student094 | Student | 094 | student094@example.com | |
+ | student095 | Student | 095 | student095@example.com | |
+ | student096 | Student | 096 | student096@example.com | |
+ | student097 | Student | 097 | student097@example.com | |
+ | student098 | Student | 098 | student098@example.com | |
+ | student099 | Student | 099 | student099@example.com | |
And the following "courses" exist:
| fullname | shortname | format | startdate |
| Course 001 | C001 | weeks | ##1 month ago## |
@@ -189,6 +192,26 @@ Feature: Teacher can search and enrol users one by one into the course
And I type "student100@example.com"
And I should see "student100@example.com, 1234567892, 1234567893, ABC1, ABC2"
+ @javascript
+ Scenario: Custom user profile fields work for search and display, if user has permission
+ Given the following config values are set as admin:
+ | showuseridentity | email,profile_field_customid |
+ And I navigate to course participants
+ And I press "Enrol users"
+ When I set the field "Select users" to "Q994"
+ Then I should see "student001@example.com, Q994"
+ And I click on "Cancel" "button" in the "Enrol users" "dialogue"
+ And the following "permission overrides" exist:
+ | capability | permission | role | contextlevel | reference |
+ | moodle/site:viewuseridentity | Prevent | editingteacher | Course | C001 |
+ And I press "Enrol users"
+ # Do this by keyboard because the 'I set the field' step doesn't let you set it to a missing value.
+ And I press tab
+ And I press tab
+ And I press tab
+ And I type "Q994"
+ And I should see "No suggestions"
+
# The following tests are commented out as a result of MDL-66339.
# @javascript
# Scenario: Enrol user from participants page
diff --git a/enrol/tests/course_enrolment_manager_test.php b/enrol/tests/course_enrolment_manager_test.php
index 11c4146d410..0eaa3fe24f2 100644
--- a/enrol/tests/course_enrolment_manager_test.php
+++ b/enrol/tests/course_enrolment_manager_test.php
@@ -254,6 +254,127 @@ class core_course_enrolment_manager_testcase extends advanced_testcase {
$this->assertArrayHasKey($this->users['user22']->id, $users);
}
+ /**
+ * Sets up a custom profile field and the showuseridentity option, and creates a test user
+ * with suitable values set.
+ *
+ * @return stdClass Test user
+ */
+ protected function setup_for_user_identity_tests(): stdClass {
+ // Configure extra fields to include one normal user field and one profile field, and
+ // set the values for a new test user.
+ $generator = $this->getDataGenerator();
+ $generator->create_custom_profile_field(['datatype' => 'text',
+ 'shortname' => 'researchtopic', 'name' => 'Research topic']);
+ set_config('showuseridentity', 'email,department,profile_field_researchtopic');
+ return $generator->create_user(
+ ['username' => 'newuser', 'department' => 'Amphibian studies', 'email' => 'x@x.org',
+ 'profile_field_researchtopic' => 'Frogs', 'imagealt' => 'Smart suit']);
+ }
+
+ /**
+ * Checks that the get_users function returns the correct user fields.
+ */
+ public function test_get_users_fields() {
+ global $PAGE;
+
+ $this->resetAfterTest();
+ $newuser = $this->setup_for_user_identity_tests();
+
+ // Enrol the user in test course.
+ $this->getDataGenerator()->enrol_user($newuser->id, $this->course->id, 'student');
+
+ // Get all users and fish out the one we're interested in.
+ $manager = new course_enrolment_manager($PAGE, $this->course);
+ $users = $manager->get_users('id');
+ $user = $users[$newuser->id];
+
+ // Should include core required fields...
+ $this->assertEquals($newuser->id, $user->id);
+
+ // ...And the ones specified in showuseridentity (one of which is also needed for user pics).
+ $this->assertEquals('Amphibian studies', $user->department);
+ $this->assertEquals('Frogs', $user->profile_field_researchtopic);
+ $this->assertEquals('x@x.org', $user->email);
+
+ // And the ones necessary for user pics.
+ $this->assertEquals('Smart suit', $user->imagealt);
+
+ // But not some random other field like city.
+ $this->assertObjectNotHasAttribute('city', $user);
+ }
+
+ /**
+ * Checks that the get_other_users function returns the correct user fields.
+ */
+ public function test_get_other_users_fields() {
+ global $PAGE, $DB;
+
+ $this->resetAfterTest();
+
+ // Configure extra fields to include one normal user field and one profile field, and
+ // set the values for a new test user.
+ $newuser = $this->setup_for_user_identity_tests();
+ $context = \context_course::instance($this->course->id);
+ role_assign($DB->get_field('role', 'id', ['shortname' => 'manager']), $newuser->id, $context->id);
+
+ // Get the 'other' (role but not enrolled) users and fish out the one we're interested in.
+ $manager = new course_enrolment_manager($PAGE, $this->course);
+ $users = array_values($manager->get_other_users('id'));
+ $user = $users[0];
+
+ // Should include core required fields...
+ $this->assertEquals($newuser->id, $user->id);
+
+ // ...And the ones specified in showuseridentity (one of which is also needed for user pics).
+ $this->assertEquals('Amphibian studies', $user->department);
+ $this->assertEquals('Frogs', $user->profile_field_researchtopic);
+ $this->assertEquals('x@x.org', $user->email);
+
+ // And the ones necessary for user pics.
+ $this->assertEquals('Smart suit', $user->imagealt);
+
+ // But not some random other field like city.
+ $this->assertObjectNotHasAttribute('city', $user);
+ }
+
+ /**
+ * Checks that the get_potential_users function returns the correct user fields.
+ */
+ public function test_get_potential_users_fields() {
+ global $PAGE;
+
+ $this->resetAfterTest();
+
+ // Configure extra fields to include one normal user field and one profile field, and
+ // set the values for a new test user.
+ $newuser = $this->setup_for_user_identity_tests();
+
+ // Get the 'potential' (not enrolled) users and fish out the one we're interested in.
+ $manager = new course_enrolment_manager($PAGE, $this->course);
+ foreach (enrol_get_instances($this->course->id, true) as $enrolinstance) {
+ if ($enrolinstance->enrol === 'manual') {
+ $enrolid = $enrolinstance->id;
+ }
+ }
+ $users = array_values($manager->get_potential_users($enrolid));
+ $user = $users[0][$newuser->id];
+
+ // Should include core required fields...
+ $this->assertEquals($newuser->id, $user->id);
+
+ // ...And the ones specified in showuseridentity (one of which is also needed for user pics).
+ $this->assertEquals('Amphibian studies', $user->department);
+ $this->assertEquals('Frogs', $user->profile_field_researchtopic);
+ $this->assertEquals('x@x.org', $user->email);
+
+ // And the ones necessary for user pics.
+ $this->assertEquals('Smart suit', $user->imagealt);
+
+ // But not some random other field like city.
+ $this->assertObjectNotHasAttribute('city', $user);
+ }
+
/**
* Test get_potential_users without returnexactcount param.
*
@@ -290,6 +411,58 @@ class core_course_enrolment_manager_testcase extends advanced_testcase {
}
}
+ /**
+ * Tests get_potential_users when the search term includes a custom field.
+ */
+ public function test_get_potential_users_search_fields() {
+ global $PAGE;
+
+ $this->resetAfterTest();
+
+ // Configure extra fields to include one normal user field and one profile field, and
+ // set the values for a new test user.
+ $newuser = $this->setup_for_user_identity_tests();
+
+ // Set up the enrolment manager.
+ $manager = new course_enrolment_manager($PAGE, $this->course);
+ foreach (enrol_get_instances($this->course->id, true) as $enrolinstance) {
+ if ($enrolinstance->enrol === 'manual') {
+ $enrolid = $enrolinstance->id;
+ }
+ }
+
+ // Search for text included in a 'standard' (user table) identity field.
+ $users = array_values($manager->get_potential_users($enrolid, 'Amphibian studies'));
+ $this->assertEquals([$newuser->id], array_keys($users[0]));
+
+ // And for text included in a custom field.
+ $users = array_values($manager->get_potential_users($enrolid, 'Frogs'));
+ $this->assertEquals([$newuser->id], array_keys($users[0]));
+
+ // With partial matches.
+ $users = array_values($manager->get_potential_users($enrolid, 'Amphibian'));
+ $this->assertEquals([$newuser->id], array_keys($users[0]));
+ $users = array_values($manager->get_potential_users($enrolid, 'Fro'));
+ $this->assertEquals([$newuser->id], array_keys($users[0]));
+
+ // With partial in-the-middle matches.
+ $users = array_values($manager->get_potential_users($enrolid, 'phibian'));
+ $this->assertEquals([], array_keys($users[0]));
+ $users = array_values($manager->get_potential_users($enrolid, 'rog'));
+ $this->assertEquals([], array_keys($users[0]));
+ $users = array_values($manager->get_potential_users($enrolid, 'phibian', true));
+ $this->assertEquals([$newuser->id], array_keys($users[0]));
+ $users = array_values($manager->get_potential_users($enrolid, 'rog', true));
+ $this->assertEquals([$newuser->id], array_keys($users[0]));
+
+ // If the current user doesn't have access to identity fields then these searches won't work.
+ $this->setUser($this->getDataGenerator()->create_user());
+ $users = array_values($manager->get_potential_users($enrolid, 'Amphibian studies'));
+ $this->assertEquals([], array_keys($users[0]));
+ $users = array_values($manager->get_potential_users($enrolid, 'Frogs'));
+ $this->assertEquals([], array_keys($users[0]));
+ }
+
/**
* Test search_other_users with returnexactcount param.
*
diff --git a/enrol/tests/externallib_test.php b/enrol/tests/externallib_test.php
index c126c90b312..3db6a354395 100644
--- a/enrol/tests/externallib_test.php
+++ b/enrol/tests/externallib_test.php
@@ -1476,4 +1476,79 @@ class core_enrol_externallib_testcase extends externallib_advanced_testcase {
$result = core_enrol_external::search_users($course1->id, 'yada yada', true, 0, 30);
$this->assertCount(0, $result);
}
+
+ /**
+ * Tests the get_potential_users external function (not too much detail because the back-end
+ * is covered in another test).
+ */
+ public function test_get_potential_users(): void {
+ $this->resetAfterTest();
+
+ // Create a couple of custom profile fields, one of which is in user identity.
+ $generator = $this->getDataGenerator();
+ $generator->create_custom_profile_field(['datatype' => 'text',
+ 'shortname' => 'researchtopic', 'name' => 'Research topic']);
+ $generator->create_custom_profile_field(['datatype' => 'text',
+ 'shortname' => 'specialid', 'name' => 'Special id']);
+ set_config('showuseridentity', 'department,profile_field_specialid');
+
+ // Create a course.
+ $course = $generator->create_course();
+
+ // Get enrol id for manual enrol plugin.
+ foreach (enrol_get_instances($course->id, true) as $instance) {
+ if ($instance->enrol === 'manual') {
+ $enrolid = $instance->id;
+ }
+ }
+
+ // Create a couple of test users.
+ $user1 = $generator->create_user(['firstname' => 'Eigh', 'lastname' => 'User',
+ 'department' => 'Amphibians', 'profile_field_specialid' => 'Q123',
+ 'profile_field_researchtopic' => 'Frogs']);
+ $user2 = $generator->create_user(['firstname' => 'Anne', 'lastname' => 'Other',
+ 'department' => 'Amphibians', 'profile_field_specialid' => 'Q456',
+ 'profile_field_researchtopic' => 'Toads']);
+
+ // Do this as admin user.
+ $this->setAdminUser();
+
+ // Get potential users and extract the 2 we care about.
+ $result = core_enrol_external::get_potential_users($course->id, $enrolid, '', false, 0, 10);
+ $result1 = $this->extract_user_from_result($result, $user1->id);
+ $result2 = $this->extract_user_from_result($result, $user2->id);
+
+ // Check the fields are the expected ones.
+ $this->assertEquals(['id', 'fullname', 'customfields',
+ 'profileimageurl', 'profileimageurlsmall', 'department'], array_keys($result1));
+ $this->assertEquals('Eigh User', $result1['fullname']);
+ $this->assertEquals('Amphibians', $result1['department']);
+
+ // Check the custom fields ONLY include the user identity one.
+ $fieldvalues = [];
+ foreach ($result1['customfields'] as $customfield) {
+ $fieldvalues[$customfield['shortname']] = $customfield['value'];
+ }
+ $this->assertEquals(['specialid'], array_keys($fieldvalues));
+ $this->AssertEquals('Q123', $fieldvalues['specialid']);
+
+ // Just check user 2 is the right user.
+ $this->assertEquals('Anne Other', $result2['fullname']);
+ }
+
+ /**
+ * Utility function to get one user out of the get_potential_users result.
+ *
+ * @param array $result Result array
+ * @param int $userid User id
+ * @return array Data for that user
+ */
+ protected function extract_user_from_result(array $result, int $userid): array {
+ foreach ($result as $item) {
+ if ($item['id'] == $userid) {
+ return $item;
+ }
+ }
+ $this->fail('User not in result: ' . $userid);
+ }
}
diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php
index 4409d500963..38a6659edaf 100644
--- a/grade/report/grader/lib.php
+++ b/grade/report/grader/lib.php
@@ -1963,7 +1963,7 @@ class grade_report_grader extends grade_report {
foreach ($extrafields as $field) {
$fieldlink = html_writer::link(new moodle_url($this->baseurl,
- array('sortitemid'=>$field)), \core\user_fields::get_display_name($field));
+ array('sortitemid' => $field)), \core\user_fields::get_display_name($field));
$arrows[$field] = $fieldlink;
if ($field == $this->sortitemid) {
diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index f6fea8ee107..107016a06a5 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -3645,9 +3645,9 @@ function fullname($user, $override=false) {
* @return object User name fields.
*/
function username_load_fields_from_object($addtoobject, $secondobject, $prefix = null, $additionalfields = null) {
- $fields = \core\user_fields::get_name_fields();
- foreach ($fields as &$field) {
- $field = $prefix . $field;
+ $fields = [];
+ foreach (\core\user_fields::get_name_fields() as $field) {
+ $fields[$field] = $prefix . $field;
}
if ($additionalfields) {
// Additional fields can specify their own 'alias' such as 'id' => 'userid'. This checks to see if
diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php
index a3d3b1f3c86..2a76c0f34e9 100644
--- a/lib/outputcomponents.php
+++ b/lib/outputcomponents.php
@@ -230,7 +230,7 @@ class user_picture implements renderable {
}
if ($needrec) {
- $this->user = $DB->get_record('user', array('id'=>$user->id),
+ $this->user = $DB->get_record('user', array('id' => $user->id),
implode(',', \core\user_fields::get_picture_fields()), MUST_EXIST);
} else {
$this->user = clone($user);
diff --git a/mod/chat/lib.php b/mod/chat/lib.php
index 9a2b1bf0793..ee019d6088e 100644
--- a/mod/chat/lib.php
+++ b/mod/chat/lib.php
@@ -907,7 +907,7 @@ function chat_format_message($message, $courseid, $currentuser, $chatlastrow=nul
if (isset($users[$message->userid])) {
$user = $users[$message->userid];
- } else if ($user = $DB->get_record('user', array('id' => $message->userid), implode(',', \core\user_fields::get_picture_fields()))) {
+ } else if ($user = $DB->get_record('user', ['id' => $message->userid], implode(',', \core\user_fields::get_picture_fields()))) {
$users[$message->userid] = $user;
} else {
return null;
@@ -938,7 +938,8 @@ function chat_format_message_theme ($message, $chatuser, $currentuser, $grouping
if (isset($users[$message->userid])) {
$sender = $users[$message->userid];
- } else if ($sender = $DB->get_record('user', array('id' => $message->userid), implode(',', \core\user_fields::get_picture_fields()))) {
+ } else if ($sender = $DB->get_record('user', array('id' => $message->userid),
+ implode(',', \core\user_fields::get_picture_fields()))) {
$users[$message->userid] = $sender;
} else {
return null;
diff --git a/report/completion/index.php b/report/completion/index.php
index a94b83ee2fd..dd862a8fdee 100644
--- a/report/completion/index.php
+++ b/report/completion/index.php
@@ -512,7 +512,7 @@ if (!$csv) {
$row[] = get_string('id', 'report_completion');
$row[] = get_string('name', 'report_completion');
foreach ($extrafields as $field) {
- $row[] = \core\user_fields::get_display_name($field);
+ $row[] = \core\user_fields::get_display_name($field);
}
// Add activity headers
diff --git a/report/log/locallib.php b/report/log/locallib.php
index 4440e1dd76d..4b6c70bf5a8 100644
--- a/report/log/locallib.php
+++ b/report/log/locallib.php
@@ -296,7 +296,7 @@ function report_log_print_mnet_selector_form($hostid, $course, $selecteduser=0,
} else {
// this may be a lot of users :-(
$userfieldsapi = \core\user_fields::for_name();
- $courseusers = $DB->get_records('user', array('deleted'=>0), 'lastaccess DESC', 'id, ' .
+ $courseusers = $DB->get_records('user', array('deleted' => 0), 'lastaccess DESC', 'id, ' .
$userfieldsapi->get_sql('', false, '', '', false)->selects,
$limitfrom, $limitnum);
}
diff --git a/user/lib.php b/user/lib.php
index 9d01bc00321..65ffbcebd95 100644
--- a/user/lib.php
+++ b/user/lib.php
@@ -302,7 +302,8 @@ function user_get_user_details($user, $course = null, array $userfields = array(
$currentuser = ($user->id == $USER->id);
$isadmin = is_siteadmin($USER);
- // TODO Does not support custom user profile fields (MDL-70456).
+ // This does not need to include custom profile fields as it is only used to check specific
+ // fields below.
$showuseridentityfields = \core\user_fields::get_identity_fields($context, false);
if (!empty($course)) {
diff --git a/userpix/index.php b/userpix/index.php
index 99a7758b62f..f3d035cb01b 100644
--- a/userpix/index.php
+++ b/userpix/index.php
@@ -23,7 +23,8 @@ $PAGE->set_title($title);
$PAGE->set_heading($title);
echo $OUTPUT->header();
-$rs = $DB->get_recordset_select("user", "deleted = 0 AND picture > 0", array(), "lastaccess DESC", implode(',', \core\user_fields::get_picture_fields()));
+$rs = $DB->get_recordset_select("user", "deleted = 0 AND picture > 0", array(), "lastaccess DESC",
+ implode(',', \core\user_fields::get_picture_fields()));
foreach ($rs as $user) {
$fullname = s(fullname($user));
echo "wwwroot/user/view.php?id=$user->id&course=1\" ".