This file is part of a Moko Consulting project. SPDX-License-Identifier: GPL-3.0-or-later */ defined('_JEXEC') or die; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Component\ComponentHelper; /** @var Joomla\CMS\Document\HtmlDocument $this */ $app = Factory::getApplication(); $input = $app->getInput(); $document = $app->getDocument(); $wa = $document->getWebAssetManager(); // Template params $params_LightColorName = (string) $this->params->get('colorLightName', 'standard'); // standard|custom $params_DarkColorName = (string) $this->params->get('colorDarkName', 'standard'); // standard|custom $params_googletagmanager = $this->params->get('googletagmanager', false); $params_googletagmanagerid = $this->params->get('googletagmanagerid', null); $params_googleanalytics = $this->params->get('googleanalytics', false); $params_googleanalyticsid = $this->params->get('googleanalyticsid', null); $params_googlesitekey = $this->params->get('googlesitekey', null); $params_custom_head_start = $this->params->get('custom_head_start', null); $params_custom_head_end = $this->params->get('custom_head_end', null); $params_developmentmode = $this->params->get('developmentmode', false) || $app->get('debug', false); $params_favicon_source = (string) $this->params->get('favicon_source', ''); // Theme params $params_theme_enabled = $this->params->get('theme_enabled', 1); $params_theme_control_type = (string) $this->params->get('theme_control_type', 'radios'); $params_theme_fab_enabled = $this->params->get('theme_fab_enabled', 1); $params_theme_fab_pos = 'br'; // Accessibility params $params_a11y_toolbar = $this->params->get('a11y_toolbar_enabled', 1); $params_a11y_resize = $this->params->get('a11y_text_resize', 1); $params_a11y_invert = $this->params->get('a11y_color_inversion', 1); $params_a11y_contrast = $this->params->get('a11y_high_contrast', 1); $params_a11y_links = $this->params->get('a11y_highlight_links', 1); $params_a11y_font = $this->params->get('a11y_readable_font', 1); $params_a11y_animations = $this->params->get('a11y_pause_animations', 1); $params_a11y_pos = 'br'; // Detecting Active Variables $option = $input->getCmd('option', ''); $view = $input->getCmd('view', ''); $layout = $input->getCmd('layout', ''); $task = $input->getCmd('task', ''); $itemid = $input->getCmd('Itemid', ''); $sitenameR = $app->get('sitename'); // raw for title composition $sitename = htmlspecialchars($sitenameR, ENT_QUOTES, 'UTF-8'); $menu = $app->getMenu()->getActive(); $pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : ''; // Template/Media path $templatePath = 'media/templates/site/mokoonyx'; // Favicon generation $faviconHeadTags = ''; if ($params_favicon_source) { require_once __DIR__ . '/helper/favicon.php'; // Joomla's media field returns paths like: // 'images/logo.png' (images folder) // 'media/templates/site/mokoonyx/images/logo.png' (template media) // 'logo.png' (bare filename) // Strip Joomla's #joomlaImage:// fragment from media field value $faviconSourceRel = strtok(ltrim($params_favicon_source, '/'), '#'); $faviconSourceAbs = JPATH_ROOT . '/' . $faviconSourceRel; // Try common prefixes if not found if (!is_file($faviconSourceAbs)) { $candidates = [ JPATH_ROOT . '/images/' . $faviconSourceRel, JPATH_ROOT . '/media/templates/site/' . $this->template . '/' . $faviconSourceRel, JPATH_ROOT . '/media/templates/site/' . $this->template . '/images/' . basename($faviconSourceRel), ]; foreach ($candidates as $candidate) { if (is_file($candidate)) { $faviconSourceAbs = $candidate; break; } } } $faviconOutputDir = JPATH_ROOT . '/images/favicons'; $faviconUrlBase = Uri::root(true) . '/images/favicons'; if (MokoFaviconHelper::generate($faviconSourceAbs, $faviconOutputDir)) { $faviconHeadTags = MokoFaviconHelper::getHeadTags($faviconUrlBase); } } // Minification: dev mode ON → delete .min files; OFF → regenerate if stale require_once __DIR__ . '/helper/minify.php'; MokoMinifyHelper::sync(JPATH_ROOT . '/' . $templatePath, (bool) $params_developmentmode); // Core template CSS + JS — use minified when not in development mode if ($params_developmentmode) { $wa->useStyle('template.base'); // css/template.css $wa->useScript('template.js'); // js/template.js } else { $wa->useStyle('template.base.min'); // css/template.min.css $wa->useScript('template.js.min'); // js/template.min.js } // Load Osaka font for site title $wa->useStyle('template.font.osaka'); // Load GTM script if GTM is enabled if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) { $wa->useScript('gtm.js'); } /** * VirtueMart detection: * - Component must exist and be enabled */ $isVirtueMartActive = ComponentHelper::isEnabled('com_virtuemart', true); if ($isVirtueMartActive) { /** * Load a VirtueMart-specific stylesheet defined in your template manifest. * This assumes you defined an asset named "template.virtuemart". */ $wa->useStyle('vendor.vm'); } // Font scheme (external or local) + CSS custom properties $params_FontScheme = $this->params->get('useFontScheme', false); $fontStyles = ''; if ($params_FontScheme) { if (stripos($params_FontScheme, 'https://') === 0) { $this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']); $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], [ 'media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'', 'crossorigin' => 'anonymous' ]); if (preg_match_all('/family=([^?:]*):/i', $params_FontScheme, $matches) > 0) { $fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;' . "\n"; $fontStyles .= '--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;' . "\n"; $fontStyles .= '--font-weight-normal: 400;' . "\n"; $fontStyles .= '--font-weight-headings: 700;'; } } else { $wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, ['version' => 'auto'], [ 'media' => 'print', 'rel' => 'lazy-stylesheet', 'onload' => 'this.media=\'all\'' ]); $this->getPreloadManager()->preload( $wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(), ['as' => 'style'] ); } } // ------------------------------------- // Brand: logo from params OR siteTitle // ------------------------------------- $brandHtml = ''; $logoFile = (string) $this->params->get('logoFile'); if ($logoFile !== '') { $brandHtml = HTMLHelper::_( 'image', Uri::root(false) . htmlspecialchars($logoFile, ENT_QUOTES, 'UTF-8'), $sitename, ['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'], false, 0 ); } else { // If no logo file, show the title (defaults to "MokoOnyx" if not set) $siteTitle = $this->params->get('siteTitle', 'MokoOnyx'); $brandHtml = '' . htmlspecialchars($siteTitle, ENT_COMPAT, 'UTF-8') . ''; } // Layout flags $hasClass = ''; if ($this->countModules('sidebar-left', true)) { $hasClass .= ' has-sidebar-left'; } if ($this->countModules('sidebar-right', true)) { $hasClass .= ' has-sidebar-right'; } if ($this->countModules('drawer-left', true)) { $hasClass .= ' has-drawer-left'; } if ($this->countModules('drawer-right', true)) { $hasClass .= ' has-drawer-right'; } // Smart Bootstrap component loading - only load what's needed HTMLHelper::_('bootstrap.collapse'); if ($this->countModules('drawer-left', true) || $this->countModules('drawer-right', true)) { HTMLHelper::_('bootstrap.offcanvas'); } // Container $wrapper = $this->params->get('fluidContainer') ? 'wrapper-fluid' : 'wrapper-static'; $stickyHeader = $this->params->get('stickyHeader') ? 'position-sticky sticky-top' : ''; // Meta $this->setMetaData('viewport', 'width=device-width, initial-scale=1'); if (!empty($params_googlesitekey)) { $this->setMetaData('google-site-verification', htmlspecialchars($params_googlesitekey, ENT_QUOTES, 'UTF-8')); } // Font Awesome 7 — Kit (CDN) or local files $faKitCode = trim((string) $this->params->get('fA6KitCode', '')); if ($faKitCode !== '') { HTMLHelper::_('script', 'https://kit.fontawesome.com/' . $faKitCode . '.js', ['crossorigin' => 'anonymous']); } else { // Load local FA7 Free — all.css via WebAsset // Resolve the actual filesystem path: media dir (Joomla install) or template dir (SFTP deploy) $faCssFile = $params_developmentmode ? 'vendor/fa7free/css/all.css' : 'vendor/fa7free/css/all.min.css'; $faCandidates = [ $templatePath . '/' . $faCssFile, // media/templates/site/mokoonyx/... 'templates/site/' . $this->template . '/media/' . $faCssFile, // templates/site/mokoonyx/media/... ]; // Also check via __DIR__ for edge cases $faFromDir = __DIR__ . '/media/' . $faCssFile; if (is_file($faFromDir)) { $faCandidates[] = ltrim(str_replace('\\', '/', str_replace(JPATH_ROOT, '', $faFromDir)), '/'); } $faRegistered = false; foreach ($faCandidates as $faPath) { if (is_file(JPATH_ROOT . '/' . $faPath)) { $wa->registerStyle('vendor.fa7free.all', $faPath); $faRegistered = true; break; } } // Use the asset — either our dynamic registration or the one from joomla.asset.json try { $wa->useStyle('vendor.fa7free.all'); } catch (\Throwable $e) { // All paths exhausted — FA icons will rely on the IcoMoon compat layer } } $params_leftIcon = htmlspecialchars($this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), ENT_COMPAT, 'UTF-8'); $params_rightIcon = htmlspecialchars($this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'), ENT_COMPAT, 'UTF-8'); // Load theme palette stylesheets — minified when not in development mode $suffix = $params_developmentmode ? '' : '.min'; $wa->useStyle('template.light.standard' . $suffix); $wa->useStyle('template.dark.standard' . $suffix); // Load custom palettes only if selected in template configuration AND files exist if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokoonyx/css/theme/light.custom.css')) { $wa->useStyle('template.light.custom' . $suffix); } if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokoonyx/css/theme/dark.custom.css')) { $wa->useStyle('template.dark.custom' . $suffix); } // Load user assets last (after all other styles and scripts) $wa->useStyle('template.user'); // css/user.css $wa->useScript('user.js'); // js/user.js ?>