workflow_revert.module 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <?php
  2. /**
  3. * @file
  4. * Adds an 'Revert' link to the first workflow history row.
  5. */
  6. /**
  7. * Implements hook_permission().
  8. */
  9. function workflow_revert_permission() {
  10. return array(
  11. 'revert workflow' => array(
  12. 'title' => t('Revert workflow'),
  13. 'description' => t('Allow user to revert workflow state.'),
  14. ),
  15. );
  16. }
  17. /**
  18. * Implements hook_menu().
  19. */
  20. function workflow_revert_menu() {
  21. $items = array();
  22. $items['workflow_revert'] = array(
  23. 'title' => 'Workflow Undo',
  24. 'file' => 'workflow_revert.pages.inc',
  25. 'access arguments' => array('revert workflow'),
  26. 'page callback' => 'drupal_get_form',
  27. 'page arguments' => array('workflow_revert_form'),
  28. 'type' => MENU_CALLBACK,
  29. );
  30. return $items;
  31. }
  32. /**
  33. * Implements hook_rules_event_info().
  34. *
  35. * @todo: Add support for every entity_type in Revert rules.
  36. */
  37. function workflow_revert_rules_event_info() {
  38. $events = array(
  39. 'workflow_state_reverted' => array(
  40. 'group' => t('Workflow'),
  41. 'label' => t('Workflow state reverted'),
  42. 'variables' => rules_events_node_variables(t('updated content'), TRUE),
  43. ),
  44. );
  45. return $events;
  46. }
  47. /**
  48. * Implements hook_workflow_history_alter().
  49. *
  50. * Adds an 'undo' operation for the most recent history change.
  51. *
  52. * @param array $variables
  53. * The current workflow history information as an array.
  54. * 'transition' - a WorkflowTransition object.
  55. */
  56. function workflow_revert_workflow_history_alter(array &$variables) {
  57. global $user;
  58. static $first = TRUE;
  59. $transition = $variables['transition'];
  60. // Check access, to avoid that user sees a revert link, but is not allowed to
  61. // view the revert form. Use $first to check only once per page.
  62. if ($first) {
  63. if (!user_access('revert workflow', $user)) {
  64. $first = FALSE;
  65. return;
  66. }
  67. }
  68. // Only mark the first row.
  69. if ($first) {
  70. $old_sid = $transition->old_sid;
  71. $new_sid = $transition->new_sid;
  72. // Some states are not fit to revert to. In each of these cases, prohibit
  73. // to revert to an even older state.
  74. $old_state = $transition->getOldState();
  75. if (!$old_state || !$old_state->isActive() || $old_state->isCreationState()) {
  76. $first = FALSE;
  77. }
  78. elseif ($old_sid == $new_sid) {
  79. // Do not add the revert link, but allow an even older state.
  80. }
  81. else {
  82. // Let's ask other modules if the reversion is allowed. Reversing old and new sid!
  83. // @todo D8: remove, or replace by 'transition pre'. See WorkflowState::getOptions().
  84. $entity_type = $transition->entity_type;
  85. $entity = $transition->getEntity();
  86. $id = $transition->entity_id;
  87. $field_name = $transition->field_name;
  88. $permitted = module_invoke_all('workflow', 'transition permitted', $new_sid, $old_sid, $entity, $force = FALSE, $entity_type, $field_name, $transition, $user);
  89. // Stop if a module says so.
  90. if (!in_array(FALSE, $permitted, TRUE)) {
  91. // If not vetoed, mark it.
  92. $options = array('query' => array('token' => drupal_get_token('workflow_revert ' . $old_sid)));
  93. $path = 'workflow_revert/' . $entity_type . '/' . $id . '/' . $field_name . '/' . $old_sid;
  94. // If you want to add additional data, place it in the 'extra' value.
  95. $variables['extra'] = l(t('Revert state change'), $path, $options);
  96. $first = FALSE;
  97. }
  98. }
  99. }
  100. }