Browse Source

Changed publication search page to look and behave more like PubMed's advanced search

spficklin 12 years ago
parent
commit
1c4d5eae12

+ 1 - 1
tripal_core/api/tripal_core_misc.api.inc

@@ -25,7 +25,7 @@
  *  callback f unction should receive one argument: an array of values that
  *  are passed into the tripal_pager_callbck function. 
  */
-function tripal_pager_callback($func, $limit = 9, $element = 0, $cfunc) {
+function tripal_pager_callback($func, $limit = 10, $element = 0, $cfunc) {
   
   global $pager_page_array, $pager_total, $pager_total_items;
   $page = isset($_GET['page']) ? $_GET['page'] : '';

+ 35 - 4
tripal_pub/api/tripal_pub.api.inc

@@ -55,9 +55,6 @@
  */
 function tripal_pub_get_remote_search_results($remote_db, $search_array, 
   $num_to_retrieve, $pager_id = 0, $page = 0) {
-   
-  // construct the callback function using the remote database name
-  $callback = 'tripal_pub_remote_search_' . strtolower($remote_db);
 
   // manually set the $_GET['page'] parameter to trick the pager
   // into giving us the requested page
@@ -65,7 +62,8 @@ function tripal_pub_get_remote_search_results($remote_db, $search_array,
     $_GET['page'] = $page;
   }  
   
-  // now call the callback function to get the rsults
+  // now call the callback function to get the results
+  $callback = 'tripal_pub_remote_search_' . strtolower($remote_db);
   $pubs = array();
   if (function_exists($callback)) {
     $pubs = call_user_func($callback, $search_array, $num_to_retrieve, $pager_id);
@@ -789,4 +787,37 @@ function tripal_pub_update_property($pub_id, $property, $value, $insert_if_missi
  */
 function tripal_pub_delete_property($pub_id, $property) {
   return tripal_core_delete_property('pub', $pub_id, $property, 'tripal');
+}
+
+/*
+ * 
+ */
+function tripal_pub_create_citation($pub) {
+  $citation = $pub['Authors'] . '. ' . $pub['Title'] .  '. ';
+  
+  if ($pub['Journal ISO Abbreviation']) {
+    $citation .= $pub['Journal ISO Abbreviation'] . '. ';
+  } 
+  elseif ($pub['Journal Name']) {
+    $pub['Journal Name'] = preg_replace('/\.$/', '', $pub['Journal Name']);
+    $citation .= $pub['Journal Name'] . '. ';
+  }
+  $citation .= $pub['Publication Date'];
+  if ($pub['Volume'] or $pub['Issue'] or $pub['Pages']) {
+    $citation .= '; ';  
+  }
+  if ($pub['Volume']) {
+    $citation .= $pub['Volume'];
+  }
+  if ($pub['Issue']) {
+    $citation .= '(' . $pub['Issue'] . ')';
+  }
+  if ($pub['Pages']) {
+    if($pub['Volume']) {
+      $citation .= ':';
+    }    
+    $citation .= $pub['Pages'];
+  }
+  $citation .= '.';
+  return $citation;
 }

+ 441 - 2
tripal_pub/includes/agricola.inc

@@ -1,8 +1,447 @@
 <?php
-// http://agricola.nal.usda.gov/help/z3950.html
+/**
+ * Installation:
+ * 1) Install the yaz libraries: sudo apt-get install yaz libyaz3 libyaz3-dev
+ * 2) Install the PHP module: sudo pecl install yaz
+ * 3) Add "extension=yaz.so" to php.ini
+ * 4) Restart apache
+ * 
+ *  http://agricola.nal.usda.gov/help/z3950.html
+ *  
+ */
+
+
 /**
  *
  */
 function tripal_pub_remote_search_AGRICOLA($search_array, $num_to_retrieve, $pager_id) {
-  dpm($search_array);
+  // get some values from the serach array
+  $num_criteria = $search_array['num_criteria'];
+  $days = $search_array['days'];     
+  
+  // Build the query by iterating through the search array values
+  $search_str = '';
+  for ($i = 0; $i <= $num_criteria; $i++) {
+    $search_terms = $search_array['criteria'][$i]['search_terms'];
+    $scope = $search_array['criteria'][$i]['scope'];
+    $op = $search_array['criteria'][$i]['operation'];
+    // Quick Reference For Attribute Fields 
+    // (eg: "@attr 2=" refers to the Relation attribute) 
+    // 1 = Use Field
+    // 2 = Relation
+    // 3 = Position
+    // 4 = Structure
+    // 5 = Truncate
+    // 6 = Completeness
+    // The attribute set used by AGRICOLA can be found at the bottom of this page:
+    // http://agricola.nal.usda.gov/help/z3950.html  
+    // 1003 == Author
+    // 4 = Title
+    if ($op) {
+      $search_str .= "$op";
+    }        
+    if($scope == 'title') {
+      $search_str = "@attr 1=4 \"$search_terms\"";
+    }    
+    elseif($scope == 'author') {
+    }    
+    elseif($scope == 'abstract') {
+    }
+    elseif($scope == 'id') {
+    }    
+  }   
+  dpm($search_str); 
+         
+  $search_array['limit'] = $num_to_retrieve;
+  $search_array['search_string'] = $search_str; 
+
+  // yaz_connect() prepares for a connection to a Z39.50 server. This function is non-blocking 
+  // and does not attempt to establish a connection - it merely prepares a connect to be 
+  // performed later when yaz_wait() is called.
+  //$yazc = yaz_connect('agricola.nal.usda.gov:7090/voyager'); // NAL Catalog
+  $yazc = yaz_connect('agricola.nal.usda.gov:7190/voyager');  // NAL Article Citation Database
+  $_SESSION['tripal_pub_AGRICOLA_query'][$search_str]['yaz_connection'] = $yazc;
+  
+  // use the USMARC record type.  But OPAC is also supported by Agricola
+  yaz_syntax($yazc, "usmarc");
+  
+  // we want to get the list of pubs using the search terms but using a Drupal style pager
+  $pubs = tripal_pager_callback('tripal_pub_AGRICOLA_range',  $num_to_retrieve, $pager_id, 
+    'tripal_pub_AGRICOLA_count', $search_array);
+  
+  // close the connection
+  unset($_SESSION['tripal_pub_AGRICOLA_query'][$search_str]['yaz_connection']);
+  yaz_close($yazc);  
+  
+  return $pubs;
+}
+/*
+ * This function is used as the callback function when used with the
+ * tripal_pager_callback function.  This function returns a count of
+ * the dataset to be paged.
+ */
+function tripal_pub_AGRICOLA_count($search_array) {
+  $search_str = $search_array['search_string'];
+  $days       = $search_array['days'];
+  $limit      = $search_array['limit'];
+  
+  $yazc = $_SESSION['tripal_pub_AGRICOLA_query'][$search_str]['yaz_connection'];
+  yaz_search($yazc, "rpn", $search_str);  
+  yaz_wait();
+  
+  // get the total number of results from the serach
+  $count = yaz_hits($yazc);  
+  $_SESSION['tripal_pub_AGRICOLA_query'][$search_str]['Count'] = $count; 
+  return $count;
+}
+
+/*
+ * This function is used as the callback function when used with the
+ * tripal_pager_callback function.  This function returns the results
+ * within the specified range
+ */
+function tripal_pub_AGRICOLA_range($search_array, $start = 0, $limit = 10) {
+  $search_str = $search_array['search_string'];
+  $days       = $search_array['days'];
+  $limit      = $search_array['limit'];
+  
+  $yazc  = $_SESSION['tripal_pub_AGRICOLA_query'][$search_str]['yaz_connection'];
+  $count = $_SESSION['tripal_pub_AGRICOLA_query'][$search_str]['Count'];
+  yaz_range($yazc, 1, $num_pubs); 
+  yaz_present($yazc);
+  
+  $pubs = array();   
+  if ($start + $limit > $count) {
+    $limit = $count - $start;
+  }
+  for($i = $start; $i < $start + $limit; $i++) { 
+    $pub_xml = yaz_record($yazc, $i + 1, 'xml');
+    $pub     = tripal_pub_AGRICOLA_parse_pubxml($pub_xml);
+    $pubs[]  = $pub;     
+  } 
+  return $pubs;
+}
+
+/*
+ * Description of XML format:
+ * http://www.loc.gov/marc/bibliographic/bdsummary.html
+ * 
+ */
+function tripal_pub_AGRICOLA_parse_pubxml($pub_xml) {
+  $pub = array();
+  
+  if (!$pub_xml) {
+    return $pub;
+  }
+  
+  // read the XML and iterate through it.
+  $xml = new XMLReader();
+  $xml->xml($pub_xml);
+  while ($xml->read()) {    
+    $element = $xml->name; 
+
+    if ($xml->nodeType == XMLReader::ELEMENT and $element == 'controlfield') {      
+      $tag = $xml->getAttribute('tag');
+      $value = $xml->read(); 
+      switch ($tag) {
+        case '001':  // control number
+          break;
+        case '003':  // control number identifier
+          break;
+        case '005':  // datea nd time of latest transaction
+          break;
+        case '006':  // fixed-length data elemetns
+          break;
+        case '007':  // physical description fixed field
+          break;
+        case '008':  // fixed length data elements
+          break;
+        default:  // unhandled tag
+          break;
+      }          
+    }
+    elseif ($xml->nodeType == XMLReader::ELEMENT and $element == 'datafield') { 
+      $tag  = $xml->getAttribute('tag');
+      $ind1 = $xml->getAttribute('ind1');
+      $ind2 = $xml->getAttribute('ind2');
+      switch ($tag) {
+
+        case '100':  // main entry-personal name
+          $author = tripal_pub_remote_search_AGRICOLA_get_author($xml, $ind1);
+          $pub['Author List'][] = $author; 
+          break;
+        case '110':  // main entry-corporate nmae
+          $author = array();
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {    
+            switch ($code) {                
+              case 'a': // Corporate name or jurisdiction name as entry elemen
+                $author['Collective'] = $value;
+                break;
+              case 'b': // Subordinate unit
+                $author['Collective'] .= ' ' . $value;
+                break;
+            }
+          }
+          $pub['Author List'][] = $author; 
+          break;
+        case '111':  // main entry-meeting name
+          break;
+        case '130':  // main entry-uniform title
+          break;
+
+        case '210':  // abbreviated title
+          break;
+        case '222':  // key title
+          break;
+        case '240':  // uniform title
+          break;
+        case '242':  // translation of title by cataloging agency
+          break;
+        case '243':  // collective uniform title
+          break;
+        case '245':  // title statement
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {          
+            switch ($code) {                
+              case 'a':
+                $pub['Title'] = preg_replace('/\.$/', '', $value);
+                break;
+              case 'b':
+                $pub['Title'] .= ' ' . $value;
+                break;
+              case 'h':
+                $pub['Publication Model'] = $value;
+                break;
+            }
+          }
+          break;
+        case '246':  // varying form of title
+          break;
+        case '247':  // former title
+          break;            
+
+        case '250':  // edition statement
+          break;
+        case '254':  // musicla presentation statement
+          break;
+        case '255':  // cartographic mathematical data
+          break;
+        case '256':  // computer file characteristics 
+          break;
+        case '257':  // country of producing entity
+          break;
+        case '258':  // philatelic issue data
+          break;
+        case '260':  // publication, distribution ,etc (imprint)
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {          
+            switch ($code) {                
+              case 'a':
+                $pub['Published Location'] = $value;
+                break;
+              case 'b':
+                $pub['Publisher'] = $value;
+                break;                
+              case 'c':
+                $pub['Publication Date'] = $value;
+                break;
+            }
+          }
+          break;
+        case '263':  // projected publication date
+          break;
+        case '264':  // production, publication, distribution, manufacture and copyright notice
+          break;
+        case '270':  // Address
+          break;
+          
+        case '300':  // Address
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {          
+            switch ($code) {                
+              case 'a':
+                $pages = $value;
+                $pages = preg_replace('/^p\. /', '', $pages);
+                $pages = preg_replace('/\.$/', '' , $pages);
+                if(preg_match('/p$/', $pages)) {
+                  // skip this, it's the number of pages not the page numbers
+                } 
+                else {
+                  $pub['Pages'] = $pages;
+                }
+                break;
+            }
+          }
+          break;                      
+
+        case '490':  // series statements
+          break;
+
+        case '520':  // Summary, etc
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {    
+            switch ($code) {                
+              case 'a':
+                $pub['Abstract'] = $value;
+                break;
+            }
+          }
+          break;
+        
+        case '700':  // Added Entry-Personal Name
+          $author = tripal_pub_remote_search_AGRICOLA_get_author($xml, $ind1);
+          $pub['Author List'][] = $author; 
+          break;
+        case '710':  // Added Entry-Corporate Name
+          $author = array();
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {    
+            switch ($code) {                
+              case 'a': // Corporate name or jurisdiction name as entry elemen
+                $author['Collective'] = $value;
+                break;
+              case 'b': // Subordinate unit
+                $author['Collective'] .= ' ' . $value;
+                break;
+            }
+          }
+          $pub['Author List'][] = $author; 
+          break;
+        case '773': // host item entry
+          $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+          foreach ($codes as $code => $value) {    
+            switch ($code) {                
+              case 't':                
+                $pub['Journal Name'] = preg_replace('/\.$/', '', $value);
+                break;
+              case 'g':
+                $matches = array();
+                if(preg_match('/^(\d\d\d\d)/', $value, $matches)) {
+                  $pub['Year'] = $matches[1];
+                  $pub['Publication Date'] = $matches[1];
+                }
+                elseif(preg_match('/(.*?)(\.|\s+)\s*(\d+),\s(\d\d\d\d)/', $value, $matches)) {
+                  $year = $matches[4];
+                  $month = $matches[1];
+                  $day = $matches[3];
+                  $pub['Year'] = $year;
+                  $pub['Publication Date'] = "$year $month $day"; 
+                }
+                elseif(preg_match('/\((.*?)(\.|\s+)(\d\d\d\d)\)/', $value, $matches)) {
+                  $year = $matches[3];
+                  $month = $matches[1];
+                  $pub['Year'] = $year;
+                  $pub['Publication Date'] = "$year $month"; 
+                }
+                elseif(preg_match('/^(.*?) (\d\d\d\d)/', $value, $matches)) {
+                  $year = $matches[2];
+                  $month = $matches[1];
+                  $pub['Year'] = $year;
+                  $pub['Publication Date'] = "$year $month"; 
+                }
+                if(preg_match('/v\. (.*?)(,|\s+)/', $value, $matches)) {
+                  $pub['Volume'] = $matches[1];
+                }
+                if(preg_match('/v\. (.*?)(,|\s+)\((.*?)\)/', $value, $matches)) {
+                  $pub['Volume'] = $matches[1];
+                  $pub['Issue'] = $matches[3];
+                }
+                if(preg_match('/no\. (.*?)(\s|$)/', $value, $matches)) {
+                  $pub['Issue'] = $matches[1];
+                }
+                break;
+              case 'p':
+                $pub['Journal Abbreviation'] = $value;
+                break;
+            }
+          }
+          break;
+      }
+    }
+  }
+  // build the full authors list
+  foreach ($pub['Author List'] as $author) {
+    if ($author['valid'] == 'N') {
+      // skip non-valid entries.  A non-valid entry should have 
+      // a corresponding corrected entry so we can saftely skip it.
+      continue;
+    }
+    if ($author['Collective']) {
+      $authors .= $author['Collective'] . ', ';
+    }
+    else {
+      $authors .= $author['Surname'] . ' ' . $author['First Initials'] . ', '; 
+    }             
+  }
+  $authors = substr($authors, 0, -2);
+  $pub['Authors'] = $authors;
+  
+  // build the citation
+  $pub['Citation'] = tripal_pub_create_citation($pub);
+  
+  $pub['raw'] = $pub_xml;
+  return $pub;
+}      
+
+/*
+ * 
+ * 
+ */
+function tripal_pub_remote_search_AGRICOLA_get_subfield($xml) {
+  $codes = array();
+  while ($xml->read()) {    
+    $sub_element = $xml->name;
+    // when we've reached the end of the datafield element then break out of the while loop
+    if ($xml->nodeType == XMLReader::END_ELEMENT and $sub_element == 'datafield') {
+      return $codes; 
+    }    
+    // if inside the subfield element then get the code 
+    if ($xml->nodeType == XMLReader::ELEMENT and $sub_element == 'subfield') {
+      $code = $xml->getAttribute('code');
+      $xml->read();
+      $value = $xml->value;
+      $codes[$code] = $value;
+    }
+  }
+  return $codes;
+}
+
+/*
+ * 
+ * 
+ */
+function tripal_pub_remote_search_AGRICOLA_get_author($xml, $ind1) {
+  $author = array();
+  $codes = tripal_pub_remote_search_AGRICOLA_get_subfield($xml);
+  foreach ($codes as $code => $value) {          
+    switch ($code) {                
+      case 'a':
+        // remove any trailing commas
+        $value = preg_replace('/,$/', '', $value);
+        if ($ind1 == 0) { // Given Name is first
+          $author['Given Name'] = $names[0];
+        }
+        if ($ind1 == 1) { // Surname is first          
+          // split the parts of the name using a comma
+          $names = explode(',', $value);
+          $author['Surname'] = $names[0];
+          $author['Given Name'] = ''; 
+          unset($names[0]);
+          foreach($names as $index => $name) {
+            $author['Given Name'] .= $name . ' ';
+          }
+          $first_names = explode(' ', $author['Given Name']);
+          $author['First Initials'] = '';
+          foreach ($first_names as $index => $name) {
+            $author['First Initials'] .= substr($name, 0, 1); 
+          }
+        }
+        if ($ind1 == 3) { // A family name
+          
+        }
+        break;
+    }
+  }
+  return $author;
 }

+ 2 - 1
tripal_pub/includes/pub_importers.inc

@@ -76,6 +76,7 @@ function tripal_pub_importer_setup($action = 'new', $pub_import_id = NULL) {
   if ($_SESSION['tripal_pub_search']['perform_search']) {
     // get the list of publications from the remote database using the search criteria.  
     $pubs = tripal_pub_get_remote_search_results($remote_db, $search_array, $limit, $pager_id);
+      dpm($pubs);
     
     // generate the pager
     $total_pages = $pager_total[$pager_id];
@@ -104,7 +105,7 @@ function tripal_pub_importer_setup($action = 'new', $pub_import_id = NULL) {
     $table = theme('table', $headers, $rows);   
   
     // join all to form the results
-    $output .= "<br>Search String: $search_str<br><p><b>Found " . number_format($total_items) .  
+    $output .= "<br><p><b>Found " . number_format($total_items) .  
       ". Page " . ($page + 1) . " of $total_pages. " .
       " Results</b></br>" . $table . '</p>' . $pager;    
   }

+ 62 - 44
tripal_pub/includes/pub_search.inc

@@ -53,18 +53,18 @@ function tripal_pub_search_page() {
       $citation_rec = tripal_core_expand_chado_vars($citation_rec, 'field', 'pubprop.value');
       
       // if we have the citation then use it, otherwise, just use the title
+      $result = $pub->title;
+      if ($pub->nid) {
+        $result = l($pub->title ,'node/' . $pub->nid, array('attributes' => array('target' => '_blank')));
+      }      
       if ($citation_rec->value) {
-        $pub_info = $citation_rec->value;
+        $result .= '<br>' . $citation_rec->value;
       } 
-      else {
-        $pub_info = $pub->title;     
-      }
-      
-      // if the publication has a node then link to it
-      if ($pub->nid) {
-        $pub_info = l($pub_info ,'node/' . $pub->nid, array('attributes' => array('target' => '_blank')));
-      }
-      $rows[] = array(number_format($i) . ".", $pub->pyear, $pub_info);
+      $rows[] = array(
+        number_format($i) . ".", 
+        $pub->pyear, 
+        $result
+      );
       $i++;
     }
 
@@ -104,7 +104,7 @@ function tripal_pub_search_form(&$form_state = NULL) {
    
   // change the number of criteria based on form_state post data.
   if (!$num_criteria) {
-    $num_criteria = 0;
+    $num_criteria = 2;
   }
   if($form_state['post']["add-$num_criteria"]) {    
     $num_criteria++;
@@ -117,6 +117,10 @@ function tripal_pub_search_form(&$form_state = NULL) {
     '#type'          => 'hidden',
     '#default_value' => $num_criteria,
   );
+  $form['instructions'] = array(
+    '#type'  => 'item',
+    '#value' => t('To search for publications enter keywords in the text boxes below.  You can limit your search by selecting the field in the dropdown box.'),
+  );
   
   // get publication properties list 
   $properties = array();
@@ -137,7 +141,7 @@ function tripal_pub_search_form(&$form_state = NULL) {
     $properties[$prop->cvterm_id] = $prop->name;
   }
   
-  for($i = 0; $i <= $num_criteria; $i++) {
+  for($i = 1; $i <= $num_criteria; $i++) {
     $search_terms = '';
     $scope = '';
     $operation = '';
@@ -169,16 +173,15 @@ function tripal_pub_search_form(&$form_state = NULL) {
   
     $form['criteria'][$i]["search_terms-$i"] = array(
       '#type'          => 'textfield',
-      '#description'   => t('Please provide a list of words for searching"'),
       '#default_value' => $search_terms,
       '#required'      => FALSE,
     );
     $form['criteria'][$i]["scope-$i"] = array(
       '#type'          => 'select',
-      '#description'   => t('Please select the fields to search for this term.'),
       '#options'       => $properties,
       '#default_value' => $scope,
     );  
+    /*
     $form['criteria'][$i]["mode-$i"] = array(
       '#type'          => 'select',
       '#options'       => array(
@@ -187,9 +190,9 @@ function tripal_pub_search_form(&$form_state = NULL) {
         'Ends With'   => 'Ends With',
         'Exactly'     => 'Exactly'),
       '#default_value' => $mode,
-    );   
+    );*/   
     
-    if ($i > 0) {
+    if ($i > 1) {
       $form['criteria'][$i]["operation-$i"] = array(
         '#type'          => 'select',
         '#options'       => array(
@@ -200,7 +203,7 @@ function tripal_pub_search_form(&$form_state = NULL) {
       );
     }
     if ($i == $num_criteria) {    
-      if($i > 0) {
+      if($i > 1) {
         $form['criteria'][$i]["remove-$i"] = array(
           '#type'         => 'image_button',
           '#value'        => t('Remove'),
@@ -228,11 +231,18 @@ function tripal_pub_search_form(&$form_state = NULL) {
       );
     }
   }
+  $form['criteria']["date"] = array(
+      '#type'          => 'select',
+      '#options'       => array(
+        'Years'    => 'Years',
+       ),
+      '#default_value' => $date,
+  );
   $form['criteria']["from_year"] = array(
     '#type'          => 'textfield',
     '#default_value' => $from_year,
     '#required'      => FALSE,
-    '#title'         => 'Years from',
+    '#title'         => 'from',
     '#size'          => 4,
     '#maxlength'     => 4,
   );
@@ -264,26 +274,35 @@ function theme_tripal_pub_search_form($form) {
   foreach ($form['criteria'] as $i => $element) {
     if(is_numeric($i)) {
       $rows[] = array(  
-        array('data' => drupal_render($element["operation-$i"]), 'width' => '10%'),    
-        array('data' => drupal_render($element["scope-$i"]), 'width' => '10%'),
-        drupal_render($element["mode-$i"]) . drupal_render($element["search_terms-$i"]),
-        array('data' => drupal_render($element["add-$i"]) . drupal_render($element["remove-$i"]), 'width' => '5%'),
+        drupal_render($element["operation-$i"]),    
+        drupal_render($element["scope-$i"]),
+        //drupal_render($element["mode-$i"]) . 
+        drupal_render($element["search_terms-$i"]),
+        drupal_render($element["add-$i"]) . drupal_render($element["remove-$i"]),
       );
     }
   } 
-  $headers = array('Operation','Scope', 'Search Terms', '');  
-  $markup  = "
-     <div id=\"pub-search-form-row1\"> ".
-       theme('table', $headers, $rows, array('id' => 'tripal-pub-search-table')) . "
-     </div>
-     <div id=\"pub-search-form-row2\"> 
-       <div id=\"pub-search-form-dates\"> ".
-        drupal_render($form['criteria']['from_year']) . 
-        drupal_render($form['criteria']['to_year']) . '
-      </div>
-     </div>
-     <div style="clear: both;">
-  '; 
+    
+  $rows[] = array(
+    drupal_render($form['criteria']['date']),
+    array(
+      'data' =>
+        "<div id=\"pub-search-form-dates-row\"> 
+           <div id=\"pub-search-form-dates\"> ".
+            drupal_render($form['criteria']['from_year']) . 
+            drupal_render($form['criteria']['to_year']) . "
+          </div>
+         </div>",
+       'colspan' => 2,
+    ),
+    ''
+  );
+  $table = theme('table', $headers, $rows, array('id' => 'tripal-pub-search-form-table', 'border' => '0')); 
+  $headers = array();  
+  $markup  = drupal_render($form['instructions']) . "
+     <div id=\"pub-search-form-row1\">$table</div>
+     <div style=\"clear: both;\">
+  "; 
   
   $form['criteria'] = array(
     '#type' => 'markup',
@@ -318,13 +337,6 @@ function tripal_pub_search_form_validate($form, &$form_state) {
   if($to_year and !preg_match('/\d\d\d\d/' , $to_year)) {
     form_set_error('to_year', 'Please provide a 4-digit year.');
   }
-  // make sure we have values for all criteria 
-  for ($i = 0; $i <= $num_criteria; $i++) {
-    $search_terms =  trim($form_state['values']["search_terms-$i"]);
-    if (!$search_terms or $search_terms = '') {
-     form_set_error("search_terms-$i", 'Please provide criteria for searching'); 
-    }      
-  } 
 }
 /**
  *
@@ -342,7 +354,8 @@ function tripal_pub_search_form_submit($form, &$form_state) {
     for ($i = 0; $i <= $num_criteria; $i++) {
       $search_terms =  trim($form_state['values']["search_terms-$i"]);
       $scope =  $form_state['values']["scope-$i"];
-      $mode =  $form_state['values']["mode-$i"];
+      //$mode =  $form_state['values']["mode-$i"];
+      $mode = 'Contains';
       $operation =  $form_state['values']["operation-$i"];
       
       $_SESSION['tripal_pub_search_form']['criteria'][$i] = array(
@@ -404,12 +417,17 @@ function tripal_pub_get_search_results($search_array, $limit, $pager_id) {
   $from_year    = $search_array['from_year'];
   $to_year      = $search_array['to_year'];
   
-  for ($i = 0; $i <= $num_criteria; $i++) {
+  for ($i = 1; $i <= $num_criteria; $i++) {
     $value = $search_array['criteria'][$i]['search_terms'];
     $type_id = $search_array['criteria'][$i]['scope'];
     $mode = $search_array['criteria'][$i]['mode'];
     $op = $search_array['criteria'][$i]['operation'];
     
+    // skip criteria with no values
+    if(!$value) {
+      continue;
+    }
+    
     // to prevent SQL injection make sure our operator is
     // what we expect    
     if ($op and $op != "AND" and $op != "OR" and $op != 'NOT') {

+ 2 - 15
tripal_pub/includes/pubmed.inc

@@ -320,20 +320,7 @@ function tripal_pub_PMID_parse_pubxml($pub_xml) {
       }
     }
   }
-  $pub['Citation'] = $pub['Authors'] . '. ' . $pub['Title'] .  '. ' .
-    $pub['Journal ISO Abbreviation'] . '. ' . $pub['Publication Date'];
-  if ($pub['Volume'] or $pub['Issue']) {
-    $pub['Citation'] .= '; ';  
-  }
-  if ($pub['Volume']) {
-    $pub['Citation'] .= $pub['Volume'];
-  }
-  if ($pub['Issue']) {
-    $pub['Citation'] .= '(' . $pub['Issue'] . ')';
-  }
-  if ($pub['Pages']) {
-    $pub['Citation'] .= ':' . $pub['Pages'];
-  }
+  $pub['Citation'] = tripal_pub_create_citation($pub);
   
   $pub['raw'] = $pub_xml;
   return $pub;
@@ -601,7 +588,7 @@ function tripal_pub_PMID_parse_journal($xml, &$pub) {
           break;
         case 'ISOAbbreviation': 
           $xml->read();
-          $pub['Journal ISO Abbreviation'] = $xml->value;         
+          $pub['Journal Abbreviation'] = $xml->value;         
           break;
         default:
           break;

+ 9 - 3
tripal_pub/tpub.obo

@@ -39,13 +39,13 @@ relationship: part_of TPUB:0000016 ! Author
 [Term]
 id: TPUB:0000007
 name: Master's Thesis
-relationship: part_of TPUB:0000006 ! Collective
+is_a: TPUB:0000015 ! Publication Type
 
 [Term]
 id: TPUB:0000008
 name: PhD Thesis
 def: PhD thesis or dissertation.
-relationship: part_of TPUB:0000006 ! Collective
+is_a: TPUB:0000015 ! Publication Type
 
 [Term]
 id: TPUB:0000009
@@ -109,7 +109,7 @@ relationship: part_of TPUB:0000002 ! Publication
 
 [Term]
 id: TPUB:0000038
-name: Journal ISO Abbreviation
+name: Journal Abbreviation
 relationship: part_of TPUB:0000037 ! Publication Details
 def: The journal title ISO Abbreviation.
 
@@ -1343,6 +1343,12 @@ id: TPUB:0000245
 name: Published Location
 relationship: part_of TPUB:0000037 ! Publication Details
 
+[Term]
+id: TPUB:0000246
+name: Prefix
+def: A prefix for a name such as a title (e.g. Mr., Mrs., Dr., Chief, Esquire, etc.)
+relationship: part_of TPUB:0000016 ! Author
+
 [Typedef]
 id: is_a
 name: is a