コード例 #1
0
 /**
  * Call-back function for sorting states by their priority. Lower sort index => lower priority.
  * @param WorkflowState $a
  * @param WorkflowState $b
  */
 private static function sortStates(WorkflowState $a, WorkflowState $b)
 {
     if ($a->getSortIndex() == $b->getSortIndex()) {
         return 0;
     }
     return $a->getSortIndex() < $b->getSortIndex() ? -1 : 1;
 }
コード例 #2
0
 /**
  * NB: All of the params are optional for compatibility with db->getObjects() .. Database is done wrong. Don't have time to fix it.
  * @param Internship $i
  * @param PHPWS_User $phpwsUser
  * @param int $timestamp
  * @param WorkflowState $fromState
  * @param WorkflowState $toState
  */
 public function __construct(Internship $i = null, PHPWS_User $phpwsUser = null, $timestamp = null, WorkflowState $fromState = null, WorkflowState $toState = null, $note = null)
 {
     if (!is_null($i)) {
         $this->id = 0;
         $this->internship_id = $i->getId();
         $this->username = $phpwsUser->getUsername();
         $this->timestamp = $timestamp;
         $this->from_state = $fromState->getName();
         $this->to_state = $toState->getName();
         $this->note = $note;
     }
 }
コード例 #3
0
 /**
  * NB: All of the params are optional for compatibility with db->getObjects() .. Database is done wrong. Don't have time to fix it.
  * @param Internship $i
  * @param PHPWS_User $phpwsUser
  * @param int $timestamp
  * @param WorkflowState $fromState
  * @param WorkflowState $toState
  */
 public function __construct(Internship $i = null, \PHPWS_User $phpwsUser = null, $timestamp = null, WorkflowState $fromState = null, WorkflowState $toState = null, $note = null)
 {
     if (!is_null($i)) {
         $this->id = 0;
         $this->internship_id = $i->getId();
         $this->username = $phpwsUser->getUsername();
         $this->timestamp = $timestamp;
         // Strip namespace from start of from and to states, all four backspaces are required to escaping backslash
         $this->from_state = preg_replace("/Intern\\\\WorkflowState\\\\/", '', $fromState->getName());
         $this->to_state = preg_replace("/Intern\\\\WorkflowState\\\\/", '', $toState->getName());
         $this->note = $note;
     }
 }
コード例 #4
0
 public static function getTransitionsFromState(WorkflowState $state, Internship $i)
 {
     $stateName = $state->getName();
     $transitions = self::getAllTransitions();
     $outgoingTrans = array();
     foreach ($transitions as $t) {
         // Set the actual source state
         $t->setSourceState($state);
         if (is_array($t->getSourceState()) && in_array($stateName, $t->getSourceState()) && $t->isApplicable($i)) {
             $outgoingTrans[] = $t;
         } else {
             if (($t->getSourceState() == $stateName || $t->getSourceState() == '*') && $t->isApplicable($i)) {
                 $outgoingTrans[] = $t;
             }
         }
     }
     uasort($outgoingTrans, array('self', 'sortTransitions'));
     return $outgoingTrans;
 }
コード例 #5
0
 /**
  * Save a scheduled transition. If the transition is executed, save as logged transition.
  */
 public function save()
 {
     // If executed, save as logged transition.
     if ($this->is_executed) {
         return parent::save();
     }
     // Avoid duplicate entries.
     $this->delete();
     // Save (insert or update) a record to the database based upon the schema.
     drupal_write_record('workflow_scheduled_transition', $this);
     // Get name of state.
     if ($state = WorkflowState::load($this->new_sid)) {
         $message = '@entity_title scheduled for state change to %state_name on %scheduled_date';
         $args = array('@entity_type' => $this->entity_type, '@entity_title' => $this->entity->title, '%state_name' => $state->label(), '%scheduled_date' => format_date($this->scheduled));
         $uri = entity_uri($this->entity_type, $this->entity);
         watchdog('workflow', $message, $args, WATCHDOG_NOTICE, l('view', $uri['path'] . '/workflow'));
         drupal_set_message(t($message, $args));
     }
 }
コード例 #6
0
 /**
  * Implements hook_field_widget_form --> WidgetInterface::formElement().
  *
  * {@inheritdoc}
  *
  * Be careful: this widget may be shown in very different places. Test carefully!!
  *  - On a entity add/edit page
  *  - On a entity preview page
  *  - On a entity view page
  *  - On a entity 'workflow history' tab
  *  - On a comment display, in the comment history
  *  - On a comment form, below the comment history
  * @todo D8: change "array $items" to "FieldInterface $items"
  */
 public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state)
 {
     $field_name = $this->field['field_name'];
     $field = $this->instance;
     $instance = $this->instance;
     $entity = $this->entity;
     $entity_type = $this->entity_type;
     $entity_id = entity_id($entity_type, $entity);
     if (!$entity) {
         // If no entity given, do not show a form. E.g., on the field settings page.
         return $element;
     }
     // Capture settings to format the form/widget.
     $settings_title_as_name = !empty($this->field['settings']['widget']['name_as_title']);
     // The schedule cannot be shown on a Content add page.
     $settings_schedule = !empty($this->field['settings']['widget']['schedule']) && $entity_id;
     $settings_schedule_timezone = !empty($this->field['settings']['widget']['schedule_timezone']);
     // Show comment, when both Field and Instance allow this.
     $settings_comment = $this->field['settings']['widget']['comment'] ? 'textarea' : 'hidden';
     $workflow = Workflow::load($this->field['settings']['wid']);
     $current_sid = workflow_node_current_state($entity, $entity_type, $field_name);
     $current_state = WorkflowState::load($current_sid);
     $options = array();
     $options = $current_state->getOptions($entity_type, $entity);
     // Determine the default value. If we are in CreationState, use a fast alternative for $workflow->getFirstSid().
     $default_value = $current_state->isCreationState() ? key($options) : $current_sid;
     // Get the scheduling info. This may change the $current_sid on the Form.
     $scheduled = '0';
     $timestamp = REQUEST_TIME;
     $comment = NULL;
     if ($settings_schedule) {
         // Read scheduled information.
         // Technically you could have more than one scheduled, but this will only add the soonest one.
         foreach (WorkflowScheduledTransition::load($entity_type, $entity_id, $field_name) as $scheduled_transition) {
             $scheduled = '1';
             $current_sid = $scheduled_transition->sid;
             $timestamp = $scheduled_transition->scheduled;
             $comment = $scheduled_transition->comment;
             break;
         }
     }
     // Fetch the form ID. This is unique for each entity, to allow multiple form per page (Views, etc.).
     $form_id = $form_state['build_info']['form_id'];
     $element_scheduled_name = 'workflow_scheduled_' . $form_id;
     $element_options_name = 'workflow_options_' . $form_id;
     $element_scheduled_name = 'workflow_scheduled';
     $element_options_name = 'workflow_options';
     $elt_state_name = 'workflow_scheduled_' . $form_id;
     $label = $workflow->label();
     // Prepare a wrapper. This might be a fieldset.
     $element['workflow']['#type'] = 'container';
     $element['workflow']['#attributes'] = array('class' => array('workflow-form-container'));
     // Save the current value of the node in the form, for later Workflow-module specific references.
     // We add prefix, since #tree == FALSE.
     $element['workflow']['workflow_entity'] = array('#type' => 'value', '#value' => $this->entity);
     $element['workflow']['workflow_entity_type'] = array('#type' => 'value', '#value' => $this->entity_type);
     $element['workflow']['workflow_field'] = array('#type' => 'value', '#value' => $this->field);
     $element['workflow']['workflow_instance'] = array('#type' => 'value', '#value' => $this->instance);
     // Save the form_id, so the form values can be retrieved in submit function.
     $element['workflow']['form_id'] = array('#type' => 'value', '#value' => $form_id);
     // First of all, we add the default value in the place were normal fields
     // have it. This is to cater for 'preview' of the entity.
     $element['#default_value'] = $default_value;
     // Decide if we show a widget or a formatter.
     // There is no need to a widget when the only choice is the current sid.
     if (!$current_state->showWidget($options)) {
         $element['workflow'][$element_options_name] = workflow_state_formatter($entity_type, $entity, $field, $instance);
         return $element;
     } else {
         $element['workflow'][$element_options_name] = array('#type' => $this->field['settings']['widget']['options'], '#title' => $settings_title_as_name ? t('Change !name state', array('!name' => $label)) : '', '#options' => $options, '#default_value' => $default_value);
     }
     // Display scheduling form, but only if entity is being edited and user has
     // permission. State change cannot be scheduled at entity creation because
     // that leaves the entity in the (creation) state.
     if ($settings_schedule == TRUE && user_access('schedule workflow transitions')) {
         global $user;
         if (variable_get('configurable_timezones', 1) && $user->uid && drupal_strlen($user->timezone)) {
             $timezone = $user->timezone;
         } else {
             $timezone = variable_get('date_default_timezone', 0);
         }
         $timezones = drupal_map_assoc(timezone_identifiers_list());
         $hours = format_date($timestamp, 'custom', 'H:i', $timezone);
         //      $element['workflow']['workflow_scheduled'] = array(
         $element['workflow'][$element_scheduled_name] = array('#type' => 'radios', '#title' => t('Schedule'), '#options' => array('0' => t('Immediately'), '1' => t('Schedule for state change')), '#default_value' => $scheduled, '#attributes' => array('id' => 'scheduled_' . $form_id));
         $element['workflow']['workflow_scheduled_date_time'] = array('#type' => 'fieldset', '#title' => t('At'), '#attributes' => array('class' => array('container-inline')), '#prefix' => '<div style="margin-left: 1em;">', '#suffix' => '</div>', '#states' => array('visible' => array(':input[id="' . 'scheduled_' . $form_id . '"]' => array('value' => '1'))));
         $element['workflow']['workflow_scheduled_date_time']['workflow_scheduled_date'] = array('#type' => 'date', '#default_value' => array('day' => date('j', $timestamp), 'month' => date('n', $timestamp), 'year' => date('Y', $timestamp)));
         $element['workflow']['workflow_scheduled_date_time']['workflow_scheduled_hour'] = array('#type' => 'textfield', '#title' => t('Time'), '#maxlength' => 5, '#size' => 6, '#default_value' => $scheduled ? $hours : '00:00');
         $element['workflow']['workflow_scheduled_date_time']['workflow_scheduled_timezone'] = array('#type' => $settings_schedule_timezone ? 'select' : 'hidden', '#title' => t('Time zone'), '#options' => $timezones, '#default_value' => array($timezone => $timezone));
         $element['workflow']['workflow_scheduled_date_time']['workflow_scheduled_help'] = array('#type' => 'item', '#prefix' => '<br />', '#description' => t('Please enter a time in 24 hour (eg. HH:MM) format.
       If no time is included, the default will be midnight on the specified date.
       The current time is: @time.', array('@time' => format_date(REQUEST_TIME, 'custom', 'H:i', $timezone))));
     }
     $element['workflow']['workflow_comment'] = array('#type' => $settings_comment, '#title' => t('Workflow comment'), '#description' => t('A comment to put in the workflow log.'), '#default_value' => $comment, '#rows' => 2);
     // The 'add submit' can explicitely set by workflowfield_field_formatter_view(),
     // to add the submit button on the Content view page and the Workflow history tab.
     if (!empty($this->instance['widget']['settings']['submit_function'])) {
         // Add a submit button, but only on Entity View and History page.
         $element['workflow']['submit'] = array('#type' => 'submit', '#value' => t('Update workflow'), '#executes_submit_callback' => TRUE, '#submit' => array($this->instance['widget']['settings']['submit_function']));
     }
     return $element;
 }
コード例 #7
0
 /**
  * Get all states in the system, with options to filter, only where a workflow exists.
  *
  * @param $wid
  *   The requested Workflow ID.
  * @param bool $reset
  *   An option to refresh all caches.
  *
  * @return array $states
  *   An array of cached states.
  *
  * D7.x-2.x: deprecated workflow_get_workflow_states --> workflow_state_load_multiple
  * D7.x-2.x: deprecated workflow_get_workflow_states_all --> workflow_state_load_multiple
  * D7.x-2.x: deprecated workflow_get_other_states_by_sid --> workflow_state_load_multiple
  */
 public static function getStates($wid = 0, $reset = FALSE)
 {
     if ($reset) {
         self::$states = array();
     }
     if (empty(self::$states)) {
         // Build the query, and get ALL states.
         // Note: self::states[] is populated in respective constructors.
         $query = db_select('workflow_states', 'ws');
         $query->fields('ws');
         $query->orderBy('ws.weight');
         $query->orderBy('ws.wid');
         // Just for grins, add a tag that might result in modifications.
         $query->addTag('workflow_states');
         // @see #2285983 for using SQLite.
         // $query->execute()->fetchAll(PDO::FETCH_CLASS, 'WorkflowState');
         /* @var $tmp DatabaseStatementBase */
         $statement = $query->execute();
         $statement->setFetchMode(PDO::FETCH_CLASS, 'WorkflowState');
         foreach ($statement->fetchAll() as $state) {
             self::$states[$state->sid] = $state;
         }
     }
     if (!$wid) {
         // All states are requested and cached: return them.
         return self::$states;
     } else {
         // All states of only 1 Workflow is requested: return this one.
         $result = array();
         foreach (self::$states as $state) {
             if ($state->wid == $wid) {
                 $result[$state->sid] = $state;
             }
         }
         return $result;
     }
 }
コード例 #8
0
 protected function _allowed_values_string($wid = 0)
 {
     $lines = array();
     $states = WorkflowState::getStates($wid);
     $previous_wid = -1;
     foreach ($states as $state) {
         // Only show enabled states.
         if ($state->status) {
             // Show a Workflow name between Workflows, if more then 1 in the list.
             if ($wid == 0 && $previous_wid != $state->wid) {
                 $previous_wid = $state->wid;
                 $lines[] = $state->name . "'s states: ";
             }
             $label = t($state->label());
             $states[$state->sid] = check_plain($label);
             $lines[] = $state->sid . ' | ' . check_plain($label);
         }
     }
     return implode("\n", $lines);
 }
コード例 #9
0
 public function testUndefinedAction()
 {
     $this->assertTrue($this->state->getAction('undefined') === null);
 }
コード例 #10
0
ファイル: Workflow.php プロジェクト: jeddobson/LacunaStories
 /**
  * Gets all states for a given workflow.
  *
  * @param mixed $all
  *   Indicates to which states to return.
  *   - TRUE = all, including Creation and Inactive;
  *   - FALSE = only Active states, not Creation;
  *   - 'CREATION' = only Active states, including Creation.
  *
  * @return array
  *   An array of WorkflowState objects.
  */
 public function getStates($all = FALSE, $reset = FALSE)
 {
     if ($this->states === NULL || $reset) {
         $this->states = $this->wid ? WorkflowState::getStates($this->wid, $reset) : array();
     }
     // Do not unset, but add to array - you'll remove global objects otherwise.
     $states = array();
     foreach ($this->states as $state) {
         if ($all === TRUE) {
             $states[$state->sid] = $state;
         } elseif ($all === FALSE && ($state->isActive() && !$state->isCreationState())) {
             $states[$state->sid] = $state;
         } elseif ($all == 'CREATION' && ($state->isActive() || $state->isCreationState())) {
             $states[$state->sid] = $state;
         }
     }
     return $states;
 }
コード例 #11
0
 /**
  * Deactivate a Workflow State, moving existing nodes to a given State.
  *
  * @param $new_sid
  *  the state ID, to which all affected entities must be moved. 
  *
  * @deprecated workflow_delete_workflow_states_by_sid() --> WorkflowState->deactivate() + delete()
  */
 public function deactivate($new_sid)
 {
     $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: reparent Workflow Field, whilst deactivating a state.
     if ($new_sid) {
         global $user;
         // 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($entity_type, $entity, $field_name, $current_sid, $new_sid, $user->uid, REQUEST_TIME, $comment);
             $transition->force($force);
             // Excute 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);
     // Find out which transitions this state is involved in.
     $preexisting = array();
     foreach (workflow_get_workflow_transitions_by_sid_involved($current_sid) as $data) {
         $preexisting[$data->sid][$data->target_sid] = TRUE;
     }
     // Delete the transitions.
     foreach ($preexisting as $from => $array) {
         foreach (array_keys($array) as $target_id) {
             if ($transition = workflow_get_workflow_transitions_by_sid_target_sid($from, $target_id)) {
                 workflow_delete_workflow_transitions_by_tid($transition->tid);
             }
         }
     }
     // 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::$states = array();
 }
コード例 #12
0
 /**
  * Sets the WorkflowState of this internship.
  *
  * @param WorkflowState $state
  */
 public function setState(WorkflowState $state)
 {
     $this->state = $state->getName();
 }
コード例 #13
0
 /**
  * Gets a state for a given workflow.
  *
  * @param $sid
  *   A state ID.
  *
  * @return
  *   A WorkflowState object.
  */
 public function getState($sid)
 {
     return WorkflowState::load($sid, $this->wid);
 }
コード例 #14
0
ファイル: Workflow.php プロジェクト: dpaduch/Workflow
 /**
  * Adds new workflow state.
  *
  * @param WorkflowState $state State object to add
  *
  * @return \DevelArts\Workflow\Workflow
  */
 public function addState(WorkflowState $state)
 {
     $this->states[$state->getName()] = $state;
     return $this;
 }
コード例 #15
0
 /**
  * Execute a transition (change state of a node).
  * @deprecated: workflow_execute_transition() --> WorkflowTransition::execute().
  *
  * @param bool $force
  *   If set to TRUE, workflow permissions will be ignored.
  *
  * @return int
  *  new state ID. If execution failed, old state ID is returned,
  */
 public function execute($force = FALSE)
 {
     global $user;
     $old_sid = $this->old_sid;
     $new_sid = $this->new_sid;
     $entity_type = $this->entity_type;
     $entity_id = $this->entity_id;
     $entity = $this->getEntity();
     // Entity may not be loaded, yet.
     $field_name = $this->field_name;
     if ($old_sid == $new_sid) {
         // Stop if not going to a different state.
         // Write comment into history though.
         if ($this->comment) {
             $this->stamp = REQUEST_TIME;
             if (!$field_name) {
                 // @todo D8: remove; this is only for Node API.
                 $entity->workflow_stamp = REQUEST_TIME;
                 workflow_update_workflow_node_stamp($entity_id, $this->stamp);
             }
             $result = module_invoke_all('workflow', 'transition pre', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
             $this->save();
             if (!$field_name) {
                 // @todo D8: remove; this is only for Node API.
                 unset($entity->workflow_comment);
                 // @todo D8: remove; this line is only for Node API.
             }
             $result = module_invoke_all('workflow', 'transition post', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
         }
         // Clear any references in the scheduled listing.
         foreach (WorkflowScheduledTransition::load($entity_type, $entity_id, $field_name) as $scheduled_transition) {
             $scheduled_transition->delete();
         }
         return $new_sid;
     }
     if (!$force) {
         // Make sure this transition is allowed.
         $result = module_invoke_all('workflow', 'transition permitted', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
         // Did anybody veto this choice?
         if (in_array(FALSE, $result)) {
             // If vetoed, quit.
             return $old_sid;
         }
     }
     // Let other modules modify the comment.
     // @todo D8: remove all but last items from $context.
     $context = array('node' => $entity, 'sid' => $new_sid, 'old_sid' => $old_sid, 'uid' => $this->uid, 'transition' => $this);
     drupal_alter('workflow_comment', $this->comment, $context);
     $args = array('%user' => $user->name, '%old' => $old_sid, '%new' => $new_sid);
     $transition = workflow_get_workflow_transitions_by_sid_target_sid($old_sid, $new_sid);
     if (!$transition && !$force) {
         watchdog('workflow', 'Attempt to go to nonexistent transition (from %old to %new)', $args, WATCHDOG_ERROR);
         return $old_sid;
     }
     // Make sure this transition is valid and allowed for the current user.
     // Check allow-ability of state change if user is not superuser (might be cron).
     if ($user->uid != 1 && !$force) {
         if (!workflow_transition_allowed($transition->tid, array_merge(array_keys($user->roles), array('author')))) {
             watchdog('workflow', 'User %user not allowed to go from state %old to %new', $args, WATCHDOG_NOTICE);
             return $old_sid;
         }
     }
     // Invoke a callback indicating a transition is about to occur.
     // Modules may veto the transition by returning FALSE.
     $result = module_invoke_all('workflow', 'transition pre', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
     // Stop if a module says so.
     if (in_array(FALSE, $result)) {
         watchdog('workflow', 'Transition vetoed by module.');
         return $old_sid;
     }
     // Log the new state in {workflow_node_history}.
     // This is only valid for Node API.
     if (!$field_name) {
         // If the node does not have an existing 'workflow' property, save the $old_sid there, so it can be logged.
         if (!isset($entity->workflow)) {
             $entity->workflow = $old_sid;
         }
         // Change the state for {workflow_node}.
         // The equivalent for Field API is in WorkflowDefaultWidget::submit.
         $data = array('nid' => $entity_id, 'sid' => $new_sid, 'uid' => isset($entity->workflow_uid) ? $entity->workflow_uid : $user->uid, 'stamp' => REQUEST_TIME);
         workflow_update_workflow_node($data);
         $entity->workflow = $new_sid;
     }
     // Log the transition in {workflow_node_history}.
     $this->is_executed = TRUE;
     $this->save();
     // Register state change with watchdog.
     if ($state = WorkflowState::load($new_sid)) {
         $workflow = $state->getWorkflow();
         if (!empty($workflow->options['watchdog_log'])) {
             $entity_type_info = entity_get_info($entity_type);
             $message = $this->isScheduled() ? 'Scheduled state change of @type %label to %state_name executed' : 'State of @type %label set to %state_name';
             $args = array('@type' => $entity_type_info['label'], '%label' => entity_label($entity_type, $entity), '%state_name' => $state->label());
             $uri = entity_uri($entity_type, $entity);
             watchdog('workflow', $message, $args, WATCHDOG_NOTICE, l('view', $uri['path']));
         }
     }
     // Notify modules that transition has occurred.
     // Action triggers should take place in response to this callback, not the previous one.
     module_invoke_all('workflow', 'transition post', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
     // Clear any references in the scheduled listing.
     foreach (WorkflowScheduledTransition::load($entity_type, $entity_id, $field_name) as $scheduled_transition) {
         $scheduled_transition->delete();
     }
     return $new_sid;
 }