Як я можу видалити елементи зі списку дозволених значень із вибраного поля, у якому є дані для значень?


16

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

Дані було введено, і було вирішено, що певні терміни більше не застосовуються і їх потрібно видалити.

Однак, намагаючись видалити зазначені терміни, я отримую таку помилку:

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

Очевидно, що в житті проекту цінності будуть змінюватися. Який практичний спосіб видалити елементи, коли вузли асоціюються із переліченими термінами?

Це про найближче, що я міг знайти:

https://drupal.org/node/1653012

У ньому згадується плагін d6 та деякі хитрощі з виправленнями, які я не вважаю за краще використовувати. Якщо мені доведеться врешті-решт вдатися до використання патча, щоб зняти перевірку перевірки на цьому полі, чи є якась шкода від того, щоб залишити ці предмети сиротами на вузлах, з якими вони були пов'язані?

Оновлення, я знову зіткнувся з цим питанням із державним клієнтом, який за останні 7 років існування сайту Drupal мав 50 країн і територій у списку вибору. Тепер політика змінилася і територій більше не потрібно включати. Можливість видалення предметів із списків вибору важлива, і тому я пропоную виграшну суму.

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

Я задоволений чистим рішенням SQL для запуску в MySQL; або, я шукаю модуль.


3
Очевидно, що в житті проекту цінності будуть змінюватися. Я заперечу проти цього - значення для статичного списку вибору слід визначити на початку проекту. Якщо вам це потрібно для гнучкості, вам слід використовувати термін посилання замість статичного списку. Статичні списки стосуються таких речей, як секс (чоловіки / жінки), які, якщо ми не зазнаємо серйозних зрушень у речах, швидше за все не зміниться. І якщо це станеться, він буде доданий , а не видалений . Щоразу, коли я робив цю "помилку", я завжди знаходив найкращий спосіб відмовитись - це запускати вручну запити на дані
Clive

1
Ви хочете зробити цей список динамічним? бути динамічним у створенні та видаленні.
M ama D

1
Так, я вважаю, що це лише до думки - виробник автомобілів завжди був би типом вузла або словником для будь-якого сайту, який я буду будувати. Оскільки виробник - це категорія автомобілів (або категорія автомобілів, які хтось ремонтує), це має для мене сенс як систематика, а не тип вмісту. Але я знаю, що це не допомагає ... Мені б насторожено залишати дані сироти в БД, дуже важко сказати, який ефект може мати, не знаючи, що саме встановлено на вашому сайті та як він налаштований
Clive

1
Що не так у view_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 Нещодавно я зіткнувся з подібною проблемою, і тепер я вважаю за краще використовувати поля типу "Посилання на термін" або (ще краще) "Посилання на об'єкт" замість списку текстових значень. Використовуючи довідкове поле, ви можете створити окремий словник для кожного поля та просто створити / редагувати / видалити терміни в будь-який час.


Якщо поле повторюється, ці запити не будуть коригувати дельти для решти даних.
mpdonadio

1

Перш за все перевірте, чи є в полі вказані дозволені значення? Якщо ви це зробите, то інший варіант не буде затверджений. Тому спробуйте спочатку видалити значення на вкладці Налаштування поля.

Крім того, у вас є два варіанти:


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. Видаліть злом, як тільки це зробите.

0

Я думаю, що ви насправді можете це зробити, використовуючи модуль « Перегляд масових операцій» .

  1. додайте нову опцію в поле, яке ви хочете замінити. наприклад: na | NA
  2. створити вузол Перегляд списку, що містить це поле
  3. додайте поля "Масові операції: Вміст" у цей вид
  4. встановіть прапорець "Змінити значення сутності" та "Показати доступні маркери" (виберіть Усі на дисплейних значеннях)
  5. Додайте поле, яке ви бажаєте змінити, у "Критерії фільтру" та "виставіть" фільтри
  6. встановити URL-адресу Шлях у цьому поданні
  7. Перейдіть на цю сторінку перегляду та змініть
  8. Тепер використовуйте функції експонування та операцій, щоб змінити параметр поля
  9. Зроблено

0

Ось поліпшення відповіді HL, яке я вважаю найкращим:

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

Окрім масових операцій Views , вам потрібно буде встановити та включити модуль Administrators Views . З цим модулем у вас вже є перегляд поза вікном із активованими масовими операціями (просто дивіться адміністратор / вміст, як тільки це ввімкнено). Потім:

1) Перейдіть до адміністратора / структури / перегляньте правки "Адміністрація: Вузол"

2) Додати перегляд нової сторінки для перегляду за допомогою кнопки "Додати -> Сторінка" вгорі

3) Призначте шлях до нового дисплея: Приклад адміністратора / вмісту / користувальницького

4) Додайте новий фільтр для вибраного поля: Виберіть оператора "є одним із", а потім виберіть усі параметри, які потрібно видалити

5) Збережіть подання

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

7) Установіть усі рядки, натиснувши перший прапорець ліворуч таблиці (якщо є більше однієї сторінки, також виберіть кнопку, на якій буде сказано "Вибрати всі X рядки в цьому вікні")

8) Виберіть операцію "змінити значення" і натисніть "Виконати"

9) Для обраного поля виберіть нове значення, щоб перезаписати ті, які потрібно видалити

10) Установіть прапорець у цьому полі вибору

11) Клацніть Далі, і ви закінчите


0

Здається, що ваша проблема Drupal заснована на більш глибокій проблемі даних: Що відбувається з суб'єктами, які зараз використовують значення амортизованого списку? Це питання лежить в корені повідомлення про помилку, яке надсилає Drupal.

Давайте докладніше розглянемо приклад вашої держави / території. Ваш клієнт вже протягом багатьох років використовує систему, яка обробляє держави і території однаково, і створила величезну групу вузлів, що містять і держави, і території. Потім одного дня повноваження, які вирішують, що з територіями потрібно по-різному оброблятись, і що спадне місце для призначення регіону більше не повинно містити територій. Чудово. Просто створіть подання, яке використовує стандартні фільтри для відображення списку всіх територіальних вузлів і використовуйте масові операції Views для зміни всіх значень своїх регіонів на ... що ... якийсь 51-й стан називається іншим? Доля територій - дуже серйозне питання. Ваше рішення повинно включати метод збереження або переселення статусу території. Вам може знадобитися створити нове поле списку під назвою "Територія"

Вам потрібно буде використовувати правила з переглядом групових операційДля виконання цих змін . Якщо ви мало знаєте про правила, знайдіть трохи часу, щоб дізнатися, як вони працюють. Правила дають можливість маніпулювати інформацією на основі тригерів, умов та дій. Дізнавшись про правила, ви можете виявити, що відповіді, які ви шукаєте, інтуїтивно представлять себе. В основному, вам потрібно буде створити правило, яке ініціюється масовою операцією, яка буде націлена на всі території та видалити, перепризначити, перейменувати або іншим чином відокремити їх від основного масиву інформації. Правило повинно бути в змозі певним чином зберігати стан території, одночасно встановлюючи спадне положення стану "інше" або "N / A". Це може бути все, що потрібно. Інакше ...

Після переназначення буде простою операцією змінити оригінальне поле списку та видалити назви територій. Однак якщо система все ще не дозволяє вам змінити список, можливо, вам знадобиться створити нове поле списку, а потім скористайтеся пунктами «Перегляд масових операцій і правила» для перегляду всіх поточних значень стану та переназначення їх до нового списку. Правила можуть працювати з операціями «Перегляд масових операцій», щоб орієнтуватися на всі відповідні вузли та діяти на них на основі значень поля. Встановити значення нового поля списку на основі значення наявного поля списку для групи вузлів легко, коли ви використовуєте Правила.

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


0

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

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

* встановити дозвіл поля для існуючого списку вибору як VIEW, але не EDIT будь-ким, окрім адміністратора

При цьому старе поле має залишатися доступним для перегляду та пошуку (додайте новий заголовок, що відображає його лише як спадщину), але не може бути редагованим. Це, звичайно, сильно залежить від користувацьких пошуків, переглядів тощо, які, можливо, потребуватимуть коригування.

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

Звичайно, ви можете зробити це на крок далі за допомогою спеціального одноразового модуля для копіювання даних зі старого списку вибору у нову систематику.


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

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

У кореневому каталозі ядра Drupal є папка під назвою модулі, а файл для редагування знаходиться за адресою: module / field / field.module. ЦЬОГО ЗАВДАННЯ ФАЙЛ, ви повинні абсолютно відновити зміни, коли виконано оновлення значень. Я взяв сайт в автономному режимі, тимчасово замінив наступний блок коду в (drupal root) /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();
}

І drupal перестав скаржитися, і я зміг змінити список. (У моєму випадку це факультет у списку цінностей, які вийшли з університету, але все ще пов'язані із записом студентів, як їх радника, наставника тощо)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.