<?php
/**
 * @file
 * Contains functions used to install/uninstall tripal.
 */

/**
 * Implementation of hook_install().
 *
 * @ingroup tripal
 */
function tripal_install() {
  // On upgrade from Tv2 to Tv3 we need to add a new field to the tripal_jobs
  // table it's missing.
  if (!db_field_exists('tripal_jobs', 'includes')) {
    db_add_field('tripal_jobs', 'includes', array(
      'type' => 'text',
      'description' => 'A serialized array of file paths that should be included prior to executing the job.',
      'not null' => FALSE,
    ));
  }

  $menu = array(
    'menu_name' => 'data_search',
    'title' => t('Data Search'),
    'description' => 'The Data Search menu contains links to search tools for finding biological data.',
  );
  menu_save($menu);
}

/**
 * Adds variables for bundles.
 */
function tripal_add_variables() {
  // Add tripal bundle variables needed for storing additional settings for
  // Tripal Bundles.
  tripal_insert_variable(
      'title_format',
      'A pattern including tokens that can be used to generate tripal entity titles.'
  );
  tripal_insert_variable(
      'url_format',
      'A pattern including tokens that can be used to generate tripal entity url aliases.'
  );
  tripal_insert_variable(
      'description',
      'The description of a Tripal Entity type/bundle.'
  );
  tripal_insert_variable(
    'hide_empty_field',
    'Structure->Tripal Content Type->edit checkbox to hide empty fields for that bundle.'
  );
  tripal_insert_variable(
    'ajax_field',
    'Structure->Tripal Content Type->edit checkbox for ajax fields for that bundle.'
  );
}

/**
 *
 */
function tripal_uninstall() {
  /*
   // So somehow I was able to uninstall this module without deleting the bundles. This
   // caused aweful errors because fields weren't deleted so when I re-installed, the code
   // tried to create fields that were inactive (despite checking if the field exists
   // before creating). The following code was meant to ensure that all content was deleted
   // before uninstall so these errors would not occur. Unfortunatly I am now unable to
   // test this because the Field API module is disabling uninstall of Tripal Chado until
   // all the content is deleted. Thus ensuring the errors described above don't occur.
   // But I'm Sure I was able to uninstall with content before...
   // **I am slowly going crazy; Crazy going slowly am I**
   // Anyway, I'll leaving the solution code here in case I am able to repeat it in
   // the future.
   // @see https://www.drupal.org/node/1262092
   // @see https://www.drupal.org/node/1861710

   // First delete all TripalEntities.
   $entity_ids = (new EntityFieldQuery)->entityCondition("entity_type", "TripalEntity")->execute();
   $entity_ids = reset($entity_ids);
   entity_delete_multiple("TripalEntity", array_keys($entity_ids));

   // Then delete all TripalBundles.
   $bundle_ids = (new EntityFieldQuery)->entityCondition("entity_type", "TripalBundle")->execute();
   $bundle_ids = reset($bundle_ids);
   entity_delete_multiple("TripalBundle", array_keys($bundle_ids));

   // @TODO: Should we delete all TripalVocabularies and TripalTerms?

   // Finally purge all fields that are no longer used.
   field_purge_batch(100);
   */
}

/**
 *
 */
function tripal_enable() {
  // If Tripal v2 is already installed, the installation of this module
  // will try and recreate some of the tables created with tripal_core and the
  // installation will fail.  Therefore, in the install we renamed it. Now
  // we want to move it back.
  if (db_table_exists('tripal_jobs2')) {
    $sql = "DROP TABLE tripal_jobs";
    db_query($sql);
    db_rename_table('tripal_jobs2', 'tripal_jobs');
  }

  if (db_table_exists('tripal_token_formats2')) {
    $sql = "DROP TABLE tripal_token_formats";
    db_query($sql);
    db_rename_table('tripal_token_formats2', 'tripal_token_formats');
  }

  if (db_table_exists('tripal_variables2')) {
    $sql = "DROP TABLE tripal_variables";
    db_query($sql);
    db_rename_table('tripal_variables2', 'tripal_variables');
  }

  if (db_table_exists('tripal_custom_quota2')) {
    $sql = "DROP TABLE tripal_custom_quota";
    db_query($sql);
    db_rename_table('tripal_custom_quota2', 'tripal_custom_quota');
  }

  if (db_table_exists('tripal_expiration_files2')) {
    $sql = "DROP TABLE tripal_expiration_files";
    db_query($sql);
    db_rename_table('tripal_expiration_files2', 'tripal_expiration_files');
  }

  // schema change
  if (!db_field_exists('tripal_jobs', 'includes')) {
    $sql = "ALTER TABLE tripal_jobs ADD COLUMN includes text";
    db_query($sql);
  }

  tripal_add_variables();
}

/**
 * Implementation of hook_schema().
 *
 * @ingroup tripal
 */
function tripal_schema() {

  // If Tripal v2 is already installed, the installation of this module
  // will try and recreate some of the tables created with tripal_core and the
  // installation will fail.  Therefore, we need to temporarily move those
  // tables out of the way, let the module install and then move them back.
  $migrated = variable_get ('tripal_v2_upgrade_v3_check', FALSE);
  if (!$migrated) {
    if (db_table_exists('tripal_jobs')) {
      db_rename_table('tripal_jobs', 'tripal_jobs2');
    }

    if (db_table_exists('tripal_token_formats')) {
      db_rename_table('tripal_token_formats', 'tripal_token_formats2');
    }

    if (db_table_exists('tripal_variables')) {
      db_rename_table('tripal_variables', 'tripal_variables2');
    }

    if (db_table_exists('tripal_custom_quota')) {
      db_rename_table('tripal_custom_quota', 'tripal_custom_quota2');
    }
    if (db_table_exists('tripal_expiration_files')) {
      db_rename_table('tripal_expiration_files', 'tripal_expiration_files2');
    }

    variable_set ('tripal_v2_upgrade_v3_check', TRUE);
  }
  $schema = array();

  $schema['tripal_jobs'] = tripal_tripal_jobs_schema();
  $schema['tripal_token_formats'] = tripal_tripal_token_formats_schema();
  $schema['tripal_variables'] = tripal_tripal_variables_schema();
  $schema['tripal_expiration_files'] = tripal_tripal_expiration_files_schema();
  $schema['tripal_custom_quota'] = tripal_tripal_custom_quota_schema();
  
  // Adds a table for managing TripalEntity entities.
  $schema['tripal_vocab'] = tripal_tripal_vocab_schema();
  $schema['tripal_term'] = tripal_tripal_term_schema();
  $schema['tripal_entity'] = tripal_tripal_entity_schema();
  $schema['tripal_bundle'] = tripal_tripal_bundle_schema();
  $schema['tripal_import'] = tripal_tripal_import_schema();
  $schema['tripal_collection'] = tripal_tripal_collection_schema();
  $schema['tripal_collection_bundle'] = tripal_tripal_collection_bundle_schema();

  // Adds a table for additional information related to bundles.
  $schema['tripal_bundle_variables'] = tripal_tripal_bundle_variables_schema();
  // Adds a table for administrative notifications on the dashboard.
  $schema['tripal_admin_notfications'] = tripal_tripal_admin_notifications_schema();
  return $schema;
}
/**
 * Returns the Drupal Schema API array for the tripal_jobs table.
 */
function tripal_tripal_jobs_schema() {
  return array(
    'fields' => array(
      'job_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE
      ),
      'uid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'The Drupal userid of the submitee'
      ),
      'job_name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'modulename' => array(
        'type' => 'varchar',
        'length' => 50,
        'not null' => TRUE,
        'description' => 'The module name that provides the callback for this job'
      ),
      'callback' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'arguments' => array(
        'type' => 'text',
        'size' => 'normal',
        'not null' => FALSE
      ),
      'progress' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'default' => 0,
        'not null' => FALSE,
        'description' => 'a value from 0 to 100 indicating percent complete'
      ),
      'status' => array(
        'type' => 'varchar',
        'length' => 50,
        'not null' => TRUE
      ),
      'submit_date' => array(
        'type' => 'int',
        'not null' => TRUE,
        'description' => 'UNIX integer submit time'
      ),
      'start_time' => array(
        'type' => 'int',
        'not null' => FALSE,
        'description' => 'UNIX integer start time'
      ),
      'end_time' => array(
        'type' => 'int',
        'not null' => FALSE,
        'description' => 'UNIX integer end time'
      ),
      'error_msg' => array(
        'type' => 'text',
        'size' => 'normal',
        'not null' => FALSE
      ),
      'pid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
        'description' => 'The process id for the job'
      ),
      'priority' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The job priority'
      ),
      'mlock' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
        'description' => 'If set to 1 then all jobs for the module are held until this one finishes'
      ),
      'lock' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
        'description' => 'If set to 1 then all jobs are held until this one finishes'
      ),
      'includes' => array(
        'type' => 'text',
        'description' => 'A serialized array of file paths that should be included prior to executing the job.',
        'not null' => FALSE,
      )
    ),
    'indexes' => array(
      'job_id' => array('job_id'),
      'job_name' => array('job_name')
    ),
    'primary key' => array('job_id'),
  );
}
/**
 * Returns the Drupal Schema API array for the tripal_jobs table.
 */
function tripal_tripal_collection_schema() {
  return array(
    'fields' => array(
      'collection_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE
      ),
      'collection_name' => array(
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE
      ),
      'description' => array(
        'type' => 'text',
        'not null' => FALSE
      ),
      'uid' => array(
        'type' => 'int',
        'not null' => TRUE,
        'description' => 'The user Id of the person who created the collection.'
      ),
      'create_date' => array(
        'type' => 'int',
        'not null' => TRUE,
        'description' => 'UNIX integer start time'
      ),
    ),
    'indexes' => array(
      'uid' => array('uid')
    ),
    'unique keys' => array(
      'user_collection' => array('uid', 'collection_name'),
    ),
    'primary key' => array('collection_id'),
  );
}

/**
 * Returns the Drupal Schema API array for the tripal_jobs table.
 */
function tripal_tripal_collection_bundle_schema() {
  return array(
    'fields' => array(
      'collection_bundle_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE
      ),
      'collection_id' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE
      ),
     'bundle_name' => array(
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE
      ),
      'ids' => array(
        'type' => 'text',
        'size' => 'normal',
        'not null' => TRUE,
        'description' => 'An array of entity IDs.'
      ),
      'fields' => array(
        'type' => 'text',
        'size' => 'normal',
        'not null' => TRUE,
        'description' => 'An array of numeric field IDs.'
      ),
      'site_id' => array(
        'type' => 'int',
        'size' => 'normal',
        'not null' => FALSE,
        'description' => 'The ID of the site from the Tripal Sites table.'
      ),
    ),
    'indexes' => array(
      'collection_id' => array('collection_id')
    ),
    'primary key' => array('collection_bundle_id'),
  );
}

/**
 * Returns the Drupal Schema API array for the tripal_jobs table.
 */
function tripal_tripal_import_schema() {
  return array(
    'fields' => array(
      'import_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE
      ),
      'uid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'The Drupal userid of the submitee.'
      ),
      'class' => array(
        'type' => 'varchar',
        'length' => 256,
        'not null' => TRUE,
      ),
      'fid' => array(
        'type' => 'text',
        'not null' => FALSE,
        'description' => 'The file IDs of the to import. This only applies if the file was uploaded (i.e. not already on the server) and is mangaged by Drupal. Multiple fids are separated using a | character.'
      ),
      'arguments' => array(
        'type' => 'text',
        'size' => 'normal',
        'not null' => FALSE,
        'description' => 'Holds a serialized PHP array containing the key/value paris that are used for arguments of the job.'
      ),
      'submit_date' => array(
        'type' => 'int',
        'not null' => TRUE,
        'description' => 'UNIX integer submit time'
      ),
    ),
    'indexes' => array(
      'class' => array('class'),
    ),
    'foreign keys' => array(
      'tripal_jobs' => array(
        'table' => 'tripal_jobs',
        'columns' => array(
          'job_id' => 'job_id',
        ),
      ),
      'users' => array(
        'table' => 'users',
        'columns' => array(
          'uid' => 'uid',
        ),
      ),
      'file_managed' => array(
        'table' => 'file_managed',
        'columns' => array(
          'fid' => 'fid',
        ),
      ),
    ),
    'primary key' => array('import_id'),
  );
}
/**
 *
 * @return
 */
function tripal_tripal_token_formats_schema() {
  return array(
    'fields' => array(
      'tripal_format_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE
      ),
      'content_type' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'application' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'format' => array(
        'type' => 'text',
        'not null' => TRUE
      ),
      'tokens' => array(
        'type' => 'text',
        'not null' => TRUE
      ),
    ),
    'unique keys' => array(
      'type_application' => array('content_type', 'application'),
    ),
    'primary key' => array('tripal_format_id'),
  );
}
function tripal_tripal_variables_schema() {

   return array(
    'description' => 'This table houses a list of unique variable names that ' .
      'can be used in the tripal_node_variables table.',
    'fields' => array(
      'variable_id' => array (
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'description' => array(
        'type' => 'text',
        'not null' => TRUE,
      ),
    ),
    'primary key' => array (
        0 => 'variable_id',
    ),
    'unique keys' => array (
      'tripal_variables_c1' => array (
        0 => 'name',
      ),
    ),
    'indexes' => array (
      'tripal_variable_names_idx1' => array (
        0 => 'variable_id',
      ),
    ),
  );

  return $schema;
}
/**
 * @section
 * Schema Definitions.
 */


/**
 * The base table for Biological Data Entities.
 *
 * This contains the actual data. For example, if you have a 5 genes and 10 mRNA then
 * this table will have 15 records and include both genes and mRNA's.
 */
function tripal_tripal_entity_schema() {

  $schema = array(
    'description' => 'The base table for Tripal Vocabulary-based entities.',
    'fields' => array(
      'id' => array(
        'description' => 'The primary identifier for a vocabulary entity.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'type' => array(
        'description' => 'The type of entity. This should be an official vocabulary ID (e.g. SO, RO, GO).',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'bundle' => array(
        'description' => 'The type of bundle. This should be an official vocabulary ID (e.g. SO, RO, GO) followed by an underscore and the term accession.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'term_id' => array(
        'description' => 'The term_id for the type of entity. This term_id corresponds to a TripalTerm record.',
        'type' => 'int',
        'not null' => TRUE,
      ),
      'title' => array(
        'description' => 'The title of this node, always treated as non-markup plain text.',
        'type' => 'text',
        'not null' => TRUE,
        'default' => '',
      ),
      'uid' => array(
        'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'status' => array(
        'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 1,
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the node was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the node was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'term_id' => array('term_id'),
      'entity_changed' => array('changed'),
      'entity_created' => array('created'),
      'type' => array('type'),
      'uid' => array('uid'),
      'bundle' => array('bundle'),
    ),
    'unique keys' => array(),
    'primary key' => array('id'),
  );
  return $schema;
}

/**
 * The base table for TripalVocab schema.
 *
 * This contains the actual data. For example, if you have a 5 genes and 10 mRNA then
 * this table will have 15 records and include both genes and mRNA's.
 */
function tripal_tripal_vocab_schema() {

  // This schema only provides enough information to assign a unique ID
  // to the vocabulary. Any additonal information is added to the Entity object
  // by the selected database back-end.
  $schema = array(
    'description' => 'The base table for TripalVocab entities.',
    'fields' => array(
      'id' => array(
        'description' => 'The primary identifier for a vocab entity.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'vocabulary' => array(
        'description' => 'The short name for the vocabulary (e.g. SO, PATO, etc.).',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the entity was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the entity was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'vocabulary' => array('vocabulary'),
      'entity_changed' => array('changed'),
      'entity_created' => array('created'),
    ),
    'unique keys' => array('vocabulary' => array('vocabulary')),
    'primary key' => array('id'),
  );
  return $schema;
}

/**
 * The base table for TripalTerm entities.
 *
 * This contains the actual data. For example, if you have a 5 genes and 10 mRNA then
 * this table will have 15 records and include both genes and mRNA's.
 */
function tripal_tripal_term_schema() {

  // This schema only provides enough information to assign a unique ID
  // to the term and associate it to it's vocabulary. Any additonal information
  // is added to the Entity object by the selected database back-end.
  $schema = array(
    'description' => 'The base table for TripalTerm entities.',
    'fields' => array(
      'id' => array(
        'description' => 'The primary identifier for a term entity.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'vocab_id' => array(
        'description' => 'The vocabulary_id of the TripalVocab entity to which this term belongs.',
        'type' => 'int',
        'not null' => TRUE,
      ),
      'accession' => array(
        'description' => 'The id (or accession) of this term in the vocabulary.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'name' => array(
        'description' => 'The human readable name for this term.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the entity was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the entity was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'vocab_id' => array('vocab_id'),
      'accession' => array('accession'),
      'entity_changed' => array('changed'),
      'entity_created' => array('created'),
    ),
    'foreign keys' => array(
      'tripal_vocab' => array(
        'table' => 'tripal_vocab',
        'columns' => array(
          'vocab_id' => 'vocab_id',
        ),
      ),
    ),
    'unique keys' => array('vocab_term' => array('vocab_id', 'accession')),
    'primary key' => array('id'),
  );
  return $schema;
}

/**
 * The base table for TripalEntity entities.
 *
 * This table contains a list of Biological Data Types.
 * For the example above (5 genes and 10 mRNAs), there would only be two records in
 * this table one for "gene" and another for "mRNA".
 */
function tripal_tripal_bundle_schema() {

  $schema = array(
    'description' => 'Stores information about defined tripal data types.',
    'fields' => array(
      'id' => array(
        'type' => 'serial',
        'not null' => TRUE,
        'description' => 'Primary Key: Unique numeric ID.',
      ),
      'type' => array(
        'description' => 'The type of entity (e.g. TripalEntity).',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'term_id' => array(
        'description' => 'The term_id for the type of entity. This term_id corresponds to a TripalTerm record.',
        'type' => 'int',
        'not null' => TRUE,
      ),
      'name' => array(
        'description' => 'The name of the bundle. This should be an official vocabulary ID (e.g. SO, RO, GO) followed by an underscore and the term accession.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'label' => array(
        'description' => 'The human-readable name of this bundle.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
    ),
    'indexes' => array(
      'name' => array('name'),
      'term_id' => array('term_id'),
      'label' => array('label'),
    ),
    'primary key' => array('id'),
    'unique keys' => array(
      'name' => array('name'),
    ),
  );
  return $schema;
}


/**
 * Additional Tripal Bundle Information.
 *
 * This table is used for storing any additonal information describing
 * a tripal bundle. For example, this is a good place to store title/url formats.
 */
function tripal_tripal_bundle_variables_schema() {

  $schema = array(
    'description' => 'This table is used for storing any additonal information describing
      a tripal bundle. For example, this is a good place to store title/url formats.',
    'fields' => array (
      'bundle_variable_id' => array (
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'bundle_id' => array (
        'type' => 'int',
        'not null' => TRUE,
      ),
      'variable_id' => array (
        'type' => 'int',
        'not null' => TRUE,
      ),
      'value' => array (
        'type' => 'text',
        'not null' => FALSE,
      ),
      'rank' => array (
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'primary key' => array (
      0 => 'bundle_variable_id',
    ),
    'unique keys' => array (
      'tripal_bundle_variables_c1' => array (
        0 => 'bundle_id',
        1 => 'variable_id',
        2 => 'rank',
      ),
    ),
    'indexes' => array (
      'tripal_bundle_variables_idx1' => array (
        0 => 'variable_id',
      ),
    ),
    'foreign keys' => array (
      'tripal_variables' => array (
        'table' => 'tripal_variables',
        'columns' => array (
          'variable_id' => 'variable_id',
        ),
      ),
    ),
  );

  return $schema;
}

/**
 * Provides the schema for the tripal_custom_quota table.
 */
function tripal_tripal_custom_quota_schema() {
  $schema = array(
    'table' => 'tripal_custom_quota',
    'fields' => array(
      'uid' => array(
        'type' => 'int',
        'size' => 'big',
        'not NULL' => TRUE,
      ),
      'custom_quota' => array(
        'type' => 'int',
        'size' => 'big',
        'not NULL' => TRUE,
      ),
      'custom_expiration' => array(
        'type' => 'int',
        'size' => 'big',
        'not NULL' => TRUE,
      ),
    ),
    'primary key' => array('uid'),
    'unique keys' => array(
      'tripal_custom_quota_uq1' => array('uid'),
    ),
    'indexes' => array(
      'tripal_custom_quota_idx1' => array('uid'),
    ),
  );
  return $schema;
}

/**
 * Provides the schema for the tripal_expiration_files table.
 */
function tripal_tripal_expiration_files_schema() {
  $schema = array (
    'table' => 'tripal_expiration_files',
    'fields' => array (
      'fid' => array(
        'type' => 'int',
        'not NULL' => TRUE
      ),
      'expiration_date' => array(
        'type' => 'int',
        'size' => 'big',
        'not NULL' => TRUE
      ),
    ),
    'primary key' => array(
      0 => 'fid'
    ),
    'unique keys' => array(
      'tripal_expiration_files_uq1' => array('fid'),
    ),
    'indexes' => array(
      'tripal_expiration_files_idx1' => array('fid'),
    ),
  );
  return $schema;
}


/**
 * Additional Tripal Admin Notification Information.
 *
 * This table is used for information describing administrative
 * notifications. For example, when new fields are available.
 */
function tripal_tripal_admin_notifications_schema() {

  $schema = array(
    'description' => 'This table is used for information describing administrative
     notifications. For example, when new fields are available.',
    'fields' => array (
      'note_id' => array (
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'details' => array (
        'description' => 'Description and additional information relating to the notification.',
        'type' => 'text',
        'not null' => TRUE,
      ),
      'title' => array (
        'description' => 'Title of the notification.',
        'type' => 'text',
        'not null' => TRUE,
      ),
      'actions' => array (
        'description' => 'Actions that can be performed on the notification, like disimissal or import.',
        'type' => 'text',
        'not null' => FALSE,
      ),
      'submitter_id' => array (
        'description' => 'A unique id that should be specific to the notification to ensure notifications are not duplicated.',
        'type' => 'text',
        'not null' => TRUE,
      ),
      'enabled' => array (
        'description' => 'Boolean indicating whether the notification is enabled or disabled (disabled will not be shown on the dashboard).',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 1,
      ),
      'type' => array (
        'description' => 'Type of the notification, relating to what tripal function the notification belongs to, IE Fields, Jobs, Vocabulary.',
        'type' => 'text',
        'not null' => FALSE,
      ),
    ),
    'primary key' => array (
      0 => 'note_id',
    ),
  );

  return $schema;
}

/**
 * Change tripal_vocab.vocabulary to varchar(128)
 */
function tripal_update_7300() {
  try {
    $spec = array(
      'description' => 'The short name for the vocabulary (e.g. SO, PATO, etc.).',
      'type' => 'varchar',
      'length' => 128,
      'not null' => TRUE
    );
    db_change_field('tripal_vocab', 'vocabulary', 'vocabulary',$spec);
  }
  catch (\PDOException $e) {
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: '. $error);
  }
}

/**
 * Create new admin notifications table.
 */
function tripal_update_7301() {
  $transaction = db_transaction();
  try {
    $schema['tripal_admin_notfications'] = tripal_tripal_admin_notifications_schema();
    db_create_table('tripal_admin_notfications', $schema['tripal_admin_notfications']);
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: '. $error);
  }
}

/**
 * Create new tripal import table.
 */
function tripal_update_7302() {
  $transaction = db_transaction();
  try {
    $schema['tripal_import'] = tripal_tripal_import_schema();
    db_create_table('tripal_import', $schema['tripal_import']);
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: '. $error);
  }
}

/**
 * Remove the job_id from the tripal import table.
 */
function tripal_update_7303() {
  $transaction = db_transaction();
  try {
    if (db_field_exists('tripal_import', 'job_id')) {
      db_drop_field('tripal_import', 'job_id');
    }
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: '. $error);
  }
}

/**
 * Adds a variable for the bundles to manage hiding of empty fields.
 */
function tripal_update_7304() {
  $transaction = db_transaction();
  try {
    tripal_insert_variable(
      'hide_empty_field',
      'Structure->Tripal Content Type->edit checkbox to hide empty fields for that bundle.'
    );
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: ' . $error);
  }
}

/**
 * Adjusts the tripal_import table to support multiple file uploads.
 */
function tripal_update_7305() {
  $transaction = db_transaction();
  try {
    db_change_field('tripal_import', 'fid', 'fid', array(
      'type' => 'text',
      'not null' => FALSE,
      'description' => 'The file IDs of the to import. This only applies if the file was uploaded (i.e. not already on the server) and is mangaged by Drupal. Multiple fids are separated using a | character.'
    ));
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: ' . $error);
  }
}

/**
 * Adds the tripal_collection table.
 */
function tripal_update_7306() {
  $transaction = db_transaction();
  try {
    $schema = array();
    $schema['tripal_collection'] = tripal_tripal_collection_schema();
    db_create_table('tripal_collection', $schema['tripal_collection']);
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not add the tripal_collection table:' . $error);
  }
}
/**
 * Adds a new Data search menu for the Tripal created search tools.  If you
 * have customized any of the Tripal content search forms then those forms will
 * remain unchanged. All other default search pages will be moved to the
 * new Data Search menu item available at Admin > Stucture > Menu > Data Search.
 */
function tripal_update_7307() {
  $menu = array(
    'menu_name' => 'data_search',
    'title' => t('Data Search'),
    'description' => 'The Data Search menu contains links to search tools for finding biological data.',
  );
  menu_save($menu);
}

/**
 * Remove the bundle_name, ids, fields from the tripal collections table.
 * And add the new tripal_tripal_collection_bundle_schema
 */
function tripal_update_7308() {
  $transaction = db_transaction();
  try {
    if (db_field_exists('tripal_collection', 'bundle_name')) {
      db_drop_field('tripal_collection', 'bundle_name');
    }
    if (db_field_exists('tripal_collection', 'ids')) {
      db_drop_field('tripal_collection', 'ids');
    }
    if (db_field_exists('tripal_collection', 'fields')) {
      db_drop_field('tripal_collection', 'fields');
    }
     $schema = array();
    $schema['tripal_collection_bundle'] = tripal_tripal_collection_bundle_schema();
    db_create_table('tripal_collection_bundle', $schema['tripal_collection_bundle']);
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not add the tripal_collection table:' . $error);
  }
}

/**
 * Add the site_id field to the tripal_collection_bundle table.
 */
function tripal_update_7309() {
  $transaction = db_transaction();
  try {
    if (!db_field_exists('tripal_collection_bundle', 'site_id')) {
       $field = array(
        'type' => 'int',
        'size' => 'normal',
        'not null' => FALSE,
        'description' => 'The ID of the site from the Tripal Sites table.',
      );
      db_add_field('tripal_collection_bundle', 'site_id', $field);
    }
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not add the tripal_collection table:' . $error);
  }
}

/**
 * Adds the missing tripal_collection_bundle table
 * @throws DrupalUpdateException
 */
function tripal_update_7310() {
  $transaction = db_transaction();
  try {
    if (!db_table_exists('tripal_collection_bundle')) {
      $schema = array();
      $schema['tripal_collection_bundle'] = tripal_tripal_collection_bundle_schema();
      db_create_table('tripal_collection_bundle', $schema['tripal_collection_bundle']);
    }
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not add the tripal_collection_bundle table:' . $error);
  }
}

/**
 * Adds support for file quotas.
 */
function tripal_update_7311() {
  try {
    $schema = array();
    $schema['tripal_custom_quota'] = tripal_tripal_custom_quota_schema();
    $schema['tripal_expiration_files'] = tripal_tripal_expiration_files_schema();
    db_create_table('tripal_custom_quota', $schema['tripal_custom_quota']);
    db_create_table('tripal_expiration_files', $schema['tripal_expiration_files']);
  }
  catch (\PDOException $e) {
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: '. $error);
  }
}

/**
 * Adds a tripal_storage_api setting to all field storage details
 */
function tripal_update_7312() {
  $transaction = db_transaction();
  try {
    $fields = db_select('field_config', 'fc')
      ->fields('fc', ['id', 'storage_type', 'data'])
      ->where("fc.storage_type = 'field_chado_storage' or fc.storage_type = 'tripal_no_storage'")
      ->execute();
    while ($field = $fields->fetchObject()) {
      $data = unserialize($field->data); 
      $data['storage']['settings']['tripal_storage_api'] = TRUE;
      db_update('field_config')
        ->fields([
          'data' => serialize($data)
        ])
        ->condition('id', $field->id)
        ->execute();
    }
  }
  catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: '. $error);
  }
}


/**
 * Adds a tripal_storage_api setting to all field storage details
 */
function tripal_update_7313() {
  $transaction = db_transaction();
  try {
    tripal_insert_variable(
      'ajax_field',
      'Structure->Tripal Content Type->edit checkbox ajax fields for that bundle.'
    );
  } catch (\PDOException $e) {
    $transaction->rollback();
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not perform update: ' . $error);
  }
}

