mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-01-17 13:18:21 +01:00
Add RSS feeds for public lists accessible via guest mode (#197)
This commit is contained in:
parent
1c98fc39ce
commit
b8135ac162
61
app/Http/Controllers/Guest/FeedController.php
Normal file
61
app/Http/Controllers/Guest/FeedController.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Guest;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Link;
|
||||
use App\Models\LinkList;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class FeedController extends Controller
|
||||
{
|
||||
public function links(Request $request)
|
||||
{
|
||||
$links = Link::publicOnly()->latest()->with('user')->get();
|
||||
$meta = [
|
||||
'title' => 'LinkAce Links',
|
||||
'link' => $request->fullUrl(),
|
||||
'updated' => now()->toRfc3339String(),
|
||||
'id' => $request->fullUrl(),
|
||||
];
|
||||
|
||||
return new Response(view('guest.links.feed', [
|
||||
'meta' => $meta,
|
||||
'links' => $links,
|
||||
]), 200, ['Content-Type' => 'application/xml']);
|
||||
}
|
||||
|
||||
public function lists(Request $request)
|
||||
{
|
||||
$lists = LinkList::publicOnly()->latest()->with('user')->get();
|
||||
$meta = [
|
||||
'title' => 'LinkAce Lists',
|
||||
'link' => $request->fullUrl(),
|
||||
'updated' => now()->toRfc3339String(),
|
||||
'id' => $request->fullUrl(),
|
||||
];
|
||||
|
||||
return new Response(view('guest.lists.feed', [
|
||||
'meta' => $meta,
|
||||
'lists' => $lists,
|
||||
]), 200, ['Content-Type' => 'application/xml']);
|
||||
}
|
||||
|
||||
public function tags(Request $request)
|
||||
{
|
||||
$tags = Tag::publicOnly()->latest()->with('user')->get();
|
||||
$meta = [
|
||||
'title' => 'LinkAce Links',
|
||||
'link' => $request->fullUrl(),
|
||||
'updated' => now()->toRfc3339String(),
|
||||
'id' => $request->fullUrl(),
|
||||
];
|
||||
|
||||
return new Response(view('guest.tags.feed', [
|
||||
'meta' => $meta,
|
||||
'tags' => $tags,
|
||||
]), 200, ['Content-Type' => 'application/xml']);
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ return [
|
||||
|
||||
'menu' => 'Menu',
|
||||
'entries' => 'Entries',
|
||||
'feed' => 'Feed',
|
||||
|
||||
'continue_adding' => 'Continue Adding',
|
||||
|
||||
|
1
resources/views/components/icon/feed.blade.php
Normal file
1
resources/views/components/icon/feed.blade.php
Normal file
@ -0,0 +1 @@
|
||||
<svg {{ $attributes->merge(['class' => 'icon', 'viewBox' =>'0 0 448 512', 'xmlns' => 'http://www.w3.org/2000/svg', 'aria-hidden' => 'true', 'focusable' => 'false']) }}><path d="M128.081 415.959c0 35.369-28.672 64.041-64.041 64.041S0 451.328 0 415.959s28.672-64.041 64.041-64.041 64.04 28.673 64.04 64.041zm175.66 47.25c-8.354-154.6-132.185-278.587-286.95-286.95C7.656 175.765 0 183.105 0 192.253v48.069c0 8.415 6.49 15.472 14.887 16.018 111.832 7.284 201.473 96.702 208.772 208.772.547 8.397 7.604 14.887 16.018 14.887h48.069c9.149.001 16.489-7.655 15.995-16.79zm144.249.288C439.596 229.677 251.465 40.445 16.503 32.01 7.473 31.686 0 38.981 0 48.016v48.068c0 8.625 6.835 15.645 15.453 15.999 191.179 7.839 344.627 161.316 352.465 352.465.353 8.618 7.373 15.453 15.999 15.453h48.068c9.034-.001 16.329-7.474 16.005-16.504z"/></svg>
|
After Width: | Height: | Size: 830 B |
20
resources/views/guest/links/feed.blade.php
Normal file
20
resources/views/guest/links/feed.blade.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?= '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL ?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>{{ $meta['title'] }}</title>
|
||||
<link href="{{ $meta['link'] }}"/>
|
||||
<updated>{{ $meta['updated'] }}</updated>
|
||||
<id>{{ $meta['id'] }}</id>
|
||||
@foreach($links as $link)
|
||||
<entry>
|
||||
<title><![CDATA[{{ $link->title }}]]></title>
|
||||
<id>{{ $link->url }}</id>
|
||||
<author>
|
||||
<name> <![CDATA[{{ $link->user->name }}]]></name>
|
||||
</author>
|
||||
<summary type="html">
|
||||
<![CDATA[{!! $link->markdownDescription !!}]]>
|
||||
</summary>
|
||||
<updated>{{ $link->updated_at->toRfc3339String() }}</updated>
|
||||
</entry>
|
||||
@endforeach
|
||||
</feed>
|
@ -1,12 +1,20 @@
|
||||
@extends('layouts.guest')
|
||||
|
||||
@push('html-header')
|
||||
<link rel="alternate" type="application/atom+xml" href="{{ route('guest.links.feed') }}">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
|
||||
<header class="d-flex align-items-center">
|
||||
<h3 class="mb-0">
|
||||
<h3 class="mb-0 mr-3">
|
||||
@lang('link.links')
|
||||
</h3>
|
||||
<div class="dropdown ml-auto">
|
||||
<a href="{{ route('guest.links.feed') }}" class="ml-auto btn btn-sm btn-outline-secondary">
|
||||
<x-icon.feed/>
|
||||
<span class="sr-only">@lang('linkace.add')</span>
|
||||
</a>
|
||||
<div class="dropdown ml-1">
|
||||
@include('models.links.partials.index-order-dropdown', ['baseRoute' => 'guest.links.index'])
|
||||
</div>
|
||||
</header>
|
||||
|
21
resources/views/guest/lists/feed.blade.php
Normal file
21
resources/views/guest/lists/feed.blade.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?= '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL ?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>{{ $meta['title'] }}</title>
|
||||
<link href="{{ $meta['link'] }}"/>
|
||||
<updated>{{ $meta['updated'] }}</updated>
|
||||
<id>{{ $meta['id'] }}</id>
|
||||
@foreach($lists as $list)
|
||||
<entry>
|
||||
<title><![CDATA[{{ $list->name }}]]></title>
|
||||
<link rel="alternate" href="{{ route('guest.lists.show', ['list' => $list]) }}"/>
|
||||
<id>{{ url($list->id) }}</id>
|
||||
<author>
|
||||
<name> <![CDATA[{{ $list->user->name }}]]></name>
|
||||
</author>
|
||||
<summary type="html">
|
||||
<![CDATA[{!! $list->description !!}]]>
|
||||
</summary>
|
||||
<updated>{{ $list->updated_at->toRfc3339String() }}</updated>
|
||||
</entry>
|
||||
@endforeach
|
||||
</feed>
|
@ -1,12 +1,20 @@
|
||||
@extends('layouts.guest')
|
||||
|
||||
@push('html-header')
|
||||
<link rel="alternate" type="application/atom+xml" href="{{ route('guest.lists.feed') }}">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
|
||||
<header class="d-flex align-items-center">
|
||||
<h3 class="mb-0 mr-3">
|
||||
@lang('list.lists')
|
||||
</h3>
|
||||
<div class="dropdown ml-auto">
|
||||
<a href="{{ route('guest.lists.feed') }}" class="ml-auto btn btn-sm btn-outline-secondary">
|
||||
<x-icon.feed/>
|
||||
<span class="sr-only">@lang('linkace.add')</span>
|
||||
</a>
|
||||
<div class="dropdown ml-1">
|
||||
@include('models.lists.partials.index-order-dropdown', ['baseRoute' => 'lists.index'])
|
||||
</div>
|
||||
</header>
|
||||
|
17
resources/views/guest/tags/feed.blade.php
Normal file
17
resources/views/guest/tags/feed.blade.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?= '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL ?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>{{ $meta['title'] }}</title>
|
||||
<link href="{{ $meta['link'] }}"/>
|
||||
<updated>{{ $meta['updated'] }}</updated>
|
||||
<id>{{ $meta['id'] }}</id>
|
||||
@foreach($tags as $tag)
|
||||
<entry>
|
||||
<title><![CDATA[{{ $tag->name }}]]></title>
|
||||
<id>{{ route('tags.show', ['tag' => $tag]) }}</id>
|
||||
<author>
|
||||
<name> <![CDATA[{{ $tag->user->name }}]]></name>
|
||||
</author>
|
||||
<updated>{{ $tag->updated_at->toRfc3339String() }}</updated>
|
||||
</entry>
|
||||
@endforeach
|
||||
</feed>
|
@ -1,11 +1,19 @@
|
||||
@extends('layouts.guest')
|
||||
|
||||
@push('html-header')
|
||||
<link rel="alternate" type="application/atom+xml" href="{{ route('guest.tags.feed') }}">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
|
||||
<header class="d-flex align-items-center">
|
||||
<h3 class="mb-0">
|
||||
<h3 class="mb-0 mr-3">
|
||||
@lang('tag.tags')
|
||||
</h3>
|
||||
<a href="{{ route('guest.tags.feed') }}" class="ml-auto btn btn-sm btn-outline-secondary">
|
||||
<x-icon.feed/>
|
||||
<span class="sr-only">@lang('linkace.add')</span>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<div class="card my-3 mb-3">
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
<title>{{ systemsettings('system_page_title') ?: config('app.name', 'LinkAce') }}</title>
|
||||
|
||||
@stack('html-header')
|
||||
@include('partials.favicon')
|
||||
|
||||
@include('partials.configure-darkmode')
|
||||
|
@ -11,6 +11,7 @@ use App\Http\Controllers\App\UserSettingsController;
|
||||
use App\Http\Controllers\CronController;
|
||||
use App\Http\Controllers\FetchController;
|
||||
use App\Http\Controllers\FrontController;
|
||||
use App\Http\Controllers\Guest\FeedController;
|
||||
use App\Http\Controllers\Guest\LinkController as GuestLinkController;
|
||||
use App\Http\Controllers\Guest\ListController as GuestListController;
|
||||
use App\Http\Controllers\Guest\TagController as GuestTagController;
|
||||
@ -129,6 +130,10 @@ Route::group(['middleware' => ['auth']], function () {
|
||||
// Guest access routes
|
||||
Route::prefix('guest')->middleware(['guestaccess'])->group(function () {
|
||||
|
||||
Route::get('links/feed', [FeedController::class, 'links'])->name('guest.links.feed');
|
||||
Route::get('lists/feed', [FeedController::class, 'lists'])->name('guest.lists.feed');
|
||||
Route::get('tags/feed', [FeedController::class, 'tags'])->name('guest.tags.feed');
|
||||
|
||||
Route::resource('links', GuestLinkController::class)
|
||||
->only(['index'])
|
||||
->names([
|
||||
|
61
tests/Controller/Guest/FeedControllerTest.php
Normal file
61
tests/Controller/Guest/FeedControllerTest.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Controller\Guest;
|
||||
|
||||
use App\Models\Link;
|
||||
use App\Models\LinkList;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class FeedControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Setting::create([
|
||||
'key' => 'system_guest_access',
|
||||
'value' => '1',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testLinkFeed(): void
|
||||
{
|
||||
$linkPublic = Link::factory()->create(['is_private' => false]);
|
||||
$linkPrivate = Link::factory()->create(['is_private' => true]);
|
||||
|
||||
$response = $this->get('guest/links/feed');
|
||||
|
||||
$response->assertOk()
|
||||
->assertSee($linkPublic->url)
|
||||
->assertDontSee($linkPrivate->url);
|
||||
}
|
||||
|
||||
public function testListFeed(): void
|
||||
{
|
||||
$listPublic = LinkList::factory()->create(['is_private' => false]);
|
||||
$listPrivate = LinkList::factory()->create(['is_private' => true]);
|
||||
|
||||
$response = $this->get('guest/lists/feed');
|
||||
|
||||
$response->assertOk()
|
||||
->assertSee($listPublic->name)
|
||||
->assertDontSee($listPrivate->name);
|
||||
}
|
||||
|
||||
public function testTagsFeed(): void
|
||||
{
|
||||
$tagPublic = Tag::factory()->create(['is_private' => false]);
|
||||
$tagPrivate = Tag::factory()->create(['is_private' => true]);
|
||||
|
||||
$response = $this->get('guest/tags/feed');
|
||||
|
||||
$response->assertOk()
|
||||
->assertSee($tagPublic->name)
|
||||
->assertDontSee($tagPrivate->name);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user