Sort out web syndication feeds, and add JSON feeds, fixes issue #52
This commit is contained in:
parent
b234e2133b
commit
e848486b33
11 changed files with 301 additions and 41 deletions
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
134
app/Http/Controllers/FeedsController.php
Normal file
134
app/Http/Controllers/FeedsController.php
Normal 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;
|
||||
}
|
||||
}
|
10
app/Note.php
10
app/Note.php
|
@ -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.
|
||||
*
|
||||
|
|
20
resources/views/articles/atom.blade.php
Normal file
20
resources/views/articles/atom.blade.php
Normal 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>
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
20
resources/views/notes/atom.blade.php
Normal file
20
resources/views/notes/atom.blade.php
Normal 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>
|
26
resources/views/notes/rss.blade.php
Normal file
26
resources/views/notes/rss.blade.php
Normal 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>
|
|
@ -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');
|
||||
});
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
77
tests/Feature/FeedsTest.php
Normal file
77
tests/Feature/FeedsTest.php
Normal 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');
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue