Sfoglia il codice sorgente

Fixed merge conflict

Stephen Ficklin 4 anni fa
parent
commit
2d3d660bfd
77 ha cambiato i file con 942 aggiunte e 376 eliminazioni
  1. 136 0
      .github/workflows/phpunit-tests.yml
  2. 0 86
      .travis.yml
  3. 1 1
      README.md
  4. 1 1
      composer.json
  5. 1 0
      docs/dev_guide.rst
  6. BIN
      docs/dev_guide/CI.create-badge.png
  7. 165 0
      docs/dev_guide/CI.rst
  8. 1 1
      docs/dev_guide/custom_field/custom_widget.rst
  9. 4 4
      docs/dev_guide/custom_field/manual_field_creation.rst
  10. 2 2
      docs/dev_guide/custom_field/select_vocab_terms.rst
  11. 1 1
      docs/dev_guide/custom_web_services.rst
  12. 1 1
      docs/dev_guide/exporting_field_settings.rst
  13. 1 1
      docs/extensions/data_input.rst
  14. 0 8
      docs/extensions/in_development.rst
  15. 1 1
      docs/extensions/module_rating.rst
  16. 1 1
      docs/extensions/search.rst
  17. 16 0
      docs/extensions/visualization.rst
  18. 1 1
      docs/user_guide/install_tripal/custom_theme.rst
  19. 1 1
      docs/user_guide/install_tripal/upgrade_from_tripal2.rst
  20. 1 1
      legacy/tripal_analysis/tripal_analysis.info
  21. 1 1
      legacy/tripal_contact/tripal_contact.info
  22. 2 2
      legacy/tripal_core/api/tripal_core.chado_nodes.properties.api.inc
  23. 2 2
      legacy/tripal_core/api/tripal_core.chado_nodes.relationships.api.inc
  24. 1 1
      legacy/tripal_core/tripal_core.info
  25. 1 1
      legacy/tripal_cv/tripal_cv.info
  26. 1 1
      legacy/tripal_db/tripal_db.info
  27. 1 1
      legacy/tripal_feature/tripal_feature.info
  28. 1 1
      legacy/tripal_featuremap/tripal_featuremap.info
  29. 1 1
      legacy/tripal_genetic/tripal_genetic.info
  30. 1 1
      legacy/tripal_library/tripal_library.info
  31. 1 1
      legacy/tripal_natural_diversity/tripal_natural_diversity.info
  32. 1 1
      legacy/tripal_organism/tripal_organism.info
  33. 1 1
      legacy/tripal_phenotype/tripal_phenotype.info
  34. 2 2
      legacy/tripal_phylogeny/tripal_phylogeny.drush.inc
  35. 1 1
      legacy/tripal_phylogeny/tripal_phylogeny.info
  36. 1 1
      legacy/tripal_project/tripal_project.info
  37. 1 1
      legacy/tripal_pub/tripal_pub.info
  38. 1 1
      legacy/tripal_stock/tripal_stock.info
  39. 1 1
      legacy/tripal_views/tripal_views.info
  40. 2 2
      tripal/api/tripal.collections.api.inc
  41. 1 1
      tripal/api/tripal.d3js.api.inc
  42. 25 19
      tripal/api/tripal.entities.api.inc
  43. 43 3
      tripal/api/tripal.fields.api.inc
  44. 1 1
      tripal/api/tripal.files.api.inc
  45. 1 1
      tripal/api/tripal.importer.api.inc
  46. 8 8
      tripal/api/tripal.jobs.api.inc
  47. 2 2
      tripal/api/tripal.notice.api.inc
  48. 3 3
      tripal/api/tripal.terms.api.inc
  49. 4 4
      tripal/api/tripal.upload.api.inc
  50. 2 2
      tripal/api/tripal.variables.api.inc
  51. 10 3
      tripal/includes/tripal.admin_blocks.inc
  52. 24 0
      tripal/tripal.drush.inc
  53. 1 1
      tripal/tripal.info
  54. 13 2
      tripal/tripal.module
  55. 1 1
      tripal_bulk_loader/tripal_bulk_loader.info
  56. 2 2
      tripal_chado/api/modules/tripal_chado.cv.api.inc
  57. 1 1
      tripal_chado/api/modules/tripal_chado.db.api.inc
  58. 37 18
      tripal_chado/api/modules/tripal_chado.organism.api.inc
  59. 1 1
      tripal_chado/api/modules/tripal_chado.phylotree.api.inc
  60. 59 59
      tripal_chado/api/tripal_chado.variables.api.inc
  61. 6 1
      tripal_chado/includes/TripalFields/chado_linker__prop/chado_linker__prop_formatter.inc
  62. 1 1
      tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_formatter.inc
  63. 91 28
      tripal_chado/includes/TripalFields/sio__references/sio__references.inc
  64. 25 6
      tripal_chado/includes/TripalFields/sio__references/sio__references_formatter.inc
  65. 87 31
      tripal_chado/includes/TripalImporter/OBOImporter.inc
  66. 3 3
      tripal_chado/includes/tripal_chado.fields.inc
  67. 1 1
      tripal_chado/includes/tripal_chado.phylotree.inc
  68. 1 1
      tripal_chado/tripal_chado.info
  69. 1 1
      tripal_chado_views/tripal_chado_views.info
  70. 1 1
      tripal_daemon/theme/tripal_daemon.log_block.css
  71. 1 1
      tripal_ds/tripal_ds.info
  72. 1 1
      tripal_ws/includes/TripalFields/remote__data/remote__data_formatter.inc
  73. 1 1
      tripal_ws/includes/TripalWebService.inc
  74. 62 29
      tripal_ws/includes/TripalWebService/TripalContentService_v0_1.inc
  75. 1 1
      tripal_ws/includes/TripalWebServiceCollection.inc
  76. 60 1
      tripal_ws/includes/TripalWebServiceResource.inc
  77. 1 1
      tripal_ws/tripal_ws.info

+ 136 - 0
.github/workflows/phpunit-tests.yml

@@ -0,0 +1,136 @@
+# Run our PHPUnit tests
+name: PHPUnit-Tests
+
+# Controls when the action will run.
+# Run this workflow every time a new commit is pushed to your repository
+on: [push, pull_request]
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+  # This workflow contains a single job called "build"
+  run-tests:
+    # The type of runner that the job will run on
+    runs-on: ubuntu-latest
+    # Matrix Build for this job.
+    strategy:
+      matrix:
+        php-versions: ['7.1', '7.2']
+    # Name the matrix build so we can tell them apart.
+    name: PHPUnit Testing of Tripal Core (PHP ${{ matrix.php-versions }})
+
+    # Service containers to run with `run-tests`
+    services:
+      # Label used to access the service container
+      postgres:
+        # Docker Hub image
+        image: postgres
+        env:
+          POSTGRES_USER: postgres
+          POSTGRES_PASSWORD: dbpass
+          POSTGRES_DB: test_db
+        # Set health checks to wait until postgres has started
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+        ports:
+          # Maps tcp port 5432 on service container to the host
+          - 5432:5432
+
+    # Steps represent a sequence of tasks that will be executed as part of the job
+    steps:
+      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+      - name: Checkout Repository
+        uses: actions/checkout@v2
+      # Sets up the PHP environment for PHP 7.2
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: ${{ matrix.php-versions }}
+          # Install extensions for PHP-PostgreSQL
+          extensions: mbstring, intl, php-pgsql, php-gd, php-xml
+          # Increase memory limit to 2G
+          ini-values: memory_limit=2G
+          # Enable xdebug for coverage reporting
+          coverage: xdebug
+          # Install composer and phpunit globally.
+          tools: composer, phpunit
+      # Install Drush 8.x globally
+      # NOTE: `drush` is not available without the full path.
+      #       I tried adding it to the path but that broke other things.
+      - name: Install Drush
+        run: |
+          composer global require "drush/drush:~8"
+          /home/runner/.composer/vendor/bin/drush --version
+      # Install Drupal and Drupal module dependencies for Tripal.
+      # It also patches Drupal.
+      - name: Install Drupal
+        env:
+          DRUSH: "/home/runner/.composer/vendor/bin/drush"
+          DRUPAL_ROOT: "/home/runner/work/drupal"
+          POSTGRES_CONNECTION_STRING: 'pgsql://postgres:dbpass@localhost:5432/test_db'
+          ACCOUNT_NAME: tripaladmin
+          ACCOUNT_PASS: somereallysecurepassword
+        run: |
+          echo "==> Downloading Drupal"
+          cd /home/runner/work
+          $DRUSH dl drupal-7 -y
+          mv drupal-7* drupal
+          echo "==> Installing Drupal"
+          cd $DRUPAL_ROOT
+          $DRUSH si -y --root=$DRUPAL_ROOT \
+                --db-url=$POSTGRES_CONNECTION_STRING \
+                --account-name=$ACCOUNT_NAME \
+                --account-pass=$ACCOUNT_PASS \
+                --site-mail=admin@example.com \
+                --site-name=Tripal3
+          echo "==> Downloading dependencies"
+          $DRUSH dl -y views ctools entity redirect date ds field_group field_group_table
+          echo "==> Enabling Dependencies"
+          $DRUSH en -y views ctools entity redirect date ds field_group field_group_table
+          echo "==> Apply Drupal Patch"
+          cd $DRUPAL_ROOT
+          wget --no-check-certificate https://drupal.org/files/drupal.pgsql-bytea.27.patch
+          patch -p1 < drupal.pgsql-bytea.27.patch
+      # Install Tripal, Chado and prepares the Drupal/Chado databases
+      # Also patches views.
+      - name: Install Tripal
+        env:
+          DRUSH: "/home/runner/.composer/vendor/bin/drush"
+          DRUPAL_ROOT: "/home/runner/work/drupal"
+          POSTGRES_CONNECTION_STRING: 'pgsql://postgres:dbpass@localhost:5432/test_db'
+          ACCOUNT_NAME: tripaladmin
+          ACCOUNT_PASS: somereallysecurepassword
+        run: |
+          echo "==> Move Tripal into the Drupal modules directory"
+          ls /home/runner/work/tripal/tripal
+          cp -R /home/runner/work/tripal/tripal $DRUPAL_ROOT/sites/all/modules
+          echo "==> Apply Views Patch"
+          cd $DRUPAL_ROOT/sites/all/modules/views
+          patch -p1 < ../tripal/tripal_chado_views/views-sql-compliant-three-tier-naming-1971160-30.patch
+          echo "==> Install Tripal"
+          cd $DRUPAL_ROOT
+          $DRUSH en -y tripal tripal_chado tripal_chado_views tripal_ws tripal_ds
+          echo "==> Install Chado"
+          $DRUSH eval "module_load_include('inc', 'tripal_chado', 'includes/tripal_chado.install'); tripal_chado_load_drush_submit('Install Chado v1.3');"
+          $DRUSH trp-run-jobs --username=$ACCOUNT_NAME
+          echo "==> Prepare Chado"
+          $DRUSH eval "module_load_include('inc', 'tripal_chado', 'includes/setup/tripal_chado.setup'); tripal_chado_prepare_drush_submit();"
+          $DRUSH trp-run-jobs --username=$ACCOUNT_NAME
+      # Runs the PHPUnit tests.
+      # https://github.com/mheap/phpunit-github-actions-printer is used
+      # to report PHPUnit fails in a meaningful way to github in PRs.
+      - name: PHPUnit Tests
+        env:
+          DRUSH: "/home/runner/.composer/vendor/bin/drush"
+          DRUPAL_ROOT: "/home/runner/work/drupal"
+          POSTGRES_CONNECTION_STRING: 'pgsql://postgres:dbpass@localhost:5432/test_db'
+          ACCOUNT_NAME: tripaladmin
+          ACCOUNT_PASS: somereallysecurepassword
+        run: |
+          cd $DRUPAL_ROOT/sites/all/modules/tripal
+          composer require --dev mheap/phpunit-github-actions-printer
+          composer update
+          cp tests/.travis.env tests/.env
+          ./vendor/bin/phpunit --printer mheap\\GithubActionsReporter\\Printer

+ 0 - 86
.travis.yml

@@ -1,86 +0,0 @@
-language: php
-
-services:
-  - docker
-  - postgresql
-
-sudo: required
-
-php:
-  - 7.1
-  - 7.2
-#  PHP 7.3 is not yet supported (issue: https://www.drupal.org/project/drupal/issues/3012308)
-#  - 7.3
-
-env:
-  - BASE_URL="http://127.0.0.1:8080"
-
-install:
-  - composer global require "drush/drush:~8"
-
-before_script:
-  - docker pull statonlab/tripal2
-  - psql -c "create database test_db encoding 'utf-8';" -U postgres
-  - psql -c "alter role postgres with password 'dbpass';" -U postgres
-  - cd ..
-
-  # Set additional environment variables
-  - export PATH="$HOME/.config/composer/vendor/bin:$PATH"
-  - export DRUPAL_ROOT="$(pwd)/drupal"
-
-  # Download and install Drupal
-  - drush dl drupal-7 -y
-  - mv drupal-7* drupal
-  - cd drupal
-  # Run the php server
-  - php -S 127.0.0.1:8080 &
-  - drush si -y --db-url='pgsql://postgres:dbpass@localhost:5432/test_db'
-                --account-name='admin'
-                --account-pass='admin_pass'
-                --site-mail='admin@example.com'
-                --site-name='Tripal 3'
-
-  # Download Dependencies
-  - drush dl -y field_group, field_group_table, field_formatter_class, field_formatter_settings, ctools, date, devel,
-                ds, link, entity, libraries, redirect, token, uuid, jquery_update, views, webform
-
-  # Enable dependencies
-  - drush en -y field_group, field_group_table, field_formatter_class, field_formatter_settings, ctools, date, devel,
-              ds, link, entity, libraries, redirect, token uuid, jquery_update, views, webform
-
-  # up memory limit of PHP
-  - echo "memory_limit=2G" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
-
-
-script:
-  # Link our repo to the modules directory
-  - mv ../tripal sites/all/modules/tripal
-
-  # Run a docker container with tripal 2 pre-installed
-  - docker run -it -d --rm --name tripal2 -v "$(pwd)/sites/all/modules/tripal":/tripal statonlab/tripal2
-
-  # Apply patches
-  - wget --no-check-certificate https://drupal.org/files/drupal.pgsql-bytea.27.patch
-  - patch -p1 < drupal.pgsql-bytea.27.patch
-  - cd sites/all/modules/views
-  - patch -p1 < ../tripal/tripal_chado_views/views-sql-compliant-three-tier-naming-1971160-30.patch
-  - cd ../tripal
-
-  # Install Tripal
-  - drush en -y tripal tripal_chado tripal_chado_views tripal_ds tripal_ws
-  - drush eval "module_load_include('inc', 'tripal_chado', 'includes/tripal_chado.install'); tripal_chado_load_drush_submit('Install Chado v1.3');"
-  - drush trp-run-jobs --username=admin
-
-  # Prepare Chado
-  - drush eval "module_load_include('inc', 'tripal_chado', 'includes/setup/tripal_chado.setup'); tripal_chado_prepare_drush_submit();"
-  - drush trp-run-jobs --username=admin
-
-  # Run PHPUnit tests
-  - composer update
-  - cp tests/.travis.env tests/.env
-  - ./vendor/bin/phpunit
-
-  # Test Tripal v2 to v3 upgrade steps
-  - docker exec -it tripal2 drush pm-disable tripal_core -y
-  - docker exec -it tripal2 bash -c "rm -rf /modules/tripal && ln -s /tripal /modules/tripal"
-  - docker exec -it tripal2 drush en -y tripal

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
-[![7.x-3.x Build Status](https://travis-ci.org/tripal/tripal.svg?branch=7.x-3.x)](https://travis-ci.org/tripal/tripal)
+![PHPUnit Tests](https://github.com/tripal/tripal/workflows/PHPUnit%20Tests/badge.svg)
 [![All Contributors](https://img.shields.io/badge/all_contributors-14-orange.svg?style=flat-square)](#contributors)
 [![Documentation Status](https://readthedocs.org/projects/tripal/badge/?version=latest)](https://tripal.readthedocs.io/en/latest/?badge=latest)
 

+ 1 - 1
composer.json

@@ -1,5 +1,5 @@
 {
-  "name": "tripal",
+  "name": "tripal/tripal",
   "description": "Tripal is an toolkit to facilitate construction of online genomic, genetic (and other biological) websites.",
   "require-dev": {
     "doctrine/instantiator": "1.0.*",

+ 1 - 0
docs/dev_guide.rst

@@ -15,5 +15,6 @@ Developer's Guide
    dev_guide/exporting_field_settings
    dev_guide/custom_data_loader
    dev_guide/custom_web_services
+   dev_guide/CI
    dev_guide/rtd
    dev_guide/tutorials

BIN
docs/dev_guide/CI.create-badge.png


+ 165 - 0
docs/dev_guide/CI.rst

@@ -0,0 +1,165 @@
+
+Continuous Integration
+========================
+
+Continuous integration refers to an active code base where multiple developers are integrating their changes continuously into a single cohesive project. One of the biggest keys to making continuous integration work is testing before integrating! Tripal Test Suite makes developing tests using PHPUnit much easier and this tutorial will show you how to ensure those tests are run every time you push to GitHub!
+
+Using GitHub Workflows
+------------------------
+
+First, what is a GitHub Workflow? From GitHub, "a workflow is a configurable automated process made up of one or more jobs". I like to think of it as configuring a bioinformatics pipeline. For the purposes of this tutorial, we are telling GitHub how to execute our PHPUnit tests automatically.
+
+You can learn more about `GitHub Action Workflows from GitHub directly <https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/introduction-to-github-actions>`_. We will cover it breifly here specifically for Tripal PHPUnit testing but the official tutorial is still recommended.
+
+Telling GitHub about your workflow
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is as simple as creating your workflow file in the right place. You want to create a new file named `phpunit.yml` at `.github/workflows/` in your repository. GitHub will automatically know this file describes a workflow and will execute the workflow based on the configuration you provide.
+
+Configuring a workflow to run PHPUnit tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+All configuration will be done in the file created in step 1.
+
+First we provide the name, when we want to run the workflow (i.e. on push and PRs) and the basic structure of a workflow:
+
+.. code-block:: yaml
+
+  name: PHPUnit
+
+  # Controls when the workflow will run.
+  # Run this workflow every time a new commit is pushed to your repository
+  on: [push, pull_request]
+
+  jobs:
+    # This key is the name of the job.
+    run-tests:
+      # The type of system that the job will run on.
+      runs-on: ubuntu-latest
+
+
+We want our tests to be run twice, one for PHP 7.1 and another for PHP 7.1. This is done by specifing a matrix build which can be done as follows:
+
+.. code-block:: yaml
+
+  jobs:
+    # This key is the name of the job.
+    run-tests:
+      # The type of system that the job will run on.
+      runs-on: ubuntu-latest
+
+      # Matrix Build for this job.
+      strategy:
+        matrix:
+          php-versions: ['7.1', '7.2']
+
+      # Name the matrix build so we can tell them apart.
+      name: PHPUnit Testing (PHP ${{ matrix.php-versions }})
+
+We also want to tell GitHub to setup a PostgreSQL server for us. This is done using services:
+
+.. code-block:: yaml
+
+  jobs:
+    # This key is the name of the job.
+    run-tests:
+      # The type of system that the job will run on.
+      runs-on: ubuntu-latest
+
+      # Service containers to run with `run-tests`
+      services:
+        # Label used to access the service container
+        postgres:
+          # Docker Hub image
+          image: postgres
+          env:
+            POSTGRES_USER: tripaladmin
+            POSTGRES_PASSWORD: somesupersecurepassword
+            POSTGRES_DB: testdb
+          # Set health checks to wait until postgres has started
+          options: >-
+            --health-cmd pg_isready
+            --health-interval 10s
+            --health-timeout 5s
+            --health-retries 5
+          ports:
+            # Maps tcp port 5432 on service container to the host
+            - 5432:5432
+
+Finally we can actually tell GitHub what steps we want to run using this beautiful container we have setup! We want to:
+
+.. code-block:: yaml
+
+  jobs:
+    # This key is the name of the job.
+    run-tests:
+      # The type of system that the job will run on.
+      runs-on: ubuntu-latest
+
+      steps:
+      # 1) Checkout the repository and setup workspace.
+      - uses: actions/checkout@v2
+
+      # 2) Setup PHP according to the version passed in.
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: ${{ matrix.php-versions }}
+          extensions: mbstring, intl, php-pgsql, php-gd, php-xml
+          ini-values: memory_limit=2G
+          coverage: xdebug
+          tools: composer, phpunit
+
+      # 3) Install Drush/Drupal/Tripal
+      - name: Setup Drush, Drupal 7.x, Tripal 3.x
+        id: tripalsetup
+        uses: tripal/setup-tripal-action@7.x-3.x-1.0
+        with:
+          postgres_user: tripaladmin
+          postgres_pass: somesupersecurepassword
+          postgres_db: testdb
+
+      # 4) Install Tripal Extension Module.
+      - name: Install Tripal Extension Module
+        id: installextension
+        env:
+          DRUSH: ${{ steps.tripalsetup.outputs.drush_path }}
+          DRUPAL_ROOT: ${{ steps.tripalsetup.outputs.drupal_root }}
+        run: |
+          mkdir -p $DRUPAL_ROOT/sites/all/modules/example_module
+          cp -R * $DRUPAL_ROOT/sites/all/modules/example_module
+          cd $DRUPAL_ROOT
+          $DRUSH en -y example_module
+
+      # 5) Runs the PHPUnit tests.
+      # https://github.com/mheap/phpunit-github-actions-printer is used
+      # to report PHPUnit fails in a meaningful way to github in PRs.
+      - name: PHPUnit Tests
+        env:
+          DRUSH: ${{ steps.tripalsetup.outputs.drush_path }}
+          DRUPAL_ROOT: ${{ steps.tripalsetup.outputs.drupal_root }}
+        run: |
+          cd $DRUPAL_ROOT/sites/all/modules/example_module
+          composer require --dev mheap/phpunit-github-actions-printer --quiet
+          composer update --quiet
+          ./vendor/bin/phpunit --printer mheap\\GithubActionsReporter\\Printer
+
+In step 4 above, I have provided an example of what installing your extension module might look like. The run section will need to be modified according to your module and should include downloading and installing any dependencies, applying any patches and installing your module. If your tests require configuration then that should also be included here.
+
+In step 5 we run our PHPUnit tests! All you need to change here is the directory name for your module. The `mheap\\GithubActionsReporter\\Printer` will ensure any errors reported by PHPUnit are shown on your PR and Action summary.
+
+All steps before step 4 should be generic for any extension module! You can find the full configuration file on the `README of the SetupTripalAction <https://github.com/tripal/setup-tripal-action#usage>`_.
+
+Checking your Action
+----------------------
+
+Everytime you push commits to your repository and when you create a pull request, your action will be run. Thus to test your action, commit your phpunit.yml file created above to trigger the GitHub action. Then click on "Actions" at the top of your repository to see it in progress.
+
+If you created a pull request, you will see your workflow action in the checks section at the bottom of your pull request. From here you can click on Details to see the full running of the job.
+
+Adding the Badge to your README
+---------------------------------
+
+Click on Actions at the top of your repository, then click on one of the PHPUnit jobs which have already been submitted. This brings you to the job summary page where you will see a button with three dots in the top right corner. Click on this and then "Create status badge" to get the markdown to add to your README.
+
+.. image:: CI.create-badge.png

+ 1 - 1
docs/dev_guide/custom_field/custom_widget.rst

@@ -135,7 +135,7 @@ But what do you do if the record you want to link to via foreign key constraint
       // Set all chado fields to their values.
     }
     // Otherwise, maybe we are creating the entity...
-    // The storage API should handle this case and automagically add the key in // once the chado record is created... so all we need to do is set the
+    // The storage API should handle this case and automatically add the key in // once the chado record is created... so all we need to do is set the
     // other columns.
     elseif ($subject_name && $object_id && $type_id) {
       $form_state['values'][$field_name][$langcode][$delta]['value'] = 'value must be set but is not used';

+ 4 - 4
docs/dev_guide/custom_field/manual_field_creation.rst

@@ -122,7 +122,7 @@ Sometimes a field is meant to provide a visualization or some other functionalit
 
 
 .. note::
-  Be sure to only set this to TRUE when you are absolutely certain the contents would not be needed in web services.  Tripal was designed so that what appears on the page will always appear in web services.  Aside form the formatting we see on the website, the content should be the same.
+  Be sure to only set this to TRUE when you are absolutely certain the contents would not be needed in web services.  Tripal was designed so that what appears on the page will always appear in web services.  Aside from the formatting we see on the website, the content should be the same.
 
 Finally, the last item in our Class variables is the **download_formatters**.  Tripal provides an API that allows tools to group entities into data collections.  Data collections are like "baskets" or "shopping carts".   Entities that are in data collections can be downloaded into files.  If your field is compatible with specific file downloaders you can specify those here.  A file downloader is a special TripalFieldDownloader class that "speaks" certain file formats.  Tripal, by default, provides the TripalTabDownloader (for tab-delimited files), the TripalCSVDownloader (for CSV files), a TripalNucFASTADownloader for creating nucleotide FASTA files and a TripalProteinFASTADownloader for protein FASTA files.   If your field is compatible with any of these formatters you can specify them in the following array:
 
@@ -198,7 +198,7 @@ Next, let's initialize our field's value to be empty.  When setting a field valu
     );
 
 
-Notice that our field has some sub elements. The first is 'und'.  This element corresponds to the "language" of the text.  Drupal supports multiple spoken languages and wants to know the language of text we provide.  For Tripal fields we always use 'und' meaning 'undefined'.   The next element is the delta index number.  Field have a cardinality, or in other words they can have multiple values.  For every value we add we increment that index, always starting at zero.  The last element is our 'value' element and it is here where we put our element. You may notice that our **delta** index is hard coded to 0.  This is because an entity can only always have one organism that it is associated with.  We will never have more than one.
+Notice that our field has some sub elements. The first is 'und'.  This element corresponds to the "language" of the text.  Drupal supports multiple spoken languages and wants to know the language of text we provide.  For Tripal fields we always use 'und' meaning 'undefined'.   The next element is the delta index number.  Fields have a cardinality, or in other words they can have multiple values.  For every value we add we increment that index, always starting at zero.  The last element is our 'value' element and it is here where we put our element. You may notice that our **delta** index is hard coded to 0.  This is because an entity can only always have one organism that it is associated with.  We will never have more than one.
 
 Now that we've got some preliminary values and we've initialized our value array we can start adding values!  Before we do though, let's double check that we have a record.  If we don't have a record for this entity, we can't get a value.
 
@@ -222,7 +222,7 @@ We can easily get all of the values we need from this organism object.   We can
 
 .. code-block:: php 
 
-      $label = tripal_replace_chado_tokens($string, $organism);
+      $label = chado_replace_tokens($string, $organism);
       $entity->{$field_name}['und'][0]['value'] = array(
         $label_term => $label,
         $genus_term => $organism->genus,
@@ -278,7 +278,7 @@ We do this because anything in the 'value' element is intended for the end-user.
 
   1.  Does the user need this value?  If yes, put it in the 'value' element.
   2.  Does Tripal need the value when writing back to the Chado table?  If yes, put it as a hidden element.
-  3.  Does the user need to see the value an will this same value need to be written to the table?  If yes, then you have to put the value in both places.
+  3.  Does the user need to see the value and will this same value need to be written to the table?  If yes, then you have to put the value in both places.
 
 For our **obi__organism** field it is for entities with records in the **feature, stock, library**, etc. tables. Those tables only have an **organism_id** to represent the organism.  So, that's the database column this field is supporting.  We therefore, need to put that field as a hidden field, and all the others are just helpful to the user and don't get saved in the feature, stock or library tables. So, those go in the values array.
 

+ 2 - 2
docs/dev_guide/custom_field/select_vocab_terms.rst

@@ -27,7 +27,7 @@ Consider the term for `organism <http://www.ebi.ac.uk/ols/ontologies/obi/terms?i
 
 .. figure:: select_vocab_terms.1.organism.png
 
-Notice how the teal box (the **short name**) is OBI, and the orange box contains the **full accession**, OBI:0100026 which includes but the **short name** and the unique term **accession** value.  Unfortunately, the OLS does not indicate the **namespace** terms.   So, as a rule we will use the short name converted to lower case.  Before using this term in a Tripal Bundle or Field you may need to insert this term into Chado.  You can do so in your custom module cude using the **tripal_insert_cvterm** function. The following provides a demonstration:
+Notice how the teal box (the **short name**) is OBI, and the orange box contains the **full accession**, OBI:0100026 which includes but the **short name** and the unique term **accession** value.  Unfortunately, the OLS does not indicate the **namespace** terms.   So, as a rule we will use the short name converted to lower case.  Before using this term in a Tripal Bundle or Field you may need to insert this term into Chado.  You can do so in your custom module code using the **tripal_insert_cvterm** function. The following provides a demonstration:
 
 .. code-block:: php
 
@@ -104,7 +104,7 @@ Some ontologies are b into sub-ontologies. This includes the Gene Ontology (GO).
 .. figure:: select_vocab_terms.3.go.png
 
 
-Case 4: Ontologies with muliptle short names
+Case 4: Ontologies with multiple short names
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The EDAM ontology builds its term accessions using different short names instead of the ontology. Consider the EDAM term for `Sequence <http://www.ebi.ac.uk/ols/ontologies/edam/terms?iri=http%3A%2F%2Fedamontology.org%2Fdata_2044>`_. The teal box is EDAM, the orange box is data:2044, and there is no **namespace**.

+ 1 - 1
docs/dev_guide/custom_web_services.rst

@@ -10,7 +10,7 @@ New in Tripal v3 are `RESTful web services <https://en.wikipedia.org/wiki/Repres
 
 Tripal v3 has been redesigned from Tripal v2 to be fully organized around controlled vocabularies.  All data made available via Tripal is expected to be described by the terms of a controlled vocabulary or ontology.  For example, all content types in Tripal are assigned a controlled vocabulary term that describes what the content is.  Additionally, each field of data attached to a content type also is described using a controlled vocabulary term.  If a field provides more than just a single data value (i.e. it provides a list or nested structured array of data of key/value pairs) then each of the keys for those pairs must also be a controlled vocabulary term.  This requirement allows Tripal to fully describe the data it houses to any other Tripal site and any other script or service that can read the web services.  As long as the client application understands the vocabulary term it will understand the meaning of the data.  Using controlled vocabulary terms to describe all data allows a Tripal site to participate in the `Semantic Web <https://en.wikipedia.org/wiki/Semantic_Web>`_. 
 
-Finally, the Tripal RESTful services are meant to be discoverable.  In some cases, when a web services is designed, the only way to understand the structure of it and the operations that it provides are for a programmer to read online documentation for the service before she can write the client application.  However, to better support automatic data discovery without human intervention by a client the Tripal web services have been designed to be discoverable.  To this end, Tripal uses the  `Hyrda Core Vocabulary <https://www.hydra-cg.com/spec/latest/core/>`_ specification.  It fully describes all of the services, their operations, and the resulting value.  A client application that understands the Hydra language can therefore learn  to use the web service without human intervention.  However, in practice, its a good idea to continue to provide online documentation for humans.  And this User's Guide :doc:`provides those instructions </user_guide/web_services>` for the default Tripal content service.  
+Finally, the Tripal RESTful services are meant to be discoverable.  In some cases, when a web services is designed, the only way to understand the structure of it and the operations that it provides are for a programmer to read online documentation for the service before she can write the client application.  However, to better support automatic data discovery without human intervention by a client the Tripal web services have been designed to be discoverable.  To this end, Tripal uses the  `Hydra Core Vocabulary <https://www.hydra-cg.com/spec/latest/core/>`_ specification.  It fully describes all of the services, their operations, and the resulting value.  A client application that understands the Hydra language can therefore learn  to use the web service without human intervention.  However, in practice, its a good idea to continue to provide online documentation for humans.  And this User's Guide :doc:`provides those instructions </user_guide/web_services>` for the default Tripal content service.  
 
 This documentation provides instructions to construct your own custom web services and making that service available through Tripal's existing web service infrastructure.  This will enable your web service to be discoverable and to provide a consistent experience to end-users.  Before proceeding with the following instructions, please review the **Structure of a Web Service Response** section on the User's Guide :doc:`Web Services page </user_guide/web_services>`.
 

+ 1 - 1
docs/dev_guide/exporting_field_settings.rst

@@ -111,7 +111,7 @@ Go to our target site, all we need to do is download and unpack the ``.tar`` fil
 
 The field should now appear when you go to create a new analysis on your target site.  To check for yourself, create a new Analysis with dummy information: you'll be able to upload a file for the new file field.
 
-Unfortunately, the field still gets imported **disabled** due to Tripal preference, so we have to go to the display settings on our target site and enable the tripal pane/field.
+Unfortunately, the field still gets imported **disabled** due to Tripal preference, so we have to go to the display settings on our target site and enable the Tripal pane/field.
 
 
 .. image:: ./exporting_field_settings.6.png

+ 1 - 1
docs/extensions/data_input.rst

@@ -14,7 +14,7 @@ A Drush-based loader for VCF files that follows the genotype storage rules outli
 Mainlab Chado Loader
 ---------------------
 
-MCL (Mainlab Chado Loader) is a module that enables users to upload their biological data to Chado database schema. Users are required to transfer their biological data into various types of data template files. MCL, then, uploads these data template files into a chado schema.
+MCL (Mainlab Chado Loader) is a module that enables users to upload their biological data to Chado database schema. Users are required to transfer their biological data into various types of data template files. MCL, then, uploads these data template files into a Chado schema.
 
 `Documentation <https://gitlab.com/mainlabwsu/mcl/blob/master/README.md>`__
 `Repository <https://gitlab.com/mainlabwsu/mcl>`__

+ 0 - 8
docs/extensions/in_development.rst

@@ -5,14 +5,6 @@ In Development
 The following modules are not yet ready for production or not fully Tripal 3 compatible.
 
 
-TripalMap
------------
-
-TripalMap MapViewer module displays map data stored in Chado. MapViewer provides interfaces to view all linkage groups of a map, choose a linkage group and zoom in to a specific region of a linkage group, compare maps that share the same markers and change colors of markers/QTL. The interface can be integrated into Tripal map page and hyperlinked to/from any Tripal page that are displayed in maps (marker, QTL, heritable morphological marker and/or gene). The admin page allows site developers some flexibility in the display pattern.
-
-`Documentation <https://gitlab.com/mainlabwsu/tripal_map/blob/master/README.md>`__
-`Repository <https://gitlab.com/mainlabwsu/tripal_map>`__
-
 Tripal Apollo
 --------------
 

+ 1 - 1
docs/extensions/module_rating.rst

@@ -23,7 +23,7 @@ Silver
 
 - Follows basic Drupal Coding standards; specifically, `code format <https://www.drupal.org/docs/develop/standards/coding-standards>`_ and `API documentation <https://www.drupal.org/docs/develop/standards/api-documentation-and-comment-standards#drupal>`_.
 - Uses Tripal API functions. Specifically, it should use the
-    - Chado Query API for querying chado (if using chado as the storage system). (`API <http://api.tripal.info/api/tripal/tripal_chado%21api%21tripal_chado.query.api.inc/group/tripal_chado_query_api/3.x>`_, :doc:`Tutorial <../dev_guide/chado>`)
+    - Chado Query API for querying Chado (if using Chado as the storage system). (`API <http://api.tripal.info/api/tripal/tripal_chado%21api%21tripal_chado.query.api.inc/group/tripal_chado_query_api/3.x>`_, :doc:`Tutorial <../dev_guide/chado>`)
     - Tripal Jobs API for long running processes. (`API  <http://api.tripal.info/api/tripal/tripal%21api%21tripal.jobs.api.inc/group/tripal_jobs_api/3.x>`_)
     - TripalField class to add data to pages (Tripal3). (:doc:`Tutorial <../dev_guide/custom_field>`)
 - Provides ways to customize the module (e.g. drush options, field/formatter settings, admin UI).

+ 1 - 1
docs/extensions/search.rst

@@ -28,7 +28,7 @@ The Tripal ElasticSearch module allows you to easily manage the indexing and dis
 Tripal MegaSearch
 ---------------------
 
-Tripal MegaSearch is a tool for downloading biological data stored in a Tripal/Chado database. The module was designed to be generic and flexible so it can be used on most Tripal sites. Site administrators may choose from 1) a set of predefined materialized views or 2) chado base tables as the data source to serve data. If neither data source is desired, developers may create their own materialized views and serve them through Tripal MegaSearch via a flexible dynamic query form. This form allows filters to be added dynamically and combined using 'AND/OR' operators. The filters correspond to the underlying data source columns so the user can filter data on each column.
+Tripal MegaSearch is a tool for downloading biological data stored in a Tripal/Chado database. The module was designed to be generic and flexible so it can be used on most Tripal sites. Site administrators may choose from 1) a set of predefined materialized views or 2) Chado base tables as the data source to serve data. If neither data source is desired, developers may create their own materialized views and serve them through Tripal MegaSearch via a flexible dynamic query form. This form allows filters to be added dynamically and combined using 'AND/OR' operators. The filters correspond to the underlying data source columns so the user can filter data on each column.
 
 `Documentation <https://gitlab.com/mainlabwsu/tripal_megasearch/blob/master/README.md>`__
 `Repository <https://gitlab.com/mainlabwsu/tripal_megasearch>`__

+ 16 - 0
docs/extensions/visualization.rst

@@ -6,6 +6,10 @@ The following modules provide specialized displays for Tripal content types.
 Analyzed Phenotypes
 --------------------
 
+.. image:: https://tripal.readthedocs.io/en/7.x-3.x/_images/Tripal-Gold.png
+  :target: https://tripal.readthedocs.io/en/7.x-3.x/extensions/module_rating.html#Gold
+  :alt: Tripal Rating: Gold
+
 This module provides support and visualization for partially analyzed data stored in a modified GMOD Chado schema. It is meant to support large scale phenotypic data through backwards compatible improvements to the Chado schema including the addition of a project and stock foreign key to the existing phenotype table, optimized queries and well-chosen indexes.
 
 `Documentation <https://analyzedphenotypes.readthedocs.io/en/latest/index.html>`__
@@ -30,6 +34,10 @@ Mainlab Tripal Data Display contains a set of Drupal/PHP templates that organize
 ND Genotypes
 -------------
 
+.. image:: https://tripal.readthedocs.io/en/7.x-3.x/_images/Tripal-Gold.png
+  :target: https://tripal.readthedocs.io/en/7.x-3.x/extensions/module_rating.html#Gold
+  :alt: Tripal Rating: Gold
+
 This module provides support and visualization of genotypic data stored in a modified GMOD Chado schema. The 3.x branch of this module represents a shift towards support for large scale genotypic datasets through backwards compatible improvements to the Chado schema including a new gathering table for genotypes (genotype_call) modeled after the Chado phenotype table, optimized queries and well-chosen indexes.
 
 `Documentation <https://nd-genotypes.readthedocs.io/en/latest/>`__
@@ -51,3 +59,11 @@ This module provides additional fields for use with Tripal 3. The current versio
 
 `Documentation <https://github.com/tripal/trpfancy_fields/blob/master/README.md>`__
 `Repository <https://github.com/tripal/trpfancy_fields>`__
+
+TripalMap
+-----------
+
+TripalMap MapViewer module displays map data stored in Chado. MapViewer provides interfaces to view all linkage groups of a map, choose a linkage group and zoom in to a specific region of a linkage group, compare maps that share the same markers and change colors of markers/QTL. The interface can be integrated into Tripal map page and hyperlinked to/from any Tripal page that are displayed in maps (marker, QTL, heritable morphological marker and/or gene). The admin page allows site developers some flexibility in the display pattern.
+
+`Documentation <https://gitlab.com/mainlabwsu/tripal_map/blob/master/README.md>`__
+`Repository <https://gitlab.com/mainlabwsu/tripal_map>`__

+ 1 - 1
docs/user_guide/install_tripal/custom_theme.rst

@@ -7,7 +7,7 @@ Drupal makes it easy to change the look-and-feel of your site by providing Theme
 
 Customizing a Theme
 -------------------
-If you want to make customizations to the theme you should create your own sub theme.  A sub theme borrows from an existing **base theme** (e.g. Bartik) and allows you to make your customizations.  Thus, when updates for a theme are released you can easily upgrade your base theme without losing your changes.   To create a sub theme, follow the instructions on the `Creating a sub-theme page <https://www.drupal.org/docs/7/theming/creating-a-sub-theme>`_ on the Drupal website.  Alternatively, completely custom themes do not borrow from any other theme, you can create your own full-blown theme by following the `Themeing instructions <https://www.drupal.org/docs/7/theming>`_ at the Drupal website.
+If you want to make customizations to the theme you should create your own sub theme.  A sub theme borrows from an existing **base theme** (e.g. Bartik) and allows you to make your customizations.  Thus, when updates for a theme are released you can easily upgrade your base theme without losing your changes.   To create a sub theme, follow the instructions on the `Creating a sub-theme page <https://www.drupal.org/docs/7/theming/creating-a-sub-theme>`_ on the Drupal website.  Alternatively, completely custom themes do not borrow from any other theme, you can create your own full-blown theme by following the `Theming instructions <https://www.drupal.org/docs/7/theming>`_ at the Drupal website.
 
 .. note::
 

+ 1 - 1
docs/user_guide/install_tripal/upgrade_from_tripal2.rst

@@ -50,7 +50,7 @@ Step 1: Upgrade Tripal
 
   .. code-block:: bash
 
-    drush pm-download tripal-7.x-3.1
+    drush pm-download tripal-7.x-3.5
 
 5. Enable the tripal module
 

+ 1 - 1
legacy/tripal_analysis/tripal_analysis.info

@@ -3,7 +3,7 @@ description = Supports the companalyses tables of Chado by providing pages for v
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal/legacy/tripal_analysis/configuration
 
 dependencies[] = tripal_core

+ 1 - 1
legacy/tripal_contact/tripal_contact.info

@@ -3,7 +3,7 @@ description = Supports the contact tables of Chado by providing pages for viewin
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 2 - 2
legacy/tripal_core/api/tripal_core.chado_nodes.properties.api.inc

@@ -178,7 +178,7 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
   // make sure the property table exists before proceeding.
   if (!chado_table_exists($details['property_table'])) {
     drupal_set_message("Cannot add property elements to the form. The property table, '" .
-      $details['property_table'] . "', does not exists", "error");
+      $details['property_table'] . "', does not exist", "error");
     tripal_report_error('tcprops_form', TRIPAL_ERROR,
       "Cannot add property elements to the form. The property table, '%name', cannot be found.",
       ['%name' => $details['property_table']]);
@@ -203,7 +203,7 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
     $result = chado_select_record('cv', ['cv_id'], ['name' => $details['cv_name']]);
     if (count($result) == 0) {
       drupal_set_message("Cannot add property elements to the form. The CV name, '" .
-        $details['cv_name'] . "', does not exists", "error");
+        $details['cv_name'] . "', does not exist", "error");
       tripal_report_error('tcprops_form', TRIPAL_ERROR,
         "Cannot add property elements to the form. The CV named, '%name', cannot be found.",
         ['%name' => $details['cv_name']]);

+ 2 - 2
legacy/tripal_core/api/tripal_core.chado_nodes.relationships.api.inc

@@ -155,7 +155,7 @@ function chado_add_node_form_relationships(&$form, &$form_state, $details) {
   // make sure the relationship table exists before proceeding.
   if (!chado_table_exists($details['relationship_table'])) {
     drupal_set_message("Cannot add relationship elements to the form. The relationship table, '" .
-      $details['relationship_table'] . "', does not exists", "error");
+      $details['relationship_table'] . "', does not exist", "error");
     tripal_report_error('tcrel_form', TRIPAL_ERROR, "Cannot add relationship elements to the form.
       The relationship table, '%name', cannot be found.", ['%name' => $details['relationship_table']]);
     return;
@@ -167,7 +167,7 @@ function chado_add_node_form_relationships(&$form, &$form_state, $details) {
     $result = chado_select_record('cv', ['cv_id'], ['name' => $details['cv_name']]);
     if (count($result) == 0) {
       drupal_set_message("Cannot add relationship elements to the form. The CV name, '" .
-        $details['cv_name'] . "', does not exists", "error");
+        $details['cv_name'] . "', does not exist", "error");
       tripal_report_error('tcrel_form', TRIPAL_ERROR, "Cannot add relationship elements to the form.
         The CV named, '%name', cannot be found.", ['%name' => $details['cv_name']]);
       return;

+ 1 - 1
legacy/tripal_core/tripal_core.info

@@ -3,7 +3,7 @@ description = Provides support for all Tripal modules and includes the Tripal AP
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal
 
 stylesheets[all][] = theme/css/tripal_core.css

+ 1 - 1
legacy/tripal_cv/tripal_cv.info

@@ -3,7 +3,7 @@ description = Supports the Controlled Vocabulary (CV) tables of Chado by providi
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal/vocab
 
 dependencies[] = tripal_core

+ 1 - 1
legacy/tripal_db/tripal_db.info

@@ -3,7 +3,7 @@ description = Supports the database cross-reference tables of Chado by providing
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal/legacy/tripal_db
 
 dependencies[] = tripal_core

+ 1 - 1
legacy/tripal_feature/tripal_feature.info

@@ -3,7 +3,7 @@ description = Supports the sequence (feature) tables of Chado by providing pages
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 stylesheets[all][] = theme/css/tripal_feature.css
 scripts[]          = theme/js/tripal_feature.js

+ 1 - 1
legacy/tripal_featuremap/tripal_featuremap.info

@@ -3,7 +3,7 @@ description = Supports the map tables of Chado by providing pages for viewing an
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 1 - 1
legacy/tripal_genetic/tripal_genetic.info

@@ -3,7 +3,7 @@ description = Supports the genetic tables of Chado by providing pages for viewin
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 1 - 1
legacy/tripal_library/tripal_library.info

@@ -3,7 +3,7 @@ description = Supports the library tables of Chado by providing pages for viewin
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 1 - 1
legacy/tripal_natural_diversity/tripal_natural_diversity.info

@@ -3,7 +3,7 @@ description = Supports the natural diversity (ND) tables of Chado by providing p
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 1 - 1
legacy/tripal_organism/tripal_organism.info

@@ -3,7 +3,7 @@ description = Supports the organism tables of Chado by providing pages for viewi
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal/legacy/tripal_organism
 
 stylesheets[all][] = theme/css/tripal_organism.css

+ 1 - 1
legacy/tripal_phenotype/tripal_phenotype.info

@@ -3,7 +3,7 @@ description = Supports the phenotype tables of Chado by providing pages for view
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 2 - 2
legacy/tripal_phylogeny/tripal_phylogeny.drush.inc

@@ -184,7 +184,7 @@ function drush_tripal_phylogeny_trp_update_phylotree() {
       $options['phylotree_id'] = $phylotree[0]->phylotree_id;
     }
     else {
-      drush_print('A phylotree record with this name does not exists.');
+      drush_print('A phylotree record with this name does not exist.');
     }
   }
 
@@ -234,7 +234,7 @@ function drush_tripal_phylogeny_trp_delete_phylotree() {
       $options['phylotree_id'] = $phylotree[0]->phylotree_id;
     }
     else {
-      drush_print('A phylotree record with this name does not exists.');
+      drush_print('A phylotree record with this name does not exist.');
     }
   }
 

+ 1 - 1
legacy/tripal_phylogeny/tripal_phylogeny.info

@@ -3,7 +3,7 @@ description = Supports the phylogeny tables of Chado by providing pages for view
 core = 7.x
 project = tripal_phylogeny
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 dependencies[] = tripal_core
 dependencies[] = tripal_cv
 dependencies[] = tripal_db

+ 1 - 1
legacy/tripal_project/tripal_project.info

@@ -3,7 +3,7 @@ description = Supports the project tables of Chado by providing pages for viewin
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal/legacy/tripal_project
 
 dependencies[] = tripal_core

+ 1 - 1
legacy/tripal_pub/tripal_pub.info

@@ -3,7 +3,7 @@ description = Supports the pub (publication) tables of Chado by providing pages
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 stylesheets[all][] = theme/css/tripal_pub.css
 

+ 1 - 1
legacy/tripal_stock/tripal_stock.info

@@ -3,7 +3,7 @@ description = Supports the stock tables of Chado by providing pages for viewing,
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_core
 dependencies[] = tripal_chado_views

+ 1 - 1
legacy/tripal_views/tripal_views.info

@@ -3,4 +3,4 @@ description = Deprecated-- no longer provides any functionality. See Tripal Chad
 core = 7.x
 project = tripal
 package = Tripal v2 Legacy
-version = 7.x-3.1
+version = 7.x-3.5

+ 2 - 2
tripal/api/tripal.collections.api.inc

@@ -4,7 +4,7 @@
  * @file
  *
  * Provides the API for working with Data collections. This includes creation,
- * experiation, and retreival.
+ * expiration, and retrieval.
  */
 
 /**
@@ -26,7 +26,7 @@
  * Creates a collection of entities for a given user.
  *
  * Use this function if you want to create a new collection with an bundle.
- * Otherwise, a new colleciton can also be created by creating an new instance
+ * Otherwise, a new collection can also be created by creating an new instance
  * of a TripalEntityCollection object.
  *
  * @param  $details

+ 1 - 1
tripal/api/tripal.d3js.api.inc

@@ -24,7 +24,7 @@
 
 
 /**
- * Load D3.js releated javascripts for the current page.
+ * Load D3.js related javascripts for the current page.
  *
  * @ingroup tripal_d3js_api
  */

+ 25 - 19
tripal/api/tripal.entities.api.inc

@@ -215,7 +215,7 @@ function hook_tripal_default_title_format($bundle, $available_tokens) {
 function tripal_load_entity($entity_type, $ids = FALSE, $reset = FALSE,
                             $field_ids = [], $cache = TRUE) {
 
-  // The $conditions is deprecated in the funtion arguments of entity_load
+  // The $conditions is deprecated in the function arguments of entity_load
   // so it was removed from the parameters of this function as well. But
   // the load() function of the entity controller still expects it so set it
   // to an empty array.
@@ -286,7 +286,7 @@ function tripal_load_term_entity($values) {
 }
 
 /**
- * Retrieves a TripalVocab entity that maches the given arguments.
+ * Retrieves a TripalVocab entity that matches the given arguments.
  *
  * @param $values
  *   An associative array used to match a vocabulary.
@@ -331,7 +331,7 @@ function tripal_load_vocab_entity($values) {
  *     - name:  the bundle name (e.g. 'bio_data_234')
  *     - label: the bundle label (e.g. 'Organism')
  *     - term_id: the term ID to which the bundle belongs
- *     - accession: the full acccession for the bundle (e.g. OBI:0100026)
+ *     - accession: the full accession for the bundle (e.g. OBI:0100026)
  *
  * @return
  *   A TripalBundle entity object or NULL if not found.
@@ -565,7 +565,7 @@ function tripal_create_bundle($args, $job = NULL) {
     // Attache the bundle fields.
     tripal_create_bundle_fields($bundle, $term);
 
-    // Specifically commiting here since we have a fully featured bundle.
+    // Specifically committing here since we have a fully featured bundle.
     // Post-create hook implementations assume we have a
     // created bundle so we don't want to rollback if a
     // custom implementation causes an exception.
@@ -641,11 +641,15 @@ function tripal_tripal_cron_notification() {
         ['%bundle' => $bundle_name]);
       return FALSE;
     }
+    $term = tripal_load_term_entity(['term_id' => $bundle->term_id]);
+
     // Allow modules to add fields to the new bundle.
     $modules = module_implements('bundle_fields_info');
     foreach ($modules as $module) {
       $function = $module . '_bundle_fields_info';
-      $info = $function('TripalEntity', $bundle);
+      $entity_type = 'TripalEntity';
+      $info = $function($entity_type, $bundle);
+      drupal_alter('bundle_fields_info', $info, $bundle, $term);
       foreach ($info as $field_name => $details) {
 
         // If the field already exists then skip it.
@@ -670,7 +674,9 @@ function tripal_tripal_cron_notification() {
     $modules = module_implements('bundle_instances_info');
     foreach ($modules as $module) {
       $function = $module . '_bundle_instances_info';
-      $info = $function('TripalEntity', $bundle);
+      $entity_type = 'TripalEntity';
+      $info = $function($entity_type, $bundle);
+      drupal_alter('bundle_instances_info', $info, $bundle, $term);
       foreach ($info as $field_name => $details) {
 
         // If the field is already attached to this bundle then skip it.
@@ -822,7 +828,7 @@ function tripal_create_bundle_fields($bundle, $term) {
     // Make sure the term is not used for any other existing field instance.
     $skip = FALSE;
     foreach ($existing_instances as $existing_name => $existing_instance) {
-      // If this instance term is the same as this exsiting term and the
+      // If this instance term is the same as this existing term and the
       // instance name is not the same then we have a problem.
       $existing_term_id = $existing_instance['settings']['term_vocabulary'] . ':' . $existing_instance['settings']['term_accession'];
       $existing_field = field_info_field($existing_name);
@@ -838,7 +844,7 @@ function tripal_create_bundle_fields($bundle, $term) {
         $skip = TRUE;
       }
 
-      // If the instance term is the same as this exsting term but the storage
+      // If the instance term is the same as this existing term but the storage
       // types are different then we have a problem.
       $existing_storage = $existing_field['storage']['type'];
       $this_field_storage = $field_info[$details['field_name']]['storage']['type'];
@@ -985,7 +991,7 @@ function tripal_update_bundle_field($field_name, $field_info, $entity_type_name,
  * @param string $variable_name
  *   The name of the variable as in tripal_variables.name.
  * @param int $bundle_id
- *   The unique identfier for the bundle you want the value for.
+ *   The unique identifier for the bundle you want the value for.
  *
  * @return text
  *   The value of the specified variable for the specified bundle.
@@ -1023,7 +1029,7 @@ function tripal_get_bundle_variable($variable_name, $bundle_id, $default = FALSE
  * @param string $variable_name
  *   The name of the variable as in tripal_variables.name.
  * @param int $bundle_id
- *   The unique identfier for the bundle you want the value for.
+ *   The unique identifier for the bundle you want the value for.
  * @param $text $value
  *   The value of the variable for the given bundle.
  *
@@ -1314,7 +1320,7 @@ function _tripal_get_entity_tokens_for_elements($instance, $parent, $elements, &
  * @param TripalEntity $entity
  *   The entity with field values used to find values of tokens.
  * @param TripalBundle $bundle_entity
- *   The bundle enitity containing special values sometimes needed for token
+ *   The bundle entity containing special values sometimes needed for token
  *   replacement.
  *
  * @return
@@ -1402,7 +1408,7 @@ function tripal_replace_entity_tokens($string, &$entity, $bundle_entity = NULL)
       $value = $bundle_entity->id;
     }
     // The TripalBundle__bundle_id is a special token for substituting the
-    // entty id.
+    // entity id.
     elseif ($field_name === 'TripalEntity__entity_id') {
       // This token should be the id of the TripalEntity.
       $value = $entity->id;
@@ -1516,7 +1522,7 @@ function tripal_get_bundle_details($bundle_name) {
     'fields' => [],
   ];
 
-  // Iterate through each feild and provide a discription of it and
+  // Iterate through each field and provide a description of it and
   // it's sub elements.
   foreach ($instances as $instance) {
     // Skip deleted fields.
@@ -1545,7 +1551,7 @@ function tripal_get_bundle_details($bundle_name) {
       'required' => $instance['required'] ? TRUE : FALSE,
       'type' => 'xs:string',
       'readonly' => TRUE,
-      // The cardinatlity value always comes from the field.
+      // The cardinality value always comes from the field.
       'cardinality' => $field['cardinality'],
     ];
 
@@ -1584,7 +1590,7 @@ function tripal_get_bundle_details($bundle_name) {
 function _tripal_get_bundle_field_element_details($elements, &$field_details) {
   $field_details['elements'] = [];
   foreach ($elements as $element_key => $element_info) {
-    // Handle the entity element differnetly.
+    // Handle the entity element differently.
     if ($element_key == 'entity') {
       continue;
     }
@@ -1737,7 +1743,7 @@ function tripal_unpublish_orphans(int $bundle_id, TripalJob $job = NULL) {
  *   cleaned up.
  *
  * @return integer
- *   The number of entitites that were cleaned up.
+ *   The number of entities that were cleaned up.
  */
 function hook_bundle_delete_orphans(TripalBundle $bundle, array $ids, TripalJob $job = NULL) {
 
@@ -1746,7 +1752,7 @@ function hook_bundle_delete_orphans(TripalBundle $bundle, array $ids, TripalJob
 }
 
 /**
- * A hook for modules to report on oprhaned entities.
+ * A hook for modules to report on orphaned entities.
  *
  * An orphaned entity can occur if the module that created the entity
  * unknowingly lost its underlying record in its data store.  Such a case
@@ -1754,12 +1760,12 @@ function hook_bundle_delete_orphans(TripalBundle $bundle, array $ids, TripalJob
  * outside of the module's control. This function allows each module
  * to report if any orphans are missing for a given bundle type.
  *
- * @param TripalBunldle $bundle
+ * @param TripalBundle $bundle
  *   A TripalBundle object for the bundle that should be checked for
  *   orphaned entities.
  * @param bool $count
  *   TRUE if the function should return only the number of orphaned entities.
- *   FALSE if the function should return the list of orphned entities.
+ *   FALSE if the function should return the list of orphaned entities.
  * @param integer $offset
  *   For paging of entities set this to the offset within the total count.
  * @param integer $limit

+ 43 - 3
tripal/api/tripal.fields.api.inc

@@ -94,6 +94,26 @@ function hook_bundle_fields_info($entity_type, $bundle) {
 
 }
 
+/**
+ * Allows a module to adjust a field's info settings.
+ *
+ * Modules should only adjust the info array for fields that
+ * they manage and not fields that were created by other modules. For example,
+ * if a field corresponds to a column in a custom table of Chado, then the
+ * tripal_chado module will automatically create a field for it. This function
+ * can be used to override the default settings created by Chado.
+ *
+ * @param $info
+ *  The fields info array for all fields.
+ * @param $bundle
+ *  The bundle content type object that the field belongs to.
+ * @param $term
+ *  The bundle type term.
+ */
+function hook_bundle_fields_info_alter(&$info, $bundle, $term) {
+
+}
+
 /**
  * Allows a module to return the field instances of a bundle.
  *
@@ -108,6 +128,26 @@ function hook_bundle_instances_info($entity_type, $bundle) {
 
 }
 
+
+/**
+ * Allows a module to adjust field instances info settings.
+ *
+ * Modules should only adjust the info array for field instances that
+ * they manage and not fields that were created by other modules. For example,
+ * if a field corresponds to a column in a custom table of Chado, then the
+ * tripal_chado module will automatically create a field for it. This function
+ * can be used to override the default settings created by Chado.
+ *
+ * @param $info
+ *  The field instance info array for all fields.
+ * @param $bundle
+ *  The bundle content type object that the field belongs to.
+ * @param $term
+ *  The bundle type term.
+ */
+function hook_bundle_instances_info_alter(&$info, $bundle, $term) {
+
+}
 /**
  * Indicate if a field has an empty value.
  *
@@ -436,15 +476,15 @@ function tripal_load_include_downloader_class($class) {
  * A Drupal field attached to an entity may have multiple items (i.e. it has
  * a cardinality > 1).  Each of these items will always have a 'value' key that
  * contains the data for that field. However, fields can also have other keys
- * with their own values.  You can easily retreive the value of these keys
+ * with their own values.  You can easily retrieve the value of these keys
  * using this function.  What makes this function useful is that you can
  * provide a default value to use if the key has no value.  This is useful
  * when developing a TripalField::widgetForm function and you need to
- * retreive default values and you don't want to have to always check if the
+ * retrieve default values and you don't want to have to always check if the
  * value is set.
  *
  * @param $items
- *   The fields $items array. Compatbile with that returned by field_get_items.
+ *   The fields $items array. Compatible with that returned by field_get_items.
  * @param $delta
  *   The index of the item.
  * @parm $key

+ 1 - 1
tripal/api/tripal.files.api.inc

@@ -22,7 +22,7 @@
  * installation of the module in the .install file.  However this causes
  * permission problems if the module is installed via drush with a
  * user account that is not the same as the web user.  Therefore, this
- * function should not be called in a location accessiblve via a drush
+ * function should not be called in a location accessible via a drush
  * command.  The tripal_get_files_dir() and tripal_get_files_stream()
  * will automatically create the directory if it doesn't exist so there is
  * little need to call this function directly.

+ 1 - 1
tripal/api/tripal.importer.api.inc

@@ -134,7 +134,7 @@ function tripal_load_include_importer_class($class) {
  * Tripal provides the TripalImporter class to allow site developers to
  * create their own data loaders.  Site users can then use any data loader
  * implemented for the site by submitting the form that comes with the
- * TripalImporter impelmentation.  This function runs the importer using the
+ * TripalImporter implementation.  This function runs the importer using the
  * arguments provided by the user.
  *
  * @param $import_id

+ 8 - 8
tripal/api/tripal.jobs.api.inc

@@ -294,7 +294,7 @@ function tripal_rerun_job($job_id, $goto_jobs_page = TRUE) {
  *   The job_id of the job to be cancelled
  *
  * @return
- *   FALSE if the an error occured or the job could not be canceled, TRUE
+ *   FALSE if the an error occurred or the job could not be canceled, TRUE
  *   otherwise.
  *
  * @ingroup tripal_jobs_api
@@ -330,7 +330,7 @@ function tripal_cancel_job($job_id, $redirect = TRUE) {
  *
  * @param $job_id
  *   To launch a specific job provide the job id.  This option should be
- *   used sparingly as the jobs queue managment system should launch jobs
+ *   used sparingly as the jobs queue management system should launch jobs
  *   based on order and priority.  However there are times when a specific
  *   job needs to be launched and this argument will allow it.  Only jobs
  *   which have not been run previously will run.
@@ -390,7 +390,7 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
 
     $job_id = $jid->job_id;
 
-    // Create the Tripoaljob object.
+    // Create the Tripaljob object.
     $job = new TripalJob();
     $job->load($job_id);
 
@@ -462,7 +462,7 @@ function tripal_set_job_progress($job_id, $percentage) {
 }
 
 /**
- * Retrieves the current proress of a job.
+ * Retrieves the current progress of a job.
  *
  * @param $job_id
  *   The job_id to get the progress for
@@ -508,9 +508,9 @@ function tripal_get_job_progress($job_id) {
  *    - status: The status of the job: Waiting, Completed, Running or Cancelled.
  *    - submit_date:  The UNIX timestamp when the job was submitted.
  *    - start_time: The UNIX timestamp for when the job started running.
- *    - end_time: The UNIX timestampe when the job completed running.
- *    - error_msg: Any error message that occured during execution of the job.
- *    - prirotiy: The execution priority of the job (value between 1 and 10)
+ *    - end_time: The UNIX timestamp when the job completed running.
+ *    - error_msg: Any error message that occurred during execution of the job.
+ *    - priority: The execution priority of the job (value between 1 and 10)
  *
  * @ingroup tripal_jobs_api
  */
@@ -552,7 +552,7 @@ function tripal_get_active_jobs($modulename = NULL) {
  * Execute a specific Tripal Job.
  *
  * @param $job_id
- *   The job id to be exeuted.
+ *   The job id to be executed.
  * @param bool $redirect [optional]
  *   Whether to redirect to the job page or not.
  *

+ 2 - 2
tripal/api/tripal.notice.api.inc

@@ -17,7 +17,7 @@
  * @}
  */
 
-// Globals used by Tripals Error catching functions
+// Globals used by Tripal's Error catching functions
 // Should match those defined by watchdog
 define('TRIPAL_CRITICAL', 2);
 define('TRIPAL_ERROR', 3);
@@ -39,7 +39,7 @@ define('TRIPAL_DEBUG', 7);
  * will add backtrace information to the message.
  *
  * @param $type
- *   The catagory to which this message belongs. Can be any string, but the
+ *   The category to which this message belongs. Can be any string, but the
  *   general practice is to use the name of the module.
  * @param $severity
  *   The severity of the message; one of the following values:

+ 3 - 3
tripal/api/tripal.terms.api.inc

@@ -2,7 +2,7 @@
 /**
  * @file
  * Provides an application programming interface (API) for working with
- * controlled vocaublary terms.
+ * controlled vocabulary terms.
  */
 
 /**
@@ -10,7 +10,7 @@
  * @ingroup tripal_api
  * @{
  * Tripal provides an application programming interface (API) for working with
- * controlled vocaublary terms.  Tripal v3 is highly dependent on controlled
+ * controlled vocabulary terms.  Tripal v3 is highly dependent on controlled
  * vocabularies for identifying all content types and fields attached to those
  * content types.  However, Tripal v3 is also database agnostic. Therefore,
  * controlled vocabularies can be stored in any database back-end.  By default
@@ -66,7 +66,7 @@ function hook_vocab_storage_info() {
  *
  * Tripal allows for vocabularies to be stored separately from the biological
  * data. This hook allows the default term storage backend to provide an
- * approprite form for importing ontologies (either in OBO or OWL format).
+ * appropriate form for importing ontologies (either in OBO or OWL format).
  *
  * @param $form
  * @param $form_state

+ 4 - 4
tripal/api/tripal.upload.api.inc

@@ -86,7 +86,7 @@
  *
  *
  * 3) Files are uploaded automatically to Tripal.  Files are saved in the
- * Tripal user's directory.  You can retreive information about the
+ * Tripal user's directory.  You can retrieve information about the
  * file by querying for the file category for the current project.
  *
  * @code
@@ -104,12 +104,12 @@
 /**
  * Allows a module to interact with the Tripal file uploader during upload.
  *
- * This function is called prior to an 'action' aoccuring and allows the
+ * This function is called prior to an 'action' occurring and allows the
  * module that is responsible for the file upload to halt an upload if
  * needed.
  *
  * @param $action
- *   The current action that is being peformed during the upload process. The
+ *   The current action that is being performed during the upload process. The
  *   actions are:  'save', 'check' and 'merge'.
  * @param $details
  *   An associative array containing details about the upload process. Valid
@@ -133,7 +133,7 @@ function hook_file_upload_check($action, $details, &$message) {
       // Place code here when chunks are being saved.
       break;
     case 'check':
-      // Place code here when a chunck is being checked if the upload
+      // Place code here when a chunk is being checked if the upload
       // completed successfully.
       break;
     case 'merge':

+ 2 - 2
tripal/api/tripal.variables.api.inc

@@ -30,7 +30,7 @@
  *   The description for the variable
  *
  * @return
- *   A record object containg the variable that was added if successful.
+ *   A record object containing the variable that was added if successful.
  *
  * @ingroup tripal_variables_api
  */
@@ -71,7 +71,7 @@ function tripal_insert_variable($name, $description) {
  *   The name of the variable to retrieve
  *
  * @return
- *   A record object containg the variable.
+ *   A record object containing the variable.
  *
  * @ingroup tripal_variables_api
  */

+ 10 - 3
tripal/includes/tripal.admin_blocks.inc

@@ -23,10 +23,15 @@ function tripal_admin_notification_import_field($field_name_note, $bundle_id, $m
     drupal_goto("admin/dashboard");
     return FALSE;
   }
+  $term = tripal_load_term_entity(['term_id' => $bundle->term_id]);
 
+
+  $instance = NULL;
   if ($field_or_instance == 'field') {
     $function = $module . '_bundle_fields_info';
-    $info = $function('TripalEntity', $bundle);
+    $entity_type = 'TripalEntity';
+    $info = $function($entity_type, $bundle);
+    drupal_alter('bundle_fields_info', $info, $bundle, $term);
     foreach ($info as $field_name => $details) {
       $field = field_info_field($field_name);
       if ($details['field_name'] == $field_name_note) {
@@ -44,7 +49,9 @@ function tripal_admin_notification_import_field($field_name_note, $bundle_id, $m
   else {
     if ($field_or_instance == 'instance') {
       $function = $module . '_bundle_instances_info';
-      $info = $function('TripalEntity', $bundle);
+      $entity_type = 'TripalEntity';
+      $info = $function($entity_type, $bundle);
+      drupal_alter('bundle_instances_info', $info, $bundle, $term);
       foreach ($info as $field_name => $details) {
         if ($details['field_name'] == $field_name_note) {
           // Create the field instance.
@@ -68,7 +75,7 @@ function tripal_admin_notification_import_field($field_name_note, $bundle_id, $m
       ->execute();
   }
   else {
-    drupal_set_message(t("There was a problem creating: %field", ['%field' => $info[$field_name]['label']]));
+    drupal_set_message(t("There was a problem creating field."), 'error');
   }
 
   drupal_goto("admin/dashboard");

+ 24 - 0
tripal/tripal.drush.inc

@@ -32,6 +32,9 @@ function tripal_drush_help($command) {
     case 'trp-get-currjob':
       return dt('Returns details about the currently running tripal job including percent complete.');
       break;
+    case 'trp-version':
+      return dt('Returns the current version of Tripal that is installed.');
+      break;
     // Placeholders for unimplmeneted jobs
     case 'trp-show-job':
       break;
@@ -125,6 +128,13 @@ function tripal_drush_command() {
       'Standard example' => 'drush trp-set-permissions --user=administrator',
     ],
   ];
+  $items['trp-version'] = [
+    'description' => dt('Returns the current version of Tripal that is installed.'),
+    'arguments' => [],
+    'examples' => [
+      'Standard usage' => 'drush trp-version',
+    ],
+  ];
   return $items;
 }
 
@@ -391,3 +401,17 @@ function drush_tripal_trp_set_permissions() {
   drush_print(dt(""));
   drush_print(dt("Permissions is now complete."));
 }
+
+/**
+ * Returns the current version of Tripal
+ * 
+ * Executed when 'drush trp-version' is called.
+ * 
+ * @ingroup tripal_drush
+ *
+ * @return string
+ */
+function drush_tripal_trp_version() {
+  $version = system_get_info('module', 'tripal');
+  drush_print("Tripal version: " . $version['version']);
+}

+ 1 - 1
tripal/tripal.info

@@ -3,7 +3,7 @@ description = Tripal is an toolkit to facilitate construction of online genomic,
 core = 7.x
 project = tripal
 package = Tripal
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal
 
 stylesheets[all][] = theme/css/tripal.css

+ 13 - 2
tripal/tripal.module

@@ -812,7 +812,7 @@ function tripal_theme($existing, $type, $theme, $path) {
     'tripal_add_list' => array(
       'variables' => array('content' => NULL),
     ),
-    // Themeing for all fields.
+    // Theming for all fields.
     'tripal_field_default' => array(
       'render element' => 'element',
       'file' => 'includes/tripal.fields.inc',
@@ -1653,4 +1653,15 @@ function tripal_job_describe_args($callback, $args) {
     return $ret;
   }
   return $args;
-}
+}
+
+/**
+ * Returns the current version of Tripal, according to the tripal.info file
+ * 
+ * @return string
+ *   The version string of Tripal. Ex. 7.x-3.1
+ */
+function tripal_version() {
+  $version = system_get_info('module', 'tripal');
+  return $version['version'];
+}

+ 1 - 1
tripal_bulk_loader/tripal_bulk_loader.info

@@ -3,6 +3,6 @@ description = Supports the construction of templates for customizable uploading
 core = 7.x
 project = tripal
 package = Tripal
-version = 7.x-3.1
+version = 7.x-3.5
 
 dependencies[] = tripal_chado_views

+ 2 - 2
tripal_chado/api/modules/tripal_chado.cv.api.inc

@@ -702,7 +702,7 @@ function chado_insert_cv($name, $definition) {
   $sel_values = ['name' => $name];
   $results = chado_select_record('cv', ['*'], $sel_values);
 
-  // If it does not exists then add it.
+  // If it does not exist then add it.
   if (count($results) == 0) {
     $success = chado_insert_record('cv', $ins_values);
     if (!$success) {
@@ -963,7 +963,7 @@ function chado_insert_cvterm($term, $options = []) {
         'is_for_definition' => 1,
       ];
       $result = chado_select_record('cvterm_dbxref', ['*'], $values);
-      // if the cvterm_dbxref record does not exists then add it
+      // if the cvterm_dbxref record does not exist then add it
       if (count($result) == 0) {
         $options = [
           'return_record' => FALSE,

+ 1 - 1
tripal_chado/api/modules/tripal_chado.db.api.inc

@@ -375,7 +375,7 @@ function chado_insert_db($values, $options = []) {
   $sel_values = ['name' => $dbname];
   $result = chado_select_record('db', ['*'], $sel_values);
 
-  // If it does not exists then add it.
+  // If it does not exist then add it.
   if (count($result) == 0) {
     $ins_options = ['statement_name' => 'ins_db_nadeurur'];
     $success = chado_insert_record('db', $ins_values, $ins_options);

+ 37 - 18
tripal_chado/api/modules/tripal_chado.organism.api.inc

@@ -1,7 +1,7 @@
 <?php
 /**
  * @file
- * Provides API functions specifically for managing feature
+ * Provides API functions specificially for managing feature
  * records in Chado.
  */
 
@@ -9,7 +9,7 @@
  * @defgroup tripal_organism_api Chado Organism
  * @ingroup tripal_chado_api
  * @{
- * Provides API functions specifically for managing organism
+ * Provides API functions specificially for managing organism
  * records in Chado.
  * @}
  */
@@ -19,7 +19,7 @@
  *
  * @param $identifier
  *   An array with the key stating what the identifier is. Supported keys (only
- *   on of the following unique keys is required):
+ *   one of the following unique keys is required):
  *    - organism_id: the chado organism.organism_id primary key.
  *    - genus & species: the chado organism.genus field & organism.species
  *   field. There are also some specially handled keys. They are:
@@ -48,7 +48,7 @@ function chado_get_organism($identifiers, $options = []) {
 
   // Set Defaults.
   if (!isset($options['include_fk'])) {
-    // Tells chado_generate_var not to follow any foreign keys.
+    // Tells chado_generate_var to not follow any foreign keys.
     $options['include_fk'] = [];
   }
 
@@ -89,7 +89,7 @@ function chado_get_organism($identifiers, $options = []) {
   }
 
   // Else we have a simple case and we can just use chado_generate_var to get 
-  // the analysis.
+  // the organism.
   else {
 
     // Try to get the organism
@@ -118,7 +118,7 @@ function chado_get_organism($identifiers, $options = []) {
     tripal_report_error(
       'tripal_organism_api',
       TRIPAL_ERROR,
-      "chado_get_organism: chado_generate_var() failed to return a organism based on the identifiers
+      "chado_get_organism: chado_generate_var() failed to return an organism based on the identifiers
         you passed in. You should check that your identifiers are correct, as well as, look
         for a chado_generate_var error for additional clues. You passed in %identifier.",
       [
@@ -150,7 +150,7 @@ function chado_get_organism_scientific_name($organism) {
   // For Chado v1.3 we have a type_id and infraspecific name.
   if (property_exists($organism, 'type_id')) {
     $rank = '';
-    // For organism objects crated using chado_generate_var.
+    // For organism objects created using chado_generate_var.
     if (is_object($organism->type_id)) {
       if ($organism->type_id) {
         $rank = $organism->type_id->name;
@@ -165,13 +165,14 @@ function chado_get_organism_scientific_name($organism) {
 
     if ($rank) {
       $rank = chado_abbreviate_infraspecific_rank($rank);
-      $name .= ' ' . $rank . ' ' . $organism->infraspecific_name;
-    }
-    else {
-      if ($organism->infraspecific_name) {
-        $name .= ' ' . $organism->infraspecific_name;
+      // rank will now be an empty string if it had been the "no_rank" cv term
+      if ($rank) {
+        $name .= ' ' . $rank;
       }
     }
+    if ($organism->infraspecific_name) {
+      $name .= ' ' . $organism->infraspecific_name;
+    }
   }
   return $name;
 }
@@ -201,21 +202,33 @@ function chado_get_organism_select_options($syncd_only = TRUE) {
         INNER JOIN {organism} O ON O.organism_id = CO.organism_id
       ORDER BY O.genus, O.species
     ";
+    // if present in this site's version of chado, include infraspecific nomenclature in sorting
+    if (chado_column_exists('organism', 'infraspecific_name')) {
+      $sql .= ", REPLACE ((SELECT name FROM {cvterm} CVT WHERE CVT.cvterm_id = O.type_id
+                AND CVT.cv_id = (SELECT cv_id FROM {cv} WHERE name='taxonomic_rank')), 'no_rank', ''),
+                O.infraspecific_name";
+    }
     $orgs = chado_query($sql);
 
     // Iterate through the organisms and build an array of those that are synced.
     foreach ($orgs as $org) {
-      $org_list[$org->organism_id] = $org->genus . ' ' . $org->species;
+      $org_list[$org->organism_id] = chado_get_organism_scientific_name($org);
     }
   }
   else {
     // use this SQL statement for getting the organisms
     $csql = "SELECT * FROM {organism} ORDER BY genus, species";
+    // if present in this site's version of chado, include infraspecific nomenclature in sorting
+    if (chado_column_exists('organism', 'infraspecific_name')) {
+      $csql .= ", REPLACE ((SELECT name FROM {cvterm} CVT WHERE CVT.cvterm_id = type_id" .
+               " AND CVT.cv_id = (SELECT cv_id FROM {cv} WHERE name='taxonomic_rank')), 'no_rank', '')," .
+               " infraspecific_name";
+    }
     $orgs = chado_query($csql);
 
     // Iterate through the organisms and build an array of those that are synced.
     foreach ($orgs as $org) {
-      $org_list[$org->organism_id] = $org->genus . ' ' . $org->species;
+      $org_list[$org->organism_id] = chado_get_organism_scientific_name($org);
     }
   }
   return $org_list;
@@ -245,7 +258,7 @@ function chado_get_organism_image_url($organism) {
 
   // Look in the file_usage table of Drupal for the image file. This
   // is the current way for handling uploaded images. It allows the file to
-  // keep it's proper name and extension.
+  // keep its proper name and extension.
   $fid = db_select('file_usage', 'fu')
     ->fields('fu', ['fid'])
     ->condition('module', 'tripal_organism')
@@ -270,7 +283,7 @@ function chado_get_organism_image_url($organism) {
     return $url;
   }
 
-  // If we don't find the file using the genus ans species then look for the
+  // If we don't find the file using the genus and species then look for the
   // image with the node ID in the name. This method was used for Tripal 1.1
   // and 2.x-alpha version.
   $image_name = $nid . ".jpg";
@@ -310,8 +323,14 @@ function chado_autocomplete_organism($text) {
     $sql .= "AND lower(species) like lower(:species) ";
     $args[':species'] = $species . '%';
   }
-  $sql .= "ORDER BY genus, species ";
-  $sql .= "LIMIT 25 OFFSET 0 ";
+  $sql .= "ORDER BY genus, species";
+  // if present in this site's version of chado, include infraspecific nomenclature in sorting
+  if (chado_column_exists('organism', 'infraspecific_name')) {
+    $sql .= ", REPLACE ((SELECT name FROM {cvterm} CVT WHERE CVT.cvterm_id = type_id" .
+            " AND CVT.cv_id = (SELECT cv_id FROM {cv} WHERE name='taxonomic_rank')), 'no_rank', '')," .
+            " infraspecific_name";
+  }
+  $sql .= " LIMIT 25 OFFSET 0";
   $results = chado_query($sql, $args);
   $items = [['args' => [$sql => $args]]];
   foreach ($results as $organism) {

+ 1 - 1
tripal_chado/api/modules/tripal_chado.phylotree.api.inc

@@ -116,7 +116,7 @@ function chado_validate_phylotree($val_type, &$options, &$errors, &$warnings) {
     // If this is a numeric Drupal file then all is good, no need to check.
     if (!is_numeric($options['tree_file'])) {
       if (!file_exists($options['tree_file'])) {
-        $errors['tree_file'] = t('The file provided does not exists.');
+        $errors['tree_file'] = t('The file provided does not exist.');
         return FALSE;
       }
     }

+ 59 - 59
tripal_chado/api/tripal_chado.variables.api.inc

@@ -119,13 +119,13 @@
  *     property table (e.g. featureprop) and you want the CV and accession
  *     but do not want the DB the following array would work:
  *
- *        $table_options =  array(
- *          'include_fk' => array(
- *            'type_id' => array(
+ *        $table_options =  [
+ *          'include_fk' => [
+ *            'type_id' => [
  *              'cv_id' => 1,
  *              'dbxref_id' => 1,
- *            )
- *          )
+ *            ]
+ *          ]
  *        );
  *
  *     The above array will expand the 'type_id' of the property table but only
@@ -198,19 +198,19 @@ function chado_generate_var($table, $values, $base_options = []) {
 
   // This allows modules to specify that some fields should be excluded by default
   // For example, tripal core provides a tripal_chado_exclude_field_from_feature_by_default()
-  // which says that we usually don't want to include the residues field by 
+  // which says that we usually don't want to include the residues field by
   // default since it can be very large and cause performance issues.
 
-  // If a field is excluded by default it can always be expanded at a later 
-  // point by calling chado_expand_var($chado_var, 'field', 
+  // If a field is excluded by default it can always be expanded at a later
+  // point by calling chado_expand_var($chado_var, 'field',
   // <field name as shown in expandable_fields array>);
 
   // First get an array of all the fields to be removed for the current table
-  // module_invoke_all() is drupal's way of invoking all implementations of the 
+  // module_invoke_all() is drupal's way of invoking all implementations of the
   // specified hook and merging all of the results.
 
   // $fields_to_remove should be an array with the keys matching field names
-  // and the values being strings to be executed using php_eval() to determine 
+  // and the values being strings to be executed using php_eval() to determine
   // whether to exclude the field (evaluates to TRUE) or not (evaluates to FALSE)
   $fields_to_remove = module_invoke_all('exclude_field_from_' . $table . '_by_default');
 
@@ -226,7 +226,7 @@ function chado_generate_var($table, $values, $base_options = []) {
     }
 
     // If criteria then remove from query
-    // @coder-ignore: only module designers can populate $criteria -not a 
+    // @coder-ignore: only module designers can populate $criteria -not a
     // security risk.
     $success = php_eval('<?php return ' . $criteria . '; ?>');
     if ($success) {
@@ -239,35 +239,35 @@ function chado_generate_var($table, $values, $base_options = []) {
   // Get fields to be removed by type................................
   // This gets all implementations of hook_exclude_type_by_default().
 
-  // This allows modules to specify that some types of fields should be excluded 
-  // by default For example, tripal core provides a 
-  // tripal_chado_exclude_type_by_default() which says that text fields are 
+  // This allows modules to specify that some types of fields should be excluded
+  // by default For example, tripal core provides a
+  // tripal_chado_exclude_type_by_default() which says that text fields are
   // often very large and if they are longer than 250 characters then
   // we want to exclude them by default
 
-  // If a field is excluded by default it can always be expanded at a later 
-  // point by calling chado_expand_var($chado_var, 'field', 
+  // If a field is excluded by default it can always be expanded at a later
+  // point by calling chado_expand_var($chado_var, 'field',
   //<field name as shown in expandable_fields array>);
 
   // First get an array of all the types of fields to be removed for the current
-  // table module_invoke_all() is drupal's way of invoking all implementations 
+  // table module_invoke_all() is drupal's way of invoking all implementations
   // of the specified hook and merging all of the results.
 
   // $types_to_remove should be an array with the keys matching field names
-  // and the values being strings to be executed using php_eval() to determine 
+  // and the values being strings to be executed using php_eval() to determine
   // whether to exclude the field (evaluates to TRUE) or not (evaluates to FALSE)
   // (ie: array('text' => 'strlen("<field_value> ") > 100');
   $types_to_remove = module_invoke_all('exclude_type_by_default');
 
   // Get a list of all the types of fields
-  // the key is the type of field and the value is an array of fields of this 
+  // the key is the type of field and the value is an array of fields of this
   // type.
   $field_types = [];
   foreach ($table_desc['fields'] as $field_name => $field_array) {
     $field_types[$field_array['type']][] = $field_name;
   }
 
-  // We want to use the types to remove in conjunction with our table field 
+  // We want to use the types to remove in conjunction with our table field
   // descriptions to determine which fields might need to be removed.
   foreach ($types_to_remove as $field_type => $criteria) {
 
@@ -286,8 +286,8 @@ function chado_generate_var($table, $values, $base_options = []) {
         }
 
         // If criteria then remove from query
-        // (as long as <field_value> is not needed for the criteria to be 
-        // evaluated) @coder-ignore: only module designers can populate 
+        // (as long as <field_value> is not needed for the criteria to be
+        // evaluated) @coder-ignore: only module designers can populate
         //$criteria -not a security risk.
         $success = php_eval('<?php return ' . $criteria . '; ?>');
         if ($success) {
@@ -316,7 +316,7 @@ function chado_generate_var($table, $values, $base_options = []) {
 
       // For Tripal v2 compatibility
       // check if the current table maps to a node type-------------------------
-      // If this table is connected to a node there will be a chado_tablename 
+      // If this table is connected to a node there will be a chado_tablename
       // table in drupal.
       $base_tables = chado_get_base_tables();
       if (module_exists('tripal_core') and db_table_exists('chado_' . $table)) {
@@ -344,10 +344,10 @@ function chado_generate_var($table, $values, $base_options = []) {
 
       // Remove any fields where criteria needs to be evalulated----------------
       // The fields to be removed can be populated by implementing either
-      // hook_exclude_field_from_<table>_by_default() where <table> is the 
-      // current table OR hook_exclude_type_by_default() where there are fields 
-      // of the specified type in the current table It only reaches this point 
-      // if the criteria specified for whether or not to exclude the field 
+      // hook_exclude_field_from_<table>_by_default() where <table> is the
+      // current table OR hook_exclude_type_by_default() where there are fields
+      // of the specified type in the current table It only reaches this point
+      // if the criteria specified for whether or not to exclude the field
       // includes <field_value> which means it has to be evaluated after
       // the query has been executed.
       foreach ($fields_to_remove as $field_name => $criteria) {
@@ -358,7 +358,7 @@ function chado_generate_var($table, $values, $base_options = []) {
           break;
         }
 
-        // Replace <field_value> with the actual value of the field from the 
+        // Replace <field_value> with the actual value of the field from the
         // query.
         $field_name_safe = preg_replace('/\'|"|\\\/', '\\1', $object->{$field_name});
         $criteria = preg_replace('/<field_value>/', $field_name_safe, $criteria);
@@ -379,22 +379,22 @@ function chado_generate_var($table, $values, $base_options = []) {
           $foreign_table = $foreign_key_array['table'];
           foreach ($foreign_key_array['columns'] as $foreign_key => $primary_key) {
 
-            // Note: Foreign key is the field in the current table whereas 
-            // primary_key is the field in the table referenced by the foreign 
+            // Note: Foreign key is the field in the current table whereas
+            // primary_key is the field in the table referenced by the foreign
             // key, don't do anything if the foreign key is empty
             if (empty($object->{$foreign_key})) {
               continue;
             }
 
             if (is_array($include_fk)) {
-              // Don't recurse if the callee has supplied an $fk_include list 
+              // Don't recurse if the callee has supplied an $fk_include list
               // and this FK table is not in the list.
               if (is_array($include_fk) and !array_key_exists($foreign_key, $include_fk)) {
                 $object->expandable_foreign_keys[] = $table . '.' . $foreign_key . ' => ' . $foreign_table;
                 continue;
               }
             }
-            // If we have the option but it is not an array then we don't 
+            // If we have the option but it is not an array then we don't
             // recurse any further.
             if ($include_fk === TRUE) {
               $object->expandable_foreign_keys[] = $table . '.' . $foreign_key . ' => ' . $foreign_table;
@@ -713,8 +713,8 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           // Get the value of the foreign key from the object
           $field_value = $object->{$field_name};
 
-          // Get the name of the field in the foreign table using the table 
-          // description For example, with the 
+          // Get the name of the field in the foreign table using the table
+          // description For example, with the
           // feature.type_id => cvterm.cvterm_id we need cvterm_id
           $foreign_field_name = FALSE;
           foreach ($table_desc['foreign keys'][$foreign_table]['columns'] as $left => $right) {
@@ -729,7 +729,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
 
             // Generate a chado variable of the foreign key
             // For example, if the foreign key to expand is feature.type_id
-            // then we want to generate a chado cvterm variable that matches the 
+            // then we want to generate a chado cvterm variable that matches the
             // feature.type_id.
             $foreign_var = chado_generate_var(
               $foreign_table, // thus in the example above, generate a cvterm var
@@ -740,7 +740,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
             // Check that the foreign object was returned.
             if ($foreign_var) {
 
-              // It was so now we can add this chado variable to our current 
+              // It was so now we can add this chado variable to our current
               // object in place of the key value.
               $object->{$field_name} = $foreign_var;
               $object->expanded = $to_expand;
@@ -778,7 +778,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
 
         }
       }
-      // Otherwise we weren't able to extract the parts of the foreign key to 
+      // Otherwise we weren't able to extract the parts of the foreign key to
       // expand thus we will warn the administrator.
       else {
         tripal_report_error('tripal_chado', TRIPAL_ERROR,
@@ -791,13 +791,13 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
       $foreign_table = $to_expand;
 
       // BASE CASE: don't expand the table it already is expanded
-      if (array_key_exists($foreign_table, $object)) {
+      if (property_exists($object, $foreign_table)) {
         return $object;
       }
       $foreign_table_desc = chado_get_schema($foreign_table);
 
-      // If we don't get a foreign_table (which could happen of a custom 
-      // table is not correctly defined or the table name is mispelled then we 
+      // If we don't get a foreign_table (which could happen of a custom
+      // table is not correctly defined or the table name is mispelled then we
       // should return gracefully.
       if (!is_array($foreign_table_desc)) {
         return $object;
@@ -837,16 +837,16 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
             $filter_criteria = [$left => $object->{$right}];
           }
 
-          // Generate a new object for this table using the FK values in the 
+          // Generate a new object for this table using the FK values in the
           // base table.
           $new_options = $table_options;
           $foreign_object = chado_generate_var($foreign_table, $filter_criteria, $new_options);
 
-          // If the generation of the object was successful, update the base 
+          // If the generation of the object was successful, update the base
           // object to include it.
           if ($foreign_object) {
             // In the case where the foreign key relationship exists more
-            // than once with the same table we want to alter the array 
+            // than once with the same table we want to alter the array
             // structure to include the field name.
             if (count($foreign_table_desc['foreign keys'][$base_table]['columns']) > 1) {
               if (!property_exists($object, $foreign_table)) {
@@ -867,7 +867,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           // If the object returned is NULL then handle that.
           else {
             // In the case where the foreign key relationship exists more
-            // than once with the same table we want to alter the array 
+            // than once with the same table we want to alter the array
             // structure to include the field name.
             if (count($foreign_table_desc['foreign keys'][$base_table]['columns']) > 1) {
               if (!property_exists($object, $foreign_table)) {
@@ -881,18 +881,18 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           }
         }
       }
-      // RECURSIVE CASE: if the table is not connected directly to the current 
-      // base table through a foreign key relationship, then maybe it has a 
+      // RECURSIVE CASE: if the table is not connected directly to the current
+      // base table through a foreign key relationship, then maybe it has a
       // relationship to one of the nested objects.
       else {
 
         // We need to recurse -the table has a relationship to one of the nested
-        // objects. We assume it's a nested object if the value of the field is 
+        // objects. We assume it's a nested object if the value of the field is
         // an object.
         $did_expansion = 0;
         foreach ((array) $object as $field_name => $field_value) {
 
-          // CASE #1: This field is an already expanded foreign key and the 
+          // CASE #1: This field is an already expanded foreign key and the
           // table to be expanded is in the table referenced by the foreign key.
 
           // First of all it can only be expanded if it's an object
@@ -902,10 +902,10 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           }
 
           // CASE #2: This field is an already expanded object (ie: the field is
-          // actually the expanded table name) and the table to be expanded is 
+          // actually the expanded table name) and the table to be expanded is
           // related to it.
 
-          // Check to see if the $field_name is a valid chado table, we don't 
+          // Check to see if the $field_name is a valid chado table, we don't
           // need to call chado_expand_var on fields that aren't tables.
           $check = chado_get_schema($field_name);
           if ($check) {
@@ -914,7 +914,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           }
         }
 
-        // If we did not expand this table we should return a message that the 
+        // If we did not expand this table we should return a message that the
         // foreign tabl could not be expanded.
         if (!$did_expansion) {
           tripal_report_error('tripal_chado', TRIPAL_ERROR, 'chado_expand_var: Could not expand %table. ' .
@@ -929,7 +929,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
 
     case "node": //-------------------------------------------------------------
 
-      // BASE CASE: if the node to be expanded is for our base table, then just 
+      // BASE CASE: if the node to be expanded is for our base table, then just
       // expand it.
       if ($object->tablename == $to_expand) {
 
@@ -940,7 +940,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
         }
         // Try to get the nid based on the tablename.
         else {
-          // Invoke all hook_node_info to avoid hard-coding the chado_$table 
+          // Invoke all hook_node_info to avoid hard-coding the chado_$table
           // assumption..
           foreach (module_invoke_all('node_info') as $node_info) {
             if (array_key_exists('chado_node_api', $node_info)) {
@@ -973,7 +973,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           unset($object->expandable_nodes);
 
           // The node becomes the base object with the obejct added to it.
-          // For example, we may start with a feature object with a name, 
+          // For example, we may start with a feature object with a name,
           // uniquename , type, etc. After expanding we will return the node and
           // at $node->feature you will find the original object.
           $node->{$base_table} = $object;
@@ -993,7 +993,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
           }
         } //End of if node.
       }
-      // RECURSIVE CASE: check to see if the node to be expanded associates with 
+      // RECURSIVE CASE: check to see if the node to be expanded associates with
       // a chado table within one of the nested objects.
       else {
 
@@ -1019,7 +1019,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
   }
 
   // Move expandable arrays downwards -------------------------------
-  // If the type was either table or foreign key then a new chado variable was 
+  // If the type was either table or foreign key then a new chado variable was
   // generated this variable will have it's own expandable array's which need to
   // be moved down and merged with the base objects expandable arrays.
 
@@ -1054,7 +1054,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
         // Move expandable foreign keys downwards.
         if (isset($field_value->expandable_foreign_keys) and is_array($field_value->expandable_foreign_keys)) {
 
-          // If the current object has it's own expandable foreign keys then 
+          // If the current object has it's own expandable foreign keys then
           // merge them.
           if (isset($object->expandable_foreign_keys)) {
             $object->expandable_foreign_keys = array_merge(
@@ -1116,7 +1116,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
   // This tells us what we have expanded (ie: that we succeeded)
   // and is needed to remove the entry from the expandable array.
 
-  // If there is no expanded field in the current object then check any of the 
+  // If there is no expanded field in the current object then check any of the
   // nested objects and move it down.
   if (!property_exists($object, 'expanded')) {
 
@@ -1139,7 +1139,7 @@ function chado_expand_var($object, $type, $to_expand, $table_options = []) {
   // We check again because it might have been moved downwards above.
   if (property_exists($object, 'expanded')) {
 
-    // If so, then remove the expanded identifier from the correct expandable 
+    // If so, then remove the expanded identifier from the correct expandable
     // array..
     $expandable_name = 'expandable_' . $type . 's';
     if (property_exists($object, $expandable_name) and $object->{$expandable_name}) {

+ 6 - 1
tripal_chado/includes/TripalFields/chado_linker__prop/chado_linker__prop_formatter.inc

@@ -27,7 +27,12 @@ class chado_linker__prop_formatter extends ChadoFieldFormatter {
 
     $list = [];
     foreach ($items as $index => $item) {
-      $list[$index] = $item['value'];
+      $value = $item['value'];
+      // any URLs are made into clickable links
+      if ( preg_match('/^https?:/i', $value) ) {
+        $value = l($value, $value, ['external' => 'TRUE', 'attributes' => ['target' => '_blank']]);
+      }
+      $list[$index] = $value;
     }
 
     // Also need to make sure to not return markup if the field is empty.

+ 1 - 1
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_formatter.inc

@@ -89,7 +89,7 @@ class sbo__relationship_formatter extends ChadoFieldFormatter {
 
       // Add bold font to the object and subject names.
       // @todo add back in bolding...
-      // @todo Fix Current Bug: if type name is in the object name, wierd bolding happens.
+      // @todo Fix Current Bug: if type name is in the object name, weird bolding happens.
       // $phrase = preg_replace("/$subject_type/", "<b>$subject_type</b>", $phrase);
       // $phrase = preg_replace("/$object_type/", "<b>$object_type</b>", $phrase);
 

+ 91 - 28
tripal_chado/includes/TripalFields/sio__references/sio__references.inc

@@ -41,6 +41,8 @@ class sio__references extends ChadoField {
     'chado_column' => 'pub_id',
     // The base table.
     'base_table' => 'pub',
+    // The number of items to show on a page.
+    'items_per_page' => 10,
   ];
 
   // The default widget for this field.
@@ -97,75 +99,136 @@ class sio__references extends ChadoField {
     foreach ($chado_tables as $chado_table) {
       $matches = [];
       if (preg_match('/^(.+?)_pub$/', $chado_table, $matches)) {
+
         $reference_table = $matches[1];
 
-        // Find the base table this links to and get the fk columns that map it.
+        // Get the schema for the pub linker table table.
         $schema = chado_get_schema($chado_table);
+
+        // Skip tables that don't have a foreign key definition.
+        if (!array_key_exists('foreign keys', $schema)) {
+          continue;
+        }
+
+        // Get information about the linking table.
         $fkeys = $schema['foreign keys'];
+        $fkleft = NULL;
+        $fkright = NULL;
+        $islinked = FALSE;
         foreach ($fkeys as $linked_table => $fk_details) {
+          if ($linked_table == 'pub') {
+            $islinked = TRUE;
+          }
           if ($linked_table == $reference_table) {
             $fkleft = array_keys($fk_details['columns'])[0];
             $fkright = $fk_details['columns'][$fkleft];
           }
+        }
+        // If this table doesn't have an FK to a reference table
+        // then it's just a table with a _pub in the name.
+        if (!$fkleft) {
+          continue;
+        }
+        // If this table does not have a FK to the pub table then
+        // we don't want to search it.
+        if (!$islinked) {
+          continue;
+        }
+
 
+        // Build the SQL to find records assocaited with this publication.
+        $ref_schema = chado_get_schema($reference_table);
+        $ref_pkey = $ref_schema['primary key'][0];
+        $select = "SELECT REF.* ";
+        $from = "FROM {" . $chado_table . "} LINK
+            INNER JOIN {" . $reference_table . "} REF on LINK.$fkleft = REF.$fkright
+        ";
+        if (array_key_exists('type_id', $ref_schema['fields'])) {
+          $select .= ", CVT.name as type_name";
+          $from .= "INNER JOIN {cvterm} CVT on REF.type_id = CVT.cvterm_id ";
         }
+
+        // Get the mapping of the refrence table to a CV term in case the
+        // records in the table don't have a type_id.
+        $ref_mapping = db_select('chado_cvterm_mapping', 'CVM')
+          ->fields('CVM')
+          ->condition('chado_table', $reference_table)
+          ->execute()
+          ->fetchObject();
+        $ref_type = NULL;
+        if ($ref_mapping) {
+          $ref_type = chado_get_cvterm(['cvterm_id' => $ref_mapping->cvterm_id]);
+        }
+
+        // Are the records in this table associated with a content type?
+        // if so, we want to get those types so we can find the entity ID.
+        $bundles = db_select('chado_bundle', 'CB')
+          ->fields('CB', ['bundle_id'])
+          ->condition('CB.data_table', $reference_table)
+          ->execute();
+        $entity_sql = '';
+        while ($bundle_id = $bundles->fetchField()) {
+          $entity_sql .= "SELECT entity_id FROM [chado_bio_data_" . $bundle_id . "] CBD" . $bundle_id . " WHERE record_id = LINK.$ref_pkey UNION ";
+        }
+        if (!empty($entity_sql)) {
+          $entity_sql = rtrim($entity_sql, " UNION ");
+          $entity_sql = ", (" . $entity_sql . " LIMIT 1) as entity_id";
+        }
+
+
         // Iterate through all of the records in the linker table that
         // match the given pub ID.
-        $records = chado_generate_var($chado_table, ['pub_id' => $chado_record->pub_id], ['return_array' => TRUE]);
-        foreach ($records as $record) {
+        $sql = "$select $entity_sql $from WHERE LINK.pub_id = :pub_id";
+        $args = [':pub_id' => $chado_record->pub_id];
+        $records = chado_query($sql, $args);
+        while($record = $records->fetchObject()) {
+        //foreach ($records as $record) {
+
           // We want to add a 'type' and 'name' element to the values (at a
           // minimum) for each of the records.  Unfortunately, every base table
-          // is different and their may not be an easy to identify name,
+          // is different and there may not be an easy to identify name,
           // so... we'll do the best we can.
           $entity->{$field_name}['und'][$delta]['value'] = [];
 
           // First get the type of record.
-          if (property_exists($record->$fkleft, 'type_id') and $record->$fkleft->type_id) {
-            $entity->{$field_name}['und'][$delta]['value']['rdfs:type'] = $record->$fkleft->type_id->name;
+          if (property_exists($record, 'type_name')) {
+            $entity->{$field_name}['und'][$delta]['value']['rdfs:type'] = $record->type_name;
           }
           else {
-            // If there's not a type_id column then see if the table is mapped
-            // to a type.
-            $mapping = db_select('chado_cvterm_mapping', 'CVM')
-              ->fields('CVM')
-              ->condition('chado_table', $reference_table)
-              ->execute()
-              ->fetchObject();
-            if ($mapping) {
-              $cvterm = chado_get_cvterm(['cvterm_id' => $mapping->cvterm_id]);
-              $entity->{$field_name}['und'][$delta]['value']['rdfs:type'] = $cvterm->name;
+            if ($ref_type) {
+              $entity->{$field_name}['und'][$delta]['value']['rdfs:type'] = $ref_type->name;
             }
           }
 
           // Add in the name and uniquename (identifier) if those fields exist.
-          if (property_exists($record->$fkleft, 'name')) {
-            $entity->{$field_name}['und'][$delta]['value']['schema:name'] = $record->$fkleft->name;
+          if (property_exists($record, 'name')) {
+            $entity->{$field_name}['und'][$delta]['value']['schema:name'] = $record->name;
           }
-          if (property_exists($record->$fkleft, 'uniquename')) {
-            $entity->{$field_name}['und'][$delta]['value']['data:0842'] = $record->$fkleft->name;
+          if (property_exists($record, 'uniquename')) {
+            $entity->{$field_name}['und'][$delta]['value']['data:0842'] = $record->name;
           }
 
           // If this records is also a published entity then include that.
-          if (property_exists($record->$fkleft, 'entity_id')) {
-            $entity->{$field_name}['und'][$delta]['value']['entity'] = 'TripalEntity:' . $record->$fkleft->entity_id;
+          if (property_exists($record, 'entity_id') and !empty($record->entity_id)) {
+            $entity->{$field_name}['und'][$delta]['value']['entity'] = 'TripalEntity:' . $record->entity_id;
           }
 
           // If this is the organism table then we will create the name
           // specially.
-          if (property_exists($record->$fkleft, 'genus')) {
-            $name = '<i>' . $record->$fkleft->genus . ' ' . $record->$fkleft->species . '</i>';
-            if (property_exists($record->$fkleft, 'infraspecific_name')) {
+          if (property_exists($record, 'genus')) {
+            $name = '<i>' . $record->genus . ' ' . $record->species . '</i>';
+            if (property_exists($record, 'infraspecific_name')) {
               if ($record->$fkleft->type_id) {
-                $name .= ' ' . $record->$fkleft->type_id->name;
+                $name .= ' ' . $record->type_name;
               }
-              $name .= ' ' . $record->$fkleft->infraspecific_name;
+              $name .= ' ' . $record->infraspecific_name;
             }
             $entity->{$field_name}['und'][$delta]['value']['schema:name'] = $name;
+            $entity->{$field_name}['und'][$delta]['value']['rdfs:type'] = $ref_type->name;
           }
           $delta++;
         }
       }
     }
   }
-
 }

+ 25 - 6
tripal_chado/includes/TripalFields/sio__references/sio__references_formatter.inc

@@ -25,22 +25,39 @@ class sio__references_formatter extends ChadoFieldFormatter {
     $ordered_items = [];
     foreach ($items as $delta => $item) {
       $type = isset($item['value']['rdfs:type']) ? $item['value']['rdfs:type'] : '';
-      $entity = isset($item['value']['entity']) ? $item['value']['entity'] : '';
+      $ientity = isset($item['value']['entity']) ? $item['value']['entity'] : '';
       $name = isset($item['value']['schema:name']) ? $item['value']['schema:name'] : '';
       $identifier = isset($item['value']['data:0842']) ? $item['value']['data:0842'] : '';
-      if ($entity) {
-        list($entity_type, $entity_id) = explode(':', $entity);
+      if ($ientity) {
+        list($entity_type, $entity_id) = explode(':', $ientity);
         $name = l(strip_tags($name), 'bio_data/' . $entity_id);
       }
       $ordered_items[ucfirst($type)][] = $name;
     }
 
     // Reorder the list so it's compatible with theming a list.
+    ksort($ordered_items);
+
+    // Generate the pagers for each type.
     $list_items = [];
     $headers = [];
     $rows = [];
-    ksort($ordered_items);
     foreach ($ordered_items as $type => $children) {
+      $items_per_page = array_key_exists('items_per_page', $this->instance['settings']) ? $this->instance['settings']['items_per_page'] : 10;
+      $total_records = count($children);
+      $total_pages = (int) ($total_records / $items_per_page) + 1;
+      $pelement = 0;
+      $current_page = pager_default_initialize($total_records, $items_per_page, $pelement);
+      $pager = theme('pager', [
+        'tags' => [],
+        'element' => $pelement,
+        'parameters' => [],
+        'quantity' => 5,
+      ]);
+      $pager = $this->ajaxifyPager($pager, $entity);
+      $page_items = array_chunk($children, $items_per_page);
+
+
       $rows[] = [
         [
           'data' => ucfirst($type) . '(s)',
@@ -48,14 +65,16 @@ class sio__references_formatter extends ChadoFieldFormatter {
           'width' => '20%',
         ],
         theme_item_list([
-          'items' => $children,
+          'items' => $page_items[$current_page],
           'title' => '',
           'type' => 'ul',
           'attributes' => [],
-        ]),
+        ]) . $pager,
       ];
     }
 
+
+
     $table = [
       'header' => [],
       'rows' => $rows,

+ 87 - 31
tripal_chado/includes/TripalImporter/OBOImporter.inc

@@ -160,6 +160,15 @@ class OBOImporter extends TripalImporter {
    */
   private $default_namespace = '';
 
+
+  /**
+   * Holds the idspace elements from the header. These will correspond
+   * to the accession prefixes, or short names (e.g. GO) for the terms. For
+   * example, the EDAM vocabulary has several id spaces:
+   * format, data, operation and topic.
+   */
+  private $idspaces = [];
+
   /**
    * The default database prefix for this ontology.
    *
@@ -169,7 +178,7 @@ class OBOImporter extends TripalImporter {
 
 
   /**
-   * An array of used cvterm objects so that we don't have to lookup them
+   * An array of used cvterm objects so that we don't have to look them
    * up repeatedly.
    */
   private $used_terms = [];
@@ -248,8 +257,8 @@ class OBOImporter extends TripalImporter {
     $form['obo_existing']['existing_instructions'] = [
       '#type' => 'item',
       '#markup' => t('The vocabularies listed in the select box below have been pre-populated
-        upon installation of Tripal or have been previously loaded.  Select one to edit
-        its settings or submit for loading.  You may reload any vocabulary that has
+        upon installation of Tripal or have been previously loaded. Select one to edit
+        its settings or submit for loading. You may reload any vocabulary that has
         already been loaded to retrieve any new updates.'),
     ];
 
@@ -298,7 +307,7 @@ class OBOImporter extends TripalImporter {
       $form['obo_existing']['uobo_name'] = [
         '#type' => 'textfield',
         '#title' => t('Vocabulary Name'),
-        '#description' => t('Please provide a name for this vocabulary.  After upload, this name will appear in the drop down
+        '#description' => t('Please provide a name for this vocabulary. After upload, this name will appear in the drop down
                              list above for use again later.'),
         '#default_value' => $uobo_name,
       ];
@@ -306,8 +315,8 @@ class OBOImporter extends TripalImporter {
       $form['obo_existing']['uobo_url'] = [
         '#type' => 'textfield',
         '#title' => t('Remote URL'),
-        '#description' => t('Please enter a URL for the online OBO file.  The file will be downloaded and parsed.
-                             (e.g. http://www.obofoundry.org/ro/ro.obo)'),
+        '#description' => t('Please enter a URL for the online OBO file. The file will be downloaded and parsed.
+                             (e.g. https://raw.githubusercontent.com/oborel/obo-relations/master/ro.obo)'),
         '#default_value' => $uobo_url,
       ];
 
@@ -318,8 +327,8 @@ class OBOImporter extends TripalImporter {
           definition file. If entering a path relative to
           the Drupal installation you may use a relative path that excludes the
           Drupal installation directory (e.g. sites/default/files/xyz.obo). Note
-          that Drupal relative paths have no preceding slash.
-          Otherwise, please provide the full path on the filesystem.  The path
+          that Drupal relative paths have no preceeding slash.
+          Otherwise, please provide the full path on the filesystem. The path
           must be accessible to the web server on which this Drupal instance is running.'),
         '#default_value' => $uobo_file,
       ];
@@ -338,24 +347,24 @@ class OBOImporter extends TripalImporter {
     ];
 
     $form['obo_new']['path_instructions'] = [
-      '#value' => t('Provide the name and path for the OBO file.  If the vocabulary OBO file
+      '#value' => t('Provide the name and path for the OBO file. If the vocabulary OBO file
                      is stored local to the server provide a file name. If the vocabulary is stored remotely,
-                     provide a URL.  Only provide a URL or a local file, not both.'),
+                     provide a URL. Only provide a URL or a local file, not both.'),
     ];
 
     $form['obo_new']['obo_name'] = [
       '#type' => 'textfield',
       '#title' => t('New Vocabulary Name'),
-      '#description' => t('Please provide a name for this vocabulary.  After upload, this name will appear in the drop down
-                             list above for use again later. Additionally, if a default namespace is not provided in the OBO
-                             header this name will be used as the default_namespace.'),
+      '#description' => t('Please provide a name for this vocabulary. After upload, this name will appear in the drop down
+                           list above for use again later. Additionally, if a default namespace is not provided in the OBO
+                           header this name will be used as the default_namespace.'),
     ];
 
     $form['obo_new']['obo_url'] = [
       '#type' => 'textfield',
       '#title' => t('Remote URL'),
       '#description' => t('Please enter a URL for the online OBO file.  The file will be downloaded and parsed.
-                             (e.g. http://www.obofoundry.org/ro/ro.obo)'),
+                           (e.g. https://raw.githubusercontent.com/oborel/obo-relations/master/ro.obo)'),
     ];
 
     $form['obo_new']['obo_file'] = [
@@ -365,7 +374,7 @@ class OBOImporter extends TripalImporter {
           definition file. If entering a path relative to
           the Drupal installation you may use a relative path that excludes the
           Drupal installation directory (e.g. sites/default/files/xyz.obo). Note
-          that Drupal relative paths have no preceding slash.
+          that Drupal relative paths have no preceeding slash.
           Otherwise, please provide the full path on the filesystem.  The path
           must be accessible to the web server on which this Drupal instance is running.'),
     ];
@@ -595,7 +604,7 @@ class OBOImporter extends TripalImporter {
     tripal_populate_mview($mview_id);
 
     // Update the cvtermpath table for each newly added CV.
-    $this->logMessage("Updating cvtermpath table.  This may take a while...");
+    $this->logMessage("Updating cvtermpath table. This may take a while...");
     foreach ($this->obo_namespaces as $namespace => $cv_id) {
       $this->logMessage("- Loading paths for vocabulary: @vocab", ['@vocab' => $namespace]);
       chado_update_cvtermpath($cv_id, $this->job);
@@ -605,7 +614,7 @@ class OBOImporter extends TripalImporter {
   /**
    * A wrapper function for importing the user specified OBO file into Chado by
    * specifying the obo_id of the OBO. It requires that the file be in OBO v1.2
-   * compatible format.  This function is typically executed via the Tripal
+   * compatible format. This function is typically executed via the Tripal
    * jobs
    * management after a user submits a job via the Load Ontologies form.
    *
@@ -653,7 +662,7 @@ class OBOImporter extends TripalImporter {
   /**
    * A wrapper function for importing the user specified OBO file into Chado by
    * specifying the filename and path of the OBO. It requires that the file be
-   * in OBO v1.2 compatible format.  This function is typically executed via
+   * in OBO v1.2 compatible format. This function is typically executed via
    * the Tripal jobs management after a user submits a job via the Load
    * Ontologies form.
    *
@@ -664,7 +673,7 @@ class OBOImporter extends TripalImporter {
    *   The path on the file system where the ontology can be found
    * @param $is_new
    *   Set to TRUE if this is a new ontology that does not yet exist in the
-   *   tripal_cv_obo table.  If TRUE the OBO will be added to the table.
+   *   tripal_cv_obo table. If TRUE the OBO will be added to the table.
    *
    * @ingroup tripal_obo_loader
    */
@@ -841,6 +850,7 @@ class OBOImporter extends TripalImporter {
   private function setDefaults($header) {
     $short_name = '';
     $namespace = '';
+    $idspaces = [];
 
     // Get the 'ontology' and 'default-namespace' headers.  Unfortunately,
     // not all OBO files contain these.
@@ -850,7 +860,19 @@ class OBOImporter extends TripalImporter {
     if (array_key_exists('default-namespace', $header)) {
       $namespace = $header['default-namespace'][0];
     }
-
+    if (array_key_exists('idspace', $header)) {
+      $matches = [];
+      foreach ($header['idspace'] as $idspace) {
+        if (preg_match('/^(.+?)\s+(.+?)\s+"(.+)"$/', $idspace, $matches)) {
+          $idspaces[$matches[1]]['url'] = $matches[2];
+          $idspaces[$matches[1]]['description'] = $matches[3];
+        }
+        elseif (preg_match('/^(.+?)\s+(.+?)$/', $idspace, $matches)) {
+          $idspaces[$matches[1]]['url'] = $matches[2];
+          $idspaces[$matches[1]]['description'] = '';
+        }
+      }
+    }
     // The OBO specification allows the 'ontology' header tag to be nested for
     // subsets (e.g. go/subsets/goslim_plant).  We need to simplify that down
     // to the top-level item.
@@ -888,9 +910,20 @@ class OBOImporter extends TripalImporter {
       }
     }
 
+    // If we still don't have a namespace defined, use the one from the form
+    // in the "New Vocabulary Name" field
+    if (!$namespace and array_key_exists('run_args', $this->arguments)
+        and array_key_exists('obo_name', $this->arguments['run_args'])) {
+      $namespace = $this->arguments['run_args']['obo_name'];
+    }
+    if (!$namespace and array_key_exists('run_args', $this->arguments)
+        and array_key_exists('uobo_name', $this->arguments['run_args'])) {
+      $namespace = $this->arguments['run_args']['uobo_name'];
+    }
+
     // If we can't find the namespace or the short_name then bust.
     if (!$namespace and !$short_name) {
-      throw new ErrorException('Cannot determine the namespace or ontology prefix from this OBO file. It is missing both the "default-namespace" and "ontology" headers.');
+      throw new ErrorException('Cannot determine the namespace or ontology prefix from this OBO file. It is missing both the "default-namespace" or a compatible "ontology" header.');
     }
 
     // Set the defaults.
@@ -899,8 +932,12 @@ class OBOImporter extends TripalImporter {
     $this->addDB($this->default_db);
     $cv = $this->addCV($this->default_namespace);
     $this->obo_namespaces[$namespace] = $cv->cv_id;
+    $this->idspaces = $idspaces;
 
-
+    // Add a new database for each idspace.
+    foreach ($idspaces as $shortname => $idspace) {
+      $this->addDB($shortname, $idspace['url'], $idspace['description']);
+    }
   }
 
   /**
@@ -916,13 +953,13 @@ class OBOImporter extends TripalImporter {
     // Check if the EBI ontology search has this ontology:
     try {
       $results = $this->oboEbiLookup($ontology, 'ontology');
-      if (array_key_exists('default-namespace', $results['config']['annotations'])) {
+      if ($results and array_key_exists('config', $results) and array_key_exists('default-namespace', $results['config']['annotations'])) {
         $namespace = $results['config']['annotations']['default-namespace'];
         if (is_array($namespace)) {
           $namespace = $namespace[0];
         }
       }
-      elseif (array_key_exists('namespace', $results['config'])) {
+      elseif ($results and array_key_exists('config', $results) and array_key_exists('namespace', $results['config'])) {
         $namespace = $results['config']['namespace'];
       }
       // If we can't find the namespace at EBI, then just default to using the
@@ -983,7 +1020,7 @@ class OBOImporter extends TripalImporter {
         "Lookup Service to retrieve the information for this term. " .
         "Please note, that vocabularies with many non-local terms " .
         "require remote lookups and these lookups can dramatically " .
-        "decrease loading time. ",
+        "increase loading time. ",
         ['!vocab' => $this->default_namespace], TRIPAL_WARNING);
       $this->ebi_warned = TRUE;
 
@@ -1053,7 +1090,7 @@ class OBOImporter extends TripalImporter {
     // If EBI sent an error message then throw an error.
     if ($results['error']) {
       $this->logMessage('Cannot find the term via an EBI OLS lookup: !term. ' .
-        'We tried to access: !url' .
+        'We tried to access: "!url" ' .
         'EBI Reported: !message. Consider finding the OBO file for this ontology and manually loading it first.',
         [
           '!message' => $results['message'],
@@ -1774,7 +1811,8 @@ class OBOImporter extends TripalImporter {
       $accession = $matches[2];
 
       // If the term is borrowed then let's try to deal with it.
-      if ($short_name != $this->default_db) {
+      $idspaces = array_keys($this->idspaces);
+      if ($short_name != $this->default_db and !in_array($short_name, $idspaces)) {
 
         // First try to lookup the term and replace the stanza with the updated
         // details.
@@ -2069,6 +2107,11 @@ class OBOImporter extends TripalImporter {
 
           // If this term has a namespace then we want to keep track of it.
           if (array_key_exists('namespace', $stanza)) {
+            // Fix the namespace for EDAM terms so they all use the same
+            // namespacke (i.e. cv record).
+            if ($this->default_namespace == 'EDAM') {
+              $stanza['namespace'][0] = 'EDAM';
+            }
             $namespace = $stanza['namespace'][0];
             $cv = $this->all_cvs[$namespace];
             $this->obo_namespaces[$namespace] = $cv->cv_id;
@@ -2079,7 +2122,7 @@ class OBOImporter extends TripalImporter {
           // add the ID to the name to ensure it doesn't.
           if (array_key_exists($stanza['name'][0], $this->term_names)) {
             $new_name = $stanza['name'][0] . '(' . $stanza['id'][0] . ')';
-            $stanza['name'][0] = $stanza['name'][0];
+            $stanza['name'][0] = $new_name;
           }
 
           $this->cacheTermStanza($stanza, $type);
@@ -2094,6 +2137,11 @@ class OBOImporter extends TripalImporter {
         continue;
       }
 
+      // For EDAM, we have to unfortuantely hard-code a fix as the
+      // short names of terms are correct.
+      $line = preg_replace('/EDAM_(\w+)/', '\1', $line);
+
+
       // break apart the line into the tag and value but ignore any escaped colons
       preg_replace("/\\:/", "|-|-|", $line); // temporarily replace escaped colons
       $pair = explode(":", $line, 2);
@@ -2247,7 +2295,7 @@ class OBOImporter extends TripalImporter {
    * @return
    *   A Chado database object.
    */
-  private function addDB($dbname) {
+  private function addDB($dbname, $url = '',  $description = '') {
     // Add the database if it doesn't exist.
     $db = NULL;
     if (array_key_exists($dbname, $this->all_dbs)) {
@@ -2256,7 +2304,14 @@ class OBOImporter extends TripalImporter {
     else {
       // If it's not in the cache we can assume it doesn't exist and insert.
       $db = new ChadoRecord('db');
-      $db->setValues(['name' => $dbname]);
+      $values = ['name' => $dbname];
+      if ($url) {
+        $values['url'] = $url;
+      }
+      if ($description) {
+        $values['description'] = $description;
+      }
+      $db->setValues($values);
       $db->insert();
       $db = (object) $db->getValues();
       $this->all_dbs[$dbname] = $db;
@@ -2331,7 +2386,8 @@ class OBOImporter extends TripalImporter {
     }
 
     if (!$accession) {
-      throw new Exception("Cannot add an Alt ID without an accession: '$alt_id'");
+      $this->logMessage("Cannot add an Alt ID without an accession: '!alt_id'", ['!alt_id' => $alt_id]);
+      return;
     }
 
     // Add the database if it doesn't exist.

+ 3 - 3
tripal_chado/includes/tripal_chado.fields.inc

@@ -813,7 +813,7 @@ function tripal_chado_bundle_fields_info_linker(&$info, $details, $entity_type,
   }
 
   // RELATIONSHIPS
-  // If the linker table does not exists then we don't want to add attach.
+  // If the linker table does not exist then we don't want to add attach.
   $rel_table = $table_name . '_relationship';
   if (chado_table_exists($rel_table)) {
     $field_name = 'sbo__relationship';
@@ -1110,7 +1110,7 @@ function tripal_chado_bundle_instances_info_base(&$info, $entity_type, $bundle,
       if ($column_name == 'uniquename') {
         $base_info['label'] = 'Unique Local Identifier';
         $base_info['required'] = TRUE;
-        $base_info['description'] = 'This publication is housed in Chado whic requires a unique identifer (or name) be provided for every publication. This identifier need not be shown to end-users but it is required. Each site must decide on a format for this unique name.';
+        $base_info['description'] = 'This publication is housed in Chado which requires a unique identifer (or name) be provided for every publication. This identifier need not be shown to end-users but it is required. Each site must decide on a format for this unique name.';
       }
       if ($column_name == 'title') {
         $base_info['description'] = 'The title of the published work.';
@@ -2676,7 +2676,7 @@ function tripal_chado_bundle_instances_info_linker(&$info, $entity_type, $bundle
   }
 
   // RELATIONSHIPS
-  // If the linker table does not exists then we don't want to add attach.
+  // If the linker table does not exist then we don't want to add attach.
   $rel_table = $table_name . '_relationship';
   if (chado_table_exists($rel_table)) {
     $field_name = 'sbo__relationship';

+ 1 - 1
tripal_chado/includes/tripal_chado.phylotree.inc

@@ -113,7 +113,7 @@ function tripal_phylogeny_ajax_get_tree_json($phylotree_id)
     // features and organisms with which it is associated.  Each phylonode
     // can be associated with an organism in one of two ways: 1) via a
     // feature linked by the phylonode.feature_id field or 2) via a
-    // a record in the phylonde_organism table.  Therefore both types of
+    // a record in the phylonode_organism table.  Therefore both types of
     // organism records are returned in the query below, but those
     // retrieved via a FK link on features are prefixed with 'fo_'.
     $sql = "

+ 1 - 1
tripal_chado/tripal_chado.info

@@ -3,7 +3,7 @@ description = Provides a set of Chado-based fields for the Tripal Entities.
 core = 7.x
 project = tripal
 package = Tripal
-version = 7.x-3.1
+version = 7.x-3.5
 
 files[] = views_handlers/chado_views_handler_field.inc
 files[] = views_handlers/chado_views_handler_filter.inc

+ 1 - 1
tripal_chado_views/tripal_chado_views.info

@@ -3,7 +3,7 @@ description = Integrates all Chado tables with Drupal Views and provides basic s
 core = 7.x
 project = tripal
 package = Tripal
-version = 7.x-3.1
+version = 7.x-3.5
 configure = admin/tripal/storage/chado/views-integration
 
 files[] = views/handlers/tripal_views_handler_filter_textarea.inc

+ 1 - 1
tripal_daemon/theme/tripal_daemon.log_block.css

@@ -1,5 +1,5 @@
 /**
- * Themeing for the Tripal Daemon Log Block.
+ * Theming for the Tripal Daemon Log Block.
  */
 
 #trpdaemon-display-log-form {

+ 1 - 1
tripal_ds/tripal_ds.info

@@ -3,7 +3,7 @@ description = Provides display options for Tripal Entities through extending Dis
 core = 7.x
 project = tripal
 package = Tripal
-version = 7.x-3.1
+version = 7.x-3.5
 
 stylesheets[all][] = theme/css/tripal_ds.css
 

+ 1 - 1
tripal_ws/includes/TripalFields/remote__data/remote__data_formatter.inc

@@ -24,7 +24,7 @@ class remote__data_formatter extends WebServicesFieldFormatter {
     $field_name = $this->field['field_name'];
 
     // Get any subfields and the header label.  Shift the array because the
-    // results should already be the value of the fisrt entry.
+    // results should already be the value of the first entry.
     $rd_field_name = $this->instance['settings']['data_info']['rd_field_name'];
     $subfields = explode(',', $rd_field_name);
     $header_label = $this->getHeaderLabel($subfields);

+ 1 - 1
tripal_ws/includes/TripalWebService.inc

@@ -295,7 +295,7 @@ class TripalWebService {
    *   An implementation of a TripalWebServiceResource.
    */
   public function setResource($resource) {
-    // Make sure the $service provides is a TripalWebServcie class.
+    // Make sure the $service provides is a TripalWebService class.
     if (!is_a($resource, 'TripalWebServiceResource')) {
       throw new Exception("Cannot add a new resource to this web service as it is not a TripalWebServiceResource.");
     }

+ 62 - 29
tripal_ws/includes/TripalWebService/TripalContentService_v0_1.inc

@@ -147,7 +147,8 @@ class TripalContentService_v0_1 extends TripalWebService {
         FIELD_LOAD_CURRENT, ['field_id' => $field['id']]);
     }
 
-    $this->addEntityField($this->resource, $term, $entity, $bundle, $field, $instance, $service_path, $expfield);
+    $field_service_path = $service_path . '/' . urlencode($term['name']);
+    $this->addEntityField($this->resource, $term, $entity, $bundle, $field, $instance, $field_service_path, $expfield);
   }
 
   /**
@@ -319,9 +320,6 @@ class TripalContentService_v0_1 extends TripalWebService {
       $instance_settings = $instance['settings'];
       if (array_key_exists('auto_attach', $instance['settings']) and
         $instance_settings['auto_attach'] == FALSE) {
-        // Add a URL only if there are values. If there are no values then
-        // don't add a URL which would make the end-user think they can get
-        // that information.
         $items = field_get_items('TripalEntity', $entity, $field_name);
         $term_key = $this->getContextTerm($term, ['lowercase', 'spacing']);
         $resource->addContextItem($term_key, $vocabulary . ':' . $accession);
@@ -329,25 +327,16 @@ class TripalContentService_v0_1 extends TripalWebService {
           '@id' => $term['url'],
           '@type' => '@id',
         ]);
-        if ($items and count($items) > 0 and $items[0]['value']) {
-          $this->addResourceProperty($resource, $term, $service_path . '/' . $entity->id . '/' . urlencode($term['name']), [
-            'lowercase',
-            'spacing',
-          ]);
-        }
-        else {
-          if ($hide_fields == FALSE) {
-            $this->addResourceProperty($resource, $term, NULL, [
-              'lowercase',
-              'spacing',
-            ]);
-          }
-        }
+        $this->addResourceProperty($resource, $term, $service_path . '/' . $entity->id . '/' . urlencode($term['name']), [
+          'lowercase',
+          'spacing',
+        ]);
         continue;
       }
 
       // Get the details for this field for the JSON-LD response.
-      $this->addEntityField($resource, $term, $entity, $bundle, $field, $instance, $service_path);
+      $field_service_path = $service_path . '/' . $entity->id . '/' . urlencode($term['name']);
+      $this->addEntityField($resource, $term, $entity, $bundle, $field, $instance, $field_service_path);
     }
   }
 
@@ -419,12 +408,25 @@ class TripalContentService_v0_1 extends TripalWebService {
       // If the value is an array and this is the field page then all of those
       // key/value pairs should be added directly to the response.
       if (is_array($values[0])) {
+        if (array_key_exists('@type', $values[0])) {
+          [$vocabulary, $accession] = explode(':', $values[0]['@type']);
+          $term = tripal_get_term_details($vocabulary, $accession);
+          $resource->addContextItem($term['vocabulary']['short_name'], $term['vocabulary']['sw_url']);
+          $resource->addContextItem($values[0]['@type'], $term['url']);
+          $resource->addContextItem($term['name'], $values[0]['@type']);
+          $values[0]['@type'] = $term['name'];
+        }
+
         if ($expfield) {
           foreach ($values[0] as $k => $v) {
+            if ($k == '@type') {
+              continue;
+            }
             $resource->addProperty($k, $v);
           }
         }
         else {
+
           $this->addResourceProperty($resource, $term, $values[0], [
             'lowercase',
             'spacing',
@@ -446,28 +448,54 @@ class TripalContentService_v0_1 extends TripalWebService {
 
       // If this is the expanded field page then we need to swap out
       // the resource for a collection.
-      $response = new TripalWebServiceCollection($service_path . '/' . urlencode($expfield), $this->params);
+      $response = new TripalWebServiceCollection($service_path, $this->params);
       $label = tripal_get_term_details('rdfs', 'label');
       $this->addResourceProperty($response, $label, $instance['label']);
       $i = 0;
+
       foreach ($values as $delta => $element) {
-        $member = new TripalWebServiceResource($service_path . '/' . urlencode($expfield));
+        $member = new TripalWebServiceResource($service_path);
         $member->setID($i);
+
+        // Turn off the @id and @type keys unless the element has these.
+        $member->disableID();
+        $member->disbleType();
+
         // Add the context of the parent resource because all of the keys
         // were santizied and set to match the proper context.
         $member->setContext($resource);
-        $this->setResourceType($member, $term);
+
+        // Iterate through the key/value pairs of the list.
         foreach ($element as $key => $value) {
+          // If this element has an '@id' then replace the generic
+          // service path that each member element automatically gets
+          // with this value.
+          if ($key == '@id') {
+            $member->setServicePath($value);
+            $member->enableID();
+            continue;
+          }
+          if ($key == '@type') {
+            [$vocabulary, $accession] = explode(':', $value);
+            $tterm = tripal_get_term_details($vocabulary, $accession);
+            $member->addContextItem($tterm['vocabulary']['short_name'], $tterm['vocabulary']['sw_url']);
+            $member->addContextItem($value, $tterm['url']);
+            $member->addContextItem($tterm['name'], $value);
+            $member->setType($tterm['name']);
+            $member->enableType();
+            continue;
+          }
           $member->addProperty($key, $value);
         }
-        $response->addMember($member);
-        $i++;
+        if (!empty($element)) {
+          $response->addMember($member);
+          $i++;
+        }
       }
       if ($expfield) {
         $this->resource = $response;
       }
       else {
-        //$this->resource->addProperty($key, $response);
         $this->addResourceProperty($resource, $term, $response, [
           'lowercase',
           'spacing',
@@ -520,6 +548,9 @@ class TripalContentService_v0_1 extends TripalWebService {
           // Index number (0, 1, 2...) of a hydra:member array.
           $temp[$k] = $this->sanitizeFieldKeys($resource, $v, $bundle, $service_path);
         }
+        elseif ($k == 'entity') {
+          $temp[$k] = $v;
+        }
         else {
           // TODO: this is an error, if we get here then we have
           // a key that isn't using the proper format... what to do?
@@ -560,6 +591,7 @@ class TripalContentService_v0_1 extends TripalWebService {
           $item_entity = reset($item_entity);
           $bundle = tripal_load_bundle_entity(['name' => $item_entity->bundle]);
           $items['@id'] = $this->getServicePath() . '/' . urlencode($bundle->label) . '/' . $item_eid;
+          $items['@type'] = $bundle->accession;
         }
         unset($items['entity']);
       }
@@ -879,13 +911,13 @@ class TripalContentService_v0_1 extends TripalWebService {
 
     // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
     $bundle = tripal_load_bundle_entity(['label' => $ctype]);
-    
+
     // Check that the user has access to this bundle.  If not then the
     // function call will throw an error.
     if (!user_access('view ' . $bundle->name)) {
       throw new Exception("Permission Denied.");
     }
-        
+
     $term = entity_load('TripalTerm', ['id' => $bundle->term_id]);
     $term = reset($term);
 
@@ -1023,9 +1055,10 @@ class TripalContentService_v0_1 extends TripalWebService {
 
       // Add in any requested fields
       foreach ($add_fields as $expfield => $expfield_details) {
+        $field_service_path = $service_path . '/' . $entity->id . '/' . urlencode($expfield);
         $this->addEntityField($member, $expfield_details['term'], $entity,
           $bundle, $expfield_details['field'], $expfield_details['instance'],
-          $service_path);
+            $field_service_path);
       }
       $this->resource->addMember($member);
     }
@@ -1058,7 +1091,7 @@ class TripalContentService_v0_1 extends TripalWebService {
         // Show only content types users have access to and skip the rest.
         continue;
       }
-      
+
       $entity = entity_load('TripalTerm', ['id' => $bundle->term_id]);
       $term = reset($entity);
       $vocab = $term->vocab;

+ 1 - 1
tripal_ws/includes/TripalWebServiceCollection.inc

@@ -91,7 +91,7 @@ class TripalWebServiceCollection extends TripalWebServiceResource {
    *   resource
    */
   public function addMember($member) {
-    // Make sure the $service provides is a TripalWebServcie class.
+    // Make sure the $service provides is a TripalWebService class.
     if (!is_a($member, 'TripalWebServiceResource')) {
       throw new Exception("Cannot add a new member to this resource collection as it is not a TripalWebServiceResource.");
     }

+ 60 - 1
tripal_ws/includes/TripalWebServiceResource.inc

@@ -31,6 +31,44 @@ class TripalWebServiceResource {
   protected $service_path;
 
 
+  /**
+   * All resources should have a @type and an @id.  But, there
+   * are times when we don't want any, such as an array of unpblished
+   * properties (e.g. featureloc elements).  These can be set to
+   * TRUE to disable.
+   */
+  protected $disable_type = FALSE;
+  protected $disable_id = FALSE;
+
+
+  /**
+   * Exclude the @type element form the data of this resource.
+   */
+  public function disbleType() {
+    $this->disable_type = TRUE;
+  }
+
+  /**
+   * Include the @type element form the data of this resource.
+   */
+  public function enableType() {
+    $this->disable_type = FALSE;
+  }
+
+  /**
+   * Exclude the @id element form the data of this resource.
+   */
+  public function disableID() {
+    $this->disable_id = TRUE;
+  }
+
+  /**
+   * Include the @id element form the data of this resource.
+   */
+  public function enableID() {
+    $this->disable_id = FALSE;
+  }
+
   /**
    * Implements the constructor.
    *
@@ -113,6 +151,20 @@ class TripalWebServiceResource {
     $this->data['@type'] = $type;
   }
 
+  /**
+   * Sets the service path for this resource.
+   *
+   * By default, the service path is provided to the constructor, but
+   * this function will allow it to be changed if needed.
+   *
+   * @param $service_path
+   *   The URL for the service path.
+   */
+  public function setServicePath($service_path) {
+    $this->service_path = $service_path;
+    $this->data['@id'] = $service_path;
+  }
+
   /**
    * Checks a key to ensure it is in the Context before being used.
    *
@@ -341,7 +393,14 @@ class TripalWebServiceResource {
    *   An associative array containing the data section of the response.
    */
   public function getData() {
-    return $this->data;
+    $data = $this->data;
+    if ($this->disable_id) {
+      unset($data['@id']);
+    }
+    if ($this->disable_type) {
+      unset($data['@type']);
+    }
+    return $data;
   }
 
   /**

+ 1 - 1
tripal_ws/tripal_ws.info

@@ -3,7 +3,7 @@ description = Exposes Tripal Entites as RESTful web services.
 core = 7.x
 project = tripal
 package = Tripal
-version = 7.x-3.1
+version = 7.x-3.5
 
 stylesheets[all][] = theme/css/tripal_ws.css