/**
  * Call-back function for sorting transitions by their priority. Lower sort index => lower priority. 
  * @param WorkflowTransition $a
  * @param WorkflowTransition $b
  */
 private static function sortTransitions(WorkflowTransition $a, WorkflowTransition $b)
 {
     if ($a->getSortIndex() == $b->getSortIndex()) {
         return 0;
     }
     return $a->getSortIndex() < $b->getSortIndex() ? -1 : 1;
 }
 /**
  * Utility method, used in tests
  * @return \WorkflowDefinition
  */
 protected function createDefinition()
 {
     $definition = new WorkflowDefinition();
     $definition->Title = "Dummy Workflow Definition";
     $definition->write();
     $stepOne = new WorkflowAction();
     $stepOne->Title = "Step One";
     $stepOne->WorkflowDefID = $definition->ID;
     $stepOne->write();
     $stepTwo = new WorkflowAction();
     $stepTwo->Title = "Step Two";
     $stepTwo->WorkflowDefID = $definition->ID;
     $stepTwo->write();
     $transitionOne = new WorkflowTransition();
     $transitionOne->Title = 'Step One T1';
     $transitionOne->ActionID = $stepOne->ID;
     $transitionOne->NextActionID = $stepTwo->ID;
     $transitionOne->write();
     return $definition;
 }
 public function handleItem()
 {
     $id = $this->request->param('ID');
     $trans = WorkflowTransition::get()->byID($id);
     if (!$trans || $trans->Action()->WorkflowDefID != $this->RootField()->Definition()->ID) {
         $this->httpError(404);
     }
     if (!$trans->canEdit()) {
         $this->httpError(403);
     }
     return new WorkflowFieldItemController($this, "item/{$id}", $trans);
 }
 public function allowed(Internship $i)
 {
     if ($i->isDistanceEd()) {
         if (Current_User::allow('intern', 'distance_ed_register')) {
             return true;
         } else {
             return false;
         }
     } else {
         return parent::allowed($i);
     }
     return false;
 }
 public static function deleteMultiple(array $conditions, $table = 'dummy')
 {
     // The $table argument is to adhere to the parent::deleteMultiple interface. It must not be changeable.
     return parent::deleteMultiple($conditions, $table = 'workflow_scheduled_transition');
 }
 /**
  * Deactivate a Workflow State, moving existing nodes to a given State.
  *
  * @param int $new_sid
  *   The state ID, to which all affected entities must be moved.
  *
  * D7.x-2.x: deprecated workflow_delete_workflow_states_by_sid() --> WorkflowState->deactivate() + delete()
  */
 public function deactivate($new_sid)
 {
     global $user;
     // We can use global, since deactivate() is a UI-only function.
     $current_sid = $this->sid;
     $force = TRUE;
     // Notify interested modules. We notify first to allow access to data before we zap it.
     // E.g., Node API (@todo Field API):
     // - re-parents any nodes that we don't want to orphan, whilst deactivating a State.
     // - delete any lingering node to state values.
     module_invoke_all('workflow', 'state delete', $current_sid, $new_sid, NULL, $force);
     // Re-parent any nodes that we don't want to orphan, whilst deactivating a State.
     // This is called in WorkflowState::deactivate().
     // @todo: re-parent Workflow Field, whilst deactivating a state.
     if ($new_sid) {
         // A candidate for the batch API.
         // @TODO: Future updates should seriously consider setting this with batch.
         $comment = t('Previous state deleted');
         foreach (workflow_get_workflow_node_by_sid($current_sid) as $workflow_node) {
             // @todo: add Field support in 'state delete', by using workflow_node_history or reading current field.
             $entity_type = 'node';
             $entity = entity_load_single('node', $workflow_node->nid);
             $field_name = '';
             $transition = new WorkflowTransition();
             $transition->setValues($entity_type, $entity, $field_name, $current_sid, $new_sid, $user->uid, REQUEST_TIME, $comment);
             $transition->force($force);
             // Execute Transition, invoke 'pre' and 'post' events, save new state in workflow_node, save also in workflow_node_history.
             // For Workflow Node, only {workflow_node} and {workflow_node_history} are updated. For Field, also the Entity itself.
             $new_sid = workflow_execute_transition($entity_type, $entity, $field_name, $transition, $force);
         }
     }
     // Delete any lingering node to state values.
     workflow_delete_workflow_node_by_sid($current_sid);
     // Delete the transitions this state is involved in.
     $workflow = workflow_load_single($this->wid);
     /* @var $transition WorkflowTransition */
     foreach ($workflow->getTransitionsBySid($current_sid, 'ALL') as $transition) {
         $transition->delete();
     }
     foreach ($workflow->getTransitionsByTargetSid($current_sid, 'ALL') as $transition) {
         $transition->delete();
     }
     // Delete the state. -- We don't actually delete, just deactivate.
     // This is a matter up for some debate, to delete or not to delete, since this
     // causes name conflicts for states. In the meantime, we just stick with what we know.
     // If you really want to delete the states, use workflow_cleanup module, or delete().
     $this->status = FALSE;
     $this->save();
     // Clear the cache.
     self::getStates(0, TRUE);
 }
示例#7
0
 /**
  * Implements hook_field_delete() -> FieldItemInterface::delete().
  */
 public function delete($items)
 {
     global $user;
     $entity_type = $this->entity_type;
     $entity = $this->entity;
     $entity_id = entity_id($entity_type, $entity);
     $field_name = $this->field['field_name'];
     // Delete the record in {workflow_node} - not for Workflow Field.
     // Use a one-liner for better code analysis when grepping on old code.
     !$field_name ? workflow_delete_workflow_node_by_nid($entity_id) : NULL;
     // Add a history record in {workflow_node_history}.
     // @see drupal.org/node/2165349, comment by Bastlynn:
     // The reason for this history log upon delete is because Workflow module
     // has historically been used to track node states and accountability in
     // business environments where accountability for changes over time is
     // *absolutely* required. Think banking and/or particularly strict
     // retention policies for legal reasons.
     //
     // However, a deleted nid may be re-used under certain circumstances:
     // e.g., working with InnoDB or after restart the DB server.
     // This may cause that old history is associated with a new node.
     $old_sid = _workflow_get_sid_by_items($items);
     $new_sid = (int) WORKFLOW_DELETION;
     $comment = t('Entity deleted.');
     $transition = new WorkflowTransition();
     $transition->setValues($entity_type, $entity, $field_name, $old_sid, $new_sid, $user->uid, REQUEST_TIME, $comment);
     $transition->save();
     // Delete all records for this node in {workflow_scheduled_transition}.
     foreach (WorkflowScheduledTransition::load($entity_type, $entity_id, $field_name) as $scheduled_transition) {
         $scheduled_transition->delete();
     }
 }
 /**
  * Extract WorkflowTransition or WorkflowScheduledTransition from the form.
  *
  * This merely extracts the transition from the form/widget. No validation.
  */
 public function getTransition($old_sid, array $items, $field_name, stdClass $user)
 {
     $entity_type = $this->entity_type;
     $entity = $this->entity;
     // $entity_id = entity_id($entity_type, $entity);
     $field_name = !empty($this->field) ? $this->field['field_name'] : '';
     if (isset($items[0]['transition'])) {
         // a complete transition was already passed on.
         $transition = $items[0]['transition'];
     } else {
         // Get the new Transition properties. First the new State ID.
         if (isset($items[0]['workflow']['workflow_sid'])) {
             // We have shown a workflow form.
             $new_sid = $items[0]['workflow']['workflow_sid'];
         } elseif (isset($items[0]['value'])) {
             // We have shown a core options widget (radios, select).
             $new_sid = $items[0]['value'];
         } else {
             // This may happen if only 1 option is left, and a formatter is shown.
             $state = workflow_state_load_single($old_sid);
             if (!$state->isCreationState()) {
                 $new_sid = $old_sid;
             } else {
                 // This only happens on workflows, when only one transition from
                 // '(creation)' to another state is allowed.
                 $workflow = $state->getWorkflow();
                 $new_sid = $workflow->getFirstSid($this->entity_type, $this->entity, $field_name, $user, FALSE);
             }
         }
         $comment = isset($items[0]['workflow']['workflow_comment']) ? $items[0]['workflow']['workflow_comment'] : '';
         // Remember, the workflow_scheduled element is not set on 'add' page.
         $scheduled = !empty($items[0]['workflow']['workflow_scheduled']);
         if (!$scheduled) {
             $transition = new WorkflowTransition();
             $transition->setValues($entity_type, $entity, $field_name, $old_sid, $new_sid, $user->uid, REQUEST_TIME, $comment);
         } else {
             // Schedule the time to change the state.
             // If Field Form is used, use plain values;
             // If Node Form is used, use fieldset 'workflow_scheduled_date_time'.
             $schedule = isset($items[0]['workflow']['workflow_scheduled_date_time']) ? $items[0]['workflow']['workflow_scheduled_date_time'] : $items[0]['workflow'];
             if (!isset($schedule['workflow_scheduled_hour'])) {
                 $schedule['workflow_scheduled_hour'] = '00:00';
             }
             $scheduled_date_time = $schedule['workflow_scheduled_date']['year'] . substr('0' . $schedule['workflow_scheduled_date']['month'], -2, 2) . substr('0' . $schedule['workflow_scheduled_date']['day'], -2, 2) . ' ' . $schedule['workflow_scheduled_hour'] . ' ' . $schedule['workflow_scheduled_timezone'];
             if ($stamp = strtotime($scheduled_date_time)) {
                 $transition = new WorkflowScheduledTransition();
                 $transition->setValues($entity_type, $entity, $field_name, $old_sid, $new_sid, $user->uid, $stamp, $comment);
             } else {
                 $transition = NULL;
             }
         }
     }
     return $transition;
 }
 /**
  * Save a scheduled transition. If the transition is executed, save in history.
  */
 public function save()
 {
     // If executed, save in history.
     if ($this->is_executed) {
         // Be careful, we are not a WorkflowScheduleTransition anymore!
         $this->entityType = 'WorkflowTransition';
         $this->setUp();
         return parent::save();
         // <--- exit !!
     }
     // Since we do not have an entity_id here, we cannot use entity_delete.
     // @todo: Add an 'entity id' to WorkflowScheduledTransition entity class.
     // $result = parent::save();
     // Avoid duplicate entries.
     $clone = clone $this;
     $clone->delete();
     // Save (insert or update) a record to the database based upon the schema.
     drupal_write_record('workflow_scheduled_transition', $this);
     // Create user message.
     if ($state = $this->getNewState()) {
         $entity_type = $this->entity_type;
         $entity = $this->getEntity();
         $message = '%entity_title scheduled for state change to %state_name on %scheduled_date';
         $args = array('@entity_type' => $entity_type, '%entity_title' => entity_label($entity_type, $entity), '%state_name' => entity_label('WorkflowState', $state), '%scheduled_date' => format_date($this->scheduled));
         $uri = entity_uri($entity_type, $entity);
         watchdog('workflow', $message, $args, WATCHDOG_NOTICE, l('view', $uri['path'] . '/workflow'));
         drupal_set_message(t($message, $args));
     }
 }
 /**
  * When deleting an action from a workflow definition, make sure that workflows currently paused on that action
  * are deleted
  * Also removes all outbound transitions
  */
 public function onAfterDelete()
 {
     parent::onAfterDelete();
     $wfActionInstances = WorkflowActionInstance::get()->leftJoin("WorkflowInstance", '"WorkflowInstance"."ID" = "WorkflowActionInstance"."WorkflowID"')->where(sprintf('"BaseActionID" = %d AND ("WorkflowStatus" IN (\'Active\',\'Paused\'))', $this->ID));
     foreach ($wfActionInstances as $wfActionInstance) {
         $wfInstances = WorkflowInstance::get()->filter('CurrentActionID', $wfActionInstance->ID);
         foreach ($wfInstances as $wfInstance) {
             $wfInstance->Groups()->removeAll();
             $wfInstance->Users()->removeAll();
             $wfInstance->delete();
         }
         $wfActionInstance->delete();
     }
     // Delete outbound transitions
     $transitions = WorkflowTransition::get()->filter('ActionID', $this->ID);
     foreach ($transitions as $transition) {
         $transition->Groups()->removeAll();
         $transition->Users()->removeAll();
         $transition->delete();
     }
 }
 /**
  * Update the transitions for a given action
  * 
  * @param array $actionTemplate
  * @param WorkflowAction $action
  * 
  * @return array
  */
 protected function updateActionTransitions($actionTemplate, $action)
 {
     $transitions = array();
     if (isset($actionTemplate['transitions']) && is_array($actionTemplate['transitions'])) {
         $existing = $action->Transitions();
         $transitionMap = array();
         foreach ($existing as $transition) {
             $transitionMap[$transition->Title] = $transition;
         }
         foreach ($actionTemplate['transitions'] as $transitionName => $transitionTemplate) {
             $target = $transitionTemplate;
             if (is_array($transitionTemplate)) {
                 $target = $transitionTemplate['to'];
             }
             if (isset($transitionMap[$transitionName])) {
                 $transition = $transitionMap[$transitionName];
             } else {
                 $transition = WorkflowTransition::create();
             }
             $transition->Title = $transitionName;
             $transition->ActionID = $action->ID;
             // we don't have the NextAction yet other than the target name, so we store that against
             // the transition and do a second pass later on to match things up
             $transition->Target = $target;
             $transitions[] = $transition;
         }
     }
     return $transitions;
 }