- Implemented configurable public URL rewriting.

What changed:
Added pretty URL helpers/default setting in 
[includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php).
Added root rewrite rules in 
[.htaccess](/Users/tyemeclifford/Documents/GH/mediaplayer/.htaccess):/v/<slug>
/all
/search/<query>

Added Admin → Settings “Public URL Style” toggle in 
[admin/settings.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/settings.php), 
defaulting to pretty URLs.
Updated public/player/catalogue/embed/admin preview links to use the 
configured URL style.
Added redirects from legacy ?v= and ?q= URLs to pretty routes when 
rewriting is enabled.
Documented deployment and fallback behavior in 
[README.md](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md).
This commit is contained in:
Ty Clifford
2026-06-24 13:16:55 -04:00
parent 0f262cab3f
commit 1abe5218ca
13 changed files with 187 additions and 30 deletions
+104
View File
@@ -67,6 +67,7 @@ function get_db(): PDO {
'admin_password' => password_hash('admin', PASSWORD_DEFAULT),
'site_title' => 'Ty Clifford',
'site_sub' => 'tyclifford.com / media',
'url_rewrite_mode' => 'pretty',
];
$ins = $pdo->prepare("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)");
foreach ($defaults as $k => $v) $ins->execute([$k, $v]);
@@ -100,6 +101,109 @@ function set_setting(string $key, string $value): void {
->execute([$key, $value]);
}
function url_rewrite_mode(): string {
$mode = strtolower(setting('url_rewrite_mode', 'pretty'));
return in_array($mode, ['pretty', 'query'], true) ? $mode : 'pretty';
}
function url_rewrite_enabled(): bool {
return url_rewrite_mode() === 'pretty';
}
function public_base_path(): string {
$script = str_replace('\\', '/', $_SERVER['SCRIPT_NAME'] ?? '');
$dir = rtrim(dirname($script), '/');
if ($dir === '/' || $dir === '.') $dir = '';
if (str_ends_with($dir, '/admin')) $dir = substr($dir, 0, -6);
return $dir;
}
function public_url_path(string $path): string {
$base = public_base_path();
$path = '/' . ltrim($path, '/');
if ($path === '/') return $base === '' ? '/' : $base . '/';
return $base . $path;
}
function public_home_url(): string {
return url_rewrite_enabled() ? public_url_path('/') : public_url_path('/index.php');
}
function public_catalogue_url(): string {
return url_rewrite_enabled() ? public_url_path('/all') : public_url_path('/catalogue.php');
}
function public_video_url(string $slug): string {
$slug = trim($slug);
if (url_rewrite_enabled()) return public_url_path('/v/' . rawurlencode($slug));
return public_url_path('/index.php') . '?v=' . rawurlencode($slug);
}
function public_search_url(string $query): string {
$query = trim($query);
if ($query === '') return public_catalogue_url();
if (url_rewrite_enabled()) return public_url_path('/search/' . rawurlencode($query));
return public_url_path('/catalogue.php') . '?q=' . rawurlencode($query);
}
function public_page_url_pattern(string $base_url): string {
return $base_url . (strpos($base_url, '?') === false ? '?' : '&') . 'page=%d';
}
function public_catalogue_page_url_pattern(string $search = ''): string {
return public_page_url_pattern($search !== '' ? public_search_url($search) : public_catalogue_url());
}
function public_player_page_url_pattern(string $slug = ''): string {
$base = $slug !== '' ? public_video_url($slug) : public_home_url();
return public_page_url_pattern($base);
}
function public_request_path(): string {
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
return is_string($path) && $path !== '' ? $path : '/';
}
function public_route_segments(): array {
$path = public_request_path();
$base = public_base_path();
if ($base !== '' && ($path === $base || str_starts_with($path, $base . '/'))) {
$path = substr($path, strlen($base));
}
$segments = array_values(array_filter(explode('/', trim($path, '/')), 'strlen'));
return array_map('rawurldecode', $segments);
}
function public_video_slug_from_request(): string {
$slug = trim((string)($_GET['v'] ?? ''));
if ($slug !== '') return $slug;
$segments = public_route_segments();
return (($segments[0] ?? '') === 'v' && isset($segments[1])) ? trim($segments[1]) : '';
}
function public_search_query_from_request(): string {
if (isset($_GET['q'])) return trim((string)$_GET['q']);
$segments = public_route_segments();
return (($segments[0] ?? '') === 'search' && isset($segments[1])) ? trim($segments[1]) : '';
}
function public_request_scheme(): string {
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
}
function public_origin(): string {
return public_request_scheme() . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost');
}
function public_absolute_url(string $url): string {
if (preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) return $url;
if (str_starts_with($url, '//')) return public_request_scheme() . ':' . $url;
if (str_starts_with($url, '/')) return public_origin() . $url;
return public_origin() . public_url_path($url);
}
function make_slug(string $title, int $id = 0): string {
$slug = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-', $title), '-'));
if ($id) {