/**
  * {@inheritdoc}
  */
 public function access(EntityInterface $entity, $operation, AccountInterface $account = NULL, $return_as_object = FALSE)
 {
     $result = AccessResult::neutral();
     $account = $this->prepareUser($account);
     // $account = workflow_current_user($account);
     /* @var $transition WorkflowTransitionInterface */
     $transition = $entity;
     // This is only for Edit/Delete transition. For Add/create, use createAccess.
     switch ($entity->getEntityTypeId()) {
         case 'workflow_transition':
         case 'workflow_scheduled_transition':
             switch ($operation) {
                 case 'update':
                     $is_owner = WorkflowManager::isOwner($account, $transition);
                     $type_id = $transition->getWorkflowId();
                     if ($account->hasPermission("bypass {$type_id} workflow_transition access")) {
                         $result = AccessResult::allowed()->cachePerPermissions();
                     } elseif ($account->hasPermission("edit any {$type_id} workflow_transition")) {
                         $result = AccessResult::allowed()->cachePerPermissions();
                     } elseif ($is_owner && $account->hasPermission("edit own {$type_id} workflow_transition")) {
                         $result = AccessResult::allowed()->cachePerPermissions();
                     }
                     return $return_as_object ? $result : $result->isAllowed();
                     break;
                 case 'delete':
                     // The delete operation is not defined for Transitions.
                     $result = AccessResult::forbidden();
                     break;
                 case 'revert':
                     // @see workflow_operations.
                 // @see workflow_operations.
                 default:
                     $type_id = $transition->getWorkflowId();
                     $result = parent::access($entity, $account, $return_as_object);
                     //if ($account->hasPermission("bypass $type_id workflow_transition access")) {
                     //  $result = AccessResult::allowed()->cachePerPermissions();
                     //}
                     break;
             }
             // End of switch ($operation).
             break;
         case 'workflow_config_transition':
             workflow_debug(__FILE__, __FUNCTION__, __LINE__, $account->id(), $transition->getOwnerId());
             // @todo D8-port: still test this snippet.
             break;
     }
     $result = parent::access($entity, $operation, $account, TRUE)->cachePerPermissions();
     return $return_as_object ? $result : $result->isAllowed();
 }
 /**
  * {@inheritdoc}
  */
 public function access(EntityInterface $entity, $operation, AccountInterface $account = NULL, $return_as_object = FALSE)
 {
     $result = AccessResult::neutral();
     $account = $user = workflow_current_user($account);
     // This is only for Edit/Delete transition. For Add/create, use createAccess.
     switch ($entity->getEntityTypeId()) {
         case 'workflow_transition':
         case 'workflow_scheduled_transition':
             /* @var $transition WorkflowTransitionInterface */
             $transition = $entity;
             switch ($operation) {
                 case 'revert':
                     $is_owner = WorkflowManager::isOwner($user, $transition);
                     $type_id = $transition->getWorkflowId();
                     if ($transition->getFromSid() == $transition->getToSid()) {
                         // No access for same state transitions.
                         $result = AccessResult::forbidden();
                     } elseif ($user->hasPermission("revert any {$type_id} workflow_transition")) {
                         // OK, add operation.
                         $result = AccessResult::allowed();
                     } elseif ($is_owner && $user->hasPermission("revert own {$type_id} workflow_transition")) {
                         // OK, add operation.
                         $result = AccessResult::allowed();
                     } else {
                         // No access.
                         $result = AccessResult::forbidden();
                     }
                     break;
                 default:
                     $result = parent::access($entity, $operation, $account, $return_as_object)->cachePerPermissions();
                     break;
             }
             // End of switch ($operation).
             break;
             // case
         // case
         default:
             // $entity_type
             $result = AccessResult::forbidden();
     }
     // End of  switch($entity->getEntityTypeId()).
     return $return_as_object ? $result : $result->isAllowed();
 }
 /**
  * Returns the allowed transitions for the current state.
  *
  * @param \Drupal\Core\Entity\EntityInterface|NULL $entity
  *   The entity at hand. May be NULL (E.g., on a Field settings page).
  * @param string $field_name
  * @param \Drupal\Core\Session\AccountInterface|NULL $account
  * @param bool|FALSE $force
  *
  * @return \Drupal\workflow\Entity\WorkflowConfigTransition[]
  *   An array of id=>transition pairs with allowed transitions for State.
  */
 public function getTransitions(EntityInterface $entity = NULL, $field_name = '', AccountInterface $account = NULL, $force = FALSE)
 {
     $transitions = array();
     if (!($workflow = $this->getWorkflow())) {
         // No workflow, no options ;-)
         return $transitions;
     }
     // @todo: Keep below code aligned between WorkflowState, ~Transition, ~TransitionListController
     /**
      * Get permissions of user, adding a Role to user, depending on situation.
      */
     // Load a User object, since we cannot add Roles to AccountInterface.
     /* @var $user \Drupal\user\UserInterface */
     $user = workflow_current_user($account);
     // Determine if user is owner of the entity.
     $is_owner = WorkflowManager::isOwner($user, $entity);
     // Check allow-ability of state change if user is not superuser (might be cron)
     $type_id = $this->getWorkflowId();
     if ($user->hasPermission("bypass {$type_id} workflow_transition access")) {
         // Superuser is special. And $force allows Rules to cause transition.
         $force = TRUE;
     } elseif ($is_owner) {
         $user->addRole(WORKFLOW_ROLE_AUTHOR_RID);
     }
     /**
      * Get the object and its permissions.
      */
     /* @var $transitions WorkflowConfigTransition[] */
     $transitions = $workflow->getTransitionsByStateId($this->id(), '');
     /**
      * Determine if user has Access.
      */
     // Use default module permissions.
     foreach ($transitions as $key => $transition) {
         if (!$transition->isAllowed($user, $force)) {
             unset($transitions[$key]);
         }
     }
     // Let custom code add/remove/alter the available transitions,
     // using the new drupal_alter.
     // Modules may veto a choice by removing a transition from the list.
     // Lots of data can be fetched via the $transition object.
     $context = array('user' => $user, 'workflow' => $workflow, 'state' => $this, 'force' => $force);
     \Drupal::moduleHandler()->alter('workflow_permitted_state_transitions', $transitions, $context);
     /**
      * Determine if user has Access.
      */
     // As of 8.x-1.x, below hook() is removed, in favour of above alter().
     // Let custom code change the options, using old_style hook.
     // Above drupal_alter() calls hook_workflow_permitted_state_transitions_alter() only once.
     //    foreach ($transitions as $transition) {
     //      $to_sid = $transition->to_sid;
     //      $permitted = array();
     //
     //      // We now have a list of config_transitions. Check each against the Entity.
     //      // Invoke a callback indicating that we are collecting state choices.
     //      // Modules may veto a choice by returning FALSE.
     //      // In this case, the choice is never presented to the user.
     //      if (!$force) {
     //        // TODO: D8-port: simplify interface for workflow_hook. Remove redundant context.
     //        $permitted = \Drupal::moduleHandler()->invokeAll('workflow', ['transition permitted', $transition, $user]);
     //      }
     //
     //      // If vetoed by a module, remove from list.
     //      if (in_array(FALSE, $permitted, TRUE)) {
     //        unset($transitions[$transition->id()]);
     //      }
     //    }
     return $transitions;
 }
Exemple #4
0
 /**
  * {@inheritdoc}
  */
 public function getNextSid($entity, $field_name, $user, $force = FALSE)
 {
     $new_sid = FALSE;
     $current_sid = WorkflowManager::getCurrentStateId($entity, $field_name);
     $current_state = WorkflowState::load($current_sid);
     $options = $current_state->getOptions($entity, $field_name, $user, $force);
     // Loop over every option. To find the next one.
     $flag = $current_state->isCreationState();
     $new_sid = $current_state->id();
     foreach ($options as $sid => $name) {
         if ($flag) {
             $new_sid = $sid;
             break;
         }
         if ($sid == $current_state->id()) {
             $flag = TRUE;
         }
     }
     return $new_sid;
 }
 /**
  * Menu access control callback. Checks access to Workflow tab.
  *
  * This used to be D7-function workflow_tab_access($user, $entity).
  *
  * The History tab should not be used with multiple workflows per entity.
  * Use the dedicated view for this use case.
  * @todo D8: remove this in favour of View 'Workflow history per entity'.
  * @todo D8-port: make this workf for non-Node entity types.
  *
  * @param \Drupal\workflow\Controller\AccountInterface $account
  *   Run access checks for this account.
  *
  * @return \Drupal\Core\Access\AccessResult
  */
 public function historyAccess(AccountInterface $account)
 {
     static $access = array();
     $uid = $account ? $account->id() : -1;
     // TODO D8-port: make Workflow History tab happen for every entity_type.
     // @see workflow.routing.yml, workflow.links.task.yml, WorkflowTransitionListController.
     // ATM it only works for Nodes and Terms.
     // This is a hack. The Route should always pass an object.
     // On view tab, $entity is object,
     // On workflow tab, $entity is id().
     // Get the entity for this form.
     $entity = workflow_url_get_entity();
     /* @var $entity EntityInterface */
     // Figure out the $entity's bundle and id.
     $entity_type = $entity->getEntityTypeId();
     $entity_bundle = $entity->bundle();
     $entity_id = $entity ? $entity->id() : '';
     $field_name = workflow_url_get_field_name();
     if (isset($access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'])) {
         return $access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'];
     }
     $access_result = AccessResult::forbidden();
     // When having multiple workflows per bundle, use Views display
     // 'Workflow history per entity' instead!
     $fields = _workflow_info_fields($entity, $entity_type, $entity_bundle, $field_name);
     if (!$fields) {
         return AccessResult::forbidden();
     } else {
         // @todo: Keep below code aligned between WorkflowState, ~Transition, ~TransitionListController
         $uid = $account ? $account->id() : -1;
         $entity_id = $entity ? $entity->id() : '';
         // Determine if user is owner of the entity.
         $is_owner = WorkflowManager::isOwner($account, $entity);
         /**
          * Determine if user has Access. Fill the cache.
          */
         // @todo: what to do with multiple workflow_fields per bundle? Use Views instead! Or introduce a setting.
         // @TODO D8-port: workflow_tab_access: use proper 'WORKFLOW_TYPE' permissions
         foreach ($fields as $definition) {
             $type_id = $definition->getSetting('workflow_type');
             if ($account->hasPermission("access any {$type_id} workflow_transion overview")) {
                 $access_result = AccessResult::allowed();
             } elseif ($is_owner && $account->hasPermission("access own {$type_id} workflow_transion overview")) {
                 $access_result = AccessResult::allowed();
             } elseif ($account->hasPermission('administer nodes')) {
                 $access_result = AccessResult::allowed();
             }
             $access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'] = $access_result;
         }
     }
     return $access_result;
 }
 /**
  * {@inheritdoc}
  *
  * N.B. A large part of this function is taken from CommentDefaultFormatter.
  */
 public function viewElements(FieldItemListInterface $items, $langcode)
 {
     $elements = array();
     $output = array();
     $field_name = $this->fieldDefinition->getName();
     $entity = $items->getEntity();
     $entity_type = $entity->getEntityTypeId();
     $status = $items->status;
     $workflow_settings = $this->getFieldSettings();
     $user = \Drupal::currentUser();
     // @todo #2287057: OK?
     // @todo: Perhaps global user is not always the correct user.
     // E.g., on ScheduledTransition->execute()? But this function is mostly used in UI.
     $current_sid = WorkflowManager::getCurrentStateId($entity, $field_name);
     /* @var $current_state WorkflowState */
     $current_state = WorkflowState::load($current_sid);
     // First compose the current value with the normal formatter from list.module.
     $elements = workflow_state_formatter($entity, $field_name, $current_sid);
     // The state must not be deleted, or corrupted.
     if (!$current_state) {
         return $elements;
     }
     // Check permission, so that even with state change rights,
     // the form can be suppressed from the entity view (#1893724).
     $type_id = $current_state->getWorkflowId();
     if (!\Drupal::currentUser()->hasPermission("access {$type_id} workflow_transition form")) {
         return $elements;
     }
     // Workflows are added to the search results and search index by
     // workflow_node_update_index() instead of by this formatter, so don't
     // return anything if the view mode is search_index or search_result.
     if (in_array($this->viewMode, array('search_result', 'search_index'))) {
         return $elements;
     }
     if ($entity_type == 'comment') {
         // No Workflow form allowed on a comment display.
         // (Also, this avoids a lot of error messages.)
         return $elements;
     }
     // Only build form if user has possible target state(s).
     if (!$current_state->showWidget($entity, $field_name, $user, FALSE)) {
         return $elements;
     }
     // Create a transition, to pass to the form. No need to use setValues().
     $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     // Remove the default formatter. We are now building the widget.
     $elements = array();
     // BEGIN Copy from CommentDefaultFormatter
     $elements['#cache']['contexts'][] = 'user.permissions';
     $output['workflows'] = [];
     // Add the WorkflowTransitionForm to the page.
     // $build = $this->viewBuilder->viewMultiple($workflows);
     $build = $this->entityFormBuilder()->getForm($transition, 'add');
     $output['workflows'] += $build;
     // Only show the add workflow form if the user has permission.
     $elements['#cache']['contexts'][] = 'user.roles';
     // Do not show the form for the print view mode.
     $elements[] = $output + array('#workflow_type' => $this->getFieldSetting('workflow_type'), '#workflow_display_mode' => $this->getFieldSetting('default_mode'), 'workflows' => array());
     // END Copy from CommentDefaultFormatter
     return $elements;
 }