3 namespace Drupal\node\Cache;
5 use Drupal\Core\Cache\CacheableMetadata;
6 use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
7 use Drupal\Core\Cache\Context\UserCacheContextBase;
10 * Defines the node access view cache context service.
12 * Cache context ID: 'user.node_grants' (to vary by all operations' grants).
13 * Calculated cache context ID: 'user.node_grants:%operation', e.g.
14 * 'user.node_grants:view' (to vary by the view operation's grants).
16 * This allows for node access grants-sensitive caching when listing nodes.
18 * @see node_query_node_access_alter()
19 * @ingroup node_access
21 class NodeAccessGrantsCacheContext extends UserCacheContextBase implements CalculatedCacheContextInterface {
26 public static function getLabel() {
27 return t("Content access view grants");
33 public function getContext($operation = NULL) {
34 // If the current user either can bypass node access then we don't need to
35 // determine the exact node grants for the current user.
36 if ($this->user->hasPermission('bypass node access')) {
40 // When no specific operation is specified, check the grants for all three
41 // possible operations.
42 if ($operation === NULL) {
44 foreach (['view', 'update', 'delete'] as $op) {
45 $result[] = $this->checkNodeGrants($op);
47 return implode('-', $result);
50 return $this->checkNodeGrants($operation);
55 * Checks the node grants for the given operation.
57 * @param string $operation
58 * The operation to check the node grants for.
61 * The string representation of the cache context.
63 protected function checkNodeGrants($operation) {
64 // When checking the grants for the 'view' operation and the current user
65 // has a global view grant (i.e. a view grant for node ID 0) — note that
66 // this is automatically the case if no node access modules exist (no
67 // hook_node_grants() implementations) then we don't need to determine the
68 // exact node view grants for the current user.
69 if ($operation === 'view' && node_access_view_all_nodes($this->user)) {
73 $grants = node_access_grants($operation, $this->user);
74 $grants_context_parts = [];
75 foreach ($grants as $realm => $gids) {
76 $grants_context_parts[] = $realm . ':' . implode(',', $gids);
78 return $operation . '.' . implode(';', $grants_context_parts);
84 public function getCacheableMetadata($operation = NULL) {
85 $cacheable_metadata = new CacheableMetadata();
87 if (!\Drupal::moduleHandler()->getImplementations('node_grants')) {
88 return $cacheable_metadata;
91 // The node grants may change if the user is updated. (The max-age is set to
92 // zero below, but sites may override this cache context, and change it to a
93 // non-zero value. In such cases, this cache tag is needed for correctness.)
94 $cacheable_metadata->setCacheTags(['user:' . $this->user->id()]);
96 // If the site is using node grants, this cache context can not be
98 return $cacheable_metadata->setCacheMaxAge(0);