Version 1
[yaffs-website] / web / core / modules / node / src / Cache / NodeAccessGrantsCacheContext.php
1 <?php
2
3 namespace Drupal\node\Cache;
4
5 use Drupal\Core\Cache\CacheableMetadata;
6 use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
7 use Drupal\Core\Cache\Context\UserCacheContextBase;
8
9 /**
10  * Defines the node access view cache context service.
11  *
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).
15  *
16  * This allows for node access grants-sensitive caching when listing nodes.
17  *
18  * @see node_query_node_access_alter()
19  * @ingroup node_access
20  */
21 class NodeAccessGrantsCacheContext extends UserCacheContextBase implements CalculatedCacheContextInterface {
22
23   /**
24    * {@inheritdoc}
25    */
26   public static function getLabel() {
27     return t("Content access view grants");
28   }
29
30   /**
31    * {@inheritdoc}
32    */
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')) {
37       return 'all';
38     }
39
40     // When no specific operation is specified, check the grants for all three
41     // possible operations.
42     if ($operation === NULL) {
43       $result = [];
44       foreach (['view', 'update', 'delete'] as $op) {
45         $result[] = $this->checkNodeGrants($op);
46       }
47       return implode('-', $result);
48     }
49     else {
50       return $this->checkNodeGrants($operation);
51     }
52   }
53
54   /**
55    * Checks the node grants for the given operation.
56    *
57    * @param string $operation
58    *   The operation to check the node grants for.
59    *
60    * @return string
61    *   The string representation of the cache context.
62    */
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)) {
70       return 'view.all';
71     }
72
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);
77     }
78     return $operation . '.' . implode(';', $grants_context_parts);
79   }
80
81   /**
82    * {@inheritdoc}
83    */
84   public function getCacheableMetadata($operation = NULL) {
85     $cacheable_metadata = new CacheableMetadata();
86
87     if (!\Drupal::moduleHandler()->getImplementations('node_grants')) {
88       return $cacheable_metadata;
89     }
90
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()]);
95
96     // If the site is using node grants, this cache context can not be
97     // optimized.
98     return $cacheable_metadata->setCacheMaxAge(0);
99   }
100
101 }