You are here

public function FieldCloner::cloneField in Field tools 8

Clone a field to a new entity type and bundle.

It is assumed that the caller has already checked that no field of this name exists on the destination bundle. TODO: check for this and throw an exception.

Parameters

\Drupal\field\FieldConfigInterface $field_config: The field config entity to clone.

string $destination_entity_type_id: The entity type to clone the field to. If this is different from the source field, then one of the following will happen:

  • a) a new field storage is created
  • b) an existing field storage is used, if its type matches the source field.
  • c) an exception is thrown if the existing type does not match.

string $destination_bundle: The destination bundle.

Throws

\Drupal\Core\Field\FieldException Throws an exception if there is already a field storage with the same name on the target entity type, whose type does not match the given field.

File

src/FieldCloner.php, line 65

Class

FieldCloner
Contains methods for cloning fields.

Namespace

Drupal\field_tools

Code

public function cloneField(FieldConfigInterface $field_config, $destination_entity_type_id, $destination_bundle) {

  // Get the entity type and bundle of the original field.
  $field_config_target_entity_type_id = $field_config
    ->getTargetEntityTypeId();

  // If the destination entity type is different from the source field, also
  // clone the field storage.
  if ($destination_entity_type_id != $field_config_target_entity_type_id) {

    // Check there isn't already a field storage on the target entity type.
    $field_storage_config_ids = $this->entityTypeManager
      ->getStorage('field_storage_config')
      ->getQuery()
      ->condition('entity_type', $destination_entity_type_id)
      ->condition('field_name', $field_config
      ->getName())
      ->execute();
    if (empty($field_storage_config_ids)) {

      // Create a new field storage, copying the one from the source field.
      $source_field_storage_config = $field_config
        ->getFieldStorageDefinition();
      $new_field_storage_config = $source_field_storage_config
        ->createDuplicate();
      $new_field_storage_config
        ->set('entity_type', $destination_entity_type_id);
      $new_field_storage_config
        ->save();
    }
    else {

      // Load the existing field storage, and check its type.
      $existing_field_storage_config = $this->entityTypeManager
        ->getStorage('field_storage_config')
        ->load(reset($field_storage_config_ids));
      if ($existing_field_storage_config
        ->getType() != $field_config
        ->getType()) {
        throw new FieldException(t("A field with a different type already exists on destination entity type @entity-type.", [
          '@entity-type' => $destination_entity_type_id,
        ]));
      }
    }
  }

  // Create and save the duplicate field.
  $new_field_config = $field_config
    ->createDuplicate();
  if ($destination_entity_type_id != $field_config_target_entity_type_id) {
    $new_field_config
      ->set('entity_type', $destination_entity_type_id);

    // Make the field use newly created storage.
    if (isset($new_field_storage_config)) {
      $new_field_config
        ->set('fieldStorage', $new_field_storage_config);
    }
  }
  $new_field_config
    ->set('bundle', $destination_bundle);
  $new_field_config
    ->save();

  // Copy the field's display settings to the destination bundle's displays,
  // where possible.
  $this
    ->copyDisplayComponents('entity_form_display', $field_config, $destination_entity_type_id, $destination_bundle);
  $this
    ->copyDisplayComponents('entity_view_display', $field_config, $destination_entity_type_id, $destination_bundle);
}