Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
The field collection module allows you to add groups of fields in to a single field on to a node. The group of fields is simply an entity. When you use node clone to clone a node the reference to the entity is preserved. I think it would be better in most cases to create a new field collection entity and clone the existing values, otherwise if you change the field collection in one spot it updates on both nodes.
Comment | File | Size | Author |
---|---|---|---|
#35 | field_collection-clone-1233256-35.patch | 1.07 KB | gregory_kapustin |
Comments
Comment #1
chalee CreditAttribution: chalee commentedThis is quite an important issue. I have experienced the problem here. I cloned a node with a multi-value field_collection field. Just deleting one item of the field in the cloned node made both nodes inaccessible showing the error below. I subscribe to the suggestion made above to create a separate instance of the entity.
-----------------------------------------------------------------------------------------------------------------------
Recoverable fatal error: Argument 2 passed to field_collection_item_access() must be an instance of FieldCollectionItemEntity, boolean given, called in ...\sites\all\modules\field_collection_table\field_collection_table.module on line 76 and defined in field_collection_item_access() (line 488 of ...\sites\all\modules\field_collection\field_collection.module).
-----------------------------------------------------------------------------------------------------------------------
Comment #2
valderama CreditAttribution: valderama commentedHi, I am also working with field_collections and node_clone here. I would also be happy to have this feature, just as mstrelan desscribed.
Can it be achieved using hook_clone_node_alter in the meanwhile? I think I'll give a try..
Comment #3
chalee CreditAttribution: chalee commented@valderama: I have managed to do it so yes it can be done.
First you reset the field_collection_item values which have been copied by node_clone using unset function as below:
Then you create your new items using Entity API methods as below:
Remember this: When you save the field_collection_item it also saves the parent node. The consequence of this is that you will have duplicate clones if you are using the "Pre-populate the node form fields " method of node_clone. Therefore you must use the "Save as a new node then edit" method to avoid the duplicates. You can set this in node_clone's configuration page admin/config/content/clone
I hope this will help you.
Comment #4
valderama CreditAttribution: valderama commentedthanks, chalee - that are actually valuable hints!
I think you can avoid saving the host entity by passing TRUE to field_collection_item->save( $skip_host_save = TRUE );
Comment #5
chalee CreditAttribution: chalee commented@valderama:Thanks for your hint about $skip_host_save = TRUE
Comment #6
clashar CreditAttribution: clashar commented+1
Comment #7
Anonymous (not verified) CreditAttribution: Anonymous commentedHi chalee,
Thanks for your insights on this issue. This type of functionality is crucial for a future Drupal 7 site that I will be building.
Could you clarify a little further on how you implemented your suggested code?
I'd appreciate any help you can give.
Thanks!
Tony
Comment #8
Anonymous (not verified) CreditAttribution: Anonymous commentedHi chalee,
Thanks for your insights on this issue. This type of functionality is crucial for a future Drupal 7 site that I will be building.
Could you clarify a little further on how you implemented your suggested code?
I'd appreciate any help you can give.
Thanks!
Tony
Comment #9
chalee CreditAttribution: chalee commented@tonylrm: I added a hook function called MY_MODULE_NAME_clone_node_alter(&$node, $context) inside MY_MODULE_NAME.module file. Inside that function I added the code in #3 above.
Comment #10
Anonymous (not verified) CreditAttribution: Anonymous commented@chalee: Thanks for your assistance.
I have implemented your suggestion but have 2 remaining issues. I would appreciate it if I could get your assistance again...
1) After cloning..the values of the field collection items all state 'NEW VALUE'. I would like to have the values of the cloned field collection items the same as the original values. Did i do something incorrect?
2) The origial node's field collection is set to unlimited values... when cloning it only creates a single set of field collection items. Can you suggest modifications to your code that would enable cloning mulitple values of field collection items?
Thanks again!!!
Comment #11
chalee CreditAttribution: chalee commented1. The code snippet I gave in #3 is just a sample, that you have to change accordingly to use correct field names and assign correct values.
2. You need a 'foreach' loop to process all the items.
Try the function below which should ideally do everything you requested. Put the function in your .module file and call it inside the MY_MODULE_NAME_clone_node_alter() passing it the correct variable names for node and the field_collection field. Please note that this function is untested. I just wrote it directly here. Give feedback after testing it.
Comment #12
kugta CreditAttribution: kugta commentedSubscribe
Comment #13
chalee CreditAttribution: chalee commented@tonylrm: Did you try my function in #11 above?
Comment #14
Summit CreditAttribution: Summit commentedSubscribing, greetings, Martijn
Comment #15
jox CreditAttribution: jox commented@chalee: thanks for the code in #11. Here is the code I ended up while trying to make it work:
Note that if the field collection contains date fields, it will produce an error. This is because the Date module does not provide entity property setters for the date fields. See #1153766: provide a property setter callback
At the moment my workaround for this is by copying the raw array instead of using field->set() for my date fields.
Replacing:
With:
(This is customized for my specific date field named 'field_time_range'.)
Comment #16
chalee CreditAttribution: chalee commented@jox: Thanks for the improvements to the code. I had noted the 3 issues you raised about my code in #11 but had not had time to figure out how to solve them. I guess we have to wait for #1153766: provide a property setter callback for the date issue before we can fully have a generic, not hardcoded, function to use.
Comment #17
jox CreditAttribution: jox commented@chalee: I have noticed that node_clone does properly clone date fields, if they are normal fields in the host node. This is because the fields do really just get raw copied (because of "$node = clone $original_node").
So why not doing this for the field_collection data as well. In fact, the entity method "$new->set($old->value())" should end up exactly the same (if not, something is wrong). It is actually an indirection.
Any field that would not get properly copied like this, would need a special handling anyway. That would be any field referencing something that should get cloned as well. A nested field_collection would be an example (if that is possible yet at all).
So, in my opinion, for now, the best generic base solution would be using the copy method all the time:
I'm running this right now with no problems so far. A field_collection with a bunch of field types (including a date range, text, list, float values and a custom field) get cloned perfectly.
One benefit is also, that it will not be affected by any bugs or incompletenesses in the entity field (or metadata) API implementation of fields (which is the problem we had).
Comment #18
chalee CreditAttribution: chalee commented@jox: Very good improvements again. I tested the code and it works well except that it fails if the field collection (fc) field is single-valued. The reason is that in line 4
$node_wrapper->{$fc_field}->value() function returns an object and not array for a single-valued fc, yet the following foreach statement is expecting an array. So to correct this I replaced line 4 with the following code to make sure that when we get to the foreach statement the variable $old_fc_items will always be an array.
Comment #19
jox CreditAttribution: jox commented@chalee: Oh, great you discovered that!
Here's a slightly shorter version that does the same:
For convenience I'll post the updated function again:
Comment #20
chalee CreditAttribution: chalee commented@jox: I have made a few more changes to cater for fc embedded within fc.
1. Added few lines to check if a field is a field collection and recursively call the same function to clone it.
2. Added two function parameters: $entity_type and $language. I could not find a uniform way to get these from the passed entity object.
3. Renamed some variables to reflect the fact that any entity not necessarily a node could be passed.
4. I removed the if (is_array($old_fc_item->{$field_name})){ which is not necessary since we are using the field_info_instances function to get the field list.
Comment #21
charlie-s CreditAttribution: charlie-s commented@chalee: Can you post a sample of the function call? Is it:
Or does entity_type and entity refer to the field collection?
Edit: I was a little hesitant to try this without getting confirmation since I didn't want to mess up any existing nodes (and have a single field collection attached to multiple nodes) but I gave it a shot and it works brilliantly. Here's what I'm running, so others can see.
clone_fc_items()
is pulled verbatim from #20.Comment #22
mrconnerton CreditAttribution: mrconnerton commentedI like the code produced here. I need this functionality right now so I'm going to implement this as a patch to field_collection module as I said here #1304214: Doesn't clone properly
Comment #23
chalee CreditAttribution: chalee commented@mrconnerton: Sure go ahead and create the patch, but wouldn't it be better to make the patch for Node clone module instead.
Comment #24
mrconnerton CreditAttribution: mrconnerton commented@chalee I have the code, just have to get the patch online.
I just see it from the perspective of:
I will try to get this patch up as soon as my schedule allows it.
Comment #25
chalee CreditAttribution: chalee commented@mrconnerton: It makes sense.
Comment #26
darin73 CreditAttribution: darin73 commentedI have the same problem (cloning) also with node revision. All the revisions use the same field-collection
Comment #27
mrconnerton CreditAttribution: mrconnerton commentedI have posted a patch for review here: http://drupal.org/node/1304214#comment-5556352
It's basically #20 but implemented in field_collection.module where I think this code belongs.
Comment #28
seaarg CreditAttribution: seaarg commentedSolution on #20 worked flawlessly for me, I have several "complex" field collections within a content type using media, date, etc. Thanks so much for this code!
Comment #29
lukusAny update on the patch? Could this be committed?
Comment #30
cjtriplett CreditAttribution: cjtriplett commentedYes it seems like this should be committed? Why wouldn't it be?
Comment #31
marcusx CreditAttribution: marcusx commentedChanging status. Or nobody will pay attention who can commit this.
Comment #32
bluetegu CreditAttribution: bluetegu commentedCheck http://drupal.org/node/1304214#comment-6339298 and the code in that thread.
Comment #33
dstorozhukMy variant of cloning function.
Examlpe of how to clone FC field from existing node to newely created node:
The main difference between this function and listed above - my function can clone FC to blank node object.
Comment #34
dstorozhukAlso who look for solution to clone field collection can check this module:
http://drupal.org/project/replicate_field_collection
Comment #35
gregory_kapustin CreditAttribution: gregory_kapustin commentedAfter using #33, which successfully cloned my collections fields on entities, I had a problem : entity form showed empty rows for each field collection item.
I bypassed it with the following patch.
Comment #36
pwolanin CreditAttribution: pwolanin commentedThere is no complete patch here.
In general I don't like adding custom support to clone for wacky non-core field modules so this has a high bar to meet.
Comment #37
psychobyte CreditAttribution: psychobyte commentedHi,
I'm affected by this issue is there an actual fix or would you suggest using this module https://drupal.org/project/field_collection_node_clone
Thanks.
Comment #38
Renee S CreditAttribution: Renee S commented@psychobyte, what is the difference between that module and "replicate field collection" module? The latter seems more powerful as it's entity-agnostic.
Comment #39
psychobyte CreditAttribution: psychobyte commented@Renee S
I believe that is the solution I'm looking for. Thx.
Comment #40
jmuzz CreditAttribution: jmuzz commentedCloning nodes with field collections is supported since the application of the patch in #1316162: Support content translation and host entity cloning. My understanding is this issue should be solved now, but please reopen with an explanation if it is not.
Comment #41
roynilanjan CreditAttribution: roynilanjan commentedSome work around as,
Now after this there is always a blank item added in the field collection(which is render from form API) & work around along with
*form_alter*
Comment #42
roynilanjan CreditAttribution: roynilanjan commentedComment #43
colanPlease read #40. The previous comment contains neither an explanation, nor code in patch format.
Comment #44
roynilanjan CreditAttribution: roynilanjan commentedAs far #40, it's being explained regrading the problem of *field_collection*, not related to *node clone*..
#41 tries to explain the probable solution(not a *patch*) using *node-clone* api and *form_alter*, as the way #3 use the *unset* it makes an improper behavior with context of node-clone, it's actually not cloning the field values rather it delete the existing field_collection values from the form during the clone.
Comment #45
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedI think this module solves the problem: https://www.drupal.org/project/field_collection_node_clone
Comment #47
pratip.ghosh CreditAttribution: pratip.ghosh commentedHi,
Is there a way to update the already cloned nodes whose field collection ID is now the same as the one from which it was cloned?