You are here

function content_moderation_workspace_access in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/content_moderation/content_moderation.module \content_moderation_workspace_access()

Implements hook_ENTITY_TYPE_access() for the 'workspace' entity type.

Prevents a workspace to be published if there are any pending revisions in a moderation state that doesn't create default revisions.

File

core/modules/content_moderation/content_moderation.module, line 283
Contains content_moderation.module.

Code

function content_moderation_workspace_access(WorkspaceInterface $workspace, $operation, AccountInterface $account) {
  if ($operation !== 'publish') {
    return AccessResult::neutral();
  }

  /** @var \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association */
  $workspace_association = \Drupal::service('workspaces.association');
  $entity_type_manager = \Drupal::entityTypeManager();
  $tracked_revisions = $workspace_association
    ->getTrackedEntities($workspace
    ->id());

  // Extract all the second-level keys (revision IDs) of the two-dimensional
  // array.
  $tracked_revision_ids = array_reduce(array_map('array_keys', $tracked_revisions), 'array_merge', []);

  // Gather a list of moderation states that don't create a default revision.
  $workflow_non_default_states = [];
  foreach ($entity_type_manager
    ->getStorage('workflow')
    ->loadByProperties([
    'type' => 'content_moderation',
  ]) as $workflow) {

    /** @var \Drupal\content_moderation\Plugin\WorkflowType\ContentModerationInterface $workflow_type */
    $workflow_type = $workflow
      ->getTypePlugin();

    // Find all workflows which are moderating entity types of the same type to
    // those that are tracked by the workspace.
    if ($entity_type_ids = array_intersect($workflow_type
      ->getEntityTypes(), array_keys($tracked_revisions))) {
      $workflow_non_default_states[$workflow
        ->id()] = array_filter(array_map(function (ContentModerationState $state) {
        return !$state
          ->isDefaultRevisionState() ? $state
          ->id() : NULL;
      }, $workflow_type
        ->getStates()));
    }
  }

  // Check if any revisions that are about to be published are in a non-default
  // revision moderation state.
  $query = $entity_type_manager
    ->getStorage('content_moderation_state')
    ->getQuery()
    ->allRevisions()
    ->accessCheck(FALSE);
  $query
    ->condition('content_entity_revision_id', $tracked_revision_ids, 'IN');
  $workflow_condition_group = $query
    ->orConditionGroup();
  foreach ($workflow_non_default_states as $workflow_id => $non_default_states) {
    $group = $query
      ->andConditionGroup()
      ->condition('workflow', $workflow_id, '=')
      ->condition('moderation_state', $non_default_states, 'IN');
    $workflow_condition_group
      ->condition($group);
  }
  $query
    ->condition($workflow_condition_group);
  if ($count = $query
    ->count()
    ->execute()) {
    $message = \Drupal::translation()
      ->formatPlural($count, 'The @label workspace can not be published because it contains 1 item in an unpublished moderation state.', 'The @label workspace can not be published because it contains @count items in an unpublished moderation state.', [
      '@label' => $workspace
        ->label(),
    ]);
    return AccessResult::forbidden((string) $message);
  }
}