98 lines
3.4 KiB
PHP
98 lines
3.4 KiB
PHP
<?php
|
|
/**
|
|
* Helpers for public page paths and their flat-file content identifiers.
|
|
*
|
|
* Public paths may contain multiple SEO-friendly segments, for example
|
|
* `products/vitamin-d`. JSON files remain flat and use a reserved double
|
|
* underscore between segments: `en_products__vitamin-d.json`.
|
|
*/
|
|
|
|
function raijuPagePathSegmentPattern(): string {
|
|
return '[a-z0-9]+(?:-[a-z0-9]+)*';
|
|
}
|
|
|
|
function raijuPagePathPattern(): string {
|
|
$segment = raijuPagePathSegmentPattern();
|
|
return $segment . '(?:/' . $segment . ')*';
|
|
}
|
|
|
|
function raijuPageContentKeyPattern(): string {
|
|
$segment = raijuPagePathSegmentPattern();
|
|
return '[a-z]{2}_' . $segment . '(?:__' . $segment . ')*';
|
|
}
|
|
|
|
function raijuPageNormalizePath(string $path): string {
|
|
$path = trim(strtolower($path));
|
|
$path = trim($path, '/');
|
|
if ($path === '' || !preg_match('#^' . raijuPagePathPattern() . '$#', $path)) {
|
|
return '';
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
function raijuPageIsValidPath(string $path): bool {
|
|
$path = trim($path);
|
|
return $path !== ''
|
|
&& $path === trim($path, '/')
|
|
&& $path === strtolower($path)
|
|
&& (bool)preg_match('#^' . raijuPagePathPattern() . '$#', $path);
|
|
}
|
|
|
|
function raijuPageContentKey(string $lang, string $path): string {
|
|
$path = raijuPageNormalizePath($path);
|
|
if (!preg_match('/^[a-z]{2}$/', $lang) || $path === '') {
|
|
return '';
|
|
}
|
|
return $lang . '_' . str_replace('/', '__', $path);
|
|
}
|
|
|
|
/** @return array{lang:string,path:string}|null */
|
|
function raijuPageParseContentKey(string $contentPage): ?array {
|
|
if (!preg_match('#^([a-z]{2})_(' . raijuPagePathSegmentPattern() . '(?:__' . raijuPagePathSegmentPattern() . ')*)$#', $contentPage, $matches)) {
|
|
return null;
|
|
}
|
|
return [
|
|
'lang' => $matches[1],
|
|
'path' => str_replace('__', '/', $matches[2]),
|
|
];
|
|
}
|
|
|
|
function raijuPageIsValidContentKey(string $contentPage): bool {
|
|
return raijuPageParseContentKey($contentPage) !== null;
|
|
}
|
|
|
|
function raijuPageJsonPath(string $root, string $lang, string $path): string {
|
|
$key = raijuPageContentKey($lang, $path);
|
|
return $key === '' ? '' : rtrim($root, '/\\') . '/content/pages/' . $key . '.json';
|
|
}
|
|
|
|
function raijuPageTemplatePath(string $root, string $lang, string $path): string {
|
|
$path = raijuPageNormalizePath($path);
|
|
if (!preg_match('/^[a-z]{2}$/', $lang) || $path === '') {
|
|
return '';
|
|
}
|
|
return rtrim($root, '/\\') . '/' . $lang . '/' . $path . '.php';
|
|
}
|
|
|
|
/**
|
|
* Relative browser path from a clean page URL back to the site root.
|
|
*/
|
|
function raijuPageBasePath(string $path, bool $languagePrefixed): string {
|
|
$path = raijuPageNormalizePath($path);
|
|
if ($path === '') return '';
|
|
$urlSegments = substr_count($path, '/') + 1 + ($languagePrefixed ? 1 : 0);
|
|
$requestPath = (string)parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH);
|
|
$directoryUrl = str_ends_with($requestPath, '/');
|
|
return str_repeat('../', max(0, $urlSegments - ($directoryUrl ? 0 : 1)));
|
|
}
|
|
|
|
function raijuPageUrlPath(string $lang, string $path, ?string $defaultLang = null): string {
|
|
$path = raijuPageNormalizePath($path);
|
|
if ($path === '') return '';
|
|
$defaultLang = $defaultLang ?: (defined('SITE_LANG_DEFAULT') ? SITE_LANG_DEFAULT : 'en');
|
|
if ($path === 'home') {
|
|
return $lang === $defaultLang ? '/' : '/' . $lang . '/';
|
|
}
|
|
return $lang === $defaultLang ? '/' . $path : '/' . $lang . '/' . $path;
|
|
}
|