Add a custom action using integration hooks: Difference between revisions From Online Manual

Jump to: navigation, search
(→‎./Sources/YourAction.php: Update to use the modified example from Add_a_custom_action)
Line 118: Line 118:
This is the function called to display an output when the ''youraction'' action is used and the one that will create the html output with the ''echo'' statements.
This is the function called to display an output when the ''youraction'' action is used and the one that will create the html output with the ''echo'' statements.


{{ambox|
text=Please note that use "hardcoded text" is a [[Customization_approval_guidelines#No_Hardcoded_Text|bad practice]] because it preclude the use of the tools provided by SMF for the presentation of the pages in multiple languages}}


Assuming the intention is to create a header and a content section the following code could be used:
Assuming the intention is to create a header and a content section the following code could be used:
{{code|1=<nowiki><?php
{{code|1=<nowiki><?php
function template_main() {
 
// Globalize what we need...
function template_main()
global $txt;
{
 
// Make sure we have all the global variables we need
global $context


// Catbg header
// Catbg header
echo '<div class="cat_bar">
echo '<div class="cat_bar">
   <h3 class="catbg">', $txt['your_action'], '</h3>
   <h3 class="catbg">', $context['youraction_Head'], '</h3>
</div>';
</div>';


Line 135: Line 136:
echo '<div class="windowbg2">
echo '<div class="windowbg2">
   <span class="topslice"><span></span></span>
   <span class="topslice"><span></span></span>
     <div class="content">Your Page Content</div>
     <div class="content">$context['youraction_Body']</div>
   <span class="botslice"><span></span></span>
   <span class="botslice"><span></span></span>
</div><br />';
</div><br />';
}
}
?></nowiki>}}
?></nowiki>}}
The file YourAction.template.php must be placed in the /Themes/default/ directory.
The file YourAction.template.php must be placed in the /Themes/default/ directory.



Revision as of 13:50, 19 September 2011

Introduction

Starting with SMF 2.0 adding a custom action doesn't need any change to the "core" code, it is sufficient to use the appropriate integration hook.

Just for the sake of learning how SMF works, let's take a look at how actions are handled internally. Opening index.php in SMF's main directory it's possible to find an array called $actionArray where are defined all the default action of SMF (e.g. calendar, post, etc.).

The structure of the elements of the array is the following:

'myaction' => array('myaction_file.php', 'myaction_function'),

Where:

  • myaction - is the action as specified in the URL
    (e.g. http://www.yourdomain.tld/forum/index.php?action=myaction),
  • myaction_function - id the function that SMF will call once the myaction is used,
  • myaction_file.php - is the file that contains the function myaction_function.

The first thing to do is decide the name of the action we want to have, the name of the function the action will trigger and the name of the file that will contain this function. In this tutorial we will use:

  • action - youraction
  • function - YourActionMain
  • file - YourAction.php

Prepare to use the hook

Add an integration hook to SMF is like modifying an entry in the database. It only needs to be done once, then SMF will know to look for your new integration hook every time afterwards. In order to facilitate this procedure a function named add_integration_function is available in SMF. In order to use this function we can create a simple php file, it can be called for example add_action_hook.php and the content can be:

<?php
// If SSI.php is in the same place as this file, and SMF isn't defined, this is being run standalone.
if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF'))
	require_once(dirname(__FILE__) . '/SSI.php');
// Hmm... no SSI.php and no SMF?
elseif (!defined('SMF'))
	die('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');

add_integration_function('integrate_pre_include', '$sourcedir/Subs-YourAction.php');
add_integration_function('integrate_actions', 'youraction_add_hook');
?>

Analysing the code provided two are the hooks used:

Prepare the 'YourAction' files

Source File

./Sources/Subs-YourAction.php

This file is ment to contain the function youraction_add_hook used every time SMF loads in order to add the action to the list of available. It must be placed in the /Sources/ directory.

The code contained in this file is:

<?php
if (!defined('SMF'))
	die('Hacking attempt...');

function youraction_add_hook(&$actionArray) {
	$actionArray['youraction'] = array('YourAction.php', 'YourActionMain');
}

?>

./Sources/YourAction.php

This file is ment to contain the function YourActionMain, triggered by the youraction action. It must be placed in the /Sources/ directory.

So to start it must at least contains the function:

<?php
if (!defined('SMF'))
	die('Hacking attempt...');

function YourActionMain(){

}
?>

This function could be used to load a template, for example the YourAction template, in order to do so we can add the instruction:

loadTemplate('YourAction');

In this case YourAction is the first part of the name of the template file, that will be YourAction.template.php.

It is also possible and encouraged to set several options that could be used later in the template, like for example the page title or the link tree.

So, the final YourAction.php should look like:

<?php

// First of all, we make sure we are accessing the source file via SMF so that people can not directly access the file. 
if (!defined('SMF'))
	die('Hack Attempt...');

function YourActionMain()
{

	// Second, give ourselves access to all the global variables we will need for this action
	global $context, $scripturl, $txt;

	// Third, Load the specialty template for this action.
	loadTemplate('YourAction');

	//Fourth, Come up with a page title for the main page
	$context['page_title'] = $txt['youraction_PageTitle'];
	$context['page_title_html_safe'] = $smcFunc['htmlspecialchars'](un_htmlspecialchars($context['page_title']));


	//Fifth, define the navigational link tree to be shown at the top of the page.
	$context['linktree'][] = array(
  		'url' => $scripturl. '?action=youraction',
 		'name' => $txt['your_action'],
	);

	//Sixth, begin doing all the stuff that we want this action to display
	//    Store the results of this stuff in the $context array.  
	//    This action's template(s) will display the contents of $context.
	$context['youraction_Head'] = $txt['youraction'];
	$context['youraction_Body'] = 'Hello World';
              
}

?>

Template File

./Themes/default/YourAction.template.php

As previously explained the YourAction.template.php file must contain the template function, in this case template_main:

<?php
function template_main() {

}
?>

This is the function called to display an output when the youraction action is used and the one that will create the html output with the echo statements.


Assuming the intention is to create a header and a content section the following code could be used:

<?php

function template_main()
{

	// Make sure we have all the global variables we need
	global $context

	// Catbg header
	echo '<div class="cat_bar">
   			<h3 class="catbg">', $context['youraction_Head'], '</h3>
	</div>';

	// Windowbg2 Content
	echo '<div class="windowbg2">
  			<span class="topslice"><span></span></span>
  		  		<div class="content">$context['youraction_Body']</div>
  			<span class="botslice"><span></span></span>
	</div><br />';

}

?>

The file YourAction.template.php must be placed in the /Themes/default/ directory.

Language Strings

./Themes/default/languages/Modifications.english.php

The Modifications.languages.php files are commonly used by modifications in order to add new strings to the $txt array. In this way it is possible to easily translate SMF and its mods in several languages. All these files can be found in /Themes/default/languages/.

In order to add our new string to the $txt array it is enough to add this code:

// Your Action Language Strings
$txt['your_action'] = 'Your Action';
$txt['page_title'] = 'This is your page title';

to the Modification.english.php file and save it.

./Themes/default/languages/Who.english.php

The strings present in Modification.language.php are available everywhere in SMF's code. In certain cases it could be more appropriate to have the strings available only where are really needed, for this reason it is possible to add strings also to other language files. The Who.english.php is a special case, it is used when someone is accessing the ?action=who page and here can be added a description for the new action that will so be visible in the page.

Once the file is opened it is enough to add the following code at the end:

// Your Action Who String
$txt['whoall_youraction'] = 'Viewing <a href="' . $scripturl . '?action=youraction">Your Action</a>.';

Finally it is necessary to clear the file cache for the language strings to take effect. This can be done in Admin > Maintenance > Forum Maintenance > Routine, and it's the last option.

Add the hook

Upload the file add_action_hook.php, previously prepared, in the root directory of your forum (the same directory that contains SSI.php), then point your prowser to http://www.yourdomain.tld/forum/add_action_hook.php.

If you don't get any error and you see a blank page everything should be fine and you can remove the add_action_hook.php from the server.

See the results

In your browser go to
http://www.yourdomain.tld/forum/index.php?action=youraction
and you should see result of the action displayed on the screen!

Removing the action

In order to remove the action two are the things to do:

  1. remove all the involved files;
  2. remove the integration hooks.

In order to remove the integration hooks a file similar to add_action_hook.php can be used, it can be called remove_action_hook.php and it should contain this code:

<?php
// If SSI.php is in the same place as this file, and SMF isn't defined, this is being run standalone.
if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF'))
	require_once(dirname(__FILE__) . '/SSI.php');
// Hmm... no SSI.php and no SMF?
elseif (!defined('SMF'))
	die('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');

remove_integration_function('integrate_pre_include', '$sourcedir/Subs-YourAction.php');
remove_integration_function('integrate_actions', 'youraction_add_hook');
?>

The file must be uploaded to the root directory of the forum, executed pointing to the
http://www.yourdomain.tld/forum/remove_action_hook.php
url and then removed from the server the same way add_action_hook.php was.

Alternative methods

Add_a_custom_action



Advertisement: