@ -0,0 +1,4 @@ | |||||
APP_DEBUG=false | |||||
DIRECTUS_API_URL= | |||||
DIRECTUS_API_TOKEN= |
@ -1,7 +1,123 @@ | |||||
composer.phar | |||||
# ---> Node | |||||
# Logs | |||||
logs | |||||
*.log | |||||
npm-debug.log* | |||||
yarn-debug.log* | |||||
yarn-error.log* | |||||
lerna-debug.log* | |||||
# Diagnostic reports (https://nodejs.org/api/report.html) | |||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | |||||
# Runtime data | |||||
pids | |||||
*.pid | |||||
*.seed | |||||
*.pid.lock | |||||
# Directory for instrumented libs generated by jscoverage/JSCover | |||||
lib-cov | |||||
# Coverage directory used by tools like istanbul | |||||
coverage | |||||
*.lcov | |||||
# nyc test coverage | |||||
.nyc_output | |||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | |||||
.grunt | |||||
# Bower dependency directory (https://bower.io/) | |||||
bower_components | |||||
# node-waf configuration | |||||
.lock-wscript | |||||
# Compiled binary addons (https://nodejs.org/api/addons.html) | |||||
build/Release | |||||
# Dependency directories | |||||
node_modules/ | |||||
jspm_packages/ | |||||
# Snowpack dependency directory (https://snowpack.dev/) | |||||
web_modules/ | |||||
# TypeScript cache | |||||
*.tsbuildinfo | |||||
# Optional npm cache directory | |||||
.npm | |||||
# Optional eslint cache | |||||
.eslintcache | |||||
# Microbundle cache | |||||
.rpt2_cache/ | |||||
.rts2_cache_cjs/ | |||||
.rts2_cache_es/ | |||||
.rts2_cache_umd/ | |||||
# Optional REPL history | |||||
.node_repl_history | |||||
# Output of 'npm pack' | |||||
*.tgz | |||||
/vendor/ | |||||
node_modules | |||||
# Yarn Integrity file | |||||
.yarn-integrity | |||||
# dotenv environment variables file | |||||
.env | .env | ||||
*.log | |||||
rysnc_exclude | |||||
.env.test | |||||
# parcel-bundler cache (https://parceljs.org/) | |||||
.cache | |||||
.parcel-cache | |||||
# Next.js build output | |||||
.next | |||||
out | |||||
# Nuxt.js build / generate output | |||||
.nuxt | |||||
# Gatsby files | |||||
.cache/ | |||||
# Comment in the public line in if your project uses Gatsby and not Next.js | |||||
# https://nextjs.org/blog/next-9-1#public-directory-support | |||||
# public | |||||
# vuepress build output | |||||
.vuepress/dist | |||||
# Serverless directories | |||||
.serverless/ | |||||
# FuseBox cache | |||||
.fusebox/ | |||||
# DynamoDB Local files | |||||
.dynamodb/ | |||||
# TernJS port file | |||||
.tern-port | |||||
# Stores VSCode versions used for testing VSCode extensions | |||||
.vscode-test | |||||
# yarn v2 | |||||
.yarn/cache | |||||
.yarn/unplugged | |||||
.yarn/build-state.yml | |||||
.yarn/install-state.gz | |||||
.pnp.* | |||||
vendor | |||||
storage/cache | |||||
!storage/cache/.gitkeep | |||||
@ -0,0 +1,56 @@ | |||||
<?php | |||||
namespace App\Controllers; | |||||
use App\Controllers\DirectusControllerAbstract; | |||||
use App\Repositories\Manager; | |||||
/** | |||||
* 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 PageController extends DirectusControllerAbstract | |||||
{ | |||||
/** default view */ | |||||
protected $defaultView = 'page/default'; | |||||
/** 404 */ | |||||
protected $page404 = [ | |||||
'data' => [ | |||||
'title' => '404', | |||||
'view' => 'page/404' | |||||
] | |||||
]; | |||||
/** | |||||
* get single page from slug | |||||
* | |||||
* | |||||
* @param string $slug | |||||
*/ | |||||
public function getAction($slug = NULL) | |||||
{ | |||||
$repository = Manager::get('Page'); | |||||
$page = $repository->findOneBySlug($slug); | |||||
if ($page['data'] === NULL) { | |||||
$this->app>redirect('/404', 301); | |||||
} else { | |||||
$this->render($page); | |||||
} | |||||
} | |||||
/** | |||||
* if page not found | |||||
* | |||||
*/ | |||||
public function notFoundAction() | |||||
{ | |||||
$this->render($this->page404); | |||||
} | |||||
} |
@ -0,0 +1,30 @@ | |||||
<?php | |||||
namespace App\Flight; | |||||
use Flight; | |||||
/** | |||||
* abstract FlightAbstract to get instance of flight engine | |||||
* | |||||
* @author Björn Hase, Tentakelfabrik | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitea.tentakelfabrik.de/Tentakelfabrik/super-gear-directus | |||||
* | |||||
*/ | |||||
abstract class FlightAbstract | |||||
{ | |||||
/** object of flight */ | |||||
protected $app; | |||||
/** | |||||
* getting object of flight | |||||
* | |||||
* | |||||
*/ | |||||
public function __construct() | |||||
{ | |||||
$this->app = Flight::app(); | |||||
} | |||||
} |
@ -1,16 +1,18 @@ | |||||
<?php | <?php | ||||
namespace SuperGear\Directus\Helpers; | |||||
namespace App\Helpers; | |||||
use Parsedown; | use Parsedown; | ||||
/** | /** | ||||
* Helper to extend Parsedown | |||||
* Helper to extend Parsedown | |||||
* | |||||
* @author Björn Hase, Tentakelfabrik | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitea.tentakelfabrik.de/Tentakelfabrik/super-gear-directus | |||||
* | * | ||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/directus GitHub Repository | |||||
*/ | */ | ||||
class MarkdownHelper extends Parsedown | class MarkdownHelper extends Parsedown | ||||
{ | { | ||||
/** | /** |
@ -1,18 +1,20 @@ | |||||
<?php | <?php | ||||
namespace SuperGear\Directus\Repositories; | |||||
namespace App\Repositories; | |||||
use Exception; | use Exception; | ||||
/** | /** | ||||
* Manager Class to create Repository Objects that | |||||
* are located in App\Repositories\ | |||||
* Manager Class to create Repository Objects that | |||||
* are located in App\Repositories\ | |||||
* | * | ||||
* | * | ||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/super-gear-directus GitHub Repository | |||||
* @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 | class Manager | ||||
{ | { | ||||
/** | /** |
@ -0,0 +1,48 @@ | |||||
<?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 PageRepository extends RepositoryAbstract | |||||
{ | |||||
/** endpoint */ | |||||
protected $endpoint = 'pages'; | |||||
/** | |||||
* find single page with a slug, | |||||
* page must be published | |||||
* | |||||
* @param string $slug | |||||
* @return array | |||||
*/ | |||||
public function findOneBySlug($slug) | |||||
{ | |||||
// if slug not set, search for empty slug | |||||
if (!$slug) { | |||||
$slug = [ '_null' => 'true' ]; | |||||
} | |||||
return $this->queryBuilder | |||||
->fields([ | |||||
'title', 'slug', 'content', 'view', 'meta', | |||||
'media_teaser.*', | |||||
'media_hero.*' | |||||
]) | |||||
->aliases('view', 'template') | |||||
->filter([ | |||||
'status' => 'published', | |||||
'slug' => $slug | |||||
]) | |||||
->findOne(); | |||||
} | |||||
} |
@ -0,0 +1,36 @@ | |||||
<?php | |||||
namespace 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 | |||||
* | |||||
*/ | |||||
abstract class RepositoryAbstract | |||||
{ | |||||
/** endpoint for request */ | |||||
protected $endpoint; | |||||
/** queryBuilder from pirectus */ | |||||
protected $queryBuilder; | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
public function __construct() | |||||
{ | |||||
$pirectus = \Flight::pirectus(); | |||||
if ($pirectus) { | |||||
$this->queryBuilder = $pirectus->items($this->endpoint); | |||||
} else { | |||||
throw new \Exception('Error! Pirectus not initialized!'); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,37 @@ | |||||
<?php | |||||
// adding functions | |||||
require_once(__DIR__.'/Functions/Blade.php'); | |||||
// adding env | |||||
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__.'/../'); | |||||
$dotenv->load(); | |||||
// display all errors if debug is true | |||||
if ($_ENV['APP_DEBUG'] === true) { | |||||
error_reporting(E_ALL); | |||||
ini_set('display_errors', 1); | |||||
} | |||||
// create app | |||||
$flight = Flight::app(); | |||||
// setting view path | |||||
$flight->set('flight.views.path', __DIR__.'/../resources/views'); | |||||
// adding blade for templates | |||||
$flight->register('view', 'Jenssegers\Blade\Blade', [ $flight->get('flight.views.path'), __DIR__.'/../storage/cache']); | |||||
$flight->map('render', function($view, $data) { | |||||
echo Flight::view()->make($view, $data); | |||||
}); | |||||
// setting path | |||||
$flight->set('basePath', __DIR__.'/../'); | |||||
$flight->set('publicPath', __DIR__.'/../public'); | |||||
$flight->set('storagePath', __DIR__.'/../storage'); | |||||
// adding pirectus | |||||
$flight->register('pirectus', 'Pirectus\Pirectus', [ $_ENV['DIRECTUS_API_URL'], [ | |||||
'auth' => new \Pirectus\Auth\TokenAuth($_ENV['DIRECTUS_API_TOKEN']) | |||||
] | |||||
]); |
@ -0,0 +1,10 @@ | |||||
<?php | |||||
require __DIR__.'/../vendor/autoload.php'; | |||||
require __DIR__.'/../app/bootstrap.php'; | |||||
// default routes | |||||
$flight->route('GET /404', array(new App\Controllers\PageController, 'notFoundAction')); | |||||
$flight->route('GET /(@slug:[a-zA-Z0-9_-])', array(new App\Controllers\PageController, 'getAction')); | |||||
$flight->start(); |
@ -0,0 +1,38 @@ | |||||
@inject('pageRepository', 'App\Repositories\PageRepository') | |||||
@inject('markdownHelper', 'App\Helpers\MarkdownHelper') | |||||
@inject('slugify', 'Cocur\Slugify\Slugify') | |||||
<!DOCTYPE html> | |||||
<html lang="de-DE" class="no-js"> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> | |||||
<title> | |||||
Elina Penner | {{ $page['data']['title'] }} | |||||
</title> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||||
<link href="{{ (isset($_SERVER['HTTPS']) ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] }}" rel="canonical"> | |||||
<link href="{{ asset('/css/index.css') }}" rel="stylesheet" type="text/css"> | |||||
@stack('head') | |||||
</head> | |||||
<body class="{{ $slugify->slugify($page['data']['view']) }}"> | |||||
<header class="site-header"> | |||||
<h1 class="site-header__title"> | |||||
Super Gear Directus | |||||
</h1> | |||||
</header> | |||||
<main class="site-main"> | |||||
@yield('content') | |||||
</main> | |||||
<footer class="site-footer"> | |||||
</footer> | |||||
@stack('scripts') | |||||
</body> | |||||
</html> |
@ -0,0 +1,8 @@ | |||||
@extends('layout') | |||||
@section('header') | |||||
@endsection | |||||
@section('content') | |||||
Wrong? Go <a href="/">back</a>! | |||||
@endsection |
@ -0,0 +1,12 @@ | |||||
@extends('layout') | |||||
@inject('markdownHelper', 'App\Helpers\MarkdownHelper') | |||||
@section('content') | |||||
<h1> | |||||
{{ $page['data']['title'] }} | |||||
</h1> | |||||
<div class="content"> | |||||
{!! $markdownHelper->parse($page['data']['content']) !!} | |||||
</div> | |||||
@endsection |
@ -0,0 +1,3 @@ | |||||
<svg class="icon @if (isset($classes)) {{ implode(' ', $classes) }} @endif" aria-hidden="true" @if (isset($alt)) alt="{{ $alt }}" @endif > | |||||
<use xlink:href="/symbol-defs.svg#icon-{{ $icon }}"></use> | |||||
</svg> |
@ -1,114 +0,0 @@ | |||||
<?php | |||||
namespace SuperGear\Directus\Collections; | |||||
/** | |||||
* send request with curl to directus instance | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/directus GitHub Repository | |||||
* | |||||
*/ | |||||
class AbstractCollection | |||||
{ | |||||
/** url */ | |||||
private $url = NULL; | |||||
/** token */ | |||||
private $token = NULL; | |||||
/** curl */ | |||||
private $curl = NULL; | |||||
/** endpoint */ | |||||
protected $endpoint = NULL; | |||||
/** | |||||
* | |||||
* @param string $url | |||||
* @param string $token | |||||
*/ | |||||
public function __construct($url, $token) | |||||
{ | |||||
$this->url = $url; | |||||
$this->token = $token; | |||||
} | |||||
/** | |||||
* | |||||
* | |||||
* @param string $name | |||||
* @param array $parameters | |||||
* @return mixed | |||||
*/ | |||||
public function findOne($name, $parameters = []) | |||||
{ | |||||
// adding single to parameters | |||||
$parameters['single'] = true; | |||||
$response = $this->request($name, $this->endpoint, $parameters); | |||||
return $response; | |||||
} | |||||
/** | |||||
* | |||||
* | |||||
* @param string $name | |||||
* @param array $parameters | |||||
* @return mixed | |||||
* | |||||
*/ | |||||
public function find($name, $parameters = []) | |||||
{ | |||||
return $this->request($name, $this->endpoint, $parameters); | |||||
} | |||||
/** | |||||
* request $endpoint | |||||
* | |||||
* @param string $name | |||||
* @param string $endpoint | |||||
* @param array $parameters | |||||
* @return mixed | |||||
* | |||||
*/ | |||||
protected function request($name, $endpoint, $parameters = []) | |||||
{ | |||||
// init curl and setup token | |||||
$curl = curl_init(); | |||||
curl_setopt($curl, CURLOPT_HTTPHEADER, [ | |||||
'Accept: application/json', | |||||
'Content-Type: application/json', | |||||
'Authorization: Bearer '.$this->token | |||||
]); | |||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |||||
$response = []; | |||||
if (count($parameters) > 0) { | |||||
$query = http_build_query($parameters); | |||||
} | |||||
$url = $this->url.$endpoint.'/'.$name; | |||||
// query parameters are set, add them to url | |||||
if (isset($query)) { | |||||
$url = $url.'?'.$query; | |||||
} | |||||
curl_setopt($curl, CURLOPT_URL, $url); | |||||
$response = curl_exec($curl); | |||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE); | |||||
$info = curl_getinfo($curl); | |||||
curl_close($curl); | |||||
$response = json_decode($response, true); | |||||
return $response; | |||||
} | |||||
} |
@ -1,28 +0,0 @@ | |||||
<?php | |||||
namespace SuperGear\Directus\Collections; | |||||
/** | |||||
* endpoint "items" for directus | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/directus GitHub Repository | |||||
* | |||||
*/ | |||||
class ItemCollection extends AbstractCollection | |||||
{ | |||||
/** | |||||
* | |||||
* @param string $url | |||||
* @param string $token | |||||
*/ | |||||
public function __construct($url, $token) | |||||
{ | |||||
// adding endpoint for items | |||||
$this->endpoint = '/items'; | |||||
parent::__construct($url, $token); | |||||
} | |||||
} |
@ -1,27 +0,0 @@ | |||||
<?php | |||||
namespace SuperGear\Directus; | |||||
use Flight; | |||||
/** | |||||
* abstract FlightAbstract get instance of flight engine | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/super-gear-directus GitHub Repository | |||||
*/ | |||||
abstract class FlightAbstract | |||||
{ | |||||
/** object of flight */ | |||||
protected $app; | |||||
/** | |||||
* getting object of flight | |||||
* | |||||
*/ | |||||
public function __construct() | |||||
{ | |||||
$this->app = Flight::app(); | |||||
} | |||||
} |
@ -1,179 +0,0 @@ | |||||
<?php | |||||
namespace SuperGear\Directus\Repositories; | |||||
/** | |||||
* class for paginate request | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/directus GitHub Repository | |||||
* | |||||
*/ | |||||
abstract class PaginationRepositoryAbstract extends RepositoryAbstract | |||||
{ | |||||
/** current page */ | |||||
protected $page; | |||||
/** limit for request */ | |||||
protected $limit; | |||||
/** max pages */ | |||||
protected $maxPages; | |||||
/** pages that are visible */ | |||||
protected $showPages = 7; | |||||
/** | |||||
* setting max pages | |||||
* | |||||
* @param integer | |||||
* @param array | |||||
* | |||||
*/ | |||||
protected function setMaxPages($limit, $results) | |||||
{ | |||||
$this->maxPages = intval(round($results['meta']['filter_count'] / $limit)); | |||||
} | |||||
/** | |||||
* getting offset for request | |||||
* | |||||
* @param integer | |||||
* @return integer | |||||
* | |||||
*/ | |||||
protected function getOffset($page, $limit) | |||||
{ | |||||
return (($page - 1) * $limit); | |||||
} | |||||
/** | |||||
* get pages that are showing | |||||
* | |||||
* @param integer | |||||
* @return array | |||||
* | |||||
*/ | |||||
protected function getPages($page) | |||||
{ | |||||
// results | |||||
$pages = []; | |||||
// count of pages that can be shown | |||||
$showPages = $this->showPages; | |||||
// get avarage value to show pages | |||||
$averagePages = $this->showPages / 2; | |||||
// run throw all pages | |||||
for ($i = 1; $i <= $this->maxPages; $i++) { | |||||
// check if $page has to show | |||||
$show = false; | |||||
// show always first and last page | |||||
if ($i === 1 || $i === $this->maxPages) { | |||||
$show = true; | |||||
} | |||||
// if showing pages are aviable check if page can be shown | |||||
if ($show === false && $showPages > 0) { | |||||
// if page from 1 to avarage | |||||
if (($i <= $averagePages && $page <= $averagePages) || | |||||
// if page is less than maxPages | |||||
(($i >= ($maxPages - $averagePages)) && $page >= ($maxPages - $averagePages)) || | |||||
// put current pages as avarage value | |||||
($i >= ($page - $averagePages) && $i <= ($page + $averagePages))) { | |||||
$showPages--; | |||||
$show = true; | |||||
} | |||||
} | |||||
if ($show) { | |||||
$pages[] = $i; | |||||
} | |||||
} | |||||
return $pages; | |||||
} | |||||
/** | |||||
* if previous is possible | |||||
* | |||||
* @param integer $page | |||||
* | |||||
*/ | |||||
protected function getPrevious($page) | |||||
{ | |||||
$result = NULL; | |||||
if ($page > 1) { | |||||
$result = $page - 1; | |||||
} | |||||
return $result; | |||||
} | |||||
/** | |||||
* if next is possible | |||||
* | |||||
* @param integer $page | |||||
* | |||||
*/ | |||||
protected function getNext($page) | |||||
{ | |||||
$result = NULL; | |||||
if ($page < $this->maxPages) { | |||||
$result = $page + 1; | |||||
} | |||||
return $result; | |||||
} | |||||
/** | |||||
* prepare query to get limited items | |||||
* | |||||
* @param integer $page | |||||
* @param integer $limit | |||||
* @param array $query | |||||
* | |||||
*/ | |||||
protected function prepare($page, $limit, $query) | |||||
{ | |||||
// setting page and limit | |||||
$this->page = $page; | |||||
$this->limit = $limit; | |||||
return array_merge($query, [ | |||||
'offset' => $this->getOffset($this->page, $this->limit), | |||||
'limit' => $this->limit, | |||||
'meta' => 'result_count,filter_count,total_count' | |||||
]); | |||||
} | |||||
/** | |||||
* paginate results | |||||
* | |||||
* @param integer $page | |||||
* @param integer $limit | |||||
* @param array $results | |||||
* | |||||
*/ | |||||
protected function paginate($results) | |||||
{ | |||||
$this->setMaxPages($this->limit, $results); | |||||
$results['meta']['current'] = $this->page; | |||||
$results['meta']['previous'] = $this->getPrevious($this->page); | |||||
$results['meta']['next'] = $this->getNext($this->page); | |||||
$results['meta']['pages'] = $this->getPages($this->page); | |||||
$results['meta']['max_pages'] = $this->maxPages; | |||||
return $results; | |||||
} | |||||
} |
@ -1,38 +0,0 @@ | |||||
<?php | |||||
namespace SuperGear\Directus\Repositories; | |||||
use SuperGear\Directus\Collections\ItemCollection; | |||||
/** | |||||
* Abstract Repository to wrap ItemCollection | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/super-gear/super-gear-directus GitHub Repository | |||||
*/ | |||||
abstract class RepositoryAbstract | |||||
{ | |||||
/** name of the collection */ | |||||
protected $name; | |||||
/** client for itemCollection */ | |||||
protected $itemCollection; | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
public function __construct() | |||||
{ | |||||
if (!$this->name) { | |||||
throw new \Exception('$name is not set!'); | |||||
}; | |||||
$this->itemCollection = new ItemCollection( | |||||
env('DIRECTUS_API_URL'), | |||||
env('DIRECTUS_API_TOKEN') | |||||
); | |||||
} | |||||
} |