access_policy-1.0.x-dev/src/Plugin/access_policy/SelectionRule/EntityReference.php
src/Plugin/access_policy/SelectionRule/EntityReference.php
<?php namespace Drupal\access_policy\Plugin\access_policy\SelectionRule; use Drupal\access_policy\EntityStubHelper; use Drupal\access_policy\LabelHelper; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; /** * Determine whether the entity field has a value. * * @SelectionRule( * id = "entity_reference", * ) */ class EntityReference extends EntityFieldBase { /** * The field definition settings for this field. * * @var array */ protected $fieldSettings = []; /** * {@inheritdoc} */ public function defaultSettings() { return [ 'value' => [], "operator" => 'not empty', ] + parent::defaultSettings(); } /** * {@inheritdoc} */ public function operators() { $operators = [ 'in' => [ 'title' => $this->t('Is one of'), 'method' => 'validateSimple', ], 'not in' => [ 'title' => $this->t('Is none of'), 'method' => 'validateSimple', ], 'empty' => [ 'title' => $this->t('Is empty'), 'method' => 'validateSimple', 'hide_value' => TRUE, ], 'not empty' => [ 'title' => $this->t('Is not empty'), 'method' => 'validateSimple', 'hide_value' => TRUE, ], 'is applicable' => [ 'title' => $this->t('Is applicable'), 'method' => 'validateIsApplicable', 'hide_value' => TRUE, 'values' => FALSE, ], ]; return $operators; } /** * {@inheritdoc} */ protected function valueForm(array &$form, FormStateInterface $form_state) { $target_bundles = $this->getTargetBundles(); if ($target_bundles) { $selection_settings = [ 'target_bundles' => $target_bundles, ]; } $form['value'] = [ '#type' => 'entity_autocomplete', '#title' => $this->t('Value'), '#target_type' => $this->getFieldSetting('target_type'), '#selection_handler' => $this->getFieldSetting('handler'), '#selection_settings' => $selection_settings ?? [], '#validate_reference' => FALSE, '#maxlength' => 1024, '#default_value' => $this->getEntities($this->getFieldSetting('target_type'), $this->settings['value']), '#tags' => TRUE, ]; } /** * Load the entity objects. * * @param string $entity_type * The entity type. * @param array $entity_ids * Array of entity ids. * * @return array|\Drupal\Core\Entity\EntityInterface[] * Array of entities. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ private function getEntities($entity_type, array $entity_ids) { foreach ($entity_ids as $item) { $ids[] = $item['target_id']; } if (!empty($ids)) { return $this->entityTypeManager->getStorage($entity_type)->loadMultiple($ids); } return []; } /** * Validate simple operators. * * @param mixed $expected * The expected value. * @param mixed $actual * The actual value. * * @return bool * TRUE if operator passes; FALSE otherwise. */ public function validateSimple($expected, $actual) { $op = $this->getOperator(); switch ($op) { case 'in': foreach ($actual as $value) { if ($this->isOneOf($expected, $value)) { return TRUE; } } break; case 'not in': foreach ($actual as $value) { if ($this->isOneOf($expected, $value)) { return FALSE; } } return TRUE; case 'empty': return $this->isEmptyValue($actual); case 'not empty': return $this->isNotEmptyValue($actual); } return FALSE; } /** * Get a field setting value. * * @param string $key * The settings key. * * @return mixed * The field setting value. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ private function getFieldSetting($key) { // @todo automatically load the field definition. if (empty($this->fieldSettings)) { $field_name = $this->definition->getFieldName(); $field_map = $this->entityFieldManager->getFieldMap()[$this->definition->getEntityType()]; $bundles = $field_map[$field_name]['bundles']; $bundle = array_pop($bundles); $entity = EntityStubHelper::createStub($this->definition->getEntityType(), $bundle); $field_definition = $entity->get($field_name)->getFieldDefinition(); $this->fieldSettings = $field_definition->getSettings(); } return $this->fieldSettings[$key]; } /** * Get all the target bundles that are configured for this field type. * * @return array * Array of bundles. */ protected function getTargetBundles() { $field_name = $this->definition->getFieldName(); $field_map = $this->entityFieldManager->getFieldMap()[$this->definition->getEntityType()]; $bundles = $field_map[$field_name]['bundles']; $target_bundles = []; foreach ($bundles as $bundle) { $definitions = $this->entityFieldManager->getFieldDefinitions($this->definition->getEntityType(), $bundle); if (isset($definitions[$field_name])) { $definition = $definitions[$field_name]; $handler_settings = $definition->getSetting('handler_settings'); if (isset($handler_settings['target_bundles'])) { $value = array_values($handler_settings['target_bundles']); $target_bundles = array_merge($target_bundles, $value); } } } return array_unique($target_bundles); } /** * {@inheritdoc} */ public function validateCallback(EntityInterface $entity, AccountInterface $account) { $operator = $this->getOperator(); $info = $this->operators(); if ($operator == 'is applicable') { return $this->validateIsApplicable($entity, $account); } $field_name = $this->definition->getFieldName(); $field_values = $this->getEntityFieldValues($entity, $field_name); $options = $this->getValue(); if (!empty($info[$operator]['method'])) { // If any of the field values match then return true. $valid = $this->{$info[$operator]['method']}($options, $field_values); if ($valid) { return TRUE; } } return FALSE; } /** * {@inheritdoc} */ public function submitSettingsForm(array &$form, FormStateInterface $form_state) { parent::submitSettingsForm($form, $form_state); $values = $form_state->getValues(); $this->settings['value'] = $values['value'] ?? []; } /** * {@inheritdoc} */ public function adminSummary() { if ($this->isValueHidden()) { return $this->getOperator(); } $entities = $this->getEntities($this->getFieldSetting('target_type'), $this->settings['value']); return $this->getOperator() . ' ' . LabelHelper::renderEntities($entities, [ 'limit' => 1, 'empty_value' => $this->t('Unknown'), ]); } }