How To Use Template Hooks

Must be a newer version Kier is working with, because even my template_hook arguments aren't described by the same name. For instance, my template_hook listener includes "string &$contents", while Kier's is just" string &$content". I guess it doesn't matter as long as the right references are used in the method, right?
 
You dirty little ;)... I can see how the callback signatures would come in handy.

Regarding Rigel's statement...
2. Is it possible to modify the template at compilation time, instead of at generation time? Right now it seems that it is modified at runtime, appending or modifying contents, but I would also like to be able to, say, modify the actual template definition. This is a little different in the sense that the hook would be applied once when the add-on is compiled and every time the templates are recompiled. Could we maybe have both?

I assume this is the problem I'm currently having with moving some hard coded template edits to template hooks.

Just for giggles, I tried to create listener to find
PHP:
<img src="@headerLogoPath" alt="{$xenOptions.boardTitle}" />
in the template hook "header_logo" of the "logo_block" template, and replace it with a reference to a new template ("mydemo_forum_logo_block") that would determine which logo should be displayed depending on the node.

I tried to do that with this code, probably not the most efficient, but...
Code:
    public static function templateHook($hookName, &$content, array $hookParams, Xenforo_Template_Abstract $template)
    {
        switch($hookName){
            case 'header_logo':
                //remove the default logo from the template, replace it with a call to a template to determine the logo
                $content = str_replace('<img src="@headerLogoPath" alt="{$xenOptions.boardTitle}" />',$template->create('mydemo_forum_logo_block', $template->getParams()), $content);
                break;
        }
    }

That doesn't work, it appears that when the callback method is called, that the template has already been converted, replaced, parsed, or whatever the nomenclature is?

I finally noticed that this did work, replacing the actual generated HTML with what I want..
Code:
    public static function templateHook($hookName, &$content, array $hookParams, Xenforo_Template_Abstract $template)
    {
        switch($hookName){
            case 'header_logo':
                //remove the default logo from the template, replace it with a call to a template to determine the logo
                 $content = str_replace('<img src="styles/{somestyle}/xenforo/logo.png" alt="{some alt}" />',$template->create('mydemo_forum_logo_block', $template->getParams()),$content);
                break;
        }
    }
 
Regarding perLoading a template... Would I have to preload my template, and any templates referenced within it, or just the main/parent template?

my_template
my_inner_template​
my_second_inner_template​
 
You don't need to preload anything that is referred to using <xen:include />, because those dependencies are resolved at compilation time, so those templates are effectively part of your template when it comes time to load them.
 
I'm having issues hooking into "message_user_info_avatar"...
PHP:
case 'message_user_info_avatar':
{
    $contents .= $template->create('EWRcustom_message_user_info_avatar', $template->getParams())->render();
    break;
}
EWRcustom_message_user_info_avatar:
HTML:
<xen:if hascontent="true">
    <ul class="ribbon">
        <xen:contentcheck>
        <xen:if is="{xen:helper ismemberof, $user, 6}">
            <li class="ribbonStaff"><div class="left"></div><div class="right"></div>Senior Moderator</li>
        </xen:if>
        <xen:if is="{xen:helper ismemberof, $user, 5}">
            <li class="ribbonPremium"><div class="left"></div><div class="right"></div>Premium Supporter</li>
        </xen:if>
        </xen:contentcheck>
    </ul>
</xen:if>
Unfortunately, its not passing in the parameter $user.
 
Okay, this isn't the problem I thought it was, so it's not a bug, but here is what you are doing wrong.

$user in the message_user_info template is a mapped variable. If you look at the include line in the message template where message_user_info is called, you can see the $user variable being created.
HTML:
<xen:include template="message_user_info">
	<xen:map from="$message" to="$user" />
</xen:include>
Therefore, $user will not be present in the template params. For this reason, we pass it explicitly through the $hookParams (3rd argument to the template_hook callback).
HTML:
<xen:hook name="message_user_info_avatar"
	params="{xen:array 'user={$user}', 'isQuickReply={$isQuickReply}'}">
To get access to $user in you hooked template, you must manually merge $hookParams into the template params.
PHP:
case 'message_user_info_avatar':
{
	$mergedParams = array_merge($template->getParams(), $hookParams);
	$contents .= $template->create(
		'EWRcustom_message_user_info_avatar',
		$mergedParams
	);
	break;
}
And finally, leave the rendering ($template->create(...)->render()) to XenForo, you don't need to do it yourself, and in fact you open yourself to potential backward compatibility breaks in the future by doing so when it's not necessary :)
 
I must be running in "luddite" mode this evening. Here's my error message when trying to add a Code Event Listener:

Please enter a valid callback method.

Hmmm. Anyway, my simple add-on is only injecting a new bit of HTML into the <head> of the page. I'm using the page_container_head template hook to do so. Here are the steps I took, with my entries in italics.

1. Create a directory under Library called Speakeasy (IOW, forum/library/Speakeasy/);

2. Create a PHP file within that directory with the code to execute for the addon (I named it Speakeasy_MyTest.php). This code contains the following:

PHP:
<?php

class Speakeasy_MyTest
{
    public static function templateHook($hookName, &$contents, $params, XenForo_Template_Abstract $template)
    {
    if ($hookName == 'page_container_head') {
        $contents .= '<link ...my code here... />';
    }
    }
}

3. Add the add-on, using the exact same name as the directory for the add-on ID ("Speakeasy") and a description of Speakeasy Add-on.

4. Add the event listener. I choose Listen to event: template_hook from the drop-down. For Execute Callback I've entered Speakeasy_MyTest :: templateHook in the two fields. Finally, I pick my addon, Speakeasy Add-on, from the drop-down box at the bottom.

I submit this, and I get the error message above. I am missing one step in all this, I'm sure, or just naming something wrong. I've pretty much followed Kier's example, to the best of my knowledge.

Plus, I have a question--how does the add-on or callback know which directory and file to look in, to find the code within my PHP file? Is this where I'm getting derailed? Does XF load whatever it finds in the library, or did I miss a step that's not in the video perhaps?

Once I get this working, I can further modify it. I just want to get it working per Kier's first example, and then build on it from there.

Thanks for looking!
 
I must be running in "luddite" mode this evening. Here's my error message when trying to add a Code Event Listener:

Hmmm. Anyway, my simple add-on is only injecting a new bit of HTML into the <head> of the page. I'm using the page_container_head template hook to do so. Here are the steps I took, with my entries in italics.

1. Create a directory under Library called Speakeasy (IOW, forum/library/Speakeasy/);

2. Create a PHP file within that directory with the code to execute for the addon (I named it Speakeasy_MyTest.php). This code contains the following:

PHP:
<?php

class Speakeasy_MyTest
{
    public static function templateHook($hookName, &$contents, $params, XenForo_Template_Abstract $template)
    {
    if ($hookName == 'page_container_head') {
        $contents .= '<link ...my code here... />';
    }
    }
}

3. Add the add-on, using the exact same name as the directory for the add-on ID ("Speakeasy") and a description of Speakeasy Add-on.

4. Add the event listener. I choose Listen to event: template_hook from the drop-down. For Execute Callback I've entered Speakeasy_MyTest :: templateHook in the two fields. Finally, I pick my addon, Speakeasy Add-on, from the drop-down box at the bottom.

I submit this, and I get the error message above. I am missing one step in all this, I'm sure, or just naming something wrong. I've pretty much followed Kier's example, to the best of my knowledge.

Plus, I have a question--how does the add-on or callback know which directory and file to look in, to find the code within my PHP file? Is this where I'm getting derailed? Does XF load whatever it finds in the library, or did I miss a step that's not in the video perhaps?

Once I get this working, I can further modify it. I just want to get it working per Kier's first example, and then build on it from there.

Thanks for looking!
I believe your class has to be Speakeasy_Speakeasy_MyTest. Or, I'd recommend you change your php file to something like this SpeakeasyMyTest.php. Then, name your class, Speakeasy_SpeakeasyMyTest.
 
That was it--I renamed the file (removing Speakeasy_), and I blasted right through. Now I see the naming conventions for the directories and filenames. Makes sense.

Better yet--the add-on works! (y) Now I can continue building on it with templates, variables, etc.

Thanks much!
 
So it's not possible to add something to a template with a hook without adding a new php file right? This was easy for me in vB since I have almost no coding experience, but I assume the XF way has advantages for actual coders.
 
I can't answer it directly, but I will say the implementation is very "clean." The add-on files stay in their own directory within /forum/library and the add-on itself is easily removed from the XF system. Meanwhile, the XF system remains intact and untouched, especially if you always add stuff for add-ons and never modify existing XF files or templates. The phpBB2 system I am running has two dozen modifications and customizations to it. And all of them were direct file edits. You can imagine my nightmare!
 
So it's not possible to add something to a template with a hook without adding a new php file right? This was easy for me in vB since I have almost no coding experience, but I assume the XF way has advantages for actual coders.
Sure you can, you can just edit the template ...
 
The template hook system is a stop-gap solution that we will replace in due course. For now, modifying templates with hooks requires a PHP callback.
Out of curiosity, which is your preferred method for hooking into templates? I know the template hook system isn't something you or Mike wanted, can we get a peak into what'll follow?!
 
Out of curiosity, which is your preferred method for hooking into templates? I know the template hook system isn't something you or Mike wanted, can we get a peak into what'll follow?!
Imagine the template hook system without the need to actually create PHP files to attach to the hooks. Obviously we'd like to keep the ability to have a PHP callback, but we'd like to remove the necessity of having one.
 
Imagine the template hook system without the need to actually create PHP files to attach to the hooks. Obviously we'd like to keep the ability to have a PHP callback, but we'd like to remove the necessity of having one.
So how would you store the code you're hooking with? Database-stored?
 
Top Bottom