diff --git a/core/includes/update.inc b/core/includes/update.inc index 9dd8456..63b6e68 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -1097,15 +1097,112 @@ function update_variables_to_config($config_name, array $variable_map) { } /** - * @defgroup update-api-7.x-to-8.x Update versions of API functions + * @defgroup update_api Update versions of API functions * @{ - * Functions similar to normal API function but not firing hooks. + * Functions that are similar to normal API functions, but do not invoke hooks. * - * During update, it is impossible to judge the consequences of firing a hook - * as it might hit a module not yet updated. So simplified versions of some - * core APIs are provided. + * These simplified versions of core API functions are provided for use by + * update functions (hook_update_N() implementations). + * + * During database updates the schema of any module could be out of date. For + * this reason, caution is needed when using any API function within an update + * function - particularly CRUD functions, functions that depend on the schema + * (for example by using drupal_write_record()), and any functions that invoke + * hooks. + * + * Instead, a simplified utility function should be used. If a utility version + * of the API function you require does not already exist, then you should + * create a new function. The new utility function should be named + * _update_N_mymodule_my_function(). N is the schema version the function acts + * on (the schema version is the number N from the hook_update_N() + * implementation where this schema was introduced, or a number following the + * same numbering scheme), and mymodule_my_function is the name of the original + * API function including the module's name. + * + * Examples: + * - _update_7000_mymodule_save(): This function performs a save operation + * without invoking any hooks using the 7.x schema. + * - _update_8000_mymodule_save(): This function performs the same save + * operation using the 8.x schema. + * + * The utility function should not invoke any hooks, and should perform database + * operations using functions from the @link database Database abstraction + * layer, @endlink like db_insert(), db_update(), db_delete(), db_query(), and + * so on. + * + * If a change to the schema necessitates a change to the utility function, a + * new function should be created with a name based on the version of the schema + * it acts on. See _update_8000_bar_get_types() and _update_8001_bar_get_types() + * in the code examples that follow. + * + * For example, foo.install could contain: + * @code + * function foo_update_dependencies() { + * // foo_update_8010() needs to run after bar_update_8000(). + * $dependencies['foo'][8010] = array( + * 'bar' => 8000, + * ); + * + * // foo_update_8036() needs to run after bar_update_8001(). + * $dependencies['foo'][8036] = array( + * 'bar' => 8001, + * ); + * + * return $dependencies; + * } + * + * function foo_update_8000() { + * // No updates have been run on the {bar_types} table yet, so this needs + * // to work with the 7.x schema. + * foreach (_update_7000_bar_get_types() as $type) { + * // Rename a variable. + * } + * } + * + * function foo_update_8010() { + * // Since foo_update_8010() is going to run after bar_update_8000(), it + * // needs to operate on the new schema, not the old one. + * foreach (_update_8000_bar_get_types() as $type) { + * // Rename a different variable. + * } + * } + * + * function foo_update_8036() { + * // This update will run after bar_update_8001(). + * foreach (_update_8001_bar_get_types() as $type) { + * } + * } + * @endcode + * + * And bar.install could contain: + * @code + * function bar_update_8000() { + * // Type and bundle are confusing, so we renamed the table. + * db_rename_table('bar_types', 'bar_bundles'); + * } + * + * function bar_update_8001() { + * // Database table names should be singular when possible. + * db_rename_table('bar_bundles', 'bar_bundle'); + * } + * + * function _update_7000_bar_get_types() { + * db_query('SELECT * FROM {bar_types}')->fetchAll(); + * } + * + * function _update_8000_bar_get_types() { + * db_query('SELECT * FROM {bar_bundles'})->fetchAll(); + * } + * + * function _update_8001_bar_get_types() { + * db_query('SELECT * FROM {bar_bundle}')->fetchAll(); + * } + * @endcode + * + * @see hook_update_N() + * @see hook_update_dependencies() */ /** - * @} End of "defgroup update-api-7.x-to-8.x". + * @} End of "defgroup update_api". */ diff --git a/core/modules/field/field.install b/core/modules/field/field.install index 9ef54d0..c30e28f 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -169,7 +169,7 @@ function field_schema() { /** * Utility function: create a field by writing directly to the database. * - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_7000_field_create_field(&$field) { // Merge in default values.` @@ -247,7 +247,7 @@ function _update_7000_field_create_field(&$field) { * @param $field_name * The field name to delete. * - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_7000_field_delete_field($field_name) { $table_name = 'field_data_' . $field_name; @@ -276,7 +276,7 @@ function _update_7000_field_delete_field($field_name) { * * BEWARE: this function deletes user data from the field storage tables. * - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_7000_field_delete_instance($field_name, $entity_type, $bundle) { // Delete field instance configuration data. @@ -314,7 +314,7 @@ function _update_7000_field_delete_instance($field_name, $entity_type, $bundle) * @return * An array of fields matching $conditions, keyed by the property specified * by the $key parameter. - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_7000_field_read_fields(array $conditions = array(), $key = 'id') { $fields = array(); @@ -346,7 +346,7 @@ function _update_7000_field_read_fields(array $conditions = array(), $key = 'id' /** * Utility function: write a field instance directly to the database. * - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_7000_field_create_instance($field, &$instance) { // Merge in defaults. diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.install b/core/modules/field/modules/field_sql_storage/field_sql_storage.install index 2229ef4..016d003 100644 --- a/core/modules/field/modules/field_sql_storage/field_sql_storage.install +++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.install @@ -27,7 +27,7 @@ function field_sql_storage_schema() { /** * Utility function: write field data directly to SQL storage. * - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_8000_field_sql_storage_write($entity_type, $bundle, $entity_id, $revision_id, $field_name, $data) { $table_name = "field_data_{$field_name}"; diff --git a/core/modules/node/node.install b/core/modules/node/node.install index 5727129..47b4345 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -490,7 +490,7 @@ function node_uninstall() { /** * Fetches node types directly from the database. * - * @ingroup update-api-7.x-to-8.x + * @ingroup update_api */ function _update_7000_node_get_types() { $node_types = db_query('SELECT * FROM {node_type}')->fetchAllAssoc('type', PDO::FETCH_OBJ); diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index efdadb4..1be35e9 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -2722,6 +2722,14 @@ function hook_install() { * In order to call a function from your mymodule.module or an include file, * you need to explicitly load that file first. * + * During database updates the schema of any module could be out of date. For + * this reason, caution is needed when using any API function within an update + * function - particularly CRUD functions, functions that depend on the schema + * (for example by using drupal_write_record()), and any functions that invoke + * hooks. + * + * See @link update_api Update versions of API functions @endlink for details. + * * If your update task is potentially time-consuming, you'll need to implement a * multipass update to avoid PHP timeouts. Multipass updates use the $sandbox * parameter provided by the batch API (normally, $context['sandbox']) to store @@ -2747,6 +2755,7 @@ function hook_install() { * * @see batch * @see schemaapi + * @see update_api * @see hook_update_last_removed() * @see update_get_update_list() */