function content_moderation_workspace_access

Same name and namespace in other branches
  1. 8.9.x 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

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 (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);
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.