internal linking
This commit is contained in:
+35
-11
@@ -3,9 +3,11 @@
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Tool;
|
||||
use App\Support\FaviconResolver;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@@ -16,20 +18,25 @@ class MirrorToolLogo implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(public Tool $tool, public string $sourceUrl) {}
|
||||
public function __construct(public Tool $tool) {}
|
||||
|
||||
public function handle(): void
|
||||
public function handle(FaviconResolver $resolver): void
|
||||
{
|
||||
// The tool may have been re-saved with a different logo_url (or one
|
||||
// already mirrored) since this job was queued; only proceed if it's
|
||||
// still pointing at the URL we were asked to mirror.
|
||||
if ($this->tool->fresh()?->logo_url !== $this->sourceUrl) {
|
||||
$tool = $this->tool->fresh();
|
||||
|
||||
// The tool may have been deleted, or already mirrored by an earlier
|
||||
// run of this same job, since this was queued.
|
||||
if (! $tool || $tool->hasLocalLogo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$response = Http::timeout(10)->get($this->sourceUrl);
|
||||
// logo_url is a hint, not a guarantee -- it's often a guessed
|
||||
// `{domain}/favicon.ico` that 404s or isn't actually an image.
|
||||
// Fall back to properly resolving the site's real favicon.
|
||||
$response = ($tool->logo_url ? $this->fetchImage($tool->logo_url) : null)
|
||||
?? $this->fetchImage($resolver->resolve($tool->url));
|
||||
|
||||
if (! $response->successful() || ! str_starts_with((string) $response->header('Content-Type'), 'image/')) {
|
||||
if (! $response) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,13 +45,30 @@ class MirrorToolLogo implements ShouldQueue
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/webp' => 'webp',
|
||||
'image/x-icon', 'image/vnd.microsoft.icon' => 'ico',
|
||||
default => 'svg' === pathinfo(parse_url($this->sourceUrl, PHP_URL_PATH) ?? '', PATHINFO_EXTENSION) ? 'svg' : 'png',
|
||||
default => 'png',
|
||||
};
|
||||
|
||||
$path = "tools/{$this->tool->slug}-".Str::random(8).".{$extension}";
|
||||
$path = "tools/{$tool->slug}-".Str::random(8).".{$extension}";
|
||||
|
||||
Storage::disk('public')->put($path, $response->body());
|
||||
|
||||
$this->tool->update(['logo_url' => Storage::disk('public')->url($path)]);
|
||||
$tool->update(['logo_url' => Storage::disk('public')->url($path)]);
|
||||
}
|
||||
|
||||
private function fetchImage(?string $url): ?Response
|
||||
{
|
||||
if (! $url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = Http::timeout(10)->get($url);
|
||||
} catch (\Throwable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $response->successful() && str_starts_with((string) $response->header('Content-Type'), 'image/')
|
||||
? $response
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user