first commit

This commit is contained in:
2025-06-17 11:53:18 +02:00
commit 9f0f7ba12b
8804 changed files with 1369176 additions and 0 deletions

View File

@ -0,0 +1,40 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_submenu
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
\defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Component\Menus\Administrator\Helper\MenusHelper;
use Joomla\Module\Submenu\Administrator\Menu\Menu;
$menutype = $params->get('menutype', '*');
$root = false;
if ($menutype === '*') {
$name = $params->get('preset', 'system');
$root = MenusHelper::loadPreset($name);
} else {
$root = MenusHelper::getMenuItems($menutype, true);
}
if ($root && $root->hasChildren()) {
Factory::getLanguage()->load(
'mod_menu',
JPATH_ADMINISTRATOR,
Factory::getLanguage()->getTag(),
true
);
Menu::preprocess($root);
// Render the module layout
require ModuleHelper::getLayoutPath('mod_submenu', $params->get('layout', 'default'));
}

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="module" client="administrator" method="upgrade">
<name>mod_submenu</name>
<author>Joomla! Project</author>
<creationDate>2006-02</creationDate>
<copyright>(C) 2006 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<version>3.0.0</version>
<description>MOD_SUBMENU_XML_DESCRIPTION</description>
<namespace path="src">Joomla\Module\Submenu</namespace>
<files>
<filename module="mod_submenu">mod_submenu.php</filename>
<folder>src</folder>
<folder>tmpl</folder>
</files>
<languages>
<language tag="en-GB">language/en-GB/mod_submenu.ini</language>
<language tag="en-GB">language/en-GB/mod_submenu.sys.ini</language>
</languages>
<help key="Admin_Modules:_Administrator_Dashboard_Menu" />
<config>
<fields name="params">
<fieldset name="basic" addfieldprefix="Joomla\Component\Menus\Administrator\Field">
<field
name="menutype"
type="menu"
label="MOD_SUBMENU_FIELD_MENUTYPE_LABEL"
clientid="1"
>
<option value="*">MOD_SUBMENU_FIELD_MENUTYPE_OPTION_PREDEFINED</option>
</field>
<field
name="preset"
type="menuPreset"
label="MOD_SUBMENU_FIELD_PRESET_LABEL"
showon="menutype:*"
/>
</fieldset>
<fieldset name="advanced">
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
class="form-select"
validate="moduleLayout"
/>
<field
name="moduleclass_sfx"
type="textarea"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
rows="3"
validate="CssIdentifier"
/>
</fieldset>
</fields>
</config>
</extension>

View File

@ -0,0 +1,237 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_submenu
*
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Module\Submenu\Administrator\Menu;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Event\Menu\PreprocessMenuItemsEvent;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Menu\MenuItem;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Menus\Administrator\Helper\MenusHelper;
use Joomla\Utilities\ArrayHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Helper class to handle permissions in mod_submenu
*
* @since 4.0.0
*/
abstract class Menu
{
/**
* Filter and perform other preparatory tasks for loaded menu items based on access rights and module configurations for display
*
* @param MenuItem $parent A menu item to process
*
* @return void
*
* @since 4.0.0
*/
public static function preprocess($parent)
{
$app = Factory::getApplication();
$user = $app->getIdentity();
$children = $parent->getChildren();
$language = Factory::getLanguage();
$dispatcher = $app->getDispatcher();
/**
* Trigger onPreprocessMenuItems for the current level of backend menu items.
* $children is an array of MenuItem objects. A plugin can traverse the whole tree,
* but new nodes will only be run through this method if their parents have not been processed yet.
*/
$children = $dispatcher->dispatch('onPreprocessMenuItems', new PreprocessMenuItemsEvent('onPreprocessMenuItems', [
'context' => 'administrator.module.mod_submenu',
'subject' => &$children, // @todo: Remove reference in Joomla 6, see PreprocessMenuItemsEvent::__constructor()
'params' => null,
'enabled' => true,
]))->getArgument('subject', $children);
foreach ($children as $item) {
if (substr($item->link, 0, 8) === 'special:') {
$special = substr($item->link, 8);
if ($special === 'language-forum') {
$item->link = 'index.php?option=com_admin&amp;view=help&amp;layout=langforum';
}
}
$uri = new Uri($item->link);
$query = $uri->getQuery(true);
/**
* This is needed to populate the element property when the component is no longer
* installed but its core menu items are left behind.
*/
if ($option = $uri->getVar('option')) {
$item->element = $option;
}
// Exclude item if is not enabled
if ($item->element && !ComponentHelper::isEnabled($item->element)) {
$parent->removeChild($item);
continue;
}
/*
* Multilingual Associations if the site is not set as multilingual and/or Associations is not enabled in
* the Language Filter plugin
*/
if ($item->element === 'com_associations' && !Associations::isEnabled()) {
$parent->removeChild($item);
continue;
}
$itemParams = $item->getParams();
// Exclude item with menu item option set to exclude from menu modules
if ($itemParams->get('menu-permission')) {
@list($action, $asset) = explode(';', $itemParams->get('menu-permission'));
if (!$user->authorise($action, $asset)) {
$parent->removeChild($item);
continue;
}
}
// Populate automatic children for container items
if ($item->type === 'container') {
$exclude = (array) $itemParams->get('hideitems') ?: [];
$components = MenusHelper::getMenuItems('main', false, $exclude);
// We are adding the nodes first to preprocess them, then sort them and add them again.
foreach ($components->getChildren() as $c) {
if (!$c->hasChildren()) {
$temp = clone $c;
$c->addChild($temp);
}
$item->addChild($c);
}
self::preprocess($item);
$children = ArrayHelper::sortObjects($item->getChildren(), 'text', 1, false, true);
foreach ($children as $c) {
$parent->addChild($c);
}
$parent->removeChild($item);
continue;
}
// Exclude Mass Mail if disabled in global configuration
if ($item->scope === 'massmail' && ($app->get('massmailoff', 0) == 1)) {
$parent->removeChild($item);
continue;
}
// Exclude item if the component is not authorised
$assetName = $item->element;
if ($item->element === 'com_categories') {
$assetName = $query['extension'] ?? 'com_content';
} elseif ($item->element === 'com_fields') {
parse_str($item->link, $query);
// Only display Fields menus when enabled in the component
$createFields = null;
if (isset($query['context'])) {
$createFields = ComponentHelper::getParams(strstr($query['context'], '.', true))->get('custom_fields_enable', 1);
}
if (!$createFields || !$user->authorise('core.manage', 'com_users')) {
$parent->removeChild($item);
continue;
}
} elseif ($item->element === 'com_workflow') {
parse_str($item->link, $query);
// Only display Workflow menus when enabled in the component
$workflow = null;
if (isset($query['extension'])) {
$parts = explode('.', $query['extension']);
$workflow = ComponentHelper::getParams($parts[0])->get('workflow_enabled') && $user->authorise('core.manage.workflow', $parts[0]);
}
if (!$workflow) {
$parent->removeChild($item);
continue;
}
[$assetName] = isset($query['extension']) ? explode('.', $query['extension'], 2) : ['com_workflow'];
} elseif (\in_array($item->element, ['com_config', 'com_privacy', 'com_actionlogs'], true) && !$user->authorise('core.admin')) {
// Special case for components which only allow super user access
$parent->removeChild($item);
continue;
} elseif ($item->element === 'com_joomlaupdate' && !$user->authorise('core.admin')) {
$parent->removeChild($item);
continue;
} elseif (
($item->link === 'index.php?option=com_installer&view=install' || $item->link === 'index.php?option=com_installer&view=languages')
&& !$user->authorise('core.admin')
) {
continue;
} elseif ($item->element === 'com_admin') {
parse_str($item->link, $query);
if (isset($query['view']) && $query['view'] === 'sysinfo' && !$user->authorise('core.admin')) {
$parent->removeChild($item);
continue;
}
} elseif ($item->element === 'com_menus') {
// Get badges for Menus containing a Home page.
$iconImage = $item->icon;
if ($iconImage) {
if (substr($iconImage, 0, 6) === 'class:' && substr($iconImage, 6) === 'icon-home') {
$iconImage = '<span class="home-image icon-home" aria-hidden="true"></span>';
$iconImage .= '<span class="visually-hidden">' . Text::_('JDEFAULT') . '</span>';
} elseif (substr($iconImage, 0, 6) === 'image:') {
$iconImage = '&nbsp;<span class="badge bg-secondary">' . substr($iconImage, 6) . '</span>';
}
$item->iconImage = $iconImage;
}
}
if ($assetName && !$user->authorise(($item->scope === 'edit') ? 'core.create' : 'core.manage', $assetName)) {
$parent->removeChild($item);
continue;
}
if ($item->hasChildren()) {
self::preprocess($item);
}
// Ok we passed everything, load language at last only
if ($item->element) {
$language->load($item->element . '.sys', JPATH_ADMINISTRATOR) ||
$language->load($item->element . '.sys', JPATH_ADMINISTRATOR . '/components/' . $item->element);
}
if ($item->type === 'separator' && $item->getParams()->get('text_separator') == 0) {
$item->title = '';
}
$item->text = Text::_($item->title);
}
}
}

View File

@ -0,0 +1,123 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage mod_submenu
*
* @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
$user = $app->getIdentity();
/** @var \Joomla\CMS\Menu\MenuItem $root */
?>
<?php foreach ($root->getChildren() as $child) : ?>
<?php if ($child->hasChildren()) : ?>
<div class="module-wrapper">
<div class="card">
<?php
$child->img = $child->img ?? '';
if (substr($child->img, 0, 6) === 'class:') {
$iconImage = '<span class="icon-' . substr($child->img, 6) . '" aria-hidden="true"></span>';
} elseif (substr($child->img, 0, 6) === 'image:') {
$iconImage = '<img src="' . substr($child->img, 6) . '" aria-hidden="true">';
} elseif (!empty($child->img)) {
$iconImage = '<img src="' . $child->img . '" aria-hidden="true">';
} elseif ($child->icon) {
$iconImage = '<span class="icon-' . $child->icon . '" aria-hidden="true"></span>';
} else {
$iconImage = '';
}
?>
<h2 class="card-header">
<?php echo $iconImage; ?>
<?php echo Text::_($child->title); ?>
</h2>
<ul class="list-group list-group-flush">
<?php foreach ($child->getChildren() as $item) : ?>
<?php $params = $item->getParams(); ?>
<?php // Only if Menu-show = true ?>
<?php if ($params->get('menu_show', 1)) : ?>
<li class="list-group-item d-flex align-items-center">
<?php $class = $params->get('menu-quicktask') ? '' : 'class="flex-grow-1"'; ?>
<a <?php echo $class; ?> href="<?php echo $item->link; ?>"
<?php echo $item->target === '_blank' ? ' title="' . Text::sprintf('JBROWSERTARGET_NEW_TITLE', Text::_($item->title)) . '"' : ''; ?>
<?php echo $item->target ? ' target="' . $item->target . '"' : ''; ?>>
<?php if (!empty($params->get('menu_image'))) : ?>
<?php
$image = htmlspecialchars($params->get('menu_image'), ENT_QUOTES, 'UTF-8');
$class = htmlspecialchars($params->get('menu_image_css'), ENT_QUOTES, 'UTF-8');
$alt = $params->get('menu_text') ? '' : htmlspecialchars(Text::_($item->title), ENT_QUOTES, 'UTF-8');
?>
<?php echo HTMLHelper::_('image', $image, $alt, 'class="' . $class . '"'); ?>
<?php endif; ?>
<?php echo ($params->get('menu_text', 1)) ? htmlspecialchars(Text::_($item->title), ENT_QUOTES, 'UTF-8') : ''; ?>
<?php if ($item->ajaxbadge) : ?>
<span class="menu-badge">
<span class="icon-spin icon-spinner mt-1 system-counter float-end" data-url="<?php echo $item->ajaxbadge; ?>"></span>
</span>
<?php endif; ?>
</a>
<?php echo $item->iconImage; ?>
<?php if ($params->get('menu-quicktask')) : ?>
<?php $permission = $params->get('menu-quicktask-permission'); ?>
<?php $scope = $item->scope !== 'default' ? $item->scope : null; ?>
<?php if (!$permission || $user->authorise($permission, $scope)) : ?>
<span class="menu-quicktask">
<?php
$link = $params->get('menu-quicktask');
$icon = $params->get('menu-quicktask-icon', 'plus');
$title = Text::_($params->get('menu-quicktask-title'));
if (empty($params->get('menu-quicktask-title'))) {
$title = Text::_('MOD_MENU_QUICKTASK_NEW');
}
$sronly = Text::_($item->title) . ' - ' . $title;
?>
<a href="<?php echo $link; ?>">
<span class="icon-<?php echo $icon; ?>" title="<?php echo htmlentities($title); ?>" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo htmlentities($sronly); ?></span>
</a>
</span>
<?php endif; ?>
<?php endif; ?>
<?php if ($item->dashboard) : ?>
<span class="menu-dashboard">
<?php
$titleDashboard = Text::sprintf('MOD_MENU_DASHBOARD_LINK', Text::_($child->title));
// Prepare the Dashboard icon. We use our own icon, not Fontawesome
$pathDashboard = 'media/templates/administrator/atum/images/icons/dashboard.svg';
$attrDashboard = [
'loading' => 'eager',
'decoding' => 'async',
'aria-hidden' => 'true',
'class' => 'atum-dashboard',
'height' => '18',
];
$iconDashboard = HTMLHelper::_('image', $pathDashboard, '', $attrDashboard, false, 0);
?>
<a href="<?php echo Route::_('index.php?option=com_cpanel&view=cpanel&dashboard=' . $item->dashboard); ?>" title="<?php echo $titleDashboard; ?>">
<span><?php echo $iconDashboard; ?></span>
<span class="visually-hidden"><?php echo $titleDashboard; ?></span>
</a>
</span>
<?php endif; ?>
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php endif; ?>
<?php endforeach; ?>