diff --git a/admin/settings/security.php b/admin/settings/security.php index e720160f20a..3d63ce6a303 100644 --- a/admin/settings/security.php +++ b/admin/settings/security.php @@ -46,11 +46,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page 1800 => new lang_string('numminutes', '', 30), 2700 => new lang_string('numminutes', '', 45), 3600 => new lang_string('numminutes', '', 60)))); - $temp->add(new admin_setting_configselect('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'), new lang_string('configfullnamedisplay', 'admin'), - 'language', array('language' => new lang_string('language'), - 'firstname lastname' => new lang_string('firstname').' + '.new lang_string('lastname'), - 'lastname firstname' => new lang_string('lastname').' + '.new lang_string('firstname'), - 'firstname' => new lang_string('firstname')))); + $temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0)); $temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'admin'), new lang_string('sitepolicy_help', 'admin'), '', PARAM_RAW)); $temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'admin'), new lang_string('sitepolicyguest_help', 'admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW)); diff --git a/admin/settings/users.php b/admin/settings/users.php index 0365ab529f0..5a50bce33ce 100644 --- a/admin/settings/users.php +++ b/admin/settings/users.php @@ -150,6 +150,7 @@ if ($hassiteconfig 'department' => new lang_string('department'), 'institution' => new lang_string('institution'), ))); + $temp->add(new admin_setting_configtext('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'), new lang_string('configfullnamedisplay', 'admin'), 'language', PARAM_TEXT, 50)); $temp->add(new admin_setting_configtext('maxusersperpage', new lang_string('maxusersperpage','admin'), new lang_string('configmaxusersperpage','admin'), 100, PARAM_INT)); $temp->add(new admin_setting_configcheckbox('enablegravatar', new lang_string('enablegravatar', 'admin'), new lang_string('enablegravatar_help', 'admin'), 0)); $temp->add(new admin_setting_configtext('gravatardefaulturl', new lang_string('gravatardefaulturl', 'admin'), new lang_string('gravatardefaulturl_help', 'admin'), 'mm')); diff --git a/admin/user/user_bulk_cohortadd.php b/admin/user/user_bulk_cohortadd.php index be72d51c26c..deb6143e258 100644 --- a/admin/user/user_bulk_cohortadd.php +++ b/admin/user/user_bulk_cohortadd.php @@ -68,8 +68,10 @@ if (count($cohorts) < 2) { } $countries = get_string_manager()->get_list_of_countries(true); +$namefields = get_all_user_name_fields(true); foreach ($users as $key => $id) { - $user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0), 'id, firstname, lastname, username, email, country, lastaccess, city'); + $user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0), 'id, ' . $namefields . ', username, + email, country, lastaccess, city'); $user->fullname = fullname($user, true); $user->country = @$countries[$user->country]; unset($user->firstname); diff --git a/admin/user/user_bulk_display.php b/admin/user/user_bulk_display.php index 1e8514a21fe..44259dfd079 100644 --- a/admin/user/user_bulk_display.php +++ b/admin/user/user_bulk_display.php @@ -24,8 +24,9 @@ echo $OUTPUT->header(); $countries = get_string_manager()->get_list_of_countries(true); +$namefields = get_all_user_name_fields(true); foreach ($users as $key => $id) { - $user = $DB->get_record('user', array('id'=>$id), 'id, firstname, lastname, username, email, country, lastaccess, city'); + $user = $DB->get_record('user', array('id'=>$id), 'id, ' . $namefields . ', username, email, country, lastaccess, city'); $user->fullname = fullname($user, true); $user->country = @$countries[$user->country]; unset($user->firstname); diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index a9267563a5d..952cc26ca28 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1194,12 +1194,12 @@ class backup_users_structure_step extends backup_structure_step { // Then, the fields potentially needing anonymization $anonfields = array( - 'username', 'idnumber', 'firstname', 'lastname', - 'email', 'icq', 'skype', + 'username', 'idnumber', 'email', 'icq', 'skype', 'yahoo', 'aim', 'msn', 'phone1', 'phone2', 'institution', 'department', 'address', 'city', 'country', 'lastip', 'picture', 'url', 'description', 'descriptionformat', 'imagealt', 'auth'); + $anonfields = array_merge($anonfields, get_all_user_name_fields()); // Add anonymized fields to $userfields with custom final element foreach ($anonfields as $field) { diff --git a/group/index.php b/group/index.php index 9a0df5fbebd..ffd8f742f12 100644 --- a/group/index.php +++ b/group/index.php @@ -78,7 +78,7 @@ switch ($action) { case 'ajax_getmembersingroup': $roles = array(); - if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, u.firstname, u.lastname')) { + if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, ' . get_all_user_name_fields(true, 'u'))) { foreach($groupmemberroles as $roleid=>$roledata) { $shortroledata = new stdClass(); $shortroledata->name = $roledata->name; @@ -246,7 +246,7 @@ $member_names = array(); $atleastonemember = false; if ($singlegroup) { - if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, u.firstname, u.lastname')) { + if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, ' . get_all_user_name_fields(true, 'u'))) { foreach($groupmemberroles as $roleid=>$roledata) { echo ''; foreach($roledata->users as $member) { diff --git a/group/overview.php b/group/overview.php index 7e6fa2cede5..134261e027f 100644 --- a/group/overview.php +++ b/group/overview.php @@ -90,7 +90,8 @@ if ($groupingid) { list($sort, $sortparams) = users_order_by_sql('u'); -$sql = "SELECT g.id AS groupid, gg.groupingid, u.id AS userid, u.firstname, u.lastname, u.idnumber, u.username +$allnames = get_all_user_name_fields(true, 'u'); +$sql = "SELECT g.id AS groupid, gg.groupingid, u.id AS userid, $allnames, u.idnumber, u.username FROM {groups} g LEFT JOIN {groupings_groups} gg ON g.id = gg.groupid LEFT JOIN {groups_members} gm ON g.id = gm.groupid @@ -106,6 +107,9 @@ foreach ($rs as $row) { $user->lastname = $row->lastname; $user->username = $row->username; $user->idnumber = $row->idnumber; + foreach (get_all_user_name_fields() as $addname) { + $user->$addname = $row->$addname; + } if (!$row->groupingid) { $row->groupingid = -1; } diff --git a/lang/en/admin.php b/lang/en/admin.php index b6e872a2fbb..d6a3c2a6758 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -227,7 +227,7 @@ $string['configfrontpage'] = 'The items selected above will be displayed on the $string['configfrontpagecourselimit'] = 'Maximum number of courses'; $string['configfrontpagecourselimithelp'] = 'Maximum number of courses to be displayed on the site\'s front page in course listings.'; $string['configfrontpageloggedin'] = 'The items selected above will be displayed on the site\'s front page when a user is logged in.'; -$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is "First name + Surname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions).'; +$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is "firstname lastname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions). Placeholders that can be used are: firstname, lastname, firstnamephonetic, lastnamephonetic, middlename, and alternatename.'; $string['configgeoipfile'] = 'Location of GeoIP City binary data file. This file is not part of Moodle distribution and must be obtained separately from MaxMind. You can either buy a commercial version or use the free version.
Simply download http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz and extract it into "{$a}" directory on your server.'; $string['configgetremoteaddrconf'] = 'If your server is behind a reverse proxy, you can use this setting to specify which HTTP headers can be trusted to contain the remote IP address. The headers are read in order, using the first one that is available.'; $string['configgradebookroles'] = 'This setting allows you to control who appears on the gradebook. Users need to have at least one of these roles in a course to be shown in the gradebook for that course.'; @@ -548,6 +548,7 @@ $string['frontpagerestore'] = 'Front page restore'; $string['frontpageroles'] = 'Front page roles'; $string['frontpagesettings'] = 'Front page settings'; $string['fullnamedisplay'] = 'Full name format'; +$string['fullnamedisplayprivate'] = 'Full name format - private'; $string['gdrecommended'] = 'GD extension is used for conversion of images, some features such as user profile images will not be available if missing.'; $string['gdrequired'] = 'The GD extension is now required by Moodle for image conversion.'; $string['generalsettings'] = 'General settings'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 3ec27d61fe9..e92ab1f5eb9 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -60,6 +60,7 @@ $string['addfilehere'] = 'Add file(s) here'; $string['addinganew'] = 'Adding a new {$a}'; $string['addinganewto'] = 'Adding a new {$a->what} to {$a->to}'; $string['addingdatatoexisting'] = 'Adding data to existing'; +$string['additionalnames'] = 'Additional names'; $string['addlinkhere'] = 'Add link here'; $string['addnewcategory'] = 'Add new category'; $string['addnewcourse'] = 'Add a new course'; @@ -135,6 +136,7 @@ $string['allparticipants'] = 'All participants'; $string['allteachers'] = 'All teachers'; $string['alphanumerical'] = 'Can only contain alphanumeric characters, hyphen (-) or period (.)'; $string['alreadyconfirmed'] = 'Registration has already been confirmed'; +$string['alternatename'] = 'Alternate name'; $string['always'] = 'Always'; $string['and'] = '{$a->one} and {$a->two}'; $string['answer'] = 'Answer'; @@ -680,6 +682,7 @@ $string['filter'] = 'Filter'; $string['findmorecourses'] = 'Find more courses...'; $string['firstaccess'] = 'First access'; $string['firstname'] = 'First name'; +$string['firstnamephonetic'] = 'First name - phonetic'; $string['firsttime'] = 'Is this your first time here?'; $string['folder'] = 'Folder'; $string['folderclosed'] = 'Closed folder'; @@ -910,6 +913,7 @@ $string['lastedited'] = 'Last edited'; $string['lastlogin'] = 'Last login'; $string['lastmodified'] = 'Last modified'; $string['lastname'] = 'Surname'; +$string['lastnamephonetic'] = 'Surname - phonetic'; $string['lastyear'] = 'Last year'; $string['latestlanguagepack'] = 'Check for latest language pack on moodle.org'; $string['layouttable'] = 'Layout table'; @@ -1019,6 +1023,7 @@ $string['messageprovider:instantmessage'] = 'Personal messages between users'; $string['messageprovider:instantmessage_help'] = 'This section configures what happens to messages that are sent to you directly from other users on this site.'; $string['messageselect'] = 'Select this user as a message recipient'; $string['messageselectadd'] = 'Send a message'; +$string['middlename'] = 'Middle name'; $string['migratinggrades'] = 'Migrating grades'; $string['min'] = 'min'; $string['mins'] = 'mins'; diff --git a/lib/accesslib.php b/lib/accesslib.php index e16b1da4bac..909fd262ce6 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -3964,7 +3964,8 @@ function get_role_users($roleid, context $context, $parent = false, $fields = '' global $DB; if (empty($fields)) { - $fields = 'u.id, u.confirmed, u.username, u.firstname, u.lastname, '. + $allnames = get_all_user_name_fields(true, 'u'); + $fields = 'u.id, u.confirmed, u.username, '. $allnames . ', ' . 'u.maildisplay, u.mailformat, u.maildigest, u.email, u.emailstop, u.city, '. 'u.country, u.picture, u.idnumber, u.department, u.institution, '. 'u.lang, u.timezone, u.lastaccess, u.mnethostid, r.name AS rolename, r.sortorder, '. diff --git a/lib/badgeslib.php b/lib/badgeslib.php index daf2d44f0ce..cf517646ced 100644 --- a/lib/badgeslib.php +++ b/lib/badgeslib.php @@ -620,8 +620,10 @@ function badges_notify_badge_award(badge $badge, $userid, $issued, $filepathhash $userfrom = new stdClass(); $userfrom->id = $admin->id; $userfrom->email = !empty($CFG->badges_defaultissuercontact) ? $CFG->badges_defaultissuercontact : $admin->email; + foreach (get_all_user_name_fields() as $addname) { + $userfrom->$addname = !empty($CFG->badges_defaultissuername) ? '' : $admin->$addname; + } $userfrom->firstname = !empty($CFG->badges_defaultissuername) ? $CFG->badges_defaultissuername : $admin->firstname; - $userfrom->lastname = !empty($CFG->badges_defaultissuername) ? '' : $admin->lastname; $userfrom->maildisplay = true; $issuedlink = html_writer::link(new moodle_url('/badges/badge.php', array('hash' => $issued)), $badge->name); diff --git a/lib/coursecatlib.php b/lib/coursecatlib.php index ba549e10023..0204812d5e1 100644 --- a/lib/coursecatlib.php +++ b/lib/coursecatlib.php @@ -712,9 +712,10 @@ class coursecat implements renderable, cacheable_object, IteratorAggregate { list($sql2, $params2) = $DB->get_in_or_equal($managerroles, SQL_PARAMS_NAMED, 'rid'); list($sort, $sortparams) = users_order_by_sql('u'); $notdeleted = array('notdeleted'=>0); + $allnames = get_all_user_name_fields(true, 'u'); $sql = "SELECT ra.contextid, ra.id AS raid, r.id AS roleid, r.name AS rolename, r.shortname AS roleshortname, - rn.name AS rolecoursealias, u.id, u.username, u.firstname, u.lastname + rn.name AS rolecoursealias, u.id, u.username, $allnames FROM {role_assignments} ra JOIN {user} u ON ra.userid = u.id JOIN {role} r ON ra.roleid = r.id @@ -2109,8 +2110,9 @@ class course_in_list implements IteratorAggregate { $user = new stdClass(); $user->id = $ruser->id; $user->username = $ruser->username; - $user->firstname = $ruser->firstname; - $user->lastname = $ruser->lastname; + foreach (get_all_user_name_fields() as $addname) { + $user->$addname = $ruser->$addname; + } $role = new stdClass(); $role->id = $ruser->roleid; $role->name = $ruser->rolename; diff --git a/lib/datalib.php b/lib/datalib.php index 49d8cb53489..d8404c99179 100644 --- a/lib/datalib.php +++ b/lib/datalib.php @@ -507,10 +507,11 @@ function get_users_listing($sort='lastaccess', $dir='ASC', $page=0, $recordsperp array('id', 'username', 'email', 'firstname', 'lastname', 'city', 'country', 'lastaccess', 'confirmed', 'mnethostid')); } + $namefields = get_all_user_name_fields(true); + $extrafields = "$extrafields, $namefields"; // warning: will return UNCONFIRMED USERS - return $DB->get_records_sql("SELECT id, username, email, firstname, lastname, city, country, - lastaccess, confirmed, mnethostid, suspended $extrafields + return $DB->get_records_sql("SELECT id, username, email, city, country, lastaccess, confirmed, mnethostid, suspended $extrafields FROM {user} WHERE $select $sort", $params, $page, $recordsperpage); @@ -1781,8 +1782,8 @@ function get_logs($select, array $params=null, $order='l.time DESC', $limitfrom= $select"; $totalcount = $DB->count_records_sql($sql, $params); - - $sql = "SELECT l.*, u.firstname, u.lastname, u.picture + $allnames = get_all_user_name_fields(true, 'u'); + $sql = "SELECT l.*, $allnames, u.picture FROM {log} l LEFT JOIN {user} u ON l.userid = u.id $select diff --git a/lib/db/install.xml b/lib/db/install.xml index 67660b3b237..dba20252823 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -793,6 +793,10 @@ + + + + @@ -809,6 +813,10 @@ + + + + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 9967c128574..b593aef76f5 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -2209,5 +2209,55 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2013070800.00); } + if ($oldversion < 2013070800.01) { + + // Define field lastnamephonetic to be added to user. + $table = new xmldb_table('user'); + $field = new xmldb_field('lastnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'imagealt'); + $index = new xmldb_index('lastnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('lastnamephonetic')); + + // Conditionally launch add field lastnamephonetic. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + $dbman->add_index($table, $index); + } + + // Define field firstnamephonetic to be added to user. + $table = new xmldb_table('user'); + $field = new xmldb_field('firstnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'lastnamephonetic'); + $index = new xmldb_index('firstnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('firstnamephonetic')); + + // Conditionally launch add field firstnamephonetic. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + $dbman->add_index($table, $index); + } + + // Define field alternatename to be added to user. + $table = new xmldb_table('user'); + $field = new xmldb_field('middlename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'firstnamephonetic'); + $index = new xmldb_index('middlename', XMLDB_INDEX_NOTUNIQUE, array('middlename')); + + // Conditionally launch add field firstnamephonetic. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + $dbman->add_index($table, $index); + } + + // Define field alternatename to be added to user. + $table = new xmldb_table('user'); + $field = new xmldb_field('alternatename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'middlename'); + $index = new xmldb_index('alternatename', XMLDB_INDEX_NOTUNIQUE, array('alternatename')); + + // Conditionally launch add field alternatename. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + $dbman->add_index($table, $index); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2013070800.01); + } + return true; } diff --git a/lib/moodlelib.php b/lib/moodlelib.php index a23299757a8..0767ee63f23 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -3558,7 +3558,7 @@ function ismoving($courseid) { /** * Returns a persons full name * - * Given an object containing firstname and lastname + * Given an object containing all of the users name * values, this function returns a string with the * full name of the person. * The result may depend on system settings @@ -3567,7 +3567,7 @@ function ismoving($courseid) { * * @global object * @global object - * @param object $user A {@link $USER} object to get full name of + * @param object $user A {@link $USER} object to get full name of. * @param bool $override If true then the name will be first name followed by last name rather than adhering to fullnamedisplay setting. * @return string */ @@ -3591,21 +3591,114 @@ function fullname($user, $override=false) { $CFG->fullnamedisplay = $SESSION->fullnamedisplay; } - if (!isset($CFG->fullnamedisplay) or $CFG->fullnamedisplay === 'firstname lastname') { - return $user->firstname .' '. $user->lastname; + $template = null; + // If the fullnamedisplay setting is available, set the template to that. + if (isset($CFG->fullnamedisplay)) { + $template = $CFG->fullnamedisplay; + } + // If the template is empty, or set to language, or $override is set, return the language string. + if (empty($template) || $template == 'language' || $override) { + return get_string('fullnamedisplay', null, $user); + } - } else if ($CFG->fullnamedisplay == 'lastname firstname') { - return $user->lastname .' '. $user->firstname; - - } else if ($CFG->fullnamedisplay == 'firstname') { - if ($override) { - return get_string('fullnamedisplay', '', $user); - } else { - return $user->firstname; + // Get all of the name fields. + $allnames = get_all_user_name_fields(); + $requirednames = array(); + // With each name, see if it is in the display name template, and add it to the required names array if it is. + foreach ($allnames as $allname) { + if (strpos($template, $allname) !== false) { + $requirednames[] = $allname; + // If the field is in the template, but not set in the user object, then notify the programmer that it needs to be fixed. + if (!array_key_exists($allname, $user)) { + debugging('You need to update your sql query to include additional name fields in the user object.', DEBUG_DEVELOPER); + } } } - return get_string('fullnamedisplay', '', $user); + $displayname = $template; + // Switch in the actual data into the template. + foreach ($requirednames as $altname) { + if (isset($user->$altname)) { + // Using empty() on the below if statement causes breakages. + if ((string)$user->$altname == '') { + $displayname = str_replace($altname, 'EMPTY', $displayname); + } else { + $displayname = str_replace($altname, $user->$altname, $displayname); + } + } else { + $displayname = str_replace($altname, 'EMPTY', $displayname); + } + } + // Tidy up any misc. characters (Not perfect, but gets most characters). + // Don't remove the "u" at the end of the first expression unless you want garbled characters when combining hiragana or katakana and parenthesis. + $patterns = array(); + // This regular expression replacement is to fix problems such as 'James () Kirk' Where 'Tiberius' (middlename) has not been filled in by a user. + // The special characters are Japanese brackets that are common enough to make special allowance for them (not covered by :punct:). + $patterns[] = '/[[:punct:]「」]*EMPTY[[:punct:]「」]*/u'; + // This regular expression is to remove any double spaces in the display name. + $patterns[] = '/\s{2,}/'; + foreach ($patterns as $pattern) { + $displayname = preg_replace($pattern, ' ', $displayname); + } + + // Trimming $displayname will help the next check to ensure that we don't have a display name with spaces. + $displayname = trim($displayname); + if (empty($displayname)) { + // Going with just the first name if no alternate fields are filled out. May be changed later depending on what + // people in general feel is a good setting to fall back on. + $displayname = $user->firstname; + } + return $displayname; +} + +/** + * A centralised location for the all name fields. Returns an array / sql string snippet. + * + * @param bool $returnsql True for an sql select field snippet. + * @param string $alias table alias to use in front of each field. + * @return array|string All name fields. + */ +function get_all_user_name_fields($returnsql = false, $alias = null) { + $alternatenames = array('firstnamephonetic', + 'lastnamephonetic', + 'middlename', + 'alternatename', + 'firstname', + 'lastname',); + if ($returnsql) { + if ($alias) { + foreach ($alternatenames as $key => $altname) { + $alternatenames[$key] = "$alias.$altname"; + } + } + $alternatenames = implode(',', $alternatenames); + } + return $alternatenames; +} + +/** + * Returns an array of values in order of occurance in a provided string. + * The key in the result is the character postion in the string. + * + * @param array $values Values to be found in the string format + * @param string $stringformat The string which may contain values being searched for. + * @return array An array of values in order according to placement in the string format. + */ +function order_in_string($values, $stringformat) { + $valuearray = array(); + foreach ($values as $value) { + $pattern = "/$value\b/"; + // Using preg_match as strpos() may match values that are similar e.g. firstname and firstnamephonetic. + if (preg_match($pattern, $stringformat)) { + $replacement = "thing"; + // replace the value with something more unique to ensure we get the right position when using strpos(). + $newformat = preg_replace($pattern, $replacement, $stringformat); + $position = strpos($newformat, $replacement); + $valuearray[$position] = $value; + } + } + ksort($valuearray); + return $valuearray; } /** diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index d3091751e70..344d4df486a 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -131,7 +131,8 @@ class user_picture implements renderable { * @var array List of mandatory fields in user record here. (do not include * TEXT columns because it would break SELECT DISTINCT in MSSQL and ORACLE) */ - protected static $fields = array('id', 'picture', 'firstname', 'lastname', 'imagealt', 'email'); + protected static $fields = array('id', 'picture', 'firstname', 'lastname', 'firstnamephonetic', 'lastnamephonetic', + 'middlename', 'alternatename', 'imagealt', 'email'); /** * @var stdClass A user object with at least fields all columns specified @@ -224,7 +225,6 @@ class user_picture implements renderable { if ($tableprefix) { $tableprefix .= '.'; } - $fields = array(); foreach (self::$fields as $field) { if ($field === 'id' and $idalias and $idalias !== 'id') { $fields[$field] = "$tableprefix$field AS $idalias"; diff --git a/lib/tablelib.php b/lib/tablelib.php index ebd4886b0d9..06e97dc26c5 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -1100,24 +1100,23 @@ class flexible_table { switch ($column) { case 'fullname': - if ($this->is_sortable($column)) { - $firstnamesortlink = $this->sort_link(get_string('firstname'), - 'firstname', $primary_sort_column === 'firstname', $primary_sort_order); + // Check the full name display for sortable fields. + $nameformat = $CFG->fullnamedisplay; + if ($nameformat == 'language') { + $nameformat = get_string('fullnamedisplay'); + } + $requirednames = order_in_string(array('firstname', 'lastname'), $nameformat); - $lastnamesortlink = $this->sort_link(get_string('lastname'), - 'lastname', $primary_sort_column === 'lastname', $primary_sort_order); - - $override = new stdClass(); - $override->firstname = 'firstname'; - $override->lastname = 'lastname'; - $fullnamelanguage = get_string('fullnamedisplay', '', $override); - - if (($CFG->fullnamedisplay == 'firstname lastname') or - ($CFG->fullnamedisplay == 'firstname') or - ($CFG->fullnamedisplay == 'language' and $fullnamelanguage == 'firstname lastname' )) { - $this->headers[$index] = $firstnamesortlink . ' / ' . $lastnamesortlink; - } else { - $this->headers[$index] = $lastnamesortlink . ' / ' . $firstnamesortlink; + if (!empty($requirednames)) { + if ($this->is_sortable($column)) { + // Done this way for the possibility of more than two sortable full name display fields. + $this->headers[$index] = ''; + foreach ($requirednames as $name) { + $sortname = $this->sort_link(get_string($name), + $name, $primary_sort_column === $name, $primary_sort_order); + $this->headers[$index] .= $sortname . ' / '; + } + $this->headers[$index] = substr($this->headers[$index], 0, -3); } } break; diff --git a/lib/testing/generator/data_generator.php b/lib/testing/generator/data_generator.php index a2578c75e17..552c1625034 100644 --- a/lib/testing/generator/data_generator.php +++ b/lib/testing/generator/data_generator.php @@ -159,6 +159,26 @@ EOD; $record['lastname'] = 'Lastname'.$i; } + if (!isset($record['firstnamephonetic'])) { + $firstnamephonetic = rand(0, 59); + $record['firstnamephonetic'] = $this->firstnames[$firstnamephonetic]; + } + + if (!isset($record['lasttnamephonetic'])) { + $lastnamephonetic = rand(0, 59); + $record['lastnamephonetic'] = $this->lastnames[$lastnamephonetic]; + } + + if (!isset($record['middlename'])) { + $middlename = rand(0, 59); + $record['middlename'] = $this->firstnames[$middlename]; + } + + if (!isset($record['alternatename'])) { + $alternatename = rand(0, 59); + $record['alternatename'] = $this->firstnames[$alternatename]; + } + if (!isset($record['idnumber'])) { $record['idnumber'] = ''; } diff --git a/lib/tests/moodlelib_test.php b/lib/tests/moodlelib_test.php index 627d8f886ff..112e74348b7 100644 --- a/lib/tests/moodlelib_test.php +++ b/lib/tests/moodlelib_test.php @@ -2623,4 +2623,163 @@ class moodlelib_testcase extends advanced_testcase { $this->assertFalse(password_is_legacy_hash($user->password)); } } + + public function test_fullname() { + global $CFG; + + $this->resetAfterTest(); + + // Create a user to test the name display on. + $record = array(); + $record['firstname'] = 'Scott'; + $record['lastname'] = 'Fletcher'; + $record['firstnamephonetic'] = 'スコット'; + $record['lastnamephonetic'] = 'フレチャー'; + $record['alternatename'] = 'No friends'; + $user = $this->getDataGenerator()->create_user($record); + + // back up config settings for restore later. + $originalcfg = new stdClass(); + $originalcfg->fullnamedisplay = $CFG->fullnamedisplay; + + // Testing existing fullnamedisplay settings. + $CFG->fullnamedisplay = 'firstname'; + $testname = fullname($user); + $this->assertEquals($testname, $user->firstname); + + $CFG->fullnamedisplay = 'firstname lastname'; + $expectedname = "$user->firstname $user->lastname"; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + + $CFG->fullnamedisplay = 'lastname firstname'; + $expectedname = "$user->lastname $user->firstname"; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + + $expectedname = get_string('fullnamedisplay', null, $user); + $CFG->fullnamedisplay = 'language'; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + + // Test override parameter. + $CFG->fullnamedisplay = 'firstname'; + $expectedname = "$user->firstname $user->lastname"; + $testname = fullname($user, true); + $this->assertEquals($testname, $expectedname); + + // Test additional name fields. + $CFG->fullnamedisplay = 'lastname lastnamephonetic firstname firstnamephonetic'; + $expectedname = "$user->lastname $user->lastnamephonetic $user->firstname $user->firstnamephonetic"; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + + // Test for handling missing data. + $user->middlename = null; + // Parenthesis with no data. + $CFG->fullnamedisplay = 'firstname (middlename) lastname'; + $expectedname = "$user->firstname $user->lastname"; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + + // Extra spaces due to no data. + $CFG->fullnamedisplay = 'firstname middlename lastname'; + $expectedname = "$user->firstname $user->lastname"; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + + // Regular expression testing. + // Remove some data from the user fields + $user->firstnamephonetic = ''; + $user->lastnamephonetic = ''; + + // Removing empty brackets and excess whitespace. + // All of these configurations should resolve to just firstname lastname. + $configarray = array(); + $configarray[] = 'firstname lastname [firstnamephonetic lastnamephonetic]'; + $configarray[] = 'firstname lastname \'middlename\''; + $configarray[] = 'firstname "firstnamephonetic" lastname'; + $configarray[] = 'firstname 「firstnamephonetic」 lastname 「lastnamephonetic」'; + + foreach ($configarray as $config) { + $CFG->fullnamedisplay = $config; + $expectedname = "$user->firstname $user->lastname"; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + } + + // Check to make sure that other characters are left in place. + $configarray = array(); + $configarray['0'] = new stdClass(); + $configarray['0']->config = 'lastname firstname, middlename'; + $configarray['0']->expectedname = "$user->lastname $user->firstname,"; + $configarray['1'] = new stdClass(); + $configarray['1']->config = 'lastname firstname + alternatename'; + $configarray['1']->expectedname = "$user->lastname $user->firstname + $user->alternatename"; + $configarray['2'] = new stdClass(); + $configarray['2']->config = 'firstname aka: alternatename'; + $configarray['2']->expectedname = "$user->firstname aka: $user->alternatename"; + $configarray['3'] = new stdClass(); + $configarray['3']->config = 'firstname (alternatename)'; + $configarray['3']->expectedname = "$user->firstname ($user->alternatename)"; + $configarray['4'] = new stdClass(); + $configarray['4']->config = 'firstname [alternatename]'; + $configarray['4']->expectedname = "$user->firstname [$user->alternatename]"; + $configarray['5'] = new stdClass(); + $configarray['5']->config = 'firstname "lastname"'; + $configarray['5']->expectedname = "$user->firstname \"$user->lastname\""; + + foreach ($configarray as $config) { + $CFG->fullnamedisplay = $config->config; + $expectedname = $config->expectedname; + $testname = fullname($user); + $this->assertEquals($testname, $expectedname); + } + + // tidy up after we finish testing. + $CFG->fullnamedisplay = $originalcfg->fullnamedisplay; + } + + public function test_get_all_user_name_fields() { + $this->resetAfterTest(); + + // Additional names in an array. + $testarray = array('firstnamephonetic', + 'lastnamephonetic', + 'middlename', + 'alternatename', + 'firstname', + 'lastname'); + $this->assertEquals($testarray, get_all_user_name_fields()); + + // Additional names as a string. + $teststring = 'firstnamephonetic,lastnamephonetic,middlename,alternatename,firstname,lastname'; + $this->assertEquals($teststring, get_all_user_name_fields(true)); + + // Additional names as a string with an alias. + $teststring = 't.firstnamephonetic,t.lastnamephonetic,t.middlename,t.alternatename,t.firstname,t.lastname'; + $this->assertEquals($teststring, get_all_user_name_fields(true, 't')); + } + + public function test_order_in_string() { + $this->resetAfterTest(); + + // Return an array in an order as they are encountered in a string. + $valuearray = array('second', 'firsthalf', 'first'); + $formatstring = 'first firsthalf some other text (second)'; + $expectedarray = array('0' => 'first', '6' => 'firsthalf', '33' => 'second'); + $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); + + // Try again with a different order for the format. + $valuearray = array('second', 'firsthalf', 'first'); + $formatstring = 'firsthalf first second'; + $expectedarray = array('0' => 'firsthalf', '10' => 'first', '16' => 'second'); + $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); + + // Try again with yet another different order for the format. + $valuearray = array('second', 'firsthalf', 'first'); + $formatstring = 'start seconds away second firstquater first firsthalf'; + $expectedarray = array('19' => 'second', '38' => 'first', '44' => 'firsthalf'); + $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); + } } diff --git a/mod/data/lib.php b/mod/data/lib.php index 9051b745e43..2da45f7cc28 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -3548,12 +3548,14 @@ function data_get_recordids($alias, $searcharray, $dataid, $recordids) { */ function data_get_advanced_search_sql($sort, $data, $recordids, $selectdata, $sortorder) { global $DB; + + $namefields = get_all_user_name_fields(true, 'u'); if ($sort == 0) { - $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname + $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ' FROM {data_content} c, {data_records} r, {user} u '; - $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname '; + $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' . $namefields; } else { // Sorting through 'Other' criteria if ($sort <= 0) { @@ -3580,12 +3582,13 @@ function data_get_advanced_search_sql($sort, $data, $recordids, $selectdata, $so $sortcontentfull = $sortfield->get_sort_sql($sortcontent); } - $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' . $sortcontentfull . ' + $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ', + ' . $sortcontentfull . ' AS sortorder FROM {data_content} c, {data_records} r, {user} u '; - $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' .$sortcontentfull; + $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ', ' .$sortcontentfull; } // Default to a standard Where statement if $selectdata is empty. diff --git a/mod/data/tests/search_test.php b/mod/data/tests/search_test.php index 29806438853..bfc84b80e91 100644 --- a/mod/data/tests/search_test.php +++ b/mod/data/tests/search_test.php @@ -162,6 +162,10 @@ class data_advanced_search_sql_test extends advanced_testcase { $this->finalrecord[6]->userid = 6; $this->finalrecord[6]->firstname = $user->firstname; $this->finalrecord[6]->lastname = $user->lastname; + $this->finalrecord[6]->firstnamephonetic = $user->firstnamephonetic; + $this->finalrecord[6]->lastnamephonetic = $user->lastnamephonetic; + $this->finalrecord[6]->middlename = $user->middlename; + $this->finalrecord[6]->alternatename = $user->alternatename; } /** diff --git a/mod/data/view.php b/mod/data/view.php index 1b8b2787524..31927210a31 100644 --- a/mod/data/view.php +++ b/mod/data/view.php @@ -498,6 +498,7 @@ if ($showactivity) { $advparams = array(); // This is used for the initial reduction of advanced search results with required entries. $entrysql = ''; + $namefields = get_all_user_name_fields(true, 'u'); /// Find the field we are sorting on if ($sort <= 0 or !$sortfield = data_get_field_from_id($sort, $data)) { @@ -521,7 +522,7 @@ if ($showactivity) { $ordering = "r.timecreated $order"; } - $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname'; + $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields; $count = ' COUNT(DISTINCT c.recordid) '; $tables = '{data_content} c,{data_records} r, {user} u '; $where = 'WHERE c.recordid = r.id @@ -554,7 +555,9 @@ if ($showactivity) { $advparams = array_merge($advparams, $val->params); } } else if ($search) { - $searchselect = " AND (".$DB->sql_like('c.content', ':search1', false)." OR ".$DB->sql_like('u.firstname', ':search2', false)." OR ".$DB->sql_like('u.lastname', ':search3', false)." ) "; + $searchselect = " AND (".$DB->sql_like('c.content', ':search1', false)." + OR ".$DB->sql_like('u.firstname', ':search2', false)." + OR ".$DB->sql_like('u.lastname', ':search3', false)." ) "; $params['search1'] = "%$search%"; $params['search2'] = "%$search%"; $params['search3'] = "%$search%"; @@ -567,7 +570,8 @@ if ($showactivity) { $sortcontent = $DB->sql_compare_text('c.' . $sortfield->get_sort_field()); $sortcontentfull = $sortfield->get_sort_sql($sortcontent); - $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' . $sortcontentfull . ' AS sortorder '; + $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ', + ' . $sortcontentfull . ' AS sortorder '; $count = ' COUNT(DISTINCT c.recordid) '; $tables = '{data_content} c, {data_records} r, {user} u '; $where = 'WHERE c.recordid = r.id diff --git a/mod/forum/lib.php b/mod/forum/lib.php index f3e33c8b922..e23f4a81692 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -1763,7 +1763,8 @@ function forum_scale_used_anywhere($scaleid) { function forum_get_post_full($postid) { global $CFG, $DB; - return $DB->get_record_sql("SELECT p.*, d.forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt + $allnames = get_all_user_name_fields(true, 'u'); + return $DB->get_record_sql("SELECT p.*, d.forum, $allnames, u.email, u.picture, u.imagealt FROM {forum_posts} p JOIN {forum_discussions} d ON p.discussion = d.id LEFT JOIN {user} u ON p.userid = u.id @@ -1782,7 +1783,8 @@ function forum_get_post_full($postid) { function forum_get_discussion_posts($discussion, $sort, $forumid) { global $CFG, $DB; - return $DB->get_records_sql("SELECT p.*, $forumid AS forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt + $allnames = get_all_user_name_fields(true, 'u'); + return $DB->get_records_sql("SELECT p.*, $forumid AS forum, $allnames, u.email, u.picture, u.imagealt FROM {forum_posts} p LEFT JOIN {user} u ON p.userid = u.id WHERE p.discussion = ? @@ -1815,8 +1817,9 @@ function forum_get_all_discussion_posts($discussionid, $sort, $tracking=false) { $params[] = $USER->id; } + $allnames = get_all_user_name_fields(true, 'u'); $params[] = $discussionid; - if (!$posts = $DB->get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture, u.imagealt $tr_sel + if (!$posts = $DB->get_records_sql("SELECT p.*, $allnames, u.email, u.picture, u.imagealt $tr_sel FROM {forum_posts} p LEFT JOIN {user} u ON p.userid = u.id $tr_join @@ -1860,7 +1863,8 @@ function forum_get_all_discussion_posts($discussionid, $sort, $tracking=false) { function forum_get_child_posts($parent, $forumid) { global $CFG, $DB; - return $DB->get_records_sql("SELECT p.*, $forumid AS forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt + $allnames = get_all_user_name_fields(true, 'u'); + return $DB->get_records_sql("SELECT p.*, $forumid AS forum, $allnames, u.email, u.picture, u.imagealt FROM {forum_posts} p LEFT JOIN {user} u ON p.userid = u.id WHERE p.parent = ? @@ -2103,10 +2107,10 @@ function forum_search_posts($searchterms, $courseid=0, $limitfrom=0, $limitnum=5 FROM $fromsql WHERE $selectsql"; + $allnames = get_all_user_name_fields(true, 'u'); $searchsql = "SELECT p.*, d.forum, - u.firstname, - u.lastname, + $allnames, u.email, u.picture, u.imagealt @@ -2243,7 +2247,8 @@ function forum_get_user_posts($forumid, $userid) { } } - return $DB->get_records_sql("SELECT p.*, d.forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt + $allnames = get_all_user_name_fields(true, 'u'); + return $DB->get_records_sql("SELECT p.*, d.forum, $allnames, u.email, u.picture, u.imagealt FROM {forum} f JOIN {forum_discussions} d ON d.forum = f.id JOIN {forum_posts} p ON p.discussion = d.id @@ -2333,10 +2338,10 @@ function forum_count_user_posts($forumid, $userid) { function forum_get_post_from_log($log) { global $CFG, $DB; + $allnames = get_all_user_name_fields(true, 'u'); if ($log->action == "add post") { - return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, - u.firstname, u.lastname, u.email, u.picture + return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, $allnames, u.email, u.picture FROM {forum_discussions} d, {forum_posts} p, {forum} f, @@ -2350,8 +2355,7 @@ function forum_get_post_from_log($log) { } else if ($log->action == "add discussion") { - return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, - u.firstname, u.lastname, u.email, u.picture + return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, $allnames, u.email, u.picture FROM {forum_discussions} d, {forum_posts} p, {forum} f, @@ -2684,8 +2688,9 @@ function forum_get_discussions($cm, $forumsort="d.timemodified DESC", $fullpost= $umtable = " LEFT JOIN {user} um ON (d.usermodified = um.id)"; } - $sql = "SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend, - u.firstname, u.lastname, u.email, u.picture, u.imagealt $umfields + $allnames = get_all_user_name_fields(true, 'u'); + $sql = "SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend, $allnames, + u.email, u.picture, u.imagealt $umfields FROM {forum_discussions} d JOIN {forum_posts} p ON p.discussion = d.id JOIN {user} u ON p.userid = u.id @@ -2862,7 +2867,8 @@ function forum_get_user_discussions($courseid, $userid, $groupid=0) { $groupselect = ""; } - return $DB->get_records_sql("SELECT p.*, d.groupid, u.firstname, u.lastname, u.email, u.picture, u.imagealt, + $allnames = get_all_user_name_fields(true, 'u'); + return $DB->get_records_sql("SELECT p.*, d.groupid, $allnames, u.email, u.picture, u.imagealt, f.type as forumtype, f.name as forumname, f.id as forumid FROM {forum_discussions} d, {forum_posts} p, @@ -2919,11 +2925,11 @@ function forum_get_potential_subscribers($forumcontext, $groupid, $fields, $sort function forum_subscribed_users($course, $forum, $groupid=0, $context = null, $fields = null) { global $CFG, $DB; + $allnames = get_all_user_name_fields(true, 'u'); if (empty($fields)) { $fields ="u.id, u.username, - u.firstname, - u.lastname, + $allnames, u.maildisplay, u.mailformat, u.maildigest, @@ -3301,8 +3307,9 @@ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=fa // Build an object that represents the posting user $postuser = new stdClass; $postuser->id = $post->userid; - $postuser->firstname = $post->firstname; - $postuser->lastname = $post->lastname; + foreach (get_all_user_name_fields() as $addname) { + $postuser->$addname = $post->$addname; + } $postuser->imagealt = $post->imagealt; $postuser->picture = $post->picture; $postuser->email = $post->email; @@ -3732,8 +3739,9 @@ function forum_print_discussion_header(&$post, $forum, $group=-1, $datestring="" // Picture $postuser = new stdClass(); $postuser->id = $post->userid; - $postuser->firstname = $post->firstname; - $postuser->lastname = $post->lastname; + foreach (get_all_user_name_fields() as $addname) { + $postuser->$addname = $post->$addname; + } $postuser->imagealt = $post->imagealt; $postuser->picture = $post->picture; $postuser->email = $post->email; @@ -3800,8 +3808,10 @@ function forum_print_discussion_header(&$post, $forum, $group=-1, $datestring="" $parenturl = (empty($post->lastpostid)) ? '' : '&parent='.$post->lastpostid; $usermodified = new stdClass(); $usermodified->id = $post->usermodified; - $usermodified->firstname = $post->umfirstname; - $usermodified->lastname = $post->umlastname; + foreach (get_all_user_name_fields() as $addname) { + $temp = 'um' . $addname; + $usermodified->$addname = $post->$temp; + } echo ''. fullname($usermodified).'
'; echo ''. @@ -6043,9 +6053,10 @@ function forum_get_recent_mod_activity(&$activities, &$index, $timestart, $cours $groupjoin = ""; } + $allnames = get_all_user_name_fields(true, 'u'); if (!$posts = $DB->get_records_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, d.timestart, d.timeend, d.userid AS duserid, - u.firstname, u.lastname, u.email, u.picture, u.imagealt, u.email + $allnames, u.email, u.picture, u.imagealt, u.email FROM {forum_posts} p JOIN {forum_discussions} d ON d.id = p.discussion JOIN {forum} f ON f.id = d.forum @@ -6118,11 +6129,12 @@ function forum_get_recent_mod_activity(&$activities, &$index, $timestart, $cours $tmpactivity->user = new stdClass(); $tmpactivity->user->id = $post->userid; - $tmpactivity->user->firstname = $post->firstname; - $tmpactivity->user->lastname = $post->lastname; $tmpactivity->user->picture = $post->picture; $tmpactivity->user->imagealt = $post->imagealt; $tmpactivity->user->email = $post->email; + foreach (get_all_user_name_fields() as $addname) { + $tmpactivity->user->$addname = $post->$addname; + } $activities[$index++] = $tmpactivity; } diff --git a/mod/quiz/report/attemptsreport_table.php b/mod/quiz/report/attemptsreport_table.php index 379577685a6..52c34e3b3f7 100644 --- a/mod/quiz/report/attemptsreport_table.php +++ b/mod/quiz/report/attemptsreport_table.php @@ -122,11 +122,12 @@ abstract class quiz_attempts_report_table extends table_sql { global $OUTPUT; $user = new stdClass(); $user->id = $attempt->userid; - $user->lastname = $attempt->lastname; - $user->firstname = $attempt->firstname; $user->imagealt = $attempt->imagealt; $user->picture = $attempt->picture; $user->email = $attempt->email; + foreach (get_all_user_name_fields() as $addname) { + $user->$addname = $attempt->$addname; + } return $OUTPUT->user_picture($user); } @@ -345,13 +346,12 @@ abstract class quiz_attempts_report_table extends table_sql { $extrafields = get_extra_user_fields_sql($this->context, 'u', '', array('id', 'idnumber', 'firstname', 'lastname', 'picture', 'imagealt', 'institution', 'department', 'email')); + $allnames = get_all_user_name_fields(true, 'u'); $fields .= ' quiza.uniqueid AS usageid, quiza.id AS attempt, u.id AS userid, - u.idnumber, - u.firstname, - u.lastname, + u.idnumber, ' . $allnames . ', u.picture, u.imagealt, u.institution, diff --git a/mod/scorm/report/basic/report.php b/mod/scorm/report/basic/report.php index c8d1082970d..aac8d1cc3b3 100644 --- a/mod/scorm/report/basic/report.php +++ b/mod/scorm/report/basic/report.php @@ -273,7 +273,7 @@ class scorm_basic_report extends scorm_default_report { // Construct the SQL $select = 'SELECT DISTINCT '.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, '; $select .= 'st.scormid AS scormid, st.attempt AS attempt, ' . - 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email' . + user_picture::fields('u', array('idnumber'), 'userid') . get_extra_user_fields_sql($coursecontext, 'u', '', array('email', 'idnumber')) . ' '; // This part is the same for all cases - join users and scorm_scoes_track tables @@ -384,9 +384,10 @@ class scorm_basic_report extends scorm_default_report { 'id'=>$scouser->userid, 'picture'=>$scouser->picture, 'imagealt'=>$scouser->imagealt, - 'email'=>$scouser->email, - 'firstname'=>$scouser->firstname, - 'lastname'=>$scouser->lastname); + 'email'=>$scouser->email); + foreach (get_all_user_name_fields() as $addname) { + $user->$addname = $scouser->$addname; + } $row[] = $OUTPUT->user_picture($user, array('courseid'=>$course->id)); } if (!$download) { diff --git a/mod/scorm/report/interactions/report.php b/mod/scorm/report/interactions/report.php index 71d4ce4b2c2..7b3ebb473b8 100644 --- a/mod/scorm/report/interactions/report.php +++ b/mod/scorm/report/interactions/report.php @@ -158,10 +158,10 @@ class scorm_interactions_report extends scorm_default_report { $params = array(); list($usql, $params) = $DB->get_in_or_equal($allowedlist, SQL_PARAMS_NAMED); - // Construct the SQL + // Construct the SQL $select = 'SELECT DISTINCT '.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, '; $select .= 'st.scormid AS scormid, st.attempt AS attempt, ' . - 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email'. + user_picture::fields('u', array('idnumber'), 'userid') . get_extra_user_fields_sql($coursecontext, 'u', '', array('email', 'idnumber')) . ' '; // This part is the same for all cases - join users and scorm_scoes_track tables @@ -419,9 +419,10 @@ class scorm_interactions_report extends scorm_default_report { 'id'=>$scouser->userid, 'picture'=>$scouser->picture, 'imagealt'=>$scouser->imagealt, - 'email'=>$scouser->email, - 'firstname'=>$scouser->firstname, - 'lastname'=>$scouser->lastname); + 'email'=>$scouser->email); + foreach (get_all_user_name_fields() as $addname) { + $user->$addname = $scouser->$addname; + } $row[] = $OUTPUT->user_picture($user, array('courseid'=>$course->id)); } if (!$download) { diff --git a/mod/workshop/allocation/manual/lib.php b/mod/workshop/allocation/manual/lib.php index 24df2c7f8f3..5e00ac4544b 100644 --- a/mod/workshop/allocation/manual/lib.php +++ b/mod/workshop/allocation/manual/lib.php @@ -224,15 +224,18 @@ class workshop_manual_allocator implements workshop_allocator { // load the participants' submissions $submissions = $this->workshop->get_submissions(array_keys($participants)); + $allnames = get_all_user_name_fields(); foreach ($submissions as $submission) { if (!isset($userinfo[$submission->authorid])) { $userinfo[$submission->authorid] = new stdclass(); $userinfo[$submission->authorid]->id = $submission->authorid; - $userinfo[$submission->authorid]->firstname = $submission->authorfirstname; - $userinfo[$submission->authorid]->lastname = $submission->authorlastname; $userinfo[$submission->authorid]->picture = $submission->authorpicture; $userinfo[$submission->authorid]->imagealt = $submission->authorimagealt; $userinfo[$submission->authorid]->email = $submission->authoremail; + foreach ($allnames as $addname) { + $temp = 'author' . $addname; + $userinfo[$submission->authorid]->$addname = $submission->$temp; + } } } @@ -240,8 +243,8 @@ class workshop_manual_allocator implements workshop_allocator { $reviewers = array(); if ($submissions) { list($submissionids, $params) = $DB->get_in_or_equal(array_keys($submissions), SQL_PARAMS_NAMED); - $sql = "SELECT a.id AS assessmentid, a.submissionid, - r.id AS reviewerid, r.lastname, r.firstname, r.picture, r.imagealt, r.email, + $picturefields = user_picture::fields('r', array(), 'reviewerid') + $sql = "SELECT a.id AS assessmentid, a.submissionid, $picturefields, s.id AS submissionid, s.authorid FROM {workshop_assessments} a JOIN {user} r ON (a.reviewerid = r.id) @@ -252,11 +255,12 @@ class workshop_manual_allocator implements workshop_allocator { if (!isset($userinfo[$reviewer->reviewerid])) { $userinfo[$reviewer->reviewerid] = new stdclass(); $userinfo[$reviewer->reviewerid]->id = $reviewer->reviewerid; - $userinfo[$reviewer->reviewerid]->firstname = $reviewer->firstname; - $userinfo[$reviewer->reviewerid]->lastname = $reviewer->lastname; $userinfo[$reviewer->reviewerid]->picture = $reviewer->picture; $userinfo[$reviewer->reviewerid]->imagealt = $reviewer->imagealt; $userinfo[$reviewer->reviewerid]->email = $reviewer->email; + foreach ($allnames as $addname) { + $userinfo[$reviewer->reviewerid]->$addname = $reviewer->$addname; + } } } } @@ -265,11 +269,12 @@ class workshop_manual_allocator implements workshop_allocator { $reviewees = array(); if ($participants) { list($participantids, $params) = $DB->get_in_or_equal(array_keys($participants), SQL_PARAMS_NAMED); + $namefields = get_all_user_name_fields(true, 'e'); $params['workshopid'] = $this->workshop->id; $sql = "SELECT a.id AS assessmentid, a.submissionid, u.id AS reviewerid, s.id AS submissionid, - e.id AS revieweeid, e.lastname, e.firstname, e.picture, e.imagealt, e.email + e.id AS revieweeid, e.lastname, e.firstname, $namefields, e.picture, e.imagealt, e.email FROM {user} u JOIN {workshop_assessments} a ON (a.reviewerid = u.id) JOIN {workshop_submissions} s ON (a.submissionid = s.id) @@ -285,6 +290,9 @@ class workshop_manual_allocator implements workshop_allocator { $userinfo[$reviewee->revieweeid]->picture = $reviewee->picture; $userinfo[$reviewee->revieweeid]->imagealt = $reviewee->imagealt; $userinfo[$reviewee->revieweeid]->email = $reviewee->email; + foreach ($allnames as $addname) { + $userinfo[$reviewee->revieweeid]->$addname = $reviewee->$addname; + } } } } diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 6b143cd8c81..dcbde8e70a6 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -1761,8 +1761,8 @@ class workshop { $sqlsort[] = $sqlsortfieldname . ' ' . $sqlsortfieldhow; } $sqlsort = implode(',', $sqlsort); - $sql = "SELECT u.id AS userid,u.firstname,u.lastname,u.picture,u.imagealt,u.email, - s.title AS submissiontitle, s.grade AS submissiongrade, ag.gradinggrade + $picturefields = user_picture::fields('u', array(), 'userid'); + $sql = "SELECT $picturefields, s.title AS submissiontitle, s.grade AS submissiongrade, ag.gradinggrade FROM {user} u LEFT JOIN {workshop_submissions} s ON (s.authorid = u.id AND s.workshopid = :workshopid1 AND s.example = 0) LEFT JOIN {workshop_aggregations} ag ON (ag.userid = u.id AND ag.workshopid = :workshopid2) @@ -1777,15 +1777,17 @@ class workshop { $userinfo = array(); // get the user details for all participants to display + $additionalnames = get_all_user_name_fields(); foreach ($participants as $participant) { if (!isset($userinfo[$participant->userid])) { $userinfo[$participant->userid] = new stdclass(); $userinfo[$participant->userid]->id = $participant->userid; - $userinfo[$participant->userid]->firstname = $participant->firstname; - $userinfo[$participant->userid]->lastname = $participant->lastname; $userinfo[$participant->userid]->picture = $participant->picture; $userinfo[$participant->userid]->imagealt = $participant->imagealt; $userinfo[$participant->userid]->email = $participant->email; + foreach ($additionalnames as $addname) { + $userinfo[$participant->userid]->$addname = $participant->$addname; + } } } @@ -1797,22 +1799,25 @@ class workshop { if (!isset($userinfo[$submission->gradeoverby])) { $userinfo[$submission->gradeoverby] = new stdclass(); $userinfo[$submission->gradeoverby]->id = $submission->gradeoverby; - $userinfo[$submission->gradeoverby]->firstname = $submission->overfirstname; - $userinfo[$submission->gradeoverby]->lastname = $submission->overlastname; $userinfo[$submission->gradeoverby]->picture = $submission->overpicture; $userinfo[$submission->gradeoverby]->imagealt = $submission->overimagealt; $userinfo[$submission->gradeoverby]->email = $submission->overemail; + foreach ($additionalnames as $addname) { + $temp = 'over' . $addname; + $userinfo[$submission->gradeoverby]->$addname = $submission->$temp; + } } } // get the user details for all reviewers of the displayed participants $reviewers = array(); + if ($submissions) { list($submissionids, $params) = $DB->get_in_or_equal(array_keys($submissions), SQL_PARAMS_NAMED); list($sort, $sortparams) = users_order_by_sql('r'); + $picturefields = user_picture::fields('r', array(), 'reviewerid'); $sql = "SELECT a.id AS assessmentid, a.submissionid, a.grade, a.gradinggrade, a.gradinggradeover, a.weight, - r.id AS reviewerid, r.lastname, r.firstname, r.picture, r.imagealt, r.email, - s.id AS submissionid, s.authorid + $picturefields, s.id AS submissionid, s.authorid FROM {workshop_assessments} a JOIN {user} r ON (a.reviewerid = r.id) JOIN {workshop_submissions} s ON (a.submissionid = s.id AND s.example = 0) @@ -1823,11 +1828,12 @@ class workshop { if (!isset($userinfo[$reviewer->reviewerid])) { $userinfo[$reviewer->reviewerid] = new stdclass(); $userinfo[$reviewer->reviewerid]->id = $reviewer->reviewerid; - $userinfo[$reviewer->reviewerid]->firstname = $reviewer->firstname; - $userinfo[$reviewer->reviewerid]->lastname = $reviewer->lastname; $userinfo[$reviewer->reviewerid]->picture = $reviewer->picture; $userinfo[$reviewer->reviewerid]->imagealt = $reviewer->imagealt; $userinfo[$reviewer->reviewerid]->email = $reviewer->email; + foreach ($additionalnames as $addname) { + $userinfo[$reviewer->reviewerid]->$addname = $reviewer->$addname; + } } } } @@ -1838,9 +1844,9 @@ class workshop { list($participantids, $params) = $DB->get_in_or_equal(array_keys($participants), SQL_PARAMS_NAMED); list($sort, $sortparams) = users_order_by_sql('e'); $params['workshopid'] = $this->id; + $picturefields = user_picture::fields('e', array(), 'authorid'); $sql = "SELECT a.id AS assessmentid, a.submissionid, a.grade, a.gradinggrade, a.gradinggradeover, a.reviewerid, a.weight, - s.id AS submissionid, - e.id AS authorid, e.lastname, e.firstname, e.picture, e.imagealt, e.email + s.id AS submissionid, $picturefields FROM {user} u JOIN {workshop_assessments} a ON (a.reviewerid = u.id) JOIN {workshop_submissions} s ON (a.submissionid = s.id AND s.example = 0) @@ -1852,11 +1858,12 @@ class workshop { if (!isset($userinfo[$reviewee->authorid])) { $userinfo[$reviewee->authorid] = new stdclass(); $userinfo[$reviewee->authorid]->id = $reviewee->authorid; - $userinfo[$reviewee->authorid]->firstname = $reviewee->firstname; - $userinfo[$reviewee->authorid]->lastname = $reviewee->lastname; $userinfo[$reviewee->authorid]->picture = $reviewee->picture; $userinfo[$reviewee->authorid]->imagealt = $reviewee->imagealt; $userinfo[$reviewee->authorid]->email = $reviewee->email; + foreach ($additionalnames as $addname) { + $userinfo[$reviewee->authorid]->$addname = $reviewee->$addname; + } } } } diff --git a/report/log/locallib.php b/report/log/locallib.php index 3d8370a2a38..2b55a8ae293 100644 --- a/report/log/locallib.php +++ b/report/log/locallib.php @@ -139,10 +139,12 @@ function report_log_print_mnet_selector_form($hostid, $course, $selecteduser=0, // If looking at a different host, we're interested in all our site users if ($hostid == $CFG->mnet_localhost_id && $course->id != SITEID) { - $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, u.firstname, u.lastname, u.idnumber', null, $limitfrom, $limitnum); + $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, ' . get_all_user_name_fields(true, 'u'), + null, $limitfrom, $limitnum); } else { // this may be a lot of users :-( - $courseusers = $DB->get_records('user', array('deleted'=>0), 'lastaccess DESC', 'id, firstname, lastname, idnumber', $limitfrom, $limitnum); + $courseusers = $DB->get_records('user', array('deleted'=>0), 'lastaccess DESC', 'id, ' . get_all_user_name_fields(true), + $limitfrom, $limitnum); } if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) { @@ -440,7 +442,8 @@ function report_log_print_selector_form($course, $selecteduser=0, $selecteddate= $limitfrom = empty($showusers) ? 0 : ''; $limitnum = empty($showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : ''; - $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, u.firstname, u.lastname', null, $limitfrom, $limitnum); + $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, ' . get_all_user_name_fields(true, 'u'), + null, $limitfrom, $limitnum); if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) { $showusers = 1; diff --git a/user/editlib.php b/user/editlib.php index 46d87538410..fd2dc575822 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -129,22 +129,41 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager $strrequired = get_string('required'); - $nameordercheck = new stdClass(); - $nameordercheck->firstname = 'a'; - $nameordercheck->lastname = 'b'; - if (fullname($nameordercheck) == 'b a' ) { // See MDL-4325 - $mform->addElement('text', 'lastname', get_string('lastname'), 'maxlength="100" size="30"'); - $mform->addElement('text', 'firstname', get_string('firstname'), 'maxlength="100" size="30"'); - } else { - $mform->addElement('text', 'firstname', get_string('firstname'), 'maxlength="100" size="30"'); - $mform->addElement('text', 'lastname', get_string('lastname'), 'maxlength="100" size="30"'); + $nameformat = $CFG->fullnamedisplay; + if ($nameformat == 'language') { + $nameformat = get_string('fullnamedisplay'); + } + + $necessarynames = array('firstname', 'lastname'); + $enablednames = array_diff(get_all_user_name_fields(), $necessarynames); + // Get a list of all of the enabled names. + $enabledadditionalusernames = array(); + foreach ($enablednames as $enabledname) { + if (strpos($CFG->fullnamedisplay, $enabledname) !== false) { + $enabledadditionalusernames[] = $enabledname; + } + } + + $combinednames = array_merge($necessarynames, $enabledadditionalusernames); + $requirednames = order_in_string($combinednames, $nameformat); + foreach ($necessarynames as $necessaryname) { + if (!in_array($necessaryname, $requirednames)) { + $requirednames = order_in_string($combinednames, get_string('fullnamedisplay')); + } + } + foreach ($requirednames as $fullname) { + $mform->addElement('text', $fullname, get_string($fullname), 'maxlength="100" size="30"'); + $mform->setType($fullname, PARAM_NOTAGS); } $mform->addRule('firstname', $strrequired, 'required', null, 'client'); - $mform->setType('firstname', PARAM_NOTAGS); - $mform->addRule('lastname', $strrequired, 'required', null, 'client'); - $mform->setType('lastname', PARAM_NOTAGS); + + $morenames = array_diff($enabledadditionalusernames, $requirednames); + foreach ($morenames as $addname) { + $mform->addElement('text', $addname, get_string($addname), 'maxlength="100" size="30"'); + $mform->setType($addname, PARAM_NOTAGS); + } // Do not show email field if change confirmation is pending if (!empty($CFG->emailchangeconfirmation) and !empty($user->preference_newemail)) { @@ -278,6 +297,18 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager } + $alladditionalnames = array_diff(get_all_user_name_fields(), $necessarynames); + if (count($enabledadditionalusernames) < count($alladditionalnames)) { + $mform->addElement('header', 'moodle_additional_names', get_string('additionalnames')); + foreach ($alladditionalnames as $allname) { + if (!in_array($allname, $enabledadditionalusernames)) { + $mform->addElement('text', $allname, get_string($allname), 'maxlength="100" size="30"'); + $mform->setType($allname, PARAM_NOTAGS); + } + } + + } + if (!empty($CFG->usetags) and empty($USER->newadminuser)) { $mform->addElement('header', 'moodle_interests', get_string('interests')); $mform->addElement('tags', 'interests', get_string('interestslist'), array('display' => 'noofficial')); diff --git a/user/externallib.php b/user/externallib.php index e21ed8c7750..9f8f375a575 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -51,21 +51,25 @@ class core_user_external extends external_api { 'users' => new external_multiple_structure( new external_single_structure( array( - 'username' => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config.'), - 'password' => new external_value(PARAM_RAW, 'Plain text password consisting of any characters'), - 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user'), - 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user'), - 'email' => new external_value(PARAM_EMAIL, 'A valid and unique email address'), - 'auth' => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_DEFAULT, 'manual', NULL_NOT_ALLOWED), - 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_DEFAULT, ''), - 'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_DEFAULT, $CFG->lang, NULL_NOT_ALLOWED), - 'theme' => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), - 'timezone' => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), - 'mailformat' => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), - 'description' => new external_value(PARAM_TEXT, 'User profile description, no HTML', VALUE_OPTIONAL), - 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), - 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), - 'preferences' => new external_multiple_structure( + 'username' => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config.'), + 'password' => new external_value(PARAM_RAW, 'Plain text password consisting of any characters'), + 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user'), + 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user'), + 'email' => new external_value(PARAM_EMAIL, 'A valid and unique email address'), + 'auth' => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_DEFAULT, 'manual', NULL_NOT_ALLOWED), + 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_DEFAULT, ''), + 'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_DEFAULT, $CFG->lang, NULL_NOT_ALLOWED), + 'theme' => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), + 'timezone' => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), + 'mailformat' => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), + 'description' => new external_value(PARAM_TEXT, 'User profile description, no HTML', VALUE_OPTIONAL), + 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), + 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), + 'firstnamephonetic' => new external_value(PARAM_NOTAGS, 'The first name(s) phonetically of the user', VALUE_OPTIONAL), + 'lastnamephonetic' => new external_value(PARAM_NOTAGS, 'The family name phonetically of the user', VALUE_OPTIONAL), + 'middlename' => new external_value(PARAM_NOTAGS, 'The middle name of the user', VALUE_OPTIONAL), + 'alternatename' => new external_value(PARAM_NOTAGS, 'The alternate name of the user', VALUE_OPTIONAL), + 'preferences' => new external_multiple_structure( new external_single_structure( array( 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the preference'), @@ -276,21 +280,25 @@ class core_user_external extends external_api { new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'ID of the user'), - 'username' => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config.', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), - 'password' => new external_value(PARAM_RAW, 'Plain text password consisting of any characters', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), - 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), - 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), - 'email' => new external_value(PARAM_EMAIL, 'A valid and unique email address', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), - 'auth' => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), - 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), - 'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), - 'theme' => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), - 'timezone' => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), - 'mailformat' => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), - 'description' => new external_value(PARAM_TEXT, 'User profile description, no HTML', VALUE_OPTIONAL), - 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), - 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), - 'customfields' => new external_multiple_structure( + 'username' => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config.', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), + 'password' => new external_value(PARAM_RAW, 'Plain text password consisting of any characters', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), + 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), + 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), + 'email' => new external_value(PARAM_EMAIL, 'A valid and unique email address', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED), + 'auth' => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), + 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), + 'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), + 'theme' => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), + 'timezone' => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), + 'mailformat' => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), + 'description' => new external_value(PARAM_TEXT, 'User profile description, no HTML', VALUE_OPTIONAL), + 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), + 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), + 'firstnamephonetic' => new external_value(PARAM_NOTAGS, 'The first name(s) phonetically of the user', VALUE_OPTIONAL), + 'lastnamephonetic' => new external_value(PARAM_NOTAGS, 'The family name phonetically of the user', VALUE_OPTIONAL), + 'middlename' => new external_value(PARAM_NOTAGS, 'The middle name of the user', VALUE_OPTIONAL), + 'alternatename' => new external_value(PARAM_NOTAGS, 'The alternate name of the user', VALUE_OPTIONAL), + 'customfields' => new external_multiple_structure( new external_single_structure( array( 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'), diff --git a/user/index.php b/user/index.php index 59fa4160e82..adf8a37c5cd 100644 --- a/user/index.php +++ b/user/index.php @@ -381,21 +381,17 @@ 'id', 'username', 'firstname', 'lastname', 'email', 'city', 'country', 'picture', 'lang', 'timezone', 'maildisplay', 'imagealt', 'lastaccess')); + $mainuserfields = user_picture::fields('u', array('username', 'email', 'city', 'country', 'lang', 'timezone', 'maildisplay')); + if ($isfrontpage) { - $select = "SELECT u.id, u.username, u.firstname, u.lastname, - u.email, u.city, u.country, u.picture, - u.lang, u.timezone, u.maildisplay, u.imagealt, - u.lastaccess$extrasql"; + $select = "SELECT $mainuserfields, u.lastaccess$extrasql"; $joins[] = "JOIN ($esql) e ON e.id = u.id"; // everybody on the frontpage usually if ($accesssince) { $wheres[] = get_user_lastaccess_sql($accesssince); } } else { - $select = "SELECT u.id, u.username, u.firstname, u.lastname, - u.email, u.city, u.country, u.picture, - u.lang, u.timezone, u.maildisplay, u.imagealt, - COALESCE(ul.timeaccess, 0) AS lastaccess$extrasql"; + $select = "SELECT $mainuserfields, COALESCE(ul.timeaccess, 0) AS lastaccess$extrasql"; $joins[] = "JOIN ($esql) e ON e.id = u.id"; // course enrolled users only $joins[] = "LEFT JOIN {user_lastaccess} ul ON (ul.userid = u.id AND ul.courseid = :courseid)"; // not everybody accessed course yet $params['courseid'] = $course->id; diff --git a/user/messageselect.php b/user/messageselect.php index 51f62919561..614352191ec 100644 --- a/user/messageselect.php +++ b/user/messageselect.php @@ -93,10 +93,12 @@ $count = 0; if ($data = data_submitted()) { require_sesskey(); + $namefields = get_all_user_name_fields(true); foreach ($data as $k => $v) { if (preg_match('/^(user|teacher)(\d+)$/',$k,$m)) { if (!array_key_exists($m[2],$SESSION->emailto[$id])) { - if ($user = $DB->get_record_select('user', "id = ?", array($m[2]), 'id,firstname,lastname,idnumber,email,mailformat,lastaccess, lang, maildisplay')) { + if ($user = $DB->get_record_select('user', "id = ?", array($m[2]), 'id, + ' . $namefields . ',idnumber,email,mailformat,lastaccess, lang, maildisplay')) { $SESSION->emailto[$id][$m[2]] = $user; $count++; } diff --git a/user/selector/lib.php b/user/selector/lib.php index 9692e3bb388..f64e687a2b2 100644 --- a/user/selector/lib.php +++ b/user/selector/lib.php @@ -413,8 +413,9 @@ abstract class user_selector_base { */ protected function required_fields_sql($u) { // Raw list of fields. - $fields = array('id', 'firstname', 'lastname'); - $fields = array_merge($fields, $this->extrafields); + $fields = array('id'); + // Add additional name fields + $fields = array_merge($fields, get_all_user_name_fields(), $this->extrafields); // Prepend the table alias. if ($u) { diff --git a/user/tests/externallib_test.php b/user/tests/externallib_test.php index 42f080ba543..ae5cfdda1e9 100644 --- a/user/tests/externallib_test.php +++ b/user/tests/externallib_test.php @@ -457,6 +457,10 @@ class core_user_external_testcase extends externallib_advanced_testcase { 'idnumber' => 'idnumbertest1', 'firstname' => 'First Name User Test 1', 'lastname' => 'Last Name User Test 1', + 'middlename' => 'Middle Name User Test 1', + 'lastnamephonetic' => '最後のお名前のテスト一号', + 'firstnamephonetic' => 'お名前のテスト一号', + 'alternatename' => 'Alternate Name User Test 1', 'email' => 'usertest1@email.com', 'description' => 'This is a description for user 1', 'city' => 'Perth', @@ -632,6 +636,10 @@ class core_user_external_testcase extends externallib_advanced_testcase { 'idnumber' => 'idnumbertest1', 'firstname' => 'First Name User Test 1', 'lastname' => 'Last Name User Test 1', + 'middlename' => 'Middle Name User Test 1', + 'lastnamephonetic' => '最後のお名前のテスト一号', + 'firstnamephonetic' => 'お名前のテスト一号', + 'alternatename' => 'Alternate Name User Test 1', 'email' => 'usertest1@email.com', 'description' => 'This is a description for user 1', 'city' => 'Perth', diff --git a/version.php b/version.php index 72d88e95c46..37d042ef188 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2013070800.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2013070800.01; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes