workflow-8.x-1.x-dev/src/Controller/WorkflowTransitionFormController.php

src/Controller/WorkflowTransitionFormController.php
<?php

namespace Drupal\workflow\Controller;

use Drupal\workflow\Entity\WorkflowManager;
use Drupal\workflow\Entity\WorkflowTransitionInterface;

/**
 * Defines a controller to influence the Transition element/form.
 */
class WorkflowTransitionFormController {
  /**
   * The transaction at hand.
   *
   * @var \Drupal\workflow\Entity\WorkflowTransitionInterface
   */
  protected $transition;

  /**
   * Constructs an object.
   *
   * @param \Drupal\workflow\Entity\WorkflowTransitionInterface $transition
   *   The transition.
   */
  public function __construct(WorkflowTransitionInterface $transition) {
    $this->transition = $transition;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(WorkflowTransitionInterface $transition) {
    return new static(
      $transition,
    );
  }

  /**
   * {@inheritdoc}
   */
  public function isSchedulingAllowed(): bool {
    $transition = $this->transition;
    $field_name = $transition->getFieldName();
    // Do not get user from transition, but from session.
    // Avoid loading same user many times by using static.
    static $user = NULL;
    // Avoid PHP8.2 Error: Constant expression contains invalid operations.
    $user ??= workflow_current_user();
    // Workflow might be empty on Action/VBO configuration.
    $wid = $transition->getWorkflowId();
    $workflow = $transition->getWorkflow();
    $settings = $workflow?->getSettings();

    // Display scheduling form only if user has permission.
    // Not shown on new entity (not supported by workflow module, because that
    // leaves the entity in the (creation) state until scheduling time.)
    // Not shown when editing existing transition.
    $entity = WorkflowManager::isTargetCommentEntity($transition)
      // On WorkflowWithComment, check entity, not comment that always isNew().
      ? $transition->getTargetEntity()->getCommentedEntity()
      : $transition->getTargetEntity();

    // Determine if scheduling may be allowed.
    $add_schedule = $settings['schedule_enable']
      && !$transition->isExecuted()
      && !$entity->isNew()
      && $user->hasPermission("schedule $wid workflow_transition");

    // When user has only 1 option, scheduling makes no sense. Do not move
    // into mustShowOptionsWidget(), since displaying widget may make sense.
    if ($add_schedule) {
      $account = $transition->getOwner();
      // $options = $transition->getSettableOptions(NULL, 'to_sid');
      $options = $transition->getFromState()->getOptions($entity, $field_name, $account);
      if (count($options) <= 1) {
        $add_schedule = FALSE;
      }
    }

    // Additional check. @todo Still needed?
    if ($add_schedule) {
      $add_schedule = $this->mustShowOptionsWidget();
    }

    return $add_schedule;
  }

  /**
   * Determines if the Workflow Transition Form must be shown.
   *
   * If not, a formatter must be shown, since there are no valid options.
   * Only the comment field may be displayed.
   *
   * @return bool
   *   A boolean indicator to display a widget or formatter.
   *   TRUE = a form (a.k.a. widget) must be shown;
   *   FALSE = no form, a formatter must be shown instead.
   */
  public function mustShowOptionsWidget(): bool {
    static $results = [];

    $transition = $this->transition;

    $tid = $transition->id();
    $eid = $transition->getTargetEntityId();
    $key = "{$eid}x{$tid}";
    if (isset($results[$key])) {
      return $results[$key];
    }

    $entity = $transition->getTargetEntity();
    $field_name = $transition->getFieldName();
    $account = $transition->getOwner();

    /** @var \Drupal\node\Entity\Node $entity */
    if ($entity?->in_preview ?? NULL) {
      // Avoid having the form in preview, since it has action buttons.
      // In preview, you can only go back to original, user cannot save data.
      return $results[$key] = FALSE;
    }

    if ($transition->isExecuted()) {
      // We are editing an existing/executed/not-scheduled transition.
      // We need the widget to edit the comment.
      // Only the comments may be changed!
      // The states may not be changed anymore.
      return $results[$key] = TRUE;
    }

    if (WorkflowManager::isTargetCommentEntity($transition)) {
      if (!$transition->getTargetEntity()->isNew()) {
        return $results[$key] = FALSE;
      }
    }

    if (!$transition->getFromSid()) {
      // On Actions, where no entity exists.
      return $results[$key] = TRUE;
    }

    // $options = $transition->getSettableOptions(NULL, 'to_sid');
    $options = $transition->getFromState()->getOptions($entity, $field_name, $account);
    // The easiest case first: more then one option: always show form.
    if (count($options) > 1) {
      return $results[$key] = TRUE;
    }
    else {
      // Check if user wants to show state option field.
      $options_type = $transition->getFromState()->get('single_state_widget');
      if ($options_type !== 'hidden') {
        return $results[$key] = TRUE;
      }
    }

    // #2226451: Even in Creation state,
    // we must have 2 visible states to show the widget.
    // // Only when in creation phase, one option is sufficient,
    // // since the '(creation)' option is not included in $options.
    // // When in creation state,
    // if ($transition->isCreationState()) {
    // return TRUE;
    // }
    return $results[$key] = FALSE;
  }

  /**
   * Returns the options widget type.
   *
   * @return string
   *   The widget type for state options.
   *   The default type may be overridden with 'item' or 'hidden'.
   */
  public function getOptionsWidgetType(): string {
    $transition = $this->transition;
    $field_name = $transition->getFieldName();
    $entity = $transition->getTargetEntity();
    $account = $transition->getOwner();
    $workflow = $this->transition->getWorkflow();

    // Avoid error with grouped options when workflow not set.
    if (!$workflow) {
      return 'select';
    }

    $workflow_settings = $workflow->getSettings();
    $options_type = $workflow_settings['options'];

    /** @var \Drupal\node\Entity\Node $entity */
    if ($entity?->in_preview ?? NULL) {
      // Avoid having the form in preview, since it has action buttons.
      // In preview, you can only go back to original, user cannot save data.
      // @todo Add user message that form is not shown in preview.
      return 'item';
    }

    if ($transition->isExecuted()) {
      // We are editing an existing/executed/not-scheduled transition.
      // We need the widget to edit the comment.
      // Only the comments may be changed!
      // The states may not be changed anymore.
      return 'item';
    }

    if ($options_type == 'buttons' || $options_type == 'dropbutton') {
      // Make sure the '#type' is not set to the invalid 'buttons' value.
      // Action buttons replace options widget, but sometimes, the select box
      // is still shown.
      // @see workflow_form_alter().
      return 'hidden';
    }

    // $options = $transition->getSettableOptions(NULL, 'to_sid');
    $options = $transition->getFromState()->getOptions($entity, $field_name, $account);
    if (count($options) == 1) {
      // Check if user wants to show single state option field.
      $single_state_widget = $transition->getFromState()->get('single_state_widget');
      switch ($single_state_widget) {
        case '':
          // 'Display state widget (default)',
          return $options_type;

        case 'item':
          // 'Display state formatter',
        case 'hidden':
          // 'Hide state widget',
          return $single_state_widget;

          case 'hide_fieldset':
          // 'Hide complete field',
          // The complete field will be hidden in AddWrapper().
          return $options_type;
      }

    }

    return $options_type;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc