I think what is going on is that during normal node saving via the node edit form is that in workbench_moderation_moderate() the latest revision is unpublished here:
// If this revision is to be published, the new moderation record should be
// the only one flagged 'published' in both
// {workbench_moderation_node_history} AND {node_revision}
if ($new_revision->published) {
$query = db_update('workbench_moderation_node_history')
->condition('nid', $node->nid)
->fields(array('published' => 0))
->execute();
$query = db_update('node_revision')
->condition('nid', $node->nid)
->fields(array('status' => 0))
->execute();
}
Then the 'real' node revision is saved via a shutdown function workbench_moderation_store()
function workbench_moderation_store($node) {
if (!isset($node->nid)) {
watchdog('Workbench moderation', 'Failed to save node revision: node not passed to shutdown function.', array(), WATCHDOG_NOTICE);
return;
}
watchdog('Workbench moderation', 'Saved node revision: %node as live version for node %live.', array('%node' => $node->vid, '%live' => $node->nid), WATCHDOG_NOTICE, l($node->title, 'node/' . $node->nid));
$live_revision = workbench_moderation_node_live_load($node);
// Make sure we're published.
$live_revision->status = 1;
// Don't create a new revision.
$live_revision->revision = 0;
// Prevent another moderation record from being written.
$live_revision->workbench_moderation['updating_live_revision'] = TRUE;
// Reset flag from taxonomy_field_update() so that {taxonomy_index} values aren't written twice.
$taxonomy_index_flag = &drupal_static('taxonomy_field_update', array());
unset($taxonomy_index_flag[$node->nid]);
// Save the node.
node_save($live_revision);
}
Of course there's a high chance that this won't work during a migration (or any other programatic node save).
Comments
Comment #1
dalinMy workaround is to do this in complete($entity, $row):
Comment #2
dalinAnd to elaborate I'm doing the following in prepare($entity, $row)
Comment #3
stevectorChanging issue queues to Workbench Moderation.
I recently used a combination of Feeds and Rules for node imports. I also found it easiest to directly change workbench_moderation_state_new.
Having never used Migrate module myself I'm not sure how to best aid its imports.
Dalin, what could Workbench Moderation add to make Migrate imports easier?
Comment #4
dalinJust the whole shutdown function seems a bit crufty. In scenarios where a lot of nodes are being acted on it results in a lot of memory overhead. And if the process is terminated prematurely then things are in an inconsistent state. Partly I'm not understanding why the shutdown function needs to exist. If the standard node hooks aren't sufficient, then perhaps there needs to be another hook added somewhere?
Comment #5
stevectorThe shutdown function is crufty. It's necessary to re-save the published version of a node after saving an unpublished "forward revision." All of the modules in this space, ERS, State Machine, etc use something like this (hook_exit also works) to get around the fact that core always puts the most recently saved thing in the node table.
I'll be bringing this up at my core conversation in Denver: http://denver2012.drupal.org/content/i-just-want-edit-node
Comment #6
dixon_Cross linking since this is semi-related: #1445824: Support for Migrate module
Comment #7
stevectorI've run into this myself now working on a migration. I think a solution is to make smarter that problem db_update() dalin points out.
So
Instead of
The module works in normal usage without that condition because the crufty shutdown function sets the status of the published revision back to 1. As dalin points out, that can fail in a migration.
And I think this patch brings the code closer to the comments which say that other revisions should be switched to status 0, not this one.
Comment #7.0
stevectorReplaced code tags with php tags
Comment #8
jp.stacey commentedFor reference, I've had some success within the migration by setting the following in the
prepare()method:This ensures that
node_save()still saves a revision (it should spot the lack of nid and set->is_newitself anyway) but preventsworkbench_moderation_moderate()from firing duringhook_node_update()/hook_node_insert(), which might otherwise register a node-moderate action with the shutdown functions.I'm not sure why Migration (or possibly Migrate D2D in this instance) sets
$entity->revisionto TRUE. Does it really need to?Edit:
->is_newhas to be set based on presence or absence of the node ID. Otherwise:$entity->is_newto TRUE to try to tricknode_save(),$entity->revisionhas been set to FALSE to trickworkbench_moderation_moderate(),INSERTed, leading to a PDO exception.This was incorrectly reported on #2204917: High-water mark and integrity constraint violation: duplicating changed nodes? as a bug in the Migrate or D2D projects, but actually came from this code!
Comment #9
damonbla commentedJust wanted to say thank you jp.stacey, #8 just fixed the problem for us. Could not figure out for the life of us why nodes looked like they were published (and said Published on the nodes themselves) but still came up as not published when looking harder (like the css classes and user visibility). Adding that prepare() function to the migrate code worked like a charm.
Comment #10
dgtlmoon commentedThumbs up for the fix in #8 (Is this a bug request? kind of in the middle right?)
Comment #11
one_orange_cat commentedIt took a number of things to get my migrate code working in the end but #8 was the charm, thanks!! More details here: https://www.drupal.org/node/1445824#comment-9176399
Comment #12
mikeryanJust going through my first migration involving workbench_moderation and hitting lots of pain with that crufty shutdown function hack. Two pain points:
We're going to try to @jp.stacey's suggestion above, thanks. But there really needs to be a less hacky way to get the proper moderation statuses set - a way to get it done within the original hook.
Comment #13
mikeryanSo far so good (although we have some testing to go to make sure everything's ending up in the right state). I found it simpler to do it through field mappings rather than by setting things in prepare():
Comment #14
mikeryanSee my updates to the migration support in https://www.drupal.org/node/1445824#comment-9255387 - with that patch, you should only need to map workbench_moderation_state_new in the normal way and everything should work (so that should address this issue as well).
Comment #15
danepowell commentedBe careful with the patch in #7, under heavy load it will result in content becoming published even if you save it as a draft.
Comment #16
earthmanweb commented$entity->is_new = !(isset($entity->nid) && ($entity->nid));jp.stacey, #8 - DUDE! Thank you for this, I was tearing my hair out with this one.
Comment #17
dalinFWIW, you can simplify that as