? Makefile ? constants.pl ? d6-50-nodes.sql.gz ? d7-50-nodes.sql.gz ? head.kpf ? patches ? modules/field/field.delete.inc ? modules/field/modules/combo ? scripts/generate-autoload.pl ? sites/modules ? sites/all/cck ? sites/default/files ? sites/default/settings.php Index: modules/field/field.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.api.php,v retrieving revision 1.5 diff -u -F^[fc] -r1.5 field.api.php --- modules/field/field.api.php 26 Mar 2009 13:31:24 -0000 1.5 +++ modules/field/field.api.php 26 Mar 2009 22:32:40 -0000 @@ -440,6 +440,36 @@ function hook_field_attach_form($obj_typ } /** + * Act on field_attach_pre_load. + * + * This hook allows modules to load data before the Field Storage API, + * optionally preventing the field storage module from doing so. + * + * @param $obj_type + * The type of objects for which to load fields; e.g. 'node' or + * 'user'. + * @param $objects + * An array of objects for which to load fields. The keys for + * primary id and bundle name to load are identified by + * hook_fieldable_info for $obj_type. + * @param $age + * FIELD_LOAD_CURRENT to load the most recent revision for all + * fields, or FIELD_LOAD_REVISION to load the version indicated by + * each object. + * @param $additions + * An array of field data for the objects being loaded, keyed by + * entity id, field name, and item delta number. + * @param $skip_fields + * An array of whose keys are field names whose data has already + * been loaded and therefore should not be loaded again. + * @return + * Loaded field values are added to $additions and loaded field + * names are set set as keys in $skip_fields. + */ +function hook_field_attach_pre_load($obj_type, $objects, $age, &$additions, &$skip_fields) { +} + +/** * Act on field_attach_load. * * This hook is invoked after the field module has performed the operation. @@ -482,22 +512,40 @@ function hook_field_attach_presave($obj_ /** * Act on field_attach_insert. - * - * This hook is invoked after the field module has performed the operation. * - * See field_attach_insert() for details and arguments. + * This hook allows modules to store data before the Field Storage + * API, optionally preventing the field storage module from doing so. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to save. + * @param $skip_fields + * An array whose keys are field names whose data has already + * been saved and therefore should not be saved again. + * @return + * Saved field names are set set as keys in $skip_fields. */ -function hook_field_attach_insert($obj_type, $object) { +function hook_field_attach_pre_insert($obj_type, $object, &$skip_fields) { } /** * Act on field_attach_update. - * - * This hook is invoked after the field module has performed the operation. * - * See field_attach_update() for details and arguments. + * This hook allows modules to store data before the Field Storage + * API, optionally preventing the field storage module from doing so. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to save. + * @param $skip_fields + * An array whose keys are field names whose data has already + * been saved and therefore should not be saved again. + * @return + * Saved field names are set set as keys in $skip_fields. */ -function hook_field_attach_update($obj_type, $object) { +function hook_field_attach_pre_update($obj_type, $object, &$skip_fields) { } /** @@ -592,11 +640,14 @@ function hook_field_attach_delete_bundle * FIELD_LOAD_CURRENT to load the most recent revision for all * fields, or FIELD_LOAD_REVISION to load the version indicated by * each object. + * @param $skip_fields + * An array of whose keys are field names whose data has already + * been loaded and therefore should not be loaded again. * @return * An array of field data for the objects, keyed by entity id, field * name, and item delta number. */ -function hook_field_storage_load($obj_type, $queried_objs, $age) { +function hook_field_storage_load($obj_type, $queried_objs, $age, $skip_fields) { } /** @@ -609,8 +660,11 @@ function hook_field_storage_load($obj_ty * @param $op * FIELD_STORAGE_UPDATE when updating an existing object, * FIELD_STORAGE_INSERT when inserting a new object. + * @param $skip_fields + * An array whose keys are field names whose data has already + * been saved and therefore should not be saved again. */ -function hook_field_storage_write($obj_type, $object, $op) { +function hook_field_storage_write($obj_type, $object, $op, $skip_fields) { } /** Index: modules/field/field.attach.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v retrieving revision 1.7 diff -u -F^[fc] -r1.7 field.attach.inc --- modules/field/field.attach.inc 26 Mar 2009 13:31:24 -0000 1.7 +++ modules/field/field.attach.inc 26 Mar 2009 22:32:40 -0000 @@ -241,7 +241,7 @@ function _field_attach_form($obj_type, $ function _field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT) { $queried_objects = array(); - // Fetch avaliable nodes from cache. + // Fetch avaliable objects from cache. foreach ($objects as $object) { list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); $cid = "field:$obj_type:$id:$vid"; @@ -254,17 +254,36 @@ function _field_attach_load($obj_type, $ $queried_objects[$id] = $objects[$id]; } } - // Fetch other nodes from the database. + + // Fetch other objects from the database. if ($queried_objects) { // We need the raw additions to be able to cache them, so - // content_storage_load() and hook_field_load() must not alter - // nodes directly but return their additions. - $additions = module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_load', $obj_type, $queried_objects, $age); + // hook_field_storage_load() and hook_field_attach_pre_load() must not + // alter objects directly but return their additions. + + // Let any module load field data before the storage engine, + // accumulating along the way. + $loaded = array(); + $skip_fields = array(); + foreach (module_implements('field_attach_pre_load') as $module) { + $function = $module . '_field_attach_pre_load'; + $function($obj_type, $queried_objects, $age, $loaded, $skip_fields); + } + + // The field storage engine loads the rest. + $additions = module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_load', $obj_type, $queried_objects, $age, $skip_fields); + foreach ($additions as $id => $obj_additions) { foreach ($obj_additions as $key => $value) { $queried_objects[$id]->$key = $value; } } + foreach ($loaded as $id => $obj_additions) { + foreach ($obj_additions as $key => $value) { + $queried_objects[$id]->$key = $value; + $additions[$id][$key] = $value; + } + } // TODO D7 : to be consistent we might want to make hook_field_load() accept // multiple objects too. Which forbids going through _field_invoke(), but @@ -464,15 +483,19 @@ function _field_attach_presave($obj_type */ function _field_attach_insert($obj_type, &$object) { - // Let other modules act on inserting the object. - foreach (module_implements('field_attach_insert') as $module) { - $function = $module . '_field_attach_insert'; - $function($obj_type, $object); - } - _field_invoke('insert', $obj_type, $object); - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_write', $obj_type, $object, FIELD_STORAGE_INSERT); + // Let other modules act on inserting the object, accumulating saved + // fields along the way. + $saved = array(); + foreach (module_implements('field_attach_pre_insert') as $module) { + $function = $module . '_field_attach_pre_insert'; + $function($obj_type, $object, $saved); + } + + // Field storage module saves any remaining unsaved fields. + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_write', $obj_type, $object, FIELD_STORAGE_INSERT, $saved); + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); if ($cacheable) { cache_clear_all("field:$obj_type:$id:", 'cache_field', TRUE); @@ -489,14 +512,18 @@ function _field_attach_insert($obj_type, */ function _field_attach_update($obj_type, &$object) { - // Let other modules act on updating the object. - foreach (module_implements('field_attach_update') as $module) { - $function = $module . '_field_attach_update'; - $function($output, $obj_type, $object); + _field_invoke('update', $obj_type, $object); + + // Let other modules act on updating the object, accumulating saved + // fields along the way. + $saved = array(); + foreach (module_implements('field_attach_pre_update') as $module) { + $function = $module . '_field_attach_pre_update'; + $function($obj_type, $object, $saved); } - _field_invoke('update', $obj_type, $object); - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_write', $obj_type, $object, FIELD_STORAGE_UPDATE); + // Field storage module saves any remaining unsaved fields. + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_write', $obj_type, $object, FIELD_STORAGE_UPDATE, $saved); list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); if ($cacheable) { Index: modules/field/field.crud.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.crud.inc,v retrieving revision 1.7 diff -u -F^[fc] -r1.7 field.crud.inc --- modules/field/field.crud.inc 26 Mar 2009 13:31:24 -0000 1.7 +++ modules/field/field.crud.inc 26 Mar 2009 22:32:40 -0000 @@ -346,10 +346,11 @@ function field_create_instance($instance _field_write_instance($instance); - module_invoke_all('field_create_instance', $instance); - // Clear caches field_cache_clear(); + + module_invoke_all('field_create_instance', $instance); + return FALSE; } Index: modules/field/field.info.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.info.inc,v retrieving revision 1.4 diff -u -F^[fc] -r1.4 field.info.inc --- modules/field/field.info.inc 10 Feb 2009 16:09:00 -0000 1.4 +++ modules/field/field.info.inc 26 Mar 2009 22:32:40 -0000 @@ -142,7 +142,7 @@ function _field_info_collate_types($rese cache_set('field_info_types', $info, 'cache_field'); } } - + return $info; } Index: modules/field/modules/field_sql_storage/field_sql_storage.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v retrieving revision 1.5 diff -u -F^[fc] -r1.5 field_sql_storage.module --- modules/field/modules/field_sql_storage/field_sql_storage.module 13 Mar 2009 21:25:40 -0000 1.5 +++ modules/field/modules/field_sql_storage/field_sql_storage.module 26 Mar 2009 22:32:40 -0000 @@ -179,11 +179,14 @@ function field_sql_storage_field_storage * FIELD_LOAD_CURRENT to load the most recent revision for all * fields, or FIELD_LOAD_REVISION to load the version indicated by * each object. + * @param $skip_fields + * An array of field names for which data has already been loaded + * and so should not be loaded by this function. * @return * An array of field data for the objects, keyed by entity id, field * name, and item delta number. */ -function field_sql_storage_field_storage_load($obj_type, $objects, $age) { +function field_sql_storage_field_storage_load($obj_type, $objects, $age, $skip_fields = array()) { $etid = _field_sql_storage_etid($obj_type); $load_current = $age == FIELD_LOAD_CURRENT; @@ -200,6 +203,10 @@ function field_sql_storage_field_storage $additions = array(); foreach ($field_ids as $field_name => $ids) { + if (isset($skip_fields[$field_name])) { + continue; + } + $field = field_info_field($field_name); $table = $load_current ? _field_sql_storage_tablename($field_name) : _field_sql_storage_revision_tablename($field_name); @@ -229,13 +236,17 @@ function field_sql_storage_field_storage return $additions; } -function field_sql_storage_field_storage_write($obj_type, $object, $op) { +function field_sql_storage_field_storage_write($obj_type, $object, $op, $skip_fields) { list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); $etid = _field_sql_storage_etid($obj_type); $instances = field_info_instances($bundle); foreach ($instances as $instance) { $field_name = $instance['field_name']; + if (isset($skip_fields[$field_name])) { + continue; + } + $table_name = _field_sql_storage_tablename($field_name); $revision_name = _field_sql_storage_revision_tablename($field_name); $field = field_read_field($field_name);