--- /dev/null
+<?php
+
+namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
+
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\TypedData\OptionsProviderInterface;
+use Drupal\Core\TypedData\ComplexDataInterface;
+use Drupal\Core\TypedData\Validation\TypedDataAwareValidatorTrait;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\ChoiceValidator;
+
+/**
+ * Validates the AllowedValues constraint.
+ */
+class AllowedValuesConstraintValidator extends ChoiceValidator implements ContainerInjectionInterface {
+
+ use TypedDataAwareValidatorTrait;
+
+ /**
+ * The current user.
+ *
+ * @var \Drupal\Core\Session\AccountInterface
+ */
+ protected $currentUser;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static($container->get('current_user'));
+ }
+
+ /**
+ * Constructs a new AllowedValuesConstraintValidator.
+ *
+ * @param \Drupal\Core\Session\AccountInterface $current_user
+ * The current user.
+ */
+ public function __construct(AccountInterface $current_user) {
+ $this->currentUser = $current_user;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint) {
+ $typed_data = $this->getTypedData();
+ if ($typed_data instanceof OptionsProviderInterface) {
+ $allowed_values = $typed_data->getSettableValues($this->currentUser);
+ $constraint->choices = $allowed_values;
+
+ // If the data is complex, we have to validate its main property.
+ if ($typed_data instanceof ComplexDataInterface) {
+ $name = $typed_data->getDataDefinition()->getMainPropertyName();
+ if (!isset($name)) {
+ throw new \LogicException('Cannot validate allowed values for complex data without a main property.');
+ }
+ $value = $typed_data->get($name)->getValue();
+ }
+ }
+
+ // The parent implementation ignores values that are not set, but makes
+ // sure some choices are available firstly. However, we want to support
+ // empty choices for undefined values; for instance, if a term reference
+ // field points to an empty vocabulary.
+ if (!isset($value)) {
+ return;
+ }
+
+ parent::validate($value, $constraint);
+ }
+
+}