access_policy-1.0.x-dev/src/Session/UserFieldValuesHashGenerator.php
src/Session/UserFieldValuesHashGenerator.php
<?php namespace Drupal\access_policy\Session; use Drupal\access_policy\AccessPolicyHandlerManager; use Drupal\access_policy\AccessPolicyInformation; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Site\Settings; /** * Defines the UserFieldValuesHashGenerator service. */ class UserFieldValuesHashGenerator implements UserFieldValuesHashGeneratorInterface { /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * The access rule manager. * * @var \Drupal\access_policy\AccessPolicyHandlerManager */ protected $accessRuleManager; /** * The access policy information service. * * @var \Drupal\access_policy\AccessPolicyInformation */ protected $accessPolicyInfo; /** * The user field values static cache. * * @var array */ protected $cache; /** * Constructs a new UserFieldValuesHashGenerator class. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\access_policy\AccessPolicyHandlerManager $access_rule_manager * The access rule manager. * @param \Drupal\access_policy\AccessPolicyInformation $access_policy_info * The access policy information service. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, AccessPolicyHandlerManager $access_rule_manager, AccessPolicyInformation $access_policy_info) { $this->entityTypeManager = $entity_type_manager; $this->accessRuleManager = $access_rule_manager; $this->accessPolicyInfo = $access_policy_info; } /** * {@inheritdoc} */ public function generate(AccountInterface $account, $field_name = NULL) { $cid = $this->getCid($account, $field_name); if ($this->cacheExists($cid)) { return $this->getCache($cid); } else { $user = $this->entityTypeManager->getStorage('user')->load($account->id()); $hash = $this->hash(serialize($this->getFieldValues($user, $field_name))); $this->setCache($cid, $hash); return $hash; } } /** * Get the field values for a user. * * @param \Drupal\Core\Session\AccountInterface $account * The current user. * @param string $field_name * (Optional) the field name. If empty, it will retrieve all fields observed * by all access policies. * * @return array * The array of field values. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ public function getFieldValues(AccountInterface $account, $field_name = NULL) { if ($field_name) { $fields = explode(',', $field_name); } else { $fields = $this->getUserFieldsObservedByAccessRules(); } // Get all the field values from the user. $values = []; foreach ($fields as $field_name) { if ($account->hasField($field_name)) { $values[$field_name] = $account->get($field_name)->getValue(); } } return $values; } /** * Fetch all user fields being observed by access policies. * * @return array * The array of field names observed by access rules. */ protected function getUserFieldsObservedByAccessRules() { $entity_types = $this->accessPolicyInfo->getAllEnabledEntityTypes(); $entity_type_ids = array_map(function ($entity_type) { return $entity_type->id(); }, $entity_types); $handlers = []; foreach ($entity_type_ids as $entity_type) { $access_rules = $this->accessRuleManager->getHandlersFromPolicies($entity_type, function ($handler) { if ($handler->getDefinition()->getEntityType() == 'user') { return TRUE; } elseif ($handler->getArgument() && $handler->getArgument()->getPluginId() == 'current_user') { return TRUE; } return FALSE; }); $handlers = array_merge($handlers, $access_rules); } $fields = array_map(function ($handler) { if ($handler->getArgument()) { return $handler->getArgument()->getField(); } else { return $handler->getDefinition()->getFieldName(); } }, $handlers); return array_unique($fields); } /** * Hashes the given string. * * @param string $identifier * The string to be hashed. * * @return string * The hash. */ protected function hash($identifier) { return hash('sha256', Settings::getHashSalt() . $identifier); } /** * Get the cid. * * @param \Drupal\Core\Session\AccountInterface $account * The current user. * @param string $field_name * The field name. * * @return string * The cache id. */ protected function getCid(AccountInterface $account, $field_name = NULL) { $field_name = $field_name ?? 'all'; return $account->id() . ':' . $field_name; } /** * Determine whether a cache exists. * * @param string $cid * Teh cache id. * * @return bool * TRUE if a cache entry exists; FALSE otherwise. */ protected function cacheExists($cid) { return isset($this->cache[$cid]); } /** * Get the hashed field values from the cache. * * @param string $cid * The cache id. * * @return string|null * The hashed field values or NULL if none found. */ protected function getCache($cid) { if (isset($this->cache[$cid])) { return $this->cache[$cid]; } } /** * Set the cached field values hash. * * @param string $cid * The cache id. * @param string $hash * The hashed field values. */ protected function setCache($cid, $hash) { $this->cache[$cid] = $hash; } }