Как удалить элементы из списка разрешенных значений поля выбора, в котором есть данные для значений?

16

Я создал тип контента, который имеет поле выбора списка / выбора, и я ввел пары ключ | значение, необходимые для функционирования списка выбора.

Данные были введены, и было решено, что определенные условия больше не применяются и их следует удалить.

Однако при попытке удалить указанные термины я получаю следующую ошибку:

Allowed values list: some values are being removed while currently in use.

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

Это самая близкая вещь, которую я смог найти:

https://drupal.org/node/1653012

Он ссылается на плагин d6 и некоторые хитрости патчей, к которым я предпочитаю не прибегать. Если бы мне пришлось в конечном итоге прибегнуть к использованию патча для удаления проверки проверки в этом поле, есть ли какой-то вред, если оставить эти элементы бесхозными на узлах, с которыми они были связаны?

Обновление, я снова столкнулся с этой проблемой с государственным клиентом, у которого за последние 7 лет существования сайта на Drupal было 50 штатов и территорий в списке выбора. Теперь политика изменилась, и территории больше не нужно включать. Возможность удалять предметы из списков выбора очень важна, и поэтому я предлагаю вознаграждение.

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

Я счастлив с чистым решением SQL, чтобы работать в MySQL; или я ищу модуль.

blue928
источник
3
Очевидно, что в жизни проекта ценности будут меняться. Я бы оспорил это - значения для статического списка выбора должны быть определены в начале проекта. Если вам нужно, чтобы он был гибким, вы должны использовать ссылку на термин вместо статического списка. Статические списки предназначены для таких вещей, как секс (мужской / женский), которые, если мы не претерпим серьезного изменения, вряд ли скоро изменятся. И если это произойдет, он будет добавлен , а не удален . Всякий раз, когда я совершал эту «ошибку», я всегда находил лучший способ отступить, выполняя ручные запросы к данным
Клайв
1
Вы хотите сделать этот список динамичным? быть динамичным в создании и удалении.
М ам D
1
Да, я полагаю, что это просто свершившееся мнение - производитель автомобилей всегда будет использовать тип узла или словарь для любого сайта, который я построю. Так как производитель - это категория автомобиля (или категория автомобиля, который кто-то ремонтирует), для меня это больше подходит в качестве таксономии, а не типа контента. Но я знаю, что это не помогает ... Я бы с осторожностью оставил бесхозные данные в БД, очень трудно сказать, какой эффект это может иметь, не зная точно, что установлено на вашем сайте и как оно настроено
Клайв
1
Что не так с views_bulk_operations?
Donquixote
1
хех, ни у одного из этих ответов еще нет никаких голосов: /
tenken

Ответы:

7

Недавно я сделал что-то подобное со следующим подходом.

  1. Добавьте новые допустимые значения.
  2. Добавьте параметр для настройки «активных» значений.
  3. Отфильтруйте «неактивные» значения из отображения на форме.

например:

/**
 * Admin settings form
 */
function MODULE_admin_settings(){

  $form = array();

  // Select active preferences for display
  $field = field_info_field('field_preferences');
  $preferences = list_allowed_values($field);
  $form['field_preferences_active'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Active preferences'),
    '#options' => $preferences,
    '#description' => t('Select the preferences available for user selection.'),
    '#default_value' => variable_get('field_preferences_active', array()),
  );

  return system_settings_form($form);

}

/**
 * Implements hook_field_attach_form
 */
function MODULE_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {

  // Filter out inactive preferences
  if(isset($form['field_preferences'])){
    $preferences = variable_get('field_preferences_active', array());
    foreach($preferences as $key => $preference){
      // If this preference isn't checked, but is set in the field values, unset it.
      if(empty($preference) && isset($form['field_preferences'][LANGUAGE_NONE]['#options'][$key])){
        unset($form['field_preferences'][LANGUAGE_NONE]['#options'][$key]);
      }
    }
  }

}

Таким образом, унаследованные данные сохраняются для справки, форма проверяется, а целостность данных остается неизменной.

Дэвид Томас
источник
1
Эта опция, по сути, не является деструктивной (т.е. скрывает, а не удаляет вещи) и, вероятно, является лучшей отправной точкой, пока вы не сможете определить наилучший способ действий для любых объектов, у которых есть устаревшие параметры.
mpdonadio
3

Как я знаю, все данные полей хранятся в 2 таблицах: field_data_field_FIELDNAME и field_revision_field_FIELDNAME. И я нашел подтверждение моей мысли здесь: /programming//a/7773117/1300562

Таким образом, чтобы удалить ненужные значения полей, необходимо удалить эти значения из вышеупомянутых таблиц, а затем удалить их из списка допустимых значений.

Шаг 1.

$values_to_remove = array('value1', 'value2'); // an array of unnecessary values
$fieldname = 'FIELDNAME'; // name of your field. For example,
                          // 'territory' for field with machine name 'field_territory'
$entity_type = 'node'; // it's 'node' in your case, but it can be 'taxonomy_term' or something else

db_delete('field_data_field_' . $fieldname)
  ->condition('entity_type', $entity_type)
  ->condition('field_' . $fieldname . '_value', $values_to_remove)
  ->execute();

db_delete('field_revision_field_' . $fieldname)
  ->condition('entity_type', $entity_type)
  ->condition('field_' . $fieldname . '_value', $values_to_remove)
  ->execute();

Шаг 2.
Удалите ненужные пары ключ | значение на странице настроек поля и отправьте форму для сохранения изменений.
После этого кэш должен очищаться автоматически, но если вы все еще можете видеть значения удаленных полей на страницах узла, очистите кеш вручную.

PS Недавно я столкнулся с подобной проблемой, и теперь я предпочитаю использовать поля типа «Ссылка на термин» или (еще лучше) «Ссылка на объект» вместо списка текстовых значений. При использовании ссылочного поля вы можете создать отдельный словарь для каждого поля и просто создавать / редактировать / удалять термины в любое время.

quotesBro
источник
Если поле повторяется, то эти запросы не будут корректировать дельты для оставшихся данных.
mpdonadio
1

Прежде всего, проверьте, есть ли у вас какие-либо допустимые значения, указанные в поле? Если вы это сделаете, другой вариант не будет проверен. Поэтому попробуйте сначала удалить значения из вкладки «Настройки поля».

В качестве альтернативы у вас есть 2 варианта:


1.

Удалите все значения, которые вы поместили в список разрешенных значений, которые используются учетными записями пользователей. Например, вы можете выполнить запрос SQL, чтобы найти эти:

SELECT * FROM field_data_field_MYFIELDNAME WHERE entity_type = 'user' and value = 'MY VALUE'

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


2.

Если вы не хотите удалять значения из полей, это может быть достигнуто путем взлома.

Внимание, это не предлагаемое решение для производства, и вы должны знать, что вы делаете!

  1. Найти и редактировать модули / field / field.module
  2. Найдите функцию field_has_data () и добавьте return TRUE;в первую строку функции.

    function field_has_data($field) {
      return FALSE; // HACK !!!
      $query = new EntityFieldQuery();
  3. Повторно сохраните поле со значениями, которые вы хотите.
  4. Удалить взломать, как только вы это сделаете.
kenorb
источник
0

Я думаю, что вы действительно можете сделать это с помощью модуля Bulk Operations .

  1. добавьте новую опцию в это поле, которое вы хотите заменить. например: na | NA
  2. создать узел View to list, содержащий с этим полем
  3. добавить поля «Массовые операции: содержимое» в этом представлении
  4. установите флажок «Изменить значения объекта» и «Показать доступные токены» (выберите «Все» в отображаемых значениях)
  5. Добавьте поле, которое вы хотите изменить, в Критерии фильтра и «выставьте» этот фильтр.
  6. установить URL-путь к этому представлению
  7. Перейти на эту страницу просмотра и изменить
  8. Теперь используйте функции экспозиции и операций для изменения опции поля
  9. Выполнено
CocoSkin
источник
0

Вот улучшение ответа HL, которое я считаю лучшим:

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

Помимо Bulk Operations , вам необходимо установить и включить модуль Администрирования Views . С этим модулем у вас уже есть готовое представление с включенными массовыми операциями (просто смотрите admin / content после включения). Потом:

1) Зайдите в админ / структуру / просмотры и отредактируйте представление «Администрирование: Узел»

2) Добавьте отображение новой страницы для просмотра, используя кнопку «Добавить -> Страница» сверху

3) Назначьте путь к новому дисплею: ​​пример admin / content / custom

4) Добавьте новый фильтр для выбранного поля: выберите оператор «is one of», а затем выберите все параметры, которые вы хотите удалить.

5) Сохранить вид

6) Зайдите в admin / content / custom Теперь вы видите весь контент, который вам нужно массово редактировать (измените значение для вашего поля выбора)

7) Выберите все строки, установив первый флажок слева от таблицы (если имеется более одной страницы, также выберите кнопку с надписью «Выбрать все X строк в этом представлении»)

8) Выберите операцию «изменить значение» и нажмите «Выполнить»

9) Для вашего поля выбора выберите новое значение, чтобы перезаписать те, которые вы хотите удалить

10) Установите флажок для этого поля выбора

11) Нажмите Далее, и все готово

Роджер
источник
0

Похоже, что ваша проблема Drupal основана на более глубокой проблеме с данными: что происходит с сущностями, которые в настоящее время используют устаревшие значения списка? Этот вопрос лежит в основе сообщения об ошибке, которое посылает вам Drupal.

Давайте внимательнее рассмотрим пример вашего штата / территории. Ваш клиент использует систему, которая обрабатывает штаты и территории одинаково в течение многих лет и создала огромную группу узлов, которые содержат как штаты, так и территории. Затем однажды полномочия решают, что территории должны обрабатываться по-другому, и что раскрывающийся список для присвоения региона больше не должен содержать территории. Отлично. Просто создайте представление, которое использует стандартные фильтры, чтобы отобразить список всех узлов территории, и используйте массовые операции представлений, чтобы изменить все значения их регионов на ... что ... какое-то 51-е состояние называется другим, может быть? Судьба территорий - очень серьезный вопрос. Ваше решение должно включать метод сохранения или изменения статуса территории. Вам может понадобиться создать новое поле списка под названием «Территория»

Вам нужно будет использовать правила с View Bulk Operations для выполнения этих изменений. Если вы мало знаете о правилах, пожалуйста, уделите немного времени, чтобы узнать, как они работают. Правила дают вам возможность манипулировать информацией на основе триггеров, условий и действий. После изучения правил вы можете обнаружить, что ответы, которые вы ищете, будут интуитивно понятны. По сути, вам нужно будет создать правило, которое запускается массовыми операциями, которое будет нацелено на все территории и удалять, переназначать, переименовывать или иным образом отделять их от основной части информации. Правило должно быть в состоянии каким-либо образом сохранять состояние территории, в то же время устанавливая раскрывающийся список состояний в статус «другое» или «N / A». Это может быть все, что нужно. В противном случае...

После переназначения необходимо выполнить простую операцию, чтобы изменить исходное поле списка и удалить названия территорий. Однако, если система по-прежнему не позволяет вам изменять список, вам может потребоваться создать новое поле списка, а затем использовать Bulk Operation и Rules для просмотра всех текущих значений состояния и переназначить их новому списку. Правила могут работать с «Массовыми операциями в представлениях», предназначаясь для всех соответствующих узлов и воздействуя на них на основе значений полей. Задать значение нового поля списка на основе значения существующего поля списка для группы узлов легко при использовании правил.

Также помните, что если у Drupal возникают проблемы с операцией, всегда очищайте кеш, прежде чем рассматривать трудную альтернативу.

Hoytman
источник
0

Я бы предположил, что ваш клиент хочет, чтобы унаследованный контент сохранил свое первоначальное значение, а это означает, что изменение списка выбора фактически уничтожит все предыдущие данные. Если это не проблема, то любой другой ответ, вероятно, сработает. Однако, если это так, вы не сможете изменить список выбора, не потеряв историю данных. Я мог бы пойти намного более простым путем, чтобы учесть исторические данные, в то же время делая сайт немного более ориентированным на будущее - я бы предложил использовать полевые разрешения:

* установить новое поле для этого списка выбора, используя таксономию вместо статических данных

* установить разрешение поля для существующего списка выбора как ВИД, но не РЕДАКТИРОВАТЬ кем-либо, кроме администратора

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

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

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

Geoff
источник
0

Простой скрипт на помощь! Мы обновляем данные полей и таблицы изменений полей и заменяем старые значения новыми, прежде чем вручную изменять настройки полей.

Если у нас есть что-то подобное в наших текущих настройках поля:

&date=today|today
&date=last2days|last2days

и хочу заменить его следующим:

date=today|today
date=last2days|last2days

Сначала мы запускаем скрипт drush, а затем меняем настройки поля в интерфейсе администратора.

Примечание. Этот код предназначен для поля с именем машины field_foo_bar.

    $field_name = 'foo_bar';

    print "for {$field_name}...\n";

    replace_field("&date=today", "date=today", $field_name);

    replace_field("&date=last2days", "date=last2days", $field_name);

    function replace_field($old_value, $new_value, $field_name, $entity_type='node') {
      print "Replacing {$old_value} with {$new_value}...\n";
      $data_count = replace_options_data_field($field_name, $entity_type, $old_value, $new_value);
      $revision_count = replace_options_revision_field($field_name, $entity_type, $old_value, $new_value);
      print $data_count + $revision_count . " entries replaced.\n";
    }

    function replace_options_data_field($field_name, $entity_type, $old_value, $new_value) {
      $num_updated = db_update('field_data_field_' . $field_name)
        ->fields(array(
                   'field_' . $field_name . '_value' => $new_value,
                 ))
        ->condition('entity_type', $entity_type)
        ->condition('field_' . $field_name . '_value', $old_value)
        ->execute();
      return $num_updated;
    }

function replace_options_revision_field($field_name, $entity_type, $old_value, $new_value) {
  $num_updated = db_update('field_revision_field_' . $field_name)
    ->fields(array(
               'field_' . $field_name . '_value' => $new_value,
             ))
    ->condition('entity_type', $entity_type)
    ->condition('field_' . $field_name . '_value', $old_value)
    ->execute();
  return $num_updated;
}
Бадри
источник
0

Я использовал 2-е предложение kenorb, и оно работало для обновления списка значений в поле Drupal 7.52, Profile2 7.x-1.3. Поэтому, если вы получили предупреждение drupal: «Список допустимых значений: некоторые значения удаляются, когда они используются в данный момент». Следующее позволило мне удалить значения из поля (profile2), не удаляя и не заменяя их в базе данных.

В корневом каталоге ядра Drupal есть папка под названием modules, а файл для редактирования находится по адресу: modules / field / field.module. ЭТО ОСНОВНОЙ ФАЙЛ, вы должны полностью отменить свои изменения, когда закончите обновление значений. Я перевел сайт в автономный режим, временно заменил следующий блок кода в (корень друпала) /modules/field/field.module

function field_has_data($field) {
  $query = new EntityFieldQuery();
  $query = $query->fieldCondition($field)
    ->range(0, 1)
    ->count()
    // Neutralize the 'entity_field_access' query tag added by
    // field_sql_storage_field_storage_query(). The result cannot depend on the
    // access grants of the current user.
    ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');

  return (bool) $query
    ->execute() || (bool) $query
    ->age(FIELD_LOAD_REVISION)
    ->execute();
}

ТОЧНО

function field_has_data($field) { 
    return FALSE; // hack 
    $query = new EntityFieldQuery();
}

И друпал перестал жаловаться, и я смог изменить список. (В моем случае это факультет в списке ценностей, которые покинули университет, но все еще связаны с записями студентов, как их советник, наставник и т. Д.)

Майкл Мартель
источник