access_policy-1.0.x-dev/src/Plugin/access_policy/AccessRule/EntityFieldList.php
src/Plugin/access_policy/AccessRule/EntityFieldList.php
<?php namespace Drupal\access_policy\Plugin\access_policy\AccessRule; use Drupal\access_policy\LabelHelper; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; /** * Restrict content by comparing field on the entity. * * @AccessRule( * id = "entity_field_list", * handlers = { * "query_alter" = "\Drupal\access_policy\AccessRuleQueryHandler\EntityField" * } * ) */ class EntityFieldList extends EntityFieldBase { /** * {@inheritdoc} */ public function defaultSettings() { return [ 'value' => [], "operator" => 'or', 'filter_allowed_values' => FALSE, ] + parent::defaultSettings(); } /** * {@inheritdoc} */ public function accessRuleFormSubmit(array &$form, FormStateInterface $form_state) { parent::accessRuleFormSubmit($form, $form_state); $values = $form_state->getValues(); $this->settings['value'] = $values['value'] ?? []; $this->settings['filter_allowed_values'] = $values['filter_allowed_values'] ?? FALSE; } /** * {@inheritdoc} */ protected function valueForm(array &$form, FormStateInterface $form_state) { $form['value'] = [ '#type' => 'select', '#title' => $this->t('Value'), '#options' => $this->getAllowedValues(), '#default_value' => $this->settings['value'], '#multiple' => TRUE, ]; } /** * {@inheritdoc} */ public function extraOptionsForm(array &$form, FormStateInterface $form_state) { if ($this->isComparingWithUser()) { $form['filter_allowed_values'] = [ '#type' => 'checkbox', '#title' => $this->t('Filter allowed values'), '#description' => $this->t("Filter options in the field widget based on the author's current values. This prevents authors from choosing options that they should not have access to.<br>Warning: This is a global setting. All instances of this field will be affected regardless of policy assigned."), '#default_value' => $this->settings['filter_allowed_values'], ]; } } /** * Determine whether the entity field list is being compared against the user. * * @return bool * TRUE if we're comparing against the user; FALSE otherwise. */ protected function isComparingWithUser() { $has_user_argument = ($this->getArgument() && $this->getArgument()->getPluginId() == 'current_user'); if ($has_user_argument) { return TRUE; } return FALSE; } /** * Get allowed field value options. * * @return array * Array of allowed values. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ protected function getAllowedValues() { $field_definition = $this->getFieldDefinition(); $settings = $field_definition->getSettings(); return $settings['allowed_values'] ?? []; } /** * Get the current field definition. * * @return \Drupal\Core\Field\FieldDefinitionInterface|false * The field definition. */ protected function getFieldDefinition() { $field_map = $this->entityFieldManager->getFieldMapByFieldType($this->definition->getFieldType()); $entity_fields = $field_map[$this->definition->getEntityType()]; $current_field = $entity_fields[$this->definition->getFieldName()] ?? []; $bundle = reset($current_field['bundles']); $definitions = $this->entityFieldManager->getFieldDefinitions($this->definition->getEntityType(), $bundle); if (isset($definitions[$this->definition->getFieldName()])) { return $definitions[$this->definition->getFieldName()]; } return FALSE; } /** * {@inheritdoc} */ public function operators() { $operators = [ 'or' => [ 'title' => $this->t('Is one of'), 'method' => 'validateSimple', ], 'not' => [ 'title' => $this->t('Is none of'), 'method' => 'validateSimple', ], ]; return $operators; } /** * Validate operators. * * @param array $options * The array of options. * @param array $values * The array of values. * * @return bool * TRUE if operator passes; FALSE otherwise. */ public function validateSimple(array $options, array $values) { $op = $this->getOperator(); switch ($op) { case 'or': foreach ($values as $value) { if ($this->isOneOf($options, $value)) { return TRUE; } } break; case 'not': foreach ($values as $value) { if ($this->isOneOf($options, $value)) { return FALSE; } } return TRUE; } return FALSE; } /** * {@inheritdoc} */ public function validateCallback(EntityInterface $entity, AccountInterface $account) { $operator = $this->getOperator(); $info = $this->operators(); $field_values = $this->getEntityValues($entity, $account); $options = $this->getValue(); $options = array_values($options); 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 adminSummary() { if (!$this->getArgument()) { $allowed_values = $this->getAllowedValues(); $labels = []; $selected = $this->settings['value']; foreach ($allowed_values as $key => $label) { if (in_array($key, $selected)) { $labels[] = $label; } } return $this->getOperator() . ' ' . LabelHelper::render($labels, [ 'limit' => 1, 'empty_value' => $this->t('Unknown'), ]); } } }