summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-04-04 07:15:48 +0000
committerDries Buytaert <dries@buytaert.net>2010-04-04 07:15:48 +0000
commit1c4ff2fc67160f0f8dbcfcd40d88866411c47295 (patch)
tree51f600e1351de20844459f4113c624b13fb572ce
parent29a93b8c08b0f2d8fe772764119c95eef56aa972 (diff)
downloadbrdo-1c4ff2fc67160f0f8dbcfcd40d88866411c47295.tar.gz
brdo-1c4ff2fc67160f0f8dbcfcd40d88866411c47295.tar.bz2
- Patch #760238 by yched: optimize _field_invoke().
-rw-r--r--modules/field/field.attach.inc194
1 files changed, 109 insertions, 85 deletions
diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc
index 92847305f..2a5278e1f 100644
--- a/modules/field/field.attach.inc
+++ b/modules/field/field.attach.inc
@@ -181,58 +181,40 @@ function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $opti
);
$options += $default_options;
- // Iterate through the entity's field instances.
- $return = array();
+ // Determine the list of instances to iterate on.
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
+ $instances = _field_invoke_get_instances($entity_type, $bundle, $options);
- if ($options['deleted']) {
- $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle), array('include_deleted' => $options['deleted']));
- }
- else {
- $instances = field_info_instances($entity_type, $bundle);
- }
-
+ // Iterate through the instances and collect results.
+ $return = array();
foreach ($instances as $instance) {
$field_name = $instance['field_name'];
-
- // When in 'single field' mode, only act on the specified field.
- if ((!isset($options['field_id']) || $options['field_id'] == $instance['field_id']) && (!isset($options['field_name']) || $options['field_name'] == $field_name)) {
- $field = field_info_field($field_name);
- $field_translations = array();
-
- // Unless a language suggestion is provided we iterate on all the
- // available languages.
+ $field = field_info_field($field_name);
+ $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
+ if (function_exists($function)) {
+ // Determine the list of languages to iterate on.
$available_languages = field_available_languages($entity_type, $field);
$languages = _field_language_suggestion($available_languages, $options['language'], $field_name);
- // Initialize field translations according to the available languages.
foreach ($languages as $langcode) {
- $field_translations[$langcode] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
- }
-
- // Invoke the field hook and collect results.
- $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
- if (function_exists($function)) {
- // Iterate over all the field translations.
- foreach ($field_translations as $langcode => $items) {
- $result = $function($entity_type, $entity, $field, $instance, $langcode, $items, $a, $b);
- if (isset($result)) {
- // For hooks with array results, we merge results together.
- // For hooks with scalar results, we collect results in an array.
- if (is_array($result)) {
- $return = array_merge($return, $result);
- }
- else {
- $return[] = $result;
- }
+ $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
+ $result = $function($entity_type, $entity, $field, $instance, $langcode, $items, $a, $b);
+ if (isset($result)) {
+ // For hooks with array results, we merge results together.
+ // For hooks with scalar results, we collect results in an array.
+ if (is_array($result)) {
+ $return = array_merge($return, $result);
}
-
- // Populate $items back in the field values, but avoid replacing missing
- // fields with an empty array (those are not equivalent on update).
- if ($items !== array() || isset($entity->{$field_name}[$langcode])) {
- $entity->{$field_name}[$langcode] = $items;
+ else {
+ $return[] = $result;
}
}
+
+ // Populate $items back in the field values, but avoid replacing missing
+ // fields with an empty array (those are not equivalent on update).
+ if ($items !== array() || isset($entity->{$field_name}[$langcode])) {
+ $entity->{$field_name}[$langcode] = $items;
+ }
}
}
}
@@ -309,23 +291,19 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
// is deleted, so we reference field data via the
// $entity->$field_name property.
foreach ($entities as $entity) {
+ // Determine the list of instances to iterate on.
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
-
- if ($options['deleted']) {
- $instances = field_read_field(array('bundle' => $bundle, array('include_deleted' => $options['deleted'])));
- }
- else {
- $instances = field_info_instances($entity_type, $bundle);
- }
+ $instances = _field_invoke_get_instances($entity_type, $bundle, $options);
foreach ($instances as $instance) {
$field_id = $instance['field_id'];
$field_name = $instance['field_name'];
- // When in 'single field' mode, only act on the specified field.
- if ((empty($options['field_id']) || $options['field_id'] == $field_id) && (empty($options['field_name']) || $options['field_name'] == $field_name)) {
+ $field = field_info_field_by_id($field_id);
+ $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
+ if (function_exists($function)) {
// Add the field to the list of fields to invoke the hook on.
if (!isset($fields[$field_id])) {
- $fields[$field_id] = field_info_field_by_id($field_id);
+ $fields[$field_id] = $field;
}
// Group the corresponding instances and entities.
$grouped_instances[$field_id][$id] = $instance;
@@ -334,7 +312,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
// by hook implementations.
// Unless a language suggestion is provided we iterate on all the
// available languages.
- $available_languages = field_available_languages($entity_type, $fields[$field_id]);
+ $available_languages = field_available_languages($entity_type, $field);
$languages = _field_language_suggestion($available_languages, $options['language'], $field_name);
foreach ($languages as $langcode) {
$grouped_items[$field_id][$langcode][$id] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
@@ -349,21 +327,19 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
foreach ($fields as $field_id => $field) {
$field_name = $field['field_name'];
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
- if (function_exists($function)) {
- // Iterate over all the field translations.
- foreach ($grouped_items[$field_id] as $langcode => $items) {
- $results = $function($entity_type, $grouped_entities[$field_id], $field, $grouped_instances[$field_id], $langcode, $grouped_items[$field_id][$langcode], $a, $b);
- if (isset($results)) {
- // Collect results by entity.
- // For hooks with array results, we merge results together.
- // For hooks with scalar results, we collect results in an array.
- foreach ($results as $id => $result) {
- if (is_array($result)) {
- $return[$id] = array_merge($return[$id], $result);
- }
- else {
- $return[$id][] = $result;
- }
+ // Iterate over all the field translations.
+ foreach ($grouped_items[$field_id] as $langcode => $items) {
+ $results = $function($entity_type, $grouped_entities[$field_id], $field, $grouped_instances[$field_id], $langcode, $grouped_items[$field_id][$langcode], $a, $b);
+ if (isset($results)) {
+ // Collect results by entity.
+ // For hooks with array results, we merge results together.
+ // For hooks with scalar results, we collect results in an array.
+ foreach ($results as $id => $result) {
+ if (is_array($result)) {
+ $return[$id] = array_merge($return[$id], $result);
+ }
+ else {
+ $return[$id][] = $result;
}
}
}
@@ -412,6 +388,59 @@ function _field_invoke_multiple_default($op, $entity_type, $entities, &$a = NULL
}
/**
+ * Helper for _field_invoke(): retrieves a list of instances to operate on.
+ *
+ * @param $entity_type
+ * The entity type.
+ * @param $bundle
+ * The bundle name.
+ * @param $options
+ * An associative array of options, as provided to _field_invoke(). Only the
+ * following keys are considered :
+ * - deleted
+ * - field_name
+ * - field_id
+ * See _field_invoke() for details.
+ *
+ * @return
+ * The array of selected instance definitions.
+ */
+function _field_invoke_get_instances($entity_type, $bundle, $options) {
+ if ($options['deleted']) {
+ // Deleted fields are not included in field_info_instances(), and need to
+ // be fetched from the database with field_read_instances().
+ $params = array('entity_type' => $entity_type, 'bundle' => $bundle);
+ if (isset($options['field_id'])) {
+ // Single-field mode by field id: field_read_instances() does the filtering.
+ // Single-field mode by field name is not compatible with the 'deleted'
+ // option.
+ $params['field_id'] = $options['field_id'];
+ }
+ $instances = field_read_instances($params, array('include_deleted' => TRUE));
+ }
+ elseif (isset($options['field_name'])) {
+ // Single-field mode by field name: field_info_instance() does the
+ // filtering.
+ $instances = array(field_info_instance($entity_type, $options['field_name'], $bundle));
+ }
+ else {
+ $instances = field_info_instances($entity_type, $bundle);
+ if (isset($options['field_id'])) {
+ // Single-field mode by field id: we need to loop on each instance to
+ // find the right one.
+ foreach ($instances as $instance) {
+ if ($instance['field_id'] == $options['field_id']) {
+ $instances = array($instance);
+ break;
+ }
+ }
+ }
+ }
+
+ return $instances;
+}
+
+/**
* Add form elements for all fields for an entity to a form structure.
*
* Sample structure for $form:
@@ -611,30 +640,25 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
$function($entity_type, $queried_entities, $age, $skip_fields, $options);
}
+ $instances = array();
+
// Collect the storage backends used by the remaining fields in the entities.
$storages = array();
foreach ($queried_entities as $entity) {
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
- if ($options['deleted']) {
- $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle), array('include_deleted' => $options['deleted']));
- }
- else {
- $instances = field_info_instances($entity_type, $bundle);
- }
+ $instances = _field_invoke_get_instances($entity_type, $bundle, $options);
foreach ($instances as $instance) {
- if (!isset($options['field_id']) || $options['field_id'] == $instance['field_id']) {
- $field_name = $instance['field_name'];
- $field_id = $instance['field_id'];
- // Make sure all fields are present at least as empty arrays.
- if (!isset($queried_entities[$id]->{$field_name})) {
- $queried_entities[$id]->{$field_name} = array();
- }
- // Collect the storage backend if the field has not been loaded yet.
- if (!isset($skip_fields[$field_id])) {
- $field = field_info_field_by_id($field_id);
- $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
- }
+ $field_name = $instance['field_name'];
+ $field_id = $instance['field_id'];
+ // Make sure all fields are present at least as empty arrays.
+ if (!isset($queried_entities[$id]->{$field_name})) {
+ $queried_entities[$id]->{$field_name} = array();
+ }
+ // Collect the storage backend if the field has not been loaded yet.
+ if (!isset($skip_fields[$field_id])) {
+ $field = field_info_field_by_id($field_id);
+ $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
}
}
}