workflow_admin_ui.page.type_map.inc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. /**
  3. * @file
  4. * Provides the type_map maintenance form.
  5. */
  6. /**
  7. * Page builder. Show a maintenance table for type mapping.
  8. *
  9. * Appends the type_map form, allowing administrator
  10. * to map workflows to content types and determine placement on content forms.
  11. */
  12. function workflow_admin_ui_type_map_form(&$form) {
  13. // Create list of all Workflow types. Include an initial empty value.
  14. // Validate each workflow, and generate a message if not complete.
  15. $workflows[0] = t('None');
  16. foreach (workflow_load_multiple() as $workflow) {
  17. if ($workflow->isValid()) {
  18. $workflows[$workflow->wid] = $workflow->label();
  19. }
  20. }
  21. if (count($workflows) == 1) {
  22. drupal_set_message(t('You must create at least one workflow before content can be assigned to a workflow.'));
  23. return $form;
  24. }
  25. $type_map = workflow_get_workflow_type_map();
  26. $form['#tree'] = TRUE;
  27. $form['type_map'] = array(
  28. '#type' => 'fieldset',
  29. // '#type' => 'container',
  30. '#theme' => 'workflow_admin_ui_type_map_form',
  31. '#title' => t('Content Type Mapping'),
  32. '#collapsible' => TRUE,
  33. '#collapsed' => FALSE,
  34. );
  35. $form['type_map']['help'] = array(
  36. '#type' => 'item',
  37. '#title' => '<h3>' . t('Content Type Mapping') . '</h3>',
  38. '#markup' => t('Each content type may have a separate workflow. The form
  39. for changing workflow state can be displayed when editing a node, editing
  40. a comment for a node, or both.'),
  41. );
  42. $placement_options = array(
  43. 'node' => t('Post'),
  44. 'comment' => t('Comment'),
  45. );
  46. foreach (node_type_get_names() as $node_type => $name) {
  47. $form['type_map'][$node_type]['workflow'] = array(
  48. '#type' => 'select',
  49. '#options' => $workflows,
  50. '#default_value' => isset($type_map[$node_type]) ? $type_map[$node_type] : 0,
  51. );
  52. $form['type_map'][$node_type]['placement'] = array(
  53. '#type' => 'checkboxes',
  54. '#options' => $placement_options,
  55. '#default_value' => variable_get('workflow_' . $node_type, array()),
  56. );
  57. }
  58. $header = array(t('Content Type cc'), t('Workflow'), t('Display Workflow Form on:'));
  59. $form['type_map']['#header'] = $header;
  60. $rows = array();
  61. foreach (node_type_get_names() as $node_type => $name) {
  62. $w = array(
  63. '#type' => 'select',
  64. '#options' => $workflows,
  65. '#default_value' => isset($type_map[$node_type]) ? $type_map[$node_type] : 0,
  66. );
  67. $p = array(
  68. '#type' => 'checkboxes',
  69. '#options' => array(
  70. 'node' => t('Post'),
  71. 'comment' => t('Comment'),
  72. ),
  73. '#default_value' => variable_get('workflow_' . $node_type, array()),
  74. '#value' => variable_get('workflow_' . $node_type, array()),
  75. '#attributes' => array('style' => 'width: auto; clear: both;'),
  76. );
  77. // Use separate line to avoid PHP5.4 error.
  78. $p_element = form_process_checkboxes($p);
  79. $row = array(
  80. check_plain(t($name)),
  81. drupal_render($w),
  82. drupal_render($p_element),
  83. );
  84. $rows[] = $row;
  85. $form['type_map'][$node_type]['workflow_map'] = array(
  86. '#theme' => 'table',
  87. // '#header' => $header,
  88. '#rows' => array($node_type => $row),
  89. '#empty' => t('No content available.'),
  90. '#attributes' => array('style' => 'width: auto; clear: both;'),
  91. );
  92. }
  93. $form['type_map']['workflow_map'] = array(
  94. '#theme' => 'table',
  95. '#header' => $header,
  96. '#rows' => $rows,
  97. '#empty' => t('No content available.'),
  98. // '#attributes' => array('style' => 'width: auto; clear: both;'),
  99. );
  100. $form['type_map']['workflow_access_priority'] = array(
  101. '#type' => 'weight',
  102. '#delta' => 10,
  103. '#title' => t('Workflow Access Priority'),
  104. '#default_value' => variable_get('workflow_access_priority', 0),
  105. '#description' => t('This sets the node access priority. Changing this
  106. setting can be dangerous. If there is any doubt, leave it at 0.
  107. <a href="@url">Read the manual.</a>', array('@url' => url('https://api.drupal.org/api/drupal/modules!node!node.api.php/function/hook_node_access_records/7'))),
  108. );
  109. $form['#submit'][] = 'workflow_admin_ui_type_map_form_submit';
  110. return $form;
  111. }
  112. /**
  113. * Theme the workflow type mapping form.
  114. */
  115. function theme_workflow_admin_ui_type_map_form($variables) {
  116. $output = '';
  117. $form = $variables['form'];
  118. $header = array(t('Content Type'), t('Workflow'), t('Display Workflow Form on:'));
  119. $caption = t('Each content type may have a separate workflow. The form for
  120. changing workflow state can be displayed when editing a node, editing a
  121. comment for a node, or both.');
  122. $rows = array();
  123. foreach (node_type_get_names() as $node_type => $type_name) {
  124. $rows[] = array(
  125. check_plain(t($type_name)),
  126. drupal_render($form[$node_type]['workflow']),
  127. drupal_render($form[$node_type]['placement']),
  128. );
  129. }
  130. $output .= theme('table', array(
  131. 'header' => $header,
  132. 'rows' => $rows,
  133. 'caption' => $caption,
  134. // 'attributes' => array('style' => 'width: auto; clear: both;'),
  135. )
  136. );
  137. return $output;
  138. }
  139. /**
  140. * Submit handler for workflow type mapping form.
  141. *
  142. * Save mapping of workflow to node type. E.g., the story node type is using the Foo workflow.
  143. *
  144. * @see workflow_types_form()
  145. */
  146. function workflow_admin_ui_type_map_form_submit($form, &$form_state) {
  147. $form_values = $form_state['values'];
  148. // Empty the table and the variables so that types no longer under workflow go away.
  149. // @todo: it is possible to switch to new workflow for node_type, leaving nodes stuck in old workflow.
  150. workflow_delete_workflow_type_map_all();
  151. $node_types = node_type_get_names();
  152. foreach ($node_types as $node_type => $type_name) {
  153. $wid = $form_values['type_map'][$node_type]['workflow'];
  154. variable_del('workflow_' . $node_type);
  155. if ($wid) {
  156. workflow_insert_workflow_type_map($node_type, $wid);
  157. variable_set('workflow_' . $node_type, array_keys(array_filter(($form_values['type_map'][$node_type]['placement']))));
  158. // If this type uses workflow, make sure pre-existing nodes are set
  159. // to the workflow's creation state.
  160. if ($form_values['type_map'][$node_type]['workflow']) {
  161. _workflow_node_initialize_nodes('node', $node_type, $field_name = '', $wid);
  162. }
  163. }
  164. }
  165. drupal_set_message(t('The workflow mapping was saved.'));
  166. }
  167. /**
  168. * Initialize all pre-existing nodes of a type to their first state.
  169. *
  170. * @param string $node_type
  171. * The node type.
  172. *
  173. * @todo: adjust _workflow_node_initialize_nodes() to handle Workflow Field.
  174. */
  175. function _workflow_node_initialize_nodes($entity_type, $node_type, $field_name, $wid) {
  176. global $user;
  177. // Build the select query.
  178. // We want all published nodes of this type that don't already have a workflow state.
  179. $query = db_select('node', 'n');
  180. $query->leftJoin('workflow_node', 'wn', 'wn.nid = n.nid');
  181. // Add the fields.
  182. $query->addField('n', 'nid');
  183. // Add conditions.
  184. $query->condition('n.type', $node_type);
  185. $query->condition('n.status', 1);
  186. $query->isNull('wn.sid');
  187. $nids = $query->execute()->fetchCol();
  188. $how_many = count($nids);
  189. if ($how_many == 0) {
  190. return;
  191. }
  192. $comment = t('Pre-existing content set to initial state.');
  193. $workflow = workflow_load_single($wid);
  194. $force = TRUE;
  195. $creation_sid = $workflow->getCreationSid();
  196. // Load them all up.
  197. $nodes = node_load_multiple($nids);
  198. foreach ($nodes as $entity) {
  199. // Get the initial state for this entity.
  200. // Due to permissions, it might be different for each user.
  201. $new_sid = $workflow->getFirstSid($entity_type, $entity, $field_name, $user, $force);
  202. $transition = new WorkflowTransition();
  203. $transition->setValues($entity_type, $entity, $field_name, $creation_sid, $new_sid, $user->uid, REQUEST_TIME, $comment);
  204. // Force it to transition to the first state and get a history record.
  205. workflow_execute_transition($entity_type, $entity, $field_name, $transition, $force);
  206. }
  207. drupal_set_message(t('!count @type nodes have been initialized.', array('@type' => node_type_get_name($node_type), '!count' => $how_many)));
  208. }