Hi,

I have to implement nested field collection up to 4 loops.
Fieldcollection1
--Fieldcollection 2
--Fieldcollection 3
--Fieldcollection 4

However, it supports up to 3 recursions only. I have attached a screenshot showing the problem as well as code snippet giving the problem (located in line number:978 in file:field_collection.module ). I just need to making it 4 or more.
The error message is:
"The field collection item form has not been embedded to avoid recursive loops"

I changed it to 4 and the module is perfectly working. So can you please highlight, why it has been limited to 3?

I am also uploading the modules in Drupal and the patch thing does not seem a good practice.

Can you please provide me a way to configure it through the setting page, since I am giving a patch to my client too. I would really appreciate your help.

Thanks!

CommentFileSizeAuthor
code_snippet.jpg61.91 KBsbasyal
field_collection_problem.jpg53.38 KBsbasyal
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jmuzz’s picture

Category: Bug report » Task
Priority: Major » Normal
Issue summary: View changes

The reason there is a limit is to prevent infinite recursion. It is simple to add a field collection as an existing field to itself for example. It could also happen with a loop involving several field collection types and this is the easiest way to implement a safeguard.

I agree that 3 is a potentially restricting number to use. I don't see why it can't be changed to something much larger like 10.

Can anybody provide some insight about why 3 was chosen or a reason it shouldn't be increased?

sigkg’s picture

Is there somewhere where this is discussed. Having only 3 is restricting.

Paulmicha’s picture

Ok, maybe my findings will interest some of you, if you stumbled upon this issue looking for ways to make "nested" 'field_collection_item's (or "recursive" Field Collection ~ "inception").

In field_collection version = "7.x-1.0-beta7", inside function field_collection_field_widget_form() - at line 1361 there's this condition preventing infinite recursion :
if ($recursion++ > 3)

I simply replaced it with :


      $depth = 0;
      if (count($element['#field_parents']) > 0) {
        $depth = count($element['#field_parents']) / 3;
      }
      if ($depth > 2)

Note : 2 is hardcoded here, by you might use a variable_get() or something more dynamic, e.g. based on field name.

Explanation :
Debugging quickly using $element['#suffix'] = "Test ". $_GET['q']; $element['#suffix'] .= kdevel_print_object($element['#field_parents']); shows an array with 3 entries per "nesting level", e.g. [field_foobar, und, 0] for level 1, or [field_foobar, und, 0, field_foobar, und, 0] for level 2, and so on...
That's why the depth can be deduced using the division by 3 above.

jmuzz’s picture

Testing nesting level doesn't seem like the best way to begin with. There can only be an infinite recursion if a field collection item is a descendant of itself right? So test the path of parent elements to the root when it is added to the form and only fail if it is already there.

Paulmicha’s picture

There can only be an infinite recursion if a field collection item is a descendant of itself

Indeed, I hadn't thought about the possibility of having different nested FC items.

In that case, what if several field collections depending on each other are nested as well ?
fc_item_a > fc_item_b > fc_item_a > ...

Maybe +1 to max depth when parent FC item is different ?
So that even when max depth is reached, any child FC item different than its "host" still gets rendered.
I might test this later on.
Note : max depth refers to the hardcoded number 2 in the suggestion above : if ($depth > 2)

Also, I didn't mention it in the first place, but the reason I needed something else than the existing $recursion variable was that the ajax widget "add more" (infinite number of items) stopped working after a while - looked like an off-by-one error somewhere, but I lost track of the increments/decrements somewhere (hence the $_GET['q'] printed in debug above).
I should have made a gif or something to better explain, sorry.

jmuzz’s picture

Several field collections depending on each other sounds like an infinite loop to me. Even if you just have the 3 levels you described, how would even the initial embedded form look?

There would be a blank fc_item_a
it would have a blank fc_item_b
that would have a blank fc_item_a
which would have a blank fc_item_b
etc.

Such a structure could work using the hidden widget for both fields and editing them through links on their view pages exclusively, but we are trying to solve the recursion problem in the embedded widget.

My idea here is that you can test to see if the bundle is already in the path to the root of the form and fail if it is... Then you won't need a max_depth as it will catch recursions that way no matter how deep they are.

Paulmicha’s picture

I thought we were talking about supporting (a finite number of) recursion - that's what I gathered on this issue at least, so I think "failing" (or displaying an error message) is not an option. In other words, I understood we wanted this potentially infinite recursion : only with a way of setting an adjustable depth limit.

For my use case, I also removed the error message to simply have the widget display something like "maximum depth reached" when the desired depth limit is reached (that use case was to use this recursion to render custom/unique layouts by combining any number of containers / subdivisions).

Hope that clears things up a bit, even though I'm not sure that this is a very common "need".

jmuzz’s picture

Yeah that does make sense. The depth limit seems like the best option afterall as it's partly implemented and prevents infinite recursion while allowing a loop if desired. Might be nice to have a patch that makes it work without the error message and makes the depth limit configurable.

vhakulinen’s picture

So there are no plans to make unlimited recursive field collections? Its not that trivial to detect circular references after all.