Sort out web syndication feeds, and add JSON feeds, fixes issue #52

This commit is contained in:
Jonny Barnes 2017-06-04 19:06:22 +01:00
parent b234e2133b
commit e848486b33
11 changed files with 301 additions and 41 deletions

View file

@ -51,19 +51,4 @@ class ArticlesController extends Controller
return redirect($article->link);
}
/**
* Returns the RSS feed.
*
* @return \Illuminate\Http\Response
*/
public function makeRSS()
{
$articles = Article::where('published', '1')->orderBy('updated_at', 'desc')->get();
$buildDate = $articles->first()->updated_at->toRssString();
return response()
->view('articles.rss', compact('articles', 'buildDate'), 200)
->header('Content-Type', 'application/rss+xml');
}
}

View file

@ -0,0 +1,134 @@
<?php
namespace App\Http\Controllers;
use App\Note;
use App\Article;
use Illuminate\Http\Request;
class FeedsController extends Controller
{
/**
* Returns the blog RSS feed.
*
* @return \Illuminate\Http\Response
*/
public function blogRss()
{
$articles = Article::where('published', '1')->latest('updated_at')->take(20)->get();
$buildDate = $articles->first()->updated_at->toRssString();
return response()
->view('articles.rss', compact('articles', 'buildDate'))
->header('Content-Type', 'application/rss+xml; charset=utf-8');
}
/**
* Returns the blog Atom feed.
*
* @return \Illuminate\Http\Response
*/
public function blogAtom()
{
$articles = Article::where('published', '1')->latest('updated_at')->take(20)->get();
return response()
->view('articles.atom', compact('articles'))
->header('Content-Type', 'application/atom+xml; charset=utf-8');
}
/**
* Returns the notes RSS feed.
*
* @return \Illuminate\Http\Response
*/
public function notesRss()
{
$notes = Note::latest()->take(20)->get();
$buildDate = $notes->first()->updated_at->toRssString();
return response()
->view('notes.rss', compact('notes', 'buildDate'))
->header('Content-Type', 'application/rss+xml; charset=utf-8');
}
/**
* Returns the notes Atom feed.
*
* @return \Illuminate\Http\Response
*/
public function notesAtom()
{
$notes = Note::latest()->take(20)->get();
return response()
->view('notes.atom', compact('notes'))
->header('Content-Type', 'application/atom+xml; charset=utf-8');
}
/**
* Returns the blog JSON feed.
*
* @return \Illuminate\Http\response
*/
public function blogJson()
{
$articles = Article::where('published', '1')->latest('updated_at')->take(20)->get();
$data = [
'version' => 'https://jsonfeed.org/version/1',
'title' => 'The JSON Feed for ' . config('app.display_name') . 's blog',
'home_page_url' => config('app.url') . '/blog',
'feed_url' => config('app.url') . '/blog/feed.json',
'items' => []
];
foreach ($articles as $key => $article) {
$data['items'][$key] = [
'id' => config('app.url') . $article->link,
'title' => $article->title,
'url' => config('app.url') . $article->link,
'content_html' => $article->main,
'date_published' => $article->created_at->tz('UTC')->toRfc3339String(),
'date_modified' => $article->updated_at->tz('UTC')->toRfc3339String(),
'author' => [
'name' => config('app.display_name')
]
];
}
return $data;
}
/**
* Returns the notes JSON feed.
*
* @return \Illuminate\Http\response
*/
public function notesJson()
{
$notes = Note::latest()->take(20)->get();
$data = [
'version' => 'https://jsonfeed.org/version/1',
'title' => 'The JSON Feed for ' . config('app.display_name') . 's notes',
'home_page_url' => config('app.url') . '/notes',
'feed_url' => config('app.url') . '/notes/feed.json',
'items' => []
];
foreach ($notes as $key => $note) {
$data['items'][$key] = [
'id' => $note->longurl,
'title' => $note->getOriginal('note'),
'url' => $note->longurl,
'content_html' => $note->note,
'date_published' => $note->created_at->tz('UTC')->toRfc3339String(),
'date_modified' => $note->updated_at->tz('UTC')->toRfc3339String(),
'author' => [
'name' => config('app.display_name')
]
];
}
return $data;
}
}

View file

@ -168,6 +168,16 @@ class Note extends Model
return config('app.shorturl') . '/notes/' . $this->nb60id;
}
/**
* Get the pubdate value for RSS feeds.
*
* @return string
*/
public function getPubdateAttribute()
{
return $this->updated_at->toRSSString();
}
/**
* Get the relavent client name assocaited with the client id.
*

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Atom feed for {{ config('app.display_name') }}s blog</title>
<link rel="self" href="{{ config('app.url') }}/blog/feed.atom" />
<id>{{ config('app.url')}}/blog</id>
<updated>{{ $articles[0]->updated_at->toAtomString() }}</updated>
@foreach($articles as $article)
<entry>
<title>{{ $article->title }}</title>
<link href="{{ config('app.url') }}{{ $article->link }}" />
<id>{{ config('app.url') }}{{ $article->link }}</id>
<updated>{{ $article->updated_at->toAtomString() }}</updated>
<content>{{ $article->main }}</content>
<author>
<name>{{ config('app.display_name') }}</name>
</author>
</entry>
@endforeach
</feed>

View file

@ -2,9 +2,9 @@
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ config('app.display_name') }}</title>
<atom:link href="{{ config('app.url') }}/feed" rel="self" type="application/rss+xml" />
<atom:link href="{{ config('app.url') }}/blog/feed.rss" rel="self" type="application/rss+xml" />
<description>An RSS feed of the blog posts found on {{ config('url.longurl') }}</description>
<link>{{ config('app.url') }}</link>
<link>{{ config('app.url') }}/blog</link>
<lastBuildDate>{{ $buildDate }}</lastBuildDate>
<ttl>1800</ttl>

View file

@ -6,6 +6,12 @@
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="/assets/frontend/normalize.css">
<link rel="stylesheet" href="/assets/css/app.css">
<link rel="alternate" type="application/rss+xml" title="Blog RSS Feed" href="/blog/feed.rss">
<link rel="alternate" type="application/atom+xml" title="Blog Atom Feed" href="/blog/feed.atom">
<link rel="alternate" type="application/json" title="Blog JSON Feed" href="/blog/feed.json">
<link rel="alternate" type="application/rss+xml" title="Notes RSS Feed" href="/notes/feed.rss">
<link rel="alternate" type="application/atom+xml" title="Notes Atom Feed" href="/notes/feed.atom">
<link rel="alternate" type="application/json" title="Notes JSON Feed" href="/notes/feed.json">
<link rel="openid.server" href="https://indieauth.com/openid">
<link rel="openid.delegate" href="{{ config('app.url') }}">
<link rel="authorization_endpoint" href="https://indieauth.com/auth">

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Atom feed for {{ config('app.display_name') }}s notes</title>
<link rel="self" href="{{ config('app.url') }}/notes/feed.atom" />
<id>{{ config('app.url')}}/notes</id>
<updated>{{ $notes[0]->updated_at->toAtomString() }}</updated>
@foreach($notes as $note)
<entry>
<title>{{ strip_tags($note->note) }}</title>
<link href="{{ $note->longurl }}" />
<id>{{ $note->longurl }}</id>
<updated>{{ $note->updated_at->toAtomString() }}</updated>
<content type="html">{{ $note->note }}</content>
<author>
<name>{{ config('app.display_name') }}</name>
</author>
</entry>
@endforeach
</feed>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ config('app.display_name') }}</title>
<atom:link href="{{ config('app.url') }}/notes/feed.rss" rel="self" type="application/rss+xml" />
<description>An RSS feed of the notes found on {{ config('url.longurl') }}</description>
<link>{{ config('app.url') }}/notes</link>
<lastBuildDate>{{ $buildDate }}</lastBuildDate>
<ttl>1800</ttl>
@foreach($notes as $note)
<item>
<title>{{ strip_tags($note->note) }}</title>
<description>
<![CDATA[
{!! $note->note !!}
]]>
</description>
<link>{{ $note->longurl }}</link>
<guid>{{ $note->longurl}}</guid>
<pubDate>{{ $note->pubdate }}</pubDate>
</item>
@endforeach
</channel>
</rss>

View file

@ -88,12 +88,18 @@ Route::group(['domain' => config('url.longurl')], function () {
});
//Blog pages using ArticlesController
Route::get('blog/feed.rss', 'FeedsController@blogRss');
Route::get('blog/feed.atom', 'FeedsController@blogAtom');
Route::get('blog/feed.json', 'FeedsController@blogJson');
Route::get('blog/s/{id}', 'ArticlesController@onlyIdInURL');
Route::get('blog/{year?}/{month?}', 'ArticlesController@index');
Route::get('blog/{year}/{month}/{slug}', 'ArticlesController@show');
//Notes pages using NotesController
Route::get('notes', 'NotesController@index');
Route::get('notes/feed.rss', 'FeedsController@notesRss');
Route::get('notes/feed.atom', 'FeedsController@notesAtom');
Route::get('notes/feed.json', 'FeedsController@notesJson');
Route::get('notes/{id}', 'NotesController@show');
Route::get('note/{id}', 'NotesController@redirect');
Route::get('notes/tagged/{tag}', 'NotesController@tagged');
@ -136,8 +142,6 @@ Route::group(['domain' => config('url.longurl')], function () {
Route::get('places', 'PlacesController@index');
Route::get('places/{slug}', 'PlacesController@show');
Route::get('feed', 'ArticlesController@makeRSS');
Route::get('search', 'SearchController@search');
});

View file

@ -1,22 +0,0 @@
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ArticlesRSSTest extends TestCase
{
/**
* Test the RSS feed.
*
* @return void
*/
public function test_rss_feed()
{
$response = $this->get('/feed');
$response->assertHeader('Content-Type', 'application/rss+xml');
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class FeedsTest extends TestCase
{
/**
* Test the blog RSS feed.
*
* @return void
*/
public function test_blog_rss_feed()
{
$response = $this->get('/blog/feed.rss');
$response->assertHeader('Content-Type', 'application/rss+xml; charset=utf-8');
}
/**
* Test the notes RSS feed.
*
* @return void
*/
public function test_notes_rss_feed()
{
$response = $this->get('/notes/feed.rss');
$response->assertHeader('Content-Type', 'application/rss+xml; charset=utf-8');
}
/**
* Test the blog RSS feed.
*
* @return void
*/
public function test_blog_atom_feed()
{
$response = $this->get('/blog/feed.atom');
$response->assertHeader('Content-Type', 'application/atom+xml; charset=utf-8');
}
/**
* Test the notes RSS feed.
*
* @return void
*/
public function test_notes_atom_feed()
{
$response = $this->get('/notes/feed.atom');
$response->assertHeader('Content-Type', 'application/atom+xml; charset=utf-8');
}
/**
* Test the blog JSON feed.
*
* @return void
*/
public function test_blog_json_feed()
{
$response = $this->get('/blog/feed.json');
$response->assertHeader('Content-Type', 'application/json');
}
/**
* Test the notes JSON feed.
*
* @return void
*/
public function test_notes_json_feed()
{
$response = $this->get('/notes/feed.json');
$response->assertHeader('Content-Type', 'application/json');
}
}