1
0
mirror of https://github.com/flarum/core.git synced 2025-07-23 17:51:24 +02:00

Use drivers for display names, add display name extender (#2174)

* Deprecate GetDisplayName event

* Add interface for display name driver

* Add username driver as default

* Add code to register supported drivers / used driver as singletons

* Configured User class to use new driver-based system for display names

* Add extender for adding display name driver

* Add integration test for user display name driver

* Add frontend UI for selecting display name driver
This commit is contained in:
Alexander Skvortsov
2020-05-19 18:45:56 -04:00
committed by GitHub
parent 577aaa16d9
commit f7985bac61
9 changed files with 247 additions and 3 deletions

View File

@@ -21,6 +21,7 @@ export default class BasicsPage extends Page {
'default_route', 'default_route',
'welcome_title', 'welcome_title',
'welcome_message', 'welcome_message',
'display_name_driver',
]; ];
this.values = {}; this.values = {};
@@ -33,6 +34,14 @@ export default class BasicsPage extends Page {
this.localeOptions[i] = `${locales[i]} (${i})`; this.localeOptions[i] = `${locales[i]} (${i})`;
} }
this.displayNameOptions = {};
const displayNameDrivers = app.data.displayNameDrivers;
displayNameDrivers.forEach(function (identifier) {
this.displayNameOptions[identifier] = identifier;
}, this);
if (!this.values.display_name_driver() && displayNameDrivers.includes('username')) this.values.display_name_driver('username');
if (typeof this.values.show_language_selector() !== 'number') this.values.show_language_selector(1); if (typeof this.values.show_language_selector() !== 'number') this.values.show_language_selector(1);
} }
@@ -114,6 +123,20 @@ export default class BasicsPage extends Page {
], ],
})} })}
{Object.keys(this.displayNameOptions).length > 1
? FieldSet.component({
label: app.translator.trans('core.admin.basics.display_name_heading'),
children: [
<div className="helpText">{app.translator.trans('core.admin.basics.display_name_text')}</div>,
Select.component({
options: this.displayNameOptions,
value: this.values.display_name_driver(),
onchange: this.values.display_name_driver,
}),
],
})
: ''}
{Button.component({ {Button.component({
type: 'submit', type: 'submit',
className: 'Button Button--primary', className: 'Button Button--primary',

View File

@@ -14,12 +14,18 @@ use Flarum\Frontend\Document;
use Flarum\Group\Permission; use Flarum\Group\Permission;
use Flarum\Settings\Event\Deserializing; use Flarum\Settings\Event\Deserializing;
use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
class AdminPayload class AdminPayload
{ {
/**
* @var Container;
*/
protected $container;
/** /**
* @var SettingsRepositoryInterface * @var SettingsRepositoryInterface
*/ */
@@ -36,13 +42,20 @@ class AdminPayload
protected $db; protected $db;
/** /**
* @param Container $container
* @param SettingsRepositoryInterface $settings * @param SettingsRepositoryInterface $settings
* @param ExtensionManager $extensions * @param ExtensionManager $extensions
* @param ConnectionInterface $db * @param ConnectionInterface $db
* @param Dispatcher $events * @param Dispatcher $events
*/ */
public function __construct(SettingsRepositoryInterface $settings, ExtensionManager $extensions, ConnectionInterface $db, Dispatcher $events) public function __construct(
{ Container $container,
SettingsRepositoryInterface $settings,
ExtensionManager $extensions,
ConnectionInterface $db,
Dispatcher $events
) {
$this->container = $container;
$this->settings = $settings; $this->settings = $settings;
$this->extensions = $extensions; $this->extensions = $extensions;
$this->db = $db; $this->db = $db;
@@ -61,6 +74,8 @@ class AdminPayload
$document->payload['permissions'] = Permission::map(); $document->payload['permissions'] = Permission::map();
$document->payload['extensions'] = $this->extensions->getExtensions()->toArray(); $document->payload['extensions'] = $this->extensions->getExtensions()->toArray();
$document->payload['displayNameDrivers'] = array_keys($this->container->make('flarum.user.display_name.supported_drivers'));
$document->payload['phpVersion'] = PHP_VERSION; $document->payload['phpVersion'] = PHP_VERSION;
$document->payload['mysqlVersion'] = $this->db->selectOne('select version() as version')->version; $document->payload['mysqlVersion'] = $this->db->selectOne('select version() as version')->version;
} }

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Extend;
use Flarum\Extension\Extension;
use Illuminate\Contracts\Container\Container;
class User implements ExtenderInterface
{
private $displayNameDrivers = [];
/**
* Add a mail driver.
*
* @param string $identifier Identifier for display name driver. E.g. 'username' for UserNameDriver
* @param string $driver ::class attribute of driver class, which must implement Flarum\User\DisplayName\DriverInterface
*/
public function displayNameDriver(string $identifier, $driver)
{
$this->drivers[$identifier] = $driver;
return $this;
}
public function extend(Container $container, Extension $extension = null)
{
$container->extend('flarum.user.display_name.supported_drivers', function ($existingDrivers) {
return array_merge($existingDrivers, $this->drivers);
});
}
}

View File

@@ -0,0 +1,25 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\User\DisplayName;
use Flarum\User\User;
/**
* An interface for a display name driver.
*
* @public
*/
interface DriverInterface
{
/**
* Return a display name for a user.
*/
public function displayName(User $user): string;
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\User\DisplayName;
use Flarum\User\User;
/**
* The default driver, which returns the user's username.
*/
class UsernameDriver implements DriverInterface
{
public function displayName(User $user): string
{
return $user->username;
}
}

View File

@@ -11,6 +11,9 @@ namespace Flarum\User\Event;
use Flarum\User\User; use Flarum\User\User;
/**
* @deprecated beta 14, removed beta 15.
*/
class GetDisplayName class GetDisplayName
{ {
/** /**

View File

@@ -23,6 +23,7 @@ use Flarum\Http\AccessToken;
use Flarum\Http\UrlGenerator; use Flarum\Http\UrlGenerator;
use Flarum\Notification\Notification; use Flarum\Notification\Notification;
use Flarum\Post\Post; use Flarum\Post\Post;
use Flarum\User\DisplayName\DriverInterface;
use Flarum\User\Event\Activated; use Flarum\User\Event\Activated;
use Flarum\User\Event\AvatarChanged; use Flarum\User\Event\AvatarChanged;
use Flarum\User\Event\CheckingPassword; use Flarum\User\Event\CheckingPassword;
@@ -93,6 +94,13 @@ class User extends AbstractModel
*/ */
protected static $preferences = []; protected static $preferences = [];
/**
* A driver for getting display names.
*
* @var DriverInterface
*/
protected static $displayNameDriver;
/** /**
* The hasher with which to hash passwords. * The hasher with which to hash passwords.
* *
@@ -172,6 +180,16 @@ class User extends AbstractModel
static::$gate = $gate; static::$gate = $gate;
} }
/**
* Set the display name driver.
*
* @param DriverInterface $driver
*/
public static function setDisplayNameDriver(DriverInterface $driver)
{
static::$displayNameDriver = $driver;
}
/** /**
* Rename the user. * Rename the user.
* *
@@ -309,7 +327,8 @@ class User extends AbstractModel
*/ */
public function getDisplayNameAttribute() public function getDisplayNameAttribute()
{ {
return static::$dispatcher->until(new GetDisplayName($this)) ?: $this->username; // Event is deprecated in beta 14, remove in beta 15.
return static::$dispatcher->until(new GetDisplayName($this)) ?: static::$displayNameDriver->displayName($this);
} }
/** /**

View File

@@ -12,12 +12,16 @@ namespace Flarum\User;
use Flarum\Event\ConfigureUserPreferences; use Flarum\Event\ConfigureUserPreferences;
use Flarum\Event\GetPermission; use Flarum\Event\GetPermission;
use Flarum\Foundation\AbstractServiceProvider; use Flarum\Foundation\AbstractServiceProvider;
use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\DisplayName\DriverInterface;
use Flarum\User\DisplayName\UsernameDriver;
use Flarum\User\Event\EmailChangeRequested; use Flarum\User\Event\EmailChangeRequested;
use Flarum\User\Event\Registered; use Flarum\User\Event\Registered;
use Flarum\User\Event\Saving; use Flarum\User\Event\Saving;
use Illuminate\Contracts\Auth\Access\Gate as GateContract; use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Factory;
use Illuminate\Support\Arr;
use League\Flysystem\FilesystemInterface; use League\Flysystem\FilesystemInterface;
use RuntimeException; use RuntimeException;
@@ -30,6 +34,30 @@ class UserServiceProvider extends AbstractServiceProvider
{ {
$this->registerGate(); $this->registerGate();
$this->registerAvatarsFilesystem(); $this->registerAvatarsFilesystem();
$this->registerDisplayNameDrivers();
}
protected function registerDisplayNameDrivers()
{
$this->app->singleton('flarum.user.display_name.supported_drivers', function () {
return [
'username' => UsernameDriver::class,
];
});
$this->app->singleton('flarum.user.display_name.driver', function () {
$drivers = $this->app->make('flarum.user.display_name.supported_drivers');
$settings = $this->app->make(SettingsRepositoryInterface::class);
$driverName = $settings->get('display_name_driver', '');
$driverClass = Arr::get($drivers, $driverName);
return $driverClass
? $this->app->make($driverClass)
: $this->app->make(UsernameDriver::class);
});
$this->app->alias('flarum.user.display_name.driver', DriverInterface::class);
} }
protected function registerGate() protected function registerGate()
@@ -84,6 +112,7 @@ class UserServiceProvider extends AbstractServiceProvider
User::setHasher($this->app->make('hash')); User::setHasher($this->app->make('hash'));
User::setGate($this->app->make('flarum.gate')); User::setGate($this->app->make('flarum.gate'));
User::setDisplayNameDriver($this->app->make('flarum.user.display_name.driver'));
$events = $this->app->make('events'); $events = $this->app->make('events');

View File

@@ -0,0 +1,69 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Tests\integration\extenders;
use Flarum\Extend;
use Flarum\Tests\integration\RetrievesAuthorizedUsers;
use Flarum\Tests\integration\TestCase;
use Flarum\User\DisplayName\DriverInterface;
use Flarum\User\User;
class UserTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function prepDb()
{
$this->prepareDatabase([
'users' => [
$this->adminUser(),
], 'settings' => [
['key' => 'display_name_driver', 'value' => 'custom'],
],
]);
}
/**
* @test
*/
public function username_display_name_driver_used_by_default()
{
$this->prepDb();
$user = User::find(1);
$this->assertEquals('admin', $user->displayName);
}
/**
* @test
*/
public function can_use_custom_display_name_driver()
{
$this->extend(
(new Extend\User)
->displayNameDriver('custom', CustomDisplayNameDriver::class)
);
$this->prepDb();
$user = User::find(1);
$this->assertEquals('admin@machine.local$$$suffix', $user->displayName);
}
}
class CustomDisplayNameDriver implements DriverInterface
{
public function displayName(User $user): string
{
return $user->email.'$$$suffix';
}
}