chore - Extract RegisterDiscoveredPageAction for shared Page::firstOrCreate logic
This commit is contained in:
parent
dda5b0f770
commit
649aeb3627
4 changed files with 115 additions and 17 deletions
22
app/Actions/RegisterDiscoveredPageAction.php
Normal file
22
app/Actions/RegisterDiscoveredPageAction.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Actions;
|
||||
|
||||
use App\Enums\PageStatusEnum;
|
||||
use App\Models\Page;
|
||||
|
||||
class RegisterDiscoveredPageAction
|
||||
{
|
||||
public function __invoke(string $url, ?int $instanceId = null): Page
|
||||
{
|
||||
return Page::firstOrCreate(
|
||||
['url' => $url],
|
||||
[
|
||||
'status' => PageStatusEnum::Discovered,
|
||||
'instance_id' => $instanceId,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Enums\PageStatusEnum;
|
||||
use App\Models\Page;
|
||||
use App\Actions\RegisterDiscoveredPageAction;
|
||||
use App\Models\PageLink;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -13,22 +12,20 @@
|
|||
|
||||
class UrlDiscoveredListener implements ShouldQueue
|
||||
{
|
||||
public function __construct(
|
||||
private RegisterDiscoveredPageAction $registerPage,
|
||||
) {}
|
||||
|
||||
public function handle(UrlDiscovered $event): void
|
||||
{
|
||||
DB::transaction(function () use ($event) {
|
||||
$targetPage = Page::firstOrCreate(
|
||||
['url' => $event->url],
|
||||
['status' => PageStatusEnum::Discovered, 'instance_id' => $event->instanceId],
|
||||
);
|
||||
$targetPage = ($this->registerPage)($event->url, $event->instanceId);
|
||||
|
||||
if ($event->postUrl === null || $event->postUrl === $event->url) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sourcePage = Page::firstOrCreate(
|
||||
['url' => $event->postUrl],
|
||||
['status' => PageStatusEnum::Discovered, 'instance_id' => $event->instanceId],
|
||||
);
|
||||
$sourcePage = ($this->registerPage)($event->postUrl, $event->instanceId);
|
||||
|
||||
PageLink::firstOrCreate([
|
||||
'source_page_id' => $sourcePage->id,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Enums\PageStatusEnum;
|
||||
use App\Models\Page;
|
||||
use App\Actions\RegisterDiscoveredPageAction;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Livewire\Component;
|
||||
|
|
@ -16,7 +15,7 @@ class UrlSubmissionForm extends Component
|
|||
|
||||
public ?string $confirmedUrl = null;
|
||||
|
||||
public function submit(): void
|
||||
public function submit(RegisterDiscoveredPageAction $registerPage): void
|
||||
{
|
||||
$key = 'submit-url:' . request()->ip();
|
||||
|
||||
|
|
@ -32,10 +31,7 @@ public function submit(): void
|
|||
'url' => ['required', 'url:http,https'],
|
||||
]);
|
||||
|
||||
Page::firstOrCreate(
|
||||
['url' => $validated['url']],
|
||||
['status' => PageStatusEnum::Discovered],
|
||||
);
|
||||
$registerPage($validated['url']);
|
||||
|
||||
$this->confirmedUrl = $validated['url'];
|
||||
$this->reset('url');
|
||||
|
|
|
|||
83
tests/Unit/Actions/RegisterDiscoveredPageActionTest.php
Normal file
83
tests/Unit/Actions/RegisterDiscoveredPageActionTest.php
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Actions;
|
||||
|
||||
use App\Actions\RegisterDiscoveredPageAction;
|
||||
use App\Enums\PageStatusEnum;
|
||||
use App\Models\Page;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Lvl0\FediDiscover\Config\InstanceType;
|
||||
use Lvl0\FediDiscover\Models\Instance;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RegisterDiscoveredPageActionTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_creates_page_with_url_and_discovered_status(): void
|
||||
{
|
||||
$action = new RegisterDiscoveredPageAction;
|
||||
|
||||
$page = $action('https://example.com/article');
|
||||
|
||||
$this->assertInstanceOf(Page::class, $page);
|
||||
$this->assertSame('https://example.com/article', $page->url);
|
||||
$this->assertSame(PageStatusEnum::Discovered, $page->status);
|
||||
$this->assertNull($page->instance_id);
|
||||
$this->assertDatabaseHas('pages', ['url' => 'https://example.com/article']);
|
||||
}
|
||||
|
||||
public function test_creates_page_with_provided_instance_id(): void
|
||||
{
|
||||
$instance = Instance::factory()
|
||||
->type(InstanceType::Mastodon)
|
||||
->enabled()
|
||||
->create();
|
||||
|
||||
$action = new RegisterDiscoveredPageAction;
|
||||
|
||||
$page = $action('https://example.com/fediverse-post', instanceId: $instance->id);
|
||||
|
||||
$this->assertInstanceOf(Page::class, $page);
|
||||
$this->assertSame($instance->id, $page->instance_id);
|
||||
$this->assertDatabaseHas('pages', [
|
||||
'url' => 'https://example.com/fediverse-post',
|
||||
'instance_id' => $instance->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_returns_existing_page_when_url_already_exists(): void
|
||||
{
|
||||
$existing = Page::factory()->createQuietly([
|
||||
'url' => 'https://example.com/seen-before',
|
||||
'status' => PageStatusEnum::Discovered,
|
||||
]);
|
||||
|
||||
$action = new RegisterDiscoveredPageAction;
|
||||
|
||||
$returned = $action('https://example.com/seen-before');
|
||||
|
||||
$this->assertSame($existing->id, $returned->id);
|
||||
$this->assertDatabaseCount('pages', 1);
|
||||
}
|
||||
|
||||
public function test_existing_page_status_not_overwritten_on_duplicate_call(): void
|
||||
{
|
||||
Page::factory()->createQuietly([
|
||||
'url' => 'https://example.com/already-fetched',
|
||||
'status' => PageStatusEnum::Fetched,
|
||||
]);
|
||||
|
||||
$action = new RegisterDiscoveredPageAction;
|
||||
|
||||
$returned = $action('https://example.com/already-fetched');
|
||||
|
||||
$this->assertSame(PageStatusEnum::Fetched, $returned->status);
|
||||
$this->assertDatabaseHas('pages', [
|
||||
'url' => 'https://example.com/already-fetched',
|
||||
'status' => PageStatusEnum::Fetched,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue