3 namespace Drupal\media\Access;
5 use Drupal\Core\Access\AccessResult;
6 use Drupal\Core\Entity\EntityTypeManagerInterface;
7 use Drupal\Core\Routing\Access\AccessInterface;
8 use Drupal\Core\Session\AccountInterface;
9 use Drupal\media\MediaInterface;
10 use Symfony\Component\Routing\Route;
13 * Provides an access checker for media item revisions.
15 * @ingroup media_access
17 class MediaRevisionAccessCheck implements AccessInterface {
22 * @var \Drupal\Core\Entity\ContentEntityStorageInterface
24 protected $mediaStorage;
27 * The media access control handler.
29 * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
31 protected $mediaAccess;
34 * A static cache of access checks.
38 protected $access = [];
41 * Constructs a new MediaRevisionAccessCheck.
43 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
44 * The entity type manager.
46 public function __construct(EntityTypeManagerInterface $entity_type_manager) {
47 $this->mediaStorage = $entity_type_manager->getStorage('media');
48 $this->mediaAccess = $entity_type_manager->getAccessControlHandler('media');
52 * Checks routing access for the media item revision.
54 * @param \Symfony\Component\Routing\Route $route
55 * The route to check against.
56 * @param \Drupal\Core\Session\AccountInterface $account
57 * The currently logged in account.
58 * @param int $media_revision
59 * (optional) The media item revision ID. If not specified, but $media is,
60 * access is checked for that object's revision.
61 * @param \Drupal\media\MediaInterface $media
62 * (optional) A media item. Used for checking access to a media items
63 * default revision when $media_revision is unspecified. Ignored when
64 * $media_revision is specified. If neither $media_revision nor $media are
65 * specified, then access is denied.
67 * @return \Drupal\Core\Access\AccessResultInterface
70 public function access(Route $route, AccountInterface $account, $media_revision = NULL, MediaInterface $media = NULL) {
71 if ($media_revision) {
72 $media = $this->mediaStorage->loadRevision($media_revision);
74 $operation = $route->getRequirement('_access_media_revision');
75 return AccessResult::allowedIf($media && $this->checkAccess($media, $account, $operation))->cachePerPermissions()->addCacheableDependency($media);
79 * Checks media item revision access.
81 * @param \Drupal\media\MediaInterface $media
82 * The media item to check.
83 * @param \Drupal\Core\Session\AccountInterface $account
84 * A user object representing the user for whom the operation is to be
87 * (optional) The specific operation being checked. Defaults to 'view'.
90 * TRUE if the operation may be performed, FALSE otherwise.
92 public function checkAccess(MediaInterface $media, AccountInterface $account, $op = 'view') {
93 if (!$media || $op !== 'view') {
94 // If there was no media to check against, or the $op was not one of the
95 // supported ones, we return access denied.
99 // Statically cache access by revision ID, language code, user account ID,
101 $langcode = $media->language()->getId();
102 $cid = $media->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $op;
104 if (!isset($this->access[$cid])) {
105 // Perform basic permission checks first.
106 if (!$account->hasPermission('view all media revisions') && !$account->hasPermission('administer media')) {
107 $this->access[$cid] = FALSE;
111 // There should be at least two revisions. If the revision ID of the
112 // given media item and the revision ID of the default revision differ,
113 // then we already have two different revisions so there is no need for a
114 // separate database check.
115 if ($media->isDefaultRevision() && ($this->countDefaultLanguageRevisions($media) == 1)) {
116 $this->access[$cid] = FALSE;
118 elseif ($account->hasPermission('administer media')) {
119 $this->access[$cid] = TRUE;
122 // First check the access to the default revision and finally, if the
123 // media passed in is not the default revision then access to that, too.
124 $this->access[$cid] = $this->mediaAccess->access($this->mediaStorage->load($media->id()), $op, $account) && ($media->isDefaultRevision() || $this->mediaAccess->access($media, $op, $account));
128 return $this->access[$cid];
132 * Counts the number of revisions in the default language.
134 * @param \Drupal\media\MediaInterface $media
135 * The media item for which to to count the revisions.
138 * The number of revisions in the default language.
140 protected function countDefaultLanguageRevisions(MediaInterface $media) {
141 $entity_type = $media->getEntityType();
142 $count = $this->mediaStorage->getQuery()
144 ->condition($entity_type->getKey('id'), $media->id())
145 ->condition($entity_type->getKey('default_langcode'), 1)