Skip to content

Commit

Permalink
Add methods which allow us to filter combined authorized handlers and…
Browse files Browse the repository at this point in the history
… handlers marked as unique that have already been attached to a bot.
  • Loading branch information
RTippin committed Aug 16, 2021
1 parent 13b4d9d commit d643df3
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/Facades/MessengerBots.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

/**
* @method static array getHandlerClasses()
* @method static array getUniqueHandlerClasses()
* @method static array|null getHandlerSettings(?string $handlerOrAlias = null)
* @method static array getAuthorizedHandlers()
* @method static array getAliases()
Expand Down
42 changes: 38 additions & 4 deletions src/Http/Controllers/Actions/AvailableBotHandlers.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,64 @@

use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Collection;
use RTippin\Messenger\MessengerBots;
use RTippin\Messenger\Models\Bot;
use RTippin\Messenger\Models\BotAction;
use RTippin\Messenger\Models\Thread;

class AvailableBotHandlers
{
use AuthorizesRequests;

/**
* @var MessengerBots
*/
private MessengerBots $bots;

/**
* @param MessengerBots $bots
*/
public function __construct(MessengerBots $bots)
{
$this->bots = $bots;
}

/**
* Get all authorized handlers the current provider is allowed to
* choose from, rejecting any handlers that are marked as unique
* and have already attached to the bot provided.
*
* @param Thread $thread
* @param Bot $bot
* @return array
* @throws AuthorizationException
*/
public function __invoke(MessengerBots $bots,
Thread $thread,
Bot $bot): array
public function __invoke(Thread $thread, Bot $bot): array
{
$this->authorize('create', [
Bot::class,
$thread,
]);

return $bots->getAuthorizedHandlers();
return $this->generateAvailableHandlers($bot);
}

/**
* @param Bot $bot
* @return array
*/
private function generateAvailableHandlers(Bot $bot): array
{
$handlers = new Collection($this->bots->getAuthorizedHandlers());

$unique = $bot->validUniqueActions()
->get()
->transform(fn (BotAction $action) => $action->getHandlerSettings()['alias'] ?? '')
->toArray();

return $handlers->reject(fn ($handler) => in_array($handler['alias'], $unique))
->values()
->toArray();
}
}
13 changes: 13 additions & 0 deletions src/MessengerBots.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ public function getHandlerClasses(): array
return $this->handlers->keys()->toArray();
}

/**
* Get all bot handler classes marked as unique.
*
* @return array
*/
public function getUniqueHandlerClasses(): array
{
return $this->handlers
->filter(fn ($settings) => $settings['unique'] === true)
->keys()
->toArray();
}

/**
* Get all or an individual bot handlers settings.
*
Expand Down
11 changes: 11 additions & 0 deletions src/Models/Bot.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \RTippin\Messenger\Models\Thread $thread
* @property-read \RTippin\Messenger\Models\BotAction[]|Collection $actions
* @property-read \RTippin\Messenger\Models\BotAction[]|Collection $validActions
* @property-read \RTippin\Messenger\Models\BotAction[]|Collection $validUniqueActions
* @mixin Model|\Eloquent
* @property-read Model|MessengerProvider $owner
*/
Expand Down Expand Up @@ -131,6 +133,15 @@ public function validActions(): HasMany
->whereIn('handler', MessengerBots::getHandlerClasses());
}

/**
* @return HasMany|BotAction|Collection
*/
public function validUniqueActions(): HasMany
{
return $this->hasMany(BotAction::class)
->whereIn('handler', MessengerBots::getUniqueHandlerClasses());
}

/**
* Get the provider settings and alias override, if set.
*
Expand Down
9 changes: 8 additions & 1 deletion tests/Fixtures/SillyBotHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

class SillyBotHandler extends BotActionHandler
{
public static bool $authorized = false;

public static function getSettings(): array
{
return [
Expand All @@ -25,6 +27,11 @@ public function handle(): void

public function authorize(): bool
{
return false;
return self::$authorized;
}

public static function reset(): void
{
self::$authorized = false;
}
}
44 changes: 42 additions & 2 deletions tests/Http/AvailableBotHandlersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use RTippin\Messenger\Facades\Messenger;
use RTippin\Messenger\Facades\MessengerBots;
use RTippin\Messenger\Models\Bot;
use RTippin\Messenger\Models\BotAction;
use RTippin\Messenger\Models\Participant;
use RTippin\Messenger\Models\Thread;
use RTippin\Messenger\Tests\Fixtures\FunBotHandler;
Expand All @@ -17,16 +18,50 @@ class AvailableBotHandlersTest extends HttpTestCase
public function admin_can_view_available_handlers()
{
$this->logCurrentRequest();
MessengerBots::registerHandlers([FunBotHandler::class]);
SillyBotHandler::$authorized = true;
MessengerBots::registerHandlers([
FunBotHandler::class,
SillyBotHandler::class,
]);
$thread = $this->createGroupThread($this->tippin);
$bot = Bot::factory()->for($thread)->owner($this->tippin)->create();
$this->actingAs($this->tippin);

$this->getJson(route('api.messenger.threads.bots.handlers', [
'thread' => $thread->id,
'bot' => $bot->id,
]))
->assertSuccessful()
->assertJson([
[
'alias' => 'fun_bot',
],
[
'alias' => 'silly_bot',
],
]);
}

/** @test */
public function unique_handlers_that_are_already_attached_to_bot_are_omitted()
{
SillyBotHandler::$authorized = true;
MessengerBots::registerHandlers([
FunBotHandler::class,
SillyBotHandler::class,
]);
$thread = $this->createGroupThread($this->tippin);
$bot = Bot::factory()->for($thread)->owner($this->tippin)->create();
BotAction::factory()->for($bot)->owner($this->tippin)->handler(FunBotHandler::class)->create();
BotAction::factory()->for($bot)->owner($this->tippin)->handler(SillyBotHandler::class)->create();
$this->actingAs($this->tippin);

$this->getJson(route('api.messenger.threads.bots.handlers', [
'thread' => $thread->id,
'bot' => $bot->id,
]))
->assertSuccessful()
->assertJsonCount(1)
->assertJson([
[
'alias' => 'fun_bot',
Expand All @@ -50,7 +85,12 @@ public function handlers_failing_authorization_are_omitted()
'bot' => $bot->id,
]))
->assertSuccessful()
->assertJsonCount(1);
->assertJsonCount(1)
->assertJson([
[
'alias' => 'fun_bot',
],
]);
}

/** @test */
Expand Down
11 changes: 11 additions & 0 deletions tests/Messenger/MessengerBotsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ public function it_can_set_bot_handlers()
$this->assertSame($handlers, $this->bots->getHandlerClasses());
}

/** @test */
public function it_can_get_unique_bot_handlers()
{
$this->bots->registerHandlers([
FunBotHandler::class,
SillyBotHandler::class,
]);

$this->assertSame([SillyBotHandler::class], $this->bots->getUniqueHandlerClasses());
}

/** @test */
public function it_can_get_bot_aliases_sorting_by_alias()
{
Expand Down
4 changes: 3 additions & 1 deletion tests/MessengerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use RTippin\Messenger\Facades\Messenger;
use RTippin\Messenger\MessengerServiceProvider;
use RTippin\Messenger\Tests\Fixtures\CompanyModel;
use RTippin\Messenger\Tests\Fixtures\SillyBotHandler;
use RTippin\Messenger\Tests\Fixtures\UserModel;

class MessengerTestCase extends TestCase
Expand Down Expand Up @@ -78,12 +79,13 @@ protected function setUp(): void
}

/**
* Reset the static properties we dynamically set on the models.
* Reset the static properties we dynamically set on the classes.
*/
protected function tearDown(): void
{
UserModel::reset();
CompanyModel::reset();
SillyBotHandler::reset();

parent::tearDown();
}
Expand Down
2 changes: 2 additions & 0 deletions tests/Models/BotTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public function it_has_relations()
$this->assertInstanceOf(Thread::class, $bot->thread);
$this->assertInstanceOf(MessengerProvider::class, $bot->owner);
$this->assertInstanceOf(Collection::class, $bot->actions);
$this->assertInstanceOf(Collection::class, $bot->validActions);
$this->assertInstanceOf(Collection::class, $bot->validUniqueActions);
$this->assertSame(BotAction::first()->id, $bot->actions->first()->id);
}

Expand Down

0 comments on commit d643df3

Please sign in to comment.