TP-Docs
HTML5 Icon HTML5 Icon HTML5 Icon
TP on Social Media

Recent

Welcome to TinyPortal. Please login or sign up.

July 20, 2024, 08:04:02 PM

Login with username, password and session length
Members
Stats
  • Total Posts: 195,333
  • Total Topics: 21,233
  • Online today: 133
  • Online ever: 3,540 (September 03, 2022, 01:38:54 AM)
Users Online
  • Users: 1
  • Guests: 90
  • Total: 91
  • @rjen

Suggestion: Forum Navigation in Sidebar

Started by likeatim, January 06, 2006, 10:48:48 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Rasyr

Update - it seems that $context only holds the category information when you are on the BoardIndex.template.php page. I think that I am going to have to learn how to write me a function to handle this.

A lot more work than I had thought, but I think it would be something neat, and if I can get it figured out, maybe bloc would consider adding it as a future feature. :)


likeatim


Rasyr

BOOYAH!!!!! I actually did it! (yes, I surprised myself!!  :2funny: )

I now have the code that allows you to display the categories, forums and child forums in a phpbox. It also uses the forum permissions to determine what gets displayed.

Ok, there are several different things that you will have to add to various files to get this to work. Also, this code is ugly, and if somebody who knows how to program php better than I do (which is likely to be anybody who knows how to program in php) wants to give a hand to help clean it up, I know that I would be very appreciative.

Okay, I will explain what I did and give you the different bits to add as we go along.

First off, I discovered (through lots of trial and error and a large number of var_dumps() into a phpbox (and boy was that messy....  ;D) that there is a setting in the global $context that only gets loaded when you are looking at the BoardIndex.

Therefore, I cut-n-paste a large portion of that code into a new function. I put this function in load.php in the Sources directory (I put it at the bottom). This is where I could use some help/advice on how to clean up the database call. Rather than mess with stuff I know nothing about, I left the DB call as it was, so it pulls a lot of extra information, but that is okay since we do not actually use most of it, and once we set this information, the function won't make the DB call a second time (I cribbed this from another function - hehe).

Okay, so you will want to copy the following and post it into the bottom of Load.php before the closing ?> tag.



function loadBoardList()
{
global $txt, $scripturl, $db_prefix, $ID_MEMBER, $user_info, $sourcedir;
global $modSettings, $context, $settings;

if (isset($context['menuList']))
return;

// Find all boards and categories, as well as related information.  This will be sorted by the natural order of boards and categories, which we control.
$result_boards = db_query("
SELECT
c.name AS catName, c.ID_CAT, b.ID_BOARD, b.name AS boardName, b.description,
b.numPosts, b.numTopics, b.ID_PARENT, IFNULL(m.posterTime, 0) AS posterTime,
IFNULL(mem.memberName, m.posterName) AS posterName, m.subject, m.ID_TOPIC,
IFNULL(mem.realName, m.posterName) AS realName," . (!$user_info['is_guest'] ? "
(IFNULL(lb.logTime, 0) >= b.lastUpdated) AS isRead, c.canCollapse,
IFNULL(cc.ID_MEMBER, 0) AS isCollapsed" : ' 1 AS isRead') . ",
IFNULL(mem.ID_MEMBER, 0) AS ID_MEMBER, m.ID_MSG,
IFNULL(mods_mem.ID_MEMBER, 0) AS ID_MODERATOR, mods_mem.realName AS modRealName
FROM {$db_prefix}boards AS b
LEFT JOIN {$db_prefix}categories AS c ON (c.ID_CAT = b.ID_CAT)
LEFT JOIN {$db_prefix}messages AS m ON (m.ID_MSG = b.ID_LAST_MSG)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)" . (!$user_info['is_guest'] ? "
LEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = b.ID_BOARD AND lb.ID_MEMBER = $ID_MEMBER)
LEFT JOIN {$db_prefix}collapsed_categories AS cc ON (cc.ID_CAT = c.ID_CAT AND cc.ID_MEMBER = $ID_MEMBER)" : '') . "
LEFT JOIN {$db_prefix}moderators AS mods ON (mods.ID_BOARD = b.ID_BOARD)
LEFT JOIN {$db_prefix}members AS mods_mem ON (mods_mem.ID_MEMBER = mods.ID_MEMBER)
WHERE $user_info[query_see_board]" . (empty($modSettings['countChildPosts']) ? "
AND b.childLevel <= 1" : ''), __FILE__, __LINE__);

// Run through the categories and boards....
$context['menuList'] = array();
while ($row_board = mysql_fetch_assoc($result_boards))
{
// Haven't set this category yet.
if (empty($context['menuList'][$row_board['ID_CAT']]))
{
$context['menuList'][$row_board['ID_CAT']] = array(
'id' => $row_board['ID_CAT'],
'name' => $row_board['catName'],
'href' => $scripturl . '#' . $row_board['ID_CAT'],
'boards' => array(),
);
$context['menuList'][$row_board['ID_CAT']]['link'] = '<a name="' . $row_board['ID_CAT'] . '" href="' . (isset($row_board['canCollapse']) ? $context['menuList'][$row_board['ID_CAT']]['collapse_href'] : $context['menuList'][$row_board['ID_CAT']]['href']) . '">' . $row_board['catName'] . '</a>';
}

// Let's save some typing.  Climbing the array might be slower, anyhow.
$this_category = &$context['menuList'][$row_board['ID_CAT']]['boards'];

// This is a parent board.
if (empty($row_board['ID_PARENT']))
{
// Is this a new board, or just another moderator?
if (!isset($this_category[$row_board['ID_BOARD']]))
{
// Not a child.
$isChild = false;

$this_category[$row_board['ID_BOARD']] = array(
'id' => $row_board['ID_BOARD'],
'name' => $row_board['boardName'],
'children' => array(),
'link_children' => array(),
'children_new' => false,
'href' => $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0',
'link' => '<a href="' . $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0">' . $row_board['boardName'] . '</a>'
);
}
if (!empty($row_board['ID_MODERATOR']))
{
$this_category[$row_board['ID_BOARD']]['moderators'][$row_board['ID_MODERATOR']] = array(
'id' => $row_board['ID_MODERATOR'],
'name' => $row_board['modRealName'],
'href' => $scripturl . '?action=profile;u=' . $row_board['ID_MODERATOR'],
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_board['ID_MODERATOR'] . '" title="' . $txt[62] . '">' . $row_board['modRealName'] . '</a>'
);
$this_category[$row_board['ID_BOARD']]['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $row_board['ID_MODERATOR'] . '" title="' . $txt[62] . '">' . $row_board['modRealName'] . '</a>';
}
}
// Found a child board.... make sure we've found its parent and the child hasn't been set already.
elseif (isset($this_category[$row_board['ID_PARENT']]['children']) && !isset($this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']]))
{
// A valid child!
$isChild = true;

$this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']] = array(
'id' => $row_board['ID_BOARD'],
'name' => $row_board['boardName'],
'description' => $row_board['description'],
'href' => $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0',
'link' => '<a href="' . $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0">' . $row_board['boardName'] . '</a>'
);
}

}
mysql_free_result($result_boards);
}



The next step is quite easy. You need to add the following lines to index.php in the root of the forum's directory.

Find:


// Load the current user's permissions.
loadPermissions();



And add the following beneath it:



//Create the Board Listing for use in a menu
loadBoardList();



Whew! Not so bad so far.... Now comes the fun part, actually making your menu....

Okay, in TPAdmin, you will want to add a phpbox, and in that box you will want to paste the following or a variation of it:



global $context, $settings, $options, $txt, $scripturl, $modSettings;
foreach ($context['menuList'] as $category)
{
echo '<b style="color: Maroon;">' . $category['name'] . '</b><br />';
foreach ($category['boards'] as $board)
{
echo '<img src="'.$settings['images_url'].'/divider.gif" alt="" /> <a href="'. $board['href'] . '">'. $board['name'] . '</a><br />';
// Show the "Child Boards:
foreach ($board['children'] as $child)
{
echo '<img src="'.$settings['images_url'].'/blank.gif" width="5" alt="" /> <img src="'.$settings['images_url'].'/divider.gif" alt="" /> <a href="' . $child['href'] . '">' . $child['name'] . '</a><br />';
}
}
}



This makes a simple list like the one shown in the image below. You can adjust the code in various ways to style it, put it in table cells, etc.. The important parts are the foreach loops, you don't really want to mess with them.  ;D


And yes, when I logged in under a test account, I was unable to see the Playtester forum as I had set it so that only the Admin could see it in the forum permissions.

So, there you go! Enjoy!



likeatim

wow, kewl! thanks so much, I'll add it to my portal and give some feedback...

Nokonium

I just have to go and have a fiddle with that don't I  ;D GREAT!

bloc

Great. :) Thats how one learn these things really...diving right in.

Now, 2 things..you already mentioned one, that of loading in all the "extras" but not using them, the thing is that the mysql resource will still use the memory needed, so the mysql call should really be shrinked.

The other thing..you should not really load all that on every page call, which adding it to index.php will do. Instead, try add the call in the actual block before your output code. That means getting it only when that blockcode is executed. ...Save the poor server. :)

Rasyr

Quote from: Bloc on January 09, 2006, 01:04:18 AM
Great. :) Thats how one learn these things really...diving right in.

That's how I usually learn anything...  :D 

Quote from: Bloc on January 09, 2006, 01:04:18 AM
Now, 2 things..you already mentioned one, that of loading in all the "extras" but not using them, the thing is that the mysql resource will still use the memory needed, so the mysql call should really be shrinked.

Yeah, I know. I will be working on whittling down that SQL string for the DB call, but I want to be very careful with it as that is a complex string, much more so than any I have ever worked with before.

Quote from: Bloc on January 09, 2006, 01:04:18 AM
The other thing..you should not really load all that on every page call, which adding it to index.php will do. Instead, try add the call in the actual block before your output code. That means getting it only when that blockcode is executed. ...Save the poor server. :)

Well, the issue here is that for it to be a used in a block, it would end up getting called every page as well.

Also, I did put the following lines in the block:



if (isset($context['menuList']))
return;


which means that it dumps out of the function prior to doing the DB call and cuts it short once the values have been added to $context. It also just occured to me that that IF statement could be placed around the function call on the index page, so that it never calls the function at all if it is already set. Does that make any sense?


likeatim

also, maybe the sql-results could be cached? because one rarely changes the board structure many times a day, and then one could force a rewrite  of the cached forum structure....

Rasyr

They are cached, after a a fashion. $context is a global variable, and it hold all sorts of information. The above function stores its results in $context when the function is first run. At that point, the function isn't needed to be called again. (thus moving the IF statement from inside the function to being a wrapper around it. However, this means that I would need to add a line of code to the functions which post changes made to the Boards (i.e. adding/deleting a category or forum) that unsets $context('menu') and thus allows the function to be called again.


bloc

$context is a run-time variable, it will be renewed on every pageload.

If this was a dedicated blocktype, it could save the results into the blocks table, and have a setting for when it was refreshed, say once a day. At least then this would be fetched in one call along with the rest of the blocks, thus not adding any separate calls for it.

As of now it works ok..the key is to minimise the db call so much that it won't impact on peformance. Meaning less of the left joins and not used fields.