71 lines
2.2 KiB
PHP
71 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Article;
|
|
use App\Models\Feed;
|
|
use SimplePie\SimplePie;
|
|
|
|
class FeedFetcher
|
|
{
|
|
public function __construct(private OgImageResolver $ogResolver) {}
|
|
public function fetch(Feed $feed): void
|
|
{
|
|
$simplepie = new SimplePie();
|
|
$simplepie->set_feed_url($feed->url);
|
|
$simplepie->enable_cache(false); // you're doing your own caching in the DB
|
|
$simplepie->init();
|
|
|
|
if ($simplepie->error()) {
|
|
report(new \RuntimeException("Feed fetch failed for {$feed->url}: {$simplepie->error()}"));
|
|
return;
|
|
}
|
|
|
|
foreach ($simplepie->get_items() as $item) {
|
|
$imageUrl = $this->extractImage($item);
|
|
|
|
$attributes = [
|
|
'title' => strip_tags($item->get_title()),
|
|
'description' => strip_tags($item->get_description() ?? ''),
|
|
'link' => $item->get_permalink(),
|
|
'author' => $item->get_author()?->get_name(),
|
|
'published_at' => $item->get_date('Y-m-d H:i:s'),
|
|
];
|
|
|
|
if ($imageUrl) {
|
|
$attributes['image_url'] = $imageUrl;
|
|
}
|
|
|
|
$article = Article::updateOrCreate(
|
|
['feed_id' => $feed->id, 'guid' => $item->get_id()],
|
|
$attributes
|
|
);
|
|
|
|
if (! $article->image_url && ! $article->image_checked_at) {
|
|
$og = $this->ogResolver->resolve($article->link);
|
|
$article->update([
|
|
'image_url' => $og,
|
|
'image_checked_at' => now(),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function extractImage($item): ?string
|
|
{
|
|
$mediaContents = $item->get_item_tags('http://search.yahoo.com/mrss/', 'content');
|
|
|
|
if (empty($mediaContents)) {
|
|
$enclosure = $item->get_enclosure();
|
|
$link = $enclosure?->get_thumbnail() ?? $enclosure?->get_link();
|
|
return $link ? html_entity_decode($link) : null;
|
|
}
|
|
|
|
usort($mediaContents, fn ($a, $b) =>
|
|
(int) ($b['attribs']['']['width'] ?? 0) <=> (int) ($a['attribs']['']['width'] ?? 0)
|
|
);
|
|
|
|
return $mediaContents[0]['attribs']['']['url'] ?? null;
|
|
}
|
|
}
|