You are here

class EntityAccess in Workspace 8

Same name and namespace in other branches
  1. 8.2 src/EntityAccess.php \Drupal\workspace\EntityAccess

Service wrapper for hooks relating to entity access control.

Hierarchy

Expanded class hierarchy of EntityAccess

1 string reference to 'EntityAccess'
workspace.services.yml in ./workspace.services.yml
workspace.services.yml
1 service uses EntityAccess
workspace.entity_access in ./workspace.services.yml
Drupal\workspace\EntityAccess

File

src/EntityAccess.php, line 16

Namespace

Drupal\workspace
View source
class EntityAccess {
  use StringTranslationTrait;

  /**
   * @var int
   *
   * The ID of the default workspace, which has special permission handling.
   */
  protected $defaultWorkspaceId;

  /**
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * @var \Drupal\multiversion\Workspace\WorkspaceManagerInterface
   */
  protected $workspaceManager;

  /**
   * Constructs a new EntityAccess.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\multiversion\Workspace\WorkspaceManagerInterface $workspace_manager
   *   The workspace manager service.
   * @param int $default_workspace
   *   The ID of the default workspace.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager, $default_workspace) {
    $this->entityTypeManager = $entity_type_manager;
    $this->workspaceManager = $workspace_manager;
    $this->defaultWorkspaceId = $default_workspace;
  }

  /**
   * Hook bridge.
   *
   * @see hook_entity_access()
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   * @param string $operation
   * @param \Drupal\Core\Session\AccountInterface $account
   *
   * @return \Drupal\Core\Access\AccessResult
   */
  public function entityAccess(EntityInterface $entity, $operation, AccountInterface $account) {

    // Workspaces themselves are handled by another hook. Ignore them here.
    if ($entity
      ->getEntityTypeId() == 'workspace') {
      return AccessResult::neutral();
    }
    return $this
      ->bypassAccessResult($account);
  }

  /**
   * Hook bridge.
   *
   * @see hook_entity_create_access()
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   * @param array $context
   * @param $entity_bundle
   *
   * @return \Drupal\Core\Access\AccessResult
   */
  public function entityCreateAccess(AccountInterface $account, array $context, $entity_bundle) {

    // Workspaces themselves are handled by another hook. Ignore them here.
    if ($entity_bundle == 'workspace') {
      return AccessResult::neutral();
    }
    return $this
      ->bypassAccessResult($account);
  }

  /**
   * @param \Drupal\Core\Session\AccountInterface $account
   * @return \Drupal\Core\Access\AccessResult
   */
  protected function bypassAccessResult(AccountInterface $account) {

    // This approach assumes that the current "global" active workspace is
    // correct, ie, if you're "in" a given workspace then you get ALL THE PERMS
    // to ALL THE THINGS! That's why this is a dangerous permission.
    $active_workspace = $this->workspaceManager
      ->getActiveWorkspace();
    return AccessResult::allowedIfHasPermission($account, 'bypass_entity_access_workspace_' . $active_workspace
      ->id())
      ->orIf(AccessResult::allowedIf($active_workspace
      ->getOwnerId() == $account
      ->id())
      ->andIf(AccessResult::allowedIfHasPermission($account, 'bypass_entity_access_own_workspace')));
  }

  /**
   * Hook bridge.
   *
   * @see hook_entity_access()
   * @see hook_ENTITY_TYPE_access()
   *
   * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
   * @param string $operation
   * @param \Drupal\Core\Session\AccountInterface $account
   *
   * @return \Drupal\Core\Access\AccessResult
   */
  public function workspaceAccess(WorkspaceInterface $workspace, $operation, AccountInterface $account) {
    $operations = [
      'view' => [
        'any' => 'view_any_workspace',
        'own' => 'view_own_workspace',
      ],
      'update' => [
        'any' => 'edit_any_workspace',
        'own' => 'edit_own_workspace',
      ],
      'delete' => [
        'any' => 'delete_any_workspace',
        'own' => 'delete_own_workspace',
      ],
    ];
    $route = \Drupal::request()->attributes
      ->get('_route');

    // The default workspace is always viewable, no matter what.
    $result = AccessResult::allowedIf($operation == 'view' && $workspace
      ->id() == $this->defaultWorkspaceId)
      ->orIf(AccessResult::allowedIf($route == 'system.cron'))
      ->orIf(AccessResult::allowedIf($route == 'system.run_cron'))
      ->orIf(AccessResult::allowedIf($route == '<none>'))
      ->orIf(AccessResult::allowedIfHasPermission($account, $operations[$operation]['any']))
      ->orIf(AccessResult::allowedIf($workspace
      ->getOwnerId() == $account
      ->id())
      ->andIf(AccessResult::allowedIfHasPermission($account, $operations[$operation]['own'])))
      ->orIf(AccessResult::allowedIfHasPermission($account, $operation . '_workspace_' . $workspace
      ->id()))
      ->orIf(AccessResult::forbiddenIf($operation == 'delete' && in_array($workspace
      ->id(), [
      $this->workspaceManager
        ->getActiveWorkspaceId(),
      $this->defaultWorkspaceId,
    ])));
    return $result;
  }

  /**
   * Hook bridge.
   *
   * @see hook_create_access()
   * @see hook_ENTITY_TYPE_create_access()
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   * @param array $context
   * @param $entity_bundle
   *
   * @return \Drupal\Core\Access\AccessResult
   */
  public function workspaceCreateAccess(AccountInterface $account, array $context, $entity_bundle) {
    return AccessResult::allowedIfHasPermission($account, 'create_workspace');
  }

  /**
   * Returns an array of workspace-specific permissions.
   *
   * Note: This approach assumes that a site will have only a small number
   * of workspace entities, under a dozen. If there are many dozens of
   * workspaces defined then this approach will have scaling issues.
   *
   * @return array
   *   The workspace permissions.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  public function workspacePermissions() {
    $perms = [];
    foreach ($this
      ->getAllWorkspaces() as $workspace) {
      $perms += $this
        ->createWorkspaceViewPermission($workspace) + $this
        ->createWorkspaceEditPermission($workspace) + $this
        ->createWorkspaceDeletePermission($workspace) + $this
        ->createWorkspaceBypassPermission($workspace);
    }
    return $perms;
  }

  /**
   * Returns a list of all workspace entities in the system.
   *
   * @return \Drupal\multiversion\Entity\WorkspaceInterface[]
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  protected function getAllWorkspaces() {
    return $this->entityTypeManager
      ->getStorage('workspace')
      ->loadMultiple();
  }

  /**
   * Derives the view permission for a specific workspace.
   *
   * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
   *   The workspace from which to derive the permission.
   *
   * @return array
   *   A single-item array with the permission to define.
   */
  protected function createWorkspaceViewPermission(WorkspaceInterface $workspace) {
    $perms['view_workspace_' . $workspace
      ->id()] = [
      'title' => $this
        ->t('View the %workspace workspace', [
        '%workspace' => $workspace
          ->label(),
      ]),
      'description' => $this
        ->t('View the %workspace workspace and content within it', [
        '%workspace' => $workspace
          ->label(),
      ]),
    ];
    return $perms;
  }

  /**
   * Derives the edit permission for a specific workspace.
   *
   * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
   *   The workspace from which to derive the permission.
   *
   * @return array
   *   A single-item array with the permission to define.
   */
  protected function createWorkspaceEditPermission(WorkspaceInterface $workspace) {
    $perms['update_workspace_' . $workspace
      ->id()] = [
      'title' => $this
        ->t('Edit the %workspace workspace', [
        '%workspace' => $workspace
          ->label(),
      ]),
      'description' => $this
        ->t('Edit the %workspace workspace itself', [
        '%workspace' => $workspace
          ->label(),
      ]),
    ];
    return $perms;
  }

  /**
   * Derives the delete permission for a specific workspace.
   *
   * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
   *   The workspace from which to derive the permission.
   *
   * @return array
   *   A single-item array with the permission to define.
   */
  protected function createWorkspaceDeletePermission(WorkspaceInterface $workspace) {
    $perms['delete_workspace_' . $workspace
      ->id()] = [
      'title' => $this
        ->t('Delete the %workspace workspace', [
        '%workspace' => $workspace
          ->label(),
      ]),
      'description' => $this
        ->t('View the %workspace workspace and all content within it', [
        '%workspace' => $workspace
          ->label(),
      ]),
    ];
    return $perms;
  }

  /**
   * Derives the delete permission for a specific workspace.
   *
   * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
   *   The workspace from which to derive the permission.
   *
   * @return array
   *   A single-item array with the permission to define.
   */
  protected function createWorkspaceBypassPermission(WorkspaceInterface $workspace) {
    $perms['bypass_entity_access_workspace_' . $workspace
      ->id()] = [
      'title' => $this
        ->t('Bypass content entity access in %workspace workspace', [
        '%workspace' => $workspace
          ->label(),
      ]),
      'description' => $this
        ->t('Allow all Edit/Update/Delete permissions for all content in the %workspace workspace', [
        '%workspace' => $workspace
          ->label(),
      ]),
      'restrict access' => TRUE,
    ];
    return $perms;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
EntityAccess::$defaultWorkspaceId protected property The ID of the default workspace, which has special permission handling.
EntityAccess::$entityTypeManager protected property
EntityAccess::$workspaceManager protected property
EntityAccess::bypassAccessResult protected function
EntityAccess::createWorkspaceBypassPermission protected function Derives the delete permission for a specific workspace.
EntityAccess::createWorkspaceDeletePermission protected function Derives the delete permission for a specific workspace.
EntityAccess::createWorkspaceEditPermission protected function Derives the edit permission for a specific workspace.
EntityAccess::createWorkspaceViewPermission protected function Derives the view permission for a specific workspace.
EntityAccess::entityAccess public function Hook bridge.
EntityAccess::entityCreateAccess public function Hook bridge.
EntityAccess::getAllWorkspaces protected function Returns a list of all workspace entities in the system.
EntityAccess::workspaceAccess public function Hook bridge.
EntityAccess::workspaceCreateAccess public function Hook bridge.
EntityAccess::workspacePermissions public function Returns an array of workspace-specific permissions.
EntityAccess::__construct public function Constructs a new EntityAccess.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.