| @ -1,4 +1,5 @@ | |||||
| APP_DEBUG=false | APP_DEBUG=false | ||||
| APP_LOCALE=en | |||||
| DIRECTUS_API_URL= | DIRECTUS_API_URL= | ||||
| DIRECTUS_API_TOKEN= | DIRECTUS_API_TOKEN= | ||||
| @ -0,0 +1,53 @@ | |||||
| <?php | |||||
| namespace App\Controllers; | |||||
| use App\Controllers\DirectusControllerAbstract; | |||||
| use App\Repositories\SiteRepository; | |||||
| use App\Repositories\PostRepository; | |||||
| /** | |||||
| * controller for render feed of posts | |||||
| * | |||||
| * | |||||
| * @author Björn Hase, Tentakelfabrik | |||||
| * @license http://opensource.org/licenses/MIT The MIT License | |||||
| * @link https://gitea.tentakelfabrik.de/Tentakelfabrik/super-gear-directus | |||||
| * | |||||
| */ | |||||
| class FeedController extends DirectusControllerAbstract | |||||
| { | |||||
| private $limit = 20; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| protected $page = [ | |||||
| 'data' => [ | |||||
| 'view' => 'rss' | |||||
| ] | |||||
| ]; | |||||
| /** | |||||
| * get single page from slug | |||||
| * | |||||
| * | |||||
| * @param string $slug | |||||
| */ | |||||
| public function indexAction() | |||||
| { | |||||
| $siteRepository = new SiteRepository(); | |||||
| $site = $siteRepository->findOne(); | |||||
| $postRepository = new PostRepository(); | |||||
| $posts = $postRepository->find($this->limit); | |||||
| // change type | |||||
| header('Content-Type: text/xml'); | |||||
| $this->render($this->page, [ | |||||
| 'site' => $site, | |||||
| 'posts' => $posts | |||||
| ]); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,36 @@ | |||||
| <?php | |||||
| namespace App\Controllers; | |||||
| use App\Controllers\DirectusControllerAbstract; | |||||
| use App\Repositories\PostRepository; | |||||
| /** | |||||
| * controller for page items from directus | |||||
| * | |||||
| * | |||||
| * @author Björn Hase, Tentakelfabrik | |||||
| * @license http://opensource.org/licenses/MIT The MIT License | |||||
| * @link https://gitea.tentakelfabrik.de/Tentakelfabrik/super-gear-directus | |||||
| * | |||||
| */ | |||||
| class PostController extends DirectusControllerAbstract | |||||
| { | |||||
| /** | |||||
| * get single page from slug | |||||
| * | |||||
| * | |||||
| * @param string $slug | |||||
| */ | |||||
| public function getAction($slug) | |||||
| { | |||||
| $repository = new PostRepository(); | |||||
| $post = $repository->findOneBySlug($slug); | |||||
| if (count($post['data']) === 0) { | |||||
| $this->app->redirect('/404'); | |||||
| } else { | |||||
| $this->render($post); | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -1,51 +0,0 @@ | |||||
| <?php | |||||
| namespace App\Repositories; | |||||
| use Exception; | |||||
| /** | |||||
| * Manager Class to create Repository Objects that | |||||
| * are located in App\Repositories\ | |||||
| * | |||||
| * | |||||
| * @author Björn Hase, Tentakelfabrik | |||||
| * @license http://opensource.org/licenses/MIT The MIT License | |||||
| * @link https://gitea.tentakelfabrik.de/Tentakelfabrik/super-gear-directus | |||||
| * | |||||
| */ | |||||
| class Manager | |||||
| { | |||||
| /** | |||||
| * naming of Repository | |||||
| * @var string | |||||
| */ | |||||
| const NAMESPACE = 'App\Repositories\\'; | |||||
| /** | |||||
| * naming of Repository | |||||
| * @var string | |||||
| */ | |||||
| const REPOSITORY_SUFFIX = 'Repository'; | |||||
| /** | |||||
| * getting repository object | |||||
| * | |||||
| * @param string $repositoryClass | |||||
| * @return AbstractRepository | |||||
| */ | |||||
| public static function get($repositoryName) | |||||
| { | |||||
| $repositoryClass = self::NAMESPACE.$repositoryName.self::REPOSITORY_SUFFIX; | |||||
| if (!class_exists($repositoryClass)) { | |||||
| throw new Exception('Repository Class '.$repositoryClass.' not exists!'); | |||||
| } | |||||
| // create respository object | |||||
| $repository = new $repositoryClass(); | |||||
| return $repository; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,83 @@ | |||||
| <?php | |||||
| namespace App\Repositories; | |||||
| use App\Repositories\RepositoryAbstract; | |||||
| /** | |||||
| * request pages items from directus | |||||
| * | |||||
| * @author Björn Hase, Tentakelfabrik | |||||
| * @license http://opensource.org/licenses/MIT The MIT License | |||||
| * @link https://gitea.tentakelfabrik.de/Tentakelfabrik/super-gear-directus | |||||
| * | |||||
| */ | |||||
| class PostRepository extends RepositoryAbstract | |||||
| { | |||||
| /** endpoint */ | |||||
| protected $endpoint = 'posts'; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| public function find($limit = 20) | |||||
| { | |||||
| return $this->queryBuilder | |||||
| ->fields([ | |||||
| 'title', | |||||
| 'slug', | |||||
| 'lead', | |||||
| 'content', | |||||
| 'view', | |||||
| 'date_created', | |||||
| 'published_at', | |||||
| 'media_teaser.id', | |||||
| 'media_teaser.description' | |||||
| ]) | |||||
| ->aliases('template', 'view') | |||||
| ->filter([ | |||||
| 'status' => 'published', | |||||
| 'published_at' => [ | |||||
| '_nnull' => 'true' | |||||
| ] | |||||
| ]) | |||||
| ->sort(['published_at']) | |||||
| ->find(); | |||||
| } | |||||
| /** | |||||
| * find single page with a slug, | |||||
| * page must be published | |||||
| * | |||||
| * @param string $slug | |||||
| * @return array | |||||
| */ | |||||
| public function findOneBySlug($slug) | |||||
| { | |||||
| return $this->queryBuilder | |||||
| ->fields([ | |||||
| 'title', | |||||
| 'slug', | |||||
| 'lead', | |||||
| 'content', | |||||
| 'view', | |||||
| 'meta', | |||||
| 'date_created', | |||||
| 'published_at', | |||||
| 'media_teaser.id', | |||||
| 'media_teaser.description', | |||||
| 'media_hero.id', | |||||
| 'media_hero.description', | |||||
| ]) | |||||
| ->aliases('template', 'view') | |||||
| ->filter([ | |||||
| 'status' => 'published', | |||||
| 'published_at' => [ | |||||
| '_nnull' => 'true' | |||||
| ], | |||||
| 'slug' => $slug | |||||
| ]) | |||||
| ->findOne(); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,53 @@ | |||||
| @extends('layout') | |||||
| {{-- pretend duplicate content --}} | |||||
| @push('head') | |||||
| <meta name="robots" content="noindex,follow" /> | |||||
| @endpush | |||||
| {{-- inject helper for content & repositories --}} | |||||
| @inject('markdownHelper', 'App\Helpers\MarkdownHelper') | |||||
| @inject('postRepository', 'App\Repositories\PostRepository') | |||||
| @php | |||||
| $posts = $postRepository->find(); | |||||
| @endphp | |||||
| @section('content') | |||||
| <h1> | |||||
| {{ $page['data']['title'] }} | |||||
| </h1> | |||||
| <div class="content"> | |||||
| {!! $markdownHelper->parse($page['data']['content']) !!} | |||||
| </div> | |||||
| @if (count($posts) > 0) | |||||
| @foreach($posts['data'] as $post) | |||||
| <a class="post" href="/blog/{{ $post['slug'] }}"> | |||||
| <header class="post__header"> | |||||
| <h2 class="post__title"> | |||||
| {{ $post['title'] }} | |||||
| </h2> | |||||
| @include('partials.date', ['post' => $post]) | |||||
| @include('partials.readtime', ['post' => $post]) | |||||
| @if (isset($post['media_teaser']['id'])) | |||||
| <div class="post__teaser"> | |||||
| <img src="{{ assetsUrl($post['media_teaser']['id']) }}" alt="{{ $post['media_teaser']['description'] }}" /> | |||||
| </div> | |||||
| @endif | |||||
| </header> | |||||
| <div class="content post__lead"> | |||||
| {!! $markdownHelper->parse($post['lead']) !!} | |||||
| </div> | |||||
| </div> | |||||
| @endforeach | |||||
| @else | |||||
| <div class="post"> | |||||
| <p> | |||||
| Nothing! | |||||
| </p> | |||||
| </div> | |||||
| @endif | |||||
| @endsection | |||||
| @ -0,0 +1,5 @@ | |||||
| <div class="post__date"> | |||||
| <time datetime="{{ $post['published_at'] }}"> | |||||
| {{ Carbon\Carbon::parse($post['published_at'])->diffForHumans() }} | |||||
| </time> | |||||
| </div> | |||||
| @ -0,0 +1,10 @@ | |||||
| @php | |||||
| $content = $post['lead'].$post['content']; | |||||
| $readtime = (new \Mtownsend\ReadTime\ReadTime($content))->timeOnly(true)->setTranslation([ | |||||
| 'minute' => '' | |||||
| ])->get(); | |||||
| @endphp | |||||
| <div class="post__readtime"> | |||||
| Reading time {{ $readtime }} Minutes | |||||
| </div> | |||||
| @ -0,0 +1,17 @@ | |||||
| @extends('layout') | |||||
| @inject('markdownHelper', 'App\Helpers\MarkdownHelper') | |||||
| @section('content') | |||||
| <h1> | |||||
| {{ $page['data']['title'] }} | |||||
| </h1> | |||||
| <div class="content content--lead"> | |||||
| {!! $markdownHelper->parse($page['data']['lead']) !!} | |||||
| </div> | |||||
| <div class="content"> | |||||
| {!! $markdownHelper->parse($page['data']['content']) !!} | |||||
| </div> | |||||
| @endsection | |||||
| @ -0,0 +1,38 @@ | |||||
| @inject('markdownHelper', 'App\Helpers\MarkdownHelper') | |||||
| @php | |||||
| if (isset($_SERVER['HTTPS'])) { | |||||
| $http = 'https'; | |||||
| } else { | |||||
| $http = 'http'; | |||||
| } | |||||
| $base_url = $http.'://'.$_SERVER['SERVER_NAME']; | |||||
| @endphp | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> | |||||
| <channel> | |||||
| <title>{{ $site['data']['title'] }}</title> | |||||
| <atom:link href="{{ $base_url }}/feed" rel="self" type="application/rss+xml" /> | |||||
| <link>{{ $base_url }}/blog</link> | |||||
| <description>{{ $site['data']['description'] }}</description> | |||||
| <lastBuildDate>{{ date(DATE_RSS) }}</lastBuildDate> | |||||
| <language>{{ $_ENV['APP_LOCALE'] }}-{{ strtoupper($_ENV['APP_LOCALE']) }}</language> | |||||
| @foreach($posts['data'] as $post) | |||||
| <item> | |||||
| <title>{{ $post['title'] }}</title> | |||||
| <link>{{ $base_url.'/blog/'.$post['slug'] }}</link> | |||||
| <pubDate>{{ date(DATE_RSS, strtotime($post['published_at'])) }}</pubDate> | |||||
| <description> | |||||
| <![CDATA[ | |||||
| {!! $markdownHelper->parse($post['lead']) !!} | |||||
| {!! $markdownHelper->parse($post['content']) !!} | |||||
| ]]> | |||||
| </description> | |||||
| <guid isPermaLink="false">{{ $post['slug'] }}</guid> | |||||
| </item> | |||||
| @endforeach | |||||
| </channel> | |||||
| </rss> | |||||