From f3ed3283db182dfbbf35f5db077ebce2bc368bfe Mon Sep 17 00:00:00 2001 From: Angie Byron Date: Thu, 5 Feb 2009 03:42:58 +0000 Subject: #361683 follow-up by sun: Remove more windows line endings. --- modules/field/field.attach.inc | 1264 ++++++++++++++++++++-------------------- 1 file changed, 632 insertions(+), 632 deletions(-) (limited to 'modules/field/field.attach.inc') diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc index 6f415c166..b16f174e3 100644 --- a/modules/field/field.attach.inc +++ b/modules/field/field.attach.inc @@ -1,632 +1,632 @@ -$field_name) ? $object->$field_name : array(); - - // Make sure AHAH 'add more' button isn't sent to the fields for processing. - // TODO D7 : needed ? - unset($items[$field_name . '_add_more']); - - $function = $default ? 'field_default_' . $op : $field['module'] . '_field_' . $op; - if (drupal_function_exists($function)) { - $result = $function($obj_type, $object, $field, $instance, $items, $a, $b); - if (is_array($result)) { - $return = array_merge($return, $result); - } - else if (isset($result)) { - $return[] = $result; - } - } - // Put back the altered items in the object, if the field was present to - // begin with (avoid replacing missing field with empty array(), those are - // not semantically equivalent on update). - if (isset($object->$field_name)) { - $object->$field_name = $items; - } - } - - return $return; -} - -/** - * Invoke field.module's version of a field hook. - */ -function _field_invoke_default($op, $obj_type, &$object, &$a = NULL, &$b = NULL) { - return _field_invoke($op, $obj_type, $object, $a, $b, TRUE); -} - -/** - * @} End of "defgroup field_attach" - * - * The rest of the functions in this file are not in a group, but - * their automatically-generated autoloaders are (see field.autoload.inc). - */ - -/** - * Add form elements for all fields for an object to a form structure. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object for which to load form elements, used to initialize - * default form values. - * @param $form - * The form structure to fill in. - * @param $form_state - * An associative array containing the current state of the form. - * - * TODO : document the resulting $form structure, like we do for - * field_attach_view(). - */ -function _field_attach_form($obj_type, $object, &$form, $form_state) { - // TODO : something's not right here : do we alter the form or return a value ? - $form += (array) _field_invoke_default('form', $obj_type, $object, $form, $form_state); - - // Let other modules make changes to the form. - foreach (module_implements('field_attach_form') as $module) { - $function = $module . '_field_attach_form'; - $function($obj_type, $object, $form, $form_state); - } -} - -/** - * Load all fields for the most current version of each of a set of - * objects of a single object type. - * - * @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. Defaults to FIELD_LOAD_CURRENT; use - * field_attach_load_revision() instead of passing FIELD_LOAD_REVISION. - * @returns - * On return, the objects in $objects are modified by having the - * appropriate set of fields added. - */ -function _field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT) { - $queried_objects = array(); - - // Fetch avaliable nodes from cache. - foreach ($objects as $object) { - list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); - $cid = "field:$obj_type:$id:$vid"; - if ($cacheable && $cached = cache_get($cid, 'cache_field')) { - foreach ($cached->data as $key => $value) { - $object->$key = $value; - } - } - else { - $queried_objects[$id] = $objects[$id]; - } - } - // Fetch other nodes 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); - foreach ($additions as $id => $obj_additions) { - foreach ($obj_additions as $key => $value) { - $queried_objects[$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 - // requires manually iterating the instances instead. - foreach ($queried_objects as $id => $object) { - list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); - - // Make sure empty fields are present as empty arrays. - $instances = field_info_instances($bundle); - foreach ($instances as $instance) { - if (!isset($object->{$instance['field_name']})) { - $queried_objects[$id]->{$instance['field_name']} = array(); - $additions[$id][$instance['field_name']] = array(); - } - } - - $custom_additions = _field_invoke('load', $obj_type, $object); - foreach ($custom_additions as $key => $value) { - $queried_objects[$id]->$key = $value; - $additions[$id][$key] = $value; - } - - // Let other modules act on loading the object. - // TODO : this currently doesn't get cached (we cache $additions). - // This should either be called after we fetch from cache, or return an - // array of additions. - foreach (module_implements('field_attach_load') as $module) { - $function = $module . '_field_attach_load'; - $function($obj_type, $queried_objects[$id]); - } - - // Cache the data. - if ($cacheable) { - $cid = "field:$obj_type:$id:$vid"; - $data = isset($additions[$id]) ? $additions[$id] : array(); - cache_set($cid, $data, 'cache_field'); - } - } - } -} - -/** - * Load all fields for a previous version of each of a set of - * objects of a single object type. - * - * @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, revision id, and bundle name to load are identified by - * hook_fieldable_info for $obj_type. - * @returns - * On return, the objects in $objects are modified by having the - * appropriate set of fields added. - */ -function _field_attach_load_revision($obj_type, $objects) { - return field_attach_load($obj_type, $objects, FIELD_LOAD_REVISION); -} - -/** - * Perform field validation against the field data in an object. - * Field validation is distinct from widget validation; the latter - * occurs during the Form API validation phase. - * - * NOTE: This functionality does not yet exist in its final state. - * Eventually, field validation will occur during field_attach_insert - * or _update which will throw an exception on failure. For now, - * fieldable entities must call this during their Form API validation - * phase, and field validation will call form_set_error for any - * errors. See http://groups.drupal.org/node/18019. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object with fields to validate. - */ -function _field_attach_validate($obj_type, &$object, $form = NULL) { - _field_invoke('validate', $obj_type, $object, $form); - _field_invoke_default('validate', $obj_type, $object, $form); - - // Let other modules validate the object. - foreach (module_implements('field_attach_validate') as $module) { - $function = $module . '_field_attach_validate'; - $function($obj_type, $object, $form); - } -} - -/** - * Perform necessary operations on field data submitted by a form. - * - * Currently, this accounts for drag-and-drop reordering of - * field values, and filtering of empty values. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object being submitted. The 'bundle key', 'id key' and (if applicable) - * 'revision key' should be present. The actual field values will be read - * from $form_state['values']. - * @param $form - * The form structure to fill in. - * @param $form_state - * An associative array containing the current state of the form. - */ -function _field_attach_submit($obj_type, &$object, $form, &$form_state) { - _field_invoke_default('submit', $obj_type, $object, $form, $form_state); - - // Let other modules act on submitting the object. - foreach (module_implements('field_attach_submit') as $module) { - $function = $module . '_field_attach_submit'; - $function($obj_type, $object, $form, $form_state); - } -} - -/** - * Perform necessary operations just before fields data get saved. - * - * We take no specific action here, we just give other - * modules the opportunity to act. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object with fields to process. - */ -function _field_attach_presave($obj_type, &$object) { - // TODO : to my knowledge, no field module has any use for 'presave' on D6. - // should we keep this ? - _field_invoke('presave', $obj_type, $object); - - // Let other modules act on presaving the object. - foreach (module_implements('field_attach_presave') as $module) { - $function = $module . '_field_attach_presave'; - $function($obj_type, $object); - } -} - -/** - * Save field data for a new object. The passed in object must - * already contain its id and (if applicable) revision id attributes. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object with fields to save. - */ -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); - - list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); - if ($cacheable) { - cache_clear_all("field:$obj_type:$id:", 'cache_field', TRUE); - } -} - -/** - * Save field data for an existing object. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object with fields to save. - */ -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); - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_write', $obj_type, $object, TRUE); - - list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); - if ($cacheable) { - cache_clear_all("field:$obj_type:$id:$vid", 'cache_field'); - } -} - -/** - * Delete field data for an existing object. This deletes all - * revisions of field data for the object. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object whose field data to delete. - */ -function _field_attach_delete($obj_type, &$object) { - _field_invoke('delete', $obj_type, $object); - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_delete', $obj_type, $object); - - // Let other modules act on deleting the object. - foreach (module_implements('field_attach_delete') as $module) { - $function = $module . '_field_attach_delete'; - $function($obj_type, $object); - } - - list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); - if ($cacheable) { - cache_clear_all("field:$obj_type:$id:", 'cache_field', TRUE); - } -} - -/** - * Delete field data for a single revision of an existing object. The - * passed object must have a revision id attribute. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object with fields to save. - */ -function _field_attach_delete_revision($obj_type, &$object) { - _field_invoke('delete revision', $obj_type, $object); - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_delete_revision', $obj_type, $object); - - // Let other modules act on deleting the revision. - foreach (module_implements('field_attach_delete_revision') as $module) { - $function = $module . '_field_attach_delete_revision'; - $function($obj_type, $object); - } - - list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); - if ($cacheable) { - cache_clear_all("field:$obj_type:$id:$vid", 'cache_field'); - } -} - -/** - * Generate and return a structured content array tree suitable for - * drupal_render() for all of the fields on an object. The format of - * each field's rendered content depends on the display formatter and - * its settings. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object with fields to render. - * @param $teaser - * Whether to display the teaser only, as on the main page. - * @return - * A structured content array tree for drupal_render(). - */ -function _field_attach_view($obj_type, &$object, $teaser = FALSE) { - // Let field modules sanitize their data for output. - _field_invoke('sanitize', $obj_type, $object); - - $output = _field_invoke_default('view', $obj_type, $object, $teaser); - - // Let other modules make changes after rendering the view. - foreach (module_implements('field_attach_view') as $module) { - $function = $module . '_field_attach_view'; - $function($output, $obj_type, $object, $teaser); - } - - return $output; - -} - -/** - * To be called in entity preprocessor. - * - * - Adds $FIELD_NAME_rendered variables - * containing the themed output for the whole field. - * - Adds the formatted values in the 'view' key of the items. - */ -function _field_attach_preprocess($obj_type, &$object) { - return _field_invoke_default('preprocess', $obj_type, $object); -} - -/** - * Implementation of hook_nodeapi_prepare_translation. - * - * TODO D7: We do not yet know if this really belongs in Field API. - */ -function _field_attach_prepare_translation(&$node) { - // Prevent against invalid 'nodes' built by broken 3rd party code. - if (isset($node->type)) { - $type = content_types($node->type); - // Save cycles if the type has no fields. - if (!empty($type['instances'])) { - $default_additions = _field_invoke_default('prepare translation', $node); - $additions = _field_invoke('prepare translation', $node); - // Merge module additions after the default ones to enable overriding - // of field values. - $node = (object) array_merge((array) $node, $default_additions, $additions); - } - } -} - -/** - * Notify field.module that a new bundle was created. - * - * The default SQL-based storage doesn't need to do anytrhing about it, but - * others might. - * - * @param $bundle - * The name of the newly created bundle. - */ -function _field_attach_create_bundle($bundle) { - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_create_bundle', $bundle); - - // Clear the cache. - field_cache_clear(); - - foreach (module_implements('field_attach_create_bundle') as $module) { - $function = $module . '_field_attach_create_bundle'; - $function($bundle); - } -} - -/** - * Notify field.module that a bundle was renamed. - * - * @param $bundle_old - * The previous name of the bundle. - * @param $bundle_new - * The new name of the bundle. - */ -function _field_attach_rename_bundle($bundle_old, $bundle_new) { - module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_rename_bundle', $bundle_old, $bundle_new); - db_update('field_config_instance') - ->fields(array('bundle' => $bundle_new)) - ->condition('bundle', $bundle_old) - ->execute(); - - // Clear the cache. - field_cache_clear(); - - foreach (module_implements('field_attach_rename_bundle') as $module) { - $function = $module . '_field_attach_rename_bundle'; - $function($bundle_old, $bundle_new); - } -} - -/** - * Notify field.module the a bundle was deleted. - * - * This deletes the data for the field instances as well as the field instances - * themselves. This function actually just marks the data and field instances - * and deleted, leaving the garbage collection for a separate process, because - * it is not always possible to delete this much data in a single page request - * (particularly since for some field types, the deletion is more than just a - * simple DELETE query). - * - * @param $bundle - * The bundle to delete. - */ -function _field_attach_delete_bundle($bundle) { - // Let other modules act on deleting the bundle - foreach (module_implements('field_attach_delete_bundle') as $module) { - $function = $module . '_field_attach_delete_bundle'; - $function($bundle); - } - - // Delete the instances themseves - $instances = field_info_instances($bundle); - foreach ($instances as $instance) { - field_delete_instance($instance['field_name'], $bundle); - } -} - -/** - * Helper function to extract id, vid, and bundle name from an object. - * - * @param $obj_type - * The type of $object; e.g. 'node' or 'user'. - * @param $object - * The object from which to extract values. - * @return - * A numerically indexed array (not a hash table) containing these - * elements: - * - * 0: primary id of the object - * 1: revision id of the object, or NULL if $obj_type is not versioned - * 2: bundle name of the object - * 3: whether $obj_type's fields should be cached (TRUE/FALSE) - */ -function _field_attach_extract_ids($object_type, $object) { - // TODO D7 : prevent against broken 3rd party $node without 'type'. - $info = field_info_fieldable_types($object_type); - // Objects being created might not have id/vid yet. - $id = isset($object->{$info['id key']}) ? $object->{$info['id key']} : NULL; - $vid = ($info['revision key'] && isset($object->{$info['revision key']})) ? $object->{$info['revision key']} : NULL; - // If no bundle key provided, then we assume a single bundle, named after the - // type of the object. - $bundle = $info['bundle key'] ? $object->{$info['bundle key']} : $object_type; - $cacheable = isset($info['cacheable']) ? $info['cacheable'] : FALSE; - return array($id, $vid, $bundle, $cacheable); -} - -/** - * @autoload} End of "@autoload field_attach" - */ +$field_name) ? $object->$field_name : array(); + + // Make sure AHAH 'add more' button isn't sent to the fields for processing. + // TODO D7 : needed ? + unset($items[$field_name . '_add_more']); + + $function = $default ? 'field_default_' . $op : $field['module'] . '_field_' . $op; + if (drupal_function_exists($function)) { + $result = $function($obj_type, $object, $field, $instance, $items, $a, $b); + if (is_array($result)) { + $return = array_merge($return, $result); + } + else if (isset($result)) { + $return[] = $result; + } + } + // Put back the altered items in the object, if the field was present to + // begin with (avoid replacing missing field with empty array(), those are + // not semantically equivalent on update). + if (isset($object->$field_name)) { + $object->$field_name = $items; + } + } + + return $return; +} + +/** + * Invoke field.module's version of a field hook. + */ +function _field_invoke_default($op, $obj_type, &$object, &$a = NULL, &$b = NULL) { + return _field_invoke($op, $obj_type, $object, $a, $b, TRUE); +} + +/** + * @} End of "defgroup field_attach" + * + * The rest of the functions in this file are not in a group, but + * their automatically-generated autoloaders are (see field.autoload.inc). + */ + +/** + * Add form elements for all fields for an object to a form structure. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object for which to load form elements, used to initialize + * default form values. + * @param $form + * The form structure to fill in. + * @param $form_state + * An associative array containing the current state of the form. + * + * TODO : document the resulting $form structure, like we do for + * field_attach_view(). + */ +function _field_attach_form($obj_type, $object, &$form, $form_state) { + // TODO : something's not right here : do we alter the form or return a value ? + $form += (array) _field_invoke_default('form', $obj_type, $object, $form, $form_state); + + // Let other modules make changes to the form. + foreach (module_implements('field_attach_form') as $module) { + $function = $module . '_field_attach_form'; + $function($obj_type, $object, $form, $form_state); + } +} + +/** + * Load all fields for the most current version of each of a set of + * objects of a single object type. + * + * @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. Defaults to FIELD_LOAD_CURRENT; use + * field_attach_load_revision() instead of passing FIELD_LOAD_REVISION. + * @returns + * On return, the objects in $objects are modified by having the + * appropriate set of fields added. + */ +function _field_attach_load($obj_type, $objects, $age = FIELD_LOAD_CURRENT) { + $queried_objects = array(); + + // Fetch avaliable nodes from cache. + foreach ($objects as $object) { + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); + $cid = "field:$obj_type:$id:$vid"; + if ($cacheable && $cached = cache_get($cid, 'cache_field')) { + foreach ($cached->data as $key => $value) { + $object->$key = $value; + } + } + else { + $queried_objects[$id] = $objects[$id]; + } + } + // Fetch other nodes 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); + foreach ($additions as $id => $obj_additions) { + foreach ($obj_additions as $key => $value) { + $queried_objects[$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 + // requires manually iterating the instances instead. + foreach ($queried_objects as $id => $object) { + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); + + // Make sure empty fields are present as empty arrays. + $instances = field_info_instances($bundle); + foreach ($instances as $instance) { + if (!isset($object->{$instance['field_name']})) { + $queried_objects[$id]->{$instance['field_name']} = array(); + $additions[$id][$instance['field_name']] = array(); + } + } + + $custom_additions = _field_invoke('load', $obj_type, $object); + foreach ($custom_additions as $key => $value) { + $queried_objects[$id]->$key = $value; + $additions[$id][$key] = $value; + } + + // Let other modules act on loading the object. + // TODO : this currently doesn't get cached (we cache $additions). + // This should either be called after we fetch from cache, or return an + // array of additions. + foreach (module_implements('field_attach_load') as $module) { + $function = $module . '_field_attach_load'; + $function($obj_type, $queried_objects[$id]); + } + + // Cache the data. + if ($cacheable) { + $cid = "field:$obj_type:$id:$vid"; + $data = isset($additions[$id]) ? $additions[$id] : array(); + cache_set($cid, $data, 'cache_field'); + } + } + } +} + +/** + * Load all fields for a previous version of each of a set of + * objects of a single object type. + * + * @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, revision id, and bundle name to load are identified by + * hook_fieldable_info for $obj_type. + * @returns + * On return, the objects in $objects are modified by having the + * appropriate set of fields added. + */ +function _field_attach_load_revision($obj_type, $objects) { + return field_attach_load($obj_type, $objects, FIELD_LOAD_REVISION); +} + +/** + * Perform field validation against the field data in an object. + * Field validation is distinct from widget validation; the latter + * occurs during the Form API validation phase. + * + * NOTE: This functionality does not yet exist in its final state. + * Eventually, field validation will occur during field_attach_insert + * or _update which will throw an exception on failure. For now, + * fieldable entities must call this during their Form API validation + * phase, and field validation will call form_set_error for any + * errors. See http://groups.drupal.org/node/18019. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to validate. + */ +function _field_attach_validate($obj_type, &$object, $form = NULL) { + _field_invoke('validate', $obj_type, $object, $form); + _field_invoke_default('validate', $obj_type, $object, $form); + + // Let other modules validate the object. + foreach (module_implements('field_attach_validate') as $module) { + $function = $module . '_field_attach_validate'; + $function($obj_type, $object, $form); + } +} + +/** + * Perform necessary operations on field data submitted by a form. + * + * Currently, this accounts for drag-and-drop reordering of + * field values, and filtering of empty values. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object being submitted. The 'bundle key', 'id key' and (if applicable) + * 'revision key' should be present. The actual field values will be read + * from $form_state['values']. + * @param $form + * The form structure to fill in. + * @param $form_state + * An associative array containing the current state of the form. + */ +function _field_attach_submit($obj_type, &$object, $form, &$form_state) { + _field_invoke_default('submit', $obj_type, $object, $form, $form_state); + + // Let other modules act on submitting the object. + foreach (module_implements('field_attach_submit') as $module) { + $function = $module . '_field_attach_submit'; + $function($obj_type, $object, $form, $form_state); + } +} + +/** + * Perform necessary operations just before fields data get saved. + * + * We take no specific action here, we just give other + * modules the opportunity to act. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to process. + */ +function _field_attach_presave($obj_type, &$object) { + // TODO : to my knowledge, no field module has any use for 'presave' on D6. + // should we keep this ? + _field_invoke('presave', $obj_type, $object); + + // Let other modules act on presaving the object. + foreach (module_implements('field_attach_presave') as $module) { + $function = $module . '_field_attach_presave'; + $function($obj_type, $object); + } +} + +/** + * Save field data for a new object. The passed in object must + * already contain its id and (if applicable) revision id attributes. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to save. + */ +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); + + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); + if ($cacheable) { + cache_clear_all("field:$obj_type:$id:", 'cache_field', TRUE); + } +} + +/** + * Save field data for an existing object. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to save. + */ +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); + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_write', $obj_type, $object, TRUE); + + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); + if ($cacheable) { + cache_clear_all("field:$obj_type:$id:$vid", 'cache_field'); + } +} + +/** + * Delete field data for an existing object. This deletes all + * revisions of field data for the object. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object whose field data to delete. + */ +function _field_attach_delete($obj_type, &$object) { + _field_invoke('delete', $obj_type, $object); + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_delete', $obj_type, $object); + + // Let other modules act on deleting the object. + foreach (module_implements('field_attach_delete') as $module) { + $function = $module . '_field_attach_delete'; + $function($obj_type, $object); + } + + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); + if ($cacheable) { + cache_clear_all("field:$obj_type:$id:", 'cache_field', TRUE); + } +} + +/** + * Delete field data for a single revision of an existing object. The + * passed object must have a revision id attribute. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to save. + */ +function _field_attach_delete_revision($obj_type, &$object) { + _field_invoke('delete revision', $obj_type, $object); + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_delete_revision', $obj_type, $object); + + // Let other modules act on deleting the revision. + foreach (module_implements('field_attach_delete_revision') as $module) { + $function = $module . '_field_attach_delete_revision'; + $function($obj_type, $object); + } + + list($id, $vid, $bundle, $cacheable) = field_attach_extract_ids($obj_type, $object); + if ($cacheable) { + cache_clear_all("field:$obj_type:$id:$vid", 'cache_field'); + } +} + +/** + * Generate and return a structured content array tree suitable for + * drupal_render() for all of the fields on an object. The format of + * each field's rendered content depends on the display formatter and + * its settings. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object with fields to render. + * @param $teaser + * Whether to display the teaser only, as on the main page. + * @return + * A structured content array tree for drupal_render(). + */ +function _field_attach_view($obj_type, &$object, $teaser = FALSE) { + // Let field modules sanitize their data for output. + _field_invoke('sanitize', $obj_type, $object); + + $output = _field_invoke_default('view', $obj_type, $object, $teaser); + + // Let other modules make changes after rendering the view. + foreach (module_implements('field_attach_view') as $module) { + $function = $module . '_field_attach_view'; + $function($output, $obj_type, $object, $teaser); + } + + return $output; + +} + +/** + * To be called in entity preprocessor. + * + * - Adds $FIELD_NAME_rendered variables + * containing the themed output for the whole field. + * - Adds the formatted values in the 'view' key of the items. + */ +function _field_attach_preprocess($obj_type, &$object) { + return _field_invoke_default('preprocess', $obj_type, $object); +} + +/** + * Implementation of hook_nodeapi_prepare_translation. + * + * TODO D7: We do not yet know if this really belongs in Field API. + */ +function _field_attach_prepare_translation(&$node) { + // Prevent against invalid 'nodes' built by broken 3rd party code. + if (isset($node->type)) { + $type = content_types($node->type); + // Save cycles if the type has no fields. + if (!empty($type['instances'])) { + $default_additions = _field_invoke_default('prepare translation', $node); + $additions = _field_invoke('prepare translation', $node); + // Merge module additions after the default ones to enable overriding + // of field values. + $node = (object) array_merge((array) $node, $default_additions, $additions); + } + } +} + +/** + * Notify field.module that a new bundle was created. + * + * The default SQL-based storage doesn't need to do anytrhing about it, but + * others might. + * + * @param $bundle + * The name of the newly created bundle. + */ +function _field_attach_create_bundle($bundle) { + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_create_bundle', $bundle); + + // Clear the cache. + field_cache_clear(); + + foreach (module_implements('field_attach_create_bundle') as $module) { + $function = $module . '_field_attach_create_bundle'; + $function($bundle); + } +} + +/** + * Notify field.module that a bundle was renamed. + * + * @param $bundle_old + * The previous name of the bundle. + * @param $bundle_new + * The new name of the bundle. + */ +function _field_attach_rename_bundle($bundle_old, $bundle_new) { + module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_rename_bundle', $bundle_old, $bundle_new); + db_update('field_config_instance') + ->fields(array('bundle' => $bundle_new)) + ->condition('bundle', $bundle_old) + ->execute(); + + // Clear the cache. + field_cache_clear(); + + foreach (module_implements('field_attach_rename_bundle') as $module) { + $function = $module . '_field_attach_rename_bundle'; + $function($bundle_old, $bundle_new); + } +} + +/** + * Notify field.module the a bundle was deleted. + * + * This deletes the data for the field instances as well as the field instances + * themselves. This function actually just marks the data and field instances + * and deleted, leaving the garbage collection for a separate process, because + * it is not always possible to delete this much data in a single page request + * (particularly since for some field types, the deletion is more than just a + * simple DELETE query). + * + * @param $bundle + * The bundle to delete. + */ +function _field_attach_delete_bundle($bundle) { + // Let other modules act on deleting the bundle + foreach (module_implements('field_attach_delete_bundle') as $module) { + $function = $module . '_field_attach_delete_bundle'; + $function($bundle); + } + + // Delete the instances themseves + $instances = field_info_instances($bundle); + foreach ($instances as $instance) { + field_delete_instance($instance['field_name'], $bundle); + } +} + +/** + * Helper function to extract id, vid, and bundle name from an object. + * + * @param $obj_type + * The type of $object; e.g. 'node' or 'user'. + * @param $object + * The object from which to extract values. + * @return + * A numerically indexed array (not a hash table) containing these + * elements: + * + * 0: primary id of the object + * 1: revision id of the object, or NULL if $obj_type is not versioned + * 2: bundle name of the object + * 3: whether $obj_type's fields should be cached (TRUE/FALSE) + */ +function _field_attach_extract_ids($object_type, $object) { + // TODO D7 : prevent against broken 3rd party $node without 'type'. + $info = field_info_fieldable_types($object_type); + // Objects being created might not have id/vid yet. + $id = isset($object->{$info['id key']}) ? $object->{$info['id key']} : NULL; + $vid = ($info['revision key'] && isset($object->{$info['revision key']})) ? $object->{$info['revision key']} : NULL; + // If no bundle key provided, then we assume a single bundle, named after the + // type of the object. + $bundle = $info['bundle key'] ? $object->{$info['bundle key']} : $object_type; + $cacheable = isset($info['cacheable']) ? $info['cacheable'] : FALSE; + return array($id, $vid, $bundle, $cacheable); +} + +/** + * @autoload} End of "@autoload field_attach" + */ -- cgit v1.2.3