Creating a Plugin¶
Plugins allow you to extend Traq's functionality by hooking into various parts of the system. This guide will walk you through creating your first plugin using the Markdown plugin as an example.
Plugin Structure¶
All plugins must extend the \traq\libraries\Plugin base class and implement the required methods. Here's the basic structure:
namespace traq\plugins;
use \FishHook;
use \ParsedownExtra;
class Markdown extends \traq\libraries\Plugin
{
protected static $parser;
protected static $info = array(
'name' => 'Markdown',
'version' => '3.0.0',
'author' => 'Jack P.'
);
/**
* Handles the startup of the plugin.
*/
public static function init()
{
FishHook::add('function:format_text', array(get_called_class(), 'format_text'));
}
/**
* Handles the format_text function hook.
*/
public static function format_text(&$text, $strip_html)
{
// If HTML is being converted to text, undo it.
if ($strip_html) {
$text = htmlspecialchars_decode($text);
}
// Initialise parser
if (!isset(static::$parser)) {
static::$parser = new ParsedownExtra();
static::$parser->setSafeMode(true);
}
// Parse the text
$text = static::$parser->text($text);
}
}
Required Components¶
Plugin Information¶
Every plugin must define a $info static property containing metadata about the plugin:
protected static $info = array(
'name' => 'Markdown', // Plugin name
'version' => '3.0.0', // Plugin version
'author' => 'Jack P.' // Plugin author
);
Fields:
- name (required): The display name of your plugin
- version (required): The version number of your plugin (e.g., "1.0.0", "2.1.3")
- author (required): The name of the plugin author
Initialization Method¶
The init() method is called when the plugin is loaded. This is where you register hooks and perform any setup tasks:
public static function init()
{
// Register hooks here
FishHook::add('function:format_text', array(get_called_class(), 'format_text'));
}
Key Points:
- Must be a public static method
- Use FishHook::add() to register hooks
- The first parameter is the hook name (see Plugin Hooks for available hooks)
- The second parameter is a callable (typically an array with the class and method name)
- Use get_called_class() to reference the current class for better inheritance support
Hook Handlers¶
Hook handlers are methods that respond to specific events in the Traq system. The method signature depends on the hook type you're using.
Function Hooks¶
Function hooks allow you to modify data before it's processed. Parameters are passed by reference, allowing you to modify them:
public static function format_text(&$text, $strip_html)
{
// Modify $text (passed by reference)
$text = static::$parser->text($text);
}
Important:
- Parameters passed by reference (&$param) can be modified
- Changes to referenced parameters affect the original data
- Check the Plugin Hooks documentation for specific parameter requirements
Template Hooks¶
Template hooks allow you to inject HTML into specific template locations:
public static function my_template_hook($project = false)
{
echo '<div class="my-plugin-content">Custom content here</div>';
}
Important:
- Template hooks output HTML directly using echo or print
- Parameters are optional and depend on the specific hook
- Always escape user-generated content using htmlspecialchars()
Controller Hooks¶
Controller hooks allow you to intercept or modify controller actions:
public static function my_controller_hook(&$user)
{
// Modify $user before validation
$user->set('custom_field', 'value');
}
Important: - Parameters are passed by reference - Modifications affect the data before it's processed by the core code - Be careful not to break expected data structures
Example: Markdown Plugin¶
The Markdown plugin demonstrates a complete plugin implementation:
- Plugin Info: Defines the plugin metadata
- Parser Property: Stores the parser instance to avoid re-initialization
- Init Method: Registers the
format_texthook - Hook Handler: Processes text through the Markdown parser
Key Features: - Uses a static property to cache the parser instance - Handles HTML decoding when needed - Enables safe mode for security - Modifies the text by reference
Best Practices¶
Code Organisation¶
- Keep your plugin class in a single file named after your plugin (e.g.,
markdown.php) - Use proper namespacing if needed
- Follow PSR coding standards
Error Handling¶
- Always validate input data
- Handle exceptions gracefully
- Don't let plugin errors break the entire system
Security¶
- Escape output when injecting HTML
- Validate and sanitize user input
- Use safe modes for parsers when available
- Be cautious when modifying data passed by reference
Performance¶
- Cache expensive operations (like parser initialization)
- Use static properties for shared resources
- Avoid unnecessary database queries
Documentation¶
- Document your plugin's purpose and functionality
- Include usage instructions
- List any dependencies or requirements
- Provide examples of how to use your plugin
Next Steps¶
- Review the Plugin Hooks documentation to see all available hooks
- Test your plugin thoroughly before deploying
- Consider versioning your plugin for easier updates
- Share your plugin with the community!
Notes¶
- Plugin Location: Plugins are typically placed in the
vendor/traq/plugins/directory - Activation: Plugins must be activated in the admin panel before they're loaded
- Hook Execution: Multiple plugins can register hooks for the same event; they execute in registration order
- Static Methods: All plugin methods should be static, as plugins are not instantiated
- Class Naming: Plugin class names should be unique to avoid conflicts