DomainAccessManager.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. namespace Drupal\domain_access;
  3. use Drupal\Core\Entity\EntityTypeManagerInterface;
  4. use Drupal\Core\Entity\FieldableEntityInterface;
  5. use Drupal\Core\Extension\ModuleHandlerInterface;
  6. use Drupal\Core\Field\FieldDefinitionInterface;
  7. use Drupal\Core\Session\AccountInterface;
  8. use Drupal\domain\DomainInterface;
  9. use Drupal\domain\DomainNegotiatorInterface;
  10. /**
  11. * Checks the access status of entities based on domain settings.
  12. *
  13. * @TODO: It is possible that this class may become a subclass of the
  14. * DomainElementManager, however, the use-case is separate as far as I can tell.
  15. */
  16. class DomainAccessManager implements DomainAccessManagerInterface {
  17. /**
  18. * The domain negotiator.
  19. *
  20. * @var \Drupal\domain\DomainNegotiatorInterface
  21. */
  22. protected $negotiator;
  23. /**
  24. * The Drupal module handler.
  25. *
  26. * @var \Drupal\Core\Extension\ModuleHandlerInterface
  27. */
  28. protected $moduleHandler;
  29. /**
  30. * The entity type manager.
  31. *
  32. * @var \Drupal\Core\Entity\EntityTypeManagerInterface
  33. */
  34. protected $entityTypeManager;
  35. /**
  36. * The domain storage.
  37. *
  38. * @var \Drupal\domain\DomainStorageInterface
  39. */
  40. protected $domainStorage;
  41. /**
  42. * Constructs a DomainAccessManager object.
  43. *
  44. * @param \Drupal\domain\DomainNegotiatorInterface $negotiator
  45. * The domain negotiator.
  46. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
  47. * The Drupal module handler.
  48. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
  49. * The entity type manager.
  50. */
  51. public function __construct(DomainNegotiatorInterface $negotiator, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager) {
  52. $this->negotiator = $negotiator;
  53. $this->moduleHandler = $module_handler;
  54. $this->entityTypeManager = $entity_type_manager;
  55. $this->domainStorage = $entity_type_manager->getStorage('domain');
  56. }
  57. /**
  58. * {@inheritdoc}
  59. */
  60. public static function getAccessValues(FieldableEntityInterface $entity, $field_name = DOMAIN_ACCESS_FIELD) {
  61. // @TODO: static cache.
  62. $list = [];
  63. // @TODO In tests, $entity is returning NULL.
  64. if (is_null($entity)) {
  65. return $list;
  66. }
  67. // Get the values of an entity.
  68. $values = $entity->hasField($field_name) ? $entity->get($field_name) : NULL;
  69. // Must be at least one item.
  70. if (!empty($values)) {
  71. foreach ($values as $item) {
  72. if ($target = $item->getValue()) {
  73. if ($domain = \Drupal::entityTypeManager()->getStorage('domain')->load($target['target_id'])) {
  74. $list[$domain->id()] = $domain->getDomainId();
  75. }
  76. }
  77. }
  78. }
  79. return $list;
  80. }
  81. /**
  82. * {@inheritdoc}
  83. */
  84. public static function getAllValue(FieldableEntityInterface $entity) {
  85. return $entity->hasField(DOMAIN_ACCESS_ALL_FIELD) ? $entity->get(DOMAIN_ACCESS_ALL_FIELD)->value : NULL;
  86. }
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function checkEntityAccess(FieldableEntityInterface $entity, AccountInterface $account) {
  91. $entity_domains = $this->getAccessValues($entity);
  92. $user = \Drupal::entityTypeManager()->getStorage('user')->load($account->id());
  93. if (!empty($this->getAllValue($user)) && !empty($entity_domains)) {
  94. return TRUE;
  95. }
  96. $user_domains = $this->getAccessValues($user);
  97. return (bool) !empty(array_intersect($entity_domains, $user_domains));
  98. }
  99. /**
  100. * {@inheritdoc}
  101. */
  102. public static function getDefaultValue(FieldableEntityInterface $entity, FieldDefinitionInterface $definition) {
  103. $item = [];
  104. if (!$entity->isNew()) {
  105. // If set, ensure we do not drop existing data.
  106. foreach (self::getAccessValues($entity) as $id) {
  107. $item[] = $id;
  108. }
  109. }
  110. // When creating a new entity, populate if required.
  111. elseif ($entity->getFieldDefinition(DOMAIN_ACCESS_FIELD)->isRequired()) {
  112. /** @var \Drupal\domain\DomainInterface $active */
  113. if ($active = \Drupal::service('domain.negotiator')->getActiveDomain()) {
  114. $item[0]['target_uuid'] = $active->uuid();
  115. }
  116. }
  117. return $item;
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function hasDomainPermissions(AccountInterface $account, DomainInterface $domain, array $permissions, $conjunction = 'AND') {
  123. // Assume no access.
  124. $access = FALSE;
  125. // In the case of multiple AND permissions, assume access and then deny if
  126. // any check fails.
  127. if ($conjunction == 'AND' && !empty($permissions)) {
  128. $access = TRUE;
  129. foreach ($permissions as $permission) {
  130. if (!($permission_access = $account->hasPermission($permission))) {
  131. $access = FALSE;
  132. break;
  133. }
  134. }
  135. }
  136. // In the case of multiple OR permissions, assume deny and then allow if any
  137. // check passes.
  138. else {
  139. foreach ($permissions as $permission) {
  140. if ($permission_access = $account->hasPermission($permission)) {
  141. $access = TRUE;
  142. break;
  143. }
  144. }
  145. }
  146. // Validate that the user is assigned to the domain. If not, deny.
  147. $user = \Drupal::entityTypeManager()->getStorage('user')->load($account->id());
  148. $allowed = $this->getAccessValues($user);
  149. if (!isset($allowed[$domain->id()]) && empty($this->getAllValue($user))) {
  150. $access = FALSE;
  151. }
  152. return $access;
  153. }
  154. /**
  155. * {@inheritdoc}
  156. */
  157. public function getContentUrls(FieldableEntityInterface $entity) {
  158. $list = [];
  159. $processed = FALSE;
  160. $domains = $this->getAccessValues($entity);
  161. if ($this->moduleHandler->moduleExists('domain_source')) {
  162. $source = domain_source_get($entity);
  163. if (isset($domains[$source])) {
  164. unset($domains['source']);
  165. }
  166. if (!empty($source)) {
  167. $list[] = $source;
  168. }
  169. $processed = TRUE;
  170. }
  171. $list = array_merge($list, array_keys($domains));
  172. $domains = $this->domainStorage->loadMultiple($list);
  173. $urls = [];
  174. foreach ($domains as $domain) {
  175. $options['domain_target_id'] = $domain->id();
  176. $url = $entity->toUrl('canonical', $options);
  177. if ($processed) {
  178. $urls[$domain->id()] = $url->toString();
  179. }
  180. else {
  181. $urls[$domain->id()] = trim($domain->getPath(), '/') . $url->toString();
  182. }
  183. }
  184. return $urls;
  185. }
  186. }