Hooks
From Achievo/ATK Wiki
Contents |
Introduction
The usual way of overriding method behaviour in an object oriented context, is to override them in derived classes.
Magic methods in ATK are methods that are similar. The difference is that these are not overrides, because these methods are not present in the base class. The reason is that these methods are dynamic in nature. ATK checks whether these methods exist, and if so, calls them. This is why we call them 'Hooks'.
This concept might be confusing, but is best explained with an example. Add this method to your node:
public function name_display($record) { return "Hello World"; }
'name' refers to an attribute of your node. If this magic method exists, ATK will call name_display every time it want to display a value from the 'name' attribute, instead of its usual display logic. If you try this code, you'll see that the 'name' column of a recordlist will now only contain 'hello world' entries.
This example also demonstrates why these are 'magic methods'. There is no name_display method in atkNode, because atkNode has no knowledge of what attributes your node may have at any time.
Whenever we refer to magic methods in the ATK documentation, we usually refer to <attribname>_display, where attribname should be replaced by an actual attribute from your node.
When to use it
For each magic method, there is a solution that does not require a magic method. For example, to override the display behaviour of an attribute, you can also extend the attribute like this:
class helloworldAttribute extends atkAttribute { public function display($record, $mode) { return "Hello World"; } }
So why should you use magic methods? Magic methods are quicker to implement, and are always node specific. They only work in the node you add the method to. If you extend an attribute, you can reuse the attribute in multiple nodes. If all you need to do is alter the display of some column in one node, a magic <attribname>_display method is less code and less overhead.
A practical example
The most commonly used magic method is <attribname>_display. It is used to alter the output of attribute values. The safest way to do this is to call the original display behaviour, and alter its output, as in the following example, which makes the text of a column bold if it contains the word 'atk':
public function content_display($record, $mode) { $attribute = $this->getAttribute("content"); $original = $attribute->display($record, $mode); if ($mode=="list" && strpos($original, "atk")!==false) { $original = "<nowiki><b></nowiki>".$original."<nowiki></b></nowiki>"; } return $original; }
In this case, the $mode parameter is used to change the behaviour only in 'list' mode (recordlists, such as the admin page).
What parameters a magic method has, depends on the method. These are documented below.
List of ATK Magic Methods
<attribname>_display
Signature:
public function <attribname>_display($record, $mode) { return "string to display"; }
Where $record is the record that is being displayed, and $mode is either "list" or "view" depending on the context in which a value needs to be displayed (useful if you only want to override display in list mode).
ADDITION: Mode can also be "csv" when exporting Suspect that mode can also be "add", "edit" for read-only fields on on those pages
<attribname>_edit
Todo: show api and example
<attribname>_validate
Todo: show api and example
<attribname>_search
Override the search box. The example below makes a custom search output for both extended and regular search.
public function name_search($record=array(), $extended=false, $fieldprefix="", atkDataGrid $grid=null) { if ($extended) return "SUPER EXTENSIVE SEARCH WIDGET CUSTOM THINGEE"; return "CUSTOM SEARCH WIDGET"; }
General
See atk/attributes/class.atkattributes.inc for the original implementations of the display/search/edit methods and their parameters.
action_<action>
Best explained via example: if a URL is generated with
dispatch_url("general.user", "display");
then loading this URL results in a call to the action_display() of the general.user node.
Actions should have the following signature:
public function action_<actionname> ($handler) { }
If you override a default action, say the 'edit' action, then $handler will be an instance of atkEditHandler.
adminHeader
If you implement a method in your node called 'adminHeader', returning a string, that string is displayed in an admin page above the list of records. This can be used for example to add information, buttons, filters or links.
Similar to adminHeader, but displays the string below the list of records.
rowColor
You can implement this method to make a row in a recordlist have a specific background color, depending on the values in your record. Useful for turning todo's red when they are expired, records grey when the status is 'disabled', etc.
public function rowColor($record) { if ($record["status"]=="expired") { return "#ff0000"; } }
The $record variable will contain only the record showed in the list. If you used AF_HIDE_LIST or AF_HIDE and if you want to use it in rowColor then you need to add the AF_FORCE_LOAD flag to the attribute.
If you want to add functionality whenever things happen in the database, have a look at Action Listeners, Trigger Listeners and Triggers. These aren't 'magic methods', but behave similarly.
Document generation
When using an atkDocumentAttribute, you can implement a hook to assign additional variables to the document template:
public function assignDocumentVars($handler, $documentWriter, $selector) { $documentWriter->assign("hello", "world"); }
This replaces [hello] in the document template with 'world'. For more detailed usage, see the howto: Assigning custom variables to a document template.