access_policy-1.0.x-dev/src/UserFieldAccessPolicyData.php
src/UserFieldAccessPolicyData.php
<?php namespace Drupal\access_policy; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\field\FieldStorageConfigInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class to manage and lazy load cached access policy data. */ class UserFieldAccessPolicyData implements ContainerInjectionInterface { use StringTranslationTrait; /** * The entity field manager. * * @var \Drupal\Core\Entity\EntityFieldManagerInterface */ protected $entityFieldManager; /** * Constructs the user field access rule data set. * * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager * The entity field manager. */ public function __construct(EntityFieldManagerInterface $entity_field_manager) { $this->entityFieldManager = $entity_field_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('entity_field.manager'), ); } /** * Defines the default access rule data. * * @see hook_access_policy_data() */ public function accessPolicyData() { $data = []; $this->createBaseFieldAccessRules($data); $this->createDerivedAccessRules($data); return $data; } /** * Create the base field access rules. * * @param array $data * The current access rule data. */ protected function createBaseFieldAccessRules(array &$data) { $data['user']['uid'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'The user ID']), 'description' => $this->t('The raw numeric user ID.'), 'plugin_id' => 'entity_field_numeric', 'field' => 'uid', 'entity_type' => 'user', ]; $data['user']['name'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Name']), 'description' => $this->t("The current user's name"), 'plugin_id' => 'entity_field_string', 'field' => 'name', 'entity_type' => 'user', ]; $data['user']['mail'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Email']), 'description' => $this->t("The current user's email address."), 'plugin_id' => 'entity_field_string', 'field' => 'mail', 'entity_type' => 'user', ]; $data['user']['init'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Initial email']), 'description' => $this->t('The email address used for initial account creation.'), 'plugin_id' => 'entity_field_string', 'field' => 'init', 'entity_type' => 'user', ]; $data['user']['status'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'User status']), 'description' => $this->t('Whether the current user is active or blocked.'), 'plugin_id' => 'entity_field_boolean', 'field' => 'status', 'entity_type' => 'user', ]; $data['user']['roles'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Roles']), 'description' => $this->t('The roles the current user has.'), 'plugin_id' => 'user_field_role', 'field' => 'roles', 'entity_type' => 'user', ]; $data['user']['created'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Created']), 'description' => $this->t('The time that the current user was created.'), 'plugin_id' => 'entity_field_date', 'field' => 'created', 'entity_type' => 'user', ]; $data['user']['login'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Last login']), 'description' => $this->t('The time that the current user last logged in.'), 'plugin_id' => 'entity_field_date', 'field' => 'login', 'entity_type' => 'user', ]; $data['user']['access'] = [ 'label' => $this->t('Current user: @field', ['@field' => 'Last access']), 'description' => $this->t('The time that the current user last accessed the site.'), 'plugin_id' => 'entity_field_date', 'field' => 'access', 'entity_type' => 'user', ]; } /** * Create user entity reference access rules. * * @param array $data * The current access rule data. */ protected function createDerivedAccessRules(array &$data) { $user_fields = $this->getUserFieldDefinitions(); foreach ($user_fields as $field_name => $definition) { $data['user'][$field_name] = $this->createUserFieldAccessRule($definition); // Add additional access rules for specific field types. $type = $definition->getType(); switch ($type) { case 'list_integer': case 'list_float': $data['user']['numeric_' . $field_name] = $this->createFieldListNumericFieldValueAccessRule($definition); break; case 'entity_reference': $storage = $definition->getFieldStorageDefinition(); if ($storage->getSetting('target_type') == 'taxonomy_term') { $data['user']['term_depth_' . $definition->getName()] = $this->createTermReferenceWithDepthAccessRule($definition); } break; } } } /** * Create user field access rule data definition. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * * @return array * The user reference access rule data definition. */ protected function createUserFieldAccessRule(FieldDefinitionInterface $field_definition) { return [ 'label' => $this->t('Current user: @field', ['@field' => $field_definition->getLabel()]), 'description' => $this->t('Grant access to user with a particular value in this field.'), 'plugin_id' => $this->getUserFieldPluginId($field_definition), 'field' => $field_definition->getName(), 'entity_type' => 'user', ]; } /** * Create numeric list field access rule. * * This access rule compares values in list_integer and list_float fields * numerically. This allows for features like mandatory access control. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * * @return array * The numeric list field access rule data definition. */ protected function createFieldListNumericFieldValueAccessRule(FieldDefinitionInterface $field_definition) { return [ 'label' => $this->t('Current user: @field (numeric)', ['@field' => $field_definition->getLabel()]), 'description' => $this->t('Grant access to user with a particular value in this field.'), 'plugin_id' => 'entity_field_list_numeric', 'field' => $field_definition->getName(), 'entity_type' => 'user', ]; } /** * Create the term reference with depth access rule. * * This access rule compares taxonomy terms while respecting the hierarchy. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * * @return array * The term reference field access rule data definition. */ protected function createTermReferenceWithDepthAccessRule(FieldDefinitionInterface $field_definition) { return [ 'label' => $this->t('Current user: @field (with depth)', ['@field' => $field_definition->getLabel()]), 'description' => $this->t('Grant access to user with specific terms or children of selected terms.'), 'plugin_id' => 'term_reference_depth', 'field' => $field_definition->getName(), 'entity_type' => 'user', 'operator' => 'in', ]; } /** * Get default user field plugin ids based on field type. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * * @return string * The default plugin id. */ protected function getUserFieldPluginId(FieldDefinitionInterface $field_definition) { switch ($field_definition->getType()) { case 'integer': case 'float': case 'decimal': case 'timestamp': return 'entity_field_numeric'; case 'changed': case 'created': case 'datetime': // @todo come back to daterange. case 'daterange': return 'entity_field_date'; case 'list_string': case 'list_integer': case 'list_float': return 'entity_field_list'; case 'string': case 'string_long': case 'text': case 'text_long': case 'text_with_summary': case 'email': return 'entity_field_string'; case 'boolean': return 'entity_field_boolean'; case 'entity_reference': return 'entity_field_entity_reference'; default: return 'entity_field_standard'; } } /** * Get the user field definitions. * * @return \Drupal\Core\Field\FieldDefinitionInterface[] * The user field definitions. * * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ protected function getUserFieldDefinitions() { $field_definitions = $this->entityFieldManager->getFieldDefinitions('user', 'user'); // Add configurable fields. return $this->filterByApplicableFieldStorage('user', $field_definitions); } /** * Array of applicable entity reference fields found on an entity type. * * @param string $entity_type_id * The entity type id. * @param \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions * Array of field definitions. * * @return \Drupal\Core\Field\FieldDefinitionInterface[] * Array of filtered field definitions. */ private function filterByApplicableFieldStorage($entity_type_id, array $field_definitions) { $options = []; foreach ($this->entityFieldManager->getFieldStorageDefinitions($entity_type_id) as $field_name => $field_storage) { if ($field_storage instanceof FieldStorageConfigInterface && !$field_storage->isLocked()) { if (isset($field_definitions[$field_name])) { $options[$field_name] = $field_definitions[$field_name]; } } } return $options; } }