diff options
Diffstat (limited to 'modules/field')
-rw-r--r-- | modules/field/field.crud.inc | 13 | ||||
-rw-r--r-- | modules/field/field.default.inc | 10 | ||||
-rw-r--r-- | modules/field/field.info.inc | 116 | ||||
-rw-r--r-- | modules/field/field.module | 18 | ||||
-rw-r--r-- | modules/field/field.test | 130 |
5 files changed, 188 insertions, 99 deletions
diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc index 91fb159ed..ca19d5ebb 100644 --- a/modules/field/field.crud.inc +++ b/modules/field/field.crud.inc @@ -339,10 +339,6 @@ function field_read_fields($params = array(), $include_additional = array()) { unset($field['data']); $field += $data; - // Make sure all settings expected in the current execution context are - // present. - $field['settings'] += field_info_field_settings($field['type']); - module_invoke_all('field_read_field', $field); // Populate storage information. @@ -624,7 +620,6 @@ function field_read_instances($params = array(), $include_additional = array()) $query = db_select('field_config_instance', 'fci', array('fetch' => PDO::FETCH_ASSOC)); $query->join('field_config', 'fc', 'fc.id = fci.field_id'); $query->fields('fci'); - $query->fields('fc', array('type')); // Turn the conditions into a query. foreach ($params as $key => $value) { @@ -654,14 +649,6 @@ function field_read_instances($params = array(), $include_additional = array()) $instance['widget']['module'] = $record['widget_module']; $instance['widget']['active'] = $record['widget_active']; - // Make sure all settings expected in the current execution context are - // present. - $instance['settings'] += field_info_instance_settings($record['type']); - $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']); - foreach ($instance['display'] as $build_mode => $display) { - $instance['display'][$build_mode]['settings'] += field_info_formatter_settings($display['type']); - } - module_invoke_all('field_read_instance', $instance); $instances[] = $instance; } diff --git a/modules/field/field.default.inc b/modules/field/field.default.inc index 2d4be00ff..537583264 100644 --- a/modules/field/field.default.inc +++ b/modules/field/field.default.inc @@ -112,14 +112,9 @@ function field_default_view($obj_type, $object, $field, $instance, $items, $buil list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); $addition = array(); + $display = $instance['display'][$build_mode]; - // If we don't have specific settings for the current build_mode, we use the - // (required) 'full' build_mode. - $display = isset($instance['display'][$build_mode]) ? $instance['display'][$build_mode] : $instance['display']['full']; - // Ensure we have a valid formatter and formatter settings. - $display = _field_get_formatter($display, $field); - - if ($display['type'] && $display['type'] !== 'hidden') { + if ($display['type'] !== 'hidden') { $theme = 'field_formatter_' . $display['type']; $single = (field_behaviors_formatter('multiple values', $display) == FIELD_BEHAVIOR_DEFAULT); @@ -174,6 +169,7 @@ function field_default_view($obj_type, $object, $field, $instance, $items, $buil $addition = array($field['field_name'] => $element); } + return $addition; } diff --git a/modules/field/field.info.inc b/modules/field/field.info.inc index 433494e1b..0b2dcbb8e 100644 --- a/modules/field/field.info.inc +++ b/modules/field/field.info.inc @@ -17,29 +17,6 @@ */ /** - * Return valid formatter type and settings. - * - * Backs up to default formatter and settings if the intended formatter is no - * longer available. This might happen when the formatter has been renamed in - * the module, or if the module has been disabled since then. - */ -function _field_get_formatter($display, $field) { - if ($display['type'] != 'hidden') { - $formatter_type = field_info_formatter_types($display['type']); - if (empty($formatter_type)) { - $field_type = field_info_field_types($field['type']); - $display['type'] = $field_type['default_formatter']; - $formatter_type = field_info_formatter_types($display['type']); - } - $function = $formatter_type['module'] . '_field_formatter_settings'; - if (drupal_function_exists($function)) { - $display['settings'] += $function($display['type']); - } - } - return $display; -} - -/** * Collate all information on field types, widget types and related structures. * * @param $reset @@ -169,18 +146,16 @@ function _field_info_collate_types($reset = FALSE) { * Collate all information on existing fields and instances. * * @param $reset - * If TRUE, clear the cache. The information will be rebuilt from the database - * next time it is needed. Defaults to FALSE. + * If TRUE, clear the cache. The information will be rebuilt from the + * database next time it is needed. Defaults to FALSE. * @return * If $reset is TRUE, nothing. * If $reset is FALSE, an array containing the following elements: - * - * - fields: array of all defined Field objects, keyed by field - * name. Each field has an additional element, bundles, which is - * an array of all bundles to which the field is assigned. - * - instances: array whose keys are bundle names and whose values - * are an array, keyed by field name, of all Instance objects in - * that bundle. + * - fields: array of all defined Field objects, keyed by field name. Each + * field has an additional element, bundles, which is an array of all + * bundles to which the field is assigned. + * - instances: array whose keys are bundle names and whose values are an + * array, keyed by field name, of all instances in that bundle. */ function _field_info_collate_fields($reset = FALSE) { static $info; @@ -197,13 +172,23 @@ function _field_info_collate_fields($reset = FALSE) { } else { $info = array( - 'fields' => field_read_fields(), - 'instances' => array_fill_keys(array_keys(field_info_bundles()), array()), + 'fields' => array(), + 'instances' => array(), ); + // Populate fields + $fields = field_read_fields(); + foreach ($fields as $field) { + $field = _field_info_prepare_field($field); + $info['fields'][$field['field_name']] = $field; + } + // Populate instances. + $info['instances'] = array_fill_keys(array_keys(field_info_bundles()), array()); $instances = field_read_instances(); foreach ($instances as $instance) { + $field = $info['fields'][$instance['field_name']]; + $instance = _field_info_prepare_instance($instance, $field); $info['instances'][$instance['bundle']][$instance['field_name']] = $instance; $info['fields'][$instance['field_name']]['bundles'][] = $instance['bundle']; } @@ -215,6 +200,69 @@ function _field_info_collate_fields($reset = FALSE) { return $info; } + /** + * Prepare a field definition for the current run-time context. + * + * Since the field was last saved or updated, new field settings can be + * expected. + * + * @param $field + * The raw field structure as read from the database. + */ +function _field_info_prepare_field($field) { + // Make sure all expected field settings are present. + $field['settings'] += field_info_field_settings($field['type']); + + return $field; +} + +/** + * Prepare an instance definition for the current run-time context. + * + * Since the instance was last saved or updated, a number of things might have + * changed: widgets or formatters disabled, new settings expected, new build + * modes added... + * + * @param $instance + * The raw instance structure as read from the database. + * @param $field + * The field structure for the instance. + */ +function _field_info_prepare_instance($instance, $field) { + $field_type = field_info_field_types($field['type']); + + // Make sure all expected instance settings are present. + $instance['settings'] += field_info_instance_settings($field['type']); + + // Fallback to default widget if widget type is not available. + if (!field_info_widget_types($instance['widget']['type'])) { + $instance['widget']['type'] = $field_type['default_widget']; + } + // Make sure all expected widget settings are present. + $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']); + + foreach ($instance['display'] as $build_mode => $display) { + if ($display['type'] != 'hidden') { + // Fallback to default formatter if formatter type is not available. + if (!field_info_formatter_types($instance['display'][$build_mode]['type'])) { + $instance['display'][$build_mode]['type'] = $field_type['default_formatter']; + } + // Make sure all expected formatter settings are present. + $instance['display'][$build_mode]['settings'] += field_info_formatter_settings($instance['display'][$build_mode]['type']); + } + } + + // Fallback to 'full' display settings for unspecified build modes. + $obj_type = field_info_bundle_entity($instance['bundle']); + foreach (field_build_modes($obj_type) as $build_mode => $label) { + if (!isset($instance['display'][$build_mode])) { + $instance['display'][$build_mode] = $instance['display']['full']; + } + } + + return $instance; +} + /** * Helper function for determining the behavior of a widget * with respect to a given operation. diff --git a/modules/field/field.module b/modules/field/field.module index 1396e2283..18a77b412 100644 --- a/modules/field/field.module +++ b/modules/field/field.module @@ -391,8 +391,8 @@ function _field_filter_xss_display_allowed_tags() { * @param $item * The field item(s) to be formatted (such as $node->field_foo[0], * or $node->field_foo if the formatter handles multiple values itself) - * @param $formatter_name - * The name of the formatter to use. + * @param $formatter_type + * The name of the formatter type to use. * @param $node * Optionally, the containing node object for context purposes and * field-instance options. @@ -402,22 +402,25 @@ function _field_filter_xss_display_allowed_tags() { * It will have been passed through the necessary check_plain() or check_markup() * functions as necessary. */ -function field_format($obj_type, $object, $field, $item, $formatter_name = NULL, $formatter_settings = array()) { +function field_format($obj_type, $object, $field, $item, $formatter_type = NULL, $formatter_settings = array()) { if (!is_array($field)) { $field = field_info_field($field); } if (field_access('view', $field)) { - // Basically, we need $field, $instance, $obj_type, $object to be able to display a value... + $field_type = field_info_field_types($field['type']); + + // We need $field, $instance, $obj_type, $object to be able to display a value... list(, , $bundle) = field_attach_extract_ids($obj_type, $object); $instance = field_info_instance($field['field_name'], $bundle); $display = array( - 'type' => $formatter_name, + 'type' => $formatter_type ? $formatter_type : $field_type['default_formatter'], 'settings' => $formatter_settings, ); - $display = _field_get_formatter($display, $field); - if ($display['type'] && $display['type'] !== 'hidden') { + $display['settings'] += field_info_formatter_settings($display['type']); + + if ($display['type'] !== 'hidden') { $theme = $formatter['module'] . '_formatter_' . $display['type']; $element = array( @@ -427,6 +430,7 @@ function field_format($obj_type, $object, $field, $item, $formatter_name = NULL, '#formatter' => $display['type'], '#settings' => $display['settings'], '#object' => $object, + '#object_type' => $obj_type, '#delta' => isset($item['#delta']) ? $item['#delta'] : NULL, ); diff --git a/modules/field/field.test b/modules/field/field.test index 84fbf0cc3..ebd82236a 100644 --- a/modules/field/field.test +++ b/modules/field/field.test @@ -871,6 +871,9 @@ class FieldInfoTestCase extends DrupalWebTestCase { parent::setUp('field_sql_storage', 'field', 'field_test'); } + /** + * Test that field types and field definitions are correcly cached. + */ function testFieldInfo() { // Test that field_test module's fields, widgets, and formatters show up. $field_test_info = field_test_field_info(); @@ -943,7 +946,93 @@ class FieldInfoTestCase extends DrupalWebTestCase { $this->assertTrue($instance < $instances[$instance['field_name']], t('Instance appears in info correctly')); } - // Test that the field_info settings convenience functions work + /** + * Test that cached field definitions are ready for current runtime context. + */ + function testFieldPrepare() { + $field_definition = array( + 'field_name' => 'field', + 'type' => 'test_field', + ); + field_create_field($field_definition); + + // Simulate a stored field definition missing a field setting (e.g. a + // third-party module adding a new field setting has been enabled, and + // existing fields do not know the setting yet). + $data = db_result(db_query('SELECT data FROM {field_config} WHERE field_name = :field_name', array(':field_name' => $field_definition['field_name']))); + $data = unserialize($data); + $data['settings'] = array(); + db_update('field_config') + ->fields(array('data' => serialize($data))) + ->condition('field_name', $field_definition['field_name']) + ->execute(); + + field_cache_clear(); + + // Read the field back. + $field = field_info_field($field_definition['field_name']); + + // Check that all expected settings are in place. + $field_type = field_info_field_types($field_definition['type']); + $this->assertIdentical($field['settings'], $field_type['settings'], t('All expected default field settings are present.')); + } + + /** + * Test that cached instance definitions are ready for current runtime context. + */ + function testInstancePrepare() { + $field_definition = array( + 'field_name' => 'field', + 'type' => 'test_field', + ); + field_create_field($field_definition); + $instance_definition = array( + 'field_name' => $field_definition['field_name'], + 'bundle' => FIELD_TEST_BUNDLE, + ); + field_create_instance($instance_definition); + + // Simulate a stored instance definition missing various settings (e.g. a + // third-party module adding instance, widget or display settings has been + // enabled, but existing instances do not know the new settings). + $data = db_result(db_query('SELECT data FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $instance_definition['field_name'], ':bundle' => $instance_definition['bundle']))); + $data = unserialize($data); + $data['settings'] = array(); + $data['widget']['settings'] = 'unavailable_widget'; + $data['widget']['settings'] = array(); + $data['display']['full']['type'] = 'unavailable_formatter'; + $data['display']['full']['settings'] = array(); + db_update('field_config_instance') + ->fields(array('data' => serialize($data))) + ->condition('field_name', $instance_definition['field_name']) + ->condition('bundle', $instance_definition['bundle']) + ->execute(); + + field_cache_clear(); + + // Read the instance back. + $instance = field_info_instance($instance_definition['field_name'], $instance_definition['bundle']); + + // Check that all expected instance settings are in place. + $field_type = field_info_field_types($field_definition['type']); + $this->assertIdentical($instance['settings'], $field_type['instance_settings'] , t('All expected instance settings are present.')); + + // Check that the default widget is used and expected settings are in place. + $this->assertIdentical($instance['widget']['type'], $field_type['default_widget'], t('Unavailable widget replaced with default widget.')); + $widget_type = field_info_widget_types($instance['widget']['type']); + $this->assertIdentical($instance['widget']['settings'], $widget_type['settings'] , t('All expected widget settings are present.')); + + // Check that the default formatter is used and expected settings are in place. + foreach (field_build_modes('test_entity') as $build_mode => $label) { + $this->assertIdentical($instance['display'][$build_mode]['type'], $field_type['default_formatter'], t('Unavailable formatter replaced with default formatter in build_mode %build_mode', array('%build_mode' => $build_mode))); + $formatter_type = field_info_formatter_types($instance['display'][$build_mode]['type']); + $this->assertIdentical($instance['display'][$build_mode]['settings'], $formatter_type['settings'] , t('All expected formatter settings are present in build_mode %build_mode', array('%build_mode' => $build_mode))); + } + } + + /** + * Test that the field_info settings convenience functions work. + */ function testSettingsInfo() { $info = field_test_field_info(); foreach ($info as $type => $data) { @@ -1355,23 +1444,9 @@ class FieldCrudTestCase extends DrupalWebTestCase { ); field_create_field($field_definition); - // Simulate a stored field definition missing a field setting (e.g. a - // third-party module adding a new field setting has been enabled, and - // existing fields do not know the setting yet). - $data = db_query('SELECT data FROM {field_config} WHERE field_name = :field_name', array(':field_name' => $field_definition['field_name']))->fetchField(); - $data = unserialize($data); - $data['settings'] = array(); - db_update('field_config') - ->fields(array('data' => serialize($data))) - ->condition('field_name', $field_definition['field_name']) - ->execute(); - // Read the field back. $field = field_read_field($field_definition['field_name']); - - // Check that all expected settings are in place. - $field_type = field_info_field_types($field_definition['type']); - $this->assertIdentical($field['settings'], $field_type['settings'], t('All expected default field settings are present.')); + $this->assertTrue($field_definition < $field, t('The field was properly read.')); } /** @@ -1585,30 +1660,9 @@ class FieldInstanceCrudTestCase extends DrupalWebTestCase { function testReadFieldInstance() { field_create_instance($this->instance_definition); - // Simulate a stored instance definition missing various settings (e.g. a - // third-party module adding instance, widget or display settings has been - // enabled, but existing instances do not know the new settings). - $data = db_query('SELECT data FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $this->instance_definition['field_name'], ':bundle' => $this->instance_definition['bundle']))->fetchField(); - $data = unserialize($data); - $data['settings'] = array(); - $data['widget']['settings'] = array(); - $data['display']['full']['settings'] = array(); - db_update('field_config_instance') - ->fields(array('data' => serialize($data))) - ->condition('field_name', $this->instance_definition['field_name']) - ->condition('bundle', $this->instance_definition['bundle']) - ->execute(); - // Read the instance back. $instance = field_read_instance($this->instance_definition['field_name'], $this->instance_definition['bundle']); - - // Check that all expected settings are in place. - $field_type = field_info_field_types($this->field['type']); - $widget_type = field_info_widget_types($instance['widget']['type']); - $formatter_type = field_info_formatter_types($instance['display']['full']['type']); - $this->assertIdentical($instance['settings'], $field_type['instance_settings'] , t('All expected instance settings are present.')); - $this->assertIdentical($instance['widget']['settings'], $widget_type['settings'] , t('All expected widget settings are present.')); - $this->assertIdentical($instance['display']['full']['settings'], $formatter_type['settings'] , t('All expected formatter settings are present.')); + $this->assertTrue($this->instance_definition < $instance, t('The field was properly read.')); } /** |