Browse Source

Property fields can now be added to the entity

Stephen Ficklin 9 years ago
parent
commit
9b0ecaeb50

+ 3 - 2
tripal_entities/includes/tripal_entities.admin.inc

@@ -63,8 +63,9 @@ function tripal_entities_content_view() {
 
 }
 
-function tripal_entities_publish() {
-  $form = drupal_get_form('tripal_entities_entity_form');
+function tripal_entities_publish($term_name = '') {
+
+  $form = drupal_get_form('tripal_entities_entity_form', $term_name);
   $output = drupal_render($form);
 
   // set the breadcrumb

+ 50 - 6
tripal_entities/includes/tripal_entities.chado_entity.inc

@@ -71,9 +71,7 @@ function tripal_entities_entity_delete($entity, $type) {
  * @param unknown $context
  */
 function tripal_entities_field_widget_form_alter(&$element, &$form_state, $context) {
-  // The timelastmodified field exists in many Chado tables.  We want
-  // the form element to update to the most recent time rather than the time
-  // in the database.
+
   if (array_key_exists('#field_name', $element)) {
     $field_name = $element['#field_name'];
     $matches = array();
@@ -81,19 +79,57 @@ function tripal_entities_field_widget_form_alter(&$element, &$form_state, $conte
       $tablename = $matches[1];
       $colname = $matches[2];
       $schema = chado_get_schema($tablename);
-      if ($colname == 'timelastmodified' and
-        $schema['fields'][$colname]['type'] == 'datetime') {
-        $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s");
+
+      // The timelastmodified field exists in many Chado tables.  We want
+      // the form element to update to the most recent time rather than the time
+      // in the database.
+      if ($colname == 'timelastmodified' and $schema['fields'][$colname]['type'] == 'datetime') {
+        // We want the default value for the field to be the current time.
+        $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s", 'UTC');
         $element['#date_items']['value'] = $element['#default_value']['value'];
       }
+      // We want the date combo fieldset to be collaspible so we will
+      // add our own theme_wrapper to replace the one added by the date
+      // module.
+      if ($schema['fields'][$colname]['type'] == 'datetime') {
+        $element['#theme_wrappers'] = array('tripal_entities_date_combo');
+      }
     }
   }
 }
+
+/**
+ * This theme function is meant to override the data_combo theme.
+ *
+ * @param $variables
+ */
+function theme_tripal_entities_date_combo($variables) {
+  $element = $variables['element'];
+  $field = field_info_field($element['#field_name']);
+  $instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
+
+  // Group start/end items together in fieldset.
+  $fieldset = array(
+    '#title' => t($element['#title']) . ' ' . ($element['#delta'] > 0 ? intval($element['#delta'] + 1) : ''),
+    '#value' => '',
+    '#description' => !empty($element['#fieldset_description']) ? $element['#fieldset_description'] : '',
+    '#attributes' => array(),
+    '#children' => $element['#children'],
+    '#attributes' => array('class' => array('collapsible', 'collapsed')),
+  );
+  return theme('fieldset', array('element' => $fieldset));
+}
 /**
  * Implements hook_chado_field_alter().
  *
  */
 function tripal_entities_chado_field_alter(&$field) {
+dpm($field);
+  // If the field doesn't list the Chado table or column then just return.
+  if (!array_key_exists('chado_table', $field) or !array_key_exists('chado_column', $field)) {
+    return;
+  }
+
 
   // Here we provide new field types and widgets for FK fields
   // and fields that need special attention.
@@ -129,6 +165,14 @@ function tripal_entities_chado_field_alter(&$field) {
     $field['label'] = 'Residues';
     $field['description'] = 'Please provide an IUPAC compatible residues for this feature. Spaces and new lines are allowed.';
   }
+  else if ($field['label'] == 'Timeaccessioned') {
+    $field['label'] = 'Time Accessioned';
+    $field['description'] = 'Please enter the time that this record was first added to the database.';
+  }
+  else if ($field['label'] == 'Timelastmodified') {
+    $field['label'] = 'Time Last Modified';
+    $field['description'] = 'Please enter the time that this record was last modified. The default is the current time.';
+  }
 }
 
 /**

+ 37 - 69
tripal_entities/includes/tripal_entities.entity_form.inc

@@ -3,11 +3,9 @@
 /**
  *
  */
-function tripal_entities_entity_form($form, &$form_state, $entity = NULL) {
-
+function tripal_entities_entity_form($form, &$form_state, $term_name = '', $entity = NULL) {
   // Set the defaults.
   $cv_id = NULL;
-  $term_name = NULL;
   $cvterm = NULL;
   $do_sync = 0;
   $terms = array();
@@ -31,6 +29,24 @@ function tripal_entities_entity_form($form, &$form_state, $entity = NULL) {
     $terms = $form_state['storage']['terms'];
     $num_terms = count($terms);
   }
+  // If we have a term name but the $form_state['storage']['terms'] isn't set
+  // then the term_name is being passed in, and we should try to get the
+  // terms.
+  else if ($term_name) {
+    $match = array(
+      'name' => $term_name,
+    );
+    $terms = chado_generate_var('cvterm', $match, array('return_array' => TRUE));
+    $form_state['storage']['terms'] = $terms;
+    $num_terms = count($terms);
+
+    // Make sure the term is set as published.
+    if ($num_terms == 1) {
+      tripal_entities_add_term_usage($terms[0], $form_state);
+    }
+    $einfo = entity_get_info($terms[0]->dbxref_id->db_id->name);
+    tripal_entities_add_bundle($terms[0]);
+  }
   if (array_key_exists('values', $form_state) and
       array_key_exists('term_name', $form_state['values'])) {
     $term_name = $form_state['values']['term_name'];
@@ -64,6 +80,7 @@ function tripal_entities_entity_form($form, &$form_state, $entity = NULL) {
     }
   }
 
+
   // If the term belongs to more than one vocabulary then add additional fields
   // to let the user select the vocabulary.
   if ($num_terms > 1) {
@@ -118,7 +135,7 @@ function tripal_entities_entity_form($form, &$form_state, $entity = NULL) {
     );
     $form['details'] = array(
       '#type' => 'item',
-      '#title' => 'Data Type',
+      '#title' => 'Record Type',
       '#markup' => '(' . $cvterm->cv_id->name . ') ' . $cvterm->name,
       '#weight' => -1000,
     );
@@ -129,10 +146,13 @@ function tripal_entities_entity_form($form, &$form_state, $entity = NULL) {
     else {
       tripal_entities_entity_form_add_sync($bundle_id, $cvterm, $form, $form_state, $entity);
     }
+
+    // Add a prefix and a suffix around this form so that fields may
+    // replace the entire form on an ajax call if they want.
+    $form['#prefix'] = "<div id='$bundle_id-entity-form'>";
+    $form['#suffix'] = "</div>";
   }
 
-  $form['#prefix'] = '<div id="tripal-entities-entity-form">';
-  $form['#suffix'] = '</div>';
   return $form;
 }
 /**
@@ -150,7 +170,7 @@ function tripal_entities_entity_form_add_sync($bundle_id, $cvterm, &$form, &$for
 function tripal_entities_entity_form_add_new($bundle_id, $cvterm, &$form, &$form_state, $entity) {
 
   // Add a vertical tabs element
-  $form['entity_vetical_tabs'] = array(
+  $form['ev_tabs'] = array(
     '#type' => 'vertical_tabs',
     '#weight' => 999,
   );
@@ -162,7 +182,7 @@ function tripal_entities_entity_form_add_new($bundle_id, $cvterm, &$form, &$form
 
     $form['add_button'] = array(
       '#type' => 'submit',
-      '#value' => t('Add a new ' .$cvterm->name),
+      '#value' => t('Save'),
       '#name' => 'add_data',
       '#weight' => 1000
     );
@@ -190,6 +210,8 @@ function tripal_entities_entity_form_add_new($bundle_id, $cvterm, &$form, &$form
   // The entity object must be added to the $form_state in order for
   // the Entity API to work. It must have a key of the entity name.
   $form_state[$cvterm->dbxref_id->db_id->name] = $entity;
+
+
 }
 /**
  * An Ajax callback for the tripal_entities_entity_form.
@@ -522,7 +544,7 @@ function tripal_entities_add_bundle_fields($entity_type_name, $bundle_name, $cvt
 
   // Check to see if there are any kv-property tables associated to this
   // base table. If so, add the fields for that type of table.
-  tripal_entities_add_bundle_kv_property_fields($entity_type_name, $bundle_name, 'featureprop');
+  tripal_entities_add_bundle_kvproperty_adder_field($entity_type_name, $bundle_name, 'featureprop');
 }
 
 /**
@@ -532,14 +554,14 @@ function tripal_entities_add_bundle_fields($entity_type_name, $bundle_name, $cvt
  * @param $bundle_name
  * @param $kv_table
  */
-function tripal_entities_add_bundle_kv_property_fields($entity_type_name, $bundle_name, $kv_table) {
+function tripal_entities_add_bundle_kvproperty_adder_field($entity_type_name, $bundle_name, $kv_table) {
   // First add a generic property field so that users can add new proeprty types.
   $field_name = $kv_table;
 
   // Initialize the field array.
   $field_info = array(
-    'field_type' => 'kvproperty',
-    'widget_type' => 'tripal_fields_kvproperty_widget',
+    'field_type' => 'kvproperty_adder',
+    'widget_type' => 'tripal_fields_kvproperty_adder_widget',
     'field_settings' => array(),
     'widget_settings' => array('display_label' => 1),
     'description' => '',
@@ -548,7 +570,7 @@ function tripal_entities_add_bundle_kv_property_fields($entity_type_name, $bundl
     'chado_column' => '',
     'is_required' => 0,
   );
-  tripal_entities_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
 }
 /**
  * Adds the fields for the base table to the entity.
@@ -623,7 +645,7 @@ function tripal_entities_add_bundle_base_fields($entity_type_name, $bundle_name,
       }
 
       // Add the field to the bundle.
-      tripal_entities_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+      tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
     }
   }
 }
@@ -698,6 +720,7 @@ function tripal_entities_get_table_column_field_default($table_name, $schema, $c
       $field_info['widget_type'] = 'date_select';
       $field_info['widget_settings']['increment'] = 1;
       $field_info['widget_settings']['tz_handling'] = 'none';
+      $field_info['widget_settings']['collapsible'] = TRUE;
 
       // TODO: Add settings so that the minutes increment by 1.
       // And turn off the timezone, as the Chado field doesn't support it.
@@ -706,58 +729,3 @@ function tripal_entities_get_table_column_field_default($table_name, $schema, $c
 
   return $field_info;
 }
-/**
- * Adds a field to a bundle.
- *
- * @param $field_name
- *   The name of the field.
- * @param $field_info
- *   An associative array containing the field information.
- */
-function tripal_entities_add_bundle_field($field_name, $field_info,
-    $entity_type_name, $bundle_name) {
-
-  $field = field_info_field($field_name);
-
-  // If the field exists and is attached to this bundle then just return,
-  // there is nothing left to do.
-  if ($field and array_key_exists('bundles', $field) and
-      array_key_exists($entity_type_name, $field['bundles']) and
-      in_array($bundle_name, $field['bundles'][$entity_type_name])) {
-    return;
-  }
-
-  // Allow other modules to alter the field information array.
-  drupal_alter('chado_field', $field_info);
-
-  // If the field doesn't exist then create it.
-  if (!$field) {
-    $field = array(
-      'field_name' => $field_name,
-      'type' => $field_info['field_type'],
-      'cardinality' => 1,
-      'locked' => FALSE,
-      'storage' => array(
-        'type' => 'field_chado_storage'
-      ),
-      'settings' => $field_info['field_settings'],
-    );
-    field_create_field($field);
-  }
-
-  // Attach the field to the bundle.
-  $field_instance = array(
-    'field_name' => $field_name,
-    'label' => $field_info['label'],
-    'description' => $field_info['description'],
-    'widget' => array(
-      'type' => $field_info['widget_type'],
-      'settings' => $field_info['widget_settings'],
-    ),
-    'entity_type' => $entity_type_name,
-    'required' => $field_info['is_required'],
-    'settings' => $field_info['field_settings'],
-    'bundle' => $bundle_name,
-  );
-  field_create_instance($field_instance);
-}

+ 1 - 1
tripal_entities/theme/css/tripal_entities.css

@@ -5,7 +5,7 @@
    margin-right: 10px;
 }
 
-.kvproperty-widget-item {
+.kvproperty-adder-widget-item {
    float: left;
    margin-right: 10px;
 }

+ 13 - 0
tripal_entities/tripal_entities.module

@@ -53,6 +53,15 @@ function tripal_entities_menu() {
     'type' => MENU_LOCAL_TASK,
     'weight' => 2
   );
+  $items['admin/tripal/bio_data/publish/%'] = array(
+    'title' => 'Publish',
+    'description' => 'Publish Data',
+    'page callback' => 'tripal_entities_publish',
+    'page arguments' => array(4),
+    'access arguments' => array('administer tripal data types'),
+    'file' =>  'includes/tripal_entities.admin.inc',
+    'type' => MENU_CALLBACK,
+  );
 
   $items['admin/tripal/bio_data/access'] = array(
     'title' => 'Access',
@@ -97,6 +106,10 @@ function tripal_entities_theme($existing, $type, $theme, $path) {
       'template' => 'tripal_entity',
       'path' => "$path/theme/templates"
     ),
+    'tripal_entities_date_combo' => array(
+      'render element' => 'element',
+      'file' => 'includes/tripal_entities.chado_entity.inc',
+    ),
   );
 }
 

+ 90 - 0
tripal_fields/api/tripal_fields.api.inc

@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Adds a field to an Entity bundle.
+ *
+ * @param $field_name
+ *   The name of the field.
+ * @param $field_info
+ *   An associative array containing the field information.  The following
+ *   key/value pairs are supported:
+ *     'field_type' : a valid field type.  May be any of the Drupal default
+ *       fields, one created by the tripal_fields module or another custom module.
+ *     'widget_type' : a valid widget type. May be any of the Drupal default
+ *       fields, one created by the tripal_fields module or another custom module.
+ *     'field_settings' : an array of settings that are appropriate for the
+ *       selected field type.
+ *     'widget_settings' : an array of settings that are appropriate for the
+ *       selected widget type.
+ *     'description' :  a default description for this field.
+ *     'label' : a label used as a header for this field.
+ *     'is_required' : indicates if the field is required in the edit form.
+ *     'cardinality' : indicates the number of values this field can support.
+ *       the default is 1 (meaning only one value). Use a value of
+ *       FIELD_CARDINALITY_UNLIMITED for unlimited number of values.
+ *   You may add additional key/value pairs as needed by your custom module
+ *   if your module adds a new field type.  The following fields are examples
+ *   that are added automatically by the tripal_fields module.  These
+ *   fields are expected when modules implement the hook_chado_field_alter()
+ *   function:
+ *     'chado_table' : the name of the table in Chado that will house the
+ *       value(s) of this field.
+ *     'chado_column' : the column in the Chado table where the field will go.
+ * @param $entity_type_name
+ *   The entity type name.
+ * @param $bundle_name
+ *   The bundle name.
+ *
+ */
+function tripal_add_bundle_field($field_name, $field_info,
+    $entity_type_name, $bundle_name) {
+
+      $field = field_info_field($field_name);
+
+      // If the field exists and is attached to this bundle then just return,
+      // there is nothing left to do.
+      if ($field and array_key_exists('bundles', $field) and
+          array_key_exists($entity_type_name, $field['bundles']) and
+          in_array($bundle_name, $field['bundles'][$entity_type_name])) {
+            return;
+          }
+
+          // Allow other modules to alter the field information array.
+          drupal_alter('chado_field', $field_info);
+
+          $cardinality = 1;
+          if (array_key_exists('cardinality', $field_info) and is_numeric($field_info['cardinality'])) {
+            $cardinality = $field_info['cardinality'];
+          }
+
+          // If the field doesn't exist then create it.
+          if (!$field) {
+            $field = array(
+              'field_name' => $field_name,
+              'type' => $field_info['field_type'],
+              'cardinality' => $cardinality,
+              'locked' => FALSE,
+              'storage' => array(
+                'type' => 'field_chado_storage'
+              ),
+              'settings' => $field_info['field_settings'],
+            );
+            field_create_field($field);
+          }
+
+          // Attach the field to the bundle.
+          $field_instance = array(
+            'field_name' => $field_name,
+            'label' => $field_info['label'],
+            'description' => $field_info['description'],
+            'widget' => array(
+              'type' => $field_info['widget_type'],
+              'settings' => $field_info['widget_settings'],
+            ),
+            'entity_type' => $entity_type_name,
+            'required' => $field_info['is_required'],
+            'settings' => $field_info['field_settings'],
+            'bundle' => $bundle_name,
+          );
+          field_create_instance($field_instance);
+}

+ 51 - 23
tripal_fields/includes/fields/kvproperty.inc

@@ -30,37 +30,65 @@ function tripal_fields_kvproperty_formatter(&$element, $entity_type, $entity, $f
  * @param unknown $delta
  * @param unknown $element
  */
-function tripal_fields_kvproperty_widget($field_name, &$widget,
-  &$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+function tripal_fields_kvproperty_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
-  $widget += array(
+  $field_name = $field['field_name'];
+  $widget = array();
+  $element += array(
     '#element_validate' => array('tripal_fields_kvproperty_widget_validate'),
-    '#type' => 'fieldset',
-    '#title' => $element['#title'],
-    '#description' =>  $element['#description'],
-    '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+    '#type' => 'textfield',
     '#delta' => $delta,
-    '#group' => 'entity_vetical_tabs',
-    array(
-      'kvproperty' => array(
-        '#title' => t('Property Type'),
-        '#type' => 'textfield',
-        '#description' => t("Please enter the type of property that you want to add.  As you type, suggestions will be provided."),
-        '#autocomplete_path' => "eadmin/tripal/chado/tripal_cv/cvterm/auto_name/",
-      ),
-      'kvproperty_add' => array(
-        '#value' => t('Add fields for property type'),
-        '#type' => 'button',
-        '#name' => 'kvproperty_add',
-      ),
-    ),
   );
+
+  if ($field['cardinality'] == 1) {
+    $element['#default_value'] = !empty($items) ? $items[0] : '';
+    $widget = array($element);
+  }
+  else {
+    foreach ($items as $item) {
+      $widget[$delta] = $element;
+      $widget[$delta]['#default_value'] = $item;
+      $widget[$delta]['#weight'] = $delta;
+      $delta++;
+    }
+  }
+  // Add one more row if delta is less than the cardinality.
+  if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta < $field['cardinality']){
+    $widget[$delta] = $element;
+    $widget[$delta]['#default_value'] = '';
+    $widget[$delta]['#weight'] = $delta;
+    $widget[$delta]['#required'] = ($element['#required'] && $delta == 0);
+  }
+
+  // The group of elements all-together need some extra functionality
+  // after building up the full list (like draggable table rows).
+  $widget['#theme'] = 'field_multiple_value_form';
+  $widget['#title'] = $element['#title'];
+  $widget['#description'] = $element['#description'];
+  $widget['#field_name'] = $element['#field_name'];
+  $widget['#language'] = $element['#language'];
+  $widget['#weight'] = isset($element['#weight']) ? $element['#weight'] : 0;
+  $widget['#cardinality'] = 1;
+  return $widget;
 }
 
+/**
+ *
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function tripal_fields_kvproperty_widget_form_ajax_callback($form, $form_state) {
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  return $form[$field_name];
+}
 /**
  * Callback function for validating the tripal_fields_kvproperty_widget.
  */
 function tripal_fields_kvproperty_widget_validate($element, &$form_state) {
-  // Add the new field to the entity
-  //$form_state['rebuild'] = TRUE;
+   $field_name = $element['#field_name'];
+}
+/**
+ * Callback function for submitting the tripal_fields_kvproperty_widget.
+ */
+function tripal_fields_kvproperty_widget_submit($element, &$form_state) {
 }

+ 125 - 0
tripal_fields/includes/fields/kvproperty_adder.inc

@@ -0,0 +1,125 @@
+<?php
+
+/**
+ *
+ * @param unknown $entity_type
+ * @param unknown $entity
+ * @param unknown $field
+ * @param unknown $instance
+ * @param unknown $langcode
+ * @param unknown $items
+ * @param unknown $display
+ */
+function tripal_fields_kvproperty_adder_formatter(&$element, $entity_type, $entity, $field,
+  $instance, $langcode, $items, $display) {
+
+  foreach ($items as $delta => $item) {
+    // Do nothing, this field is only meant for the form.
+  }
+}
+/**
+ *
+ * @param unknown $field_name
+ * @param unknown $widget
+ * @param unknown $form
+ * @param unknown $form_state
+ * @param unknown $field
+ * @param unknown $instance
+ * @param unknown $langcode
+ * @param unknown $items
+ * @param unknown $delta
+ * @param unknown $element
+ */
+function tripal_fields_kvproperty_adder_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+
+  $field_name = $field['field_name'];
+  $widget = $element;
+  $widget += array(
+    '#element_validate' => array('tripal_fields_kvproperty_adder_widget_validate'),
+    '#type' => 'fieldset',
+    '#title' => $element['#title'],
+    '#group' => 'ev_tabs',
+    array(
+      'kvproperty_instructions' => array(
+        '#type' => 'item',
+        '#markup' => t('You may add additional properties to this form by
+            providing a property name (from a vocabulary) in the field below
+            and clicking the "Add Property" button.  This will add a
+            new field to the form above for the property you entered.'),
+      ),
+      'kvproperty_adder' => array(
+        '#title' => t('Property Type'),
+        '#type' => 'textfield',
+        '#description' => t("Please enter the type of property that you want to add.  As you type, suggestions will be provided."),
+        '#autocomplete_path' => "admin/tripal/chado/tripal_cv/cvterm/auto_name/",
+      ),
+      'kvproperty_adder_link' => array(
+        '#type' => 'item',
+        '#markup' => '<span class="kvproperty-adder-link">' . l('Add a term', 'admin/tripal/chado/tripal_cv/cvterm/add', array('attributes' => array('target' => '_blank'))) . '</span>',
+      ),
+      // When this button is clicked, the form will be validated and submitted.
+      // Therefore, we set custom submit and validate functions to override the
+      // default form submit.  In the validate function we set the form_state
+      // to rebuild the form so the submit function never actually gets called,
+      // but we need it or Drupal will run the default validate anyway.
+      // we also set #limit_validation_errors to empty so fields that
+      // are required that don't have values won't generate warnings.
+      'kvproperty_adder_button' => array(
+        '#value' => t('Add Property'),
+        '#type' => 'submit',
+        '#name' => 'kvproperty_adder_button',
+        '#validate' => 'tripal_fields_kvproperty_adder_widget_validate',
+        '#submit' => 'tripal_fields_kvproperty_adder_widget_submit',
+        '#limit_validation_errors' => array(array($field_name)),
+      ),
+    ),
+  );
+  return $widget;
+}
+
+/**
+ * Callback function for validating the tripal_fields_kvproperty_adder_widget.
+ */
+function tripal_fields_kvproperty_adder_widget_validate($element, &$form_state) {
+
+   // Add the new field to the entity
+   if (array_key_exists('triggering_element', $form_state) and
+       $form_state['triggering_element']['#name'] == 'kvproperty_adder_button') {
+
+     $form_state['rebuild'] = TRUE;
+
+     $field_name = $element['#field_name'];
+     $entity_type = $element['#entity_type'];
+     $bundle = $element['#bundle'];
+
+     // Get the term for the property
+     $kvproperty = tripal_fields_get_field_form_values($field_name, $form_state, 'kvproperty_adder');
+     $term = chado_generate_var('cvterm', array('name' => $kvproperty), $options = array('return_array' => TRUE));
+     if (count($term) == 1) {
+       $prop_field_name = $field_name . '__' . strtolower($term[0]->dbxref_id->db_id->name) . '_' . $term[0]->dbxref_id->accession;
+       $field_info = array(
+         'field_type' => 'kvproperty',
+         'widget_type' => 'tripal_fields_kvproperty_widget',
+         'field_settings' => array(),
+         'widget_settings' => array(),
+         'description' => '',
+         'label' => ucfirst(preg_replace('/_/', ' ', $term[0]->name)),
+         'is_required' => FALSE,
+         // All properties are unlimited.
+         'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+       );
+       tripal_add_bundle_field($prop_field_name, $field_info, $entity_type, $bundle);
+     }
+     else if (count($term) > 1) {
+       form_set_error(implode('][', $element ['#parents']) . '][0][kvproperty_adder', t("This term is present in multiple vocabularies. Please select the appropriate one."));
+     }
+     else {
+       form_set_error(implode('][', $element ['#parents']) . '][0][kvproperty_adder', t("Please provide a property type to add."));
+     }
+   }
+}
+/**
+ * Callback function for submitting the tripal_fields_kvproperty_adder_widget.
+ */
+function tripal_fields_kvproperty_adder_widget_submit($element, &$form_state) {
+}

+ 9 - 6
tripal_fields/includes/fields/md5checksum.inc

@@ -34,10 +34,11 @@ function tripal_fields_md5checksum_checkbox_formatter(&$element, $entity_type, $
  * @param unknown $delta
  * @param unknown $element
  */
-function tripal_fields_md5checksum_checkbox_widget($field_name, &$widget,
-  &$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+function tripal_fields_md5checksum_checkbox_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
-  $widget += array(
+  $field_name = $field['field_name'];
+  $widget = $element;
+  $widget +=  array(
     '#type' => 'checkbox',
     '#title' => $element['#title'],
     '#description' => $element['#description'],
@@ -47,6 +48,7 @@ function tripal_fields_md5checksum_checkbox_widget($field_name, &$widget,
     '#delta' => $delta,
     '#element_validate' => array('tripal_fields_md5checksum_checkbox_widget_validate'),
   );
+  return $widget;
 }
 /**
  * Callback function for validating the tripal_fields_md5checksum_checkbox_widget.
@@ -54,13 +56,14 @@ function tripal_fields_md5checksum_checkbox_widget($field_name, &$widget,
 function tripal_fields_md5checksum_checkbox_widget_validate($element, &$form_state) {
   $field_name = $element['#field_name'];
 
-  // Calculate the md5 checksum for the sequence only if md5 box is checked and the residues exist
+  // Calculate the md5 checksum for the sequence only if md5 box is checked and
+  // the residues exist.
   $residues = tripal_fields_get_field_form_values('feature__residues', $form_state);
   if (count($residues) > 0 && trim($residues[0]) != '') {
-    tripal_fields_set_field_form_values ($field_name, $form_state, md5($residues[0]));
+    tripal_fields_set_field_form_values($field_name, $form_state, md5($residues[0]));
   }
   else {
     // Otherwise, remove the md5 value
-    tripal_fields_set_field_form_values ($field_name, $form_state, '__NULL__');
+    tripal_fields_set_field_form_values($field_name, $form_state, '__NULL__');
   }
 }

+ 6 - 5
tripal_fields/includes/fields/organism_id.inc

@@ -35,10 +35,10 @@ function tripal_fields_organism_select_formatter(&$element, $entity_type, $entit
  * @param unknown $delta
  * @param unknown $element
  */
-function tripal_fields_organism_select_widget($field_name, &$widget,
-  &$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-
+function tripal_fields_organism_select_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+  $field_name = $field['field_name'];
   $options = tripal_get_organism_select_options();
+  $widget = $element;
   $widget += array(
     '#type' => 'select',
     '#title' => $element['#title'],
@@ -50,13 +50,14 @@ function tripal_fields_organism_select_widget($field_name, &$widget,
     '#delta' => $delta,
     '#element_validate' => array('tripal_fields_organism_select_widget_validate'),
   );
-  $element['value'] = $widget;
+  return $widget;
 }
 
 /**
  * Callback function for validating the tripal_fields_organism_select_widget.
  */
 function tripal_fields_organism_select_widget_validate($element, &$form_state) {
+  //dpm($element);
   $field_name = $element['#field_name'];
 
   // If the form ID is field_ui_field_edit_form, then the user is editing the
@@ -68,6 +69,6 @@ function tripal_fields_organism_select_widget_validate($element, &$form_state) {
   $organism_id = tripal_fields_get_field_form_values($field_name, $form_state);
 
   if (count($organism_id) == 0) {
-    form_error($element, t("Please specify an organism that already exists in the database."));
+    form_error($element, t("Please specify an organism."));
   }
 }

+ 9 - 4
tripal_fields/includes/fields/primary_dbxref.inc

@@ -41,8 +41,10 @@ function tripal_fields_primary_dbxref_formatter(&$element, $entity_type, $entity
  * @param unknown $delta
  * @param unknown $element
  */
-function tripal_fields_primary_dbxref_widget($field_name, &$widget,
-  &$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+function tripal_fields_primary_dbxref_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+
+  $widget = $element;
+  $field_name = $field['field_name'];
 
   // Get the field defaults from the database if a record exists.
   $dbxref_id = '';
@@ -65,7 +67,7 @@ function tripal_fields_primary_dbxref_widget($field_name, &$widget,
 
   $schema = chado_get_schema('dbxref');
   $options = tripal_get_db_select_options();
-  $widget += array(
+  $widget +=  array(
     '#element_validate' => array('tripal_fields_primary_dbxref_widget_validate'),
     '#type' => 'fieldset',
     '#title' => $element['#title'],
@@ -73,7 +75,9 @@ function tripal_fields_primary_dbxref_widget($field_name, &$widget,
     '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
     '#delta' => $delta,
     '#theme' => 'tripal_fields_primary_dbxref_widget',
-#    '#group' => 'entity_vetical_tabs',
+    '#group' => 'entity_vetical_tabs',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
     array(
       $element['#field_name'] => array(
         '#type' => 'hidden',
@@ -124,6 +128,7 @@ function tripal_fields_primary_dbxref_widget($field_name, &$widget,
     '#prefix' => "<span id='$field_name-dbxref--db-id'>",
     '#suffix' => "</span>"
   );
+  return $widget;
 }
 /**
  * An Ajax callback for the tripal_fields_admin_publish_form..

+ 5 - 3
tripal_fields/includes/fields/residues.inc

@@ -37,9 +37,10 @@ function tripal_fields_residues_textarea_formatter(&$element, $entity_type, $ent
  * @param unknown $delta
  * @param unknown $element
  */
-function tripal_fields_residues_textarea_widget($field_name, &$widget,
-  &$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+function tripal_fields_residues_textarea_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
+  $field_name = $field['field_name'];
+  $widget = $element;
   $widget += array(
     '#type' => 'textarea',
     '#title' => $element['#title'],
@@ -49,7 +50,8 @@ function tripal_fields_residues_textarea_widget($field_name, &$widget,
     '#delta' => $delta,
     '#element_validate' => array('tripal_fields_residues_textarea_widget_validate'),
   );
-  $element['value'] = $widget;
+   return $widget;
+
 }
 /**
  * Callback function for validating the tripal_fields_residues_textarea_widget.

+ 6 - 5
tripal_fields/includes/fields/seqlen.inc

@@ -36,10 +36,11 @@ function tripal_fields_seqlen_hidden_formatter(&$element, $entity_type, $entity,
  * @param unknown $delta
  * @param unknown $element
  */
-function tripal_fields_seqlen_hidden_widget($field_name, &$widget,
-  &$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+function tripal_fields_seqlen_hidden_widget($form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
-  $widget += array(
+  $field_name = $field['field_name'];
+  $widget = $element;
+  $widget +=  array(
     '#type' => 'hidden',
     '#title' => $element['#title'],
     '#description' => $element['#description'],
@@ -47,7 +48,7 @@ function tripal_fields_seqlen_hidden_widget($field_name, &$widget,
     '#delta' => $delta,
     '#element_validate' => array('tripal_fields_seqlen_hidden_widget_validate'),
   );
-  $element['value'] = $widget;
+  return $widget;
 }
 /**
  * Callback function for validating the tripal_fields_seqlen_hidden_widget.
@@ -65,6 +66,6 @@ function tripal_fields_seqlen_hidden_widget_validate($element, &$form_state) {
   }
   else {
     // Otherwise, remove the md5 value
-    tripal_fields_set_field_form_values ($field_name, $form_state, '__NULL__');
+    tripal_fields_set_field_form_values($field_name, $form_state, '__NULL__');
   }
 }

+ 0 - 311
tripal_fields/includes/tripal_fields.fields.inc

@@ -1,311 +0,0 @@
-<?php
-
-/**
- * Implements hook_field_info().
- */
-function tripal_fields_field_info() {
-  $fields = array(
-    'organism_id' => array(
-      'label' => t('Organism'),
-      'description' => t('A field for specifying an organism.'),
-      'default_widget' => 'tripal_fields_organism_select_widget',
-      'default_formatter' => 'tripal_fields_organism_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_fields',
-        'active' => TRUE
-      ),
-    ),
-    'dbxref_id' => array(
-      'label' => t('Cross-reference'),
-      'description' => t('This record can be cross-referenced with a record in another online database. This field is intended for the most prominent reference.  At a minimum, the database and accession must be provided.'),
-      'default_widget' => 'tripal_fields_primary_dbxref_widget',
-      'default_formatter' => 'tripal_fields_primary_dbxref_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_fields',
-        'active' => TRUE
-      ),
-    ),
-    'residues' => array(
-      'label' => t('Residues'),
-      'description' => t('A field for managing nucleotide and protein residues.'),
-      'default_widget' => 'tripal_fields_residue_textarea_widget',
-      'default_formatter' => 'tripal_fields_residues_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_fields',
-        'active' => TRUE
-      ),
-    ),
-    'md5checksum' => array(
-      'label' => t('MD5 checksum'),
-      'description' => t('A field for generating MD5 checksum for a sequence.'),
-      'default_widget' => 'tripal_fields_md5checksum_checkbox_widget',
-      'default_formatter' => 'tripal_fields_md5checksum_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_fields',
-        'active' => TRUE
-      ),
-    ),
-    'seqlen' => array(
-      'label' => t('Sequence length'),
-      'description' => t('A field for calculating the length of a sequence.'),
-      'default_widget' => 'tripal_fields_seqlen_hidden_widget',
-      'default_formatter' => 'tripal_fields_seqlen_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_fields',
-        'active' => TRUE
-      ),
-    ),
-    // The field provides a widget for adding new properties
-    // to an entity that is connected to a base table that has a prop table
-    // in Chado.
-    'kvproperty' => array(
-      'label' => t('Add a Property Type'),
-      'description' => t('This record may have any number of properties. Use this field to first add the type.'),
-      'default_widget' => 'tripal_fields_kvproperty_widget',
-      'default_formatter' => 'tripal_fields_kvproperty_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_fields',
-        'active' => TRUE
-      ),
-    ),
-  );
-  return $fields;
-}
-
-/**
- * Implements hook_field_widget_info().
- */
-function tripal_fields_field_widget_info() {
-  return array(
-    'tripal_fields_organism_select_widget' => array(
-      'label' => t('Organism Select'),
-      'field types' => array('organism_id')
-    ),
-    'tripal_fields_primary_dbxref_widget' => array(
-      'label' => t('Cross-reference'),
-      'field types' => array('dbxref_id'),
-      'description' => t('This record can be cross-referenced with a record in another online database. This field is intended for the most prominent reference.  At a minimum, the database and accession must be provided.'),
-    ),
-    'tripal_fields_md5checksum_checkbox_widget' => array(
-      'label' => t('MD5 Checksum Checkbox'),
-      'field types' => array('md5checksum'),
-    ),
-    'tripal_fields_residues_textarea_widget' => array(
-      'label' => t('Residues'),
-      'field types' => array('residues'),
-    ),
-    'tripal_fields_seqlen_hidden_widget' => array(
-      'label' => t('Sequence Length'),
-      'field types' => array('seqlen'),
-    ),
-    'tripal_fields_kvproperty_widget' => array(
-      'label' => t('Property'),
-      'field types' => array('kvproperty'),
-    ),
-  );
-}
-/**
- * Implements hook_field_formatter_info().
- */
-function tripal_fields_field_formatter_info() {
-  return array(
-    'tripal_fields_organism_formatter' => array(
-      'label' => t('Organism'),
-      'field types' => array('organism_id')
-    ),
-    'tripal_fields_primary_dbxref_formatter' => array(
-      'label' => t('Cross-reference'),
-      'field types' => array('dbxref_id')
-    ),
-    'tripal_fields_md5checksum_formatter' => array(
-      'label' => t('MD5 checksum'),
-      'field types' => array('md5checksum')
-    ),
-    'tripal_fields_residues_formatter' => array(
-      'label' => t('Residues'),
-      'field types' => array('residues')
-    ),
-    'tripal_fields_seqlen_formatter' => array(
-      'label' => t('Sequence length'),
-      'field types' => array('seqlen')
-    ),
-    'tripal_fields_kvproperty_formatter' => array(
-      'label' => t('Property'),
-      'field types' => array('kvproperty')
-    ),
-  );
-}
-/**
- * Implements hook_field_formatter_view().
- *
- * Two formatters are implemented.
- * - field_example_simple_text just outputs markup indicating the color that
- *   was entered and uses an inline style to set the text color to that value.
- * - field_example_color_background does the same but also changes the
- *   background color of div.region-content.
- *
- * @see field_example_field_formatter_info()
- */
-function tripal_fields_field_formatter_view($entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
-
-  $element = array();
-  switch ($display['type']) {
-
-    case 'tripal_fields_organism_formatter':
-      module_load_include('inc', 'tripal_fields', 'includes/fields/organism_id');
-      tripal_fields_organism_select_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_fields_primary_dbxref_formatter':
-      module_load_include('inc', 'tripal_fields', 'includes/fields/primary_dbxref');
-      tripal_fields_primary_dbxref_formatter($element, $entity_type, $entity, $field,
-        $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_fields_md5checksum_formatter':
-      module_load_include('inc', 'tripal_fields', 'includes/fields/md5checksum');
-      tripal_fields_md5checksum_checkbox_formatter($element, $entity_type, $entity, $field,
-        $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_fields_residues_formatter':
-      module_load_include('inc', 'tripal_fields', 'includes/fields/residues');
-      tripal_fields_residues_textarea_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_fields_seqlen_formatter':
-      module_load_include('inc', 'tripal_fields', 'includes/fields/seqlen');
-      tripal_fields_seqlen_hidden_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_fields_kvproperty_formatter':
-      module_load_include('inc', 'tripal_fields', 'includes/fields/kvproperty');
-      tripal_fields_kvproperty_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-  }
-  return $element;
-}
-
-/**
- * Implements hook_field_widget_form().
- */
-function tripal_fields_field_widget_form(&$form, &$form_state, $field,
-  $instance, $langcode, $items, $delta, $element) {
-
-  $widget = $element;
-  $widget['#delta'] = $delta;
-  $field_name = $field['field_name'];
-
-  switch ($instance['widget']['type']) {
-    case 'tripal_fields_organism_select_widget':
-      // Make sure the include files get parsed now and for the form submits.
-      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/organism_id');
-      module_load_include('inc', 'tripal_fields', 'includes/fields/organism_id');
-      // Update the widget with the new field.
-      tripal_fields_organism_select_widget($field_name, $widget, $form,
-          $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      $element['value'] = $widget;
-      break;
-    case 'tripal_fields_primary_dbxref_widget':
-      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/primary_dbxref');
-      module_load_include('inc', 'tripal_fields', 'includes/fields/primary_dbxref');
-      tripal_fields_primary_dbxref_widget($field_name, $widget, $form,
-        $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      $element['value'] = $widget;
-      break;
-    case 'tripal_fields_md5checksum_checkbox_widget':
-      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/md5checksum');
-      module_load_include('inc', 'tripal_fields', 'includes/fields/md5checksum');
-      tripal_fields_md5checksum_checkbox_widget($field_name, $widget,
-          $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      $element['value'] = $widget;
-      break;
-    case 'tripal_fields_residues_textarea_widget':
-      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/residues');
-      module_load_include('inc', 'tripal_fields', 'includes/fields/residues');
-      tripal_fields_residues_textarea_widget($field_name, $widget,
-          $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      $element['value'] = $widget;
-      break;
-    case 'tripal_fields_seqlen_hidden_widget':
-      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/seqlen');
-      module_load_include('inc', 'tripal_fields', 'includes/fields/seqlen');
-      tripal_fields_seqlen_hidden_widget($field_name, $widget,
-          $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      $element['value'] = $widget;
-      break;
-    case 'tripal_fields_kvproperty_widget':
-      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/kvproperty');
-      module_load_include('inc', 'tripal_fields', 'includes/fields/kvproperty');
-      tripal_fields_kvproperty_widget($field_name, $widget,
-          $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      $element['value'] = $widget;
-      break;
-  }
-  return $element;
-}
-
-
-/**
- * Implements hook_field_is_empty().
- */
-function tripal_fields_field_is_empty($item, $field) {
-  if (empty($item['value']) && (string) $item['value'] !== '0') {
-    return TRUE;
-  }
-  return FALSE;
-}
-
-/**
- * Returns the values of the field from the $form_state.
- */
-function tripal_fields_get_field_form_values($field_name, $form_state, $child = NULL) {
-  $values = array();
-  if (!array_key_exists('values', $form_state)) {
-    return $values;
-  }
-  if (array_key_exists($field_name, $form_state['values'])) {
-    foreach ($form_state['values'][$field_name] as $langcode => $items) {
-      foreach ($items as $delta => $value) {
-        if ($child and array_key_exists($child, $value['value'][0]) and $value['value'][0][$child]) {
-          $values[] = $value['value'][0][$child];
-        }
-        else if (!$child and $value['value']) {
-          $values[] = $value['value'];
-        }
-      }
-    }
-  }
-  return $values;
-}
-
-/**
- * Returns the values of the field from the $form_state.
- */
-function tripal_fields_set_field_form_values($field_name, &$form_state, $newvalue, $child = NULL) {
-  $values = array();
-  foreach ($form_state['values'][$field_name] as $langcode => $items) {
-    foreach ($items as $delta => $value) {
-      if ($child and array_key_exists($child, $value['value'][0]) and $value['value'][0][$child]) {
-        $form_state['values'][$field_name][$langcode][$delta]['value'][0][$child] = $newvalue;
-      }
-      else if (!$child) {
-        $form_state['values'][$field_name][$langcode][$delta]['value'] = $newvalue;
-      }
-    }
-  }
-  return $values;
-}
-

+ 335 - 2
tripal_fields/tripal_fields.module

@@ -1,7 +1,341 @@
 <?php
 
+require_once "api/tripal_fields.api.inc";
 require_once "includes/tripal_fields.field_storage.inc";
-require_once "includes/tripal_fields.fields.inc";
+
+/**
+ * Implements hook_field_info().
+ */
+function tripal_fields_field_info() {
+  $fields = array(
+    'organism_id' => array(
+      'label' => t('Organism'),
+      'description' => t('A field for specifying an organism.'),
+      'default_widget' => 'tripal_fields_organism_select_widget',
+      'default_formatter' => 'tripal_fields_organism_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+    'dbxref_id' => array(
+      'label' => t('Cross-reference'),
+      'description' => t('This record can be cross-referenced with a record in another online database. This field is intended for the most prominent reference.  At a minimum, the database and accession must be provided.'),
+      'default_widget' => 'tripal_fields_primary_dbxref_widget',
+      'default_formatter' => 'tripal_fields_primary_dbxref_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+    'residues' => array(
+      'label' => t('Residues'),
+      'description' => t('A field for managing nucleotide and protein residues.'),
+      'default_widget' => 'tripal_fields_residue_textarea_widget',
+      'default_formatter' => 'tripal_fields_residues_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+    'md5checksum' => array(
+      'label' => t('MD5 checksum'),
+      'description' => t('A field for generating MD5 checksum for a sequence.'),
+      'default_widget' => 'tripal_fields_md5checksum_checkbox_widget',
+      'default_formatter' => 'tripal_fields_md5checksum_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+    'seqlen' => array(
+      'label' => t('Sequence length'),
+      'description' => t('A field for calculating the length of a sequence.'),
+      'default_widget' => 'tripal_fields_seqlen_hidden_widget',
+      'default_formatter' => 'tripal_fields_seqlen_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+    // The field provides a widget for adding new properties
+    // to an entity that is connected to a base table that has a prop table
+    // in Chado.
+    'kvproperty_adder' => array(
+      'label' => t('Add a Property Type'),
+      'description' => t('This record may have any number of properties. Use this field to first add the type.'),
+      'default_widget' => 'tripal_fields_kvproperty_adder_widget',
+      'default_formatter' => 'tripal_fields_kvproperty_adder_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+    // The field provides form elements for adding a property to an entity
+    // that in turn gets stored in a prop table of Chado (e.g. featureprop,
+    // stockprop, etc).
+    'kvproperty' => array(
+      'label' => t('Add a Property'),
+      'description' => t('Add details about this property.'),
+      'default_widget' => 'tripal_fields_kvproperty_widget',
+      'default_formatter' => 'tripal_fields_kvproperty_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_fields',
+        'active' => TRUE
+      ),
+    ),
+  );
+  return $fields;
+}
+
+/**
+ * Implements hook_field_widget_info().
+ */
+function tripal_fields_field_widget_info() {
+  return array(
+    'tripal_fields_organism_select_widget' => array(
+      'label' => t('Organism Select'),
+      'field types' => array('organism_id')
+    ),
+    'tripal_fields_primary_dbxref_widget' => array(
+      'label' => t('Cross-reference'),
+      'field types' => array('dbxref_id'),
+      'description' => t('This record can be cross-referenced with a record in another online database. This field is intended for the most prominent reference.  At a minimum, the database and accession must be provided.'),
+    ),
+    'tripal_fields_md5checksum_checkbox_widget' => array(
+      'label' => t('MD5 Checksum Checkbox'),
+      'field types' => array('md5checksum'),
+    ),
+    'tripal_fields_residues_textarea_widget' => array(
+      'label' => t('Residues'),
+      'field types' => array('residues'),
+    ),
+    'tripal_fields_seqlen_hidden_widget' => array(
+      'label' => t('Sequence Length'),
+      'field types' => array('seqlen'),
+    ),
+    'tripal_fields_kvproperty_adder_widget' => array(
+      'label' => t('Add a Property'),
+      'field types' => array('kvproperty_adder'),
+    ),
+    'tripal_fields_kvproperty_widget' => array(
+      'label' => t('Property'),
+      'field types' => array('kvproperty'),
+    ),
+  );
+}
+/**
+ * Implements hook_field_formatter_info().
+ */
+function tripal_fields_field_formatter_info() {
+  return array(
+    'tripal_fields_organism_formatter' => array(
+      'label' => t('Organism'),
+      'field types' => array('organism_id')
+    ),
+    'tripal_fields_primary_dbxref_formatter' => array(
+      'label' => t('Cross-reference'),
+      'field types' => array('dbxref_id')
+    ),
+    'tripal_fields_md5checksum_formatter' => array(
+      'label' => t('MD5 checksum'),
+      'field types' => array('md5checksum')
+    ),
+    'tripal_fields_residues_formatter' => array(
+      'label' => t('Residues'),
+      'field types' => array('residues')
+    ),
+    'tripal_fields_seqlen_formatter' => array(
+      'label' => t('Sequence length'),
+      'field types' => array('seqlen')
+    ),
+    'tripal_fields_kvproperty_adder_formatter' => array(
+      'label' => t('Add a Property'),
+      'field types' => array('kvproperty_adder')
+    ),
+    'tripal_fields_kvproperty_formatter' => array(
+      'label' => t('Property'),
+      'field types' => array('kvproperty')
+    ),
+  );
+}
+/**
+ * Implements hook_field_formatter_view().
+ *
+ * Two formatters are implemented.
+ * - field_example_simple_text just outputs markup indicating the color that
+ *   was entered and uses an inline style to set the text color to that value.
+ * - field_example_color_background does the same but also changes the
+ *   background color of div.region-content.
+ *
+ * @see field_example_field_formatter_info()
+ */
+function tripal_fields_field_formatter_view($entity_type, $entity, $field,
+    $instance, $langcode, $items, $display) {
+
+      $element = array();
+      switch ($display['type']) {
+
+        case 'tripal_fields_organism_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/organism_id');
+          tripal_fields_organism_select_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+        case 'tripal_fields_primary_dbxref_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/primary_dbxref');
+          tripal_fields_primary_dbxref_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+        case 'tripal_fields_md5checksum_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/md5checksum');
+          tripal_fields_md5checksum_checkbox_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+        case 'tripal_fields_residues_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/residues');
+          tripal_fields_residues_textarea_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+        case 'tripal_fields_seqlen_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/seqlen');
+          tripal_fields_seqlen_hidden_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+        case 'tripal_fields_kvproperty_adder_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/kvproperty_adder');
+          tripal_fields_kvproperty_adder_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+        case 'tripal_fields_kvproperty_formatter':
+          module_load_include('inc', 'tripal_fields', 'includes/fields/kvproperty');
+          tripal_fields_kvproperty_formatter($element, $entity_type, $entity, $field,
+              $instance, $langcode, $items, $display);
+          break;
+      }
+      return $element;
+}
+
+/**
+ * Implements hook_field_widget_form().
+ */
+function tripal_fields_field_widget_form(&$form, &$form_state, $field,
+    $instance, $langcode, $items, $delta, $element) {
+
+  switch ($instance['widget']['type']) {
+    case 'tripal_fields_organism_select_widget':
+      // Make sure the include files get parsed now and for the form submits.
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/organism_id');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/organism_id');
+      // Update the widget with the new field.
+      $element['value'] = tripal_fields_organism_select_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_fields_primary_dbxref_widget':
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/primary_dbxref');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/primary_dbxref');
+      $element['value'] = tripal_fields_primary_dbxref_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_fields_md5checksum_checkbox_widget':
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/md5checksum');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/md5checksum');
+      $element['value'] = tripal_fields_md5checksum_checkbox_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_fields_residues_textarea_widget':
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/residues');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/residues');
+      $element['value'] = tripal_fields_residues_textarea_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_fields_seqlen_hidden_widget':
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/seqlen');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/seqlen');
+      $element['value'] = tripal_fields_seqlen_hidden_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_fields_kvproperty_adder_widget':
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/kvproperty_adder');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/kvproperty_adder');
+      $element['value'] = tripal_fields_kvproperty_adder_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_fields_kvproperty_widget':
+      form_load_include($form_state, 'inc', 'tripal_fields', 'includes/fields/kvproperty');
+      module_load_include('inc', 'tripal_fields', 'includes/fields/kvproperty');
+      $element['value'] = tripal_fields_kvproperty_widget($form,
+          $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+  }
+
+  return $element;
+}
+
+
+/**
+ * Implements hook_field_is_empty().
+ */
+function tripal_fields_field_is_empty($item, $field) {
+  if (empty($item['value']) && (string) $item['value'] !== '0') {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Returns the values of the field from the $form_state.
+ */
+function tripal_fields_get_field_form_values($field_name, $form_state, $child = NULL) {
+  $values = array();
+  if (!array_key_exists('values', $form_state)) {
+    return $values;
+  }
+  if (array_key_exists($field_name, $form_state['values'])) {
+    foreach ($form_state['values'][$field_name] as $langcode => $items) {
+      foreach ($items as $delta => $value) {
+        if ($child and array_key_exists($child, $value['value'][0]) and $value['value'][0][$child]) {
+          $values[] = $value['value'][0][$child];
+        }
+        else if (!$child and is_array($value) and $value['value']) {
+          $values[] = $value['value'];
+        }
+      }
+    }
+  }
+  return $values;
+}
+
+/**
+ * Returns the values of the field from the $form_state.
+ */
+function tripal_fields_set_field_form_values($field_name, &$form_state, $newvalue, $child = NULL) {
+  $values = array();
+  foreach ($form_state['values'][$field_name] as $langcode => $items) {
+    foreach ($items as $delta => $value) {
+      if ($child and array_key_exists($child, $value['value'][0]) and $value['value'][0][$child]) {
+        $form_state['values'][$field_name][$langcode][$delta]['value'][0][$child] = $newvalue;
+      }
+      else if (!$child) {
+        $form_state['values'][$field_name][$langcode][$delta]['value'] = $newvalue;
+      }
+    }
+  }
+  return $values;
+}
 
 
 /**
@@ -16,4 +350,3 @@ function tripal_fields_theme($existing, $type, $theme, $path) {
   );
 }
 
-

+ 2 - 2
tripal_pub/includes/tripal_pub.pub_importers.inc

@@ -300,11 +300,11 @@ function tripal_pub_importer_setup_form($form, &$form_state = NULL, $pub_import_
   }
 
   if (array_key_exists('triggering_element', $form_state) and
-  $form_state['triggering_element']['#name'] == 'add') {
+      $form_state['triggering_element']['#name'] == 'add') {
     $num_criteria++;
   }
   if (array_key_exists('triggering_element', $form_state) and
-  $form_state['triggering_element']['#name'] == 'remove') {
+      $form_state['triggering_element']['#name'] == 'remove') {
     $num_criteria--;
   }