<?php
/**
 * @file
 * Installation of the example module
 */

/**
 * Implements hook_disable().
 *
 * Perform actions when the module is disabled by the site administrator
 *
 * @ingroup tripal_example
 */
function tripal_example_disable() {

  // EXPLANATION: If you are using Drupal Views you want to ensure that any
  // default views that your module provides are disabled when the module is
  // disabled. Default views are specified in the
  // [module name].views.default.inc file. The following code will disable these
  // views. If your module does not create any default views you can remove the
  // following code.

  // Disable all default views provided by this module
  require_once("tripal_example.views_default.inc");
  $views = tripal_example_views_default_views();
  foreach (array_keys($views) as $view_name) {
    tripal_disable_view($view_name,FALSE,array('suppress_error' => TRUE));
  }

}

/**
 * Implements hook_requirements().
 *
 * Performs check to see if all required dependencies are met. Drupal will
 * automatically check for module dependencies but here you can check for other
 * requirements.
 *
 * @ingroup tripal_example
 */
function tripal_example_requirements($phase) {


  $requirements = array();
  if ($phase == 'install') {
    // EXPLANATION: It is essential that Chado be installed for almost all
    // Tripal modules. Therefore, the following code checks to ensure Chado is
    // installed and available. If your module does not require that Chado be
    // installed, you can remove the following check.

    // make sure chado is installed
    if (!$GLOBALS["chado_is_installed"]) {
      $requirements ['tripal_example'] = array(
          'title' => "tripal_example",
          'value' => "ERROR: Chado must be installed before this module can be enabled",
          'severity' => REQUIREMENT_ERROR,
      );
    }
  }
  return $requirements;
}

/**
 * Implements hook_install().
 *
 * Performs actions when the modules is first installed.
 *
 * @ingroup tripal_example
 */
function tripal_example_install() {

  // EXPLANATION: Here is a good place to add any materialized views, controlled
  // vocabularies CV, databases or CV terms needed by your module.
  // To keep this module code short, create functions to do each of those tasks

  // add any materialized view
  tripal_example_add_mviews();

  // add any external databases used by the example module.
  tripal_example_add_dbs();

  // add any controlled vocabularies used by the example module. You may need
  // to add a vocabulary if you to set it as default (see next lines of code).
  // For example, the Sequence Ontology (SO) is used by the feature module as
  // the default vocabulary for the feature type_id field. But, that vocabulary
  // does not yet exist in Chado until after the SO is loaded using the Tripal
  // OBO loader. But, we can add it here as a place-holder so that we can then
  // set it as a default vocabulary (see below).
  tripal_example_add_cvs();


  // add any controlled vocabulary terms
  tripal_example_add_cvterms();

  // EXPLANATION: Many tables in Chado have a 'type_id' column which allows for
  // association of controlled vocabularies to describe the record. Chado places
  // no restrictions on which vocabularies can be used, but Tripal can be
  // instructed to provide a default vocabulary for any given field. For
  // example, the feature.type_id column will typically use the Sequence
  // Ontology. In that case, we can use the tripal_set_default_cv() function to
  // specify the Sequence Ontology (sequence) as the default vocabulary.
  tripal_set_default_cv('example', 'type_id', 'example_type');
  tripal_set_default_cv('exampleprop', 'type_id', 'example_property');
  tripal_set_default_cv('example_relationship', 'type_id', 'example_relationship');

  // add any custom tables. For this case we will add an 'example' table to the
  // chado schema
  tripal_example_add_custom_tables();
}


/**
 * Implements hook_uninstall().
 *
 * Performs actions when the modules is uninstalled.
 *
 * @ingroup tripal_example
 */
function tripal_example_uninstall() {

}

/**
 * Implementation of hook_schema().
 *
 * Provides a list of tables to be created inside of the Drupal schema (the
 * 'public' schema by default). It uses the Drupal Schema API array structure to
 * define the table, its indexes and constraints.
 *
 * Schema API documentation is here:
 * https://api.drupal.org/api/drupal/includes%21database%21schema.inc/group/schemaapi/7
 *
 * @ingroup tripal_example
 */
function tripal_example_schema() {

  // EXPLANATION: If your module creates a node type for data in the Chado
  // database then you probably need to link Drupal nodes with a respective ID
  // in the Chado table. The following is an example array for a table that will
  // link the 'chado_example' node type (created by this example module) with a
  // record in the fake Chado example table. This table will link the 'nid' of
  // the node with the 'example_id' of the example record.
  $schema['chado_example'] = array(
    'fields' => array(
      'vid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0
       ),
      'nid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0
       ),
      'example_id' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0
      ),
      'sync_date' => array(
        'type' => 'int',
        'not null' => FALSE,
        'description' => 'UNIX integer sync date/time'
      ),
    ),
    'indexes' => array(
      'chado_example_idx1' => array('example_id')
    ),
    'unique keys' => array(
      'chado_example_uq1' => array('nid', 'vid'),
      'chado_example_uq2' => array('vid')
    ),
    'primary key' => array('nid'),
  );

  return $schema;
};

/**
 * Creates a materialized view that stores the type & number of examples per
 * organism.
 *
 * @ingroup tripal_example
 */
function tripal_example_add_mviews() {

  // EXPLANATION: use the tripal_add_mview() function to add a materialized view
  // needed by your module. If you have more than one materialized view it is
  // best to create a single function for each one and call each function here.
  // Otherwise this function can become quite long.

}
/**
 * Add cvs related to publications
 *
 * @ingroup tripal_example
 */
function tripal_example_add_dbs() {
  // EXPLANATION: use the tripal_insert_db() function to add any external
  // databases needed by your module. If the database already exists then the
  // function will gracefully return.

  tripal_insert_db(array(
    'name' => 'example_db',
    'description' => 'An example database.'
  ));
}
/**
 * Add cvs related to publications
 *
 * @ingroup tripal_example
 */
function tripal_example_add_cvs() {

  // EXPLANATION: use the tripal_insert_cv() function to add any controlled
  // vocabularies needed by your module. If the vocabulary already exists then
  // the function will gracefully return. Chado conventions use a singular name
  // for CV names (not plural).

  tripal_insert_cv(
    'example_property',
    'Contains property terms for examples.'
  );

  tripal_insert_cv(
    'example_type',
    'Contains terms describing types of examples.'
  );

  tripal_insert_cv(
   'example_relationship',
   'Contains terms for describing relationship types between examples.'
  );

}

/**
 * Adds controlled vocabulary terms needed by this module.
 *
 * @ingroup tripal_example
 */
function tripal_example_add_cvterms() {

  // EXPLANATION: for our test module to work we need to add some terms to our
  // example_type controlled vocabulary. Ideally we should have a full OBO file
  // for loading but sometimes we just have a small list that won't really
  // change so we can add those terms here.
  tripal_insert_cvterm(array(
    'id'         => 'test',         // the term accession
    'name'       => 'Test type',    // the human readable term name
    'cv_name'    => 'example_type', // the CV name this term belongs to.
    'definition' => 'A test type for the example module.',
    'db_name'    => 'example_db',   // the database in which the term is found.
  ));
}

/**
 * Add custom tables to Chado that are required by this module
 *
 * @ingroup tripal_example
 */
function tripal_example_add_custom_tables() {

  // EXPLANATION: for this example module we will create a set of example tables
  // that mimic Chado tables. These tables are:
  //
  //   1) example     (for storing the primary example records)
  //   2) exampleprop (for sorting properties about the example)
  //   3) example_relationship (for storing relationships about examples)
  //   4) example_dbxref (for storing cross-references about an example)
  //
  // To make the code easier to read, each table is created by a separate
  // function called here:

  tripal_example_add_example_table();
  tripal_example_add_exampleprop_table();
  tripal_example_add_example_relationship_table();
  tripal_example_add_example_dbxref_table();
}

/**
 * Adds the 'example' custom table to Chado.
 *
 * @ingroup tripal_example
 */
function tripal_example_add_example_table() {
  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
  // add the table using the chado_create_custom_table() function.
  $schema = array(
    'table' => 'example',
    'fields' => array(
      'example_id' => array(
        'type' => 'serial',
        'not null' => true,
      ),
      'uniquename' => array(
        'type' => 'varchar',
        'length' => '255',
        'not null' => TRUE,
      ),
      'type_id' => array(
        'type' => 'int',
        'not null' => true,
      ),
      'organism_id' => array(
        'type' => 'int',
        'not null' => true,
      ),
      'description' => array(
        'type' => 'text',
      ),
    ),
    'primary key' => array(
      0 => 'example_id',
    ),
    'unique keys' => array(
      'example_uq1' => array(
        0 => 'uniquename',
        1 => 'type_id',
        2 => 'organism_id',
      ),
    ),
    'indexes' => array(
      'example_idx1' => array(
        0 => 'example_id',
      ),
      'example_idx2' => array(
        0 => 'uniquename',
      ),
    ),
    'foreign keys' => array(
      'cvterm' => array(
        'table' => 'cvterm',
        'columns' => array(
          'type_id' => 'cvterm_id',
        ),
      ),
      'organism' => array(
        'table' => 'organism',
        'columns' => array(
          'organism_id' => 'organism_id',
        ),
      ),
    ),
    // EXPLANATION: the 'referring_tables' array is the list of tables that have
    // a foreign key relationships with this table. This information is required
    // for the Tripal API to be able to expand tables in templates.
    'referring_tables' => array(
      0 => 'example_relationship',
      1 => 'exampleprop',
      2 => 'example_dbxref',
    ),
  );
  chado_create_custom_table('example', $schema, TRUE);
}
/**
 * Adds the 'example_relationship' custom table to Chado.
 *
 * @ingroup tripal_example
 */
function tripal_example_add_exampleprop_table() {
  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
  // add the table using the chado_create_custom_table() function.

  // Add the exampleprop table
  $schema =  array(
    'table' => 'exampleprop',
    'fields' => array(
      'exampleprop_id' => array(
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'example_id' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
      'type_id' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
      'value' => array(
        'type' => 'text',
        'not null' => FALSE,
      ),
      'rank' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
    ),
    'primary key' => array(
      0 => 'exampleprop_id',
    ),
    'unique keys' => array(
      'example_id_type_id_rank' => array(
        0 => 'example_id',
        1 => 'type_id',
        2 => 'rank',
      ),
    ),
    'foreign keys' => array(
      'cvterm' => array(
        'table' => 'cvterm',
        'columns' => array(
          'type_id' => 'cvterm_id',
        ),
      ),
      'example' => array(
        'table' => 'example',
        'columns' => array(
          'example_id' => 'example_id',
        ),
      ),
    ),
  );
  chado_create_custom_table('exampleprop', $schema, TRUE);
}

/**
 * Adds the 'example_relationship' custom table to Chado.
 *
 * @ingroup tripal_example
 */
function tripal_example_add_example_relationship_table() {
  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
  // add the table using the chado_create_custom_table() function.

  $schema =  array(
    'table' => 'example_relationship',
    'fields' => array(
      'example_relationship_id' => array(
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'subject_id' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
      'object_id' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
      'type_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 => 'example_relationship_id',
    ),
    'unique keys' => array(
      'example_relationship_c1' => array(
        0 => 'subject_id',
        1 => 'object_id',
        2 => 'type_id',
        3 => 'rank',
      ),
    ),
    'indexes' => array(
      'example_relationship_idx1' => array(
        0 => 'subject_id',
      ),
      'example_relationship_idx2' => array(
        0 => 'object_id',
      ),
      'example_relationship_idx3' => array(
        0 => 'type_id',
      ),
    ),
    'foreign keys' => array(
      'cvterm' => array(
        'table' => 'cvterm',
        'columns' => array(
          'type_id' => 'cvterm_id',
        ),
      ),
      'example' => array(
        'table' => 'example',
        'columns' => array(
          'subject_id' => 'example_id',
          'object_id' => 'example_id',
        ),
      ),
    ),
  );
  chado_create_custom_table('example_relationship', $schema, TRUE);
}

/**
 * Adds the 'example_dbxref' custom table to Chado.
 *
 * @ingroup tripal_example
 */
function tripal_example_add_example_dbxref_table() {

  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
  // add the table using the chado_create_custom_table() function.

  $schema =  array(
    'table' => 'example_dbxref',
    'fields' => array(
      'example_dbxref_id' => array(
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'example_id' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
      'dbxref_id' => array(
        'type' => 'int',
        'not null' => TRUE,
      ),
      'is_current' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 1,
      ),
    ),
    'primary key' => array(
      0 => 'example_dbxref_id',
    ),
    'unique keys' => array(
      'example_dbxref_unq1' => array(
        0 => 'example_id',
        1 => 'dbxref_id',
      ),
    ),
    'indexes' => array(
      'example_dbxref_idx1' => array(
        0 => 'example_id',
      ),
      'example_dbxref_idx2' => array(
        0 => 'dbxref_id',
      ),
    ),
    'foreign keys' => array(
      'dbxref' => array(
        'table' => 'dbxref',
        'columns' => array(
          'dbxref_id' => 'dbxref_id',
        ),
      ),
      'example' => array(
        'table' => 'example',
        'columns' => array(
          'example_id' => 'example_id',
        ),
      ),
    ),
  );
  chado_create_custom_table('example_dbxref', $schema, TRUE);
}
/**
 * This is the required update for tripal_example.
 */
function tripal_example_update_7200() {
  // EXPLANATION: as you create new releases of your module you may find that
  // tables your module created, or data may need to be adjusted. This function
  // allows you to do that. This function is executed using the
  // http://[your site]/update.php  URL or using the drush command 'updatedb'.
  // This function should be named according to the instructions provided here:
  // https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_update_N/7
  //
  // It is best not to use Tripal API calls inside of this function because an
  // upgrade from Drupal 6 to Drupal 7 requires that all modules be disabled
  // which means the Tripal API is not available. This is an unfortunate
  // requirement, but will prevent errors during a major upgrade.

  // it is good to wrap any database changes inside of a try catch block:
  try {
   // perform database changes
  }
  catch (\PDOException $e) {
    $error = $e->getMessage();
    throw new DrupalUpdateException('Could not apply updates: '. $error);
  }
}

/**
 * Implementation of hook_update_dependencies(). It specifies a list of other
 * modules whose updates must be run prior to this one.
 */
function tripal_example_update_dependencies() {
  $dependencies = array();

  // EXPLANATION: here we can specify which modules must be updated prior to
  // applying the updates in this module. This is useful because it prevents
  // updates from being executed out of order. The following example code shows
  // that the 'tripal_example' module update number 7200 must be executed after
  // the 'tripal_cv' module's 7200 update.
  $dependencies['tripal_example'][7200] = array(
    'tripal_cv' => 7200
  );

  return $dependencies;
}
