Commit 43942f8a authored by catch's avatar catch

Issue #1040790 by yched, swentel, geerlingguy, beejeebus, Berdir: Fixed...

Issue #1040790 by yched, swentel, geerlingguy, beejeebus, Berdir: Fixed _field_info_collate_fields() memory usage.
parent 3319def6
...@@ -498,6 +498,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) { ...@@ -498,6 +498,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
} }
// Allow modules to react prior to the enabling of a module. // Allow modules to react prior to the enabling of a module.
entity_info_cache_clear();
module_invoke_all('modules_preenable', array($module)); module_invoke_all('modules_preenable', array($module));
// Enable the module. // Enable the module.
......
...@@ -1576,6 +1576,11 @@ function hook_field_storage_details_alter(&$details, $field) { ...@@ -1576,6 +1576,11 @@ function hook_field_storage_details_alter(&$details, $field) {
* Modules implementing this hook should load field values and add them to * Modules implementing this hook should load field values and add them to
* objects in $entities. Fields with no values should be added as empty arrays. * objects in $entities. Fields with no values should be added as empty arrays.
* *
* By the time this hook runs, the relevant field definitions have been
* populated and cached in FieldInfo, so calling field_info_field_by_id() on
* each field individually is more efficient than loading all fields in memory
* upfront with field_info_field_by_ids() (which is uncached).
*
* @param $entity_type * @param $entity_type
* The type of entity, such as 'node' or 'user'. * The type of entity, such as 'node' or 'user'.
* @param $entities * @param $entities
...@@ -1593,11 +1598,10 @@ function hook_field_storage_details_alter(&$details, $field) { ...@@ -1593,11 +1598,10 @@ function hook_field_storage_details_alter(&$details, $field) {
* fields. If unset or FALSE, only non-deleted fields should be loaded. * fields. If unset or FALSE, only non-deleted fields should be loaded.
*/ */
function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) { function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) {
$field_info = field_info_field_by_ids();
$load_current = $age == FIELD_LOAD_CURRENT; $load_current = $age == FIELD_LOAD_CURRENT;
foreach ($fields as $field_id => $ids) { foreach ($fields as $field_id => $ids) {
$field = $field_info[$field_id]; $field = field_info_field_by_id($field_id);
$field_name = $field['field_name']; $field_name = $field['field_name'];
$table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field); $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
......
...@@ -349,7 +349,6 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b = ...@@ -349,7 +349,6 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
'langcode' => NULL, 'langcode' => NULL,
); );
$options += $default_options; $options += $default_options;
$field_info = field_info_field_by_ids();
$fields = array(); $fields = array();
$grouped_instances = array(); $grouped_instances = array();
...@@ -373,7 +372,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b = ...@@ -373,7 +372,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
foreach ($instances as $instance) { foreach ($instances as $instance) {
$field_id = $instance['field_id']; $field_id = $instance['field_id'];
$field_name = $instance['field_name']; $field_name = $instance['field_name'];
$field = $field_info[$field_id]; $field = field_info_field_by_id($field_id);
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
if (function_exists($function)) { if (function_exists($function)) {
// Add the field to the list of fields to invoke the hook on. // Add the field to the list of fields to invoke the hook on.
...@@ -736,7 +735,6 @@ function field_attach_form($entity_type, EntityInterface $entity, &$form, &$form ...@@ -736,7 +735,6 @@ function field_attach_form($entity_type, EntityInterface $entity, &$form, &$form
* operated on. * operated on.
*/ */
function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $options = array()) { function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $options = array()) {
$field_info = field_info_field_by_ids();
$load_current = $age == FIELD_LOAD_CURRENT; $load_current = $age == FIELD_LOAD_CURRENT;
// Merge default options. // Merge default options.
...@@ -814,7 +812,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $ ...@@ -814,7 +812,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
} }
// Collect the storage backend if the field has not been loaded yet. // Collect the storage backend if the field has not been loaded yet.
if (!isset($skip_fields[$field_id])) { if (!isset($skip_fields[$field_id])) {
$field = $field_info[$field_id]; $field = field_info_field_by_id($field_id);
$storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid; $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
} }
} }
......
...@@ -322,7 +322,11 @@ function field_read_field($field_name, $include_additional = array()) { ...@@ -322,7 +322,11 @@ function field_read_field($field_name, $include_additional = array()) {
* Reads in fields that match an array of conditions. * Reads in fields that match an array of conditions.
* *
* @param array $params * @param array $params
* An array of conditions to match against. * An array of conditions to match against. Keys are columns from the
* 'field_config' table, values are conditions to match. Additionally,
* conditions on the 'entity_type' and 'bundle' columns from the
* 'field_config_instance' table are supported (select fields having an
* instance on a given bundle).
* @param array $include_additional * @param array $include_additional
* The default behavior of this function is to not return fields that are * The default behavior of this function is to not return fields that are
* inactive or have been deleted. Setting * inactive or have been deleted. Setting
...@@ -340,8 +344,18 @@ function field_read_fields($params = array(), $include_additional = array()) { ...@@ -340,8 +344,18 @@ function field_read_fields($params = array(), $include_additional = array()) {
// Turn the conditions into a query. // Turn the conditions into a query.
foreach ($params as $key => $value) { foreach ($params as $key => $value) {
// Allow filtering on the 'entity_type' and 'bundle' columns of the
// field_config_instance table.
if ($key == 'entity_type' || $key == 'bundle') {
if (empty($fci_join)) {
$fci_join = $query->join('field_config_instance', 'fci', 'fc.id = fci.field_id');
}
$key = 'fci.' . $key;
}
$query->condition($key, $value); $query->condition($key, $value);
} }
if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) { if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
$query $query
->condition('fc.active', 1) ->condition('fc.active', 1)
......
This diff is collapsed.
...@@ -1001,7 +1001,8 @@ function field_view_field($entity_type, $entity, $field_name, $display = array() ...@@ -1001,7 +1001,8 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
if ($field = field_info_field($field_name)) { if ($field = field_info_field($field_name)) {
if (is_array($display)) { if (is_array($display)) {
// When using custom display settings, fill in default values. // When using custom display settings, fill in default values.
$display = _field_info_prepare_instance_display($field, $display); $cache = _field_info_field_cache();
$display = $cache->prepareInstanceDisplay($display, $field["type"]);
} }
// Hook invocations are done through the _field_invoke() functions in // Hook invocations are done through the _field_invoke() functions in
......
This diff is collapsed.
...@@ -63,7 +63,7 @@ function testFieldInfo() { ...@@ -63,7 +63,7 @@ function testFieldInfo() {
// Verify that no unexpected instances exist. // Verify that no unexpected instances exist.
$instances = field_info_instances('test_entity'); $instances = field_info_instances('test_entity');
$expected = array('test_bundle' => array()); $expected = array();
$this->assertIdentical($instances, $expected, "field_info_instances('test_entity') returns " . var_export($expected, TRUE) . '.'); $this->assertIdentical($instances, $expected, "field_info_instances('test_entity') returns " . var_export($expected, TRUE) . '.');
$instances = field_info_instances('test_entity', 'test_bundle'); $instances = field_info_instances('test_entity', 'test_bundle');
$this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'test_bundle') returns an empty array."); $this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'test_bundle') returns an empty array.");
...@@ -120,7 +120,7 @@ function testFieldInfo() { ...@@ -120,7 +120,7 @@ function testFieldInfo() {
// Test with an entity type that has no bundles. // Test with an entity type that has no bundles.
$instances = field_info_instances('user'); $instances = field_info_instances('user');
$expected = array('user' => array()); $expected = array();
$this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.'); $this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.');
$instances = field_info_instances('user', 'user'); $instances = field_info_instances('user', 'user');
$this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array."); $this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array.");
...@@ -234,6 +234,81 @@ function testInstanceDisabledEntityType() { ...@@ -234,6 +234,81 @@ function testInstanceDisabledEntityType() {
$this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), 'No instances are returned on disabled entity types.'); $this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), 'No instances are returned on disabled entity types.');
} }
/**
* Test field_info_field_map().
*/
function testFieldMap() {
// We will overlook fields created by the 'standard' install profile.
$exclude = field_info_field_map();
// Create a new bundle for 'test_entity' entity type.
field_test_create_bundle('test_bundle_2');
// Create a couple fields.
$fields = array(
array(
'field_name' => 'field_1',
'type' => 'test_field',
),
array(
'field_name' => 'field_2',
'type' => 'hidden_test_field',
),
);
foreach ($fields as $field) {
field_create_field($field);
}
// Create a couple instances.
$instances = array(
array(
'field_name' => 'field_1',
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
),
array(
'field_name' => 'field_1',
'entity_type' => 'test_entity',
'bundle' => 'test_bundle_2',
),
array(
'field_name' => 'field_2',
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
),
array(
'field_name' => 'field_2',
'entity_type' => 'test_cacheable_entity',
'bundle' => 'test_bundle',
),
);
foreach ($instances as $instance) {
field_create_instance($instance);
}
$expected = array(
'field_1' => array(
'type' => 'test_field',
'bundles' => array(
'test_entity' => array('test_bundle', 'test_bundle_2'),
),
),
'field_2' => array(
'type' => 'hidden_test_field',
'bundles' => array(
'test_entity' => array('test_bundle'),
'test_cacheable_entity' => array('test_bundle'),
),
),
);
// Check that the field map is correct.
$map = field_info_field_map();
$map = array_diff_key($map, $exclude);
$this->assertEqual($map, $expected);
}
/** /**
* Test that the field_info settings convenience functions work. * Test that the field_info settings convenience functions work.
*/ */
......
...@@ -335,11 +335,10 @@ function field_sql_storage_field_storage_delete_field($field) { ...@@ -335,11 +335,10 @@ function field_sql_storage_field_storage_delete_field($field) {
* Implements hook_field_storage_load(). * Implements hook_field_storage_load().
*/ */
function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) { function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
$field_info = field_info_field_by_ids();
$load_current = $age == FIELD_LOAD_CURRENT; $load_current = $age == FIELD_LOAD_CURRENT;
foreach ($fields as $field_id => $ids) { foreach ($fields as $field_id => $ids) {
$field = $field_info[$field_id]; $field = field_info_field_by_id($field_id);
$field_name = $field['field_name']; $field_name = $field['field_name'];
$table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field); $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
......
...@@ -327,23 +327,30 @@ function _field_ui_bundle_admin_path($entity_type, $bundle_name) { ...@@ -327,23 +327,30 @@ function _field_ui_bundle_admin_path($entity_type, $bundle_name) {
* Identifies inactive fields within a bundle. * Identifies inactive fields within a bundle.
*/ */
function field_ui_inactive_instances($entity_type, $bundle_name = NULL) { function field_ui_inactive_instances($entity_type, $bundle_name = NULL) {
if (!empty($bundle_name)) { $params = array('entity_type' => $entity_type);
$inactive = array($bundle_name => array());
$params = array('bundle' => $bundle_name); if (empty($bundle_name)) {
$active = field_info_instances($entity_type);
$inactive = array();
} }
else { else {
$inactive = array(); // Restrict to the specified bundle. For consistency with the case where
$params = array(); // $bundle_name is NULL, the $active and $inactive arrays are keyed by
// bundle name first.
$params['bundle'] = $bundle_name;
$active = array($bundle_name => field_info_instances($entity_type, $bundle_name));
$inactive = array($bundle_name => array());
} }
$params['entity_type'] = $entity_type;
$active_instances = field_info_instances($entity_type); // Iterate on existing definitions, and spot those that do not appear in the
// $active list collected earlier.
$all_instances = field_read_instances($params, array('include_inactive' => TRUE)); $all_instances = field_read_instances($params, array('include_inactive' => TRUE));
foreach ($all_instances as $instance) { foreach ($all_instances as $instance) {
if (!isset($active_instances[$instance['bundle']][$instance['field_name']])) { if (!isset($active[$instance['bundle']][$instance['field_name']])) {
$inactive[$instance['bundle']][$instance['field_name']] = $instance; $inactive[$instance['bundle']][$instance['field_name']] = $instance;
} }
} }
if (!empty($bundle_name)) { if (!empty($bundle_name)) {
return $inactive[$bundle_name]; return $inactive[$bundle_name];
} }
......
...@@ -172,7 +172,7 @@ function addExistingField() { ...@@ -172,7 +172,7 @@ function addExistingField() {
*/ */
function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') { function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
// Reset the fields info. // Reset the fields info.
_field_info_collate_fields_reset(); field_info_cache_clear();
// Assert field settings. // Assert field settings.
$field = field_info_field($field_name); $field = field_info_field($field_name);
$this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.'); $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
...@@ -262,7 +262,7 @@ function testDeleteField() { ...@@ -262,7 +262,7 @@ function testDeleteField() {
$this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type); $this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type);
// Reset the fields info. // Reset the fields info.
_field_info_collate_fields_reset(); field_info_cache_clear();
// Check that the field instance was deleted. // Check that the field instance was deleted.
$this->assertNull(field_info_instance('node', $this->field_name, $this->type), 'Field instance was deleted.'); $this->assertNull(field_info_instance('node', $this->field_name, $this->type), 'Field instance was deleted.');
// Check that the field was not deleted // Check that the field was not deleted
...@@ -272,7 +272,7 @@ function testDeleteField() { ...@@ -272,7 +272,7 @@ function testDeleteField() {
$this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2); $this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2);
// Reset the fields info. // Reset the fields info.
_field_info_collate_fields_reset(); field_info_cache_clear();
// Check that the field instance was deleted. // Check that the field instance was deleted.
$this->assertNull(field_info_instance('node', $this->field_name, $type_name2), 'Field instance was deleted.'); $this->assertNull(field_info_instance('node', $this->field_name, $type_name2), 'Field instance was deleted.');
// Check that the field was deleted too. // Check that the field was deleted too.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment