trigger_example.module 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <?php
  2. /**
  3. * @file
  4. * Trigger definition example module.
  5. */
  6. /**
  7. * @defgroup trigger_example Example: Trigger
  8. * @ingroup examples
  9. * @{
  10. *
  11. * Trigger definition example module.
  12. *
  13. * Triggers and actions are a pair of special-purpose functions allowing some
  14. * Drupal programming without using PHP. Using the
  15. * appropriate action in a specific event, a site administrator can
  16. * add new functionality. Examples are:
  17. * - Send an email after a node is published or edited.
  18. * - Display a message after a user has logged in.
  19. * - Display a message and send an email after a node has been deleted.
  20. *
  21. * A Trigger is a special function able to enqueue actions. The trigger module
  22. * provides the interface allowing us to associate certain actions with certain
  23. * triggers.
  24. *
  25. * Actions are functions intended to be run by triggers.
  26. *
  27. * A trigger should build the appropriate context for the action to be fired.
  28. * Actions are very often
  29. * grouped by functionality: examples are 'user', 'node', 'taxonomy'. When some
  30. * actions are grouped it is because they expect the same arguments. This way,
  31. * you can enqueue as many actions understanding the 'user' object as you want.
  32. *
  33. * Not all actions can be used in all triggers because they require different
  34. * contexts. But some actions
  35. * are generic enough to not require special objects in their
  36. * contexts, and so can be used on every available trigger. This 'group' type
  37. * is used by actions to be available for this trigger.
  38. *
  39. * What are good candidates to be triggers? Any function can be a trigger, as
  40. * long as it has the code to call the enqueued actions, but to make Drupal
  41. * more extensible, you will find hooks (from Drupal and contributed modules)
  42. * very good candidates. A trigger should build the arguments, ask for enqueued
  43. * actions and run them. You may define a function being a trigger, and run it
  44. * through a button in the front page, or you may prepare a trigger for a hook,
  45. * and everytime that hook is fired, your trigger will be.
  46. *
  47. * What are good candidates to be actions? any function is a possible action,
  48. * the only problem is finding a trigger able to run it.
  49. *
  50. * This module describes how to create triggers and actions for Drupal. In this
  51. * example we are providing two triggers:
  52. *
  53. * - A custom trigger, in its simplest form. We provide a page with a button.
  54. * This button does nothing at all, but when you click (and submit the empty
  55. * form), any actions you have configured will be executed.
  56. *
  57. * - A trigger which extends the capabilities of User triggers.
  58. * This creates a new event which fires the first time a user ever logs in.
  59. * In the module we will create it, and then provide a trigger for
  60. * the administrator to be able to enqueue actions. They will be executed
  61. * only the first time the user logs in the system.
  62. *
  63. * See:
  64. *
  65. * @link http://drupal.org/node/375833 Creating Triggers @endlink
  66. *
  67. * @link http://drupal.org/node/172152 Writing Actions @endlink
  68. *
  69. * @link http://drupal.org/node/199254 Triggers and Actions in Drupal 6 @endlink
  70. *
  71. * @see hook_trigger_info()
  72. * @see hook_trigger_info_alter()
  73. * Also see the @link action_example.module Action Example @endlink.
  74. */
  75. /**
  76. * Implements hook_trigger_info().
  77. *
  78. * We call hook_trigger_info when we are defining the triggers we provide.
  79. * Triggers are the events that make fire any number of assigned actions. In
  80. * this example, we are registering our three new triggers, providing the group
  81. * (system, user..), the callback 'hook' (only informative, does not require a
  82. * real hook) function and the label to be shown in the triggers interface.
  83. *
  84. * Example: In the group (a tab) 'system', for the 'mail' functionality, show:
  85. * An email is sent by Drupal.
  86. */
  87. function trigger_example_trigger_info() {
  88. return array(
  89. 'user' => array(
  90. 'user_first_time_login' => array(
  91. 'label' => t('After a user has logged in for the first time'),
  92. ),
  93. ),
  94. 'trigger_example' => array(
  95. 'triggersomething' => array(
  96. 'label' => t('After the triggersomething button is clicked'),
  97. ),
  98. ),
  99. );
  100. }
  101. /**
  102. * Triggers are used most of the time to do something when an event happens.
  103. * The most common type of event is a hook invocation,
  104. * but that is not the only possibility.
  105. */
  106. /**
  107. * Trigger: triggersomething. Run actions associated with an arbitrary event.
  108. *
  109. * Here pressing a button is a trigger. We have defined a
  110. * custom function as a trigger (trigger_example_triggersomething).
  111. * It will ask for all actions attached to the 'triggersomething' event,
  112. * prepare a basic 'context' for them
  113. * and run all of them. This could have been implemented by a hook
  114. * implementation, but in this demonstration, it will just be called in a
  115. * form's submit.
  116. *
  117. * This function is executed during the submission of the example form defined
  118. * in this module.
  119. *
  120. * @param array $options
  121. * Array of arguments used to call the triggersomething function, if any.
  122. */
  123. function trigger_example_triggersomething($options = array()) {
  124. // Ask the trigger module for all actions enqueued for the 'triggersomething'
  125. // trigger.
  126. $aids = trigger_get_assigned_actions('triggersomething');
  127. // Prepare a basic context, indicating group and "hook", and call all the
  128. // actions with this context as arguments.
  129. $context = array(
  130. 'group' => 'trigger_example',
  131. 'hook' => 'triggersomething',
  132. );
  133. actions_do(array_keys($aids), (object) $options, $context);
  134. }
  135. /**
  136. * The next trigger is more complex, we are providing a trigger for a
  137. * new event: "user first time login". We need to create this event
  138. * first.
  139. */
  140. /**
  141. * Implements hook_user_login().
  142. *
  143. * User first login trigger: Run actions on user first login.
  144. *
  145. * The event "User first time login" does not exist, we should create it before
  146. * it can be used. We use hook_user_login to be informed when a user logs in and
  147. * try to find if the user has previously logged in before. If the user has not
  148. * accessed previously, we make a call to our trigger function.
  149. */
  150. function trigger_example_user_login(&$edit, $account, $category = NULL) {
  151. // Verify user has never accessed the site: last access was creation date.
  152. if ($account->access == 0) {
  153. // Call the aproppriate trigger function.
  154. _trigger_example_first_time_login('user_first_time_login', $edit, $account, $category);
  155. }
  156. }
  157. /**
  158. * Trigger function for "User first time login".
  159. *
  160. * This trigger is a user-type triggers, so is grouped with other user-type
  161. * triggers. It needs to provide all the context that user-type triggers
  162. * provide. For this example, we are going to copy the trigger.module
  163. * implementation for the 'User has logged in' event.
  164. *
  165. * This function will run all the actions assigned to the
  166. * 'user_first_time_login' trigger.
  167. *
  168. * For testing you can use an update query like this to reset a user to
  169. * "never logged in":
  170. * @code
  171. * update users set access=created where name='test1';
  172. * @endcode
  173. *
  174. * @param string $hook
  175. * The trigger identification.
  176. * @param array $edit
  177. * Modifications for the account object (should be empty).
  178. * @param object $account
  179. * User object that has logged in.
  180. * @param string $category
  181. * Category of the profile.
  182. */
  183. function _trigger_example_first_time_login($hook, &$edit, $account, $category = NULL) {
  184. // Keep objects for reuse so that changes actions make to objects can persist.
  185. static $objects;
  186. // Get all assigned actions for the 'user_first_time_login' trigger.
  187. $aids = trigger_get_assigned_actions($hook);
  188. $context = array(
  189. 'group' => 'user',
  190. 'hook' => $hook,
  191. 'form_values' => &$edit,
  192. );
  193. // Instead of making a call to actions_do for all triggers, doing this loop
  194. // we provide the opportunity for actions to alter the account object, and
  195. // the next action should have this altered account object as argument.
  196. foreach ($aids as $aid => $info) {
  197. $type = $info['type'];
  198. if ($type != 'user') {
  199. if (!isset($objects[$type])) {
  200. $objects[$type] = _trigger_normalize_user_context($type, $account);
  201. }
  202. $context['user'] = $account;
  203. actions_do($aid, $objects[$type], $context);
  204. }
  205. else {
  206. actions_do($aid, $account, $context, $category);
  207. }
  208. }
  209. }
  210. /**
  211. * Helper functions for the module interface to test the triggersomething
  212. * trigger.
  213. */
  214. /**
  215. * Implements hook_help().
  216. */
  217. function trigger_example_help($path, $arg) {
  218. switch ($path) {
  219. case 'examples/trigger_example':
  220. $explanation = t(
  221. 'Click the button on this page to call trigger_example_triggersomething()
  222. and fire the triggersomething event. First, you need to create an action
  223. and assign it to the "After the triggersomething button is clicked" trigger,
  224. or nothing will happen. Use the <a href="@actions-url">Actions settings page</a>
  225. and assign these actions to the triggersomething event on the
  226. <a href="@triggers-url">Triggers settings page</a>. <br/><br/>
  227. The other example is the "user never logged in before" example. For that one,
  228. assign an action to the "After a user has logged in for the first time" trigger
  229. and then log a user in.', array('@actions-url' => url('admin/config/system/actions'), '@triggers-url' => url('admin/structure/trigger/trigger_example')));
  230. return "<p>$explanation</p>";
  231. case 'admin/structure/trigger/system':
  232. return t('you can assign actions to run everytime an email is sent by Drupal');
  233. case 'admin/structure/trigger/trigger_example':
  234. $explanation = t(
  235. "A trigger is a system event. For the trigger example, it's just a button-press.
  236. To demonstrate the trigger example, choose to associate the 'display a message to the user'
  237. action with the 'after the triggersomething button is pressed' trigger."
  238. );
  239. return "<p>$explanation</p>";
  240. }
  241. }
  242. /**
  243. * Implements hook_menu().
  244. *
  245. * Provides a form that can be used to fire the module's triggers.
  246. */
  247. function trigger_example_menu() {
  248. $items['examples/trigger_example'] = array(
  249. 'title' => 'Trigger Example',
  250. 'description' => 'Provides a form to demonstrate the trigger example.',
  251. 'page callback' => 'drupal_get_form',
  252. 'page arguments' => array('trigger_example_form'),
  253. 'access callback' => TRUE,
  254. );
  255. return $items;
  256. }
  257. /**
  258. * Trigger example test form.
  259. *
  260. * Provides a button to run the triggersomething event.
  261. */
  262. function trigger_example_form($form_state) {
  263. $form['triggersomething'] = array(
  264. '#type' => 'submit',
  265. '#value' => t('Run triggersomething event'),
  266. );
  267. return $form;
  268. }
  269. /**
  270. * Submit handler for the trigger_example_form().
  271. */
  272. function trigger_example_form_submit($form, $form_state) {
  273. // If the user clicked the button, then run the triggersomething trigger.
  274. if ($form_state['values']['op'] == t('Run triggersomething event')) {
  275. trigger_example_triggersomething();
  276. }
  277. }
  278. /**
  279. * Optional usage of hook_trigger_info_alter().
  280. *
  281. * This function is not required to write your own triggers, but it may be
  282. * useful when you want to alter existing triggers.
  283. */
  284. /**
  285. * Implements hook_trigger_info_alter().
  286. *
  287. * We call hook_trigger_info_alter when we want to change an existing trigger.
  288. * As mentioned earlier, this hook is not required to create your own triggers,
  289. * and should only be used when you need to alter current existing triggers. In
  290. * this example implementation a little change is done to the existing trigger
  291. * provided by core: 'cron'
  292. *
  293. * @see hook_trigger_info()
  294. */
  295. function trigger_example_trigger_info_alter(&$triggers) {
  296. // Make a simple change to an existing core trigger, altering the label
  297. // "When cron runs" to our custom label "On cron execution"
  298. $triggers['system']['cron']['label'] = t('On cron execution');
  299. }