3 namespace Drupal\permissions_by_term\Service;
5 use Drupal\Core\Database\Connection;
6 use Drupal\Component\Utility\Tags;
7 use Drupal\Core\Form\FormState;
8 use Drupal\Core\Session\AccountInterface;
9 use Drupal\user\Entity\User;
12 * Class AccessStorage.
14 * @package Drupal\permissions_by_term
19 * The database connection.
26 * The term name for which the access is set.
33 * The user ids which gain granted access.
37 protected $aUserIdsGrantedAccess;
40 * The roles with granted access.
44 protected $aSubmittedRolesGrantedAccess;
54 const NODE_ACCESS_REALM = 'permissions_by_term';
59 protected $accessCheck;
62 * AccessStorageService constructor.
64 * @param Connection $database
66 * @param AccessCheck $accessCheck
68 public function __construct(Connection $database, Term $term, AccessCheck $accessCheck) {
69 $this->database = $database;
71 $this->accessCheck = $accessCheck;
75 * Gets submitted roles with granted access from form.
78 * An array with chosen roles.
80 public function getSubmittedRolesGrantedAccess(FormState $form_state) {
81 $aRoles = $form_state->getValue('access')['role'];
83 foreach ($aRoles as $sRole) {
85 $aChosenRoles[] = $sRole;
92 * @param FormState $form_state
94 public function checkIfUsersExists(FormState $form_state) {
95 $sAllowedUsers = $form_state->getValue('access')['user'];
96 $aAllowedUsers = Tags::explode($sAllowedUsers);
97 foreach ($aAllowedUsers as $sUserId) {
98 $aUserId = \Drupal::entityQuery('user')
99 ->condition('uid', $sUserId)
101 if (empty($aUserId)) {
102 $form_state->setErrorByName('access][user',
103 t('The user with ID %user_id does not exist.',
104 ['%user_id' => $sUserId]));
110 * @param int $term_id
114 public function getUserTermPermissionsByTid($term_id) {
115 return $this->database->select('permissions_by_term_user', 'pu')
116 ->condition('tid', $term_id)
117 ->fields('pu', ['uid'])
128 public function getPermittedTids($uid, $rids) {
129 $permittedTids = $this->database->select('permissions_by_term_user', 'pu')
130 ->condition('uid', $uid)
131 ->fields('pu', ['tid'])
135 foreach ($rids as $rid) {
136 $permittedTidsByRid = $this->database->select('permissions_by_term_role', 'pr')
137 ->condition('rid', $rid)
138 ->fields('pr', ['tid'])
142 $permittedTids = array_merge($permittedTidsByRid, $permittedTids);
145 return array_unique($permittedTids);
153 public function getUserTermPermissionsByTids($tids) {
156 foreach ($tids as $tid) {
157 if (!empty($tmpUids = $this->getUserTermPermissionsByTid($tid))) {
158 foreach ($tmpUids as $tmpUid) {
168 * @param int $term_id
172 public function getRoleTermPermissionsByTid($term_id) {
173 return $this->database->select('permissions_by_term_role', 'pr')
174 ->condition('tid', $term_id)
175 ->fields('pr', ['rid'])
185 public function getRoleTermPermissionsByTids($tids) {
188 foreach ($tids as $tid) {
189 $tmpRids = $this->getRoleTermPermissionsByTid($tid);
190 if (!empty($tmpRids)) {
191 foreach ($tmpRids as $tmpRid) {
201 * @param string $sUsername
205 public function getUserIdByName($sUsername) {
206 return $this->database->select('users_field_data', 'ufd')
207 ->condition('name', $sUsername)
208 ->fields('ufd', ['uid'])
214 * @param array $aUserNames
218 public function getUserIdsByNames($aUserNames) {
220 foreach ($aUserNames as $userName) {
221 $iUserId = $this->getUserIdByName($userName)['uid'];
222 $aUserIds[] = $iUserId['uid'];
228 * @param int $term_id
232 public function getAllowedUserIds($term_id) {
233 $query = $this->database->select('permissions_by_term_user', 'p')
234 ->fields('p', ['uid'])
235 ->condition('p.tid', $term_id);
237 // fetchCol() returns all results, fetchAssoc() only "one" result.
238 return $query->execute()
243 * @param array $aUserIdsAccessRemove
244 * @param int $term_id
246 public function deleteTermPermissionsByUserIds($aUserIdsAccessRemove, $term_id) {
247 foreach ($aUserIdsAccessRemove as $iUserId) {
248 $this->database->delete('permissions_by_term_user')
249 ->condition('uid', $iUserId, '=')
250 ->condition('tid', $term_id, '=')
256 * @param array $aRoleIdsAccessRemove
257 * @param int $term_id
259 public function deleteTermPermissionsByRoleIds($aRoleIdsAccessRemove, $term_id) {
260 foreach ($aRoleIdsAccessRemove as $sRoleId) {
261 $this->database->delete('permissions_by_term_role')
262 ->condition('rid', $sRoleId, '=')
263 ->condition('tid', $term_id, '=')
271 public function deleteAllTermPermissionsByUserId($userId) {
272 $this->database->delete('permissions_by_term_user')
273 ->condition('uid', $userId, '=')
278 * @param array $aUserIdsGrantedAccess
279 * @param int $term_id
283 public function addTermPermissionsByUserIds($aUserIdsGrantedAccess, $term_id) {
284 foreach ($aUserIdsGrantedAccess as $iUserIdGrantedAccess) {
285 $this->database->insert('permissions_by_term_user')
286 ->fields(['tid', 'uid'], [$term_id, $iUserIdGrantedAccess])
292 * @param array $aRoleIdsGrantedAccess
293 * @param int $term_id
297 public function addTermPermissionsByRoleIds($aRoleIdsGrantedAccess, $term_id) {
298 foreach ($aRoleIdsGrantedAccess as $sRoleIdGrantedAccess) {
299 $this->database->insert('permissions_by_term_role')
300 ->fields(['tid', 'rid'], [$term_id, $sRoleIdGrantedAccess])
306 * Gets the user ids which have been submitted by form.
308 * Users which will gain granted access to taxonomy terms.
311 * The user ids which have been submitted.
313 public function getSubmittedUserIds() {
314 /* There's a $this->oFormState->getValues() method, but
315 * it is loosing multiple form values. Don't know why.
316 * So there're some custom lines on the $_REQUEST array. */
317 $sRawUsers = $_REQUEST['access']['user'];
319 if (empty($sRawUsers)) {
323 $aRawUsers = explode('),', $sRawUsers);
325 if (!empty($aRawUsers)) {
326 foreach ($aRawUsers as $sRawUser) {
327 $aTempRawUser = explode(' (', $sRawUser);
328 // We check the user id by user name. If we get null back, the user might
329 // be the Anonymous user. In that case we get null back and then we use
330 // this id, which is 0.
331 if (!empty($aTempRawUser[1])) {
332 $fallback_user_id = str_replace(')', '', $aTempRawUser[1]);
333 $fallback_user_id = intval($fallback_user_id);
336 $sRawUser = trim($aTempRawUser['0']);
337 $uid = $this->getUserIdByName($sRawUser)['uid'];
338 if ($uid == NULL && $fallback_user_id == 0) {
339 // We might want to give access to the Anonymous user.
343 $aUserIds[] = $this->getUserIdByName($sRawUser)['uid'];
352 * Saves term permissions by users.
354 * Opposite to save term permission by roles.
356 * @param FormState $form_state
357 * @param int $term_id
360 * Data for database queries.
362 public function saveTermPermissions(FormState $form_state, $term_id) {
363 $aExistingUserPermissions = $this->getUserTermPermissionsByTid($term_id);
364 $aSubmittedUserIdsGrantedAccess = $this->getSubmittedUserIds();
366 $aExistingRoleIdsGrantedAccess = $this->getRoleTermPermissionsByTid($term_id);
367 $aSubmittedRolesGrantedAccess = $this->getSubmittedRolesGrantedAccess($form_state);
369 $aRet = $this->getPreparedDataForDatabaseQueries($aExistingUserPermissions,
370 $aSubmittedUserIdsGrantedAccess, $aExistingRoleIdsGrantedAccess,
371 $aSubmittedRolesGrantedAccess);
373 // Run the database queries.
374 $this->deleteTermPermissionsByUserIds($aRet['UserIdPermissionsToRemove'], $term_id);
375 $this->addTermPermissionsByUserIds($aRet['UserIdPermissionsToAdd'], $term_id);
377 $this->deleteTermPermissionsByRoleIds($aRet['UserRolePermissionsToRemove'], $term_id);
378 $this->addTermPermissionsByRoleIds($aRet['aRoleIdPermissionsToAdd'], $term_id);
384 * Get array items to remove.
386 * The array items which aren't in the new items array, but are in old items
387 * array, will be returned.
389 * @param array $aExistingItems
390 * The existing array items.
391 * @param array|bool $aNewItems
392 * Either false if there're no new items or an array with items.
395 * The array items to remove.
397 private function getArrayItemsToRemove($aExistingItems, $aNewItems) {
400 foreach ($aExistingItems as $existingItem) {
401 if (!in_array($existingItem, $aNewItems)) {
402 $aRet[] = $existingItem;
410 * Get the array items to add.
412 * The items in the new items array, which aren't in the existing items array,
415 * @param array $aNewItems
416 * The new array items.
417 * @param array $aExistingItems
418 * The existing array items.
421 * The items which needs to be added.
423 private function getArrayItemsToAdd($aNewItems, $aExistingItems) {
426 foreach ($aNewItems as $newItem) {
427 if (!in_array($newItem, $aExistingItems)) {
436 * Prepares the data which has to be applied to the database.
438 * @param array $aExistingUserPermissions
439 * The permissions for existing user.
440 * @param array $aSubmittedUserIdsGrantedAccess
441 * The user ids which get access.
442 * @param array $aExistingRoleIdsGrantedAccess
443 * The existing role ids.
444 * @param array $aSubmittedRolesGrantedAccess
445 * The user roles which get access.
448 * User ID and role data.
450 public function getPreparedDataForDatabaseQueries($aExistingUserPermissions,
451 $aSubmittedUserIdsGrantedAccess,
452 $aExistingRoleIdsGrantedAccess,
453 $aSubmittedRolesGrantedAccess) {
454 // Fill array with user ids to remove permission.
455 $aRet['UserIdPermissionsToRemove'] =
456 $this->getArrayItemsToRemove($aExistingUserPermissions,
457 $aSubmittedUserIdsGrantedAccess);
459 // Fill array with user ids to add permission.
460 $aRet['UserIdPermissionsToAdd'] =
461 $this->getArrayItemsToAdd($aSubmittedUserIdsGrantedAccess,
462 $aExistingUserPermissions);
464 // Fill array with user roles to remove permission.
465 $aRet['UserRolePermissionsToRemove'] =
466 $this->getArrayItemsToRemove($aExistingRoleIdsGrantedAccess,
467 $aSubmittedRolesGrantedAccess);
469 // Fill array with user roles to add permission.
470 $aRet['aRoleIdPermissionsToAdd'] =
471 $this->getArrayItemsToAdd($aSubmittedRolesGrantedAccess,
472 $aExistingRoleIdsGrantedAccess);
478 * The form value for allowed users as string to be shown to the user.
480 * @param User[] $aAllowedUsers
481 * An array with the allowed users.
483 * @return null|string
484 * Either null or the user name.
486 public function getUserFormValue($aAllowedUsers) {
490 if (!empty($aAllowedUsers)) {
492 foreach ($aAllowedUsers as $oUser) {
493 $iUid = intval($oUser->id());
495 $sUsername = $oUser->getDisplayName();
498 $sUsername = t('Anonymous User');
501 $sUserInfos .= "$sUsername ($iUid), ";
504 // Remove space and comma at the end of the string.
505 $sUserInfos = substr($sUserInfos, 0, -2);
514 public function getAllNids()
516 $query = $this->database->select('node', 'n')
517 ->fields('n', ['nid']);
519 return $query->execute()
528 public function getTidsByNid($nid)
530 $node = \Drupal::entityTypeManager()->getStorage('node')->load($nid);
533 foreach ($node->getFields() as $field) {
534 if ($field->getFieldDefinition()->getType() == 'entity_reference' && $field->getFieldDefinition()->getSetting('target_type') == 'taxonomy_term') {
535 $aReferencedTaxonomyTerms = $field->getValue();
536 if (!empty($aReferencedTaxonomyTerms)) {
537 foreach ($aReferencedTaxonomyTerms as $aReferencedTerm) {
538 if (isset($aReferencedTerm['target_id'])) {
539 $tids[] = $aReferencedTerm['target_id'];
552 public function getAllUids()
554 $nodes = \Drupal::entityQuery('user')
557 return array_values($nodes);
565 public function getNodeType($nid)
567 $query = $this->database->select('node', 'n')
568 ->fields('n', ['type'])
569 ->condition('n.nid', $nid);
571 return $query->execute()
572 ->fetchAssoc()['type'];
580 public function getLangCode($nid)
582 $query = $this->database->select('node', 'n')
583 ->fields('n', ['langcode'])
584 ->condition('n.nid', $nid);
586 return $query->execute()
587 ->fetchAssoc()['langcode'];
591 * @param AccountInterface $user
595 public function getGids(AccountInterface $user)
599 if (!empty($permittedNids = $this->computePermittedTids($user))) {
600 $query = $this->database->select('node_access', 'na')
601 ->fields('na', ['gid'])
602 ->condition('na.nid', $permittedNids, 'IN')
603 ->condition('na.realm', self::NODE_ACCESS_REALM);
605 $gids = $query->execute()->fetchCol();
607 foreach ($gids as $gid) {
608 $grants[self::NODE_ACCESS_REALM][] = $gid;
615 private function computePermittedTids(AccountInterface $user)
617 $nidsWithNoTidRestriction = $this->getNidsWithNoTidRestriction();
618 $nidsByTids = $this->term->getNidsByTids($this->getPermittedTids($user->id(), $user->getRoles()));
620 if (\Drupal::config('permissions_by_term.settings.single_term_restriction')->get('value')) {
622 foreach ($nidsByTids as $nid) {
623 if($this->accessCheck->canUserAccessByNodeId($nid)) {
624 $permittedNids[] = $nid;
627 $nidsByTids = $permittedNids;
630 if (!empty($nidsByTids)) {
632 $this->getNidsWithNoTidRestriction(),
637 return $nidsWithNoTidRestriction;
640 private function getNidsWithNoTidRestriction() {
641 $queryNidsNoRestriction = $this->database->select('node', 'n')
642 ->fields('n', ['nid']);
644 $queryNidsNoRestriction->leftJoin('taxonomy_index', 'ti', 'n.nid = ti.nid');
645 $queryNidsNoRestriction->leftJoin('permissions_by_term_user', 'ptu', 'ptu.tid = ti.tid');
646 $queryNidsNoRestriction->condition('ptu.tid', NULL, 'IS');
647 $queryNidsNoRestriction->leftJoin('permissions_by_term_role', 'ptr', 'ptr.tid = ti.tid');
648 $queryNidsNoRestriction->condition('ptr.tid', NULL, 'IS');
650 return $queryNidsNoRestriction
661 public function getAllNidsUserCanAccess($uid)
663 $query = $this->database->select('node_access', 'na')
664 ->fields('na', ['nid'])
665 ->condition('na.realm', 'permissions_by_term__uid_' . $uid);
667 return $query->execute()
676 public function getNidsByTid($tid)
678 $query = $this->database->select('taxonomy_index', 'ti')
679 ->fields('ti', ['nid'])
680 ->condition('ti.tid', $tid);
682 return $query->execute()->fetchCol();