So, I found out where the issue is coming from.
Basically, Revisioning works as follows:
- A node gets saved by Drupal. Drupal doesn't care much about the status.
If the node is published, it remains published. It is important to realize
that, when using Revisioning, if a node has a published revision, for
Drupal the node has a status of 1, regardless of the pending, unpublished
revision. Upon saving, Drupal simply stores a new revision, and updates
the node database row, pointing the revision ID to this new revision.
- Revisioning kicks in, with
revisioning_node_update()
. It checks the
revision_operation
property. Based on its value, it "reverts" what Drupal
just did, setting the revision ID in the node table back to the previous
revision. This is what keeps the published revision one step behind the
pending revision.
Now, this revision_operation
property is only set when in context of a node form. When using VBO (or any way to trigger actions, for that matter), Revisioning doesn't see the revision_operation
property, and revisioning_node_update()
doesn't revert the revision ID.
We could patch this in Revisioning, but the project hasn't received much attention lately (for the D7 version). So this is how I solved it (I have several actions, but I'll give the example of the node_assign_owner_action
action):
/**
* Implements hook_action_info().
*/
function mymodule_action_info() {
return array(
'mymodule_assign_to_user_action' => array(
'type' => 'node',
'label' => t("Assign to user (Revisioning compatible)"),
'configurable' => TRUE,
'behavior' => array('changes_property'),
'triggers' => array('node_presave'),
),
);
}
/**
* Assign a node to a user.
*
* We need a custom action for this, as actions are not entirely compatible with
* Revisioning. We need to tweak the node a bit to force a pending revision to
* stay that way. node_assign_owner_action() does not allow this. See
* _mymodule_actions_reset_revision_operation() for an explanation on why we
* need this.
*
* @see node_assign_owner_action()
* @see node_action_info()
*/
function mymodule_assign_to_user_action($node, $context = array()) {
// Simply proxy to node_assign_owner_action().
node_assign_owner_action($node, $context);
// Make sure the revision_operation property is correctly set.
_mymodule_actions_reset_revision_operation($node);
}
/**
* Configuration form for mymodule_assign_to_user_action().
*
* @see mymodule_assign_to_user_action()
* @see node_assign_owner_action_form()
*/
function mymodule_assign_to_user_action_form($context = array()) {
return node_assign_owner_action_form($context);
}
/**
* Validation callback for mymodule_assign_to_user_action_form().
*
* @see mymodule_assign_to_user_action()
* @see node_assign_owner_action_validate()
*/
function mymodule_assign_to_user_action_validate($form, $form_state) {
node_assign_owner_action_validate($form, $form_state);
}
/**
* Submission callback for mymodule_assign_to_user_action_form().
*
* @see mymodule_assign_to_user_action()
* @see node_assign_owner_action_submit()
*/
function mymodule_assign_to_user_action_submit($form, $form_state) {
return node_assign_owner_action_submit($form, $form_state);
}
/**
* Set the correct node revision_operation property.
*
* @param object $node
* The node on which the action is performed.
*/
function _mymodule_actions_reset_revision_operation($node) {
module_load_include('inc', 'revisioning', 'revisioning_api');
$is_moderated_content = isset($node->revision_moderation) ?
$node->revision_moderation :
revisioning_content_is_moderated($node->type, $node);
$node->revision_operation = (int) $node->is_pending + (int) $is_moderated_content;
}
Thanks to this, we can still use actions provided by core or other modules, but we need to wrap them in another, Revisioning compatible action. When calling _mymodule_actions_reset_revision_operation()
, we use the same logic as Revisioning is using when altering the node form.
It now works.