Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 12 commits into from
May 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions js/src/admin/components/BasicsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default class BasicsPage extends Page {
'default_route',
'welcome_title',
'welcome_message',
'display_name_driver',
];
this.values = {};

Expand All @@ -33,6 +34,14 @@ export default class BasicsPage extends Page {
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);
}

Expand Down Expand Up @@ -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({
type: 'submit',
className: 'Button Button--primary',
Expand Down
19 changes: 17 additions & 2 deletions src/Admin/Content/AdminPayload.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@
use Flarum\Group\Permission;
use Flarum\Settings\Event\Deserializing;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\ConnectionInterface;
use Psr\Http\Message\ServerRequestInterface as Request;

class AdminPayload
{
/**
* @var Container;
*/
protected $container;

/**
* @var SettingsRepositoryInterface
*/
Expand All @@ -36,13 +42,20 @@ class AdminPayload
protected $db;

/**
* @param Container $container
* @param SettingsRepositoryInterface $settings
* @param ExtensionManager $extensions
* @param ConnectionInterface $db
* @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->extensions = $extensions;
$this->db = $db;
Expand All @@ -61,6 +74,8 @@ public function __invoke(Document $document, Request $request)
$document->payload['permissions'] = Permission::map();
$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['mysqlVersion'] = $this->db->selectOne('select version() as version')->version;
}
Expand Down
38 changes: 38 additions & 0 deletions src/Extend/User.php
Original file line number Diff line number Diff line change
@@ -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);
});
}
}
25 changes: 25 additions & 0 deletions src/User/DisplayName/DriverInterface.php
Original file line number Diff line number Diff line change
@@ -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;
}
23 changes: 23 additions & 0 deletions src/User/DisplayName/UsernameDriver.php
Original file line number Diff line number Diff line change
@@ -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;
}
}
3 changes: 3 additions & 0 deletions src/User/Event/GetDisplayName.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

use Flarum\User\User;

/**
* @deprecated beta 14, removed beta 15.
*/
class GetDisplayName
{
/**
Expand Down
21 changes: 20 additions & 1 deletion src/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Flarum\Http\UrlGenerator;
use Flarum\Notification\Notification;
use Flarum\Post\Post;
use Flarum\User\DisplayName\DriverInterface;
use Flarum\User\Event\Activated;
use Flarum\User\Event\AvatarChanged;
use Flarum\User\Event\CheckingPassword;
Expand Down Expand Up @@ -93,6 +94,13 @@ class User extends AbstractModel
*/
protected static $preferences = [];

/**
* A driver for getting display names.
*
* @var DriverInterface
*/
protected static $displayNameDriver;

/**
* The hasher with which to hash passwords.
*
Expand Down Expand Up @@ -172,6 +180,16 @@ public static function setGate($gate)
static::$gate = $gate;
}

/**
* Set the display name driver.
*
* @param DriverInterface $driver
*/
public static function setDisplayNameDriver(DriverInterface $driver)
{
static::$displayNameDriver = $driver;
}

/**
* Rename the user.
*
Expand Down Expand Up @@ -309,7 +327,8 @@ public function getAvatarUrlAttribute(string $value = null)
*/
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);
}

/**
Expand Down
29 changes: 29 additions & 0 deletions src/User/UserServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@
use Flarum\Event\ConfigureUserPreferences;
use Flarum\Event\GetPermission;
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\Registered;
use Flarum\User\Event\Saving;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Filesystem\Factory;
use Illuminate\Support\Arr;
use League\Flysystem\FilesystemInterface;
use RuntimeException;

Expand All @@ -30,6 +34,30 @@ public function register()
{
$this->registerGate();
$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()
Expand Down Expand Up @@ -84,6 +112,7 @@ public function boot()

User::setHasher($this->app->make('hash'));
User::setGate($this->app->make('flarum.gate'));
User::setDisplayNameDriver($this->app->make('flarum.user.display_name.driver'));

$events = $this->app->make('events');

Expand Down
69 changes: 69 additions & 0 deletions tests/integration/extenders/UserTest.php
Original file line number Diff line number Diff line change
@@ -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';
}
}