Browse Source

Merge pull request #254 from statonlab/staton/protocol_field

Protocol field
Stephen Ficklin 7 years ago
parent
commit
00454a5261

+ 3 - 0
tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact_widget.inc

@@ -24,7 +24,10 @@ class chado_linker__contact_widget extends ChadoFieldWidget {
     // Get the FK column that links to the base table.
     $schema = chado_get_schema($field_table);
     $pkey = $schema['primary key'][0];
+
     $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
+//    $fkey_lcolumn = key($schema['foreign keys']['protocol']['columns']);
+
     $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
 
     // Get the field defaults.

+ 149 - 0
tripal_chado/includes/TripalFields/sep__protocol/sep__protocol.inc

@@ -0,0 +1,149 @@
+<?php
+
+/**
+ * @class
+ * Purpose: Provide a field for Protocol (typically the protocol_id column of a
+ *   Chado table).
+ *
+ * Data:
+ * Assumptions:
+ */
+class sep__protocol extends ChadoField {
+
+  // The default label for this field.
+  public static $default_label = 'Protocol';
+
+  // The default description for this field.
+  public static $default_description = 'The protocol followed to generate this resource.';
+
+  // The default widget for this field.
+  public static $default_widget = 'sep__protocol_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'sep__protocol_formatter';
+
+  // The module that manages this field.
+  public static $module = 'tripal_chado';
+
+  // A list of global settings. These can be accessed within the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  // Once instances exist for a field type then these settings cannot be
+  // changed.
+  public static $default_settings = [
+    'storage' => 'field_chado_storage',
+    // It is expected that all fields set a 'value' in the load() function.
+    // In many cases, the value may be an associative array of key/value pairs.
+    // In order for Tripal to provide context for all data, the keys should
+    // be a controlled vocabulary term (e.g. rdfs:type). Keys in the load()
+    // function that are supported by the query() function should be
+    // listed here.
+    'searchable_keys' => [],
+  ];
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instance.
+  // It is recommended to put settings at the instance level whenever possible.
+  // If you override this variable in a child class be sure to replicate the
+  // term_name, term_vocab, term_accession and term_fixed keys as these are
+  // required for all TripalFields.
+  public static $default_instance_settings = [
+    // The DATABASE name, as it appears in chado.db.  This also builds the link-out url.  In most cases this will simply be the CV name.  In some cases (EDAM) this will be the SUBONTOLOGY.
+    'term_vocabulary' => 'sep',
+    // The name of the term.
+    'term_name' => 'protocol',
+    // The unique ID (i.e. accession) of the term.
+    'term_accession' => '00101',
+    // Set to TRUE if the site admin is not allowed to change the term
+    // type, otherwise the admin can change the term mapped to a field.
+    'term_fixed' => FALSE,
+    // Indicates if this field should be automatically attached to display
+    // or web services or if this field should be loaded separately. This
+    // is convenient for speed.  Fields that are slow should for loading
+    // should have auto_attach set to FALSE so tha their values can be
+    // attached asynchronously.
+    'auto_attach' => FALSE,
+  ];
+
+  // A boolean specifying that users should not be allowed to create
+  // fields and instances of this field type through the UI. Such
+  // fields can only be created programmatically with field_create_field()
+  // and field_create_instance().
+  public static $no_ui = FALSE;
+
+  // A boolean specifying that the field will not contain any data. This
+  // should exclude the field from web services or downloads.  An example
+  // could be a quick search field that appears on the page that redirects
+  // the user but otherwise provides no data.
+  public static $no_data = FALSE;
+
+  /**
+   * Loads the field values from the underlying data store.
+   *
+   * @param $entity
+   *
+   * @return
+   *   An array of the following format:
+   *     $entity->{$field_name}['und'][0]['value'] = $value;
+   *   where:
+   *     - $entity is the entity object to which this field is attached.
+   *     - $field_name is the name of this field
+   *     - 'und' is the language code (in this case 'und' == undefined)
+   *     - 0 is the cardinality.  Increment by 1 when more than one item is
+   *       available.
+   *     - 'value' is the key indicating the value of this field. It should
+   *       always be set.  The value of the 'value' key will be the contents
+   *       used for web services and for downloadable content.  The value
+   *       should be of the follow format types: 1) A single value (text,
+   *       numeric, etc.) 2) An array of key value pair. 3) If multiple entries
+   *       then cardinality should incremented and format types 1 and 2 should
+   *       be used for each item.
+   *   The array may contain as many other keys at the same level as 'value'
+   *   but those keys are for internal field use and are not considered the
+   *   value of the field.
+   *
+   *
+   */
+  public function load($entity) {
+
+    parent::load($entity);
+
+
+    $record = $entity->chado_record;
+    $settings = $this->instance['settings'];
+
+
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+    $linker_field = 'chado-' . $field_table . '__protocol_id';
+
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = [
+      'value' => [],
+    ];
+
+    if (!$record->protocol_id->protocol_id) {
+      return;
+    }
+
+    $protocol_id = $record->protocol_id->protocol_id;
+    $protocol_name = $record->protocol_id->name;
+
+    $entity_id = $record->entity_id;
+
+    $entity->{$field_name}['und'][0]['value'] = [
+      "protocol_id" => $protocol_id,
+      "protocol_name" => $protocol_name,
+      "entity_id" => $entity_id,
+    ];
+
+    // Is there a published entity for this protocol?
+    if (property_exists($record->{$field_column}, 'entity_id')) {
+      $entity->{$field_name}['und'][0]['value']['entity_id'] = 'TripalEntity:' . $record->{$field_column}->entity_id;
+    }
+  }
+
+}

+ 133 - 0
tripal_chado/includes/TripalFields/sep__protocol/sep__protocol_formatter.inc

@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * @class
+ * Purpose:
+ *
+ * Display:
+ * Configuration:
+ */
+class sep__protocol_formatter extends ChadoFieldFormatter {
+
+  // The default label for this field.
+  public static $default_label = 'Protocol';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = ['sep__protocol'];
+
+  // The list of default settings for this formatter.
+  public static $default_settings = [
+    'setting1' => 'default_value',
+  ];
+
+  /**
+   * Provides the field's setting form.
+   *
+   * This function corresponds to the hook_field_formatter_settings_form()
+   * function of the Drupal Field API.
+   *
+   * The settings form appears on the 'Manage Display' page of the content
+   * type administration page. This function provides the form that will
+   * appear on that page.
+   *
+   * To add a validate function, please create a static function in the
+   * implementing class, and indicate that this function should be used
+   * in the form array that is returned by this function.
+   *
+   * This form will not be displayed if the formatter_settings_summary()
+   * function does not return anything.
+   *
+   * param $field
+   *   The field structure being configured.
+   * param $instance
+   *   The instance structure being configured.
+   * param $view_mode
+   *   The view mode being configured.
+   * param $form
+   *   The (entire) configuration form array, which will usually have no use
+   *   here.  Typically for reference only.
+   * param $form_state
+   *   The form state of the (entire) configuration form.
+   *
+   * @return
+   *   A Drupal Form array containing the settings form for this field.
+   */
+  public function settingsForm($view_mode, $form, &$form_state) {
+
+  }
+
+  /**
+   *  Provides the display for a field
+   *
+   * This function corresponds to the hook_field_formatter_view()
+   * function of the Drupal Field API.
+   *
+   *  This function provides the display for a field when it is viewed on
+   *  the web page.  The content returned by the formatter should only include
+   *  what is present in the $items[$delta]['values] array. This way, the
+   *  contents that are displayed on the page, via webservices and downloaded
+   *  into a CSV file will always be identical.  The view need not show all
+   *  of the data in the 'values' array.
+   *
+   * @param $element
+   * @param $entity_type
+   * @param $entity
+   * @param $langcode
+   * @param $items
+   * @param $display
+   *
+   * @return
+   *    An element array compatible with that returned by the
+   *    hook_field_formatter_view() function.
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    if (count($items) > 0) {
+      $protocol_id = $items[0]['value']["protocol_id"];
+      $protocol_name = $items[0]['value']["protocol_name"];
+      $content = $protocol_name;
+      list($entity_type, $entity_id) = explode(':', $items[0]['value']['entity_id']);
+      if ($entity_id) {
+        $content = l($protocol_name, 'bio_data/' . $entity_id);
+      }
+    }
+
+    //cardinality for this field is 1
+    $element[0] = [
+      '#type' => 'markup',
+      '#markup' => $content,
+    ];
+  }
+
+
+  /**
+   * Provides a summary of the formatter settings.
+   *
+   * This function corresponds to the hook_field_formatter_settings_summary()
+   * function of the Drupal Field API.
+   *
+   * On the 'Manage Display' page of the content type administration page,
+   * fields are allowed to provide a settings form.  This settings form can
+   * be used to allow the site admin to define how the field should be
+   * formatted.  The settings are then available for the formatter()
+   * function of this class.  This function provides a text-based description
+   * of the settings for the site developer to see.  It appears on the manage
+   * display page inline with the field.  A field must always return a
+   * value in this function if the settings form gear button is to appear.
+   *
+   * See the hook_field_formatter_settings_summary() function for more
+   * information.
+   *
+   * @param $field
+   * @param $instance
+   * @param $view_mode
+   *
+   * @return string
+   *   A string that provides a very brief summary of the field settings
+   *   to the user.
+   *
+   */
+  public function settingsSummary($view_mode) {
+    return '';
+  }
+
+}

+ 153 - 0
tripal_chado/includes/TripalFields/sep__protocol/sep__protocol_widget.inc

@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * @class
+ * Purpose:
+ *
+ * Data:
+ * Assumptions:
+ */
+class sep__protocol_widget extends ChadoFieldWidget {
+
+  // The default label for this field.
+  public static $default_label = 'Protocol';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = ['sep__protocol'];
+
+  /**
+   * Provides the form for editing of this field.
+   *
+   * This function corresponds to the hook_field_widget_form()
+   * function of the Drupal Field API.
+   *
+   * This form is diplayed when the user creates a new entity or edits an
+   * existing entity.  If the field is attached to the entity then the form
+   * provided by this function will be displayed.
+   *
+   * At a minimum, the form must have a 'value' element.  For Tripal, the
+   * 'value' element of a field always corresponds to the value that is
+   * presented to the end-user either directly on the page (with formatting)
+   * or via web services, or some other mechanism.  However, the 'value' is
+   * sometimes not enough for a field.  For example, the Tripal Chado module
+   * maps fields to table columns and sometimes those columns are foreign keys
+   * therefore, the Tripal Chado modules does not just use the 'value' but adds
+   * additional elements to help link records via FKs.  But even in this case
+   * the 'value' element must always be present in the return form and in such
+   * cases it's value should be set equal to that added in the 'load' function.
+   *
+   * @param $widget
+   * @param $form
+   *   The form structure where widgets are being attached to. This might be a
+   *   full form structure, or a sub-element of a larger form.
+   * @param $form_state
+   *   An associative array containing the current state of the form.
+   * @param $langcode
+   *   The language associated with $items.
+   * @param $items
+   *   Array of default values for this field.
+   * @param $delta
+   *   The order of this item in the array of subelements (0, 1, 2, etc).
+   * @param $element
+   * A form element array containing basic properties for the widget:
+   *  - #entity_type: The name of the entity the field is attached to.
+   *  - #bundle: The name of the field bundle the field is contained in.
+   *  - #field_name: The name of the field.
+   *  - #language: The language the field is being edited in.
+   *  - #field_parents: The 'parents' space for the field in the form. Most
+   *    widgets can simply overlook this property. This identifies the location
+   *    where the field values are placed within $form_state['values'], and is
+   *    used to access processing information for the field through the
+   *    field_form_get_state() and field_form_set_state() functions.
+   *  - #columns: A list of field storage columns of the field.
+   *  - #title: The sanitized element label for the field instance, ready for
+   *    output.
+   *  - #description: The sanitized element description for the field instance,
+   *    ready for output.
+   *  - #required: A Boolean indicating whether the element value is required;
+   *    for required multiple value fields, only the first widget's values are
+   *    required.
+   *  - #delta: The order of this item in the array of subelements; see
+   *    $delta above
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+    $linker_field = 'chado-' . $field_table . '__protocol_id';
+
+    $protocols = [];
+    //options are all protocols
+    //It could be argued that options should only be protocols where protocol_type matches the bundle base table.
+
+    $sql = "SELECT * FROM {protocol}";
+    $results = chado_query($sql);
+    foreach ($results as $protocol) {
+      $protocols[$protocol->protocol_id] = $protocol->name;
+    }
+
+    $widget['value'] = [
+      '#type' => 'select',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#options' => $protocols,
+      '#empty_option' => '- Select a Protocol -',
+      '#required' => $element['#required'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+    ];
+
+  }
+
+  /**
+   * Performs validation of the widgetForm.
+   *
+   * Use this validate to ensure that form values are entered correctly.
+   * The 'value' key of this field must be set in the $form_state['values']
+   * array anytime data is entered by the user.  It may be the case that there
+   * are other fields for helping select a value. In the end those helper
+   * fields must be used to set the 'value' field.
+   */
+  public function validate($element, $form, &$form_state, $langcode, $delta) {
+
+  }
+
+  /**
+   * Performs extra commands when the entity form is submitted.
+   *
+   * Drupal typically does not provide a submit hook for fields.  The
+   * TripalField provides one to allow for behind-the-scenes actions to
+   * occur.   This function should never be used for updates, deletes or
+   * inserts for the Chado table associated with the field.  Rather, the
+   * storage backend should be allowed to handle inserts, updates deletes.
+   * However, it is permissible to perform inserts, updates or deletions within
+   * Chado using this function.  Those operations can be performed if needed but
+   * on other tables not directly associated with the field.
+   *
+   * An example is the chado.feature_synonym table.  The chado_linker__synonym
+   * field allows the user to provide a brand new synonynm and it must add it
+   * to the chado.synonym table prior to the record in the
+   * chado.feature_synonym table.  This insert occurs in the widgetFormSubmit
+   * function.
+   *
+   * @param $form
+   *    The submitted form array.
+   * @param $form_state .
+   *    The form state array.
+   * @param $entity_type
+   *    The type of $entity.
+   * @param $entity
+   *    The entity for the operation.
+   * @param $langcode
+   *    The language associated with $items.
+   * @param $delta
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+  }
+
+}

+ 61 - 0
tripal_chado/includes/tripal_chado.fields.inc

@@ -452,6 +452,22 @@ function tripal_chado_bundle_fields_info_custom(&$info, $details, $entity_type,
       ),
     );
   }
+
+  //protocol
+  if ($table_name == 'protocol' and array_key_exists('protocol_id', $schema['fields'])) {
+    $field_name = 'sep__protocol';
+    $field_type = 'sep__protocol';
+    $info[$field_name] = array(
+      'field_name' => $field_name,
+      'type' => $field_type,
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+    );
+  }
+
 }
 
 /**
@@ -1611,6 +1627,51 @@ function tripal_chado_bundle_instances_info_custom(&$info, $entity_type, $bundle
       ),
     );
   }
+
+
+  // PROTOCOL FIELD
+  if ($table_name != 'protocol' and
+    (array_key_exists('protocol_id', $schema['fields']))) {
+
+    $field_name = 'sep__protocol';
+    $is_required = FALSE;
+    $table_column = 'protocol_id';
+    if  (array_key_exists('not null', $schema['fields']['protocol_id']) and
+      $schema['fields']['protocol_id']['not null']) {
+      $is_required = TRUE;
+    }
+    $info[$field_name] =  array(
+      'field_name' => $field_name,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Protocol',
+      'description' => 'The parameterizable description of a process',
+      'required' => $is_required,
+      'settings' => array(
+        'auto_attach' => TRUE,
+        'chado_table' => $table_name,
+        'chado_column' => $table_column,
+        'base_table' => $table_name,
+      ),
+      'widget' => array(
+        'type' => 'sep__protocol_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'inline',
+          'type' => 'sep__protocol_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
+  }
+
+
+
+
 }
 
 /**