diff --git a/e107_core/templates/admin_template.php b/e107_core/templates/admin_template.php
index 83cf7de90..48dcd032f 100644
--- a/e107_core/templates/admin_template.php
+++ b/e107_core/templates/admin_template.php
@@ -296,36 +296,36 @@ $ADMIN_TEMPLATE['menu']['start'] = '
$ADMIN_TEMPLATE['menu']['button'] = '
- {LINK_IMAGE}
+ {LINK_IMAGE}
{SUB_MENU}
';
+
$ADMIN_TEMPLATE['menu']['button_active'] = '
- {LINK_IMAGE}
+ {LINK_IMAGE}
{SUB_MENU}
';
$ADMIN_TEMPLATE['menu']['start_sub'] = '
-
';
$ADMIN_TEMPLATE['menu']['end'] = '
diff --git a/e107_handlers/admin_ui.php b/e107_handlers/admin_ui.php
index 4c96bc09b..9dda2114e 100755
--- a/e107_handlers/admin_ui.php
+++ b/e107_handlers/admin_ui.php
@@ -1570,169 +1570,206 @@ class e_admin_dispatcher
* Generic Admin Menu Generator
* @return string
*/
- public function renderMenu()
- {
+public function renderMenu()
+{
- $tp = e107::getParser();
- $var = array();
- $selected = false;
+ $tp = e107::getParser();
+ $var = array();
+ $selected = false;
- foreach($this->adminMenu as $key => $val)
- {
+ foreach ($this->adminMenu as $key => $val)
+ {
- if(isset($val['perm']) && $val['perm']!=='' && !getperms($val['perm']))
- {
- continue;
- }
+ if (isset($val['perm']) && $val['perm'] !== '' && !getperms($val['perm']))
+ {
+ continue;
+ }
- $tmp = explode('/', trim($key, '/'), 3);
+ $tmp = explode('/', trim($key, '/'), 3);
+ $isSubItem = count($tmp) === 3;
- // sync with mode/route access
- if(!$this->hasModeAccess($tmp[0]) || !$this->hasRouteAccess($tmp[0].'/'.varset($tmp[1])))
- {
- continue;
- }
+ if ($isSubItem)
+ {
+ $parentKey = $tmp[0].'/'.$tmp[1];
+ if (!$this->hasModeAccess($tmp[0]) || !$this->hasRouteAccess($parentKey))
+ {
+ continue;
+ }
+ }
+ else
+ {
+ if (!$this->hasModeAccess($tmp[0]) || !$this->hasRouteAccess($tmp[0].'/'.varset($tmp[1])))
+ {
+ continue;
+ }
+ }
- // custom 'selected' check
- if(isset($val['selected']) && $val['selected'])
- {
- $selected = $val['selected'] === true ? $key : $val['selected'];
- }
+ if (isset($val['selected']) && $val['selected'])
+ {
+ $selected = $val['selected'] === true ? $key : $val['selected'];
+ }
- foreach ($val as $k=>$v)
- {
- switch($k)
- {
- case 'caption':
- $k2 = 'text';
- $v = defset($v, $v);
+ $processedItem = $this->processMenuItem($val, $key, $tmp);
+ $processedItem['link_id'] = str_replace('/', '-', $key);
- break;
+ if ($isSubItem)
+ {
+ $parentKey = $tmp[0].'/'.$tmp[1];
+ if (!isset($var[$parentKey]))
+ {
+ $var[$parentKey] = array(
+ 'text' => 'Unknown',
+ 'image_src' => e_navigation::guessMenuIcon($parentKey),
+ 'link_id' => str_replace('/', '-', $parentKey) // Add link_id for parent
+ );
+ }
+ $var[$parentKey]['sub'][$tmp[2]] = $processedItem;
+ }
+ else
+ {
+ $var[$key] = $processedItem;
+ }
+ }
- case 'url':
- $k2 = 'link';
- $qry = (isset($val['query'])) ? $val['query'] : '?mode='.$tmp[0].'&action='.$tmp[1];
- $v = $tp->replaceConstants($v, 'abs').$qry;
- break;
+ // Handle links and collapse attributes
+ foreach ($var as $key => &$item)
+ {
+ if (!empty($item['sub']))
+ {
+ $item['link'] = '#';
+ $item['link_data'] = [
+ 'data-toggle' => 'collapse',
+ 'data-target' => '#sub-' . $item['link_id'],
+ 'role' => 'button'
+ ];
+ if ($selected === $key || strpos($selected, $key . '/') === 0)
+ {
+ $item['link_data']['aria-expanded'] = 'true';
+ }
+ }
+ elseif (!isset($item['link']))
+ {
+ $tmp = explode('/', trim($key, '/'), 3);
+ $item['link'] = e_REQUEST_SELF.'?mode='.$tmp[0].'&action='.($tmp[1] ?? 'main');
+ }
+ }
- case 'uri':
- $k2 = 'link';
- $v = $tp->replaceConstants($v, 'abs');
+ if (empty($var))
+ {
+ return '';
+ }
- if(!empty($v) && ($v === e_REQUEST_URI))
- {
- $selected = $key;
- }
+ // Debug $var
+ e107::getMessage()->addInfo(print_a($var, true));
- break;
+ $request = $this->getRequest();
+ if (!$selected)
+ {
+ $selected = $request->getMode() . '/' . $request->getAction();
+ if (isset($_GET['sub']) && !empty($_GET['sub']))
+ {
+ $selected .= '/' . $_GET['sub'];
+ }
+ }
+ $selected = vartrue($this->adminMenuAliases[$selected], $selected);
+ $icon = '';
- case 'badge': // array('value'=> int, 'type'=>'warning');
- $k2 = 'badge';
- $v = (array) $v;
- break;
+ if (!empty($this->adminMenuIcon))
+ {
+ $icon = e107::getParser()->toIcon($this->adminMenuIcon);
+ }
+ elseif (deftrue('e_CURRENT_PLUGIN'))
+ {
+ $icon = e107::getPlug()->load(e_CURRENT_PLUGIN)->getIcon(24);
+ }
- case 'icon':
- $k2 = 'image_src';
- $v = (string) $v.'.glyph';
- break;
+ $toggle = "";
- default:
- $k2 = $k;
-
- break;
- }
+ $var['_extras_'] = array('icon' => $icon, 'return' => true);
+ return $toggle . e107::getNav()->admin($this->menuTitle, $selected, $var);
+}
- // Access check done above
- // if($val['perm']!= null) // check perms
- // {
- // if(getperms($val['perm']))
- // {
- // $var[$key][$k2] = $v;
- // }
- // }
- // else
- {
- $var[$key][$k2] = $v;
-
- }
+private function processMenuItem($val, $key, $tmp)
+{
+ $tp = e107::getParser();
+ $item = array();
- }
+ foreach ($val as $k => $v)
+ {
+ switch ($k)
+ {
+ case 'caption':
+ $k2 = 'text';
+ $v = defset($v, $v);
+ break;
- // guess an icon.
- if(!isset($var[$key]['image_src']))
- {
- $var[$key]['image_src'] = e_navigation::guessMenuIcon($key);
- }
-
-
- // TODO slide down menu options?
- if(!vartrue($var[$key]['link']))
- {
- $var[$key]['link'] = e_REQUEST_SELF.'?mode='.$tmp[0].'&action='.$tmp[1]; // FIXME - URL based on $modes, remove url key
- }
+ case 'url':
+ $k2 = 'link';
+ $qry = (isset($val['query'])) ? $val['query'] : '?mode='.$tmp[0].'∓action='.($tmp[1] ?? 'main').(isset($tmp[2]) ? '&sub='.$tmp[2] : '');
+ $v = $tp->replaceConstants($v, 'abs').$qry;
+ break;
-
- if(varset($val['tab']))
- {
- $var[$key]['link'] .= '&tab=' .$val['tab'];
- }
+ case 'uri':
+ $k2 = 'link';
+ $v = $tp->replaceConstants($v, 'abs');
+ if (!empty($v) && ($v === e_REQUEST_URI))
+ {
+ $GLOBALS['selected'] = $key;
+ }
+ break;
- /*$var[$key]['text'] = $val['caption'];
- $var[$key]['link'] = (vartrue($val['url']) ? $tp->replaceConstants($val['url'], 'abs') : e_SELF).'?mode='.$tmp[0].'&action='.$tmp[1];
- $var[$key]['perm'] = $val['perm']; */
- if(!empty($val['modal']))
- {
- $var[$key]['link_class'] = ' e-modal';
- if(!empty($val['modal-caption']))
- {
- $var[$key]['link_data'] = ['data-modal-caption' => $val['modal-caption']];
- }
+ case 'badge':
+ $k2 = 'badge';
+ $v = (array) $v;
+ break;
- }
+ case 'icon':
+ $k2 = 'image_src';
+ $v = (string) $v . '.glyph'; // Ensure .glyph suffix
+ break;
- if(!empty($val['class']))
- {
+ default:
+ $k2 = $k;
+ break;
+ }
+
+ $item[$k2] = $v;
+ }
+
+ if (!isset($item['image_src']))
+ {
+ $item['image_src'] = e_navigation::guessMenuIcon($key); // Includes .glyph
+ }
+
+ if (!vartrue($item['link']))
+ {
+ $item['link'] = e_REQUEST_SELF.'?mode='.$tmp[0].'&action='.($tmp[1] ?? 'main').(isset($tmp[2]) ? '&sub='.$tmp[2] : '');
+ }
+
+ if (varset($val['tab']))
+ {
+ $item['link'] .= '&tab=' .$val['tab'];
+ }
+
+ if (!empty($val['modal']))
+ {
+ $item['link_class'] = ' e-modal';
+ if (!empty($val['modal-caption']))
+ {
+ $item['link_data'] = array_merge($item['link_data'] ?? [], ['data-modal-caption' => $val['modal-caption']]);
+ }
+ }
+
+ if (!empty($val['class']))
+ {
$var[$key]['link_class'] ?? '';
$var[$key]['link_class'] .= ' '.$val['class'];
- }
-
- }
-
-
- if(empty($var))
- {
- return '';
- }
-
- $request = $this->getRequest();
- if(!$selected)
- {
- $selected = $request->getMode() . '/' . $request->getAction();
- }
- $selected = vartrue($this->adminMenuAliases[$selected], $selected);
-
- $icon = '';
-
- if(!empty($this->adminMenuIcon))
- {
- $icon = e107::getParser()->toIcon($this->adminMenuIcon);
- }
- elseif(deftrue('e_CURRENT_PLUGIN'))
- {
- $icon = e107::getPlug()->load(e_CURRENT_PLUGIN)->getIcon(24);
- }
-
- $toggle = "";
-
- $var['_extras_'] = array('icon'=> $icon, 'return'=>true);
-
- // $var['_icon_'] = $icon;
-
- return e107::getNav()->admin($this->menuTitle, $selected, $var);
- }
+ }
+ return $item;
+}
/**
* Render Help Text in format. XXX TODO
@@ -4910,7 +4947,7 @@ class e_admin_controller_ui extends e_admin_controller
* @param mixed $qryField Specific query field(s) to filter.
* @param mixed $isfilter Determines if a specific filter is applied.
* @param mixed $handleAction Custom action handler for the search process.
- * @return string
+ * @return string|false
*/
public function _modifyListQrySearch(string|null $listQry, string $searchTerm, string $filterOptions, string $tablePath, string $tableFrom, string|null $primaryName, $raw, $orderField, $qryAsc, $forceFrom, int $qryFrom, $forceTo, int $perPage, $qryField, $isfilter, $handleAction)
{
diff --git a/e107_handlers/sitelinks_class.php b/e107_handlers/sitelinks_class.php
index 35bac417b..0ddaeda1c 100644
--- a/e107_handlers/sitelinks_class.php
+++ b/e107_handlers/sitelinks_class.php
@@ -1432,7 +1432,7 @@ i.e-cat_users-32{ background-position: -555px 0; width: 32px; height: 32px; }
$temp = varset($tmpl[$tmplateKey]);
}
-
+ $replace['LINK_ID'] = $e107_vars[$act]['link_id'] ?? $rid;
$replace['LINK_TEXT'] = str_replace(" ", " ", varset($e107_vars[$act]['text']));
$replace['LINK_DESCRIPTION'] = varset($e107_vars[$act]['description']);
@@ -1476,7 +1476,7 @@ i.e-cat_users-32{ background-position: -555px 0; width: 32px; height: 32px; }
$dataTmp = array();
foreach($e107_vars[$act]['link_data'] as $k=>$v)
{
- $dataTmp[] = $k.'="'.$v.'"';
+ $dataTmp[] = $k.'="'.$v.'"'; // eg. data-toggle="modal" or data-target="#myModal"
}
$replace['LINK_DATA'] = implode(" ", $dataTmp); // $e107_vars[$act]['link_data']
@@ -1499,9 +1499,11 @@ i.e-cat_users-32{ background-position: -555px 0; width: 32px; height: 32px; }
if(!empty($e107_vars[$act]['sub']))
{
$replace['SUB_ID'] = $id ? " id='eplug-nav-{$rid}-sub'" : '';
- $replace['LINK_CLASS'] = ' '.varset($e107_vars[$act]['link_class'], 'e-expandit');
+ $replace['LINK_CLASS'] = ' '.varset($e107_vars[$act]['link_class'], ''); // e-expandit removed.
$replace['SUB_CLASS'] = ' '.varset($e107_vars[$act]['sub_class'], 'e-hideme e-expandme');
+
+
$replace['SUB_MENU'] = $tp->parseTemplate($START_SUB, false, $replace);
$replace['SUB_MENU'] .= $this->admin(false, $active_page, $e107_vars[$act]['sub'], $tmpl, true, (isset($e107_vars[$act]['sort']) ? $e107_vars[$act]['sort'] : $sortlist));
$replace['SUB_MENU'] .= isset($tmpl['end_sub']) ? $tmpl['end_sub'] : '';
diff --git a/e107_plugins/_blank/admin_config.php b/e107_plugins/_blank/admin_config.php
index 7e0b4e0b2..d374322ae 100644
--- a/e107_plugins/_blank/admin_config.php
+++ b/e107_plugins/_blank/admin_config.php
@@ -46,9 +46,12 @@ class plugin_blank_admin extends e_admin_dispatcher
*/
protected $adminMenu = array(
'main/list' => array('caption'=> 'Manage', 'perm' => '0'),
- 'main/create' => array('caption'=> LAN_CREATE, 'perm' => '0'),
- 'main/prefs' => array('caption'=> 'Settings', 'perm' => '0'),
- 'main/custom' => array('caption'=> 'Custom Page', 'perm' => '0')
+ 'main/create' => array('caption'=> 'LAN_CREATE', 'perm' => '0'),
+ 'main/prefs' => array('caption'=> 'Settings', 'perm' => '0', 'icon'=>'fa-cog'),
+ 'main/custom' => array('caption'=> 'Custom Pages', 'perm' => '0', 'icon'=>'fa-asterisk'),
+ 'main/custom/sub1' => array('caption' => 'Custom Page 1', 'perm' => '0', 'icon' => ''),
+ 'main/custom/sub2' => array('caption' => 'Custom Page 2', 'perm' => '0', 'icon' => ''),
+
);
/**
diff --git a/e107_themes/bootstrap3/css/modern-dark-2.css b/e107_themes/bootstrap3/css/modern-dark-2.css
index 1c8cd02a9..b17a341a5 100644
--- a/e107_themes/bootstrap3/css/modern-dark-2.css
+++ b/e107_themes/bootstrap3/css/modern-dark-2.css
@@ -1574,10 +1574,9 @@ thead th, thead tr, .table > thead > tr > th { border-bottom: 0; border-left:0;
div.admin-left-panel .nav-pills > li > a > span > i { font-size:16px; opacity: 0; width:0; }
div.admin-left-panel .nav-pills > li > a:not(.text-primary):not(.text-success):not(.text-info):not(.text-warning):not(.text-danger):not(.text-muted) > span > i {
color: rgba(255,255,255,0.5);
- font-size: 16px;
- opacity: 0;
- width: 0;
}
+div.admin-left-panel .nav-pills > li.active > a > span > i { color:white !important }
+
div.admin-left-panel-collapsed .nav-pills > li > a > span > i { opacity: 1; padding-left: 2px; }
div.admin-left-panel-collapsed .nav-pills > li.active > a { background:none; }
div.admin-left-panel-collapsed .nav-header.sidebar-toggle-panel { display: none; }