From a91ebacb7214ca13e20decfc3b5028f644280db0 Mon Sep 17 00:00:00 2001 From: Franck Deroche Date: Mon, 30 Jan 2012 11:06:27 +0100 Subject: [PATCH] bug #1167004: Tweak content_get_nested_elements a lot - Change it to be non-recursive. - Make it accept an array of field names. - Use this in _content_field_invoke_default to prefetch the wrappers for all the fields in one pass. - Fix a bug in Content Multigroup that created a second entry in the form array for the group during the AHAH Add More processing. --- content.module | 74 ++++++++++++++++---- .../content_multigroup.node_form.inc | 2 +- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/content.module b/content.module index ea510c9..090c5f5 100644 --- a/content.module +++ b/content.module @@ -703,7 +703,7 @@ function content_associate_fields($module) { * ), * ); */ -function content_field($op, &$node, $field, &$items, $teaser, $page) { +function content_field($op, &$node, $field, &$items, $teaser, $page, $all_wrappers = NULL) { switch ($op) { case 'validate': // If the field is configured for multiple values and these are handled @@ -848,7 +848,12 @@ function content_field($op, &$node, $field, &$items, $teaser, $page) { // The location of the field's rendered output depends on whether the // field is in a fieldgroup or not. - $wrappers = content_get_nested_elements($node->content, $field['field_name']); + if (is_array($all_wrappers) && isset($all_wrappers[$field['field_name']])) { + $wrappers = $all_wrappers[$field['field_name']]; + } + else { + $wrappers = content_get_nested_elements($node->content, $field['field_name']); + } foreach ($wrappers as $wrapper) { $element = $wrapper['field']; // '#single' is not set if the field is hidden or inaccessible. @@ -878,7 +883,12 @@ function content_field($op, &$node, $field, &$items, $teaser, $page) { // The location of the field's rendered output depends on whether the // field is in a fieldgroup or not. - $wrappers = content_get_nested_elements($node->content, $field['field_name']); + if (is_array($all_wrappers) && isset($all_wrappers[$field['field_name']])) { + $wrappers = $all_wrappers[$field['field_name']]; + } + else { + $wrappers = content_get_nested_elements($node->content, $field['field_name']); + } foreach ($wrappers as $wrapper) { // '#children' is not set if the field is empty. $addition[$field['field_name'] .'_rendered'] .= isset($wrapper['#children']) ? $wrapper['#children'] : ''; @@ -1330,9 +1340,15 @@ function _content_field_invoke_default($op, &$node, $teaser = NULL, $page = NULL return content_storage($op, $node); } else { + if (in_array($op, array('alter', 'preprocess_node'))) { + $wrappers = content_get_nested_elements($node->content, array_keys($type['fields'])); + } + else { + $wrappers = NULL; + } foreach ($type['fields'] as $field) { $items = isset($node->$field['field_name']) ? $node->$field['field_name'] : array(); - $result = content_field($op, $node, $field, $items, $teaser, $page); + $result = content_field($op, $node, $field, $items, $teaser, $page, $wrappers); if (is_array($result)) { $return = array_merge($return, $result); } @@ -2800,19 +2816,49 @@ function content_inactive_instances($type_name = NULL) { * An array of all matching form elements, returned by reference. */ function &content_get_nested_elements(&$form, $field_name) { + if (!is_array($field_name)) { + $single = TRUE; + $names = array($field_name => $field_name); + } + else { + $single = FALSE; + $names = drupal_map_assoc($field_name); + } + $queue = array(&$form); $elements = array(); - foreach (element_children($form) as $key) { - if ($key === $field_name) { - $elements[] = &$form[$key]; - } - else if (is_array($form[$key])) { - $nested_form = &$form[$key]; - if ($sub_elements = &content_get_nested_elements($nested_form, $field_name)) { - $elements = array_merge($elements, $sub_elements); + foreach($names as $n) { + $elements[$n] = array(); + } + while ($current = &content_shift($queue)) { + foreach (element_children($current) as $key) { + if (isset($names[$key])) { + $elements[$key][] = &$current[$key]; + } + else if (is_array($current[$key])) { + $queue[] = &$current[$key]; } } } - return $elements; + return $single ? $elements[$field_name] : $elements; +} + +/** + * Returns the first element of an array by reference. + * + * This is conceptually equivalent to PHP built-in array_shift, but the + * element is returned by reference to allow the caller to modify it. + * + * @param $array + * The array whose first element's should be returned. + * @return mixed + * A reference to the variable that was the first array element. + */ +function &content_shift(&$array) { + reset($array); + $k = key($array); + $v = &$array[$k]; + unset($array[$k]); + return $v; } /** @@ -2838,4 +2884,4 @@ function content_set_nested_elements(&$form, $field_name, $value) { } } return $success; -} \ No newline at end of file +} diff --git a/modules/content_multigroup/content_multigroup.node_form.inc b/modules/content_multigroup/content_multigroup.node_form.inc index e9c48bf..4a32286 100644 --- a/modules/content_multigroup/content_multigroup.node_form.inc +++ b/modules/content_multigroup/content_multigroup.node_form.inc @@ -320,7 +320,7 @@ function _content_multigroup_node_form_after_build($form, &$form_state) { } - if ($form_state['submitted']) { + if ($form_state['submitted'] && !$form_state['multigroup_add_more']) { // Fix value positions in $form_state for the fields in multigroups. foreach (array_keys($form['#multigroups']) as $group_name) { content_multigroup_node_form_transpose_elements($form, $form_state, $form['#node']->type, $group_name); -- 1.7.8.4