Let an installation add its own tabs without the repo having to name them

This commit is contained in:
Gmer4Lfe
2026-08-22 16:37:37 -04:00
parent 879109e55d
commit 76faf0f9f8
2 changed files with 51 additions and 2 deletions
+12
View File
@@ -43,3 +43,15 @@ Plugin/dist/
*.swp
*~
.vscode/
# ── Local-only plugin surfaces (per-installation, never pushed) ───────────────
# Varaverk.page discovers pages/local/*.php and registers each as a tab; api/local/ holds their
# endpoints. Both are symlinks into a store outside this repo, so what they contain belongs to
# one installation and is not part of the project. The tracked loader is deliberately generic —
# it names no page — so the public mirror never learns what a given server runs here.
#
# No trailing slash on either pattern. These paths are symlinks, not directories, and git treats
# a symlink as a blob — a "dir/" pattern does not match one, so the entries sat untracked rather
# than ignored, which is the same near-miss the *.bak rule above documents.
Plugin/unraid/pages/local
Plugin/unraid/api/local
+39 -2
View File
@@ -477,8 +477,42 @@ $validTabs = ['monitor', 'scheduler', 'watchdog', 'partnership', 'fallback', 'ar
$_vv_ai = vv_ai_owner_ui_on();
if ($_vv_ai) $validTabs[] = 'ai';
// ── Local pages ───────────────────────────────────────────────────────────────────────────────
// pages/local/ is gitignored, so whatever is in it belongs to this installation alone and never
// reaches the public mirror. This loader is the tracked half: a generic extension point that
// knows nothing about what it is loading.
//
// It exists because the alternative — a tracked `if (file_exists(pages/thing.php))` per private
// page — puts the name and purpose of every private page into the public repo, which defeats the
// point of keeping the page out of it.
//
// Discovered rather than configured: a conf key listing local pages would itself be a tracked
// file naming them, and an untracked one would be a second thing to keep in sync with the
// directory. The directory is the declaration.
//
// The label comes from a `// vv-local-page: Name` line in the first 2KB of the file, falling back
// to the capitalised id. Reading it out of the file keeps the page self-describing — nothing
// outside it has to be edited to add one.
$localPages = [];
foreach (glob("$pluginDir/pages/local/*.php") ?: [] as $_lp) {
$_id = basename($_lp, '.php');
// Ids are restricted and collisions rejected: $tab is user input that becomes an include
// path below, and a local page must never be able to shadow a real tab.
if (!preg_match('/^[a-z0-9][a-z0-9_-]{0,31}$/', $_id)) continue;
if (in_array($_id, $validTabs, true)) continue;
$_lbl = ucfirst($_id);
if (preg_match('/^\s*(?:\/\/|#)\s*vv-local-page:\s*(.+)$/m', (string)@file_get_contents($_lp, false, null, 0, 2048), $_m)) {
$_lbl = trim($_m[1]);
}
$localPages[$_id] = ['path' => $_lp, 'label' => $_lbl];
$validTabs[] = $_id;
}
unset($_lp, $_id, $_lbl, $_m);
if (!in_array($tab, $validTabs)) $tab = 'monitor';
$tabLabels = ['monitor' => 'Monitor', 'scheduler' => 'Scheduler', 'watchdog' => 'Watchdog', 'partnership' => 'Partnership', 'fallback' => 'FallBack', 'arrs' => 'Media Stack', 'rsync' => 'Rsync', 'auth' => 'Auth Stack', 'settings' => 'Settings', 'ai' => 'AI'];
foreach ($localPages as $_id => $_lp) $tabLabels[$_id] = $_lp['label'];
unset($_id, $_lp);
// Cache stamp for the stylesheet and script below. Both are served straight off the plugin
// directory at a path that never changes, so a browser holding an old copy keeps using it after
@@ -521,9 +555,12 @@ foreach (['css/varaverk.css', 'js/varaverk.js'] as $_vv_a) {
<!-- Tab content -->
<div id="vv-content">
<?php
$page = "$pluginDir/pages/$tab.php";
// Local pages resolve from the map built above, never by composing a path out of $tab —
// the map's keys were validated against a strict pattern, so nothing user-supplied
// reaches an include.
$page = isset($localPages[$tab]) ? $localPages[$tab]['path'] : "$pluginDir/pages/$tab.php";
if (file_exists($page)) include $page;
else echo "<p>Page not found: $tab</p>";
else echo "<p>Page not found: " . htmlspecialchars($tab, ENT_QUOTES) . "</p>";
?>
</div>