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 }
|