Рейтинг:1

ConstraintValidator не может проверить ограничение в поле ссылки на термин таксономии

флаг nr

Клиент имеет простую и последовательную иерархическую таксономию.

Города на верхнем уровне и школы на втором уровне.

.
🔸Город 1
🔸 Школа №1
🔸Школа2
✨ Школа5
ââ Город2
    ✨Школа3
    ââ Школа4

Пакет сущностей учетной записи пользователя содержит поле «Ссылка на сущность» для терминов таксономии учебного заведения.

Я пытаюсь применить ограничение, чтобы предотвратить создание или сохранение учетной записи пользователя, если выбранный термин находится на верхнем уровне иерархии (и, следовательно, в городе, а не в школе).

Вот пример кода, пропускающий внедрение зависимостей $this->entityTypeManager для краткости.

TermParentConstraint.php:

<?php

пространство имен Drupal\entity_validation_examples\Plugin\Validation\Constraint;

используйте Symfony\Component\Validator\Constraint;

/**
 * Предотвратить создание учетной записи, если термин школьной таксономии не имеет родителя.
 *
 * @Ограничение(
 * id = "Родительский термин",
 * label = @Translation("Запретить создание учетной записи, если термин не имеет родителя", context = "Проверка"),
 * тип = "сущность"
 * )
 */
класс TermParentConstraint расширяет ограничение {

  /**
   * Сообщение отображается при попытке создать учетную запись, если у школы нет родительского города.
   *
   * @var строка
   * Школьное сообщение.
   */
  public $schoolMessage = 'Вы должны выбрать и город, и школу.';

}

TermParentConstraintValidator.php:

<?php

пространство имен Drupal\entity_validation_examples\Plugin\Validation\Constraint;

используйте Drupal\user\Entity\User;
используйте Symfony\Component\Validator\Constraint;
используйте Symfony\Component\Validator\ConstraintValidator;

/**
 * Проверяет ограничение TermParent.
 */
класс TermParentConstraintValidator расширяет ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  проверка публичной функции ($entity, ограничение $constraint) {
    если (!isset($entity)) {
      возвращаться;
    }

    если ($entity->getEntityTypeId() == 'пользователь') {

      $school = $entity->get('field_select_a_school')->getValue();

      // Термины таксономии школ-сирот должны быть городами, а не школами.
      $parent = \Drupal::entityTypeManager()
        ->getStorage('taxonomy_term')
        ->loadParents($school[0]['target_id']);
      если (пусто($родитель)) {
        $this->context->addViolation($constraint->schoolMessage);
      }
    }
  }

}

Ожидаемое поведение: Когда я создаю новую учетную запись пользователя и выбираю Город1 как значение Школа, создание учетной записи должно завершиться ошибкой, и должно появиться сообщение об ошибке.

Фактическое поведение: Когда я создаю новую учетную запись пользователя и выбираю Город1 как значение Школа, создание учетной записи завершается успешно, и сообщение об ошибке не отображается.

Журналы Drupal Watchdog содержат некоторые ошибки, но я не уверен, что они актуальны:

 драш сс
 --------- -------------- ------ ---------- ----------- --------------------------------------------- --------------------------------------------- --------------------------------------------- ----------------------------- 
  ID Дата Тип Сообщение о серьезности                                                                                                                                                                                       
 --------- -------------- ------ ---------- ----------- --------------------------------------------- --------------------------------------------- --------------------------------------------- ----------------------------- 
  5298867 18 октября 22:57 Предупреждение php Предупреждение: недопустимый тип смещения в isset или пустой в Drupal\Core\Entity\EntityStorageBase->load() (строка 246 файла /app/docroot/core/lib/Drupal/Core/Entity/ EntityStorageBase.php) #0 /app/docroot/  
  5298866 18 октября 22:57 Уведомление о php Уведомление: преобразование массива в строку в Drupal\Core\Entity\EntityStorageBase->buildCacheId() (строка 126 файла /app/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php ) #0 /приложение/docroot/ядро  
  5298865 18/окт 22:57 php Предупреждение Предупреждение: array_flip(): Может переворачивать только значения STRING и INTEGER! в Drupal\Core\Entity\EntityStorageBase->loadMultiple() (строка 261 файла /app/docroot/core/lib/Drupal/Core/Entity/EntityStorageB  
  5298864 18 октября 22:57 Уведомление о php Уведомление: iconv(): неправильный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 из /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
  5298863 18 октября 22:57 Уведомление о php Уведомление: iconv(): неверный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 файла /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
  5298862 18 октября 22:57 Уведомление о php Уведомление: iconv(): неверный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 файла /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
  5298861 18 октября, 22:57 Уведомление о php Уведомление: iconv(): Неверный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 файла /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
  5298860 18 октября 22:57 Уведомление о php Уведомление: iconv(): неверный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 файла /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
  5298859 18 октября, 22:57 Уведомление о php Уведомление: iconv(): Неправильный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 файла /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
  5298858 18 октября, 22:57 Уведомление о php Уведомление: iconv(): неправильный набор символов, преобразование из `HTML-ENTITIES' в `UTF-8' не разрешено в twig_convert_encoding() (строка 1009 файла /app/vendor/twig/twig /src/Расширение/CoreExtension.php) #0  
 --------- -------------- ------ ---------- ----------- --------------------------------------------- --------------------------------------------- --------------------------------------------- ----------------------------- 

я видел значокv() ошибки после обновления этого проекта с Drupal 8 на Drupal 9, поэтому я не думаю, что они актуальны. Первые три сообщения об ошибках здесь могут быть связаны с проверкой ограничения, но они также являются довольно распространенными ошибками в этом проекте (и их отладка имеет гораздо более низкий приоритет, чем основные функции, которые должны появиться в ближайшее время).

Любые идеи? Я хоть на правильном пути?

Рейтинг:1
флаг ph

loadParents() вызовы методов loadMultiple(), и именно там массив_флип() происходит ошибка:

Предупреждение: array_flip(): может переворачивать только значения STRING и INTEGER! в Drupal\Core\Entity\EntityStorageBase->loadMultiple() (строка 261 файла /app/docroot/core/lib/Drupal/Core/Entity/EntityStorageB

Так что скорее всего там что-то происходит.

loadParents() метод отличается в зависимости от вашей версии Drupal.

hotwebmatter avatar
флаг nr
Спасибо за совет! Вот частичный `drush status`: Версия Drupal: `9.2.7` База данных: `Connected` Начальная загрузка Drupal: `Successful` Тема по умолчанию: `projectname` Тема администратора: `projectname_admin` Версия Drush: `10.6.0` Профиль установки: ` стандартный` корень Drupal: `/app/docroot`
Рейтинг:1
флаг cn

The problem is you are loading parents in an array and then check for an empty value. Terms at the top level can have a root parent (ID=0), so this would be an item in the array as well, even if not pointing at an existing term.

You can try to simplify the code, since D8.6 you don't need to use the term storage anymore to handle the parent field. empty() on the target ID catches NULL for an empty field and 0 for the root parent.

 public function validate($entity, Constraint $constraint) {
    if (!isset($entity)) {
      return;
    }

    if ($entity->getEntityTypeId() == 'user') {
      $term = $entity->get('field_select_a_school')->entity;
      if ($term) {
        if (empty($term->parent->target_id)) {
          $this->context->addViolation($constraint->schoolMessage);
        }
      }
    }

  }
Рейтинг:0
флаг nr

In this case, it turns out that the quickest solution is to configure the Simple Hierarchical Select widget correctly. (The SHS module is already installed, so I may as well use it!)

For the record, this is the problematic widget configuration.

BEFORE:

Checkbox labeled "Force selection of deepest level" unchecked

AFTER:

Checkbox labeled "Force selection of deepest level" checked

Thanks for all the answers, everybody! I learned quite a bit about constraint validation and hierarchical taxonomy, which will help me next time I have to deal with taxonomy trees or implement a ConstraintValidator class.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.