workflow.form.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <?php
  2. /**
  3. * @file
  4. * Contains helper functions for WorkflowTransitionForm.
  5. */
  6. /**
  7. * Getter/Setter to tell if the action buttons are used.
  8. *
  9. * @param bool $new_value
  10. * Options. If TRUE/FALSE, the value is set. If NULL, value is only 'getted'.
  11. *
  12. * @return bool
  13. * Previous value. If TRUE, action buttons must be created.
  14. *
  15. * @see workflow_form_alter()
  16. * @see WorkflowDefaultWidget::formElement()
  17. *
  18. * Used to save some expensive operations on every form.
  19. */
  20. function _workflow_use_action_buttons($new_value = NULL) {
  21. global $_workflow_use_actions_buttons;
  22. $old_value = $_workflow_use_actions_buttons ? TRUE : FALSE;
  23. // Reset value if requested.
  24. if ($new_value !== NULL) {
  25. $_workflow_use_actions_buttons = $new_value;
  26. }
  27. return $old_value;
  28. }
  29. /**
  30. * Form builder. Move action buttons next to the 'Save'/'Delete' buttons.
  31. *
  32. * This is only used if the set the 'options widget' to 'action buttons'.
  33. * Do not use with multiple workflows per entity: confusing UX.
  34. * ATM this works for:
  35. * - Workflow Field: create, edit, view, workflow tab, comment;
  36. * - Workflow Node: view, workflow tab;
  37. * (For forms with Workflow Node, the form_alter() is AFTER formElement(). )
  38. *
  39. * @todo: move this to WorkflowTransitionForm::_addActionButtons();
  40. */
  41. function workflow_form_alter(&$form, &$form_state, $form_id) {
  42. // Use a fast, custom way to check if we need to do this.
  43. // @todo: Make this work with multiple workflows per entity.
  44. if (!_workflow_use_action_buttons()) {
  45. return;
  46. }
  47. // Find the first workflow.
  48. // (So this won't work with multiple workflows per entity.)
  49. $workflow_form = array();
  50. if (isset($form['workflow'])) {
  51. // Workflow Node or // Workflow History tab.
  52. $workflow_form = &$form['workflow'];
  53. $field_info = $workflow_form['workflow_field']['#value'];
  54. $field_name = $field_info['field_name'];
  55. $langcode = LANGUAGE_NONE;
  56. // Move non-standard 'Submit workflow' button in hook_node_view, workflow_tab_page, workflow_vbo.
  57. if (isset($form['workflow']['actions'])) {
  58. $form['actions'] = $form['workflow']['actions'];
  59. unset($form['workflow']['actions']);
  60. }
  61. }
  62. else {
  63. $field_name = '';
  64. foreach (element_children($form) as $key) {
  65. if (isset($form[$key]['#language'])) {
  66. $langcode = $form[$key]['#language'];
  67. if (isset($form[$key][$langcode][0]['workflow'])) {
  68. // Reference the Workflow Form, we'll remove the buttons later.
  69. $field_name = $key;
  70. $langcode = $form[$field_name]['#language'];
  71. $workflow_form = &$form[$key][$langcode][0]['workflow'];
  72. // Stop looping if found.
  73. break;
  74. }
  75. }
  76. }
  77. }
  78. // Quit if there is no Workflow on this page.
  79. if (!$workflow_form ) {
  80. return;
  81. }
  82. // Quit if there are no Workflow Action buttons.
  83. // (If user has only 1 workflow option, there are no Action buttons.)
  84. if (count($workflow_form['workflow_sid']['#options']) <= 1) {
  85. return;
  86. }
  87. // Find the default submit button and replace with our own action buttons.
  88. if (isset($form['actions']['submit'])) {
  89. $default_submit_action = $form['actions']['submit'];
  90. unset($form['actions']['submit']);
  91. }
  92. elseif (isset($form['actions']['save'])) {
  93. $default_submit_action = $form['actions']['save'];
  94. unset($form['actions']['save']);
  95. }
  96. if (isset($default_submit_action)) {
  97. $current_sid = $workflow_form['workflow_sid']['#default_value'];
  98. $scheduled = isset($workflow_form['workflow_scheduling']['scheduled']) && $workflow_form['workflow_scheduling']['scheduled']['#default_value'];
  99. // Get the min weight for our buttons.
  100. $option_weight = isset($default_submit_action['#weight']) ? $default_submit_action['#weight'] : 0;
  101. $option_weight = $option_weight - count($workflow_form['workflow_sid']['#options']);
  102. $min_weight = $option_weight;
  103. foreach ($workflow_form['workflow_sid']['#options'] as $sid => $option_name) {
  104. // Make the workflow button act exactly like the original submit button.
  105. $same_state_button = ($sid == $current_sid);
  106. // Add target State ID and Field name, to set correct value in validate_buttons callback.
  107. $workflow_submit_action = $default_submit_action + array(
  108. '#workflow_sid' => $sid,
  109. '#workflow_field_name' => $field_name,
  110. );
  111. // Keep option order. Put current state first.
  112. $workflow_submit_action['#weight'] = ($same_state_button) ? $min_weight : ++$option_weight;
  113. // Add/Overwrite some other settings.
  114. $workflow_submit_action['#access'] = TRUE;
  115. $workflow_submit_action['#value'] = $option_name;
  116. $workflow_submit_action['#attributes'] = ($same_state_button) ? array('class' => array('form-save-default-button')) : array();
  117. //$workflow_submit_action['#executes_submit_callback'] = TRUE;
  118. $workflow_submit_action['#attributes']['class'][] = drupal_html_class('workflow_button_' . $option_name);
  119. // Append the form's #validate function, or it won't be called upon submit,
  120. // because the workflow buttons have its own #validate.
  121. if (isset($default_submit_action['#validate'])) {
  122. $workflow_submit_action['#validate'] = $default_submit_action['#validate'];
  123. }
  124. elseif (isset($form['#validate'])) {
  125. $workflow_submit_action['#validate'] = $form['#validate'];
  126. }
  127. $workflow_submit_action['#validate'][] = '_workflow_transition_form_validate_buttons';
  128. // Append the submit-buttons's #submit function, or it won't be called upon submit.
  129. if (isset($default_submit_action['#submit'])) {
  130. $workflow_submit_action['#submit'] = $default_submit_action['#submit'];
  131. }
  132. elseif (isset($form['#submit'])) {
  133. $workflow_submit_action['#submit'] = $form['#submit'];
  134. }
  135. // Hide the same-state button in some cases.
  136. // Alternative: use hide($element);
  137. if ($same_state_button && !$scheduled) {
  138. if (substr( $form['#form_id'], 0, 24) == 'workflow_transition_form') {
  139. // Hide same-state-button on the transition-form (that is:
  140. // view page or workflow history tab) if there is nothing to do.
  141. // However, a Transition may be fieldable.
  142. if ($form['workflow']['workflow_comment']['#access'] == FALSE) {
  143. $workflow_submit_action['#access'] = FALSE;
  144. }
  145. }
  146. elseif ($form['#id'] == 'comment-form') {
  147. // On comment-form, the button must stay, since you can comment to same state.
  148. }
  149. else {
  150. // On a entity edit page, the button must stay.
  151. }
  152. }
  153. // Place the button with the other action buttons.
  154. $form['actions']['workflow_' . $sid] = $workflow_submit_action;
  155. }
  156. // On Edit page, remove the submit button from the workflow form.
  157. unset($workflow_form['actions']);
  158. }
  159. }
  160. /**
  161. * Form builder. Allow workflow comment change from menu item/Views link.
  162. *
  163. * @todo D8: This is used, because the D7 form workflow_transition_form
  164. * has the wrong parameters for the EntityUIController.
  165. * But changing it breaks backwards compatibility.
  166. */
  167. function workflow_transition_wrapper_form(array $form, array &$form_state, $transition, $op, $form_id) {
  168. // Override the default function 'entity_ui_controller_form_<op>'; we're not ready for that yet.
  169. $form['#validate'] = array('workflow_transition_form_validate');
  170. $form['#submit'] = array('workflow_transition_form_submit');
  171. // The Workflow transition is provided as such:
  172. // $form_state['entity_type'] = 'WorkflowTransition';
  173. // $form_state['WorkflowTransition'] = (Object) WorkflowTransition;
  174. return workflow_transition_form($form, $form_state, array(), array(), '', NULL);
  175. }
  176. function workflow_transition_form(array $form, array &$form_state, array $field, $instance, $entity_type, $entity) {
  177. if (!isset ($instance['widget']['settings']['submit_function'])) {
  178. $instance['widget']['settings']['submit_function'] = 'workflow_transition_form_submit';
  179. }
  180. $transition_form = new WorkflowTransitionForm($field, $instance, $entity_type, $entity);
  181. return $transition_form->buildForm($form, $form_state);
  182. }
  183. /**
  184. * Submit callback function for the Workflow Form / DefaultWidget.
  185. *
  186. * Validate target state and either save a transition immediately or schedule
  187. * a transition to be executed later by cron.
  188. */
  189. function workflow_transition_form_validate($form, &$form_state) {
  190. // Even if this function is empty, it must exist.
  191. // Validate the attached fields.
  192. // field_attach_form_validate('WorkflowTransition', $form_state['values'], $form, $form_state);
  193. // $transition_form = new WorkflowTransitionForm($field, $instance, $entity_type, $entity);
  194. // return $transition_form->submitForm($form, $form_state, $items);
  195. }
  196. /**
  197. * Submit callback function for the Workflow Form / DefaultWidget.
  198. *
  199. * Validate target state and either save a transition immediately or schedule
  200. * a transition to be executed later by cron.
  201. */
  202. function workflow_transition_form_submit($form, &$form_state) {
  203. // Retrieve the data from the form.
  204. if (isset($form_state['values']['workflow_field'])) {
  205. // If $entity filled: We are on a Entity View page or Workflow History Tab page.
  206. // If $entity empty: We are on an Advanced Action page.
  207. $field = $form_state['values']['workflow_field'];
  208. $instance = $form_state['values']['workflow_instance'];
  209. $entity_type = $form_state['values']['workflow_entity_type'];
  210. $entity = $form_state['values']['workflow_entity'];
  211. $items = array();
  212. $transition_form = new WorkflowTransitionForm($field, $instance, $entity_type, $entity);
  213. return $transition_form->submitForm($form, $form_state, $items);
  214. }
  215. else {
  216. watchdog('workflow', 'workflow_transition_form_submit() is called with error.');
  217. // We are on an Entity/Node/Comment Form page.
  218. // We should not be here.
  219. return;
  220. }
  221. }
  222. /**
  223. * Submit callback function for the Workflow Form / DefaultWidget.
  224. *
  225. * Validate form data for 'time' element.
  226. */
  227. function _workflow_transition_form_element_validate_time($element, &$form_state, $form) {
  228. if (!strtotime($element['#value'])) {
  229. form_error($element, t('Please enter a valid value for time.'));
  230. }
  231. }
  232. /**
  233. * Submit callback function for the Workflow Form / DefaultWidget.
  234. *
  235. * This is only used when using action buttons in Workflow form.
  236. * It sets the new state to proper
  237. * element and sets a submit function if needed, making sure the action is
  238. * executed, influencing function core/includes/form.inc/form_execute_handlers().
  239. * (While constructing the Workflow form, we were not yet aware of the submit
  240. * buttons of the complete form. We try to correct this here, without adding
  241. * another hook_form_alter. We guess the first button is the Save button.
  242. */
  243. function _workflow_transition_form_validate_buttons($form, &$form_state) {
  244. $field_name = $form_state['triggering_element']['#workflow_field_name'];
  245. $new_sid = $form_state['triggering_element']['#workflow_sid'];
  246. $langcode = LANGUAGE_NONE;
  247. // Retrieve the data from the form.
  248. if (isset($form_state['values']['workflow_field'])) {
  249. // We are on a Entity View page or Workflow History Tab page.
  250. $entity_type = $form_state['values']['workflow_entity_type'];
  251. $entity = $form_state['values']['workflow_entity'];
  252. $langcode = _workflow_metadata_workflow_get_properties($entity, array(), 'langcode', $entity_type, $field_name);
  253. }
  254. /*
  255. if (isset($form_state['triggering_element']['#submit'])) {
  256. // We are on a View page or History tab. Try to fix the form_state.
  257. else {
  258. // We are on a Node/Entity/Comment form. Try to fix the form_state.
  259. }
  260. */
  261. if ($field_name) {
  262. $form_state['input']['workflow_sid'] = $new_sid;
  263. $form_state['values'][$field_name][$langcode][0]['workflow']['workflow_sid'] = $new_sid;
  264. }
  265. else {
  266. $form_state['input']['workflow_sid'] = $new_sid;
  267. $form_state['values']['workflow_sid'] = $new_sid;
  268. }
  269. }