You are here

content.install in Content Construction Kit (CCK) 6

Same filename and directory in other branches
  1. 5 content.install
  2. 6.3 content.install
  3. 6.2 content.install

File

content.install
View source
<?php

// Updates happen in random order, whether or not the module is enabled,
// so include critical code here just to be sure.
// We also avoid calling drupal_get_path, for it causes problems when
// installation happen in an install profile.
include_once dirname(__FILE__) . '/content.module';

/**
 * 'Safe' version of content_types() to use in updates and installs.
 *
 * Can't safely use content_fields() or content_types() in an update to get
 * a fields array, especially without knowing what field modules are enabled,
 * or the current state of the database and cache, so create a fields array
 * from database info that is limited to fields from modules that are
 * currently enabled.
 */
function content_types_install() {
  $module_field_types = $module_widgets = array();
  foreach (module_list() as $module) {
    if ($field_type = module_invoke($module, 'field_info')) {
      $module_field_types[$module] = $field_type;
    }
    if ($widget_type = module_invoke($module, 'widget_info')) {
      $module_widgets[$module] = $widget_type;
    }
  }
  $fields = array();
  $db_result = db_query("SELECT * FROM {" . content_instance_tablename() . "} nfi " . " LEFT JOIN {" . content_field_tablename() . "} nf ON nf.field_name = nfi.field_name");
  while ($field = db_fetch_array($db_result)) {

    // There may be module data available for currently disabled modules,
    // or missing module data for currently enabled modules, so start over
    // to get only field info for enabled modules.
    unset($field['module']);
    unset($field['widget_module']);

    // 'columns' is a reserved word in MySQL4, so our column is named 'db_columns'.
    $field['columns'] = $field['db_columns'];
    unset($field['db_columns']);
    foreach ($module_field_types as $module => $types) {
      foreach ($types as $type_name => $type) {
        if ($field['type'] == $type_name) {
          $field['module'] = $module;
        }
      }
    }
    foreach ($module_widgets as $module => $types) {
      foreach ($types as $type_name => $type) {
        if ($field['widget_type'] == $type_name) {
          $field['widget_module'] = $module;
        }
      }
    }
    if (!empty($field['module']) && !empty($field['widget_module'])) {
      $field['widget_settings'] = unserialize($field['widget_settings']);
      $field['display_settings'] = unserialize($field['display_settings']);
      $field['columns'] = module_invoke($field['module'], 'field_settings', 'database columns', $field);
      $fields[$field['type_name']][$field['field_name']] = $field;
    }
  }
  return $fields;
}

/**
 * Implementation of hook_install().
 */
function content_install() {
  variable_set('content_schema_version', 6002);
  drupal_install_schema('content');
}

/**
 * Implementation of hook_uninstall().
 */
function content_uninstall() {
  variable_del('content_schema_version');
  drupal_uninstall_schema('content');
}

/**
 * Implementation of hook_enable().
 */
function content_enable() {

  // Make sure old data is emptied out of the caches, since it
  // may no longer be valid since the module was last enabled,
  // especially if not all the same field modules are enabled
  // as before. Especially needed during updates.
  cache_clear_all('*', 'cache_content', TRUE);
  content_clear_type_cache(TRUE);
}

/**
 * Implementation of hook_disable().
 */
function content_disable() {

  // Make sure old data is emptied out of the caches, since it
  // may no longer be valid when the module is re-enabled.
  cache_clear_all('*', 'cache_content', TRUE);
  content_clear_type_cache(TRUE);
}

/**
 * Implementation of hook_schema.
 */
function content_schema() {

  // Static (meta) tables.
  $schema['content_node_field'] = array(
    'fields' => array(
      'field_name' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'type' => array(
        'type' => 'varchar',
        'length' => 127,
        'not null' => TRUE,
        'default' => '',
      ),
      'global_settings' => array(
        'type' => 'text',
        'size' => 'medium',
        'not null' => TRUE,
        'serialize' => TRUE,
      ),
      'required' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ),
      'multiple' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ),
      'db_storage' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 1,
      ),
      'module' => array(
        'type' => 'varchar',
        'length' => 127,
        'not null' => TRUE,
        'default' => '',
      ),
      'db_columns' => array(
        'type' => 'text',
        'size' => 'medium',
        'not null' => TRUE,
        'serialize' => TRUE,
      ),
      'active' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'primary key' => array(
      'field_name',
    ),
  );
  $schema['content_node_field_instance'] = array(
    'fields' => array(
      'field_name' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'type_name' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'weight' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'label' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'widget_type' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'widget_settings' => array(
        'type' => 'text',
        'size' => 'medium',
        'not null' => TRUE,
        'serialize' => TRUE,
      ),
      'display_settings' => array(
        'type' => 'text',
        'size' => 'medium',
        'not null' => TRUE,
        'serialize' => TRUE,
      ),
      'description' => array(
        'type' => 'text',
        'size' => 'medium',
        'not null' => TRUE,
      ),
      'widget_module' => array(
        'type' => 'varchar',
        'length' => 127,
        'not null' => TRUE,
        'default' => '',
      ),
      'widget_active' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'primary key' => array(
      'field_name',
      'type_name',
    ),
  );
  $schema['cache_content'] = drupal_get_schema_unprocessed('system', 'cache');

  // When the module is first installed, the remaining code in the schema
  // will create errors, since these tables have not yet been created.
  // We don't need to create data tables on initial installation anyway
  // since no fields have been created yet, so just return with this much
  // of the schema.
  if (!db_table_exists('content_node_field') || !db_table_exists('content_node_field_instance')) {
    return $schema;
  }

  // Dynamic (data) tables.
  // We can't use many helper functions here, like content_fields() or
  // content_types() or we risk creating a fatal loop from circular
  // logic when they call other functions that use this schema, so create
  // the schema directly from a fresh query of the database.
  // content_table_schema() and content_database_info() have no
  // circular logic and are safe to use here.
  $db_result = db_query("SELECT * FROM {" . content_instance_tablename() . "} nfi " . " LEFT JOIN {" . content_field_tablename() . "} nf ON nf.field_name = nfi.field_name WHERE nf.active = 1 AND nfi.widget_active = 1");
  while ($field = db_fetch_array($db_result)) {

    // 'columns' is a reserved word in MySQL4, so our db column is named 'db_columns'.
    $field['columns'] = unserialize($field['db_columns']);
    unset($field['db_columns']);
    $content_table = _content_tablename($field['type_name'], CONTENT_DB_STORAGE_PER_CONTENT_TYPE);
    $field_table = _content_tablename($field['field_name'], CONTENT_DB_STORAGE_PER_FIELD);

    // We always add a 'per content type' table for each content type that
    // has fields.
    if (!isset($schema[$content_table])) {
      $schema[$content_table] = content_table_schema();
    }
    $base_schema = content_table_schema($field);
    if ($field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) {

      // Per-field storage : add the 'per field' table if needed.
      if (!isset($schema[$field_table])) {
        $schema[$field_table] = $base_schema;
      }
    }
    else {

      // Per-type storage : merge the information for the field
      // in the existing table.
      $schema[$content_table]['fields'] = array_merge($schema[$content_table]['fields'], $base_schema['fields']);
      $schema[$content_table]['content fields'] = array_merge($schema[$content_table]['content fields'], $base_schema['content fields']);
    }
  }
  return $schema;
}
function content_update_last_removed() {
  return 1008;
}

/**
 * Add module name to fields table to make it easier to identify the fields to delete when a module
 * is uninstalled.
 *
 * Needed because the value drops out of content_info() when module is disabled, so there
 * is no other way to find the associated fields.
 */
function content_update_6000() {
  $ret = array();
  if (db_column_exists(content_field_tablename(), 'active')) {
    return $ret;
  }
  db_add_field($ret, content_field_tablename(), 'module', array(
    'type' => 'varchar',
    'length' => 127,
    'not null' => TRUE,
    'default' => '',
  ));
  db_add_field($ret, content_field_tablename(), 'db_columns', array(
    'type' => 'text',
    'not null' => TRUE,
    'default' => '',
  ));
  db_add_field($ret, content_field_tablename(), 'active', array(
    'type' => 'int',
    'size' => 'tiny',
    'not null' => TRUE,
    'default' => 0,
  ));
  db_add_field($ret, content_instance_tablename(), 'widget_module', array(
    'type' => 'varchar',
    'length' => 127,
    'not null' => TRUE,
    'default' => '',
  ));
  db_add_field($ret, content_instance_tablename(), 'widget_active', array(
    'type' => 'int',
    'size' => 'tiny',
    'not null' => TRUE,
    'default' => 0,
  ));

  // This will update the table for any modules enabled at this time.
  foreach (module_list() as $module) {
    content_associate_fields($module);
  }

  // Fix the cache_content schema
  if (db_table_exists('cache_content')) {
    db_drop_table($ret, 'cache_content');
  }
  db_create_table($ret, 'cache_content', drupal_get_schema_unprocessed('system', 'cache'));
  variable_set('content_schema_version', 6000);

  // The cache table had to be used to store data until this update ran,
  // so clear cache out now that we're switching back to the cache_content table.
  $ret[] = update_sql('DELETE FROM {cache}');
  return $ret;
}

/**
 * Rename node_field and node_field_instance tables.
 *
 * This is a carryover from when the data tables were renamed,
 * postponed so we wouldn't create any more havoc than necessary
 * until a major version change.
 *
 * Using 'content_node_field' instead of 'content_field'
 * to avoid conflicts with field tables that will be prefixed
 * with 'content_field'.
 */
function content_update_6001() {
  $ret = array();
  if (db_table_exists('content_node_field')) {
    return $ret;
  }
  db_rename_table($ret, 'node_field', 'content_node_field');
  db_rename_table($ret, 'node_field_instance', 'content_node_field_instance');
  variable_set('content_schema_version', 6001);
  content_clear_type_cache(TRUE);
  return $ret;
}

/**
 * Get rid of automatic per content tables for content types that have no fields.
 * Switching to adding those tables only when needed.
 */
function content_update_6002() {
  $ret = array();
  $db_types = content_types_install();
  $field_types = array();
  $result = db_query("SELECT DISTINCT type_name FROM {" . content_instance_tablename() . "}");
  while ($type = db_fetch_array($result)) {
    $field_types[] = $type['type_name'];
  }
  foreach ($db_types as $content_type => $content_info) {
    if (!in_array($content_type, $field_types)) {
      $table = _content_tablename($content_type, CONTENT_DB_STORAGE_PER_CONTENT_TYPE);
      if (db_table_exists($table)) {
        db_drop_table($ret, $table);
      }
    }
  }
  variable_set('content_schema_version', 6002);
  content_clear_type_cache(TRUE);
  return $ret;
}

/**
 * 'db_columns' column 1st got introduced as 'columns', which is forbidden in MySQL 4.
 * This update function will only be useful for early testers...
 */
function content_update_6003() {
  $ret = array();
  if (db_column_exists('content_node_field', 'columns')) {
    db_change_field($ret, 'content_node_field', 'columns', 'db_columns', array(
      'type' => 'text',
      'size' => 'medium',
      'not null' => TRUE,
    ));
  }
  return $ret;
}

Functions

Namesort descending Description
content_disable Implementation of hook_disable().
content_enable Implementation of hook_enable().
content_install Implementation of hook_install().
content_schema Implementation of hook_schema.
content_types_install 'Safe' version of content_types() to use in updates and installs.
content_uninstall Implementation of hook_uninstall().
content_update_6000 Add module name to fields table to make it easier to identify the fields to delete when a module is uninstalled.
content_update_6001 Rename node_field and node_field_instance tables.
content_update_6002 Get rid of automatic per content tables for content types that have no fields. Switching to adding those tables only when needed.
content_update_6003 'db_columns' column 1st got introduced as 'columns', which is forbidden in MySQL 4. This update function will only be useful for early testers...
content_update_last_removed