' . t('Current state: @state', array('@state' => $state)) . ''; } /** * Implements hook_node_load(). */ function workflownode_node_load($nodes, $types) { // Get which types have workflows associated with them. $workflow_types = workflow_get_workflow_type_map(); // Leave early if nodes do not have workflow. if (!$workflow_types || !array_intersect_key($workflow_types, array_flip($types))) { return; } // Read the current state for all nodes. $states = workflow_get_workflow_node_by_nid(array_keys($nodes)); foreach ($nodes as $nid => $node) { // If it's not a workflow type, quit immediately. if (!array_key_exists($node->type, $workflow_types)) { continue; } // Nodes that existed before the workflow was defined may not have a state. $workflow_node = isset($states[$nid]) ? $states[$nid] : NULL; if (!$workflow_node) { if ($workflow = workflow_get_workflows_by_type($node->type, 'node')) { $node->workflow = $workflow->getCreationSid(); $node->workflow_stamp = $node->created; } else { // Is this possible? } } else { $node->workflow = $workflow_node->sid; $node->workflow_stamp = $workflow_node->stamp; } } // As of workflow 7.x-2.x, the scheduled transition is not loaded. See issue #2138591. } /** * Implements hook_node_view(). */ function workflownode_node_view($node, $view_mode, $langcode) { global $user; $form = array(); $entity_type = 'node'; // This hook is only for nodes. $entity_id = $node->nid; $field_name = ''; // This hook is only for workflow_node. $entity_bundle = $node->type; // Skip if there are no Node API workflows. if (!workflow_get_workflow_type_map_by_type($entity_bundle)) { return; } // Check permission, so that even with state change rights, // the form can be suppressed from the node view (#1893724). if (!user_access('show workflow state form', $user)) { return; } // Get the current sid. $field_name is updated with relevant value. $current_sid = workflow_node_current_state($node, $entity_type, $field_name); $current_state = workflow_state_load_single($current_sid); // Show current state at the top of the node display. $field = $instance = array(); $node->content['workflow_current_state'] = workflow_state_formatter($entity_type, $node, $field, $instance, $current_sid); $node->content['workflow_current_state']['#weight'] = -99; if ($current_state && $current_state->showWidget('node', $node, '', $user, FALSE)) { $workflow = $current_state->getWorkflow(); // Show the current state and the Workflow form to allow state changing. // N.B. This part is replicated in hook_node_view, workflow_tab_page, workflow_vbo. if ($workflow) { $field = _workflow_info_field($field_name, $workflow); $field_id = $field['id']; $instance = field_info_instance($entity_type, $field_name, $entity_bundle); // If no instance is found, restore the array. if (!is_array($instance)) { $instance = array(); } if (!$field['id']) { // This is a Workflow Node workflow. Set widget options as in v7.x-1.2 $field['settings']['widget']['comment'] = isset($workflow->options['comment_log_node']) ? $workflow->options['comment_log_node'] : 1; // vs. ['comment_log_tab']; $field['settings']['widget']['current_status'] = FALSE; } } // By including the nid in the form id. For backwards compatiblity, do not add entity_type, field_id. $form_id = implode('_', array('workflow_transition_form', $entity_id)); $form += drupal_get_form($form_id, $field, $instance, $entity_type, $node); $form['#weight'] = 99; $node->content['workflow'] = $form; } } /** * Implements hook_node_insert(). * * This is executed after saving data to the database. * We cannot use hook_node_presave, because workflow_execute_transition() needs the nid. */ function workflownode_node_insert($node) { global $user; if (!isset($node->workflow_field)) { // Initializing the state of the node in case no widget on Node form. if ($workflow = workflow_get_workflows_by_type($node->type, 'node')) { $comment = t('Set to initial state.'); $force = TRUE; $creation_sid = $workflow->getCreationSid(); // Get the initial state for this node. // Due to permissions, it might be different for each user. $new_sid = $workflow->getFirstSid('node', $node, null, $user, $force); $transition = new WorkflowTransition(); $transition->setValues('node', $node, null, $creation_sid, $new_sid, $user->uid, REQUEST_TIME, $comment); // Force it to transition to the first state and get a history record. workflow_execute_transition('node', $node, null, $transition, $force); } } return workflownode_node_update($node); } /** * Implements hook_node_update(). */ function workflownode_node_update($node) { if (!isset($node->workflow_field)) { // For this type_map, user did not want a form here. return; } $form = array(); // Retrieve the data from the form. // Add form values (field, instance, entity_type, entity), then form input. $form_state = array(); $form_state['values']['workflow_field'] = $node->workflow_field; $form_state['values']['workflow_instance'] = $node->workflow_instance; $form_state['values']['workflow_entity_type'] = 'node'; // Careful: take the fresh node here, not the one that is in the form. $form_state['values']['workflow_entity'] = $node; // For some reason, the Workflow Form does not return the form in a 'workflow' array. // @todo: correct this (use '#tree => TRUE'), or filter on 'workflow' elements. $form_state['input'] = (array) $node; workflow_transition_form_submit($form, $form_state); } /** * Implements hook_node_delete(). */ function workflownode_node_delete($node) { if (!empty($node->workflow)) { // Call field_info_field(). // Generates pseudo data for workflow_node to re-use Field API. $field = _workflow_info_field($field_name = '', $workflow = NULL); $instance = array(); $items[0]['value'] = $node->workflow; $workflow_field = new WorkflowItem($field, $instance, 'node', $node); $workflow_field->delete($items); } } /** * Implements hook_comment_insert(). */ function workflownode_comment_insert($comment) { workflownode_comment_update($comment); } /** * Implements hook_comment_update(). */ function workflownode_comment_update($comment) { // Retrieve the data from the form. if (!isset($comment->workflow_field)) { // For this type_map, user did not want a form here. return; } $form = array(); // Retrieve the data from the form. // Add form values (field, instance, entity_type, entity), then form input. $form_state = array(); $form_state['values']['workflow_field'] = $comment->workflow_field; $form_state['values']['workflow_instance'] = $comment->workflow_instance; $form_state['values']['workflow_entity_type'] = $comment->workflow_entity_type; $form_state['values']['workflow_entity'] = $comment->workflow_entity; // For some reason, the Workflow Form does not return the form in a 'workflow' array. // @todo: correct this, or filter on 'workflow' elements. $form_state['input'] = (array) $comment; workflow_transition_form_submit($form, $form_state); } /** * Implements hook_field_extra_fields(). */ function workflownode_field_extra_fields() { $extra = array(); // Get all workflows by content types. $types = array_filter(workflow_get_workflow_type_map()); // Add the extra fields to each content type that has a workflow. foreach ($types as $type => $wid) { $extra['node'][$type] = array( 'form' => array( 'workflow' => array( 'label' => t('Workflow'), 'description' => t('Workflow module form'), 'weight' => 99, // Default to bottom. ), ), 'display' => array( 'workflow_current_state' => array( 'label' => t('Workflow: Current State'), 'description' => t('Current workflow state'), 'weight' => -99, // Default to top. ), 'workflow' => array( 'label' => t('Workflow: State Change Form'), 'description' => t('The form for controlling workflow state changes.'), 'weight' => 99, // Default to bottom. ), ), ); } return $extra; } /** * Implements hook_form_BASE_FORM_ID_alter(). * * Shows the form only on Node Edit forms. */ function workflownode_form_node_form_alter(&$form, &$form_state, $form_id) { _workflownode_form_alter($form, $form_state, $form_id); } /** * Implements hook_form_BASE_FORM_ID_alter(). * * Shows the form only on Comment forms. */ function workflownode_form_comment_form_alter(&$form, &$form_state, $form_id) { _workflownode_form_alter($form, $form_state, $form_id); } /** * Helper function to implement hook_form_alter(). * * Is now a subfunction of workflow_form_BASE_FORM_ID_alter(). * This is more performant (compared to 7.x-1.2 and before), since it is called * only on form with correct BASE_FORM_ID. * * @see http://bryanbraun.com/2013/08/17/using-hook-form-base-form-id-alter */ function _workflownode_form_alter(&$form, &$form_state, $form_id) { // Set node to #node if available or load from nid value. $node = isset($form['#node']) ? $form['#node'] : node_load($form['nid']['#value']); $bundle = $node->type; $entity = $node; $entity_type = 'node'; $field_name = ''; // Skip if there are no Node API workflows. if (!workflow_get_workflow_type_map_by_type($bundle)) { return; } if ($workflow = workflow_get_workflows_by_type($bundle, 'node')) { $workflow_entities = variable_get('workflow_' . $bundle, array()); // Abort if the entity type of the form is not in the list that the user // wants to display the workflow form on. if (!in_array($form['#entity_type'], $workflow_entities)) { return; } /* $form['#wf'] = $workflow; $form['workflow'] = array( '#type' => 'fieldset', '#title' => check_plain($label), '#collapsible' => TRUE, '#collapsed' => FALSE, '#weight' => 10, ); */ // Emulate a Field API interface. // Show the current state and the Workflow form to allow state changing. // N.B. This part is replicated in hook_node_view, workflow_tab_page, etc. if ($workflow) { $field = _workflow_info_field($field_name, $workflow); $field_name = $field['field_name']; $field_id = $field['id']; $instance = field_info_instance($entity_type, $field_name, $bundle); if (!$field_id) { // This is a Workflow Node workflow. Set widget options as in v7.x-1.2 $field['settings']['widget']['comment'] = isset($workflow->options['comment_log_node']) ? $workflow->options['comment_log_node'] : 1; // vs. ['comment_log_tab']; $field['settings']['widget']['current_status'] = TRUE; } } // Do not include the default 'Update Workflow' button, since we are already in an Edit form. $instance['widget']['settings']['submit_function'] = ''; // Include the 'workflow form'. $form is modified by reference. $form = workflow_transition_form($form, $form_state, $field, $instance, $entity_type, $entity); } }