Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.800 diff -u -p -r1.800 comment.module --- modules/comment/comment.module 3 Nov 2009 06:47:22 -0000 1.800 +++ modules/comment/comment.module 3 Nov 2009 16:35:19 -0000 @@ -2336,18 +2336,27 @@ function comment_action_info() { 'label' => t('Publish comment'), 'type' => 'comment', 'configurable' => FALSE, - 'triggers' => array('comment_insert', 'comment_update'), + 'behavior' => array('changes_property'), + 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), ), 'comment_unpublish_action' => array( 'label' => t('Unpublish comment'), 'type' => 'comment', 'configurable' => FALSE, - 'triggers' => array('comment_insert', 'comment_update'), + 'behavior' => array('changes_property'), + 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), ), 'comment_unpublish_by_keyword_action' => array( 'label' => t('Unpublish comment containing keyword(s)'), 'type' => 'comment', 'configurable' => TRUE, + 'behavior' => array('changes_property'), + 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), + ), + 'comment_save_action' => array( + 'label' => t('Save comment'), + 'type' => 'comment', + 'configurable' => FALSE, 'triggers' => array('comment_insert', 'comment_update'), ), ); @@ -2364,18 +2373,18 @@ function comment_action_info() { * @ingroup actions */ function comment_publish_action($comment, $context = array()) { - if (isset($comment->cid)) { - $cid = $comment->cid; + if (isset($comment->comment)) { $subject = $comment->subject; + $comment->status = COMMENT_PUBLISHED; } else { $cid = $context['cid']; $subject = db_query('SELECT subject FROM {comment} WHERE cid = :cid', array(':cid', $cid))->fetchField(); + db_update('comment') + ->fields(array('status' => COMMENT_PUBLISHED)) + ->condition('cid', $cid) + ->execute(); } - db_update('comment') - ->fields(array('status' => COMMENT_PUBLISHED)) - ->condition('cid', $cid) - ->execute(); watchdog('action', 'Published comment %subject.', array('%subject' => $subject)); } @@ -2390,18 +2399,18 @@ function comment_publish_action($comment * @ingroup actions */ function comment_unpublish_action($comment, $context = array()) { - if (isset($comment->cid)) { - $cid = $comment->cid; + if (isset($comment->comment)) { $subject = $comment->subject; + $comment->status = COMMENT_NOT_PUBLISHED; } else { $cid = $context['cid']; $subject = db_query('SELECT subject FROM {comment} WHERE cid = :cid', array(':cid', $cid))->fetchField(); + db_update('comment') + ->fields(array('status' => COMMENT_NOT_PUBLISHED)) + ->condition('cid', $cid) + ->execute(); } - db_update('comment') - ->fields(array('status' => COMMENT_NOT_PUBLISHED)) - ->condition('cid', $cid) - ->execute(); watchdog('action', 'Unpublished comment %subject.', array('%subject' => $subject)); } @@ -2411,9 +2420,7 @@ function comment_unpublish_action($comme * @param $comment * A comment object. * @param $context - * An array providing more information about the context of the call to this action. - * Unused here, since this action currently only supports the insert and update ops of - * the comment hook, both of which provide a complete $comment object. + * Keyed array. Must contain the id of the comment if $comment is not passed. * * @ingroup actions * @see comment_unpublish_by_keyword_action_form() @@ -2422,10 +2429,7 @@ function comment_unpublish_action($comme function comment_unpublish_by_keyword_action($comment, $context) { foreach ($context['keywords'] as $keyword) { if (strpos($comment->comment, $keyword) !== FALSE || strpos($comment->subject, $keyword) !== FALSE) { - db_update('comment') - ->fields(array('status' => COMMENT_NOT_PUBLISHED)) - ->condition('cid', $comment->cid) - ->execute(); + $comment->status = COMMENT_NOT_PUBLISHED; watchdog('action', 'Unpublished comment %subject.', array('%subject' => $comment->subject)); break; } @@ -2460,6 +2464,14 @@ function comment_unpublish_by_keyword_ac } /** + * Action to save a comment. + */ +function comment_save_action($comment) { + comment_save($comment); + watchdog('action', 'Saved comment %title', array('%title' => $comment->subject)); +} + +/** * Implement hook_ranking(). */ function comment_ranking() { Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1161 diff -u -p -r1.1161 node.module --- modules/node/node.module 3 Nov 2009 06:47:22 -0000 1.1161 +++ modules/node/node.module 3 Nov 2009 16:33:00 -0000 @@ -2948,76 +2948,56 @@ function node_action_info() { 'type' => 'node', 'label' => t('Publish content'), 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'triggers' => array('node_presave', 'comment_insert', 'comment_update'), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_unpublish_action' => array( 'type' => 'node', 'label' => t('Unpublish content'), 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'triggers' => array( - 'node_presave', - 'comment_insert', - 'comment_update', - 'comment_delete' - ), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_make_sticky_action' => array( 'type' => 'node', 'label' => t('Make content sticky'), 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'triggers' => array('node_presave', 'comment_insert', 'comment_update'), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_make_unsticky_action' => array( 'type' => 'node', 'label' => t('Make content unsticky'), 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'triggers' => array( - 'node_presave', - 'comment_insert', - 'comment_update', - 'comment_delete' - ), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_promote_action' => array( 'type' => 'node', 'label' => t('Promote content to front page'), 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'triggers' => array('node_presave', 'comment_insert', 'comment_update'), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_unpromote_action' => array( 'type' => 'node', 'label' => t('Remove content from front page'), 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'triggers' => array( - 'node_presave', - 'comment_insert', - 'comment_update', - 'comment_delete' - ), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_assign_owner_action' => array( 'type' => 'node', 'label' => t('Change the author of content'), 'configurable' => TRUE, - 'behavior' => array('changes_node_property'), - 'triggers' => array( - 'node_presave', - 'comment_insert', - 'comment_update', - 'comment_delete', - ), + 'behavior' => array('changes_property'), + 'triggers' => array('node_presave', 'comment_insert', 'comment_update', 'comment_delete'), ), 'node_save_action' => array( 'type' => 'node', 'label' => t('Save content'), 'configurable' => FALSE, - 'triggers' => array('comment_delete', 'comment_insert', 'comment_update'), + 'triggers' => array('comment_insert', 'comment_update', 'comment_delete'), ), 'node_unpublish_by_keyword_action' => array( 'type' => 'node', Index: modules/system/system.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v retrieving revision 1.99 diff -u -p -r1.99 system.api.php --- modules/system/system.api.php 3 Nov 2009 06:47:23 -0000 1.99 +++ modules/system/system.api.php 3 Nov 2009 16:40:26 -0000 @@ -2376,13 +2376,16 @@ function hook_file_mimetype_mapping_alte * - 'triggers': An array of the events (that is, hooks) that can trigger this * action. For example: array('node_insert', 'user_update'). You can also * declare support for any trigger by returning array('any') for this value. - * - 'behavior': (optional) machine-readable array of behaviors of this - * action, used to signal additional actions that may need to be triggered. - * Currently recognized behaviors by Trigger module: - * - 'changes_node_property': If an action with this behavior is assigned to - * a trigger other than 'node_presave', any node save actions also - * assigned to this trigger are moved later in the list. If a node save - * action is not present, one will be added. + * - 'behavior': (optional) A machine-readable array of behaviors of this + * action, used to signal additionally required actions that may need to be + * triggered. Currently recognized behaviors by Trigger module: + * - 'changes_property': If an action with this behavior is assigned to a + * trigger other than a "presave" hook, any save actions also assigned to + * this trigger are moved later in the list. If no save action is present, + * one will be added. + * Modules that are processing actions (like Trigger module) should take + * special care for the "presave" hook, in which case a dependent "save" + * action should NOT be invoked. */ function hook_action_info() { return array( @@ -2390,12 +2393,20 @@ function hook_action_info() { 'type' => 'comment', 'label' => t('Unpublish comment'), 'configurable' => FALSE, - 'triggers' => array('comment_insert', 'comment_update'), + 'behavior' => array('changes_property'), + 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), ), 'comment_unpublish_by_keyword_action' => array( 'type' => 'comment', 'label' => t('Unpublish comment containing keyword(s)'), 'configurable' => TRUE, + 'behavior' => array('changes_property'), + 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), + ), + 'comment_save_action' => array( + 'type' => 'comment', + 'label' => t('Save comment'), + 'configurable' => FALSE, 'triggers' => array('comment_insert', 'comment_update'), ), ); Index: modules/trigger/trigger.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.admin.inc,v retrieving revision 1.20 diff -u -p -r1.20 trigger.admin.inc --- modules/trigger/trigger.admin.inc 2 Nov 2009 04:36:25 -0000 1.20 +++ modules/trigger/trigger.admin.inc 3 Nov 2009 17:30:37 -0000 @@ -83,17 +83,16 @@ function trigger_unassign($form, $form_s * Submit callback for trigger_unassign() form. */ function trigger_unassign_submit($form, &$form_state) { - $form_values = $form_state['values']; - if ($form_values['confirm'] == 1) { - $aid = actions_function_lookup($form_values['aid']); + if ($form_state['values']['confirm'] == 1) { + $aid = actions_function_lookup($form_state['values']['aid']); db_delete('trigger_assignments') - ->condition('hook', $form_values['hook']) + ->condition('hook', $form_state['values']['hook']) ->condition('aid', $aid) ->execute(); $actions = actions_get_all_actions(); watchdog('actions', 'Action %action has been unassigned.', array('%action' => check_plain($actions[$aid]['label']))); drupal_set_message(t('Action %action has been unassigned.', array('%action' => $actions[$aid]['label']))); - $form_state['redirect'] = 'admin/structure/trigger/' . $form_values['module']; + $form_state['redirect'] = 'admin/structure/trigger/' . $form_state['values']['module']; } else { drupal_goto('admin/structure/trigger'); @@ -206,49 +205,56 @@ function trigger_assign_form_validate($f /** * Submit function for trigger_assign_form(). */ -function trigger_assign_form_submit($form, $form_state) { - $form_values = $form_state['values']; - - if (!empty($form_values['aid'])) { - $aid = actions_function_lookup($form_values['aid']); - $weight = db_query("SELECT MAX(weight) FROM {trigger_assignments} WHERE hook = :hook", array( - ':hook' => $form_values['hook'], - ))->fetchField(); +function trigger_assign_form_submit($form, &$form_state) { + if (!empty($form_state['values']['aid'])) { + $aid = actions_function_lookup($form_state['values']['aid']); + $weight = db_query("SELECT MAX(weight) FROM {trigger_assignments} WHERE hook = :hook", array(':hook' => $form_state['values']['hook']))->fetchField(); + // Insert the new action. db_insert('trigger_assignments') ->fields(array( - 'hook' => $form_values['hook'], + 'hook' => $form_state['values']['hook'], 'aid' => $aid, 'weight' => $weight + 1, )) ->execute(); - // If this action changes a node property, we need to save the node - // so the change will persist. + // If we are not configuring an action for a "presave" hook and this action + // changes an object property, then we need to save the object, so the + // property change will persist. $actions = actions_list(); - if (isset($actions[$aid]['behavior']) && in_array('changes_node_property', $actions[$aid]['behavior']) && ($form_values['hook'] != 'node_presave') && ($form_values['hook'] != 'comment_presave')) { - // Delete previous node_save_action if it exists, and re-add a new one at - // a higher weight. - $save_post_action_assigned = db_query("SELECT aid FROM {trigger_assignments} WHERE hook = :hook AND aid = :aid", array( - ':hook' => $form_values['hook'], - ':aid' => 'node_save_action', - ))->fetchField(); + if (strpos($form_state['values']['hook'], 'presave') === FALSE && isset($actions[$aid]['behavior']) && in_array('changes_property', $actions[$aid]['behavior'])) { + // Determine the corresponding save action name for this action. + $save_action = strtok($aid, '_') . '_save_action'; + // If no corresponding save action exists, we need to bail out. + if (!isset($actions[$save_action])) { + throw new Exception(t('Missing/undefined save action (%save_aid) for %aid action.', array('%save_aid' => $aid, '%aid' => $aid))); + } + // Delete previous save action if it exists, and re-add it using a higher + // weight. + $save_action_assigned = db_query("SELECT aid FROM {trigger_assignments} WHERE hook = :hook AND aid = :aid", array(':hook' => $form_state['values']['hook'], ':aid' => $save_action))->fetchField(); - if ($save_post_action_assigned) { + if ($save_action_assigned) { db_delete('trigger_assignments') - ->condition('hook', $form_values['hook']) - ->condition('aid', 'node_save_action') + ->condition('hook', $form_state['values']['hook']) + ->condition('aid', $save_action) ->execute(); } db_insert('trigger_assignments') ->fields(array( - 'hook' => $form_values['hook'], - 'aid' => 'node_save_action', + 'hook' => $form_state['values']['hook'], + 'aid' => $save_action, 'weight' => $weight + 2, )) ->execute(); - if (!$save_post_action_assigned) { - drupal_set_message(t("You have added an action that changes a the property of some content. Your 'Save content' action has been moved later in the list so that the property change will be saved.")); + + // If no save action existed before, inform the user about it. + if (!$save_action_assigned) { + drupal_set_message(t('The %label action has been appended, which is required to save the property change.', array('%label' => $actions[$save_action]['label']))); + } + // Otherwise, just inform about the new weight. + else { + drupal_set_message(t('The %label action was moved to save the property change.', array('%label' => $actions[$save_action]['label']))); } } } Index: modules/trigger/trigger.module =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.module,v retrieving revision 1.52 diff -u -p -r1.52 trigger.module --- modules/trigger/trigger.module 1 Nov 2009 12:11:10 -0000 1.52 +++ modules/trigger/trigger.module 3 Nov 2009 16:28:56 -0000 @@ -106,7 +106,10 @@ function trigger_trigger_info() { ), ), 'comment' => array( - 'comment_insert' => array( + 'comment_presave' => array( + 'label' => t('When either saving a new comment or updating an existing comment'), + ), + 'comment_insert' => array( 'label' => t('After saving a new comment'), ), 'comment_update' => array( @@ -349,6 +352,13 @@ function _trigger_normalize_comment_cont } /** + * Implement hook_comment_presave(). + */ +function trigger_comment_presave($comment) { + _trigger_comment($comment, 'comment_presave'); +} + +/** * Implement hook_comment_insert(). */ function trigger_comment_insert($comment) { @@ -407,7 +417,6 @@ function _trigger_comment($a1, $hook) { actions_do($aid, $objects[$type], $context); } else { - $a1 = (object) $a1; actions_do($aid, $a1, $context); } }