Fix unreachable index page and duplicate homepage entry in navigation

buildUrl() hardcoded 'index' as the homepage, so the menu link for
index.md pointed at /nl. With a different default_page that root URL
served another page, making index.md unreachable.

- Add getEffectiveDefaultPage(): resolves 'auto' to the detected page
  and caches the result
- buildUrl() now omits the page segment only for the effective default
  page instead of the literal string 'index'
- Route getPage(), generateBreadcrumb(), getContentType() and the
  render() template data (default_page, homepage, is_homepage,
  home_active_class, current_page, lang switch URLs) through it
- getHomepageTitle() returns t('home') so the home button no longer
  duplicates a menu item label
- Drop the now-redundant default_page skip in renderMenu() so every
  page stays reachable from the menu
- getAllContentDirs() also skips dot-directories (.git) in the move
  dropdown
This commit is contained in:
2026-07-28 16:09:44 +02:00
parent 2faea90872
commit b203f6d12a
2 changed files with 36 additions and 29 deletions
+33 -27
View File
@@ -25,6 +25,7 @@ class CodePressCMS {
public $currentLanguage;
public $searchResults = [];
private $menu = [];
private ?string $effectiveDefaultPage = null;
private $translations = [];
private $pluginManager;
@@ -66,10 +67,12 @@ class CodePressCMS {
* @param array $params Additional query parameters
* @return string Clean URL
*/
public function buildUrl($page = 'index', $lang = null, $params = []) {
public function buildUrl($page = null, $lang = null, $params = []) {
$lang = $lang ?: $this->currentLanguage;
$url = '/' . $lang;
if ($page && $page !== 'index') {
// Only omit the page segment for the actual homepage (default_page),
// not for a page that happens to be called 'index'
if ($page && $page !== $this->getEffectiveDefaultPage()) {
$url .= '/' . $page;
}
if (!empty($params)) {
@@ -78,6 +81,20 @@ class CodePressCMS {
return $url;
}
/**
* Resolve the effective default page (handles 'auto' mode)
*
* @return string Page key that is served on the language root URL
*/
public function getEffectiveDefaultPage(): string
{
if ($this->effectiveDefaultPage === null) {
$page = $this->config['default_page'] ?? 'auto';
$this->effectiveDefaultPage = ($page === 'auto') ? $this->detectDefaultPage() : $page;
}
return $this->effectiveDefaultPage;
}
/**
* Build a clean admin URL
*
@@ -353,10 +370,7 @@ class CodePressCMS {
return $this->getGuidePage();
}
$page = $_GET['page'] ?? $this->config['default_page'];
if ($page === 'auto') {
$page = $this->detectDefaultPage();
}
$page = $_GET['page'] ?? $this->getEffectiveDefaultPage();
// Limit length
$page = substr($page, 0, 255);
// Only remove file extension at the end, not all dots
@@ -1057,11 +1071,11 @@ class CodePressCMS {
'search_query' => isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '',
'menu' => $this->renderMenu($menu),
'breadcrumb' => $breadcrumb,
'default_page' => $this->config['default_page'],
'homepage' => $this->config['default_page'],
'default_page' => $this->getEffectiveDefaultPage(),
'homepage' => $this->getEffectiveDefaultPage(),
'homepage_title' => $homepageTitle,
'is_homepage' => (!isset($_GET['page']) || $_GET['page'] === $this->config['default_page']),
'home_active_class' => (!isset($_GET['page']) || $_GET['page'] === $this->config['default_page']) ? 'active' : '',
'is_homepage' => (!isset($_GET['page']) || $_GET['page'] === $this->getEffectiveDefaultPage()),
'home_active_class' => (!isset($_GET['page']) || $_GET['page'] === $this->getEffectiveDefaultPage()) ? 'active' : '',
'is_guide_page' => isset($_GET['guide']),
'lang_switch_url' => '',
'author_name' => $this->config['author']['name'] ?? 'CodePress Developer',
@@ -1084,11 +1098,11 @@ class CodePressCMS {
// Language
'current_lang' => $this->currentLanguage,
'current_lang_upper' => strtoupper($this->currentLanguage),
'current_page' => $_GET['page'] ?? $this->config['default_page'],
'current_page' => $_GET['page'] ?? $this->getEffectiveDefaultPage(),
'available_langs' => array_map(function($lang) {
$lang['is_current'] = $lang['code'] === $this->currentLanguage;
$page = $_GET['page'] ?? $this->config['default_page'];
$lang['url'] = '/' . $lang['code'] . ($page !== $this->config['default_page'] ? '/' . $page : '');
$page = $_GET['page'] ?? $this->getEffectiveDefaultPage();
$lang['url'] = '/' . $lang['code'] . ($page !== $this->getEffectiveDefaultPage() ? '/' . $page : '');
return $lang;
}, $this->getAvailableLanguages()),
// Translations
@@ -1187,12 +1201,12 @@ class CodePressCMS {
return '<nav aria-label="breadcrumb"><ol class="breadcrumb">' . $sidebarToggle . '<li class="breadcrumb-item"><a href="/' . $this->currentLanguage . '"><i class="bi bi-house"></i></a></li><li class="breadcrumb-item"> > </li><li class="breadcrumb-item active">' . $this->t('search') . '</li></ol></nav>';
}
$page = $_GET['page'] ?? $this->config['default_page'];
$page = $_GET['page'] ?? $this->getEffectiveDefaultPage();
$page = htmlspecialchars($page, ENT_QUOTES, 'UTF-8');
$page = preg_replace('/\.[^.]+$/', '', $page);
// Convert page to clean URL format for breadcrumb
if ($page === $this->config['default_page']) {
if ($page === $this->getEffectiveDefaultPage()) {
return '<nav aria-label="breadcrumb"><ol class="breadcrumb">' . $sidebarToggle . '<li class="breadcrumb-item active"><i class="bi bi-house"></i></li></ol></nav>';
}
@@ -1274,11 +1288,6 @@ class CodePressCMS {
} else {
// Show files in root as tabs, files in folders as dropdown items
if ($level === 0) {
// Don't show the homepage file as a separate tab since it's already the Home button
if ($item['path'] === $this->config['default_page']) {
continue;
}
$active = (isset($_GET['page']) && $_GET['page'] === $item['path']) ? 'active' : '';
$html .= '<li class="nav-item">';
$html .= '<a class="nav-link ' . $active . '" href="' . htmlspecialchars($item['url']) . '">';
@@ -1305,7 +1314,7 @@ class CodePressCMS {
*/
private function getContentType($page) {
// Try to determine content type from page request
$pagePath = $_GET['page'] ?? $this->config['default_page'];
$pagePath = $_GET['page'] ?? $this->getEffectiveDefaultPage();
$pagePath = preg_replace('/\.[^.]+$/', '', $pagePath);
$filePath = $this->config['content_dir'] . '/' . $pagePath;
@@ -1363,12 +1372,9 @@ class CodePressCMS {
* @return string Homepage title
*/
private function getHomepageTitle() {
// Use formatted filename for homepage title in navigation
$page = $this->config['default_page'];
if ($page === 'auto') {
$page = $this->detectDefaultPage();
}
return $this->formatDisplayName($page);
// Use a generic "Home" label instead of the page name
// to avoid duplication with the navigation menu
return $this->t('home');
}
/**