/** * Helper function for __construct. Used for all children of WorkflowTransition (aka WorkflowScheduledTransition) * * @param $entity_type * @param $entity * @param $field_name * @param $old_sid * @param $new_sid * @param null $uid * @param int $stamp * @param string $comment */ public function setValues($entity_type, $entity, $field_name, $old_sid, $new_sid, $uid = NULL, $stamp = REQUEST_TIME, $comment = '') { // Normally, the values are passed in an array, and set in parent::__construct, but we do it ourselves. // (But there is no objection to do it there.) global $user; $this->entity_type = !$entity_type ? $this->entity_type : $entity_type; $this->field_name = !$field_name ? $this->field_name : $field_name; $uid = $uid === NULL ? $user->uid : $uid; // If constructor is called with new() and arguments. // Load the supplied entity. if ($entity && !$entity_type) { // Not all parameters are passed programmatically. drupal_set_message(t('Wrong call to new Workflow*Transition()'), 'error'); } elseif ($entity) { $this->setEntity($entity_type, $entity); } if (!$entity && !$old_sid && !$new_sid) { // If constructor is called without arguments, e.g., loading from db. } elseif ($entity && $old_sid) { // Caveat: upon entity_delete, $new_sid is '0'. // If constructor is called with new() and arguments. $this->old_sid = $old_sid; $this->sid = $new_sid; $this->uid = $uid; $this->stamp = $stamp; $this->comment = $comment; // Set language. Multi-language is not supported for Workflow Node. $this->language = _workflow_metadata_workflow_get_properties($entity, array(), 'langcode', $entity_type, $field_name); } elseif (!$old_sid) { // Not all parameters are passed programmatically. drupal_set_message(t('Wrong call to constructor Workflow*Transition(@old_sid to @new_sid)', array('@old_sid' => $old_sid, '@new_sid' => $new_sid)), 'error'); } // Fill the 'new' fields correctly. @todo D8: rename these fields in db table. $this->entity_id = $this->nid; $this->new_sid = $this->sid; // Initialize wid, if not set. if ($this->old_sid && !$this->wid) { $this->getWorkflow(); } }
/** * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state, array &$items) { // $items is a D7 parameter. // @todo: clean this code up. It is the result of gluing code together. global $user; // @todo #2287057: verify if submit() really is only used for UI. If not, $user must be passed. $entity = $this->entity; $entity_type = $this->entity_type; $field = $this->field; $field_name = $field['field_name']; // Retrieve the data from the form. if (isset($form_state['values']['workflow_field'])) { // If $entity filled: We are on a Entity View page or Workflow History Tab page. // If $entity empty: We are on an Advanced Action page. // $field = $form_state['values']['workflow_field']; // $instance = $form_state['values']['workflow_instance']; // $entity_type = $form_state['values']['workflow_entity_type']; // $entity = $form_state['values']['workflow_entity']; // $field_name = $field['field_name']; } elseif (isset($form_state['triggering_element'])) { // We are on an Entity/Node/Comment Form page (add/edit). $field_name = $form_state['triggering_element']['#workflow_field_name']; } else { // We are on an Entity/Comment Form page (add/edit). } // Determine if the transition is forced. // This can be set by a 'workflow_vbo action' in an additional form element. $force = isset($form_state['input']['workflow_force']) ? $form_state['input']['workflow_force'] : FALSE; // Set language. Multi-language is not supported for Workflow Node. $langcode = _workflow_metadata_workflow_get_properties($entity, array(), 'langcode', $entity_type, $field_name); if (!$entity) { // E.g., on VBO form. } elseif ($field_name) { // Save the entity, but only if we were not in edit mode. // Perhaps there is a better way, but for now we use 'changed' property. // Also test for 'is_new'. When Migrating content, the 'changed' property may be set externally. // Caveat: Some entities do not have 'changed' property set. if (!empty($entity->is_new) || isset($entity->changed) && $entity->changed == REQUEST_TIME) { // We are in add/edit mode. No need to save the entity explicitly. // // Add the $form_state to the $items, so we can do a getTransition() later on. // $items[0]['workflow'] = $form_state['input']; // // Create a Transition. The Widget knows if it is scheduled. // $widget = new WorkflowDefaultWidget($field, $instance, $entity_type, $entity); // $new_sid = $widget->submit($form, $form_state, $items, $force); } elseif (isset($form_state['input'])) { // Save $entity, but only if sid has changed. // Use field_attach_update for this? Save always? $entity->{$field_name}[$langcode][0]['workflow'] = $form_state['input']; // @todo & totest: Save ony the field, not the complete entity. // workflow_entity_field_save($entity_type, $entity, $field_name, $langcode, FALSE); entity_save($entity_type, $entity); return; // <---- exit! } else { // We are saving a node from a comment. $entity->{$field_name}[$langcode] = $items; // @todo & totest: Save ony the field, not the complete entity. // workflow_entity_field_save($entity_type, $entity, $field_name, $langcode, FALSE); entity_save($entity_type, $entity); return; // <---- exit! } } else { // For a Node API form, only contrib fields need to be filled. // No updating of the node itself. // (Unless we need to record the timestamp.) // Add the $form_state to the $items, so we can do a getTransition() later on. $items[0]['workflow'] = $form_state['input']; // // Create a Transition. The Widget knows if it is scheduled. // $widget = new WorkflowDefaultWidget($field, $instance, $entity_type, $entity); // $new_sid = $widget->submit($form, $form_state, $items, $force); } // Extract the data from $items, depending on the type of widget. // @todo D8: use MassageFormValues($values, $form, $form_state). $old_sid = workflow_node_previous_state($entity, $entity_type, $field_name); if (!$old_sid) { // At this moment, $old_sid should have a value. If the content does not // have a state yet, old_sid contains '(creation)' state. But if the // content is not associated to a workflow, old_sid is now 0. This may // happen in workflow_vbo, if you assign a state to non-relevant nodes. $entity_id = entity_id($entity_type, $entity); drupal_set_message(t('Error: content !id has no workflow attached. The data is not saved.', array('!id' => $entity_id)), 'error'); // The new state is still the previous state. $new_sid = $old_sid; return $new_sid; } // Now, save/execute the transition. $transition = $this->getTransition($old_sid, $items, $field_name, $user, $form, $form_state); // Try to execute the transition. Return $old_sid when error. if (!$transition) { // This should only happen when testing/developing. drupal_set_message(t('Error: the transition from %old_sid to %new_sid could not be generated.'), 'error'); // The current value is still the previous state. $new_sid = $old_sid; } elseif ($transition->isScheduled() || $transition->isExecuted()) { // A scheduled or executed transition must only be saved to the database. // The entity is not changed. $force = $force || $transition->isForced(); $transition->save(); // The current value is still the previous state. $new_sid = $old_sid; } elseif (!$transition->isScheduled()) { // Now the data is captured in the Transition, and before calling the // Execution, restore the default values for Workflow Field. // For instance, workflow_rules evaluates this. if ($field_name) { // $items = array(); // $items[0]['value'] = $old_sid; // $entity->{$field_name}[$transition->language] = $items; } // It's an immediate change. Do the transition. // - validate option; add hook to let other modules change comment. // - add to history; add to watchdog // Return the new State ID. (Execution may fail and return the old Sid.) $force = $force || $transition->isForced(); $new_sid = $transition->execute($force); } // The entity is still to be saved, so set to a 'normal' value. if ($field_name) { $items = array(); $items[0]['value'] = $new_sid; $entity->{$field_name}[$transition->language] = $items; } return $new_sid; }