Рейтинг:4

Как сделать имена терминов таксономии уникальными для каждого пользователя?

флаг cn

У меня есть таксономический словарь, Группы.

Требования

  • Разные пользователи могут создавать группы с одинаковым именем. (Пользователь А может сделать яблоки группу, а пользователь B также может сделать яблоки группа.)
  • Один и тот же пользователь не может создать две группы с одинаковым именем (пользователь А не может создать две группы). яблоки группы.)

Как я могу реализовать это?

D8/9 предлагает ограничение поля как объяснено в этом ответе и этот пост в блоге, но это делает поле уникальным для всех пользователей.

я хочу сделать название термина таксономии уникальный на пользователя. Кроме того, это должно работать с JSON: API. Как я могу это сделать?

Рейтинг:4
флаг cn

Вам разрешено добавлять настраиваемые ограничения проверки используя эти шаги:

  1. Шаг 1: Определите ограничение:

    Определение ограничения будет помещено в пространство имен Drupal[MODULENAME]\Plugin\Validation\Constraint и будет расширять Symfony\Component\Validator\Constraint. В этом классе определяются типы нарушений ограничений, а также сообщения об ошибках, которые будут отображаться для данных нарушений.

  2. Шаг 2: Создайте проверку для ограничения

    Следующим шагом является создание класса, который будет проверять ограничение. Проверка ограничений будет выполняться в пространстве имен Drupal[MODULENAME]\Plugin\Validation\Constraint и будет расширяться Symfony\Component\Validator\ConstraintValidator. В этом классе будут возвращены представленные значения, и будут зарегистрированы любые нарушения.

    Обратите внимание, что имя вашего класса валидатора по умолчанию должно быть ${ConstraintClassName}Validator. Если вы хотите использовать другое имя, вы можете перезаписать метод validatedBy() вашего класса Constraint, который вы создали на шаге 1.

и на последнем этапе вы можете добавить новое ограничение в свое поле, как ответ, который вы упомянули

теперь, имея эту информацию, вы можете добавить поле ссылки на пользователя в свою таксономию, чтобы каждый термин содержал информацию об авторе, вы можете использовать hook_Entity_Type_presave установить это поле программно

затем вы можете создать собственное ограничение, называемое notUniquePerArthor (или любое имя, которое вам нравится), затем на шаге 2, где вы определяете метод isUniquePerUser, вы можете запустить запрос и получить список терминов таксономии, у которых метка равна значению, а автор равен текущему пользователю, если этот запрос возвращает значение, то это означает, что этот термин не уникален (пользователь определил этот термин ранее), и вы можете вызвать ошибку

флаг cn
Потрясающий! Это выглядит как отличный способ сделать это, за исключением того, что имя термина не является полем, верно? Это как заголовок узла/страницы — он недоступен (насколько мне известно) как поле. Так что мне делать в таком случае?
apaderno avatar
флаг us
@PatrickKenny Заголовок узла представляет собой поле сущности: `$fields['title'] = BaseFieldDefinition::create('string')->setLabel(t('Title'))->setRequired(TRUE)->setTranslatable(TRUE )->setRevisionable(TRUE)->setSetting('max_length', 255)->setDisplayOptions('view', ['label' => 'hidden','type' => 'string','weight' => - 5,]);` Пусть вас не смущает Drupal, показывающий заголовок страницы в блоке.
apaderno avatar
флаг us
То же верно и для названия термина таксономии: `$fields['name'] = BaseFieldDefinition::create('string')->setLabel(t('Name'))->setTranslatable(TRUE)->setRevisionable(TRUE )->setRequired(TRUE)->setSetting('max_length', 255)->setDisplayOptions('view', ['label' => 'hidden','type' => 'string','weight' => - 5,]);`
флаг cn
@apaderno Спасибо, это очень полезно. К сожалению, в `hook_entity_bundle_field_info_alter()` кажется, что поле `name` недоступно, что меня смутило. Дополнительный вопрос здесь: https://drupal.stackexchange.com/questions/305789/how-to-set-a-validation-constraint-for-the-taxonomy-term-name
apaderno avatar
флаг us
@PatrickKenny Это потому, что `hook_entity_bundle_field_info_alter()` предназначено для полей пакета, а имя таксономии является базовым полем, что означает, что оно присутствует в каждом пакете таксономии.
Alireza Tabatabaeian avatar
флаг cn
@PatrickKenny, вы можете использовать `hook_entity_base_field_info_alter` https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_base_field_info_alter/8.2.x, чтобы изменить базовое поле определения, такие как id или title или ...
Рейтинг:3
флаг cn

Спасибо @Alireza Tabatabaeian за это. Я просто публикую свой код, который использовал на основе этого ответа.

К таксономии, к которой я хотел применить ограничение, я добавил field_term_ref_author ссылка сущности на пользователя.

моймодуль.php

функция MYMOUDLE_taxonomy_term_presave(TermInterface $term) {
  $словарь = $term->bundle();
  переключатель ($словарь) {
    случай 'my_vocab_type':
      если ($term->isNew()) {
        // Установить автора (через настраиваемое поле).
        $current_user = \Drupal::currentUser()->id();
        $term->set('field_term_ref_author', $current_user);
      }
    сломать;

функция MYMODULE_entity_base_field_info_alter(&$fields, $entity_type) {
  если ($entity_type->id() === 'taxonomy_term') {
    если (isset($fields['имя'])) {
      $fields['name']->addConstraint('TermNameUniquePerUser');
    }
  }
}

mymodule/src/Plugin/Validation/Constraint/TermNameUniquePerUser.php

<?php

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

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

/**
 * Проверяет уникальность отправленного значения для пользователя.
 *
 * @Ограничение(
 * id = "TermNameUniquePerUser",
 * label = @Translation("Имя термина уникально для каждого пользователя", context = "Проверка"),
 * тип = "строка"
 * )
 */
класс TermNameUniquePerUser расширяет ограничение {
  // Сообщение, которое будет показано, если значение не уникально.
  public $notUnique = 'Вы уже создали термин с именем %value.';

}

mymodule/src/Plugin/Validation/Constraint/TermNameUniquePerUserValidator.php

<?php

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

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

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

  /**
   * {@inheritdoc}
   */
  общедоступная функция проверки ($ элементы, ограничение $ ограничение) {
    foreach ($items as $item) {
      // Далее проверяем уникальность значения.
      если (!$this->isUnique($item->value)) {
        $this->context->addViolation($constraint->notUnique, ['%value' => $item->value]);
      }
    }
  }

  /**
   * Является уникальным?
   *
   * @param строка $значение
   */
  частная функция isUnique($value) {
    $uid = \Drupal::currentUser()->id();
    $term_name_query = \Drupal::entityQuery('taxonomy_term')
      ->условие('имя', $значение, '=')
      ->условие('field_term_ref_author', $uid);
    // Если запрос имеет какие-либо результаты, то он не уникален.
    // Таким образом, мы должны вернуть противоположное тому, есть ли какие-либо результаты.
    вернуть !($term_name_query->выполнить());
  }

}

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

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

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