workflow.pages.inc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <?php
  2. /**
  3. * @file
  4. * Provide user interface for changing workflow state.
  5. *
  6. * @todo D8: remove this in favour of View 'Workflow history per entity'.
  7. */
  8. define('MARK_STATE_IS_DELETED', '*');
  9. /**
  10. * Menu callback. Display workflow summary of a node.
  11. *
  12. * N.B. When having multiple workflows per bundle, use Views display
  13. * 'Workflow history per entity' instead!
  14. */
  15. function workflow_tab_page($entity_type, $entity = NULL) {
  16. drupal_set_title(entity_label($entity_type, $entity));
  17. $form = array();
  18. $field_name = NULL;
  19. $workflow = NULL;
  20. // Figure out the $entity's bundle and id.
  21. list($entity_id, , $entity_bundle) = entity_extract_ids($entity_type, $entity);
  22. $entity_id = entity_id($entity_type, $entity);
  23. // Get the current sid. $field_name is updated with relevant value.
  24. $current_sid = workflow_node_current_state($entity, $entity_type, $field_name);
  25. $current_state = workflow_state_load_single($current_sid);
  26. $workflow = $current_state->getWorkflow();
  27. // Show the current state and the Workflow form to allow state changing.
  28. // N.B. This part is replicated in hook_node_view, workflow_tab_page, workflow_vbo, transition_edit.
  29. // @todo: support multiple workflows per entity.
  30. // For workflow_tab_page with multiple workflows, use a separate view. See [#2217291].
  31. $field = _workflow_info_field($field_name, $workflow);
  32. $field_id = $field['id'];
  33. $instance = field_info_instance($entity_type, $field_name, $entity_bundle);
  34. if (!$field_id) {
  35. // This is a Workflow Node workflow. Set widget options as in v7.x-1.2
  36. $field['settings']['widget']['comment'] = isset($workflow->options['comment_log_tab']) ? $workflow->options['comment_log_tab'] : 1; // vs. ['comment_log_node'];
  37. $field['settings']['widget']['current_status'] = TRUE;
  38. }
  39. $form_id = implode('_', array('workflow_transition_form', $entity_type, $entity_id, $field_id));
  40. $form += drupal_get_form($form_id, $field, $instance, $entity_type, $entity);
  41. $output = drupal_render($form);
  42. // Show the history table.
  43. $rows = array();
  44. $current_themed = FALSE;
  45. $limit = variable_get('workflow_states_per_page', 20);
  46. // Get the history for any field_name.
  47. foreach (workflow_transition_load_multiple($entity_type, array($entity_id), NULL, $limit) as $history) {
  48. $old_state_name = $new_state_name = '';
  49. $label = $name = '';
  50. $new_state = $history->getNewState();
  51. if ($new_state) {
  52. $name = $new_state->getName();
  53. $label = $new_state->label();
  54. }
  55. if (!$new_state) {
  56. // This is an invalid/deleted state.
  57. $old_state_name = $label;
  58. }
  59. elseif ($history->new_sid == $current_sid && $new_state->isActive() && !$current_themed) {
  60. // Theme the current state differently so it stands out.
  61. $new_state_name = theme('workflow_history_current_state', array(
  62. 'state_name' => $label,
  63. 'state_system_name' => $name,
  64. 'sid' => $history->new_sid,
  65. ));
  66. // Make a note that we have themed the current state; other times in the history
  67. // of this node where the node was in this state do not need to be specially themed.
  68. $current_themed = TRUE;
  69. }
  70. elseif (!$new_state->isActive()) {
  71. // The state has been deleted, but we include it in the history.
  72. $new_state_name = theme('workflow_deleted_state', array(
  73. 'state_name' => $label,
  74. 'state_system_name' => $name,
  75. 'sid' => $history->new_sid,
  76. ));
  77. $footer_needed = TRUE;
  78. }
  79. else {
  80. // Regular state.
  81. $new_state_name = $label;
  82. }
  83. unset($new_state); // Not needed anymore.
  84. $label = $name = MARK_STATE_IS_DELETED;
  85. $old_state = $history->getOldState();
  86. if ($old_state) {
  87. $name = $old_state->getName();
  88. $label = $old_state->label();
  89. }
  90. if (!$old_state) {
  91. // This is an invalid/deleted state.
  92. $old_state_name = $label;
  93. }
  94. elseif (!$old_state->isActive()) {
  95. $old_state_name = theme('workflow_deleted_state', array(
  96. 'state_name' => $label,
  97. 'state_system_name' => $name,
  98. 'sid' => $history->old_sid,
  99. ));
  100. $footer_needed = TRUE;
  101. }
  102. else {
  103. // Regular state.
  104. $old_state_name = $label;
  105. }
  106. unset($old_state); // Not needed anymore.
  107. $variables = array(
  108. 'transition' => $history, // @todo D8: pass this WorkflowTransition as only variable. It contains everything.
  109. 'extra' => '',
  110. 'history' => $history, // @todo D8: remove, as this is the same as 'transition'.
  111. 'old_sid' => $history->old_sid, // @todo D8: remove this redundant property.
  112. 'sid' => $history->new_sid, // @todo D8: remove this redundant property.
  113. 'uid' => $history->uid, // @todo D8: remove this redundant property.
  114. 'old_state_name' => $old_state_name,
  115. 'state_name' => $new_state_name,
  116. );
  117. // Allow other modules to modify the row.
  118. // $todo D8: pass only a $transition object.
  119. drupal_alter('workflow_history', $variables);
  120. $rows[] = theme('workflow_history_table_row', $variables);
  121. }
  122. // Mark the first and last rows.
  123. $rows[0]['class'][] = 'first';
  124. $last = count($rows) - 1;
  125. $rows[$last]['class'][] = 'last';
  126. $header = array(t('Date'), t('Field name'), t('Old State'), t('New State'), t('By'), t('Comment'));
  127. $header[] = array('data' => t('Operations'));
  128. // Only display the table if there's anything in it.
  129. if ($rows) {
  130. $variables = array(
  131. 'header' => $header,
  132. 'rows' => $rows,
  133. 'footer' => !empty($footer_needed),
  134. 'entity' => $entity,
  135. 'entity_type' => $entity_type,
  136. );
  137. $output .= theme('workflow_history_table', $variables);
  138. $output .= theme('pager', array('tags' => $limit));
  139. }
  140. return $output;
  141. }
  142. /**
  143. * Theme one WorkflowTansition in a workflow history table row.
  144. *
  145. * $old_state_name and $state_name must be run through check_plain(t()) prior
  146. * to calling this theme function.
  147. */
  148. function theme_workflow_history_table_row($variables) {
  149. $row = array();
  150. $old_state_name = $variables['old_state_name'];
  151. $state_name = $variables['state_name'];
  152. $transition = $variables['transition'];
  153. $row = array(
  154. 'data' => array(
  155. array('data' => format_date($transition->stamp), 'class' => array('timestamp')),
  156. array('data' => $transition->field_name, 'class' => array('field-name')),
  157. array('data' => $old_state_name, 'class' => array('previous-state-name')),
  158. array('data' => $state_name, 'class' => array('state-name')),
  159. array('data' => theme('username', array('account' => $transition->getUser())), 'class' => array('user-name')),
  160. array('data' => filter_xss($transition->comment), 'class' => array('log-comment')),
  161. $variables['extra'],
  162. ),
  163. 'class' => array('workflow_history_row'),
  164. );
  165. return $row;
  166. }
  167. /**
  168. * Theme entire workflow history table.
  169. */
  170. function theme_workflow_history_table($variables) {
  171. $header = $variables['header'];
  172. $rows = $variables['rows'];
  173. $footer = $variables['footer'];
  174. $entity = $variables['entity'];
  175. $entity_type = $variables['entity_type'];
  176. $column_field_name = 1;
  177. $column_operations = 6;
  178. // Remove the Operations column if none are added.
  179. $empty = TRUE;
  180. foreach ($rows as $row) {
  181. $empty &= empty($row['data'][$column_operations]);
  182. }
  183. if ($empty) {
  184. foreach ($rows as &$row) {
  185. unset($row['data'][$column_operations]);
  186. unset($header[$column_operations]);
  187. }
  188. }
  189. // Remove the Field name column if only 1 workflow_field exists.
  190. if (count(_workflow_info_fields($entity, $entity_type)) < 2) {
  191. foreach ($rows as &$row) {
  192. unset($row['data'][$column_field_name]);
  193. unset($header[$column_field_name]);
  194. }
  195. }
  196. $output = theme('table', array('header' => $header, 'rows' => $rows, 'caption' => t('Workflow History')));
  197. if ($footer) {
  198. $output .= MARK_STATE_IS_DELETED . ' ' . t('State is no longer available.');
  199. }
  200. return $output;
  201. }
  202. /**
  203. * Theme the current state in the workflow history table.
  204. *
  205. * $state_name must be run through check_plain(t()) prior
  206. * to calling this theme function.
  207. */
  208. function theme_workflow_history_current_state($variables) {
  209. return $variables['state_name'];
  210. }
  211. /**
  212. * Theme a deleted state in the workflow history table.
  213. *
  214. * $state_name must be run through check_plain(t()) prior
  215. * to calling this theme function.
  216. */
  217. function theme_workflow_deleted_state($variables) {
  218. return $variables['state_name'] . MARK_STATE_IS_DELETED;
  219. }