Skip to content

Commit f35edd3

Browse files
authored
Automatic generation of social images (#549)
* Install intervention/image * Add command to generate image * Add route to generate social image * Render social share image * Apply PHP CS Fixer changes * Update formatting
1 parent 5b1b009 commit f35edd3

File tree

11 files changed

+356
-2
lines changed

11 files changed

+356
-2
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Jobs\GenerateSocialShareImage;
6+
use App\Models\Article;
7+
8+
class SocialImageController extends Controller
9+
{
10+
public function __invoke(Article $article)
11+
{
12+
return $this->dispatchNow(new GenerateSocialShareImage($article));
13+
}
14+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace App\Jobs;
4+
5+
use App\Models\Article;
6+
use Intervention\Image\ImageManager;
7+
8+
final class GenerateSocialShareImage
9+
{
10+
private $article;
11+
12+
const TEXT_X_POSITION = 50;
13+
14+
const TEXT_Y_POSITION = 100;
15+
16+
const TEXT_COLOUR = '#161e2e';
17+
18+
const FONT = 'inter.ttf';
19+
20+
const FONT_SIZE = 50;
21+
22+
const CHARACTERS_PER_LINE = 30;
23+
24+
const TEMPLATE = 'social-share-template.png';
25+
26+
const CACHE_LIFETIME = 43200;
27+
28+
public function __construct(Article $article)
29+
{
30+
$this->article = $article;
31+
}
32+
33+
public function handle(ImageManager $image)
34+
{
35+
$text = wordwrap($this->article->title(), self::CHARACTERS_PER_LINE);
36+
37+
return $image->cache(function ($image) use ($text) {
38+
$image->make(storage_path('images/' . self::TEMPLATE))
39+
->text($text, self::TEXT_X_POSITION, self::TEXT_Y_POSITION, function ($font) {
40+
$font->file(storage_path('fonts/' . self::FONT));
41+
$font->size(self::FONT_SIZE);
42+
$font->color(self::TEXT_COLOUR);
43+
});
44+
}, self::CACHE_LIFETIME, true)->response('png');
45+
}
46+
}

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"fideloper/proxy": "^4.2",
1515
"fruitcake/laravel-cors": "^1.0",
1616
"guzzlehttp/guzzle": "^6.3",
17+
"intervention/image": "^2.5",
18+
"intervention/imagecache": "^2.4",
1719
"laravel/framework": "^7.0",
1820
"laravel/horizon": "^4.0",
1921
"laravel/socialite": "^4.3",

composer.lock

Lines changed: 258 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/macros/blade.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@
2121
Blade::directive('title', function ($expression) {
2222
return "<?php \$title = $expression ?>";
2323
});
24+
25+
Blade::directive('shareImage', function ($expression) {
26+
return "<?php \$shareImage = $expression ?>";
27+
});

resources/views/articles/show.blade.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@title($article->title())
2+
@shareImage(route('articles.image', $article->slug()))
23

34
@extends('layouts.default')
45

resources/views/layouts/_social.blade.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,11 @@
77
<!-- Facebook sharing -->
88
<meta property="og:url" content="{{ url()->current() }}" />
99
<meta property="og:title" content="{{ isset($title) ? $title.' | ' : '' }}{{ config('app.name') }}" />
10-
<meta property="og:image" content="{{ asset('images/laravelio-share.png') }}" />
10+
11+
@if (isset($shareImage))
12+
<meta property="og:image" content="{{ $shareImage }}" />
13+
@else
14+
<meta property="og:image" content="{{ asset('images/laravelio-share.png') }}" />
15+
@endif
16+
1117
<!-- /Facebook sharing -->

routes/web.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
Route::get('privacy', 'HomeController@privacy')->name('privacy');
1212
Route::get('bin/{paste?}', 'HomeController@pastebin');
1313

14+
Route::get('articles/{article}/social.png', 'SocialImageController')->name('articles.image');
15+
1416
// Authentication
1517
Route::namespace('Auth')->group(function () {
1618
// Sessions

storage/fonts/inter.ttf

287 KB
Binary file not shown.
34.5 KB
Loading

0 commit comments

Comments
 (0)