Problem/Motivation
drupal_array_nested_key_exists / drupal_array_get_nested_value is very costly and essentially always traverses the same path within either form_state['input'] / form_state['values'] .
field_x/und/0/_weight
etc.
The traversing itself can with 30 files go into direction of 300 - 500 ms alone already.
Proposed resolution
However form_builder() already traverses this path - unless someone overwrote it with arbitrary #parents - so in 90% of the cases, a reference could be put in $form_state or a new variable on where the form builder according to #tree and #parents should be right now in relation to the base of 'values' / 'input'.
e.g. pseudo code for values:
<?php
function form_builder() {
// check if set first obviously.
$current_values_element = &$form_state['form_builder_current']['values'];
foreach (element_children(...) as $key) {
// use $key only with #tree obviously.
if (!isset($element[$key]['#parents'])) {
if ($is_tree) {
$form_state['form_builder_current']['values'] = &$current_values_element[$key];
}
else {
$form_state['form_builder_current']['values'] = &$form_state['values'];
}
}
else {
$form_state['form_builder_current'] = array();
}
// ...
form_builder(..., $form_state);
}
}
?>
It is also possible to create short-cut cache paths based on the parents as string, but that is more effort than trailing along directly:
<?php
function &drupal_array_get_nested_value_cached(array &$array, array $parents, &$key_exists = NULL) {
$ref = &$array;
$i = 0;
$path = '';
$found = array();
$paths = array();
$skip = FALSE;
foreach ($parents as $index => $parent) {
$path .= '/' . $parent;
if (isset($array['#form_builder_cached_path'][$path])) {
$skip = $index;
$ref = &$array['#form_builder_cached_path'][$path];
}
}
$path = '';
foreach ($parents as $index => $parent) {
$path .= '/' . $parent;
if ($skip !== FALSE) {
if ($skip != $index) {
continue;
}
$skip = FALSE;
continue;
}
elseif (is_array($ref) && (isset($parent[$ref]) || array_key_exists($parent, $ref))) {
$array['#form_builder_cached_path'][$path] = &$ref[$parent];
$ref = &$ref[$parent];
}
else {
$key_exists = FALSE;
$null = NULL;
return $null;
}
}
$key_exists = TRUE;
return $ref;
}
function drupal_array_nested_key_exists_cached(array &$array, array $parents) {
// although this function is similar to php's array_key_exists(), its
// arguments should be consistent with drupal_array_get_nested_value().
$key_exists = null;
drupal_array_get_nested_value_cached($array, $parents, $key_exists);
return $key_exists;
}
?>
Remaining tasks
- See if one of the proposed approaches passes core tests.