Files
adocWP/kb-antora-importer/includes/Frontend/UrlBuilder.php
2026-05-12 14:37:09 +02:00

164 lines
4.7 KiB
PHP

<?php
declare(strict_types=1);
namespace KbAntoraImporter\Frontend;
use KbAntoraImporter\Plugin;
final class UrlBuilder
{
private static string $embedBaseUrl = '';
public static function beginEmbed(string $baseUrl): void
{
self::$embedBaseUrl = remove_query_arg(['kb_docs_route', 'kb_docs_product', 'kb_docs_version', 'kb_docs_page'], $baseUrl);
}
public static function endEmbed(): void
{
self::$embedBaseUrl = '';
}
public static function isEmbed(): bool
{
return '' !== self::$embedBaseUrl;
}
public static function docsIndex(): string
{
return self::route('index');
}
public static function product(string $productSlug): string
{
return self::route('product', $productSlug);
}
public static function version(string $productSlug, string $versionSlug): string
{
return self::route('version', $productSlug, $versionSlug);
}
public static function page(string $productSlug, string $versionSlug, string $pageSlug = ''): string
{
return self::route('page', $productSlug, $versionSlug, $pageSlug);
}
private static function route(string $route, string $productSlug = '', string $versionSlug = '', string $pageSlug = ''): string
{
if (self::isEmbed()) {
$args = ['kb_docs_route' => $route];
if ($productSlug) {
$args['kb_docs_product'] = $productSlug;
}
if ($versionSlug) {
$args['kb_docs_version'] = $versionSlug;
}
if ($pageSlug) {
$args['kb_docs_page'] = $pageSlug;
}
return add_query_arg($args, self::$embedBaseUrl);
}
$base = trim((string) Plugin::settings()['docs_base_slug'], '/') ?: 'docs';
if (self::supportsPrettyPermalinks()) {
$parts = array_filter([$base, $productSlug, $versionSlug, $pageSlug], static fn (string $part): bool => '' !== $part);
return home_url('/' . implode('/', array_map('rawurlencode', $parts)) . '/');
}
$args = ['kb_antora_route' => $route];
if ($productSlug) {
$args['kb_product_slug'] = $productSlug;
}
if ($versionSlug) {
$args['kb_version_slug'] = $versionSlug;
}
if ($pageSlug) {
$args['kb_page_slug'] = $pageSlug;
}
return add_query_arg($args, home_url('/'));
}
private static function supportsPrettyPermalinks(): bool
{
return '' !== (string) get_option('permalink_structure', '');
}
public static function rewriteHtml(string $html): string
{
if (! self::isEmbed()) {
return $html;
}
return preg_replace_callback('/href=(["\'])([^"\']+)\1/i', static function (array $matches): string {
$url = html_entity_decode((string) $matches[2], ENT_QUOTES);
$replacement = self::rewriteUrl($url);
if (! $replacement) {
return $matches[0];
}
return 'href=' . $matches[1] . esc_url($replacement) . $matches[1];
}, $html) ?? $html;
}
private static function rewriteUrl(string $url): string
{
$parts = wp_parse_url($url);
if (! is_array($parts)) {
return '';
}
$query = [];
if (! empty($parts['query'])) {
wp_parse_str((string) $parts['query'], $query);
}
if (! empty($query['kb_antora_route'])) {
return self::route(
sanitize_key((string) $query['kb_antora_route']),
sanitize_title((string) ($query['kb_product_slug'] ?? '')),
sanitize_title((string) ($query['kb_version_slug'] ?? '')),
sanitize_title((string) ($query['kb_page_slug'] ?? ''))
);
}
$base = trim((string) Plugin::settings()['docs_base_slug'], '/') ?: 'docs';
$path = trim((string) ($parts['path'] ?? ''), '/');
if ($path === $base) {
return self::docsIndex();
}
if (! str_starts_with($path . '/', $base . '/')) {
return '';
}
$routeParts = array_values(array_filter(explode('/', substr($path, strlen($base))), static fn (string $part): bool => '' !== $part));
if (1 === count($routeParts)) {
return self::product(sanitize_title($routeParts[0]));
}
if (2 === count($routeParts)) {
return self::version(sanitize_title($routeParts[0]), sanitize_title($routeParts[1]));
}
return self::page(
sanitize_title($routeParts[0] ?? ''),
sanitize_title($routeParts[1] ?? ''),
sanitize_title(implode('/', array_slice($routeParts, 2)))
);
}
}