From e4e7cbc7e4944b08d74f5752de337ba7700367f4 Mon Sep 17 00:00:00 2001
From: Daniel Karbach <daniel.karbach@localhorst.tv>
Date: Sun, 20 Aug 2023 13:29:10 +0200
Subject: [PATCH] serverside tech init

---
 app/Http/Controllers/TechniqueController.php |  22 ++++
 app/Http/Kernel.php                          | 116 ++++++++++---------
 app/Http/Middleware/LanguageMiddleware.php   |  34 ++++++
 app/Models/Technique.php                     |  11 ++
 resources/views/app.blade.php                |   5 +-
 routes/web.php                               |  23 ++++
 6 files changed, 153 insertions(+), 58 deletions(-)
 create mode 100644 app/Http/Middleware/LanguageMiddleware.php

diff --git a/app/Http/Controllers/TechniqueController.php b/app/Http/Controllers/TechniqueController.php
index 59559a9..1d51aff 100644
--- a/app/Http/Controllers/TechniqueController.php
+++ b/app/Http/Controllers/TechniqueController.php
@@ -6,6 +6,7 @@ use App\Models\Technique;
 use App\Models\TechniqueMap;
 use App\Models\TechniqueTranslation;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\ModelNotFoundException;
 use Illuminate\Http\Request;
 
 class TechniqueController extends Controller
@@ -68,6 +69,27 @@ class TechniqueController extends Controller
 		return $result->toJson();
 	}
 
+	public function web(Request $request, $type, $name) {
+		$tech = Technique::where('type', '=', $type)->where('name', '=', $name)->first();
+		if ($tech) {
+			return view('app')
+				->with('title', $tech->getTranslatedProperty('title'))
+				->with('description', $tech->getTranslatedProperty('short'));
+		}
+		$url_map = [
+			'dungeon' => 'dungeons',
+			'location' => 'locations',
+			'mode' => 'modes',
+			'ruleset' => 'rulesets',
+			'tech' => 'tech',
+		];
+		$tech = Technique::where('name', '=', $name)->whereIn('type', array_keys($url_map))->first();
+		if ($tech && isset($url_map[$tech->type])) {
+			return redirect('/'.$url_map[$tech->type].'/'.$tech->name);
+		}
+		throw new ModelNotFoundException();
+	}
+
 	private function applyLocalizedValues($validatedData, $content) {
 		foreach (['attribution', 'description', 'short', 'title'] as $name) {
 			if (isset($validatedData[$name])) {
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index c8803ca..1466d94 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -4,64 +4,66 @@ namespace App\Http;
 
 use Illuminate\Foundation\Http\Kernel as HttpKernel;
 
-class Kernel extends HttpKernel
-{
-    /**
-     * The application's global HTTP middleware stack.
-     *
-     * These middleware are run during every request to your application.
-     *
-     * @var array<int, class-string|string>
-     */
-    protected $middleware = [
-        // \App\Http\Middleware\TrustHosts::class,
-        \App\Http\Middleware\TrustProxies::class,
-        \Illuminate\Http\Middleware\HandleCors::class,
-        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
-        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
-        \App\Http\Middleware\TrimStrings::class,
-        // \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
-    ];
+class Kernel extends HttpKernel {
 
-    /**
-     * The application's route middleware groups.
-     *
-     * @var array<string, array<int, class-string|string>>
-     */
-    protected $middlewareGroups = [
-        'web' => [
-            \App\Http\Middleware\EncryptCookies::class,
-            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
-            \Illuminate\Session\Middleware\StartSession::class,
-            // \Illuminate\Session\Middleware\AuthenticateSession::class,
-            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
-            \App\Http\Middleware\VerifyCsrfToken::class,
-            \Illuminate\Routing\Middleware\SubstituteBindings::class,
-        ],
+	/**
+	 * The application's global HTTP middleware stack.
+	 *
+	 * These middleware are run during every request to your application.
+	 *
+	 * @var array<int, class-string|string>
+	 */
+	protected $middleware = [
+		// \App\Http\Middleware\TrustHosts::class,
+		\App\Http\Middleware\TrustProxies::class,
+		\Illuminate\Http\Middleware\HandleCors::class,
+		\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
+		\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
+		\App\Http\Middleware\LanguageMiddleware::class,
+		\App\Http\Middleware\TrimStrings::class,
+		// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
+	];
 
-        'api' => [
-            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
-            'throttle:api',
-            \Illuminate\Routing\Middleware\SubstituteBindings::class,
-        ],
-    ];
+	/**
+	 * The application's route middleware groups.
+	 *
+	 * @var array<string, array<int, class-string|string>>
+	 */
+	protected $middlewareGroups = [
+		'web' => [
+			\App\Http\Middleware\EncryptCookies::class,
+			\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+			\Illuminate\Session\Middleware\StartSession::class,
+			// \Illuminate\Session\Middleware\AuthenticateSession::class,
+			\Illuminate\View\Middleware\ShareErrorsFromSession::class,
+			\App\Http\Middleware\VerifyCsrfToken::class,
+			\Illuminate\Routing\Middleware\SubstituteBindings::class,
+		],
+
+		'api' => [
+			\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
+			'throttle:api',
+			\Illuminate\Routing\Middleware\SubstituteBindings::class,
+		],
+	];
+
+	/**
+	 * The application's route middleware.
+	 *
+	 * These middleware may be assigned to groups or used individually.
+	 *
+	 * @var array<string, class-string|string>
+	 */
+	protected $routeMiddleware = [
+		'auth' => \App\Http\Middleware\Authenticate::class,
+		'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
+		'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
+		'can' => \Illuminate\Auth\Middleware\Authorize::class,
+		'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
+		'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
+		'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
+		'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
+		'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+	];
 
-    /**
-     * The application's route middleware.
-     *
-     * These middleware may be assigned to groups or used individually.
-     *
-     * @var array<string, class-string|string>
-     */
-    protected $routeMiddleware = [
-        'auth' => \App\Http\Middleware\Authenticate::class,
-        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
-        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
-        'can' => \Illuminate\Auth\Middleware\Authorize::class,
-        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
-        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
-        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
-        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
-        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
-    ];
 }
diff --git a/app/Http/Middleware/LanguageMiddleware.php b/app/Http/Middleware/LanguageMiddleware.php
new file mode 100644
index 0000000..b8f9837
--- /dev/null
+++ b/app/Http/Middleware/LanguageMiddleware.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\App;
+
+class LanguageMiddleware {
+
+	/**
+	 * Handle an incoming request.
+	 *
+	 * @param  \Illuminate\Http\Request  $request
+	 * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
+	 * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
+	 */
+	public function handle(Request $request, Closure $next) {
+		$lang = $request->input('lng');
+		if ($lang && in_array($lang, $this->available)) {
+			App::setLocale($lang);
+			return $next($request);
+		}
+		$lang = $request->header('Accept-Language');
+		if ($lang && in_array($lang, $this->available)) {
+			App::setLocale($lang);
+			return $next($request);
+		}
+		return $next($request);
+	}
+
+	private $available = ['de', 'en'];
+
+}
diff --git a/app/Models/Technique.php b/app/Models/Technique.php
index 2eb0a94..0b25e47 100644
--- a/app/Models/Technique.php
+++ b/app/Models/Technique.php
@@ -4,6 +4,7 @@ namespace App\Models;
 
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\App;
 
 class Technique extends Model
 {
@@ -28,6 +29,16 @@ class Technique extends Model
 		return $this->hasMany(TechniqueTranslation::class);
 	}
 
+	public function getTranslatedProperty($prop, $lang = null) {
+		if (is_null($lang)) $lang = App::getLocale();
+		foreach ($this->translations as $translation) {
+			if ($translation->locale == $lang) {
+				return $translation->{$prop};
+			}
+		}
+		return $this->{$prop};
+	}
+
 	protected $casts = [
 		'index' => 'boolean',
 		'requirements' => 'array',
diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php
index 5ad20de..63acef3 100644
--- a/resources/views/app.blade.php
+++ b/resources/views/app.blade.php
@@ -4,8 +4,11 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 
-		<title>{{ config('app.name', 'Laravel') }}</title>
+		<title>{{ $title ?? config('app.name', 'Laravel') }}</title>
 		<link rel="icon" href="{{ URL::asset('favicon.ico') }}" type="image/x-icon">
+@isset($description)
+		<meta name="description" content="{{ $description }}">
+@endisset
 
 		<script src="{{ mix('js/manifest.js') }}" defer></script>
 		<script src="{{ mix('js/vendor.js') }}" defer></script>
diff --git a/routes/web.php b/routes/web.php
index 450d21f..782fb6d 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -2,6 +2,9 @@
 
 use App\Http\Controllers\DiscordController;
 use App\Http\Controllers\SitemapXmlController;
+use App\Http\Controllers\TechniqueController;
+use App\Models\Event;
+use App\Models\Technique;
 use Illuminate\Support\Facades\Route;
 
 /*
@@ -17,6 +20,26 @@ use Illuminate\Support\Facades\Route;
 
 Route::get('/sitemap.xml', [SitemapXmlController::class, 'index']);
 
+Route::get('/dungeons/{name}', function($name) {
+	return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'dungeon', 'name' => $name]);
+});
+
+Route::get('/locations/{name}', function($name) {
+	return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'location', 'name' => $name]);
+});
+
+Route::get('/modes/{name}', function($name) {
+	return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'mode', 'name' => $name]);
+});
+
+Route::get('/rulesets/{name}', function($name) {
+	return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'ruleset', 'name' => $name]);
+});
+
+Route::get('/tech/{name}', function($name) {
+	return app()->call('App\Http\Controllers\TechniqueController@web', ['type' => 'tech', 'name' => $name]);
+});
+
 Route::view('/{path?}', 'app')->where('path', '.*');
 
 Route::group(['prefix' => config('larascord.prefix'), 'middleware' => ['web']], function() {
-- 
2.39.5