Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / modules / contrib / permissions_by_term / src / Service / AccessCheck.php
1 <?php
2
3 namespace Drupal\permissions_by_term\Service;
4
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;
11
12 /**
13  * AccessCheckService class.
14  */
15 class AccessCheck {
16
17   /**
18    * The database connection.
19    *
20    * @var \Drupal\Core\Database\Connection
21    */
22   protected $database;
23
24   /**
25    * @var ContainerAwareEventDispatcher
26    */
27   private $eventDispatcher;
28
29   /**
30    * Constructs AccessCheck object.
31    *
32    * @param Connection $database
33    *   The database connection.
34    */
35   public function __construct(Connection $database, ContainerAwareEventDispatcher $eventDispatcher) {
36     $this->database  = $database;
37     $this->eventDispatcher = $eventDispatcher;
38   }
39
40   /**
41    * @param int $nid
42    * @param bool $uid
43    * @param string $langcode
44    *
45    * @return array|bool
46    */
47   public function canUserAccessByNodeId($nid, $uid = FALSE, $langcode = 'en') {
48     if (\Drupal::currentUser()->hasPermission('bypass node access')) {
49       return TRUE;
50     }
51
52     if (!$singleTermRestriction = \Drupal::config('permissions_by_term.settings.single_term_restriction')->get('value')) {
53       $access_allowed = TRUE;
54     } else {
55       $access_allowed = FALSE;
56     }
57
58     $terms = $this->database
59       ->query("SELECT tid FROM {taxonomy_index} WHERE nid = :nid",
60       [':nid' => $nid])->fetchAll();
61
62     if (empty($terms)) {
63       return TRUE;
64     }
65
66     foreach ($terms as $term) {
67       $termInfo = Term::load($term->tid);
68
69       if ($termInfo->get('langcode')->getLangcode() == $langcode) {
70         $access_allowed = $this->isAccessAllowedByDatabase($term->tid, $uid, $termInfo->get('langcode')->getLangcode());
71         if (!$access_allowed) {
72           if ($singleTermRestriction) {
73             return $access_allowed;
74           }
75         }
76
77         if ($access_allowed && !$singleTermRestriction) {
78           return $access_allowed;
79         }
80       }
81
82     }
83
84     return $access_allowed;
85   }
86
87   /**
88    * @param int      $tid
89    * @param bool|int $uid
90    * @param string   $langcode
91    * @return bool
92    */
93   public function isAccessAllowedByDatabase($tid, $uid = FALSE, $langcode = 'en') {
94
95     if ($uid === FALSE || (int) $uid === 0) {
96       $user = \Drupal::currentUser();
97     } elseif (is_numeric($uid)) {
98       $user = User::load($uid);
99     }
100
101     $tid = (int) $tid;
102
103     if (!$this->isAnyPermissionSetForTerm($tid, $langcode)) {
104       return TRUE;
105     }
106
107     /* At this point permissions are enabled, check to see if this user or one
108      * of their roles is allowed.
109      */
110     $aUserRoles = $user->getRoles();
111
112     foreach ($aUserRoles as $sUserRole) {
113
114       if ($this->isTermAllowedByUserRole($tid, $sUserRole, $langcode)) {
115         return TRUE;
116       }
117
118     }
119
120     $iUid = intval($user->id());
121
122     if ($this->isTermAllowedByUserId($tid, $iUid, $langcode)) {
123       return TRUE;
124     }
125
126     return FALSE;
127
128   }
129
130   /**
131    * @param int    $tid
132    * @param int    $iUid
133    * @param string $langcode
134    *
135    * @return bool
136    */
137   private function isTermAllowedByUserId($tid, $iUid, $langcode) {
138     $query_result = $this->database->query("SELECT uid FROM {permissions_by_term_user} WHERE tid = :tid AND uid = :uid AND langcode = :langcode",
139       [':tid' => $tid, ':uid' => $iUid, ':langcode' => $langcode])->fetchField();
140
141     if (!empty($query_result)) {
142       return TRUE;
143     }
144     else {
145       return FALSE;
146     }
147   }
148
149   /**
150    * @param int    $tid
151    * @param string $sUserRole
152    * @param string $langcode
153    *
154    * @return bool
155    */
156   public function isTermAllowedByUserRole($tid, $sUserRole, $langcode) {
157     $query_result = $this->database->query("SELECT rid FROM {permissions_by_term_role} WHERE tid = :tid AND rid IN (:user_roles) AND langcode = :langcode",
158       [':tid' => $tid, ':user_roles' => $sUserRole, ':langcode' => $langcode])->fetchField();
159
160     if (!empty($query_result)) {
161       return TRUE;
162     }
163     else {
164       return FALSE;
165     }
166
167   }
168
169   /**
170    * @param int    $tid
171    * @param string $langcode
172    *
173    * @return bool
174    */
175   public function isAnyPermissionSetForTerm($tid, $langcode = 'en') {
176     $iUserTableResults = intval($this->database->query("SELECT COUNT(1) FROM {permissions_by_term_user} WHERE tid = :tid AND langcode = :langcode",
177       [':tid' => $tid, ':langcode' => $langcode])->fetchField());
178
179     $iRoleTableResults = intval($this->database->query("SELECT COUNT(1) FROM {permissions_by_term_role} WHERE tid = :tid AND langcode = :langcode",
180       [':tid' => $tid, ':langcode' => $langcode])->fetchField());
181
182     if ($iUserTableResults > 0 ||
183       $iRoleTableResults > 0) {
184       return TRUE;
185     }
186
187   }
188
189   /**
190    * @param string $nodeId
191    * @param string $langcode
192    *
193    * @return AccessResult
194    */
195   public function handleNode($nodeId, $langcode) {
196     if ($this->canUserAccessByNodeId($nodeId, false, $langcode) === TRUE) {
197       return AccessResult::neutral();
198     }
199     else {
200       $accessDeniedEvent = new PermissionsByTermDeniedEvent($nodeId);
201       $this->eventDispatcher->dispatch(PermissionsByTermDeniedEvent::NAME, $accessDeniedEvent);
202
203       return AccessResult::forbidden();
204     }
205   }
206
207 }