Mercurial > hg > rr-repo
diff modules/field/field.install @ 0:ff03f76ab3fe
initial version
author | danieleb <danielebarchiesi@me.com> |
---|---|
date | Wed, 21 Aug 2013 18:51:11 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/field/field.install Wed Aug 21 18:51:11 2013 +0100 @@ -0,0 +1,471 @@ +<?php + +/** + * @file + * Install, update and uninstall functions for the field module. + */ + +/** + * Implements hook_schema(). + */ +function field_schema() { + // Static (meta) tables. + $schema['field_config'] = array( + 'fields' => array( + 'id' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'The primary identifier for a field', + ), + 'field_name' => array( + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'description' => 'The name of this field. Non-deleted field names are unique, but multiple deleted fields can have the same name.', + ), + 'type' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'description' => 'The type of this field.', + ), + 'module' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The module that implements the field type.', + ), + 'active' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Boolean indicating whether the module that implements the field type is enabled.', + ), + 'storage_type' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'description' => 'The storage backend for the field.', + ), + 'storage_module' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The module that implements the storage backend.', + ), + 'storage_active' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Boolean indicating whether the module that implements the storage backend is enabled.', + ), + 'locked' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => '@TODO', + ), + 'data' => array( + 'type' => 'blob', + 'size' => 'big', + 'not null' => TRUE, + 'serialize' => TRUE, + 'description' => 'Serialized data containing the field properties that do not warrant a dedicated column.', + ), + 'cardinality' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + ), + 'translatable' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + ), + 'deleted' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('id'), + 'indexes' => array( + 'field_name' => array('field_name'), + // Used by field_sync_field_status(). + 'active' => array('active'), + 'storage_active' => array('storage_active'), + 'deleted' => array('deleted'), + // Used by field_modules_disabled(). + 'module' => array('module'), + 'storage_module' => array('storage_module'), + 'type' => array('type'), + 'storage_type' => array('storage_type'), + ), + ); + $schema['field_config_instance'] = array( + 'fields' => array( + 'id' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'The primary identifier for a field instance', + ), + 'field_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'description' => 'The identifier of the field attached by this instance', + ), + 'field_name' => array( + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '' + ), + 'entity_type' => array( + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '' + ), + 'bundle' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '' + ), + 'data' => array( + 'type' => 'blob', + 'size' => 'big', + 'not null' => TRUE, + 'serialize' => TRUE, + ), + 'deleted' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('id'), + 'indexes' => array( + // Used by field_delete_instance(). + 'field_name_bundle' => array('field_name', 'entity_type', 'bundle'), + // Used by field_read_instances(). + 'deleted' => array('deleted'), + ), + ); + $schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache'); + + return $schema; +} + +/** + * Utility function: create a field by writing directly to the database. + * + * This function can be used for databases whose schema is at field module + * version 7000 or higher. + * + * @ingroup update_api + */ +function _update_7000_field_create_field(&$field) { + // Merge in default values.` + $field += array( + 'entity_types' => array(), + 'cardinality' => 1, + 'translatable' => FALSE, + 'locked' => FALSE, + 'settings' => array(), + 'indexes' => array(), + 'deleted' => 0, + 'active' => 1, + ); + + // Set storage. + $field['storage'] = array( + 'type' => 'field_sql_storage', + 'settings' => array(), + 'module' => 'field_sql_storage', + 'active' => 1, + ); + + // Fetch the field schema to initialize columns and indexes. The field module + // is not guaranteed to be loaded at this point. + module_load_install($field['module']); + $schema = (array) module_invoke($field['module'], 'field_schema', $field); + $schema += array('columns' => array(), 'indexes' => array()); + // 'columns' are hardcoded in the field type. + $field['columns'] = $schema['columns']; + // 'indexes' can be both hardcoded in the field type, and specified in the + // incoming $field definition. + $field['indexes'] += $schema['indexes']; + + // The serialized 'data' column contains everything from $field that does not + // have its own column and is not automatically populated when the field is + // read. + $data = $field; + unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']); + // Additionally, do not save the 'bundles' property populated by + // field_info_field(). + unset($data['bundles']); + + // Write the field to the database. + $record = array( + 'field_name' => $field['field_name'], + 'type' => $field['type'], + 'module' => $field['module'], + 'active' => (int) $field['active'], + 'storage_type' => $field['storage']['type'], + 'storage_module' => $field['storage']['module'], + 'storage_active' => (int) $field['storage']['active'], + 'locked' => (int) $field['locked'], + 'data' => serialize($data), + 'cardinality' => $field['cardinality'], + 'translatable' => (int) $field['translatable'], + 'deleted' => (int) $field['deleted'], + ); + // We don't use drupal_write_record() here because it depends on the schema. + $field['id'] = db_insert('field_config') + ->fields($record) + ->execute(); + + // Create storage for the field. + field_sql_storage_field_storage_create_field($field); +} + +/** + * Utility function: delete a field stored in SQL storage directly from the database. + * + * To protect user data, this function can only be used to delete fields once + * all information it stored is gone. Delete all data from the + * field_data_$field_name table before calling by either manually issuing + * delete queries against it or using _update_7000_field_delete_instance(). + * + * This function can be used for databases whose schema is at field module + * version 7000 or higher. + * + * @param $field_name + * The field name to delete. + * + * @ingroup update_api + */ +function _update_7000_field_delete_field($field_name) { + $table_name = 'field_data_' . $field_name; + if (db_select($table_name)->range(0, 1)->countQuery()->execute()->fetchField()) { + $t = get_t(); + throw new Exception($t('This function can only be used to delete fields without data')); + } + // Delete all instances. + db_delete('field_config_instance') + ->condition('field_name', $field_name) + ->execute(); + + // Nuke field data and revision tables. + db_drop_table($table_name); + db_drop_table('field_revision_' . $field_name); + + // Delete the field. + db_delete('field_config') + ->condition('field_name', $field_name) + ->execute(); +} + + +/** + * Utility function: delete an instance and all its data of a field stored in SQL Storage. + * + * BEWARE: this function deletes user data from the field storage tables. + * + * This function is valid for a database schema version 7000. + * + * @ingroup update_api + */ +function _update_7000_field_delete_instance($field_name, $entity_type, $bundle) { + // Delete field instance configuration data. + db_delete('field_config_instance') + ->condition('field_name', $field_name) + ->condition('entity_type', $entity_type) + ->condition('bundle', $bundle) + ->execute(); + + // Nuke data. + db_delete('field_data_' . $field_name) + ->condition('entity_type', $entity_type) + ->condition('bundle', $bundle) + ->execute(); + db_delete('field_revision_' . $field_name) + ->condition('entity_type', $entity_type) + ->condition('bundle', $bundle) + ->execute(); +} + +/** + * Utility function: fetch all the field definitions from the database. + * + * Warning: unlike the field_read_fields() API function, this function returns + * all fields by default, including deleted and inactive fields, unless + * specified otherwise in the $conditions parameter. + * + * @param $conditions + * An array of conditions to limit the select query to. + * @param $key + * The name of the field property the return array is indexed by. Using + * anything else than 'id' might cause incomplete results if the $conditions + * do not filter out deleted fields. + * + * @return + * An array of fields matching $conditions, keyed by the property specified + * by the $key parameter. + * + * @ingroup update_api + */ +function _update_7000_field_read_fields(array $conditions = array(), $key = 'id') { + $fields = array(); + $query = db_select('field_config', 'fc', array('fetch' => PDO::FETCH_ASSOC)) + ->fields('fc'); + foreach ($conditions as $column => $value) { + $query->condition($column, $value); + } + foreach ($query->execute() as $record) { + $field = unserialize($record['data']); + $field['id'] = $record['id']; + $field['field_name'] = $record['field_name']; + $field['type'] = $record['type']; + $field['module'] = $record['module']; + $field['active'] = $record['active']; + $field['storage']['type'] = $record['storage_type']; + $field['storage']['module'] = $record['storage_module']; + $field['storage']['active'] = $record['storage_active']; + $field['locked'] = $record['locked']; + $field['cardinality'] = $record['cardinality']; + $field['translatable'] = $record['translatable']; + $field['deleted'] = $record['deleted']; + + $fields[$field[$key]] = $field; + } + return $fields; +} + +/** + * Utility function: write a field instance directly to the database. + * + * This function can be used for databases whose schema is at field module + * version 7000 or higher. + * + * @ingroup update_api + */ +function _update_7000_field_create_instance($field, &$instance) { + // Merge in defaults. + $instance += array( + 'field_id' => $field['id'], + 'field_name' => $field['field_name'], + 'deleted' => 0, + ); + + // The serialized 'data' column contains everything from $instance that does + // not have its own column and is not automatically populated when the + // instance is read. + $data = $instance; + unset($data['id'], $data['field_id'], $data['field_name'], $data['entity_type'], $data['bundle'], $data['deleted']); + + $record = array( + 'field_id' => $instance['field_id'], + 'field_name' => $instance['field_name'], + 'entity_type' => $instance['entity_type'], + 'bundle' => $instance['bundle'], + 'data' => serialize($data), + 'deleted' => (int) $instance['deleted'], + ); + $instance['id'] = db_insert('field_config_instance') + ->fields($record) + ->execute(); +} + +/** + * @addtogroup updates-6.x-to-7.x + * @{ + */ + +/** + * Field update version placeholder. + */ +function field_update_7000() { + // Some update helper functions (such as _update_7000_field_create_field()) + // modify the database directly. They can be used safely only if the database + // schema matches the field module schema established for Drupal 7.0 (i.e. + // version 7000). This function exists solely to set the schema version to + // 7000, so that update functions calling those helpers can do so safely + // by declaring a dependency on field_update_7000(). +} + +/** + * Fix fields definitions created during the d6 to d7 upgrade path. + */ +function field_update_7001() { + $fields = _update_7000_field_read_fields(); + foreach ($fields as $field) { + // _update_7000_field_create_field() was broken in d7 RC2, and the fields + // created during a d6 to d7 upgrade do not correcly store the 'index' + // entry. See http://drupal.org/node/996160. + + module_load_install($field['module']); + $schema = (array) module_invoke($field['module'], 'field_schema', $field); + $schema += array('indexes' => array()); + // 'indexes' can be both hardcoded in the field type, and specified in the + // incoming $field definition. + $field['indexes'] += $schema['indexes']; + + // Place the updated entries in the existing serialized 'data' column. + $data = db_query("SELECT data FROM {field_config} WHERE id = :id", array(':id' => $field['id']))->fetchField(); + $data = unserialize($data); + $data['columns'] = $field['columns']; + $data['indexes'] = $field['indexes']; + + // Save the new data. + $query = db_update('field_config') + ->condition('id', $field['id']) + ->fields(array('data' => serialize($data))) + ->execute(); + } +} + +/** + * @} End of "addtogroup updates-6.x-to-7.x". + */ + +/** + * @addtogroup updates-7.x-extra + * @{ + */ + +/** + * Split the all-inclusive field_bundle_settings variable per bundle. + */ +function field_update_7002() { + $settings = variable_get('field_bundle_settings', array()); + if ($settings) { + foreach ($settings as $entity_type => $entity_type_settings) { + foreach ($entity_type_settings as $bundle => $bundle_settings) { + variable_set('field_bundle_settings_' . $entity_type . '__' . $bundle, $bundle_settings); + } + } + variable_del('field_bundle_settings'); + } +} + +/** + * Add the FieldInfo class to the class registry. + */ +function field_update_7003() { + // Empty update to force a rebuild of the registry. +} + +/** + * @} End of "addtogroup updates-7.x-extra". + */