You are here

public function WorkflowDefaultWidget::formElement in Workflow 7

Same name and namespace in other branches
  1. 7.2 includes/Field/WorkflowDefaultWidget.php \WorkflowDefaultWidget::formElement()

Implements hook_field_widget_form --> WidgetInterface::formElement().

Be careful: this widget may be shown in very different places. Test carefully!!

  • On a node add/edit page
  • On a node preview page
  • On a node view page
  • On a node '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"

File

includes/Field/WorkflowDefaultWidget.php, line 66
Contains workflow\includes\Field\WorkflowDefaultWidget.

Class

WorkflowDefaultWidget
Plugin implementation of the 'workflow_default' widget. @todo D8: Replace "extends WorkflowD7WidgetBase" by "extends WidgetBase" or perhaps by "extends OptionsWidgetBase" from Options module.

Code

public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
  $field_name = $this->field['field_name'];
  $entity = $this->entity;
  $entity_type = $this->entity_type;
  $entity_id = isset($entity->nid) ? $entity->nid : 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 = $this->field['settings']['widget']['name_as_title'] && $this->instance['widget']['settings']['name_as_title'];

  // The schedule cannot be shown on a Content add page.
  $settings_schedule = $this->field['settings']['widget']['schedule'] && $entity_id;
  $settings_schedule_timezone = $this->field['settings']['widget']['schedule_timezone'];

  
  $settings_comment = $this->field['settings']['widget']['comment'] && $this->instance['widget']['settings']['comment'] ? 'textarea' : 'hidden';

  // The 'add submit' setting is explicitely set by workflowfield_field_formatter_view(), to add the submit button on the Content view page.
  $settings_submit = isset($this->instance['widget']['settings']['submit']) ? TRUE : FALSE;
  $workflow = Workflow::load($this->field['settings']['wid']);

  // @todo: Get the current sid for content, comment, preview.
  if (count($items)) {

    // A normal Content edit.
    $sid = _workflow_get_sid_by_items($items);
  }
  else {

    // We are on a Content add or Comment add (which do not have a state, yet),
    // or we are viewing existing content, which didn't have a state before.

    //@todo: why/when would field_get_items returns a result, if $items is already empty?
    $items = field_get_items($entity_type, $entity, $field_name);
    if ($items) {
      $sid = _workflow_get_sid_by_items($items);
    }
  }
  if (empty($sid)) {

    // Content add page: No valid sid is given, so get the first state.
    // or a states has been deleted.
    $sid = $workflow
      ->getFirstSid($entity_type, $entity);
  }
  $state = WorkflowState::load($sid);
  $options = $state
    ->getOptions($entity_type, $entity);

  // 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';
      $sid = $scheduled_transition->sid;
      $timestamp = $scheduled_transition->scheduled;
      $comment = $scheduled_transition->comment;
      break;
    }
  }

  // Stop if user has no new target state(s) to choose.
  if (!workflow_show_form($sid, $workflow, $options)) {

    //dpm('show only formatter for ' . $sid , __FUNCTION__);
    return $element;
  }
  $label = $workflow
    ->label();
  $element['workflow'] = array(
    '#type' => 'fieldset',
    '#title' => $label,
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );

  // Save the current value of the node in the form, for later reference.
  $element['workflow']['#node'] = $entity;
  $element['workflow']['#entity'] = $entity;
  $element['#node'] = $entity;
  $element['#entity'] = $entity;

  //dpm(array_pop($options));

  //dpm(array_pop($options));
  if (count($options) == 1) {

    // Add the State widget/formatter
    // @todo: add real formatter, instead.
    // @todo: TEST THIS USE CASE.
    // There is no need to show the single choice.
    // A form choice would be an array with the key of the state.
    $state = key($options);

    //      $element['workflow'][$label] = array(
    $element['workflow']['workflow_options'] = array(
      '#type' => 'value',
      '#value' => array(
        $state => $state,
      ),
    );
  }
  else {

    // @todo: Q: why are we overwriting 'fieldset' with 'container' ?
    //        A: this is because you'd want the form in a vertical tab, and a fieldset makes no sense there.
    $element['workflow']['#type'] = 'container';
    $element['workflow']['#attributes'] = array(
      'class' => array(
        'workflow-form-container',
      ),
    );
    $element['workflow']['workflow_options'] = array(
      '#type' => $this->field['settings']['widget']['options'],
      '#title' => $settings_title_as_name ? t('Change !name state', array(
        '!name' => $label,
      )) : '',
      '#options' => $options,
      //        '#name' => $label,
      //        '#parents' => array('workflow'),
      '#default_value' => $sid,
    );
  }

  // 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')) {

    // Caveat: for the #states to work in multi-node view, the name is suffixed by unique ID.
    if (isset($form['#id']) && $form['#id'] == 'comment-form') {

      // This is already the name for Node API and now also for Comment form.
      // We assume there is only one Comment form on a page.
      $element_name = 'workflow_scheduled';
    }
    else {

      // This name allows for multiple nodes on a page.
      // @todo: #states doesn't work yet for non-Node entities.
      $element_name = 'workflow_scheduled' . '-' . $entity_type . '-' . $entity_id;
    }

    //    $element['workflow']['workflow_scheduled'] = array(
    $element['workflow'][$element_name] = array(
      '#type' => 'radios',
      '#title' => t('Schedule'),
      '#options' => array(
        '0' => t('Immediately'),
        '1' => t('Schedule for state change'),
      ),
      '#default_value' => $scheduled,
    );
    $element['workflow']['workflow_scheduled_date_time'] = array(
      '#type' => 'fieldset',
      '#title' => t('At'),
      '#prefix' => '<div style="margin-left: 1em;">',
      '#suffix' => '</div>',
      '#states' => array(
        //        'visible' => array(':input[name="workflow_scheduled"]' => array('value' => '1')),
        //        'invisible' => array(':input[name="workflow_scheduled"]' => array('value' => '0')),
        'visible' => array(
          ':input[name="' . $element_name . '"]' => array(
            'value' => '1',
          ),
        ),
        'invisible' => array(
          ':input[name="' . $element_name . '"]' => array(
            'value' => '0',
          ),
        ),
      ),
    );
    $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),
      ),
    );
    $hours = format_date($timestamp, 'custom', 'H:i');
    $element['workflow']['workflow_scheduled_date_time']['workflow_scheduled_hour'] = array(
      '#type' => 'textfield',
      '#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' => $hours,
      )),
      '#default_value' => $scheduled ? isset($form_state['values']['workflow_scheduled_hour']) ? $form_state['values']['workflow_scheduled_hour'] : $hours : '00:00',
    );
    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());
    $element['workflow']['workflow_scheduled_date_time']['workflow_scheduled_timezone'] = array(
      '#type' => $settings_schedule_timezone ? 'select' : 'hidden',
      '#options' => $timezones,
      '#title' => t('Time zone'),
      '#default_value' => array(
        $timezone => $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,
  );
  if ($settings_submit) {

    // 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(
        'workflowfield_field_widget_form_submit',
      ),
    );
  }
  return $element;
}