mediaStorage = $entity_type_manager->getStorage('media'); $this->mediaAccess = $entity_type_manager->getAccessControlHandler('media'); } /** * Checks routing access for the media item revision. * * @param \Symfony\Component\Routing\Route $route * The route to check against. * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. * @param int $media_revision * (optional) The media item revision ID. If not specified, but $media is, * access is checked for that object's revision. * @param \Drupal\media\MediaInterface $media * (optional) A media item. Used for checking access to a media items * default revision when $media_revision is unspecified. Ignored when * $media_revision is specified. If neither $media_revision nor $media are * specified, then access is denied. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ public function access(Route $route, AccountInterface $account, $media_revision = NULL, MediaInterface $media = NULL) { if ($media_revision) { $media = $this->mediaStorage->loadRevision($media_revision); } $operation = $route->getRequirement('_access_media_revision'); return AccessResult::allowedIf($media && $this->checkAccess($media, $account, $operation))->cachePerPermissions()->addCacheableDependency($media); } /** * Checks media item revision access. * * @param \Drupal\media\MediaInterface $media * The media item to check. * @param \Drupal\Core\Session\AccountInterface $account * A user object representing the user for whom the operation is to be * performed. * @param string $op * (optional) The specific operation being checked. Defaults to 'view'. * * @return bool * TRUE if the operation may be performed, FALSE otherwise. */ public function checkAccess(MediaInterface $media, AccountInterface $account, $op = 'view') { if (!$media || $op !== 'view') { // If there was no media to check against, or the $op was not one of the // supported ones, we return access denied. return FALSE; } // Statically cache access by revision ID, language code, user account ID, // and operation. $langcode = $media->language()->getId(); $cid = $media->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $op; if (!isset($this->access[$cid])) { // Perform basic permission checks first. if (!$account->hasPermission('view all media revisions') && !$account->hasPermission('administer media')) { $this->access[$cid] = FALSE; return FALSE; } // There should be at least two revisions. If the revision ID of the // given media item and the revision ID of the default revision differ, // then we already have two different revisions so there is no need for a // separate database check. if ($media->isDefaultRevision() && ($this->countDefaultLanguageRevisions($media) == 1)) { $this->access[$cid] = FALSE; } elseif ($account->hasPermission('administer media')) { $this->access[$cid] = TRUE; } else { // First check the access to the default revision and finally, if the // media passed in is not the default revision then access to that, too. $this->access[$cid] = $this->mediaAccess->access($this->mediaStorage->load($media->id()), $op, $account) && ($media->isDefaultRevision() || $this->mediaAccess->access($media, $op, $account)); } } return $this->access[$cid]; } /** * Counts the number of revisions in the default language. * * @param \Drupal\media\MediaInterface $media * The media item for which to to count the revisions. * * @return int * The number of revisions in the default language. */ protected function countDefaultLanguageRevisions(MediaInterface $media) { $entity_type = $media->getEntityType(); $count = $this->mediaStorage->getQuery() ->allRevisions() ->condition($entity_type->getKey('id'), $media->id()) ->condition($entity_type->getKey('default_langcode'), 1) ->count() ->execute(); return $count; } }