0

I need to convert a field on a paragraph from the string_long type to the text_long type.

There is data in the field so I can't change it in the UI.

How would I do this programmatically?

3

2 Answers 2

3

Here's the solution I came up with based on the example code provided by https://drupal.stackexchange.com/users/71454/miststudent2011. I had to adapt it a bit for this specific case:

/**
 * Convert plain text field to formatted text field.
 */
function mymodule_update_9002() {
  $entity_type = 'paragraph';
  $field = 'field_paragraph_variant';

  // Retrieve existing field data.
  $database = \Drupal::database();
  $tables = [
    "{$entity_type}__$field",
    "{$entity_type}_revision__$field",
  ];
  $existing_data = [];
  foreach ($tables as $table) {
    // Get the old data.
    $existing_data[$table] = $database->select($table)
      ->fields($table)
      ->execute()
      ->fetchAll(PDO::FETCH_ASSOC);
  }

  // Get the field config.
  $field_storage = \Drupal::entityTypeManager()->getStorage('field_storage_config');
  $field_storage_config = $field_storage->loadByProperties(['field_name' => $field]);

  foreach ($field_storage_config as $field_storage) {
    // Save the config as an array and change the type.
    $new_field_storage = $field_storage->toArray();
    $new_field_storage['type'] = 'text_long';

    // Delete the original field, otherwise the new table columns won't get added.
    $field_storage->delete();

    // Re-create the field.
    $new_field_storage = $field_storage->create($new_field_storage);
    $new_field_storage->enforceIsNew(TRUE);
    $new_field_storage->save();
  }

  // Restore the data.
  foreach ($tables as $table) {
    $insert_query = $database
      ->insert($table)
      ->fields([
        'bundle',
        'deleted',
        'entity_id',
        'revision_id',
        'langcode',
        'delta',
        $field . '_value',
        $field . '_format',
      ]);
    foreach ($existing_data[$table] as $row) {
      $row[$field . '_format'] = 'subscriber_text';
      $insert_query->values(array_values($row));
    }
    $insert_query->execute();
  }
}
0

There is now a module for that: https://www.drupal.org/project/field_type_converter

As mentioned in the module page, you can implement a hook_post_update_NAME with this code to convert the field_foo in nodes into a long_text.

function hook_post_update_NAME(&$sandbox) {
  $field_map['node'] = [
    'field_foo' => 'text_long',
  ];
  return \Drupal\field_type_converter\FieldTypeConverter::processBatch($sandbox, $field_map);
}

Don't forget to run drush updated in order to execute this conversion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.