feat: auto-discover installed Moko extensions in admin sidebar menu
Static MokoWaaS views listed first, then installed Moko components auto-discovered from #__extensions. Supported: MokoJoomBackup, MokoJoomCommunity, MokoJoomCalendar, MokoJoomGallery, MokoJoomCross, Akeeba Backup, Akeeba Ticket System. New extensions appear automatically. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,34 +2,89 @@
|
||||
/**
|
||||
* MokoWaaS Admin Sidebar Menu
|
||||
*
|
||||
* Uses native Joomla admin menu classes (MetisMenu) so it renders
|
||||
* identically to Joomla's own sidebar menu items.
|
||||
* Uses native Joomla admin menu classes (MetisMenu). Static MokoWaaS
|
||||
* views are listed first, then installed Moko extensions are auto-discovered
|
||||
* from #__extensions so they appear automatically when installed.
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
$items = [
|
||||
['icon' => 'icon-cogs', 'title' => 'Dashboard', 'link' => 'index.php?option=com_mokowaas'],
|
||||
['icon' => 'fa-solid fa-handshake-angle', 'title' => 'Helpdesk', 'link' => 'index.php?option=com_mokowaas&view=tickets'],
|
||||
['icon' => 'icon-puzzle-piece', 'title' => 'Extensions', 'link' => 'index.php?option=com_mokowaas&view=extensions'],
|
||||
['icon' => 'fa-solid fa-file-code', 'title' => '.htaccess Maker', 'link' => 'index.php?option=com_mokowaas&view=htaccess'],
|
||||
['icon' => 'icon-lock', 'title' => 'Privacy Guard', 'link' => 'index.php?option=com_mokowaas&view=privacy'],
|
||||
['icon' => 'icon-shield-alt', 'title' => 'WAF Log', 'link' => 'index.php?option=com_mokowaas&view=waflog'],
|
||||
['icon' => 'icon-database', 'title' => 'Database Tools', 'link' => 'index.php?option=com_mokowaas&view=database'],
|
||||
['icon' => 'icon-trash', 'title' => 'Cache Cleanup', 'link' => 'index.php?option=com_mokowaas&view=cleanup'],
|
||||
['icon' => 'icon-power-off', 'title' => 'Feature Plugins', 'link' => 'index.php?option=com_plugins&filter[folder]=system&filter[search]=mokowaas'],
|
||||
];
|
||||
|
||||
$app = \Joomla\CMS\Factory::getApplication();
|
||||
$app = Factory::getApplication();
|
||||
$currentOption = $app->getInput()->get('option', '');
|
||||
$currentView = $app->getInput()->get('view', '');
|
||||
|
||||
// Determine if any child is active (auto-expand)
|
||||
$anyActive = ($currentOption === 'com_mokowaas');
|
||||
$parentClass = 'item parent item-level-1' . ($anyActive ? ' mm-active' : '');
|
||||
// ── Static MokoWaaS views ────────────────────────────────────────────
|
||||
$items = [
|
||||
['icon' => 'icon-cogs', 'title' => 'Dashboard', 'link' => 'index.php?option=com_mokowaas'],
|
||||
['icon' => 'fa-solid fa-handshake-angle', 'title' => 'Helpdesk', 'link' => 'index.php?option=com_mokowaas&view=tickets'],
|
||||
['icon' => 'icon-puzzle-piece', 'title' => 'Extensions', 'link' => 'index.php?option=com_mokowaas&view=extensions'],
|
||||
['icon' => 'fa-solid fa-file-code', 'title' => '.htaccess Maker', 'link' => 'index.php?option=com_mokowaas&view=htaccess'],
|
||||
['icon' => 'icon-lock', 'title' => 'Privacy Guard', 'link' => 'index.php?option=com_mokowaas&view=privacy'],
|
||||
['icon' => 'icon-shield-alt', 'title' => 'WAF Log', 'link' => 'index.php?option=com_mokowaas&view=waflog'],
|
||||
['icon' => 'icon-database', 'title' => 'Database Tools', 'link' => 'index.php?option=com_mokowaas&view=database'],
|
||||
['icon' => 'icon-trash', 'title' => 'Cache Cleanup', 'link' => 'index.php?option=com_mokowaas&view=cleanup'],
|
||||
['icon' => 'icon-power-off', 'title' => 'Feature Plugins', 'link' => 'index.php?option=com_plugins&filter[folder]=system&filter[search]=mokowaas'],
|
||||
];
|
||||
|
||||
// ── Auto-discover installed Moko extensions ──────────────────────────
|
||||
// Map element → menu entry. Only shown when the extension is installed.
|
||||
$mokoExtensions = [
|
||||
'com_mokojoombackup' => ['icon' => 'fa-solid fa-box-archive', 'title' => 'MokoJoomBackup', 'link' => 'index.php?option=com_mokojoombackup'],
|
||||
'com_mokojoomtos' => ['icon' => 'icon-file-contract', 'title' => 'MokoJoomTOS', 'link' => 'index.php?option=com_mokojoomtos'],
|
||||
'com_comprofiler' => ['icon' => 'icon-users', 'title' => 'MokoJoomCommunity', 'link' => 'index.php?option=com_comprofiler'],
|
||||
'com_dpcalendar' => ['icon' => 'icon-calendar', 'title' => 'MokoJoomCalendar', 'link' => 'index.php?option=com_dpcalendar'],
|
||||
'com_joomgallery' => ['icon' => 'icon-images', 'title' => 'MokoJoomGallery', 'link' => 'index.php?option=com_joomgallery'],
|
||||
'com_mokojoomcross' => ['icon' => 'fa-solid fa-arrow-right-arrow-left', 'title' => 'MokoJoomCross', 'link' => 'index.php?option=com_mokojoomcross'],
|
||||
'com_ats' => ['icon' => 'fa-solid fa-headset', 'title' => 'Akeeba Ticket System','link' => 'index.php?option=com_ats'],
|
||||
'com_akeebabackup' => ['icon' => 'fa-solid fa-hard-drive', 'title' => 'Akeeba Backup', 'link' => 'index.php?option=com_akeebabackup'],
|
||||
];
|
||||
|
||||
try
|
||||
{
|
||||
$db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class);
|
||||
$elements = array_keys($mokoExtensions);
|
||||
$quoted = array_map([$db, 'quote'], $elements);
|
||||
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select($db->quoteName('element'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('component'))
|
||||
->where($db->quoteName('element') . ' IN (' . implode(',', $quoted) . ')')
|
||||
->where($db->quoteName('enabled') . ' = 1')
|
||||
);
|
||||
$installed = $db->loadColumn() ?: [];
|
||||
|
||||
foreach ($installed as $element)
|
||||
{
|
||||
if (isset($mokoExtensions[$element]))
|
||||
{
|
||||
$items[] = $mokoExtensions[$element];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
// Silent — menu still works with static items only
|
||||
}
|
||||
|
||||
// ── Determine active state ───────────────────────────────────────────
|
||||
$anyActive = false;
|
||||
foreach ($items as $item)
|
||||
{
|
||||
$parsed = [];
|
||||
parse_str(parse_url($item['link'], PHP_URL_QUERY) ?? '', $parsed);
|
||||
if (($parsed['option'] ?? '') === $currentOption)
|
||||
{
|
||||
$anyActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$parentClass = 'item parent item-level-1' . ($anyActive ? ' mm-active' : '');
|
||||
$collapseClass = 'collapse-level-1 mm-collapse' . ($anyActive ? ' mm-show' : '');
|
||||
?>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user