Skip to content

Commit df0a0e5

Browse files
feat: implement created_by relationship & search (#65)
* feat: add created_by column * feat: serialize created_by to admin frontend * test: implement gambit test * feat: implement search gambit * Apply fixes from StyleCI * chore: teardown * chore * refactor: use FK * Apply fixes from StyleCI * chore * chore: reorder * refactor: chore --------- Co-authored-by: StyleCI Bot <[email protected]>
1 parent 7ea1b32 commit df0a0e5

15 files changed

+239
-47
lines changed

extend.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
use Flarum\User\User;
2020
use FoF\Doorman\Api\Controllers;
2121
use FoF\Doorman\Content\AdminPayload;
22+
use FoF\Doorman\Filter\CreatedByFilterGambit;
2223
use FoF\Doorman\Filter\DoorkeyFilterer;
23-
use FoF\Doorman\Filter\NoFilter;
2424
use FoF\Doorman\Search\DoorkeySearcher;
2525
use FoF\Doorman\Search\Gambit\FulltextGambit;
2626
use FoF\Doorman\Validators\DoorkeyLoginValidator;
@@ -46,10 +46,11 @@
4646
->get('/fof/doorkeys/{id}', 'fof.doorkeys.show', Controllers\ShowDoorkeyController::class),
4747

4848
(new Extend\SimpleFlarumSearch(DoorkeySearcher::class))
49+
->addGambit(CreatedByFilterGambit::class)
4950
->setFullTextGambit(FulltextGambit::class),
5051

5152
(new Extend\Filter(DoorkeyFilterer::class))
52-
->addFilter(NoFilter::class),
53+
->addFilter(CreatedByFilterGambit::class),
5354

5455
new Extend\Locales(__DIR__.'/resources/locale'),
5556

js/src/admin/components/DoorkeyListPage.tsx

+27
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,33 @@ export default class DoorkeyListPage extends ExtensionPage {
414414
40
415415
);
416416

417+
columns.add(
418+
'createdBy',
419+
{
420+
name: app.translator.trans('fof-doorman.admin.list.columns.created_by'),
421+
content: (doorkey: Doorkey) => {
422+
const user = doorkey.createdBy();
423+
424+
if (!user) return app.translator.trans('fof-doorman.admin.list.content.no_created_by');
425+
426+
const profileUrl = `${app.forum.attribute('baseUrl')}/u/${user.slug()}`;
427+
428+
return (
429+
<a
430+
target="_blank"
431+
href={profileUrl}
432+
title={extractText(
433+
app.translator.trans('core.admin.users.grid.columns.username.profile_link_tooltip', { username: user.displayName() })
434+
)}
435+
>
436+
{user.displayName()}
437+
</a>
438+
);
439+
},
440+
},
441+
30
442+
);
443+
417444
return columns;
418445
}
419446

js/src/common/models/Doorkey.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Model from 'flarum/common/Model';
22
import type Group from 'flarum/common/models/Group';
3+
import type User from 'flarum/common/models/User';
34

45
export default class Doorkey extends Model {
56
key() {
@@ -26,6 +27,10 @@ export default class Doorkey extends Model {
2627
return Model.attribute<number>('uses').call(this);
2728
}
2829

30+
createdBy() {
31+
return Model.hasOne<User>('createdBy').call(this);
32+
}
33+
2934
protected apiEndpoint() {
3035
return '/fof/doorkeys' + (this.exists ? `/${(this.data as any).id}` : '');
3136
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of fof/doorman.
5+
*
6+
* Copyright (c) Reflar.
7+
* Copyright (c) FriendsOfFlarum.
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*
12+
*/
13+
14+
use Flarum\Database\Migration;
15+
16+
return Migration::addColumns('doorkeys', [
17+
'created_by' => ['integer', 'unsigned' => true, 'nullable' => true],
18+
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of fof/doorman.
5+
*
6+
* Copyright (c) Reflar.
7+
* Copyright (c) FriendsOfFlarum.
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*
12+
*/
13+
14+
use Illuminate\Database\Schema\Blueprint;
15+
use Illuminate\Database\Schema\Builder;
16+
17+
return [
18+
'up' => function (Builder $schema) {
19+
$schema->table('doorkeys', function (Blueprint $table) {
20+
$table->foreign('created_by')->references('id')->on('users')->nullOnDelete();
21+
});
22+
},
23+
'down' => function (Builder $schema) {
24+
$schema->table('doorkeys', function (Blueprint $table) {
25+
$table->dropForeign(['created_by']);
26+
});
27+
},
28+
];

resources/locale/en.yml

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ fof-doorman:
7474
activates_user: => fof-doorman.admin.ref.fields.activates_user.label
7575
manage: Manage
7676
uses: Uses
77+
created_by: Created By
7778
content:
7879
invalid_column: => core.admin.users.grid.columns.invalid_column
7980
no_group: => core.admin.users.grid.columns.group_badges.no_badges
@@ -82,6 +83,7 @@ fof-doorman:
8283
uses:
8384
used_times: "{remaining, plural, =0 {Unlimited uses} one {{remainingUses} use left} other {{remainingUses} uses left}}"
8485
total_uses: "{totalUses, plural, one {Used {totalUses} time} other {Used {totalUses} times}}"
86+
no_created_by: Unknown User
8587
pagination:
8688
first_page_button: => core.admin.users.pagination.first_page_button
8789
back_button: => core.admin.users.pagination.back_button

src/Api/Controllers/ListDoorkeysController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class ListDoorkeysController extends AbstractListController
2727
{
2828
public $serializer = DoorkeySerializer::class;
2929

30-
public $include = ['group'];
30+
public $include = ['group', 'createdBy'];
3131

3232
/**
3333
* @var DoorkeyFilterer

src/Api/Controllers/ShowDoorkeyController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ShowDoorkeyController extends AbstractShowController
2525
{
2626
public $serializer = DoorkeySerializer::class;
2727

28-
public $include = ['group'];
28+
public $include = ['group', 'createdBy'];
2929

3030
/**
3131
* @var DoorkeyRepository

src/Api/Serializers/DoorkeySerializer.php

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use Flarum\Api\Serializer\AbstractSerializer;
1717
use Flarum\Api\Serializer\GroupSerializer;
18+
use Flarum\Api\Serializer\UserSerializer;
1819
use FoF\Doorman\Doorkey;
1920
use InvalidArgumentException;
2021

@@ -51,4 +52,9 @@ protected function group($user)
5152
{
5253
return $this->hasOne($user, GroupSerializer::class);
5354
}
55+
56+
protected function createdBy($user)
57+
{
58+
return $this->hasOne($user, UserSerializer::class);
59+
}
5460
}

src/Commands/CreateDoorkeyHandler.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public function __construct(DoorkeyValidator $validator, Dispatcher $events)
5050
public function handle(CreateDoorkey $command)
5151
{
5252
$data = $command->data;
53+
$actor = $command->actor;
5354

5455
$doorkey = Doorkey::build(
5556
Arr::get($data, 'attributes.key'),
@@ -58,12 +59,12 @@ public function handle(CreateDoorkey $command)
5859
Arr::get($data, 'attributes.activates')
5960
);
6061

62+
$doorkey->created_by = $actor->id;
63+
6164
$this->validator->assertValid($doorkey->getAttributes());
6265

6366
$doorkey->save();
6467

65-
$actor = $command->actor;
66-
6768
$doorkey->afterSave(function ($doorkey) use ($actor, $data) {
6869
$this->events->dispatch(
6970
new DoorkeyCreated($doorkey, $actor, $data)

src/Doorkey.php

+7
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
use Flarum\Database\AbstractModel;
1717
use Flarum\Database\ScopeVisibilityTrait;
1818
use Flarum\Group\Group;
19+
use Flarum\User\User;
1920

2021
/**
2122
* @property string $key
2223
* @property int $group_id
2324
* @property int $max_uses
2425
* @property int $activates
2526
* @property int $uses
27+
* @property int $created_by
2628
*/
2729
class Doorkey extends AbstractModel
2830
{
@@ -48,4 +50,9 @@ public function group()
4850
{
4951
return $this->belongsTo(Group::class, 'group_id');
5052
}
53+
54+
public function createdBy()
55+
{
56+
return $this->belongsTo(User::class, 'created_by');
57+
}
5158
}

src/Filter/CreatedByFilterGambit.php

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
/*
4+
* This file is part of fof/doorman.
5+
*
6+
* Copyright (c) Reflar.
7+
* Copyright (c) FriendsOfFlarum.
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*
12+
*/
13+
14+
namespace FoF\Doorman\Filter;
15+
16+
use Flarum\Filter\FilterInterface;
17+
use Flarum\Filter\FilterState;
18+
use Flarum\Filter\ValidateFilterTrait;
19+
use Flarum\Search\AbstractRegexGambit;
20+
use Flarum\Search\SearchState;
21+
use Flarum\User\UserRepository;
22+
use Illuminate\Database\Query\Builder;
23+
24+
class CreatedByFilterGambit extends AbstractRegexGambit implements FilterInterface
25+
{
26+
use ValidateFilterTrait;
27+
28+
/**
29+
* @var \Flarum\User\UserRepository
30+
*/
31+
protected $users;
32+
33+
/**
34+
* @param \Flarum\User\UserRepository $users
35+
*/
36+
public function __construct(UserRepository $users)
37+
{
38+
$this->users = $users;
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function getGambitPattern()
45+
{
46+
return 'created_by:(.+)';
47+
}
48+
49+
/**
50+
* {@inheritdoc}
51+
*/
52+
protected function conditions(SearchState $search, array $matches, $negate)
53+
{
54+
$this->constrain($search->getQuery(), $matches[1], $negate);
55+
}
56+
57+
public function getFilterKey(): string
58+
{
59+
return 'created_by';
60+
}
61+
62+
public function filter(FilterState $filterState, $filterValue, bool $negate)
63+
{
64+
$this->constrain($filterState->getQuery(), $filterValue, $negate);
65+
}
66+
67+
protected function constrain(Builder $query, $rawUsernames, $negate)
68+
{
69+
$usernames = $this->asStringArray($rawUsernames);
70+
71+
$ids = $this->users->getIdsForUsernames($usernames);
72+
73+
$query->whereIn('doorkeys.created_by', $ids, 'and', $negate);
74+
}
75+
}

src/Filter/NoFilter.php

-35
This file was deleted.

tests/integration/api/CreateDoorkeyTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public function permitted_users_can_create_doorkey($actorId)
8181
$this->assertEquals('ABCDEFG1', Arr::get($response, 'data.attributes.key'));
8282

8383
$this->assertEquals(1, Doorkey::count());
84+
$this->assertEquals($actorId, Doorkey::first()->created_by);
8485
}
8586

8687
/**

0 commit comments

Comments
 (0)