How To Use Template Hooks

lasertits

Active member
Well I've run into another bump in the road, can't get this to work.

Here's what I have going on. I've got a plague_message_bar template, containing:
Code:
<xen:require css="plague_message_bar.css" />
<div class="plagueMessageBarContainer">
    <xen:hook name="group_tags" params="{xen:array 'user={$user}', 'isQuickReply={$isQuickReply}'}">
        <div class="plagueMessageBarUsername">
            <xen:username user="$user" itemprop="name" rich="true" />
        </div>
    </xen:hook>
</div>
This is added to the message_content hook with the following listener:

Code:
            case 'message_content';
            {
                $mergedParams = array_merge($template->getParams(), $hookParams);
                $pos = strpos($contents, '<div class="messageContent">');
                $contents = substr($contents, 0, $pos) . $template->create('plague_message_bar', $mergedParams) . substr($contents, $pos);
                break;
            }
What I'm basically trying to do, is pull the username of the message author and slap it in my custom plague_message_bar template, rather than having it inside message_user_info.

The group_tags hook is for another listener which adds content AFTER (or to the right of) the username, this will be my next area to tackle once I can get the usernames going, also I should note the group_tags listener is disabled so it shouldn't be affecting my attempts to get the usernames to work.

Here's the error I get on thread / conversation views when it loads my plague_message_bar template:

Code:
Template Errors: plague_message_bar

    Argument 1 passed to XenForo_Template_Helper_Core::helperUserNameHtml() must be an array, null given in /*removed*/library/XenForo/Template/Helper/Core.php, line 1488
    Argument 1 passed to XenForo_Template_Helper_Core::helperRichUserName() must be an array, null given in /*removed*/library/XenForo/Template/Helper/Core.php, line 878
    Argument 1 passed to XenForo_Template_Helper_Core::getUserHref() must be an array, null given, called in /*removed*/library/XenForo/Template/Helper/Core.php on line 1500 and defined in /*removed*/library/XenForo/Template/Helper/Core.php, line 1389

Template Errors: plague_message_bar

    Argument 1 passed to XenForo_Template_Helper_Core::helperUserNameHtml() must be an array, null given in /*removed*/library/XenForo/Template/Helper/Core.php, line 1488
    Argument 1 passed to XenForo_Template_Helper_Core::helperRichUserName() must be an array, null given in /*removed*/library/XenForo/Template/Helper/Core.php, line 878
    Argument 1 passed to XenForo_Template_Helper_Core::getUserHref() must be an array, null given, called in /*removed*/library/XenForo/Template/Helper/Core.php on line 1500 and defined in /*removed*/library/XenForo/Template/Helper/Core.php, line 1389

Template Errors: plague_message_bar

    Argument 1 passed to XenForo_Template_Helper_Core::helperUserNameHtml() must be an array, null given in /*removed*/library/XenForo/Template/Helper/Core.php, line 1488
    Argument 1 passed to XenForo_Template_Helper_Core::helperRichUserName() must be an array, null given in /*removed*/library/XenForo/Template/Helper/Core.php, line 878
    Argument 1 passed to XenForo_Template_Helper_Core::getUserHref() must be an array, null given, called in /*removed*/library/XenForo/Template/Helper/Core.php on line 1500 and defined in /*removed*/library/XenForo/Template/Helper/Core.php, line 1389
I'm pretty stumped. Where's my mistake(s) in all this? :confused:

Thanks
 

Robbo

Well-known member
Try just with $template->getParams() instead of $mergedParams.

The problem you are getting is $user is not as expected.

Off topic a bit...
I don't actually see the point of $hookParams in template hooks since you can get them all with $template->getParams(). Template hooks are in general very limiting. I have to do a lot of DOM parsing in certain areas which is slow and not something I want to do all the time on certain areas.
 

lasertits

Active member
In regards to hookParams, I was following kier's post here: http://xenforo.com/community/threads/how-to-use-template-hooks.13167/page-2#post-175362

I also tried $template->getParams(), as I use this on just about everything else, but no dice.

However, looking back at it, message_content doesn't contain params to do with $user..

Code:
<xen:hook name="message_content" params="{xen:array 'message={$message}'}">
I think I'm confusing myself quite a bit here... I feel as if a d'oh moment is on its way.
 

Robbo

Well-known member
Yeah I didn't say the merge stuff was wrong. Just wanted to see if that was the issue. $user isn't set so you are doing something wrong somewhere... no idea though.
 

lasertits

Active member
At this point I'm not even sure what's right or wrong. I think I need to take a step back and reevaluate this after some :sleep:

Thanks for the assistance anyway.
 

Luciano

Member
Heres my 2 cents...
i would just do some basic debugging. i.e. add the red lines to the code to see if the content of the arrays are as you expect them to be and if the vars fit into your template:
case 'message_content';
{

$mergedParams = array_merge($template->getParams(), $hookParams);

$the_params = $template->getParams();
print "<pre>";
print "<br /> -------------------------------- <br /> <br />template->getParams():<br />";
print_r($the_params);
print "<br /><br /> -------------------------------- <br /> <br />hookparams:<br />";
print_r($hookParams);
print "<br /><br /> -------------------------------- <br /> <br />mergedParams:<br />";
print_r($mergedParams);
exit;

$pos = strpos($contents, '<div class="messageContent">');
$contents = substr($contents, 0, $pos) . $template->create('plague_message_bar', $mergedParams) . substr($contents, $pos);
break;
}
you can do it in a more elegant way, but for me this method usually is good enough
Luc
 

Robbo

Well-known member
Unless you have a lot of memory spare then don't do that dump. $template->getParams() has a LOT of data. Browser will probably crash. Do the same thing but just dump the 'user' in various areas as that is the key causing the problem.

Edit: also a slightly more elegant way is to use Zend_Debug::dump().
 

Luciano

Member
you are absolutely right @robbo
I do it that way when i'm in hurry (and I do it only on localhost dev environment with a win7 machine and firefox - i actually never went out of mem.)

@lasertits
at first sight, the username would be in: $hookParams['message']['username']
so you would have to create the $user, from the hookParams and format it as needed,
example:
$userparams['user'] = array(
'user_id' => $hookParams['message']['user_id'],
'username' => $hookParams['message']['username'],
'display_style_group_id' => $hookParams['message']['display_style_group_id']
);
not quite sure what other elements you need, but I think this should be the basic idea...
then adding the $userparams instead of the $mergedparams when creating template

Luc
 

lasertits

Active member
you are absolutely right @robbo
I do it that way when i'm in hurry (and I do it only on localhost dev environment with a win7 machine and firefox - i actually never went out of mem.)

@lasertits
at first sight, the username would be in: $hookParams['message']['username']
so you would have to create the $user, from the hookParams and format it as needed,
example:
$userparams['user'] = array(
'user_id' => $hookParams['message']['user_id'],
'username' => $hookParams['message']['username'],
'display_style_group_id' => $hookParams['message']['display_style_group_id']
);
not quite sure what other elements you need, but I think this should be the basic idea...
then adding the $userparams instead of the $mergedparams when creating template

Luc
Thanks a lot for this, it actually works, but so does another suggestion I received. I'll put them both here in case someone else finds it useful.

Luc's code (which works with $user inside the template):

PHP:
            case 'message_notices';
            {
                $userParams['user'] = array(
                    'user_id' => $hookParams['message']['user_id'],
                    'username' => $hookParams['message']['username'],
                    'display_style_group_id' => $hookParams['message']['display_style_group_id']
                    );
                $userParams = array_merge($template->getParams(), $hookParams);
                $contents = $template->create('plague_message_bar', $userParams) . $contents;
                break;
            }
This spit out the usernames and linked to them just as I wanted.

However, this code also works, but within the plague_message_bar template $user had to be changed to $message:

PHP:
            case 'message_notices';
            {
                $mergedParams = array_merge($template->getParams(), $hookParams);
                $myTemplate = $template->create('plague_message_bar', $mergedParams);
                $rendered = $myTemplate->render();
                $contents = $contents . $rendered;
                break;
            }
Credit to Fuhrmann on that last one. I guess my curiosity is now diverted toward which one would be the better one to use? Or perhaps it doesn't make much difference? I'm not going to need other info in the plague_message_bar other than username and groups. Groups will be handled with that group_tags hook, hopefully utilizing code such as this:

Code:
        <xen:if is="{xen:helper ismemberof, $user, 3}">
            <div class="groupTag.gManagement">Management</div>
        </xen:if>
I'm now curious if the above will spit out any array errors when I turn on the group_tags listener... guess I'll just have to find out and see either of the two listener codes above also work for group_tags...


I also might want to pull info from one of the identities... but I'll cross this bridge when I come to it.

Thanks again for all the help & insight. You guys are life savers. :D
 

Luciano

Member
stupid question..
if you are only populating the template with username. Why do you need $template->getParams()??
IMHO if you are only going to use this template here.. (i meen not using it somewhere where you have the param $user) you can use $message without a problem.
but then the shortest code would be:
Code:
            case 'message_notices';
            {
                $contents = $contents . $template->create('plague_message_bar', $hookParams);
                break;
            }
no need to array_merge as the "message" part is contained in $hookParams... and those are the only ones you need
(as I am not in front of my computer... I dont know if you need the ->render(); at the end of the line.. (maybe it works without it.. try..)

anyway I would also cache the plague_message_bar template as it will be used in every post. (You can see how it is done in Kiers tutorial).

(as to the code snippet you posted with my code above.. it should NOT work like that, because the array_merge line is overwriting the$userParams['user'] ... strange.. )

Luc

PS: I dont know why the text in this post turns green after [ /code] and also after some ->render(); more than strange.. (or was it because i copy/paste from editor????)
 

Morgain

Well-known member
I've watched that video several times and I'm no wiser.
I understood before I watched it that a "hook" is a place where the template can call in extra stuff from outside. So the basic template can trot on undisturbed, with extras not being a disruption. If I didn't understand that I wouldn't have been interested in the video.
I also understand the desirability because of upgrading. It also seems tidier to leave the core templates alone anyway: easier to keep track of changes.

But having explained that much Kier suddenly plunges into "listeners" and "callbacks" without saying what they are.
I kept going and watched it several times in case an overview helped it to make sense. It doesn't.
Sigh. So where is a BASIC level tutorial to fill in the gap? Or is it that my php is so minimal? - I know a cal;lback is phpo.

Kier also says hooks are going to be replaced which kinda demotivates me from struggling to learn them.
Maybe I'll just stick to includes. My stuff is about design and pasting in bits of code from another page (like Start Conversation buttons being added). So probably that's enough.
 

SchmitzIT

Well-known member
A listener is kind of like a trigger. I would consider a trigger to be anything that sits somewhere, waiting for something else to happen. Think of it as a button. When nobody is around, nothing happens. When someone pushes the button, though, they trigger the action that pushing the button puts into motion.

A listener does the exact same thing. It's a piece of code on the server, just waiting to be triggered. XenForo has a variety of these listeners, all of which fullfill a particular function. template_create listenes for a piece of code that creates a template. template_hook waits until a template hook is called on in the code.

The video demonstrates Kier creating a listener that waits for a specific template to be hooked into. So whenever that particular template (footer, from the top of my head) is encountered (which happens on every page that includes the footer), the listener jumps into action.

Specifically, the listener will be on the lookout for a specific hook location IN the footer template (which you can see by opening the template and looking for <xen:hook. By looking at the template in question and comparing it with the result on your screen when it is rendered (by navigating on your forum to the place you want to add something), you can determine which hook is best for you to use.

The video initially shows him simply adding a link to the footer template, at the specific location he picked, and then later on substituting the hard-coded link with a new template he created himself. By using the latter approach, you get more control over the functionality provided, and you can add styling etc.

Using templates gives you the ability to style the content you will add, but it does not allow you to actually run sophisticated code.


A callback is a piece of code that enables you to go beyond the 'simply add HTML and CSS' approach, and actually execute code. Using that approach, though, would require you to brush up your PHP skills, but generically speaking, CallBacks allow you to do far more complicated stuff than templates would.

Let me know if that clarifies it enough?
 
Following the introduction of the mega footer here on XenForo.com, which I said was included using template hooks and requires no direct template edits, this video tutorial talks about template hooks, what they are and why you would want to use them.

Or view on Vimeo
Afraid you lost me.

I'm not new at web programming, I've been doing it since 1993. (Before Netscape existed, when CGI was new and ImageMap'ing a graphic was trendy)... But here the problem is I'm using a stock XenForo deployment.

I have the following:

A stanza of PHP I want to use in part of a page.

I don't see a Add-On adder tool in the Admin tools.

What am I missing?

Let's' say I want to add

<?php
print "Hello world\n";
?>

Above the default right side stack of widgets on the default homepage.

Also, I appreciate the video but these old eyes just cannot read along...

EDIT:

Upon reflecting on what he said in the video (without being able to read it), the jist is:

I need to create a hook to fire the trigger that is implemented by my PHP.

So the server needs to be aware of my code, the new trigger, and I need to instrument the template to listen to the trigger.

All of that in general makes sense. Perfect sense. I just don't see the tools in the Admin section to implement it.
 
Last edited:

herocus

Active member
hi I'm a newbie here... try to check out how to use template hook...
unfortunately, vimeo video blocked from my country.. :(

any idea how to get hold of the tutorial video so that I can see it... *sigh*
 
Top