Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\node\Cache;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Cache\CacheableMetadata;
|
Chris@0
|
6 use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
|
Chris@0
|
7 use Drupal\Core\Cache\Context\UserCacheContextBase;
|
Chris@0
|
8
|
Chris@0
|
9 /**
|
Chris@0
|
10 * Defines the node access view cache context service.
|
Chris@0
|
11 *
|
Chris@0
|
12 * Cache context ID: 'user.node_grants' (to vary by all operations' grants).
|
Chris@0
|
13 * Calculated cache context ID: 'user.node_grants:%operation', e.g.
|
Chris@0
|
14 * 'user.node_grants:view' (to vary by the view operation's grants).
|
Chris@0
|
15 *
|
Chris@0
|
16 * This allows for node access grants-sensitive caching when listing nodes.
|
Chris@0
|
17 *
|
Chris@0
|
18 * @see node_query_node_access_alter()
|
Chris@0
|
19 * @ingroup node_access
|
Chris@0
|
20 */
|
Chris@0
|
21 class NodeAccessGrantsCacheContext extends UserCacheContextBase implements CalculatedCacheContextInterface {
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * {@inheritdoc}
|
Chris@0
|
25 */
|
Chris@0
|
26 public static function getLabel() {
|
Chris@0
|
27 return t("Content access view grants");
|
Chris@0
|
28 }
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * {@inheritdoc}
|
Chris@0
|
32 */
|
Chris@0
|
33 public function getContext($operation = NULL) {
|
Chris@0
|
34 // If the current user either can bypass node access then we don't need to
|
Chris@0
|
35 // determine the exact node grants for the current user.
|
Chris@0
|
36 if ($this->user->hasPermission('bypass node access')) {
|
Chris@0
|
37 return 'all';
|
Chris@0
|
38 }
|
Chris@0
|
39
|
Chris@0
|
40 // When no specific operation is specified, check the grants for all three
|
Chris@0
|
41 // possible operations.
|
Chris@0
|
42 if ($operation === NULL) {
|
Chris@0
|
43 $result = [];
|
Chris@0
|
44 foreach (['view', 'update', 'delete'] as $op) {
|
Chris@0
|
45 $result[] = $this->checkNodeGrants($op);
|
Chris@0
|
46 }
|
Chris@0
|
47 return implode('-', $result);
|
Chris@0
|
48 }
|
Chris@0
|
49 else {
|
Chris@0
|
50 return $this->checkNodeGrants($operation);
|
Chris@0
|
51 }
|
Chris@0
|
52 }
|
Chris@0
|
53
|
Chris@0
|
54 /**
|
Chris@0
|
55 * Checks the node grants for the given operation.
|
Chris@0
|
56 *
|
Chris@0
|
57 * @param string $operation
|
Chris@0
|
58 * The operation to check the node grants for.
|
Chris@0
|
59 *
|
Chris@0
|
60 * @return string
|
Chris@0
|
61 * The string representation of the cache context.
|
Chris@0
|
62 */
|
Chris@0
|
63 protected function checkNodeGrants($operation) {
|
Chris@0
|
64 // When checking the grants for the 'view' operation and the current user
|
Chris@0
|
65 // has a global view grant (i.e. a view grant for node ID 0) — note that
|
Chris@0
|
66 // this is automatically the case if no node access modules exist (no
|
Chris@0
|
67 // hook_node_grants() implementations) then we don't need to determine the
|
Chris@0
|
68 // exact node view grants for the current user.
|
Chris@0
|
69 if ($operation === 'view' && node_access_view_all_nodes($this->user)) {
|
Chris@0
|
70 return 'view.all';
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 $grants = node_access_grants($operation, $this->user);
|
Chris@0
|
74 $grants_context_parts = [];
|
Chris@0
|
75 foreach ($grants as $realm => $gids) {
|
Chris@0
|
76 $grants_context_parts[] = $realm . ':' . implode(',', $gids);
|
Chris@0
|
77 }
|
Chris@0
|
78 return $operation . '.' . implode(';', $grants_context_parts);
|
Chris@0
|
79 }
|
Chris@0
|
80
|
Chris@0
|
81 /**
|
Chris@0
|
82 * {@inheritdoc}
|
Chris@0
|
83 */
|
Chris@0
|
84 public function getCacheableMetadata($operation = NULL) {
|
Chris@0
|
85 $cacheable_metadata = new CacheableMetadata();
|
Chris@0
|
86
|
Chris@0
|
87 if (!\Drupal::moduleHandler()->getImplementations('node_grants')) {
|
Chris@0
|
88 return $cacheable_metadata;
|
Chris@0
|
89 }
|
Chris@0
|
90
|
Chris@0
|
91 // The node grants may change if the user is updated. (The max-age is set to
|
Chris@0
|
92 // zero below, but sites may override this cache context, and change it to a
|
Chris@0
|
93 // non-zero value. In such cases, this cache tag is needed for correctness.)
|
Chris@0
|
94 $cacheable_metadata->setCacheTags(['user:' . $this->user->id()]);
|
Chris@0
|
95
|
Chris@0
|
96 // If the site is using node grants, this cache context can not be
|
Chris@0
|
97 // optimized.
|
Chris@0
|
98 return $cacheable_metadata->setCacheMaxAge(0);
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 }
|