annotate core/modules/media/src/Access/MediaRevisionAccessCheck.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\media\Access;
Chris@0 4
Chris@0 5 use Drupal\Core\Access\AccessResult;
Chris@0 6 use Drupal\Core\Entity\EntityTypeManagerInterface;
Chris@0 7 use Drupal\Core\Routing\Access\AccessInterface;
Chris@0 8 use Drupal\Core\Session\AccountInterface;
Chris@0 9 use Drupal\media\MediaInterface;
Chris@0 10 use Symfony\Component\Routing\Route;
Chris@0 11
Chris@0 12 /**
Chris@0 13 * Provides an access checker for media item revisions.
Chris@0 14 *
Chris@0 15 * @ingroup media_access
Chris@0 16 */
Chris@0 17 class MediaRevisionAccessCheck implements AccessInterface {
Chris@0 18
Chris@0 19 /**
Chris@0 20 * The media storage.
Chris@0 21 *
Chris@0 22 * @var \Drupal\Core\Entity\ContentEntityStorageInterface
Chris@0 23 */
Chris@0 24 protected $mediaStorage;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * The media access control handler.
Chris@0 28 *
Chris@0 29 * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
Chris@0 30 */
Chris@0 31 protected $mediaAccess;
Chris@0 32
Chris@0 33 /**
Chris@0 34 * A static cache of access checks.
Chris@0 35 *
Chris@0 36 * @var array
Chris@0 37 */
Chris@0 38 protected $access = [];
Chris@0 39
Chris@0 40 /**
Chris@0 41 * Constructs a new MediaRevisionAccessCheck.
Chris@0 42 *
Chris@0 43 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
Chris@0 44 * The entity type manager.
Chris@0 45 */
Chris@0 46 public function __construct(EntityTypeManagerInterface $entity_type_manager) {
Chris@0 47 $this->mediaStorage = $entity_type_manager->getStorage('media');
Chris@0 48 $this->mediaAccess = $entity_type_manager->getAccessControlHandler('media');
Chris@0 49 }
Chris@0 50
Chris@0 51 /**
Chris@0 52 * Checks routing access for the media item revision.
Chris@0 53 *
Chris@0 54 * @param \Symfony\Component\Routing\Route $route
Chris@0 55 * The route to check against.
Chris@0 56 * @param \Drupal\Core\Session\AccountInterface $account
Chris@0 57 * The currently logged in account.
Chris@0 58 * @param int $media_revision
Chris@0 59 * (optional) The media item revision ID. If not specified, but $media is,
Chris@0 60 * access is checked for that object's revision.
Chris@0 61 * @param \Drupal\media\MediaInterface $media
Chris@0 62 * (optional) A media item. Used for checking access to a media items
Chris@0 63 * default revision when $media_revision is unspecified. Ignored when
Chris@0 64 * $media_revision is specified. If neither $media_revision nor $media are
Chris@0 65 * specified, then access is denied.
Chris@0 66 *
Chris@0 67 * @return \Drupal\Core\Access\AccessResultInterface
Chris@0 68 * The access result.
Chris@0 69 */
Chris@0 70 public function access(Route $route, AccountInterface $account, $media_revision = NULL, MediaInterface $media = NULL) {
Chris@0 71 if ($media_revision) {
Chris@0 72 $media = $this->mediaStorage->loadRevision($media_revision);
Chris@0 73 }
Chris@0 74 $operation = $route->getRequirement('_access_media_revision');
Chris@0 75 return AccessResult::allowedIf($media && $this->checkAccess($media, $account, $operation))->cachePerPermissions()->addCacheableDependency($media);
Chris@0 76 }
Chris@0 77
Chris@0 78 /**
Chris@0 79 * Checks media item revision access.
Chris@0 80 *
Chris@0 81 * @param \Drupal\media\MediaInterface $media
Chris@0 82 * The media item to check.
Chris@0 83 * @param \Drupal\Core\Session\AccountInterface $account
Chris@0 84 * A user object representing the user for whom the operation is to be
Chris@0 85 * performed.
Chris@0 86 * @param string $op
Chris@0 87 * (optional) The specific operation being checked. Defaults to 'view'.
Chris@0 88 *
Chris@0 89 * @return bool
Chris@0 90 * TRUE if the operation may be performed, FALSE otherwise.
Chris@0 91 */
Chris@0 92 public function checkAccess(MediaInterface $media, AccountInterface $account, $op = 'view') {
Chris@0 93 if (!$media || $op !== 'view') {
Chris@0 94 // If there was no media to check against, or the $op was not one of the
Chris@0 95 // supported ones, we return access denied.
Chris@0 96 return FALSE;
Chris@0 97 }
Chris@0 98
Chris@0 99 // Statically cache access by revision ID, language code, user account ID,
Chris@0 100 // and operation.
Chris@0 101 $langcode = $media->language()->getId();
Chris@0 102 $cid = $media->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $op;
Chris@0 103
Chris@0 104 if (!isset($this->access[$cid])) {
Chris@0 105 // Perform basic permission checks first.
Chris@0 106 if (!$account->hasPermission('view all media revisions') && !$account->hasPermission('administer media')) {
Chris@0 107 $this->access[$cid] = FALSE;
Chris@0 108 return FALSE;
Chris@0 109 }
Chris@0 110
Chris@0 111 // There should be at least two revisions. If the revision ID of the
Chris@0 112 // given media item and the revision ID of the default revision differ,
Chris@0 113 // then we already have two different revisions so there is no need for a
Chris@0 114 // separate database check.
Chris@0 115 if ($media->isDefaultRevision() && ($this->countDefaultLanguageRevisions($media) == 1)) {
Chris@0 116 $this->access[$cid] = FALSE;
Chris@0 117 }
Chris@0 118 elseif ($account->hasPermission('administer media')) {
Chris@0 119 $this->access[$cid] = TRUE;
Chris@0 120 }
Chris@0 121 else {
Chris@0 122 // First check the access to the default revision and finally, if the
Chris@0 123 // media passed in is not the default revision then access to that, too.
Chris@0 124 $this->access[$cid] = $this->mediaAccess->access($this->mediaStorage->load($media->id()), $op, $account) && ($media->isDefaultRevision() || $this->mediaAccess->access($media, $op, $account));
Chris@0 125 }
Chris@0 126 }
Chris@0 127
Chris@0 128 return $this->access[$cid];
Chris@0 129 }
Chris@0 130
Chris@0 131 /**
Chris@0 132 * Counts the number of revisions in the default language.
Chris@0 133 *
Chris@0 134 * @param \Drupal\media\MediaInterface $media
Chris@0 135 * The media item for which to to count the revisions.
Chris@0 136 *
Chris@0 137 * @return int
Chris@0 138 * The number of revisions in the default language.
Chris@0 139 */
Chris@0 140 protected function countDefaultLanguageRevisions(MediaInterface $media) {
Chris@0 141 $entity_type = $media->getEntityType();
Chris@0 142 $count = $this->mediaStorage->getQuery()
Chris@0 143 ->allRevisions()
Chris@0 144 ->condition($entity_type->getKey('id'), $media->id())
Chris@0 145 ->condition($entity_type->getKey('default_langcode'), 1)
Chris@0 146 ->count()
Chris@0 147 ->execute();
Chris@0 148 return $count;
Chris@0 149 }
Chris@0 150
Chris@0 151 }