5

I have a use case where I need to create a copy of an entity (commerce product) that is home to various field collections.

the entity is created by a simple load/save combo:

// load entity
$old_entity = commerce_product_load_by_sku($sku);

// copy 
$new_entity = $old_entity;

// alter copy so it can be saved as a new entity
$new_entity->status = 0;
$new_entity->title = $old_entity->title . '(COPY)';
$new_entity->is_new = TRUE;
// [...] and a few more unsets (created, revision, copying translations...)

// ->>> missing field_collection clone / exchange of id references in the entity here <<<-

// save entity
commerce_product_save($new_entity);

As the field_collection id stored in the entity remains unchanged, both entities now share the field collection which leads to unwanted effects.

Can someone point me to a reference on how to create copies of field_collections and get their id's returned, so I can exchange them in the parent entity before saving it? ... or maybe there is an even better way to deal with this?

closed as off-topic by kenorb, Adrian Cid Almaguer, Krishna Mohan, No Sssweat, Scott Joudry Mar 21 '16 at 16:35

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question was caused by a problem that can no longer be reproduced, was solved by a cache clear, or was a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers." – kenorb, Adrian Cid Almaguer, Krishna Mohan, No Sssweat, Scott Joudry
If this question can be reworded to fit the rules in the help center, please edit the question.

4

This has been solved by chalee on d.o on the following issue: Integrate node_clone with field_collection module.

This is his function that works just fine for my use case:

<?php
function clone_fc_items($entity_type, &$entity, $fc_field, $language = LANGUAGE_NONE){
  $entity_wrapper = entity_metadata_wrapper($entity_type, $entity);
  $old_fc_items = $entity_wrapper->{$fc_field}->value();
  if (!is_array($old_fc_items)) {
    $old_fc_items = array($old_fc_items);
  }

  $field_info_instances = field_info_instances();
  $field_names = element_children($field_info_instances['field_collection_item'][$fc_field]);

  unset($entity->{$fc_field}[$language]);

  foreach ($old_fc_items as $old_fc_item) {
    $old_fc_item_wrapper = entity_metadata_wrapper('field_collection_item', $old_fc_item);
    $new_fc_item = entity_create('field_collection_item', array('field_name' => $fc_field));
    $new_fc_item->setHostEntity($entity_type, $entity);
    $new_fc_item_wrapper = entity_metadata_wrapper('field_collection_item', $new_fc_item);

    foreach ($field_names as $field_name) {
        //if (is_array($old_fc_item->{$field_name})){
            if (!empty($old_fc_item->{$field_name})){
                $new_fc_item->{$field_name} = $old_fc_item->{$field_name};
            }
        //}   
    }
    $new_fc_item_wrapper->save();

    //Now check if any of the fields in the newly cloned fc item is a field collection and recursively call this function to properly clone it.
    foreach ($field_names as $field_name) {
        if (!empty($new_fc_item->{$field_name})){
            $field_info = field_info_field($field_name);
            if ($field_info['type'] == 'field_collection'){
                clone_fc_items('field_collection_item',$new_fc_item, $field_name,$language);
            }    
        }
    }

  }
}
?>

Again, kudos goes to @chalee - thanks :)

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