cms/drupal/modules/trigger/trigger.module
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * Enables functions to be stored and executed at a later time.
       
     6  */
       
     7 
       
     8 /**
       
     9  * Implements hook_help().
       
    10  */
       
    11 function trigger_help($path, $arg) {
       
    12   // Generate help text for admin/structure/trigger/(module) tabs.
       
    13   $matches = array();
       
    14   if (preg_match('|^admin/structure/trigger/(.*)$|', $path, $matches)) {
       
    15     $explanation = '<p>' . t('Triggers are events on your site, such as new content being added or a user logging in. The Trigger module associates these triggers with actions (functional tasks), such as unpublishing content containing certain keywords or e-mailing an administrator. The <a href="@url">Actions settings page</a> contains a list of existing actions and provides the ability to create and configure advanced actions (actions requiring configuration, such as an e-mail address or a list of banned words).', array('@url' => url('admin/config/system/actions'))) . '</p>';
       
    16 
       
    17     $module = $matches[1];
       
    18     $trigger_info = _trigger_tab_information();
       
    19     if (!empty($trigger_info[$module])) {
       
    20       $explanation .= '<p>' . t('There is a tab on this page for each module that defines triggers. On this tab you can assign actions to run when triggers from the <a href="@module-help">@module-name module</a> happen.', array('@module-help' => url('admin/help/' . $module), '@module-name' => $trigger_info[$module])) . '</p>';
       
    21     }
       
    22 
       
    23     return $explanation;
       
    24   }
       
    25 
       
    26   if ($path == 'admin/help#trigger') {
       
    27     $output = '';
       
    28     $output .= '<h3>' . t('About') . '</h3>';
       
    29     $output .= '<p>' . t('The Trigger module provides the ability to cause <em>actions</em> to run when certain <em>triggers</em> take place on your site. Triggers are events, such as new content being added to your site or a user logging in, and actions are tasks, such as unpublishing content or e-mailing an administrator. For more information, see the online handbook entry for <a href="@trigger">Trigger module</a>.', array('@trigger' => 'http://drupal.org/documentation/modules/trigger/')) . '</p>';
       
    30     $output .= '<h3>' . t('Uses') . '</h3>';
       
    31     $output .= '<dl>';
       
    32     $output .= '<dt>' . t('Configuring triggers and actions') . '</dt>';
       
    33     $output .= '<dd>' . t('The combination of actions and triggers can perform many useful tasks, such as e-mailing an administrator if a user account is deleted, or automatically unpublishing comments that contain certain words. To set up a trigger/action combination, first visit the <a href="@actions-page">Actions configuration page</a>, where you can either verify that the action you want is already listed, or create a new <em>advanced</em> action. You will need to set up an advanced action if there are configuration options in your trigger/action combination, such as specifying an e-mail address or a list of banned words. After configuring or verifying your action, visit the <a href="@triggers-page">Triggers configuration page</a> and choose the appropriate tab (Comment, Taxonomy, etc.), where you can assign the action to run when the trigger event occurs.', array('@triggers-page' => url('admin/structure/trigger'), '@actions-page' => url('admin/config/system/actions'))) . '</dd>';
       
    34     $output .= '</dl>';
       
    35     return $output;
       
    36   }
       
    37 }
       
    38 
       
    39 /**
       
    40  * Implements hook_menu().
       
    41  */
       
    42 function trigger_menu() {
       
    43   $items['admin/structure/trigger'] = array(
       
    44     'title' => 'Triggers',
       
    45     'description' => 'Configure when to execute actions.',
       
    46     'page callback' => 'trigger_assign',
       
    47     'access arguments' => array('administer actions'),
       
    48     'file' => 'trigger.admin.inc',
       
    49   );
       
    50 
       
    51   $trigger_info = _trigger_tab_information();
       
    52   foreach ($trigger_info as $module => $module_name) {
       
    53     $items["admin/structure/trigger/$module"] = array(
       
    54       'title' => $module_name,
       
    55       'page callback' => 'trigger_assign',
       
    56       'page arguments' => array($module),
       
    57       'access arguments' => array('administer actions'),
       
    58       'type' => MENU_LOCAL_TASK,
       
    59       'file' => 'trigger.admin.inc',
       
    60     );
       
    61   }
       
    62 
       
    63   $items['admin/structure/trigger/unassign'] = array(
       
    64     'title' => 'Unassign',
       
    65     'description' => 'Unassign an action from a trigger.',
       
    66     'page callback' => 'drupal_get_form',
       
    67     'page arguments' => array('trigger_unassign'),
       
    68     // Only accessible if there are any actions that can be unassigned.
       
    69     'access callback' => 'trigger_menu_unassign_access',
       
    70     // Only output in the breadcrumb, not in menu trees.
       
    71     'type' => MENU_VISIBLE_IN_BREADCRUMB,
       
    72     'file' => 'trigger.admin.inc',
       
    73   );
       
    74 
       
    75   return $items;
       
    76 }
       
    77 
       
    78 /**
       
    79  * Access callback: Determines if triggers can be unassigned.
       
    80  *
       
    81  * @return bool
       
    82  *   TRUE if there are triggers that the user can unassign, FALSE otherwise.
       
    83  *
       
    84  * @see trigger_menu()
       
    85  */
       
    86 function trigger_menu_unassign_access() {
       
    87   if (!user_access('administer actions')) {
       
    88     return FALSE;
       
    89   }
       
    90   $count = db_select('trigger_assignments')
       
    91     ->countQuery()
       
    92     ->execute()
       
    93     ->fetchField();
       
    94   return $count > 0;
       
    95 }
       
    96 
       
    97 /**
       
    98  * Implements hook_trigger_info().
       
    99  *
       
   100  * Defines all the triggers that this module implements triggers for.
       
   101  */
       
   102 function trigger_trigger_info() {
       
   103    return array(
       
   104      'node' => array(
       
   105        'node_presave' => array(
       
   106          'label' => t('When either saving new content or updating existing content'),
       
   107        ),
       
   108        'node_insert' => array(
       
   109          'label' => t('After saving new content'),
       
   110        ),
       
   111        'node_update' => array(
       
   112          'label' => t('After saving updated content'),
       
   113        ),
       
   114        'node_delete' => array(
       
   115          'label' => t('After deleting content'),
       
   116        ),
       
   117        'node_view' => array(
       
   118          'label' => t('When content is viewed by an authenticated user'),
       
   119        ),
       
   120      ),
       
   121      'comment' => array(
       
   122        'comment_presave' => array(
       
   123          'label' => t('When either saving a new comment or updating an existing comment'),
       
   124        ),
       
   125        'comment_insert' => array(
       
   126          'label' => t('After saving a new comment'),
       
   127        ),
       
   128        'comment_update' => array(
       
   129          'label' => t('After saving an updated comment'),
       
   130        ),
       
   131        'comment_delete' => array(
       
   132          'label' => t('After deleting a comment'),
       
   133        ),
       
   134        'comment_view' => array(
       
   135          'label' => t('When a comment is being viewed by an authenticated user'),
       
   136        ),
       
   137      ),
       
   138      'taxonomy' => array(
       
   139        'taxonomy_term_insert' => array(
       
   140          'label' => t('After saving a new term to the database'),
       
   141        ),
       
   142        'taxonomy_term_update' => array(
       
   143          'label' => t('After saving an updated term to the database'),
       
   144        ),
       
   145        'taxonomy_term_delete' => array(
       
   146          'label' => t('After deleting a term'),
       
   147        ),
       
   148      ),
       
   149      'system' => array(
       
   150        'cron' => array(
       
   151          'label' => t('When cron runs'),
       
   152        ),
       
   153      ),
       
   154      'user' => array(
       
   155        'user_insert' => array(
       
   156          'label' => t('After creating a new user account'),
       
   157        ),
       
   158        'user_update' => array(
       
   159          'label' => t('After updating a user account'),
       
   160        ),
       
   161        'user_delete' => array(
       
   162          'label' => t('After a user has been deleted'),
       
   163        ),
       
   164        'user_login' => array(
       
   165          'label' => t('After a user has logged in'),
       
   166        ),
       
   167        'user_logout' => array(
       
   168          'label' => t('After a user has logged out'),
       
   169        ),
       
   170        'user_view' => array(
       
   171          'label' => t("When a user's profile is being viewed"),
       
   172        ),
       
   173      ),
       
   174    );
       
   175  }
       
   176 
       
   177 /**
       
   178  * Gets the action IDs of actions to be executed for a hook.
       
   179  *
       
   180  * @param $hook
       
   181  *   The name of the hook being fired.
       
   182  *
       
   183  * @return
       
   184  *   An array whose keys are action IDs that the user has associated with
       
   185  *   this trigger, and whose values are arrays containing the action type and
       
   186  *   label.
       
   187  */
       
   188 function trigger_get_assigned_actions($hook) {
       
   189   $actions = &drupal_static(__FUNCTION__, array());
       
   190   if (!isset($actions[$hook])) {
       
   191     $actions[$hook] = db_query("SELECT ta.aid, a.type, a.label FROM {trigger_assignments} ta LEFT JOIN {actions} a ON ta.aid = a.aid WHERE ta.hook = :hook ORDER BY ta.weight", array(
       
   192       ':hook' => $hook,
       
   193     ))->fetchAllAssoc('aid', PDO::FETCH_ASSOC);
       
   194   }
       
   195   return $actions[$hook];
       
   196 }
       
   197 
       
   198 /**
       
   199  * Implements hook_theme().
       
   200  */
       
   201 function trigger_theme() {
       
   202   return array(
       
   203     'trigger_display' => array(
       
   204       'render element' => 'element',
       
   205       'file' => 'trigger.admin.inc',
       
   206     ),
       
   207   );
       
   208 }
       
   209 
       
   210 /**
       
   211  * Implements hook_forms().
       
   212  *
       
   213  * We re-use code by using the same assignment form definition for each hook.
       
   214  */
       
   215 function trigger_forms() {
       
   216   $trigger_info = _trigger_get_all_info();
       
   217   $forms = array();
       
   218   foreach ($trigger_info as $module => $hooks) {
       
   219     foreach ($hooks as $hook => $description) {
       
   220       $forms['trigger_' . $hook . '_assign_form'] = array('callback' => 'trigger_assign_form');
       
   221     }
       
   222   }
       
   223 
       
   224   return $forms;
       
   225 }
       
   226 
       
   227 /**
       
   228  * Loads associated objects for node triggers.
       
   229  *
       
   230  * When an action is called in a context that does not match its type, the
       
   231  * object that the action expects must be retrieved. For example, when an action
       
   232  * that works on users is called during a node hook implementation, the user
       
   233  * object is not available since the node hook call doesn't pass it. So here we
       
   234  * load the object the action expects.
       
   235  *
       
   236  * @param $type
       
   237  *   The type of action that is about to be called.
       
   238  * @param $node
       
   239  *   The node that was passed via the node hook.
       
   240  *
       
   241  * @return
       
   242  *   The object expected by the action that is about to be called.
       
   243  */
       
   244 function _trigger_normalize_node_context($type, $node) {
       
   245   // Note that comment-type actions are not supported in node contexts,
       
   246   // because we wouldn't know which comment to choose.
       
   247   switch ($type) {
       
   248     // An action that works on users is being called in a node context.
       
   249     // Load the user object of the node's author.
       
   250     case 'user':
       
   251       return user_load($node->uid);
       
   252   }
       
   253 }
       
   254 
       
   255 /**
       
   256  * Calls action functions for node triggers.
       
   257  *
       
   258  * @param $node
       
   259  *   Node object.
       
   260  * @param $hook
       
   261  *   Hook to trigger.
       
   262  * @param $a3
       
   263  *   Additional argument to action function.
       
   264  * @param $a4
       
   265  *   Additional argument to action function.
       
   266  */
       
   267 function _trigger_node($node, $hook, $a3 = NULL, $a4 = NULL) {
       
   268   // Keep objects for reuse so that changes actions make to objects can persist.
       
   269   static $objects;
       
   270   // Prevent recursion by tracking which operations have already been called.
       
   271   static $recursion;
       
   272 
       
   273   $aids = trigger_get_assigned_actions($hook);
       
   274   if (!$aids) {
       
   275     return;
       
   276   }
       
   277 
       
   278   if (isset($recursion[$hook])) {
       
   279     return;
       
   280   }
       
   281   $recursion[$hook] = TRUE;
       
   282 
       
   283   $context = array(
       
   284     'group' => 'node',
       
   285     'hook' => $hook,
       
   286   );
       
   287 
       
   288   // We need to get the expected object if the action's type is not 'node'.
       
   289   // We keep the object in $objects so we can reuse it if we have multiple actions
       
   290   // that make changes to an object.
       
   291   foreach ($aids as $aid => $info) {
       
   292     $type = $info['type'];
       
   293     if ($type != 'node') {
       
   294       if (!isset($objects[$type])) {
       
   295         $objects[$type] = _trigger_normalize_node_context($type, $node);
       
   296       }
       
   297       // Since we know about the node, we pass that info along to the action.
       
   298       $context['node'] = $node;
       
   299       $result = actions_do($aid, $objects[$type], $context, $a3, $a4);
       
   300     }
       
   301     else {
       
   302       actions_do($aid, $node, $context, $a3, $a4);
       
   303     }
       
   304   }
       
   305 
       
   306   unset($recursion[$hook]);
       
   307 }
       
   308 
       
   309 /**
       
   310  * Implements hook_node_view().
       
   311  */
       
   312 function trigger_node_view($node, $view_mode) {
       
   313   _trigger_node($node, 'node_view', $view_mode);
       
   314 }
       
   315 
       
   316 /**
       
   317  * Implements hook_node_update().
       
   318  */
       
   319 function trigger_node_update($node) {
       
   320   _trigger_node($node, 'node_update');
       
   321 }
       
   322 
       
   323 /**
       
   324  * Implements hook_node_presave().
       
   325  */
       
   326 function trigger_node_presave($node) {
       
   327   _trigger_node($node, 'node_presave');
       
   328 }
       
   329 
       
   330 /**
       
   331  * Implements hook_node_insert().
       
   332  */
       
   333 function trigger_node_insert($node) {
       
   334   _trigger_node($node, 'node_insert');
       
   335 }
       
   336 
       
   337 /**
       
   338  * Implements hook_node_delete().
       
   339  */
       
   340 function trigger_node_delete($node) {
       
   341   _trigger_node($node, 'node_delete');
       
   342 }
       
   343 
       
   344 /**
       
   345  * Loads associated objects for comment triggers.
       
   346  *
       
   347  * When an action is called in a context that does not match its type, the
       
   348  * object that the action expects must be retrieved. For example, when an action
       
   349  * that works on nodes is called during the comment hook, the node object is not
       
   350  * available since the comment hook doesn't pass it. So here we load the object
       
   351  * the action expects.
       
   352  *
       
   353  * @param $type
       
   354  *   The type of action that is about to be called.
       
   355  * @param $comment
       
   356  *   The comment that was passed via the comment hook.
       
   357  *
       
   358  * @return
       
   359  *   The object expected by the action that is about to be called.
       
   360  */
       
   361 function _trigger_normalize_comment_context($type, $comment) {
       
   362   switch ($type) {
       
   363     // An action that works with nodes is being called in a comment context.
       
   364     case 'node':
       
   365       return node_load(is_array($comment) ? $comment['nid'] : $comment->nid);
       
   366 
       
   367     // An action that works on users is being called in a comment context.
       
   368     case 'user':
       
   369       return user_load(is_array($comment) ? $comment['uid'] : $comment->uid);
       
   370   }
       
   371 }
       
   372 
       
   373 /**
       
   374  * Implements hook_comment_presave().
       
   375  */
       
   376 function trigger_comment_presave($comment) {
       
   377   _trigger_comment($comment, 'comment_presave');
       
   378 }
       
   379 
       
   380 /**
       
   381  * Implements hook_comment_insert().
       
   382  */
       
   383 function trigger_comment_insert($comment) {
       
   384   _trigger_comment($comment, 'comment_insert');
       
   385 }
       
   386 
       
   387 /**
       
   388  * Implements hook_comment_update().
       
   389  */
       
   390 function trigger_comment_update($comment) {
       
   391   _trigger_comment($comment, 'comment_update');
       
   392 }
       
   393 
       
   394 /**
       
   395  * Implements hook_comment_delete().
       
   396  */
       
   397 function trigger_comment_delete($comment) {
       
   398   _trigger_comment($comment, 'comment_delete');
       
   399 }
       
   400 
       
   401 /**
       
   402  * Implements hook_comment_view().
       
   403  */
       
   404 function trigger_comment_view($comment) {
       
   405   _trigger_comment($comment, 'comment_view');
       
   406 }
       
   407 
       
   408 /**
       
   409  * Calls action functions for comment triggers.
       
   410  *
       
   411  * @param $a1
       
   412  *   Comment object or array of form values.
       
   413  * @param $hook
       
   414  *   Hook to trigger.
       
   415  */
       
   416 function _trigger_comment($a1, $hook) {
       
   417   // Keep objects for reuse so that changes actions make to objects can persist.
       
   418   static $objects;
       
   419   $aids = trigger_get_assigned_actions($hook);
       
   420   $context = array(
       
   421     'group' => 'comment',
       
   422     'hook' => $hook,
       
   423   );
       
   424   // We need to get the expected object if the action's type is not 'comment'.
       
   425   // We keep the object in $objects so we can reuse it if we have multiple
       
   426   // actions that make changes to an object.
       
   427   foreach ($aids as $aid => $info) {
       
   428     $type = $info['type'];
       
   429     if ($type != 'comment') {
       
   430       if (!isset($objects[$type])) {
       
   431         $objects[$type] = _trigger_normalize_comment_context($type, $a1);
       
   432       }
       
   433       // Since we know about the comment, we pass it along to the action
       
   434       // in case it wants to peek at it.
       
   435       $context['comment'] = (object) $a1;
       
   436       actions_do($aid, $objects[$type], $context);
       
   437     }
       
   438     else {
       
   439       actions_do($aid, $a1, $context);
       
   440     }
       
   441   }
       
   442 }
       
   443 
       
   444 /**
       
   445  * Implements hook_cron().
       
   446  */
       
   447 function trigger_cron() {
       
   448   $aids = trigger_get_assigned_actions('cron');
       
   449   $context = array(
       
   450     'group' => 'cron',
       
   451     'hook' => 'cron',
       
   452   );
       
   453   // Cron does not act on any specific object.
       
   454   $object = NULL;
       
   455   actions_do(array_keys($aids), $object, $context);
       
   456 }
       
   457 
       
   458 /**
       
   459  * Loads associated objects for user triggers.
       
   460  *
       
   461  * When an action is called in a context that does not match its type, the
       
   462  * object that the action expects must be retrieved. For example, when an action
       
   463  * that works on nodes is called during the user hook, the node object is not
       
   464  * available since the user hook doesn't pass it. So here we load the object the
       
   465  * action expects.
       
   466  *
       
   467  * @param $type
       
   468  *   The type of action that is about to be called.
       
   469  * @param $account
       
   470  *   The account object that was passed via the user hook.
       
   471  *
       
   472  * @return
       
   473  *   The object expected by the action that is about to be called.
       
   474  */
       
   475 function _trigger_normalize_user_context($type, $account) {
       
   476   // Note that comment-type actions are not supported in user contexts,
       
   477   // because we wouldn't know which comment to choose.
       
   478   switch ($type) {
       
   479     // An action that works with nodes is being called in a user context.
       
   480     // If a single node is being viewed, return the node.
       
   481     case 'node':
       
   482       // If we are viewing an individual node, return the node.
       
   483       if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == NULL) {
       
   484         return node_load(array('nid' => arg(1)));
       
   485       }
       
   486       break;
       
   487   }
       
   488 }
       
   489 
       
   490 /**
       
   491  * Implements hook_user_login().
       
   492  */
       
   493 function trigger_user_login(&$edit, $account, $category) {
       
   494   _trigger_user('user_login', $edit, $account, $category);
       
   495 }
       
   496 
       
   497 /**
       
   498  * Implements hook_user_logout().
       
   499  */
       
   500 function trigger_user_logout($account) {
       
   501   $edit = array();
       
   502   _trigger_user('user_logout', $edit, $account);
       
   503 }
       
   504 
       
   505 /**
       
   506  * Implements hook_user_insert().
       
   507  */
       
   508 function trigger_user_insert(&$edit, $account, $category) {
       
   509   _trigger_user('user_insert', $edit, $account, $category);
       
   510 }
       
   511 
       
   512 /**
       
   513  * Implements hook_user_update().
       
   514  */
       
   515 function trigger_user_update(&$edit, $account, $category) {
       
   516   _trigger_user('user_update', $edit, $account, $category);
       
   517 }
       
   518 
       
   519 /**
       
   520  * Implements hook_user_cancel().
       
   521  */
       
   522 function trigger_user_cancel($edit, $account, $method) {
       
   523   switch ($method) {
       
   524     case 'user_cancel_reassign':
       
   525       _trigger_user('user_delete', $edit, $account, $method);
       
   526       break;
       
   527   }
       
   528 }
       
   529 
       
   530 /**
       
   531  * Implements hook_user_delete().
       
   532  */
       
   533 function trigger_user_delete($account) {
       
   534   $edit = array();
       
   535   _trigger_user('user_delete', $edit, $account, NULL);
       
   536 }
       
   537 
       
   538 /**
       
   539  * Implements hook_user_view().
       
   540  */
       
   541 function trigger_user_view($account) {
       
   542   $edit = NULL;
       
   543   _trigger_user('user_view', $edit, $account, NULL);
       
   544 }
       
   545 
       
   546 /**
       
   547  * Calls action functions for user triggers.
       
   548  *
       
   549  * @param $hook
       
   550  *   The hook that called this function.
       
   551  * @param $edit
       
   552  *   Edit variable passed in to the hook or empty array if not needed.
       
   553  * @param $account
       
   554  *   Account variable passed in to the hook.
       
   555  * @param $method
       
   556  *   Method variable passed in to the hook or NULL if not needed.
       
   557  */
       
   558 function _trigger_user($hook, &$edit, $account, $category = NULL) {
       
   559   // Keep objects for reuse so that changes actions make to objects can persist.
       
   560   static $objects;
       
   561   $aids = trigger_get_assigned_actions($hook);
       
   562   $context = array(
       
   563     'group' => 'user',
       
   564     'hook' => $hook,
       
   565     'form_values' => &$edit,
       
   566   );
       
   567   foreach ($aids as $aid => $info) {
       
   568     $type = $info['type'];
       
   569     if ($type != 'user') {
       
   570       if (!isset($objects[$type])) {
       
   571         $objects[$type] = _trigger_normalize_user_context($type, $account);
       
   572       }
       
   573       $context['user'] = $account;
       
   574       actions_do($aid, $objects[$type], $context);
       
   575     }
       
   576     else {
       
   577       actions_do($aid, $account, $context, $category);
       
   578     }
       
   579   }
       
   580 }
       
   581 
       
   582 /**
       
   583  * Calls action functions for taxonomy triggers.
       
   584  *
       
   585  * @param $hook
       
   586  *   Hook to trigger actions for taxonomy_term_insert(),
       
   587  *   taxonomy_term_update(), and taxonomy_term_delete().
       
   588  * @param $array
       
   589  *   Item on which operation is being performed, either a term or
       
   590  *   form values.
       
   591  */
       
   592 function _trigger_taxonomy($hook, $array) {
       
   593   $aids = trigger_get_assigned_actions($hook);
       
   594   $context = array(
       
   595     'group' => 'taxonomy',
       
   596     'hook' => $hook
       
   597   );
       
   598   actions_do(array_keys($aids), (object) $array, $context);
       
   599 }
       
   600 
       
   601 /**
       
   602  * Implements hook_taxonomy_term_insert().
       
   603  */
       
   604 function trigger_taxonomy_term_insert($term) {
       
   605   _trigger_taxonomy('taxonomy_term_insert', (array) $term);
       
   606 }
       
   607 
       
   608 /**
       
   609  * Implements hook_taxonomy_term_update().
       
   610  */
       
   611 function trigger_taxonomy_term_update($term) {
       
   612   _trigger_taxonomy('taxonomy_term_update', (array) $term);
       
   613 }
       
   614 
       
   615 /**
       
   616  * Implements hook_taxonomy_term_delete().
       
   617  */
       
   618 function trigger_taxonomy_term_delete($term) {
       
   619   _trigger_taxonomy('taxonomy_term_delete', (array) $term);
       
   620 }
       
   621 
       
   622 /**
       
   623  * Implements hook_actions_delete().
       
   624  *
       
   625  * Removes all trigger entries for the given action, when an action is deleted.
       
   626  */
       
   627 function trigger_actions_delete($aid) {
       
   628   db_delete('trigger_assignments')
       
   629     ->condition('aid', $aid)
       
   630     ->execute();
       
   631   drupal_static_reset('trigger_get_assigned_actions');
       
   632 }
       
   633 
       
   634 /**
       
   635  * Retrieves and caches information from hook_trigger_info() implementations.
       
   636  *
       
   637  * @return
       
   638  *   Array of all triggers.
       
   639  */
       
   640 function _trigger_get_all_info() {
       
   641   $triggers = &drupal_static(__FUNCTION__);
       
   642 
       
   643   if (!isset($triggers)) {
       
   644     $triggers = module_invoke_all('trigger_info');
       
   645     drupal_alter('trigger_info', $triggers);
       
   646   }
       
   647 
       
   648   return $triggers;
       
   649 }
       
   650 
       
   651 /**
       
   652  * Gathers information about tabs on the triggers administration screen.
       
   653  *
       
   654  * @return
       
   655  *   Array of modules that have triggers, with the keys being the
       
   656  *   machine-readable name of the module, and the values being the
       
   657  *   human-readable name of the module.
       
   658  */
       
   659 function _trigger_tab_information() {
       
   660   // Gather information about all triggers and modules.
       
   661   $trigger_info = _trigger_get_all_info();
       
   662   $modules = system_get_info('module');
       
   663   $modules = array_intersect_key($modules, $trigger_info);
       
   664 
       
   665   $return_info = array();
       
   666   foreach ($modules as $name => $info) {
       
   667     $return_info[$name] = $info['name'];
       
   668   }
       
   669 
       
   670   return $return_info;
       
   671 }