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) {
}
// Allow modules to react prior to the enabling of a module.
entity_info_cache_clear();
module_invoke_all('modules_preenable', array($module));
// Enable the module.
......
......@@ -1576,6 +1576,11 @@ function hook_field_storage_details_alter(&$details, $field) {
* 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.
*
* 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
* The type of entity, such as 'node' or 'user'.
* @param $entities
......@@ -1593,11 +1598,10 @@ function hook_field_storage_details_alter(&$details, $field) {
* fields. If unset or FALSE, only non-deleted fields should be loaded.
*/
function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) {
$field_info = field_info_field_by_ids();
$load_current = $age == FIELD_LOAD_CURRENT;
foreach ($fields as $field_id => $ids) {
$field = $field_info[$field_id];
$field = field_info_field_by_id($field_id);
$field_name = $field['field_name'];
$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 =
'langcode' => NULL,
);
$options += $default_options;
$field_info = field_info_field_by_ids();
$fields = array();
$grouped_instances = array();
......@@ -373,7 +372,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
foreach ($instances as $instance) {
$field_id = $instance['field_id'];
$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;
if (function_exists($function)) {
// 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
* operated on.
*/
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;
// Merge default options.
......@@ -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.
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;
}
}
......
......@@ -322,7 +322,11 @@ function field_read_field($field_name, $include_additional = array()) {
* Reads in fields that match an array of conditions.
*
* @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
* The default behavior of this function is to not return fields that are
* inactive or have been deleted. Setting
......@@ -340,8 +344,18 @@ function field_read_fields($params = array(), $include_additional = array()) {
// Turn the conditions into a query.
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);
}
if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
$query
->condition('fc.active', 1)
......
This diff is collapsed.
......@@ -1001,7 +1001,8 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
if ($field = field_info_field($field_name)) {
if (is_array($display)) {
// 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
......
This diff is collapsed.
......@@ -63,7 +63,7 @@ function testFieldInfo() {
// Verify that no unexpected instances exist.
$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) . '.');
$instances = field_info_instances('test_entity', 'test_bundle');
$this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'test_bundle') returns an empty array.");
......@@ -120,7 +120,7 @@ function testFieldInfo() {
// Test with an entity type that has no bundles.
$instances = field_info_instances('user');
$expected = array('user' => array());
$expected = array();
$this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.');
$instances = field_info_instances('user', 'user');
$this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array.");
......@@ -234,6 +234,81 @@ function testInstanceDisabledEntityType() {
$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.
*/
......
......@@ -335,11 +335,10 @@ function field_sql_storage_field_storage_delete_field($field) {
* Implements hook_field_storage_load().
*/
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;
foreach ($fields as $field_id => $ids) {
$field = $field_info[$field_id];
$field = field_info_field_by_id($field_id);
$field_name = $field['field_name'];
$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) {
* Identifies inactive fields within a bundle.
*/
function field_ui_inactive_instances($entity_type, $bundle_name = NULL) {
if (!empty($bundle_name)) {
$inactive = array($bundle_name => array());
$params = array('bundle' => $bundle_name);
$params = array('entity_type' => $entity_type);
if (empty($bundle_name)) {
$active = field_info_instances($entity_type);
$inactive = array();
}
else {
$inactive = array();
$params = array();
// Restrict to the specified bundle. For consistency with the case where
// $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));
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;
}
}
if (!empty($bundle_name)) {
return $inactive[$bundle_name];
}
......
......@@ -172,7 +172,7 @@ function addExistingField() {
*/
function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
// Reset the fields info.
_field_info_collate_fields_reset();
field_info_cache_clear();
// Assert field settings.
$field = field_info_field($field_name);
$this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
......@@ -262,7 +262,7 @@ function testDeleteField() {
$this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type);
// Reset the fields info.
_field_info_collate_fields_reset();
field_info_cache_clear();
// Check that the 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
......@@ -272,7 +272,7 @@ function testDeleteField() {
$this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2);
// Reset the fields info.
_field_info_collate_fields_reset();
field_info_cache_clear();
// Check that the 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.
......
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