Blade-Component: Webmentions
source link: https://gummibeer.dev/blog/2020/blade-component-webmentions/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Photo by NordWood Themes on Unsplash
- Dec 17th, 2020
- 5.5 min read
Blade-Component: Webmentions
While developing my new website including this blog I've decided to go with a static site and don't want to handle comments and so on. But I still wanted to include user contributed content below the articles.
So I searched for solutions and found some articles by my friends at Spatie how they've implemented webmention.io.
As I've created this site with Laravel 7 I wanted to create a simple to use Blade Component that will do everything for me. The result is a PHP file that loads the webmentions and maps them into three collections - likes, reposts and comments - and a blade file that renders them.
The approach is pretty simple as webmention does the hard job for us. At first I load all webmentions for the given or current URL. As the API is paginated I'm using a do-while
loop to load all pages. After that I'm splitting the results in three collections.
namespace App\View\Components;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Illuminate\View\Component;
class Webmentions extends Component
{
public Collection $likes;
public Collection $reposts;
public Collection $comments;
public function __construct(?string $url = null)
{
$url ??= request()->url();
$webmentions = collect();
$page = 0;
do {
$entries = Http::get('https://webmention.io/api/mentions.jf2', [
'token' => config('services.webmention.token'),
'domain' => parse_url($url, PHP_URL_HOST),
'per-page' => 100,
'page' => $page,
])->json()['children'] ?? [];
$webmentions->push(...$entries);
$page++;
} while (count($entries) >= 100);
$webmentions = $webmentions
->filter(fn (array $entry): bool => trim(parse_url($entry['wm-target'], PHP_URL_PATH), '/') === trim(parse_url($url, PHP_URL_PATH), '/'));
$this->likes = $webmentions
->filter(fn (array $entry): bool => $entry['wm-property'] === 'like-of')
->mapInto(Like::class)
->sortByDesc('date');
$this->reposts = $webmentions
->filter(function (array $entry): bool {
if ($entry['wm-property'] === 'repost-of') {
return true;
}
if ($entry['wm-property'] === 'mention-of') {
return empty($entry['content']['text']);
}
return false;
})
->mapInto(Repost::class)
->sortByDesc('date');
$this->comments = $webmentions
->filter(fn (array $entry): bool => in_array($entry['wm-property'], ['mention-of', 'in-reply-to']))
->reject(fn (array $entry): bool => empty($entry['content']['text']))
->mapInto(Comment::class)
->sortBy('date');
}
public function render()
{
return view('components.webmentions');
}
}
And the Blade view is super opinionated so I will reduce it to the important part. You automatically have access to all public properties of the component class. To use autocompletion in my blade files I'm always adding the variables to the top of the blade file as a doc-comment.
<?php /** @var \Illuminate\View\ComponentAttributeBag $attributes */ ?>
<?php /** @var \Illuminate\Support\Collection|\App\Webmentions\Like[] $likes */ ?>
<?php /** @var \Illuminate\Support\Collection|\App\Webmentions\Repost[] $reposts */ ?>
<?php /** @var \Illuminate\Support\Collection|\App\Webmentions\Comment[] $comments */ ?>
With this you can loop over the items and render them however you want. And can use the new blade component wherever you need it.
<x-webmentions :url="$url" />
17 likes
5 reposts
Comments
-
π A Blade component to render Webmentions (by @devgummibeer)
gummibeer.dev/blog/2020/bladβ¦
#laravel #blade #webmentions -
Thanks for sharing! π€©π₯³
Could be that a package for this is incoming. π -
It was worth the read just for learning that you can use phpdoc in blade files. π
-
See kids, if you procrastinate long enough someone else will do it for you π
-
There's a typo in the tweet (additional s): webmention.io π
-
Twitter should do a ping check for links in tweets. π
Thanks! π
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK