= 1.2.3
*/
// 1. Register Routes
Hooks::addAction('router_init', function(Router $router) {
// Page to show the download button
$router->get('/{session}/theme/manager', function($session) {
$title = 'Theme Manager'; // Fallback title
// Include Header
require ROOT . '/app/Views/layouts/header_main.php';
// 1. Inject Plugin Translations using the new extend() method
?>
Theme Manager
Manage and download your captive portal theme.
Download Mivo Theme
Download the fully configured captive portal theme for this router session. The package includes your specific configuration (API Base URL and Session ID) automatically injected into the theme assets.
Installation
- Download the zip file.
- Extract the contents.
- Upload the folders (css, fonts, js, etc.) and login.html to your Mikrotik Hotspot directory.
post('/{session}/theme/download', function($session) {
$sourcePath = __DIR__ . '/theme';
if (!is_dir($sourcePath)) {
die("Theme source not found.");
}
// Determine Configuration
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$host = $_SERVER['HTTP_HOST'];
$baseUrl = $protocol . $host . '/mivo/public'; // Adjust if needed based on real deployment, maybe just $protocol . $host if root
// If app is in root:
$baseUrl = $protocol . $host;
// Prepare Zip
$zipFile = sys_get_temp_dir() . '/mivo-theme-' . $session . '-' . date('YmdHis') . '.zip';
$zip = new ZipArchive();
if ($zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
die("Cannot create zip file.");
}
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourcePath, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
if ($file->isDir()) continue;
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($sourcePath) + 1);
// Normalize slashes for Zip
$zipPath = str_replace('\\', '/', $relativePath);
if (strpos($zipPath, 'assets/js/main.js') !== false) {
// Read and Replace
$content = file_get_contents($filePath);
// Replacements
$content = str_replace('apiBaseUrl: ""', 'apiBaseUrl: "' . $baseUrl . '"', $content);
$content = str_replace('apiSession: "router-jakarta-1"', 'apiSession: "' . $session . '"', $content);
$zip->addFromString($zipPath, $content);
} else {
$zip->addFile($filePath, $zipPath);
}
}
$zip->close();
// Serve File
if (file_exists($zipFile)) {
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="mivo-theme-'.$session.'.zip"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($zipFile));
readfile($zipFile);
unlink($zipFile);
exit;
} else {
die("Failed to create zip.");
}
});
});
// 2. Inject Menu into Sidebar (Using Footer JS Hack)
Hooks::addAction('mivo_footer', function() {
// Get current session from URL if possible
$uri = $_SERVER['REQUEST_URI'] ?? '/';
$parts = explode('/', trim($uri, '/'));
if (count($parts) >= 2 && $parts[1] === 'dashboard' || isset($parts[0])) {
$session = $parts[0]; // Assuming /{session}/...
// Check if it's a valid session context looking like a session string
// Simple basic check to avoid injecting on non-session pages
if (!empty($session) && $session !== 'settings' && $session !== 'login' && $session !== 'install') {
?>