From 0195814219c6ec98b36351353c7a3d7ff5bab3b2 Mon Sep 17 00:00:00 2001 From: Jonny Barnes Date: Sat, 20 Jun 2020 16:47:39 +0100 Subject: [PATCH] Add jf2 feeds for notes and blog posts --- app/Http/Controllers/FeedsController.php | 85 ++++++++++++++++++++++-- routes/web.php | 2 + tests/Feature/FeedsTest.php | 42 ++++++++++++ 3 files changed, 125 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/FeedsController.php b/app/Http/Controllers/FeedsController.php index 530b0af0..945609fc 100644 --- a/app/Http/Controllers/FeedsController.php +++ b/app/Http/Controllers/FeedsController.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace App\Http\Controllers; use App\Models\{Article, Note}; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Response; class FeedsController extends Controller @@ -12,7 +13,7 @@ class FeedsController extends Controller /** * Returns the blog RSS feed. * - * @return \Illuminate\Http\Response + * @return Response */ public function blogRss(): Response { @@ -27,7 +28,7 @@ class FeedsController extends Controller /** * Returns the blog Atom feed. * - * @return \Illuminate\Http\Response + * @return Response */ public function blogAtom(): Response { @@ -41,7 +42,7 @@ class FeedsController extends Controller /** * Returns the notes RSS feed. * - * @return \Illuminate\Http\Response + * @return Response */ public function notesRss(): Response { @@ -56,7 +57,7 @@ class FeedsController extends Controller /** * Returns the notes Atom feed. * - * @return \Illuminate\Http\Response + * @return Response */ public function notesAtom(): Response { @@ -133,4 +134,80 @@ class FeedsController extends Controller return $data; } + + /** + * Returns the blog JF2 feed. + * + * @return JsonResponse + */ + public function blogJf2(): JsonResponse + { + $articles = Article::where('published', '1')->latest('updated_at')->take(20)->get(); + $items = []; + foreach ($articles as $article) { + $items[] = [ + 'type' => 'entry', + 'published' => $article->created_at, + 'uid' => config('app.url') . $article->link, + 'url' => config('app.url') . $article->link, + 'content' => [ + 'text' => $article->main, + 'html' => $article->html, + ], + 'post-type' => 'article', + ]; + } + + return response()->json([ + 'type' => 'feed', + 'name' => 'Blog feed for ' . config('app.name'), + 'url' => url('/blog'), + 'author' => [ + 'type' => 'card', + 'name' => config('user.displayname'), + 'url' => config('app.longurl'), + ], + 'children' => $items, + ], 200, [ + 'Content-Type' => 'application/jf2feed+json', + ]); + } + + /** + * Returns the notes JF2 feed. + * + * @return JsonResponse + */ + public function notesJf2(): JsonResponse + { + $notes = Note::latest()->take(20)->get(); + $items = []; + foreach ($notes as $note) { + $items[] = [ + 'type' => 'entry', + 'published' => $note->created_at, + 'uid' => $note->longurl, + 'url' => $note->longurl, + 'content' => [ + 'text' => $note->getRawOriginal('note'), + 'html' => $note->note, + ], + 'post-type' => 'note', + ]; + } + + return response()->json([ + 'type' => 'feed', + 'name' => 'Notes feed for ' . config('app.name'), + 'url' => url('/notes'), + 'author' => [ + 'type' => 'card', + 'name' => config('user.displayname'), + 'url' => config('app.longurl'), + ], + 'children' => $items, + ], 200, [ + 'Content-Type' => 'application/jf2feed+json', + ]); + } } diff --git a/routes/web.php b/routes/web.php index 39ac2d41..de53f1a0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -108,6 +108,7 @@ Route::group(['domain' => config('url.longurl')], function () { Route::get('/feed.rss', 'FeedsController@blogRss'); Route::get('/feed.atom', 'FeedsController@blogAtom'); Route::get('/feed.json', 'FeedsController@blogJson'); + Route::get('/feed.jf2', 'Feedscontroller@blogJf2'); Route::get('/s/{id}', 'ArticlesController@onlyIdInURL'); Route::get('/{year?}/{month?}', 'ArticlesController@index'); Route::get('/{year}/{month}/{slug}', 'ArticlesController@show'); @@ -119,6 +120,7 @@ Route::group(['domain' => config('url.longurl')], function () { Route::get('/feed.rss', 'FeedsController@notesRss'); Route::get('/feed.atom', 'FeedsController@notesAtom'); Route::get('/feed.json', 'FeedsController@notesJson'); + Route::get('/feed.jf2', 'FeedsController@notesJf2'); Route::get('/{id}', 'NotesController@show'); Route::get('/tagged/{tag}', 'NotesController@tagged'); }); diff --git a/tests/Feature/FeedsTest.php b/tests/Feature/FeedsTest.php index 37c51a27..1c3c8bd2 100644 --- a/tests/Feature/FeedsTest.php +++ b/tests/Feature/FeedsTest.php @@ -39,6 +39,27 @@ class FeedsTest extends TestCase $response->assertHeader('Content-Type', 'application/atom+xml; charset=utf-8'); } + /** @test */ + public function blog_jf2_feed() + { + $response = $this->get('/blog/feed.jf2'); + $response->assertHeader('Content-Type', 'application/jf2feed+json'); + $response->assertJson([ + 'type' => 'feed', + 'name' => 'Blog feed for ' . config('app.name'), + 'url' => url('/blog'), + 'author' => [ + 'type' => 'card', + 'name' => config('user.displayname'), + 'url' => config('app.longurl'), + ], + 'children' => [[ + 'type' => 'entry', + 'post-type' => 'article', + ]] + ]); + } + /** * Test the notes RSS feed. * @@ -72,6 +93,27 @@ class FeedsTest extends TestCase $response->assertHeader('Content-Type', 'application/json'); } + /** @test */ + public function notes_jf2_feed() + { + $response = $this->get('/notes/feed.jf2'); + $response->assertHeader('Content-Type', 'application/jf2feed+json'); + $response->assertJson([ + 'type' => 'feed', + 'name' => 'Notes feed for ' . config('app.name'), + 'url' => url('/notes'), + 'author' => [ + 'type' => 'card', + 'name' => config('user.displayname'), + 'url' => config('app.longurl'), + ], + 'children' => [[ + 'type' => 'entry', + 'post-type' => 'note', + ]] + ]); + } + /** * Each JSON feed item must have one of `content_text` or `content_html`, * and whichever one they have can’t be `null`.