125 lines
4.6 KiB
PHP
125 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Enums\DynamicPages\PageStatusEnum;
|
|
use App\Models\DynamicPage;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Support\Facades\Route;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Facades\View;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
|
use Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes;
|
|
|
|
class DynamicPageRouteServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* Register services.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function boot(): void
|
|
{
|
|
// Assert that a specific table in the database.
|
|
if (!Schema::hasTable('dynamic_pages')) {
|
|
return;
|
|
}
|
|
|
|
// Load all published dynamic pages with each parent page relationship.
|
|
$dynamicPageModels = DynamicPage::getModelsCached()
|
|
->where('status', PageStatusEnum::published)
|
|
->load('parentPage');
|
|
|
|
// Get all locales supported defined in the config.
|
|
$supportedLocales = LaravelLocalization::getSupportedLanguagesKeys();
|
|
|
|
// Get the default locale defined in the project.
|
|
$defaultLocale = LaravelLocalization::getDefaultLocale();
|
|
|
|
// Loop on all locales to generate all routes scoped to their locale.
|
|
foreach ($supportedLocales as $locale) {
|
|
// Detects whether a prefix should be added or not.
|
|
$prefix = $locale === $defaultLocale ? '' : $locale;
|
|
|
|
Route::group([
|
|
// Set the prefix according to the locale.
|
|
'prefix' => $prefix,
|
|
// Set custom middlewares.
|
|
'middleware' => ['web'],
|
|
], function () use ($locale, $dynamicPageModels) {
|
|
foreach ($dynamicPageModels as $dynamicPageModel) {
|
|
$slug = $dynamicPageModel->getTranslation('slug', $locale);
|
|
|
|
// If no slug for the locale → skip.
|
|
if (!$slug) continue;
|
|
|
|
// Retrieves the parent segments for this locale.
|
|
$segments = $this->buildFullUrlFromGroups(
|
|
$dynamicPageModel,
|
|
$dynamicPageModels->keyBy('id'),
|
|
$locale
|
|
);
|
|
|
|
// If a parent does not have a slug in this locale → skip.
|
|
if ($segments === null) continue;
|
|
|
|
$segmentsPath = implode('/', $segments);
|
|
$finalPath = $segmentsPath ? "/{$segmentsPath}/{$slug}" : "/{$slug}";
|
|
|
|
Route::get($finalPath, function () use ($dynamicPageModel, $locale) {
|
|
app()->setLocale($locale);
|
|
LaravelLocalization::setLocale($locale);
|
|
return view($dynamicPageModel->getView(), compact('dynamicPageModel'));
|
|
})->name("front.dynamic-pages.{$dynamicPageModel->id_key}.{$locale}");
|
|
}
|
|
});
|
|
}
|
|
|
|
// Share all published dynamic pages to all blade views.
|
|
foreach ($dynamicPageModels as $dynamicPageModel) {
|
|
$pascalCase = str_replace(' ', '', ucwords(str_replace('-', ' ', $dynamicPageModel->id_key)));
|
|
View::share(sprintf("page%s", $pascalCase), $dynamicPageModel);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the parent segments for the locale or null if a parent does not have a slug.
|
|
*
|
|
* @param \App\Models\DynamicPage $page
|
|
* @param \Illuminate\Database\Eloquent\Collection $groupsKeyedById
|
|
* @param string $locale
|
|
* @return array|null
|
|
*/
|
|
private function buildFullUrlFromGroups(DynamicPage $page, Collection $groupsKeyedById, string $locale): ?array
|
|
{
|
|
$segments = [];
|
|
|
|
// Start at page_id of the DynamicPage.
|
|
$parentPageId = $page->page_id ?? ($page->parentPage->id ?? null);
|
|
|
|
// Browse all relationships.
|
|
while ($parentPageId) {
|
|
/** @var \App\Models\DynamicPage|null $parentPage */
|
|
$parentPage = $groupsKeyedById->find($parentPageId);
|
|
|
|
if (!$parentPage || !$parentPage->status->equals(PageStatusEnum::published)) {
|
|
return null;
|
|
}
|
|
|
|
$slug = $parentPage->getTranslation('slug', $locale);
|
|
|
|
if (empty($slug)) {
|
|
return null;
|
|
}
|
|
|
|
// Save parentPage slug if it is published.
|
|
array_unshift($segments, $slug);
|
|
|
|
// Continue to move up even if the parentPage is not published.
|
|
$parentPageId = $parentPage->page_id;
|
|
} //end while
|
|
|
|
return $segments;
|
|
}
|
|
}
|