public function getWorkflow()
 {
     if (isset($this->workflow)) {
         return $this->workflow;
     }
     return workflow_load_single($this->wid);
 }
Esempio n. 2
0
 /**
  * Implements hook_field_update() -> FieldItemInterface::update().
  *
  * @todo: in course of time, this is not used anymore...
  * It is called also from hook_field_insert(), since we need $nid to store {workflow_node_history}.
  * We cannot use hook_field_presave(), since $nid is not yet known at that moment.
  *
  * "Contrary to the old D7 hooks, the methods do not receive the parent entity
  * "or the langcode of the field values as parameters. If needed, those can be accessed
  * "by the getEntity() and getLangcode() methods on the Field and FieldItem classes.
  */
 public function update(&$items)
 {
     // ($entity_type, $entity, $field, $instance, $langcode, &$items) {
     // @todo: apparently, in course of time, this is not used anymore. Restore or remove.
     $field_name = $this->field['field_name'];
     // $field['settings']['wid'] can be numeric or named.
     $workflow = workflow_load_single($this->field['settings']['wid']);
     $wid = $workflow->wid;
     // @todo D8: remove below lines.
     $entity = $this->entity;
     $entity_type = $this->entity_type;
     $entity_id = entity_id($entity_type, $entity);
     if (!$entity) {
         // No entity available, we are on the field Settings page - 'default value' field.
         // This is hidden from the admin, because the default value can be different for every user.
     } elseif (!$entity_id && $entity_type == 'comment') {
         // Not possible: a comment on a non-existent node.
     } elseif ($entity_id && $this->entity_type == 'comment') {
         // This happens when we are on an entity's comment.
         $referenced_entity_type = 'node';
         // Comments only exist on nodes.
         $referenced_entity = entity_load_single($referenced_entity_type, $entity_id);
         // Comments only exist on nodes.
         // Submit the data. $items is reset by reference to normal value, and is magically saved by the field itself.
         $form = array();
         $form_state = array();
         $widget = new WorkflowDefaultWidget($this->field, $this->instance, $referenced_entity_type, $referenced_entity);
         $widget->submit($form, $form_state, $items);
         // $items is a proprietary D7 parameter.
         // Remember: we are on a comment form, so the comment is saved automatically, but the referenced entity is not.
         // @todo: probably we'd like to do this form within the Widget, but
         // $todo: that does not know wether we are on a comment or a node form.
         //
         // Widget::submit() returns the new value in a 'sane' state.
         // Save the referenced entity, but only is transition succeeded, and is not scheduled.
         $old_sid = _workflow_get_sid_by_items($referenced_entity->{$field_name}[LANGUAGE_NONE]);
         $new_sid = _workflow_get_sid_by_items($items);
         if ($old_sid != $new_sid) {
             $referenced_entity->{$field_name}[LANGUAGE_NONE] = $items;
             entity_save($referenced_entity_type, $referenced_entity);
         }
     } elseif ($this->entity_type != 'comment') {
         if (isset($items[0]['value'])) {
             // A 'normal' options.module-widget is used, and $items[0]['value'] is already properly set.
         } elseif (isset($items[0]['workflow'])) {
             // The WorkflowDefaultWidget is used.
             // Submit the data. $items is reset by reference to normal value, and is magically saved by the field itself.
             $form = array();
             $form_state = array();
             $widget = new WorkflowDefaultWidget($this->field, $this->instance, $entity_type, $entity);
             $widget->submit($form, $form_state, $items);
             // $items is a proprietary D7 parameter.
         } else {
             drupal_set_message(t('error in WorkfowItem->update()'), 'error');
         }
     }
     // A 'normal' node add page.
     // We should not be here, since we only do inserts after $entity_id is known.
     // $current_sid = workflow_load_single($wid)->getCreationSid();
 }
 /**
  * Implements hook_field_widget_form --> WidgetInterface::formElement().
  *
  * {@inheritdoc}
  *
  * Be careful: 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, array &$form, array &$form_state)
 {
     global $user;
     // @todo #2287057: verify if formElement() really is only used for UI. If not, $user must be passed.
     $field = $this->field;
     $instance = $this->instance;
     $entity = $this->entity;
     $entity_type = $this->entity_type;
     $entity_id = $entity ? entity_id($entity_type, $entity) : 0;
     $field_name = $field['field_name'];
     $current_sid = FALSE;
     // $field['settings']['wid'] can be numeric or named.
     // $wid may not be specified.
     $wid = $field['settings']['wid'];
     $workflow = workflow_load_single($wid);
     $workflow_label = $workflow ? check_plain(t($workflow->label())) : '';
     // Capture settings to format the form/widget.
     $settings_title_as_name = !empty($field['settings']['widget']['name_as_title']);
     $settings_options_type = $field['settings']['widget']['options'];
     // The schedule can be hidden via field settings, ...
     $settings_schedule = !empty($field['settings']['widget']['schedule']);
     if ($settings_schedule) {
         if (isset($form_state['step']) && $form_state['step'] == 'views_bulk_operations_config_form') {
             // On VBO 'modify entity values' form, leave field settings.
             $settings_schedule = TRUE;
         } else {
             // ... and cannot be shown on a Content add page (no $entity_id),
             // ...but can be shown on a VBO 'set workflow state to..'page (no entity).
             $settings_schedule = !($entity && !$entity_id);
         }
     }
     $settings_schedule_timezone = !empty($field['settings']['widget']['schedule_timezone']);
     // Show comment, when both Field and Instance allow this.
     $settings_comment = $field['settings']['widget']['comment'];
     $options = array();
     if (!$entity) {
         // Sometimes, no entity is given. We encountered the following cases:
         // - the Field settings page,
         // - the VBO action form;
         // - the Advance Action form on admin/config/system/actions;
         // If so, show all options for the given workflow(s).
         // Set 'grouped' option. This is only valid for select list.
         $grouped = $settings_options_type == 'select';
         $options = workflow_get_workflow_state_names($wid, $grouped, $all = FALSE);
         $show_widget = TRUE;
         $default_value = isset($items[0]['value']) ? $items[0]['value'] : '0';
     } else {
         $force = FALSE;
         $current_sid = workflow_node_current_state($entity, $entity_type, $field_name);
         if ($current_state = workflow_state_load_single($current_sid)) {
             // $grouped = TRUE; // Grouped options only makes sense for multiple workflows.
             $options = $current_state->getOptions($entity_type, $entity, $field_name, $user, $force);
             $show_widget = $current_state->showWidget($entity_type, $entity, $field_name, $user, $force);
             // 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;
         } else {
             // We are in trouble! A message is already set in workflow_node_current_state().
             $show_widget = FALSE;
             $default_value = $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';
             $default_value = $scheduled_transition->new_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.).
     // Make it uniquer by adding the field name, or else the scheduling of
     // multiple workflow_fields is not indendent.
     $form_id = $form_state['build_info']['form_id'] . '_' . $field_name;
     // Prepare a UI wrapper. This might be a fieldset.
     $element['workflow']['#type'] = 'container';
     // 'fieldset';
     $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' => $field);
     $element['workflow']['workflow_instance'] = array('#type' => 'value', '#value' => $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 (!$show_widget) {
         $element['workflow']['workflow_sid'] = workflow_state_formatter($entity_type, $entity, $field, $instance, $default_value);
         return $element;
         // <---- exit.
     }
     // The 'options' widget. May be removed later if 'Action buttons' are chosen.
     $element['workflow']['workflow_sid'] = array('#type' => $settings_options_type, '#title' => $settings_title_as_name ? t('Change !name state', array('!name' => $workflow_label)) : t('Target state'), '#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')) {
         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('#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' => 7, '#size' => 6, '#default_value' => $scheduled ? $hours : '00:00', '#element_validate' => array('_workflow_transition_form_element_validate_time'));
         $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.
       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 == '0' ? 'hidden' : 'textarea', '#required' => $settings_comment == '2', '#title' => t('Workflow comment'), '#description' => t('A comment to put in the workflow log.'), '#default_value' => $comment, '#rows' => 2);
     // Finally, add Submit buttons/Action buttons.
     // Either a default 'Submit' button is added, or a button per permitted state.
     if ($settings_options_type == 'buttons') {
         // How do action buttons work? See also d.o. issue #2187151.
         // Create 'action buttons' per state option. Set $sid property on each button.
         // 1. Admin sets ['widget']['options']['#type'] = 'buttons'.
         // 2. This function formElelent() creates 'action buttons' per state option;
         //    sets $sid property on each button.
         // 3. User clicks button.
         // 4. Callback _workflow_transition_form_validate_buttons() sets proper State.
         // 5. Callback _workflow_transition_form_validate_buttons() sets Submit function.
         // @todo: this does not work yet for the Add Comment form.
         // Performance: inform workflow_form_alter() to do its job.
         _workflow_use_action_buttons(TRUE);
     }
     $submit_functions = empty($instance['widget']['settings']['submit_function']) ? array() : array($instance['widget']['settings']['submit_function']);
     if ($settings_options_type == 'buttons' || $submit_functions) {
         $element['workflow']['actions']['#type'] = 'actions';
         $element['workflow']['actions']['submit'] = array('#type' => 'submit', '#value' => t('Update workflow'), '#weight' => -5, '#attributes' => array('class' => array('form-save-default-button')));
         // 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.
         // Add a submit button, but only on Entity View and History page.
         // Add the submit function only if one provided. Set the submit_callback accordingly.
         if ($submit_functions) {
             $element['workflow']['actions']['submit']['#submit'] = $submit_functions;
         } else {
             // '#submit' Must be empty, or else the submit function is not called.
             // $element['workflow']['actions']['submit']['#submit'] = array();
         }
     } else {
         // In some cases, no submit callback function is specified. This is
         // explicitly done on e.g., the node edit form, because the workflow form
         // is 'just a field'.
         // So, no Submit button is to be shown.
     }
     return $element;
 }
 /**
  * {@inheritdoc}
  *
  * @param array $form
  * @param array $form_state
  * @param WorkflowTransition
  *  The Transition to be edited, created.
  *
  * @return
  *  The enhanced form structure.
  */
 public function buildForm(array $form, array &$form_state)
 {
     global $user;
     /* @var $transition WorkflowTransition */
     $transition = NULL;
     if (isset($form_state['WorkflowTransition'])) {
         // If provided, get data from WorkflowTransition.
         // This happens when calling entity_ui_get_form(), like in the
         // WorkflowTransition Comment Edit form.
         $transition = $form_state['WorkflowTransition'];
         $field_name = $transition->field_name;
         $workflow = $transition->getWorkflow();
         $wid = $transition->wid;
         $entity = $this->entity = $transition->getEntity();
         $entity_type = $this->entity_type = $transition->entity_type;
         // Figure out the $entity's bundle and id.
         list(, , $entity_bundle) = entity_extract_ids($entity_type, $entity);
         $entity_id = entity_id($entity_type, $entity);
         // 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, transition_edit.
         // @todo: support multiple workflows per entity.
         // For workflow_tab_page with multiple workflows, use a separate view. See [#2217291].
         $field = _workflow_info_field($field_name, $workflow);
         $instance = $this->instance + field_info_instance($entity_type, $field_name, $entity_bundle);
     } else {
         // Get data from normal parameters.
         $entity = $this->entity;
         $entity_type = $this->entity_type;
         $entity_id = $entity ? entity_id($entity_type, $entity) : 0;
         $field = $this->field;
         $field_name = $field['field_name'];
         $instance = $this->instance;
         // $field['settings']['wid'] can be numeric or named.
         // $wid may not be specified.
         $wid = $field['settings']['wid'];
         $workflow = workflow_load_single($wid);
     }
     $force = FALSE;
     // Get values.
     // Current sid and default value may differ in a scheduled transition.
     // Set 'grouped' option. Only valid for select list and undefined/multiple workflows.
     $settings_options_type = $field['settings']['widget']['options'];
     $grouped = $settings_options_type == 'select';
     if ($transition) {
         // If a Transition is passed as parameter, use this.
         if ($transition->isExecuted()) {
             // We are editing an existing/executed/not-scheduled transition.
             // Only the comments may be changed!
             // Fetch the old state for the formatter on top of form.
             $current_state = $transition->getOldState();
             $current_sid = $current_state->sid;
             // The states may not be changed anymore.
             $new_state = $transition->getNewState();
             $options = array($new_state->sid => $new_state->label());
             // We need the widget to edit the comment.
             $show_widget = TRUE;
         } else {
             $current_state = $transition->getOldState();
             $current_sid = $current_state->sid;
             $options = $current_state->getOptions($entity_type, $entity, $field_name, $user, $force);
             $show_widget = $current_state->showWidget($entity_type, $entity, $field_name, $user, $force);
         }
         $default_value = $transition->new_sid;
     } elseif (!$entity) {
         // Sometimes, no entity is given. We encountered the following cases:
         // - the Field settings page,
         // - the VBO action form;
         // - the Advance Action form on admin/config/system/actions;
         // If so, show all options for the given workflow(s).
         $options = workflow_get_workflow_state_names($wid, $grouped, $all = FALSE);
         $show_widget = TRUE;
         $default_value = $current_sid = isset($items[0]['value']) ? $items[0]['value'] : '0';
     } else {
         $current_sid = workflow_node_current_state($entity, $entity_type, $field_name);
         if ($current_state = workflow_state_load_single($current_sid)) {
             /* @var $current_state WorkflowTransition */
             $options = $current_state->getOptions($entity_type, $entity, $field_name, $user, $force);
             $show_widget = $current_state->showWidget($entity_type, $entity, $field_name, $user, $force);
             $default_value = !$current_state->isCreationState() ? $current_sid : $workflow->getFirstSid($entity_type, $entity, $field_name, $user, FALSE);
         } else {
             // We are in trouble! A message is already set in workflow_node_current_state().
             $options = array();
             $show_widget = FALSE;
             $default_value = $current_sid;
         }
         // Get the scheduling info. This may change the $default_value on the Form.
         // Read scheduled information, only if an entity exists.
         // 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, 1) as $transition) {
             $default_value = $transition->new_sid;
             break;
         }
     }
     // Prepare a new transition, if still not provided.
     if (!$transition) {
         $transition = new WorkflowTransition(array('old_sid' => $default_value, 'stamp' => REQUEST_TIME));
     }
     // Fetch the form ID. This is unique for each entity, to allow multiple form per page (Views, etc.).
     // Make it uniquer by adding the field name, or else the scheduling of
     // multiple workflow_fields is not independent of each other.
     // IF we are truly on a Transition form (so, not a Node Form with widget)
     // then change the form id, too.
     $form_id = $this->getFormId();
     if (!isset($form_state['build_info']['base_form_id'])) {
         // Strange: on node form, the base_form_id is node_form,
         // but on term form, it is not set.
         // In both cases, it is OK.
     } else {
         if ($form_state['build_info']['base_form_id'] == 'workflow_transition_wrapper_form') {
             $form_state['build_info']['base_form_id'] = 'workflow_transition_form';
         }
         if ($form_state['build_info']['base_form_id'] == 'workflow_transition_form') {
             $form_state['build_info']['form_id'] = $form_id;
         }
     }
     $workflow_label = $workflow ? check_plain(t($workflow->label())) : '';
     // Change settings locally.
     if (!$field_name) {
         // This is a Workflow Node workflow. Set widget options as in v7.x-1.2
         if ($form_state['build_info']['base_form_id'] == 'node_form') {
             $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;
         } else {
             $field['settings']['widget']['comment'] = isset($workflow->options['comment_log_tab']) ? $workflow->options['comment_log_tab'] : 1;
             // vs. ['comment_log_node'];
             $field['settings']['widget']['current_status'] = TRUE;
         }
     }
     // Capture settings to format the form/widget.
     $settings_title_as_name = !empty($field['settings']['widget']['name_as_title']);
     $settings_fieldset = isset($field['settings']['widget']['fieldset']) ? $field['settings']['widget']['fieldset'] : 0;
     $settings_options_type = $field['settings']['widget']['options'];
     // The scheduling info can be hidden via field settings, ...
     // You may not schedule an existing Transition.
     // You must have the correct permission.
     $settings_schedule = !empty($field['settings']['widget']['schedule']) && !$transition->isExecuted() && user_access('schedule workflow transitions');
     if ($settings_schedule) {
         if (isset($form_state['step']) && $form_state['step'] == 'views_bulk_operations_config_form') {
             // On VBO 'modify entity values' form, leave field settings.
             $settings_schedule = TRUE;
         } else {
             // ... and cannot be shown on a Content add page (no $entity_id),
             // ...but can be shown on a VBO 'set workflow state to..'page (no entity).
             $settings_schedule = !($entity && !$entity_id);
         }
     }
     $settings_schedule_timezone = !empty($field['settings']['widget']['schedule_timezone']);
     // Show comment, when both Field and Instance allow this.
     $settings_comment = $field['settings']['widget']['comment'];
     // 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' => $field);
     $element['workflow']['workflow_instance'] = array('#type' => 'value', '#value' => $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);
     // Save the hid, when editing an existing transition.
     $element['workflow']['workflow_hid'] = array('#type' => 'hidden', '#value' => $transition->hid);
     // Add the default value in the place where 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 for a widget when the only option is the current sid.
     // Show state formatter before the rest of the form,
     // when transition is scheduled or widget is hidden.
     if (!$show_widget || $transition->isScheduled() || $transition->isExecuted()) {
         $form['workflow_current_state'] = workflow_state_formatter($entity_type, $entity, $field, $instance, $current_sid);
         // Set a proper weight, which works for Workflow Options in select list AND action buttons.
         $form['workflow_current_state']['#weight'] = -0.005;
     }
     // Add class following node-form pattern (both on form and container).
     $workflow_type_id = $workflow ? $workflow->getName() : 'none';
     // No workflow on New Action form.
     $element['workflow']['#attributes']['class'][] = 'workflow-transition-container';
     $element['workflow']['#attributes']['class'][] = 'workflow-transition-' . $workflow_type_id . '-container';
     // Add class for D7-backwards compatibility (only on container).
     $element['workflow']['#attributes']['class'][] = 'workflow-form-container';
     if (!$show_widget) {
         // Show no widget.
         $element['workflow']['workflow_sid']['#type'] = 'value';
         $element['workflow']['workflow_sid']['#value'] = $default_value;
         $element['workflow']['workflow_sid']['#options'] = $options;
         // In case action buttons need them.
         $form += $element;
         return $form;
         // <---- exit.
     } else {
         // Prepare a UI wrapper. This might be a fieldset or a container.
         if ($settings_fieldset == 0) {
             // Use 'container'.
             $element['workflow'] += array('#type' => 'container');
         } else {
             $element['workflow'] += array('#type' => 'fieldset', '#title' => t($workflow_label), '#collapsible' => TRUE, '#collapsed' => $settings_fieldset == 1 ? FALSE : TRUE);
         }
         // The 'options' widget. May be removed later if 'Action buttons' are chosen.
         // The help text is not available for container. Let's add it to the
         // State box.
         $help_text = isset($instance['description']) ? $instance['description'] : '';
         $element['workflow']['workflow_sid'] = array('#type' => $settings_options_type, '#title' => $settings_title_as_name ? t('Change !name state', array('!name' => $workflow_label)) : t('Target state'), '#access' => TRUE, '#options' => $options, '#default_value' => $default_value, '#description' => $help_text);
     }
     // 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) {
         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());
         $timestamp = $transition->getTimestamp();
         $hours = !$transition->isScheduled() ? '00:00' : format_date($timestamp, 'custom', 'H:i', $timezone);
         // Add a container, so checkbox and time stay together in extra fields.
         $element['workflow']['workflow_scheduling'] = array('#type' => 'container', '#tree' => TRUE);
         $element['workflow']['workflow_scheduling']['scheduled'] = array('#type' => 'radios', '#title' => t('Schedule'), '#options' => array('0' => t('Immediately'), '1' => t('Schedule for state change')), '#default_value' => $transition->isScheduled() ? '1' : '0', '#attributes' => array('class' => array(drupal_html_class('scheduled_' . $form_id))));
         $element['workflow']['workflow_scheduling']['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.' . drupal_html_class('scheduled_' . $form_id) => array('value' => '1'))));
         $element['workflow']['workflow_scheduling']['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_scheduling']['date_time']['workflow_scheduled_hour'] = array('#type' => 'textfield', '#title' => t('Time'), '#maxlength' => 7, '#size' => 6, '#default_value' => $hours, '#element_validate' => array('_workflow_transition_form_element_validate_time'));
         $element['workflow']['workflow_scheduling']['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_scheduling']['date_time']['workflow_scheduled_help'] = array('#type' => 'item', '#prefix' => '<br />', '#description' => t('Please enter a time.
       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' => 'textarea', '#required' => $settings_comment == '2', '#access' => $settings_comment != '0', '#title' => t('Workflow comment'), '#description' => t('A comment to put in the workflow log.'), '#default_value' => $transition->comment, '#rows' => 2);
     // Add the fields and extra_fields from the WorkflowTransition.
     // Because we have a 'workflow' wrapper, it doesn't work flawlessly.
     field_attach_form('WorkflowTransition', $transition, $element['workflow'], $form_state);
     // Undo the following elements from field_attach_from. They mess up $this->getTransition().
     // - '#parents' corrupts the Defaultwidget.
     unset($element['workflow']['#parents']);
     // - '#pre_render' adds the exra_fields from workflow_field_extra_fields().
     //   That doesn't work, since 'workflow' is not of #type 'form', but
     //   'container' or 'fieldset', and must be executed separately,.
     $element['workflow']['#pre_render'] = array_diff($element['workflow']['#pre_render'], array('_field_extra_fields_pre_render'));
     // Add extra fields.
     $rescue_value = $element['workflow']['#type'];
     $element['workflow']['#type'] = 'form';
     $element['workflow'] = _field_extra_fields_pre_render($element['workflow']);
     $element['workflow']['#type'] = $rescue_value;
     // Finally, add Submit buttons/Action buttons.
     // Either a default 'Submit' button is added, or a button per permitted state.
     if ($settings_options_type == 'buttons') {
         // How do action buttons work? See also d.o. issue #2187151.
         // Create 'action buttons' per state option. Set $sid property on each button.
         // 1. Admin sets ['widget']['options']['#type'] = 'buttons'.
         // 2. This function formElement() creates 'action buttons' per state option;
         //    sets $sid property on each button.
         // 3. User clicks button.
         // 4. Callback _workflow_transition_form_validate_buttons() sets proper State.
         // 5. Callback _workflow_transition_form_validate_buttons() sets Submit function.
         // @todo: this does not work yet for the Add Comment form.
         // Performance: inform workflow_form_alter() to do its job.
         _workflow_use_action_buttons(TRUE);
         // Hide the options box. It will be replaced by action buttons.
         $element['workflow']['workflow_sid']['#type'] = 'select';
         $element['workflow']['workflow_sid']['#access'] = FALSE;
     }
     if ($form_state['build_info']['base_form_id'] == 'workflow_transition_form') {
         // Add action buttons on WorkflowTransitionForm (history tab, formatter)
         // but not on Entity form, and not if action_buttons is selected.
         // you can explicitly NOT add a submit button, e.g., on VBO page.
         if ($instance['widget']['settings']['submit_function'] !== '') {
             // @todo D8: put buttons outside of 'workflow' element, in the standard location.
             $element['workflow']['actions']['#type'] = 'actions';
             $element['workflow']['actions']['submit'] = array('#type' => 'submit', '#value' => t('Update workflow'), '#weight' => -5, '#attributes' => array('class' => array('form-save-default-button')));
             // The 'add submit' can explicitly set by workflowfield_field_formatter_view(),
             // to add the submit button on the Content view page and the Workflow history tab.
             // Add a submit button, but only on Entity View and History page.
             // Add the submit function only if one provided. Set the submit_callback accordingly.
             if (!empty($instance['widget']['settings']['submit_function'])) {
                 $element['workflow']['actions']['submit']['#submit'] = array($instance['widget']['settings']['submit_function']);
             } else {
                 // '#submit' Must be empty, or else the submit function is not called.
                 // $element['workflow']['actions']['submit']['#submit'] = array();
             }
         }
     }
     /*
         $submit_functions = empty($instance['widget']['settings']['submit_function']) ? array() : array($instance['widget']['settings']['submit_function']);
         if ($settings_options_type == 'buttons' || $submit_functions) {
         }
         else {
      // In some cases, no submit callback function is specified. This is
      // explicitly done on e.g., the node edit form, because the workflow form
      // is 'just a field'.
      // So, no Submit button is to be shown.
         }
     */
     $form += $element;
     // Add class following node-form pattern (both on form and container).
     $workflow_type_id = $workflow ? $workflow->getName() : 'none';
     // No workflow on New Action form.
     $form['#attributes']['class'][] = 'workflow-transition-form';
     $form['#attributes']['class'][] = 'workflow-transition-' . $workflow_type_id . '-form';
     return $form;
 }
 /**
  * Implements hook_field_settings_form() -> ConfigFieldItemInterface::settingsForm().
  *
  * @param array $form
  * @param array $form_state
  * @param $has_data
  *
  * @return array $element
  *   The newly constructed element.
  */
 public function settingsForm(array $form, array &$form_state, $has_data)
 {
     $field_info = self::getInfo();
     $settings = $this->field['settings'];
     $settings += $field_info['workflow']['settings'];
     $settings['widget'] += $field_info['workflow']['settings']['widget'];
     // Create list of all Workflow types. Include an initial empty value.
     // Validate each workflow, and generate a message if not complete.
     /* @var $workflow Workflow */
     $workflows = array();
     $workflows[''] = t('- Select a value -');
     foreach ($workflows += workflow_get_workflow_names() as $wid => $label) {
         $workflow = workflow_load_single($wid);
         if ($wid && !$workflow->isValid()) {
             unset($workflows[$wid]);
         }
     }
     // Set message, if no 'validated' workflows exist.
     if (count($workflows) == 1) {
         drupal_set_message(t('You must create at least one workflow before content can be
       assigned to a workflow.'));
     }
     // The allowed_values_functions is used in the formatter from list.module.
     $element['allowed_values_function'] = array('#type' => 'value', '#value' => $settings['allowed_values_function']);
     // $field['settings']['wid'] can be numeric or named, or empty.
     $wid = isset($settings['wid']) ? $settings['wid'] : '';
     // Let the user choose between the available workflow types.
     $element['wid'] = array('#type' => 'select', '#title' => t('Workflow type'), '#options' => $workflows, '#default_value' => $wid, '#required' => TRUE, '#disabled' => $has_data, '#description' => t('Choose the Workflow type. Maintain workflows !url.', array('!url' => l(t('here'), 'admin/config/workflow/workflow'))));
     // Inform the user of possible states.
     // If no Workflow type is selected yet, do not show anything.
     if ($wid) {
         // Get a string representation to show all options.
         $allowed_values_string = $this->_allowed_values_string($wid);
         $element['allowed_values_string'] = array('#type' => 'textarea', '#title' => t('Allowed values for the selected Workflow type'), '#default_value' => $allowed_values_string, '#rows' => 10, '#access' => TRUE, '#disabled' => TRUE);
     }
     $element['widget'] = array('#type' => 'fieldset', '#title' => t('Workflow widget'), '#description' => t('Set some global properties of the widgets for this
     workflow. Some can be altered per widget instance.'));
     $fieldset_options = array(0 => t('No fieldset'), 1 => t('Collapsible fieldset'), 2 => t('Collapsed fieldset'));
     $element['widget']['fieldset'] = array('#type' => 'select', '#options' => $fieldset_options, '#title' => t('Show the form in a fieldset?'), '#default_value' => $settings['widget']['fieldset'], '#description' => t("The Widget can be wrapped in a visible fieldset. You'd\n        do this when you use the widget on a Node Edit page."));
     $element['widget']['options'] = array('#type' => 'select', '#title' => t('How to show the available states'), '#required' => FALSE, '#default_value' => $settings['widget']['options'], '#options' => array('select' => 'Select list', 'radios' => 'Radio buttons', 'buttons' => 'Action buttons'), '#description' => t("The Widget shows all available states. Decide which\n        is the best way to show them. ('Action buttons' do not work on Comment form.)"));
     $element['widget']['hide'] = array('#type' => 'checkbox', '#attributes' => array('class' => array('container-inline')), '#title' => t('Hide the widget on Entity form.'), '#default_value' => $settings['widget']['hide'], '#description' => t('Using Workflow Field, the widget is always shown when editing an
     Entity. Set this checkbox in case you only want to change the status
     on the Workflow History tab or on the Node View. (This checkbox is
     only needed because Drupal core does not have a "hidden" widget.)'));
     $element['widget']['name_as_title'] = array('#type' => 'checkbox', '#attributes' => array('class' => array('container-inline')), '#title' => t('Use the workflow name as the title of the workflow form'), '#default_value' => $settings['widget']['name_as_title'], '#description' => t('The workflow section of the editing form is in its own fieldset.
      Checking the box will add the workflow name as the title of workflow
      section of the editing form.'));
     $element['widget']['schedule'] = array('#type' => 'checkbox', '#title' => t('Allow scheduling of workflow transitions.'), '#required' => FALSE, '#default_value' => $settings['widget']['schedule'], '#description' => t('Workflow transitions may be scheduled to a moment in the future.
      Soon after the desired moment, the transition is executed by Cron.
      This may be hidden by settings in widgets, formatters or permissions.'));
     $element['widget']['schedule_timezone'] = array('#type' => 'checkbox', '#title' => t('Show a timezone when scheduling a transition.'), '#required' => FALSE, '#default_value' => $settings['widget']['schedule_timezone']);
     $element['widget']['comment'] = array('#type' => 'select', '#title' => t('Allow adding a comment to workflow transitions'), '#required' => FALSE, '#options' => array(0 => t('hidden'), 1 => t('optional'), 2 => t('required')), '#default_value' => $settings['widget']['comment'], '#description' => t('On the Workflow form, a Comment form can be included
     so that the person making the state change can record reasons for doing
     so. The comment is then included in the node\'s workflow history. This
     may be altered by settings in widgets, formatters or permissions.'));
     $element['watchdog_log'] = array('#type' => 'checkbox', '#attributes' => array('class' => array('container-inline')), '#title' => t('Log informational watchdog messages when a transition is
     executed (a state value is changed)'), '#default_value' => $settings['watchdog_log'], '#description' => t('Optionally log transition state changes to watchdog.'));
     $element['history'] = array('#type' => 'fieldset', '#title' => t('Workflow history'), '#collapsible' => TRUE, '#collapsed' => FALSE);
     $element['history']['history_tab_show'] = array('#type' => 'checkbox', '#title' => t('Use the workflow history, and show it on a separate tab.'), '#required' => FALSE, '#default_value' => $settings['history']['history_tab_show'], '#description' => t("Every state change is recorded in table\n        {workflow_node_history}. If checked and user has proper permission, a\n        tab 'Workflow' is shown on the entity view page, which gives access to\n        the History of the workflow. If you have multiple workflows per bundle,\n        better disable this feature, and use, clone & adapt the Views display\n        'Workflow history per Entity'."));
     $element['history']['roles'] = array('#type' => 'checkboxes', '#options' => workflow_get_roles(), '#title' => t('Workflow history permissions'), '#default_value' => $settings['history']['roles'], '#description' => t('Select any roles that should have access to the workflow tab on nodes that have a workflow.'));
     return $element;
 }