334 lines
7.5 KiB
Ucode
334 lines
7.5 KiB
Ucode
|
/**
|
||
|
* Menu manager for the webadmin
|
||
|
*
|
||
|
* Copyright 2008 Epic Games, Inc. All Rights Reserved
|
||
|
*
|
||
|
* @author Michiel 'elmuerte' Hendriks
|
||
|
*/
|
||
|
class WebAdminMenu extends Object;
|
||
|
|
||
|
struct MenuItem
|
||
|
{
|
||
|
/**
|
||
|
* The absolute path (from the webapp path). Examples:
|
||
|
* foo
|
||
|
* foo/bar/quux
|
||
|
* bar
|
||
|
* bar/quux
|
||
|
* bar/quux2
|
||
|
* bar/quux2+data
|
||
|
*
|
||
|
* The bar/quux2+data item will be considered as a sub page of bar/quux2
|
||
|
* When checking for permissions bar/quux2 will be used instead of
|
||
|
* bar/quux2+data
|
||
|
*/
|
||
|
var string path;
|
||
|
/**
|
||
|
* The path to use for permission checking. Will default to path
|
||
|
*/
|
||
|
var string permPath;
|
||
|
/**
|
||
|
* Title of the menu item. If empty the menu item is not shown in the
|
||
|
* rendered menu
|
||
|
*/
|
||
|
var string title;
|
||
|
/**
|
||
|
* A short description
|
||
|
*/
|
||
|
var string description;
|
||
|
/**
|
||
|
* The weight of this item. A low number means it will be higher in the list.
|
||
|
*/
|
||
|
var int weight;
|
||
|
/**
|
||
|
* If true, the menu item is not rendered. Can be used to hide previously
|
||
|
* visible menu items from the navigation menu.
|
||
|
*/
|
||
|
var bool hidden;
|
||
|
/**
|
||
|
* The handler responsible for handling this menu item.
|
||
|
*/
|
||
|
var IQueryHandler handler;
|
||
|
};
|
||
|
|
||
|
var array<MenuItem> menu;
|
||
|
|
||
|
var WebAdmin webadmin;
|
||
|
|
||
|
struct TreeItem
|
||
|
{
|
||
|
/**
|
||
|
* Index to the item in the menu list;
|
||
|
*/
|
||
|
var int cur;
|
||
|
/**
|
||
|
* Path element
|
||
|
*/
|
||
|
var string elm;
|
||
|
var array<int> children;
|
||
|
};
|
||
|
|
||
|
var array<TreeItem> tree;
|
||
|
|
||
|
/**
|
||
|
* Add an item to the menu, or if the path already exist, update an existing
|
||
|
* item. To create a hidden item simply leave out the title.
|
||
|
*/
|
||
|
function addMenuItem(MenuItem item)
|
||
|
{
|
||
|
local int idx;
|
||
|
idx = menu.find('path', item.path);
|
||
|
if (len(item.permPath) == 0)
|
||
|
{
|
||
|
item.permPath = item.path;
|
||
|
}
|
||
|
if (idx > -1)
|
||
|
{
|
||
|
menu[idx].title = item.title;
|
||
|
menu[idx].description = item.description;
|
||
|
menu[idx].weight = item.weight;
|
||
|
menu[idx].handler = item.handler;
|
||
|
}
|
||
|
else {
|
||
|
menu.addItem(item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add a new menu item (or overwrite the previous for the given path).
|
||
|
*/
|
||
|
function addMenu(string path, string title, IQueryHandler handler,
|
||
|
optional string description = "", optional int weight = 0,
|
||
|
optional string permPath = "")
|
||
|
{
|
||
|
local MenuItem item;
|
||
|
item.path = path;
|
||
|
item.title = title;
|
||
|
item.description = description;
|
||
|
item.weight = weight;
|
||
|
item.handler = handler;
|
||
|
item.permPath = permPath;
|
||
|
item.hidden = len(title) == 0;
|
||
|
addMenuItem(item);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the menu handler for a given path
|
||
|
*/
|
||
|
function IQueryHandler getHandlerFor(string path, out string title, out string desc)
|
||
|
{
|
||
|
local int idx;
|
||
|
idx = menu.find('path', path);
|
||
|
if (idx > -1)
|
||
|
{
|
||
|
title = menu[idx].title;
|
||
|
desc = menu[idx].description;
|
||
|
return menu[idx].handler;
|
||
|
}
|
||
|
return none;
|
||
|
}
|
||
|
|
||
|
function setVisibility(string path, bool isVisible)
|
||
|
{
|
||
|
local int idx;
|
||
|
idx = menu.find('path', path);
|
||
|
if (idx > -1)
|
||
|
{
|
||
|
menu[idx].hidden = !isVisible;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* return the menu instance of the given user. All paths to which the user has
|
||
|
* no access will be filtered from the list.
|
||
|
*
|
||
|
* @return none when the user has absolutely no access, otherwise an instance is
|
||
|
* returned that only contains the paths the user has access to.
|
||
|
*/
|
||
|
function WebAdminMenu getUserMenu(IWebAdminUser forUser)
|
||
|
{
|
||
|
local WebAdminMenu result;
|
||
|
local MenuItem entry, dummy;
|
||
|
|
||
|
if (!forUser.canPerform(webadmin.getAuthURL("/")))
|
||
|
{
|
||
|
return none;
|
||
|
}
|
||
|
|
||
|
result = new(webadmin) class; // create a new instance this class
|
||
|
result.webadmin = webadmin;
|
||
|
foreach menu(entry)
|
||
|
{
|
||
|
if (forUser.canPerform(webadmin.getAuthURL(entry.permPath)))
|
||
|
{
|
||
|
result.addSortedItem(entry);
|
||
|
}
|
||
|
else {
|
||
|
dummy.path = entry.path;
|
||
|
dummy.weight = entry.weight;
|
||
|
result.addSortedItem(dummy);
|
||
|
}
|
||
|
}
|
||
|
result.createTree();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Add a menu item to the list sorting on the full path.
|
||
|
*/
|
||
|
protected function addSortedItem(MenuItem item)
|
||
|
{
|
||
|
local MenuItem entry;
|
||
|
local int idx;
|
||
|
foreach menu(entry, idx)
|
||
|
{
|
||
|
if (entry.path > item.path)
|
||
|
{
|
||
|
menu.InsertItem(idx, item);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
menu.AddItem(item);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses the sorted list of menu items and creates the tree.
|
||
|
*/
|
||
|
protected function createTree()
|
||
|
{
|
||
|
local MenuItem entry;
|
||
|
local int idx;
|
||
|
|
||
|
local int i, idx2, parent, child;
|
||
|
local array<string> parts;
|
||
|
local bool found;
|
||
|
|
||
|
tree.Length = 1;
|
||
|
tree[0].cur = -1;
|
||
|
|
||
|
foreach menu(entry, idx)
|
||
|
{
|
||
|
ParseStringIntoArray(entry.path, parts, "/", true);
|
||
|
parent = 0;
|
||
|
i = 0;
|
||
|
|
||
|
// find the parent item
|
||
|
while (i < parts.length-1)
|
||
|
{
|
||
|
found = false;
|
||
|
foreach tree[parent].children(child)
|
||
|
{
|
||
|
if (tree[child].elm == parts[i])
|
||
|
{
|
||
|
i++;
|
||
|
parent = child;
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!found)
|
||
|
{
|
||
|
// create a dummy item
|
||
|
tree.Add(1);
|
||
|
tree[tree.length-1].cur = -1;
|
||
|
tree[tree.length-1].elm = parts[i];
|
||
|
tree[parent].children.AddItem(tree.length-1);
|
||
|
parent = tree.length-1;
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// add the item
|
||
|
found = false;
|
||
|
foreach tree[parent].children(child, idx2)
|
||
|
{
|
||
|
if (menu[tree[child].cur].weight > entry.weight)
|
||
|
{
|
||
|
tree[parent].children.Insert(idx2, 1);
|
||
|
tree[parent].children[idx2] = tree.length;
|
||
|
tree.Add(1);
|
||
|
tree[tree.length-1].cur = idx;
|
||
|
tree[tree.length-1].elm = parts[parts.length-1];
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!found)
|
||
|
{
|
||
|
idx2 = tree[parent].children.length;
|
||
|
tree[parent].children.add(1);
|
||
|
tree[parent].children[idx2] = tree.length;
|
||
|
tree.Add(1);
|
||
|
tree[tree.length-1].cur = idx;
|
||
|
tree[tree.length-1].elm = parts[parts.length-1];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render the current menu tree to a navigation menu
|
||
|
*/
|
||
|
function string render(optional string menu_template = "/navigation_menu.inc",
|
||
|
optional string item_template = "/navigation_item.inc")
|
||
|
{
|
||
|
local string result;
|
||
|
local WebResponse wr;
|
||
|
local MenuItem entry;
|
||
|
local array<MenuItem> menuCopy;
|
||
|
|
||
|
wr = new class'WebResponse';
|
||
|
if (tree.Length == 0)
|
||
|
{
|
||
|
menuCopy = menu;
|
||
|
menu.length = 0;
|
||
|
foreach menuCopy(entry)
|
||
|
{
|
||
|
addSortedItem(entry);
|
||
|
}
|
||
|
createTree();
|
||
|
}
|
||
|
result = renderChilds(tree[0].children, wr, menu_template, item_template);
|
||
|
wr.subst("navigation.items", result);
|
||
|
return wr.LoadParsedUHTM(webadmin.path$menu_template);
|
||
|
}
|
||
|
|
||
|
protected function string renderChilds(array<int> childs, WebResponse wr,
|
||
|
optional string menu_template = "/navigation_menu.inc",
|
||
|
optional string item_template = "/navigation_item.inc")
|
||
|
{
|
||
|
local int child, menuid;
|
||
|
local string result, subitems;
|
||
|
foreach childs(child)
|
||
|
{
|
||
|
menuid = tree[child].cur;
|
||
|
if ((menuid > -1) && !menu[menuid].hidden && (Len(menu[menuid].title) > 0))
|
||
|
{
|
||
|
if (tree[child].children.length > 0)
|
||
|
{
|
||
|
subitems = renderChilds(tree[child].children, wr, menu_template, item_template);
|
||
|
if (len(subitems) > 0)
|
||
|
{
|
||
|
wr.subst("navigation.items", subitems, true);
|
||
|
subitems = wr.LoadParsedUHTM(webadmin.path$menu_template);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
subitems = "";
|
||
|
}
|
||
|
wr.subst("item.submenu", subitems, true);
|
||
|
wr.subst("item.type", tree[child].children.length > 0?"with-submenu":"no-submenu");
|
||
|
wr.subst("item.path", webadmin.path$menu[menuid].path);
|
||
|
wr.subst("item.menupath", menu[menuid].path);
|
||
|
wr.subst("item.title", menu[menuid].title);
|
||
|
wr.subst("item.description", menu[menuid].description);
|
||
|
result $= wr.LoadParsedUHTM(webadmin.path$item_template);
|
||
|
}
|
||
|
else if (tree[child].children.length > 0)
|
||
|
{
|
||
|
result $= renderChilds(tree[child].children, wr, menu_template, item_template);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|