Skip to content

Instantly share code, notes, and snippets.

@wizonesolutions
Last active December 20, 2015 06:48
Show Gist options
  • Save wizonesolutions/6087966 to your computer and use it in GitHub Desktop.
Save wizonesolutions/6087966 to your computer and use it in GitHub Desktop.
See README.md.

This function is intended to be used within THEMENAME_preprocess_node() (or, well, any template_preprocess_node() implementation). It parses the field collection render array and gives you direct access to the render arrays of the individual deltas. They are normally buried in a few layers of arrays and normally require you to look up the field collection item ID/revision yourself first. Often, you simply want to iterate over them and don't care about their IDs. This helper function helps solve that problem.

You pass it the $variables array and the field names of the Field Collection fields that are attached to the node and that you want to massage. It adds variables to the $variables array, named after the field + _indexed.

So if you call THEMENAME_massage_field_collections($variables, array('field_my_field_collection');, $variables['field_my_field_collection'] will exist after it's done.

It also adds a #value and #revision_id property to the variable it creates, just in case you need to know those in your template for some reason.

<?php
/**
* Adds (field name)_indexed items to the $variables array containing just
* the field collection deltas. This saves having to correlate the IDs to the
* actual render arrays just to iterate over them.
*
* @param $variables The $variables array. See notes on $source.
* @param $field_names An array of field collection field names that you want
* processed. The value of this is ignored if $source === 'field', so you can
* pass array() or NULL or whatever you want in that case.
* @param string $source Tell the function what behavior you expect, since
* you might call it from a node or field preprocess hook. Possible values:
* - 'node': $variables is from a node preprocess function, and $field_names
* is an array of field collection field names.
* - 'field': $variables is from a field preprocess function, and
* $field_names doesn't matter (we overwrite it).
* - 'field_children' (not yet implemented): $variables is from a field
* preprocess function, and $field_names is an array of field collection
* field names attached to the field collection itself (not a node). This
* mode of operation massages the underlying fields instead of the field
* itself. Similar in concept to 'node'.
*/
function THEMENAME_massage_field_collections(&$variables, $field_names, $source = 'node') {
// We need to know what to expect $variables to contain.
// The logic is mostly the same, so we just hook up $content and $field_names
// appropriately for each case.
switch ($source) {
// Called from the field itself, and should massage its own deltas.
case 'field':
$element = $variables['element'];
// So we can avoid doing a bajillion isset() checks.
if (THEMENAME_element_is_field_collection($element)) {
// We fake the content array so that when the code below checks for
// $content[$field_name], it finds the contents of $element.
$content = array(
$element['#field_name'] => $element,
);
$field_names = array($element['#field_name']);
}
break;
// Called from the field, but we want to massage attached field collections.
// $field_names must contain their names.
case 'field_children':
// TODO: Write this when it's needed.
break;
// Called from a node preprocess function.
case 'node':
$content = $variables['content'];
break;
}
foreach ($field_names as $field_name) {
$field_name_indexed = $field_name . "_indexed";
$field_is_set = FALSE;
switch ($source) {
case 'field';
// If we have element, we have the field for our purposes here.
$field_is_set = isset($content[$field_name]);
break;
case 'field_children':
case 'node':
// In this case it's actually in the variables array. We don't use it,
// but we just check that it actually has any values like this.
$field_is_set = isset($variables[$field_name]);
break;
}
if ($field_is_set) {
// Get the actual deltas from #items, since they might not start at 0
$deltas = element_children($content[$field_name]['#items']);
foreach ($deltas as $record) {
$value = $content[$field_name]['#items'][$record]['value'];
$revision_id = $content[$field_name]['#items'][$record]['revision_id'];
$variables[$field_name_indexed][$record] = $content[$field_name][$record]['entity']['field_collection_item'][$value];
$variables[$field_name_indexed][$record]['#value'] = $value;
$variables[$field_name_indexed][$record]['#revision_id'] = $revision_id;
}
}
}
}
/**
* Is this a field_collection-type field?
* NOTE: We aren't checking if it's a field_collection_item entity. We are
* checking for an element structure matching a field collection field, the
* thing that gets attached to a node.
*/
function THEMENAME_element_is_field_collection($element) {
if (isset($element) && isset($element['#bundle']) && isset($element['#field_name']) && isset($element['#field_type']) && $element['#field_type'] === 'field_collection') {
return TRUE;
}
return FALSE;
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment