Events in concrete5 make it very easy to extend what concrete5 does without modifying existing code.
The Basics:
Events are inserted all throughout concrete5 and more are added at each release. It is easiest to hook into events in a package controller in the on_start() method.
The naming of events is extremely standardized to make it easy to understand what each event does, such as:
- on_user_add - Fired when a user is added.
- on_file_delete - Fired right before a file is deleted.
- on_user_change_password - Fired when a user changes their password.
This makes it easy to also guess event names. An event is fired when a line of code in a function or method is run, (such as UserInfo::add()).
Making your own Events:
Adding events to concrete5 is extremely easy to do. Below is an example function that will insert a value into the databse:
function insert($value) {
$db = Loader::db();
$db->Execute('INSERT into `SomeTable` (value) values (?)', array($value));
}
Lets say we wanted to add an event to this function so that developers can hook into it. To add an event, you just need to add 1 line of code.
Events::fire('on_value_insert', $value);
If we integrate that into the function it would look like so:
function insert($value) {
Events::fire('on_value_insert', $value);
$db = Loader::db();
$db->Execute('INSERT into `SomeTable` (value) values (?)', array($value));
}
Lets say we want to allow the developer to change the value that is inserted into the database, we would just add a simple if statement:
function insert($value) {
$ret = Events::fire('on_value_insert', $value);
if($ret) {
$value = $ret;
}
$db = Loader::db();
$db->Execute('INSERT into `SomeTable` (value) values (?)', array($value));
}
If nothing was returned, it would return null
, so you can do a strict comparison, (so things like ''
can be returned).
function insert($value) {
$ret = Events::fire('on_value_insert', $value);
if($ret !== null) {
$value = $ret;
}
$db = Loader::db();
$db->Execute('INSERT into `SomeTable` (value) values (?)', array($value));
}
You can pass as many variables as you want in an event:
Events::fire('on_something_happening', $val1, $val2, $val3);
and so on.
Note*: If you want an easy way to test your events, check out the Event Tester addon, Event Tester Addon
Utilizing Events:
In order to use events, you must "extend" it.
For the following examples, I will be using the on_user_change_password
event. This event passes 2 variables, the first is the hashed password, and the second is the password in plaintext.
I assume that you have the basic understanding of the developer side of concrete5 and packages.
In the on_start() method of your package controller, you would place a line like so:
Events::extend('on_user_change_password', 'MyClass', 'myMethod', 'path/to/file.php');
This is the bare minimum that you can have to extend an event. There are 2 other parameters that can be used as well. One is an array of parameters that you want to pass, and the second is the priority of the event, (lower number runs first). As of at least 5.4.2.2, only the last run event is able to return anything.
In path/to/file.php
I would have the following code (if I passed the array I would also need to add more variables):
class MyClass {
public function myMethod($hash, $plain) {
/* your code here */
}
}
Note*: If you want to know what data an event returns, check out the Event Tester addon, Event Tester Addon
Some events allow you to "cancel" the event, such as the on_user_delete
event. If you return -1 in the above method (assuming it is the on_user_delete
event) it would not delete the user. (Throwing an exception can also stop execution).
Troubleshooting:
If you have problems with events not firing, use the Event Tester Addon to monitor the event. If the addon does not catch anything, make sure that the function or method that contains the Event is being called correctly.
If there is a place where you think an event should fire, but does not (core only) please open a bug report for the current version of concrete5 (but check to make sure it does not already exist).
Any other questions can be directed to me.