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");
function favorites_added()
{
global $db, $mybb, $templates, $thread, $theme, $lang, $favorites;
$lang->load("favorites");
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.
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'];
}
|