function ($query) { $query->select(['id', 'name']); }, 'category' => function ($query) { $query->with('translations'); }, 'translations' => function ($query) { $query ->where('locale', App::getLocale()); // ->whereDate('from', '<=', now()) //TODO: Exclude date queries ONLY for post Admins! // ->where( function($query) { // $query->whereDate('till', '>', now())->orWhereNull('till'); // }) }, ]) ->where('id', $id) ->firstOrFail(); if ($post->media) { $media = Post::find($id)->getFirstMedia('posts'); } if ($post->translations->count() >= 1) { if ($post->category->translations) { $category = $post->category->translations->where('locale', App::getLocale())->first()->name; } $update = Carbon::createFromTimeStamp(strtotime($post->translations->first()->updated_at))->isoFormat('LL'); } else { // No translation in current locale - check for fallback translations return $this->handleNoTranslation($post, $id); } // Use guest layout for non-authenticated users, app layout for authenticated users $viewName = Auth::check() ? 'posts.show' : 'posts.show-guest'; return ($post != null ? view($viewName, compact(['post','media','category','update'])) : abort(403)); } /** * Handle case when no translation exists for current locale. * Check for available translations in other locales and offer fallback. */ private function handleNoTranslation($post, $postId) { // Get all available translations for this post (active ones) $availableTranslation = PostTranslation::where('post_id', $postId) ->whereDate('from', '<=', now()) ->where(function ($query) { $query->whereDate('till', '>', now())->orWhereNull('till'); }) ->first(); $viewData = [ 'fallbackLocale' => null, 'fallbackLanguageName' => null, 'fallbackUrl' => null, 'post' => $post, ]; if ($availableTranslation) { // Found an available translation in another locale $fallbackLocale = $availableTranslation->locale; $fallbackLanguageName = Language::where('lang_code', $fallbackLocale)->first()->name ?? $fallbackLocale; // Generate URL to the same post in the fallback locale $fallbackUrl = \LaravelLocalization::getLocalizedURL($fallbackLocale, route('post.show', ['id' => $postId])); $viewData['fallbackLocale'] = $fallbackLocale; $viewData['fallbackLanguageName'] = __($fallbackLanguageName); $viewData['fallbackUrl'] = $fallbackUrl; } // Use guest layout for non-authenticated users, app layout for authenticated users $viewName = Auth::check() ? 'posts.no_translation' : 'posts.no_translation-guest'; return view($viewName, $viewData); } /** * Show view by .../posts/{slug}. * Post will be shown in user's App:locale() language if available, even is the slug is in another language. * * @param mixed $slug * @return void */ public function showBySlug($slug) { $postTranslation = PostTranslation::where('slug', $slug)->get()->first(); if (!$postTranslation) { return view('posts.not_found'); } $id = $postTranslation->post_id; $locale = $postTranslation->locale; $post = Post::with([ 'postable' => function ($query) { $query->select(['id', 'name']); }, 'category' => function ($query) { $query->with('translations'); }, 'meeting', 'translations' => function ($query) { //TODO!: Currently only user 1 (Super-admin) can view unpublished posts, change to permission/role based! $query->where('locale', App::getLocale()); // Only show published posts for guests and non-admin users if (!Auth::guard('web')->check() || Auth::guard('web')->user()->id != 1) { $query->whereDate('from', '<=', now()) ->where(function ($query) { $query->whereDate('till', '>', now())->orWhereNull('till'); }); } } ]) ->where('id', $id) ->first(); if ($post->media) { $media = Post::find($id)->getFirstMedia('posts'); } if ($post->translations->count() >= 1) { if ($post->category->translations) { $category = $post->category->translations->where('locale', App::getLocale())->first()->name; } $update = Carbon::createFromTimeStamp(strtotime($post->translations->first()->updated_at))->isoFormat('LL'); } else { // No translation in current locale - check for fallback translations return $this->handleNoTranslation($post, $id); } // Use guest layout for non-authenticated users, app layout for authenticated users $viewName = Auth::check() ? 'posts.show' : 'posts.show-guest'; return ($post != null ? view($viewName, compact(['post','media','category','update'])) : abort(403)); } public function manage() { if (getActiveProfileType() !== 'Admin') { abort(403, __('Admin profile required')); } return view('posts.manage'); } public function notFound() { return view('posts.not_found'); } }