3 namespace Drupal\permissions_by_term\Service;
5 use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
6 use Drupal\Core\Access\AccessResult;
7 use Drupal\Core\Database\Connection;
8 use Drupal\permissions_by_term\Event\PermissionsByTermDeniedEvent;
9 use Drupal\user\Entity\User;
10 use Drupal\taxonomy\Entity\Term;
13 * AccessCheckService class.
18 * The database connection.
20 * @var \Drupal\Core\Database\Connection
25 * @var ContainerAwareEventDispatcher
27 private $eventDispatcher;
30 * Constructs AccessCheck object.
32 * @param Connection $database
33 * The database connection.
35 public function __construct(Connection $database, ContainerAwareEventDispatcher $eventDispatcher) {
36 $this->database = $database;
37 $this->eventDispatcher = $eventDispatcher;
43 * @param string $langcode
47 public function canUserAccessByNodeId($nid, $uid = FALSE, $langcode = '') {
48 $langcode = ($langcode === '') ? \Drupal::languageManager()->getCurrentLanguage()->getId() : $langcode;
50 if (\Drupal::currentUser()->hasPermission('bypass node access')) {
54 if (!$singleTermRestriction = \Drupal::config('permissions_by_term.settings.single_term_restriction')->get('value')) {
55 $access_allowed = TRUE;
57 $access_allowed = FALSE;
60 $terms = $this->database
61 ->query("SELECT tid FROM {taxonomy_index} WHERE nid = :nid",
62 [':nid' => $nid])->fetchAll();
68 foreach ($terms as $term) {
69 $termInfo = Term::load($term->tid);
71 if ($termInfo instanceof Term && $termInfo->get('langcode')->getLangcode() == $langcode) {
72 $access_allowed = $this->isAccessAllowedByDatabase($term->tid, $uid, $termInfo->get('langcode')->getLangcode());
73 if (!$access_allowed) {
74 if ($singleTermRestriction) {
75 return $access_allowed;
79 if ($access_allowed && !$singleTermRestriction) {
80 return $access_allowed;
86 return $access_allowed;
91 * @param bool|int $uid
92 * @param string $langcode
95 public function isAccessAllowedByDatabase($tid, $uid = FALSE, $langcode = '') {
96 $langcode = ($langcode === '') ? \Drupal::languageManager()->getCurrentLanguage()->getId() : $langcode;
98 if ($uid === FALSE || (int) $uid === 0) {
99 $user = \Drupal::currentUser();
100 } elseif (is_numeric($uid)) {
101 $user = User::load($uid);
106 if (!$this->isAnyPermissionSetForTerm($tid, $langcode)) {
110 /* At this point permissions are enabled, check to see if this user or one
111 * of their roles is allowed.
113 $aUserRoles = $user->getRoles();
115 foreach ($aUserRoles as $sUserRole) {
117 if ($this->isTermAllowedByUserRole($tid, $sUserRole, $langcode)) {
123 $iUid = intval($user->id());
125 if ($this->isTermAllowedByUserId($tid, $iUid, $langcode)) {
136 * @param string $langcode
140 private function isTermAllowedByUserId($tid, $iUid, $langcode) {
141 $query_result = $this->database->query("SELECT uid FROM {permissions_by_term_user} WHERE tid = :tid AND uid = :uid AND langcode = :langcode",
142 [':tid' => $tid, ':uid' => $iUid, ':langcode' => $langcode])->fetchField();
144 if (!empty($query_result)) {
154 * @param string $sUserRole
155 * @param string $langcode
159 public function isTermAllowedByUserRole($tid, $sUserRole, $langcode) {
160 $query_result = $this->database->query("SELECT rid FROM {permissions_by_term_role} WHERE tid = :tid AND rid IN (:user_roles) AND langcode = :langcode",
161 [':tid' => $tid, ':user_roles' => $sUserRole, ':langcode' => $langcode])->fetchField();
163 if (!empty($query_result)) {
174 * @param string $langcode
178 public function isAnyPermissionSetForTerm($tid, $langcode = '') {
179 $langcode = ($langcode === '') ? \Drupal::languageManager()->getCurrentLanguage()->getId() : $langcode;
181 $iUserTableResults = intval($this->database->query("SELECT COUNT(1) FROM {permissions_by_term_user} WHERE tid = :tid AND langcode = :langcode",
182 [':tid' => $tid, ':langcode' => $langcode])->fetchField());
184 $iRoleTableResults = intval($this->database->query("SELECT COUNT(1) FROM {permissions_by_term_role} WHERE tid = :tid AND langcode = :langcode",
185 [':tid' => $tid, ':langcode' => $langcode])->fetchField());
187 if ($iUserTableResults > 0 ||
188 $iRoleTableResults > 0) {
195 * @param string $nodeId
196 * @param string $langcode
198 * @return AccessResult
200 public function handleNode($nodeId, $langcode) {
201 if ($this->canUserAccessByNodeId($nodeId, false, $langcode) === TRUE) {
202 return AccessResult::neutral();
205 $accessDeniedEvent = new PermissionsByTermDeniedEvent($nodeId);
206 $this->eventDispatcher->dispatch(PermissionsByTermDeniedEvent::NAME, $accessDeniedEvent);
208 return AccessResult::forbidden();