a8a0bc6241e03a41ccbc64452f742293547ab676
[yaffs-website] / web / core / modules / node / src / NodeAccessControlHandler.php
1 <?php
2
3 namespace Drupal\node;
4
5 use Drupal\Core\Access\AccessResult;
6 use Drupal\Core\Entity\EntityHandlerInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Field\FieldDefinitionInterface;
9 use Drupal\Core\Field\FieldItemListInterface;
10 use Drupal\Core\Entity\EntityAccessControlHandler;
11 use Drupal\Core\Entity\EntityInterface;
12 use Drupal\Core\Session\AccountInterface;
13 use Symfony\Component\DependencyInjection\ContainerInterface;
14
15 /**
16  * Defines the access control handler for the node entity type.
17  *
18  * @see \Drupal\node\Entity\Node
19  * @ingroup node_access
20  */
21 class NodeAccessControlHandler extends EntityAccessControlHandler implements NodeAccessControlHandlerInterface, EntityHandlerInterface {
22
23   /**
24    * The node grant storage.
25    *
26    * @var \Drupal\node\NodeGrantDatabaseStorageInterface
27    */
28   protected $grantStorage;
29
30   /**
31    * Constructs a NodeAccessControlHandler object.
32    *
33    * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
34    *   The entity type definition.
35    * @param \Drupal\node\NodeGrantDatabaseStorageInterface $grant_storage
36    *   The node grant storage.
37    */
38   public function __construct(EntityTypeInterface $entity_type, NodeGrantDatabaseStorageInterface $grant_storage) {
39     parent::__construct($entity_type);
40     $this->grantStorage = $grant_storage;
41   }
42
43   /**
44    * {@inheritdoc}
45    */
46   public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
47     return new static(
48       $entity_type,
49       $container->get('node.grant_storage')
50     );
51   }
52
53
54   /**
55    * {@inheritdoc}
56    */
57   public function access(EntityInterface $entity, $operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
58     $account = $this->prepareUser($account);
59
60     if ($account->hasPermission('bypass node access')) {
61       $result = AccessResult::allowed()->cachePerPermissions();
62       return $return_as_object ? $result : $result->isAllowed();
63     }
64     if (!$account->hasPermission('access content')) {
65       $result = AccessResult::forbidden("The 'access content' permission is required.")->cachePerPermissions();
66       return $return_as_object ? $result : $result->isAllowed();
67     }
68     $result = parent::access($entity, $operation, $account, TRUE)->cachePerPermissions();
69
70     return $return_as_object ? $result : $result->isAllowed();
71   }
72
73   /**
74    * {@inheritdoc}
75    */
76   public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
77     $account = $this->prepareUser($account);
78
79     if ($account->hasPermission('bypass node access')) {
80       $result = AccessResult::allowed()->cachePerPermissions();
81       return $return_as_object ? $result : $result->isAllowed();
82     }
83     if (!$account->hasPermission('access content')) {
84       $result = AccessResult::forbidden()->cachePerPermissions();
85       return $return_as_object ? $result : $result->isAllowed();
86     }
87
88     $result = parent::createAccess($entity_bundle, $account, $context, TRUE)->cachePerPermissions();
89     return $return_as_object ? $result : $result->isAllowed();
90   }
91
92   /**
93    * {@inheritdoc}
94    */
95   protected function checkAccess(EntityInterface $node, $operation, AccountInterface $account) {
96     /** @var \Drupal\node\NodeInterface $node */
97
98     // Fetch information from the node object if possible.
99     $status = $node->isPublished();
100     $uid = $node->getOwnerId();
101
102     // Check if authors can view their own unpublished nodes.
103     if ($operation === 'view' && !$status && $account->hasPermission('view own unpublished content') && $account->isAuthenticated() && $account->id() == $uid) {
104       return AccessResult::allowed()->cachePerPermissions()->cachePerUser()->addCacheableDependency($node);
105     }
106
107     // Evaluate node grants.
108     return $this->grantStorage->access($node, $operation, $account);
109   }
110
111   /**
112    * {@inheritdoc}
113    */
114   protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
115     return AccessResult::allowedIf($account->hasPermission('create ' . $entity_bundle . ' content'))->cachePerPermissions();
116   }
117
118   /**
119    * {@inheritdoc}
120    */
121   protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
122     // Only users with the administer nodes permission can edit administrative
123     // fields.
124     $administrative_fields = ['uid', 'status', 'created', 'promote', 'sticky'];
125     if ($operation == 'edit' && in_array($field_definition->getName(), $administrative_fields, TRUE)) {
126       return AccessResult::allowedIfHasPermission($account, 'administer nodes');
127     }
128
129     // No user can change read only fields.
130     $read_only_fields = ['revision_timestamp', 'revision_uid'];
131     if ($operation == 'edit' && in_array($field_definition->getName(), $read_only_fields, TRUE)) {
132       return AccessResult::forbidden();
133     }
134
135     // Users have access to the revision_log field either if they have
136     // administrative permissions or if the new revision option is enabled.
137     if ($operation == 'edit' && $field_definition->getName() == 'revision_log') {
138       if ($account->hasPermission('administer nodes')) {
139         return AccessResult::allowed()->cachePerPermissions();
140       }
141       return AccessResult::allowedIf($items->getEntity()->type->entity->isNewRevision())->cachePerPermissions();
142     }
143     return parent::checkFieldAccess($operation, $field_definition, $account, $items);
144   }
145
146   /**
147    * {@inheritdoc}
148    */
149   public function acquireGrants(NodeInterface $node) {
150     $grants = $this->moduleHandler->invokeAll('node_access_records', [$node]);
151     // Let modules alter the grants.
152     $this->moduleHandler->alter('node_access_records', $grants, $node);
153     // If no grants are set and the node is published, then use the default grant.
154     if (empty($grants) && $node->isPublished()) {
155       $grants[] = ['realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0];
156     }
157     return $grants;
158   }
159
160   /**
161    * {@inheritdoc}
162    */
163   public function writeGrants(NodeInterface $node, $delete = TRUE) {
164     $grants = $this->acquireGrants($node);
165     $this->grantStorage->write($node, $grants, NULL, $delete);
166   }
167
168   /**
169    * {@inheritdoc}
170    */
171   public function writeDefaultGrant() {
172     $this->grantStorage->writeDefault();
173   }
174
175   /**
176    * {@inheritdoc}
177    */
178   public function deleteGrants() {
179     $this->grantStorage->delete();
180   }
181
182   /**
183    * {@inheritdoc}
184    */
185   public function countGrants() {
186     return $this->grantStorage->count();
187   }
188
189   /**
190    * {@inheritdoc}
191    */
192   public function checkAllGrants(AccountInterface $account) {
193     return $this->grantStorage->checkAll($account);
194   }
195
196 }