From eb72307a546cf1bd604dc15b93e699a24a37b2c4 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Wed, 20 Sep 2017 16:42:18 +0930 Subject: [PATCH] User display names (#1246) * Introduce user display names It is not uncommon for forums to be intergrated with sites where users don't have a unique "handle" - they might just have their first name, or a full name, which is not guaranteed to be unique. This commit introduces the concept of "display names" for users. By default display names are the same as usernames, but extensions may override this and set them to something different. The important thing is that all code should use `display_name` whenever intending to output a human-readable name - `username` is reserved for cases where you want to output a unique identifier (which may or may not be human-friendly). The new "GetDisplayName" API is probably sub-optimal, but I didn't worry too much because we can come up with something better in `next-back`. ref #557 * Apply fixes from StyleCI [ci skip] [skip ci] --- js/forum/dist/app.js | 7 +++-- js/forum/src/components/UsersSearchSource.js | 2 +- js/lib/helpers/username.js | 2 +- js/lib/models/User.js | 1 + src/Api/Serializer/PostBasicSerializer.php | 1 - src/Api/Serializer/UserBasicSerializer.php | 5 ++-- .../Command/RequestPasswordResetHandler.php | 2 +- src/Core/Listener/EmailConfirmationMailer.php | 2 +- src/Core/User.php | 11 +++++++ src/Event/GetDisplayName.php | 30 +++++++++++++++++++ 10 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 src/Event/GetDisplayName.php diff --git a/js/forum/dist/app.js b/js/forum/dist/app.js index 16374dc0b..fffd65333 100644 --- a/js/forum/dist/app.js +++ b/js/forum/dist/app.js @@ -28942,7 +28942,9 @@ System.register('flarum/components/UsersSearchSource', ['flarum/helpers/highligh query = query.toLowerCase(); var results = app.store.all('users').filter(function (user) { - return user.username().toLowerCase().substr(0, query.length) === query; + return [user.username(), user.displayName()].some(function (value) { + return value.toLowerCase().substr(0, query.length) === query; + }); }); if (!results.length) return ''; @@ -29534,7 +29536,7 @@ System.register("flarum/helpers/username", [], function (_export, _context) { "use strict"; function username(user) { - var name = user && user.username() || app.translator.trans('core.lib.username.deleted_text'); + var name = user && user.displayName() || app.translator.trans('core.lib.username.deleted_text'); return m( "span", @@ -30533,6 +30535,7 @@ System.register('flarum/models/User', ['flarum/Model', 'flarum/utils/stringToCol babelHelpers.extends(User.prototype, { username: Model.attribute('username'), + displayName: Model.attribute('displayName'), email: Model.attribute('email'), isActivated: Model.attribute('isActivated'), password: Model.attribute('password'), diff --git a/js/forum/src/components/UsersSearchSource.js b/js/forum/src/components/UsersSearchSource.js index f05fbb30d..7f687b811 100644 --- a/js/forum/src/components/UsersSearchSource.js +++ b/js/forum/src/components/UsersSearchSource.js @@ -20,7 +20,7 @@ export default class UsersSearchResults { query = query.toLowerCase(); const results = app.store.all('users') - .filter(user => user.username().toLowerCase().substr(0, query.length) === query); + .filter(user => [user.username(), user.displayName()].some(value => value.toLowerCase().substr(0, query.length) === query)); if (!results.length) return ''; diff --git a/js/lib/helpers/username.js b/js/lib/helpers/username.js index 16e12654f..7e05ca4d6 100644 --- a/js/lib/helpers/username.js +++ b/js/lib/helpers/username.js @@ -6,7 +6,7 @@ * @return {Object} */ export default function username(user) { - const name = (user && user.username()) || app.translator.trans('core.lib.username.deleted_text'); + const name = (user && user.displayName()) || app.translator.trans('core.lib.username.deleted_text'); return {name}; } diff --git a/js/lib/models/User.js b/js/lib/models/User.js index a28173c3b..07d5aaf1b 100644 --- a/js/lib/models/User.js +++ b/js/lib/models/User.js @@ -10,6 +10,7 @@ export default class User extends Model {} Object.assign(User.prototype, { username: Model.attribute('username'), + displayName: Model.attribute('displayName'), email: Model.attribute('email'), isActivated: Model.attribute('isActivated'), password: Model.attribute('password'), diff --git a/src/Api/Serializer/PostBasicSerializer.php b/src/Api/Serializer/PostBasicSerializer.php index c5ef11168..3a79eed84 100644 --- a/src/Api/Serializer/PostBasicSerializer.php +++ b/src/Api/Serializer/PostBasicSerializer.php @@ -12,7 +12,6 @@ namespace Flarum\Api\Serializer; use Flarum\Core\Post; -use Flarum\Core\Post\CommentPost; use InvalidArgumentException; class PostBasicSerializer extends AbstractSerializer diff --git a/src/Api/Serializer/UserBasicSerializer.php b/src/Api/Serializer/UserBasicSerializer.php index 2699c8714..f5919ebf5 100644 --- a/src/Api/Serializer/UserBasicSerializer.php +++ b/src/Api/Serializer/UserBasicSerializer.php @@ -36,8 +36,9 @@ class UserBasicSerializer extends AbstractSerializer } return [ - 'username' => $user->username, - 'avatarUrl' => $user->avatar_url + 'username' => $user->username, + 'displayName' => $user->display_name, + 'avatarUrl' => $user->avatar_url ]; } diff --git a/src/Core/Command/RequestPasswordResetHandler.php b/src/Core/Command/RequestPasswordResetHandler.php index fb484fbda..3318c9882 100644 --- a/src/Core/Command/RequestPasswordResetHandler.php +++ b/src/Core/Command/RequestPasswordResetHandler.php @@ -107,7 +107,7 @@ class RequestPasswordResetHandler $token->save(); $data = [ - '{username}' => $user->username, + '{username}' => $user->display_name, '{url}' => $this->url->toRoute('resetPassword', ['token' => $token->id]), '{forum}' => $this->settings->get('forum_title'), ]; diff --git a/src/Core/Listener/EmailConfirmationMailer.php b/src/Core/Listener/EmailConfirmationMailer.php index 295d45d7c..6c7583cad 100755 --- a/src/Core/Listener/EmailConfirmationMailer.php +++ b/src/Core/Listener/EmailConfirmationMailer.php @@ -130,7 +130,7 @@ class EmailConfirmationMailer $token = $this->generateToken($user, $email); return [ - '{username}' => $user->username, + '{username}' => $user->display_name, '{url}' => $this->url->toRoute('confirmEmail', ['token' => $token->id]), '{forum}' => $this->settings->get('forum_title') ]; diff --git a/src/Core/User.php b/src/Core/User.php index dd50ab449..e8325b0e5 100755 --- a/src/Core/User.php +++ b/src/Core/User.php @@ -18,6 +18,7 @@ use Flarum\Core\Support\ScopeVisibilityTrait; use Flarum\Database\AbstractModel; use Flarum\Event\CheckUserPassword; use Flarum\Event\ConfigureUserPreferences; +use Flarum\Event\GetDisplayName; use Flarum\Event\PostWasDeleted; use Flarum\Event\PrepareUserGroups; use Flarum\Event\UserAvatarWasChanged; @@ -333,6 +334,16 @@ class User extends AbstractModel } } + /** + * Get the user's display name. + * + * @return string + */ + public function getDisplayNameAttribute() + { + return static::$dispatcher->until(new GetDisplayName($this)) ?: $this->username; + } + /** * Get the user's locale, falling back to the forum's default if they * haven't set one. diff --git a/src/Event/GetDisplayName.php b/src/Event/GetDisplayName.php new file mode 100644 index 000000000..71fbe6ba4 --- /dev/null +++ b/src/Event/GetDisplayName.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Event; + +use Flarum\Core\User; + +class GetDisplayName +{ + /** + * @var User + */ + public $user; + + /** + * @param User $user + */ + public function __construct(User $user) + { + $this->user = $user; + } +}