MyBB Hacks

Full Version: MyBB Threadcache
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have been working on extending a plugin (favourite threads by Starpaul). I wanted to show on forumdisplay to a user if they had already favourited a thread.

I was able to do that, but at the cost of 2 queries per thread; the user and the tid. Not a good plan.

I looked at how MyBB get the doticons out as that seemed like a similar function, and indeed I was able to hack the core file to repurpose the doticons. But that feels like a wrong thing to do, as now I dont have any doticons.

So I added a function to the plugin, trying to get my data added to the threadcache so I could have less queries on my page.

This is my function:

PHP Code:
$plugins->add_hook("forumdisplay_thread", "favorites_added");

//Starpaul code is all here

//My function

function favorites_added()
{
	global $db, $mybb, $templates, $thread, $theme, $lang, $favorites;
	$lang->load("favorites");
	
	// Check faves by the current user in any of these threads
	
	if($mybb->user['uid'] && !empty($threadcache))
	{
		$query = $db->simple_select("favorites", "tid,uid", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})");
		while($thread = $db->fetch_array($query))
		{
			if($threadcache[$thread['tid']])
			{
				$threadcache[$thread['tid']]['favorites'] = 1;
			}

		}

	}
	if($thread['favorites'] == 1)
		{
		$thread['fave'] = "HELLO";
		}
}


and unsurprisingly it does not work. Please can you help me get this right as I think this would be useful for other plugins I might make. Thank you.

You need to check that you're actually global'ing the variables you're referencing, like $tids.

I also don't recommend modifying MyBB's $threadcache - use your own variable instead.

There's quite a number of other problems with the code, but start off with the above two.
ok, I have reached a point where things are sort of working, but I am struggling on the way hooks actually work in MyBB. If this was a custom page I would get a bit further, but yea, its forumdisplay. My foreach is a disaster and I am unsure how to actually find the values of the array I get from the database so I know what the code is that I have extracted. I have tried with var_dump but no dice. Frown

How does the hook actually work? Does it take into account/ allow access to all variables arrays etc after the hook or before the hook?
forumdisplay_thread will give you access to the $thread variable, which basically is the whole thread it self.

I would rather investigate the possibility of hooking at forumdisplay_get_threads to hijack or modify the query to join the favorites table. If that works (it should one way or another, even if dirty) then just hook at forumdisplay_thread with something like:

PHP Code:
function favorites_added()
{
	global $thread;

	if(isset($thread['favorite']))
	{
		$thread['favorite'] = 'HELLO';
	}
}


If you are unable to hijack/modify the query you can simple run your own in there appending its value to $threadcache. You already have this query in your original code.

Thanks Omar, I have been looking at the hooks and trying to figure it out and did try forumdisplay_get_threads but no result.

It does seem indeed that I need to add two functions; one at forumdisplay_start (maybe) or in get_threads and then another in forumdisplay_thread. I have had a look at a couple of plugins that use a cache, but they so far they all seem to actually query on every thread on the page (so not what I saw as a cache).

Not giving up, but still a bit confused on which point of the hook the code works on.

For example, get threads starts the foreach for thread cache

Code:
foreach($threadcache as $thread)
	{
		$plugins->run_hooks("forumdisplay_thread");


So If I use that hook is my code already part of the foreach loop?

Think of hooks like replacing the 'run_hooks' line with your own code.

eg

PHP Code:
open_eyes();
$plugins->run_hooks('blank_stare');
close_eyes();

-- your plugin --
$plugins->add_hook('blank_stare', 'hands_in_the_air');
function hands_in_the_air() {
  if($hands != 'in_air') {
    $hands = 'in_air';
  }
}

is kinda like:

PHP Code:
open_eyes();
  if($hands != 'in_air') {
    $hands = 'in_air';
  }
close_eyes();

Focus only in the forumdisplay_thread hook Leefish, that is everything you need. I tried what I commented before and failed (forumdisplay_get_threads).

If you have worked with postbit hooks then a foreach loop isn't going to be an issue to understand.
If I use the forumdisplay hook then the code runs for each thread - which is pointless to have a cache. Can I use the &$thread like I would on a postbit plugin?
(03-01-2015 02:20 PM)leefish Wrote: [ -> ]If I use the forumdisplay hook then the code runs for each thread - which is pointless to have a cache.
You can still have a cache.  You just need to ensure that it's only ever loaded once.  Typical pattern looks something like

PHP Code:
function bleh() {
static $something_cache;
if(!isset($something_cache)) {
  $something_cache = load_cache();
}

$item['value'] = $something_cache[$item['id']]['verifiability'];

}

Quote:Can I use the &$thread like I would on a postbit plugin?

Something like that, just than only instead of:
Quote:function bleh(&$thread)
{

You will use:
Quote:function bleh()
{
global $thread;

$thread is not passes by reference here but is on the global scope.

Mege with Zinga Burga's code and you will have something like this:

PHP Code:
function bleh() {
global $thread;
static $something_cache;
if(!isset($something_cache)) {
  $something_cache = load_cache();
}

$thread['favorites'] = $something_cache[$thread['tid']]['favorites'];

}

Reference URL's