Themes can be imbued with the power of plugins via a special themehooks php file. Using the themehooks file, you can override existing functions in Vanilla, plug in to existing Vanilla events, and set data for your views.
Naming
To use event hooks in a theme, the theme must have a plugin with a classname ending in ThemeHooks
and must have a filename ending in ThemeHooks.php
. The prevailing convention results in a class MySiteThemeHooks
and file MySiteThemeHooks.php
. This file must be located in the root of your addon.
Events
To get a better understanding of what the theme hooks are capable of, familiarize yourself with custom events & handlers, magic events, example events and magic methods.
Here’s an example of a themehooks file that sets some config variables, adds locale data for the view, adds a respond button to the discussion page, and overrides a method to add an extra css class to a menu count span.
Example Themehooks
<?php
/**
* @author My Name <name@email.com>
* @copyright 2015 (c) My Organizations
* @license http://opensource.org/licenses/MIT MIT
*/
/**
* Adds locale data to the view, and adds a respond button to the discussion page.
*/
class MyThemeNameThemeHooks extends Gdn_Plugin {
/**
* Fetches the current locale and sets the data for the theme view.
* Render the locale in a smarty template using {$locale}
*
* @param Controller $sender The sending controller object.
*/
public function base_render_before($sender) {
// Bail out if we're in the dashboard
if (inSection('Dashboard')) {
return;
}
// Fetch the currently enabled locale (en by default)
$locale = Gdn::locale()->current();
$sender->setData('locale', $locale);
}
/**
* Adds a 'respond' button on a discussion page below the discussion title
* that links to the comment form.
*
* @param DiscussionController $sender The sending object.
*/
public function discussionController_afterDiscussionTitle_handler($sender) {
// Ensure the user is signed in.
if (Gdn::session()) {
echo '<div class="below-discussion-title">'.
'<a class="respond-button Button" href="#Form_Comment">Respond</a>'.
'</div>';
}
}
}
Common Hooks
There are a few common functions for a themehooks file.
base_render_before()
This runs on every single page load before the render. This includes the Dashboard so be sure to exclude it! This is also a good place to use the Gdn_Controller
method setData()
to inject data into your Smarty templates. For details on these controller methods, see our framework documentation.
For information about using this injected data see Accessing Controller Data with Smarty. If you’re trying to verify that the data that is getting passed into the template, try out the {debug} function in smarty.
setup()
This runs when when an addon is first enabled. This is a good place for setting configuration values your theme may rely on, but is not required. Sometimes it may be desirable to put most of this content inside the structure() method and call structure from the setup method. See the example below.
structure()
This update function is called every time you reach the /utility/update
endpoint. Many plugins use this as a place to update the database, but it can be a good place for configuration values as well, and can be used to manually create a category, discussion, Pocket, etc that your theme relies on. See the example below.
This event is optional.
Example
Here is an example of setup method being used.
public function setup() {
saveToConfig([
'Vanilla.Categories.Layout' => 'table',
'Vanilla.Discussions.Layout' => 'table',
'Garden.Thumbnail.Size' => '200',
]);
Pocket::touch("My Custom Pocket", "<div>My custom pocket contents</div>");
}
Other Examples
For more examples see our Example Events section.