diff --git a/lib/classes/user.php b/lib/classes/user.php index 0593334241d..889cc050301 100644 --- a/lib/classes/user.php +++ b/lib/classes/user.php @@ -1226,4 +1226,31 @@ class core_user { }; return null; } + + + /** + * Get initials for users + * + * @param stdClass $user + * @return string + */ + public static function get_initials(stdClass $user): string { + // Get the available name fields. + $namefields = \core_user\fields::get_name_fields(); + // Build a dummy user to determine the name format. + $dummyuser = array_combine($namefields, $namefields); + // Determine the name format by using fullname() and passing the dummy user. + $nameformat = fullname((object) $dummyuser); + // Fetch all the available username fields. + $availablefields = order_in_string($namefields, $nameformat); + // We only want the first and last name fields. + if (!empty($availablefields) && count($availablefields) >= 2) { + $availablefields = [reset($availablefields), end($availablefields)]; + } + $initials = ''; + foreach ($availablefields as $userfieldname) { + $initials .= mb_substr($user->$userfieldname, 0, 1); + } + return $initials; + } } diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 6e1ce2a4bc3..079bf5681a0 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -2668,8 +2668,12 @@ class core_renderer extends renderer_base { // Get the image html output first, auto generated based on initials if one isn't already set. if ($user->picture == 0 && empty($CFG->enablegravatar) && !defined('BEHAT_SITE_RUNNING')) { - $output = html_writer::tag('span', mb_substr($user->firstname, 0, 1) . mb_substr($user->lastname, 0, 1), - ['class' => 'userinitials size-' . $size]); + $initials = \core_user::get_initials($user); + // Don't modify in corner cases where neither the firstname nor the lastname appears. + $output = html_writer::tag( + 'span', $initials, + ['class' => 'userinitials size-' . $size] + ); } else { $output = html_writer::empty_tag('img', $attributes); } diff --git a/lib/tests/user_test.php b/lib/tests/user_test.php index d99bb0564a3..607ef61979b 100644 --- a/lib/tests/user_test.php +++ b/lib/tests/user_test.php @@ -813,4 +813,73 @@ class user_test extends \advanced_testcase { $this->assertFalse(\core_user::awaiting_action($admin)); $this->assertTrue(\core_user::awaiting_action($manager)); } + + /** + * Test that user with Letter avatar respect language preference. + * + * @param array $userdata + * @param string $fullnameconfig + * @param string $expected + * @return void + * @covers \core_user::get_initials + * @dataProvider user_name_provider + */ + public function test_get_initials(array $userdata, string $fullnameconfig, string $expected): void { + $this->resetAfterTest(); + // Create a user. + $page = new \moodle_page(); + $page->set_url('/user/profile.php'); + $page->set_context(\context_system::instance()); + $renderer = $page->get_renderer('core'); + $user1 = + $this->getDataGenerator()->create_user( + array_merge( + ['picture' => 0, 'email' => 'user1@example.com'], + $userdata + ) + ); + set_config('fullnamedisplay', $fullnameconfig); + $initials = \core_user::get_initials($user1); + $this->assertEquals($expected, $initials); + } + + /** + * Provider of user configuration for testing initials rendering + * + * @return array[] + */ + public static function user_name_provider(): array { + return [ + 'simple user' => [ + 'user' => ['firstname' => 'first', 'lastname' => 'last'], + 'fullnamedisplay' => 'language', + 'expected' => 'fl', + ], + 'simple user with lastname firstname in language settings' => [ + 'user' => ['firstname' => 'first', 'lastname' => 'last'], + 'fullnamedisplay' => 'lastname firstname', + 'expected' => 'lf', + ], + 'simple user with no surname' => [ + 'user' => ['firstname' => '', 'lastname' => 'L'], + 'fullnamedisplay' => 'language', + 'expected' => 'L', + ], + 'simple user with a middle name' => [ + 'user' => ['firstname' => 'f', 'lastname' => 'l', 'middlename' => 'm'], + 'fullnamedisplay' => 'middlename lastname', + 'expected' => 'ml', + ], + 'user with a middle name & fullnamedisplay contains 3 names' => [ + 'user' => ['firstname' => 'first', 'lastname' => 'last', 'middlename' => 'middle'], + 'fullnamedisplay' => 'firstname middlename lastname', + 'expected' => 'fl', + ], + 'simple user with a namefield consisting of one element' => [ + 'user' => ['firstname' => 'first', 'lastname' => 'last'], + 'fullnamedisplay' => 'lastname', + 'expected' => 'l', + ], + ]; + } } diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 9da0ce9a40d..74eb47cbc30 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -1,6 +1,9 @@ This files describes API changes in core libraries and APIs, information provided here is intended especially for developers. +=== 4.1.7 === +* Add a new method core_user::get_initials to get the initials of a user in a way compatible with internationalisation. + === 4.1.6 === * \moodle_page::set_title() has been updated to append the site name depending on the value of $CFG->sitenameintitle and whether the site's fullname/shortname has been set. So there's no need to manually add the site name whenever calling $PAGE->set_title().