<?php
// $Id: ubio_wrapper.php,v 1.1.1.1 2005/05/19 10:31:10 rdmpage Exp $
/**
* @brief Wrapper to talk to uBio using its SOAP web service
*
* <A HREF="http://www.ubio.org/services/network/index.html">uBio</A> provide a web service interface to their
* Taxonomic Name Server. The service has a SOAP interface and is well documented with
* example client PHP code and sample output. My class makes extensive use of that code.
*
* A key thing to remember is that uBio SOAP message use base64 encoding for strings.
* uBio also returns arrays of results (as opposed to, say, XML), and so we construct our
* own XML document from the returned array.
*
* I have also experienced problems with Mindreef's SOAPscope and the uBio web service. If SOAPscope
* is used as a proxy server then the message is corrupted.
*
*/
/* Various experiments with entities */
/*
function utf2html ($str ) {
$ret ="" ;
$max =strlen ($str );
$last =0; // keeps the index of the last regular character
for ( $i =0;$i <$max ;$i ++) {
$c =$str {$i };
$c1 =ord ($c );
if ( $c1 >> 5== 6) { // 110x xxxx, 110 prefix for 2 bytes unicode
$ret .= substr ($str ,$last ,$i -$last ); // append all the regular characters we've passed
$c1 &= 31 ;// remove the 3 bit two bytes prefix
$c2 =ord ($str {++ $i }); // the next byte
$c2 &= 63 ; // remove the 2 bit trailing byte prefix
$c2 |= (( $c1 &3) << 6); // last 2 bits of c1 become first 2 of c2
$c1 >>= 2;// c1 shifts 2 to the right
$ret .= "&#" . ( $c1 *100 +$c2 ) . ";" ;// this is the fastest string concatenation
$last =$i +1;
}
}
return $ret .substr ($str ,$last ,$i ); // append the last batch of regular characters
}
function xmlentities ($string , $quote_style = ENT_QUOTES )
{
$translation_table = get_html_translation_table( HTML_ENTITIES, $quote_style);
foreach ( $translation_table as $key => $value )
$translation_table [$key ] = '&#' .ord ($key ). ';' ;
// dont translate the '&' in case it is part of &xxx;
$translation_table [chr (38 )] = '&' ;
// after the initial translation, _do_ map standalone '&' into '&'
return preg_replace ("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/" ,"&" ,
strtr ($string ,$translation_table ));
}
*/
class uBioWrapper extends Wrapper {
/**
* Store the address of the WSDL file for this service.
* @protected
*/
var $wsdl;
//----------------------------------------------------------------------------
/**
* Sets the WSDL address for the service
* (currently <A HREF="http://uio.mbl.edu/service/uBioServiceWSDL.php#wsdl">
* http://uio.mbl.edu/service/uBioServiceWSDL.php#wsdl</a>),
* and sets the authority and namespace.
*/
function uBioWrapper ()
{
$this->wsdl = "http://uio.mbl.edu/service/index.php#wsdl";
$this->authority = "ubio.org";
$this->namespace = "namebankID";
$this->xml = "";
$this->StartXML();
}
//----------------------------------------------------------------------------
/**
* @brief Tests if uBio is alive.
*
* @return true if service is live, false otherwise
*/
function IsAlive ()
{
$result = true; // for now
return $result;
}
//----------------------------------------------------------------------------
/**
* @brief Return details for a single record in uBio, using their SOAP interface
*
* @param id Index Fungorum of taxon name to retrieve
* @return Result in my XML format
*/
function GetDataForID ($id)
{
$result = "";
global $config;
$big = "";
$data = $this->GetDataFromCache ("GetDataForID", "txt", $id);
if ($data != "")
{
$big = unserialize($data);
}
else
{
// Search parameters.
$args = array(
"namebankID"=>$id,
"vernacularFlag"=>1,
"homotypicSynonymsFlag"=>1,
"citationsFlag"=>0,
"mappingsFlag"=>1,
"basicFlag"=>1,
"childrenFlag"=>1,
"clientVersion"=>"0.1",
"requestorIP"=>$_SERVER["SERVER_ADDR"],
"keyCode"=>$config["uBio_key"]
);
//$parameters = array('args'=>$args);
//print_r ($parameters);
// From 7 April 2005 uBio data structures changed (sigh).
$parameters = $args;
// Proxy settings
$proxyhost = '';
$proxyport = '';
if ($config['proxy_name'] != '')
{
$proxyhost = $config['proxy_name'];
$proxyport = $config['proxy_port'];
}
if ($config['soap_proxy_name'] != '')
{
$proxyhost = $config['soap_proxy_name'];
$proxyport = $config['soap_proxy_port'];
}
// Create SOAP client from WSDL
$soapclient = new soapclient($this->wsdl);
if ($soapclient->fault)
{
$this->Error ("SOAP", $soapclient->getError());
$this->EndXML();
return $this->xml;
}
$soapclient->soap_defencoding = 'ISO-8859-1'; //'UTF-8';
$soapclient->debug_flag=true;
$soapclient->setHTTPProxy ($proxyhost, $proxyport);
// Make the call
$this->StartTimer();
// Make the call
$big = $soapclient->call('namebank_object', $parameters);
$this->StopTimer();
//print_r($big);
//--------------------------------------------------------------------------------------------
// Check for a fault
if ($soapclient->fault)
{
$this->Error ("SOAP", $soapclient->getError());
$this->EndXML();
return $this->xml;
} else
{
// Check for errors
$err = $soapclient->getError();
if ($err)
{
$this->Error ("SOAP", $soapclient->getError());
$this->EndXML();
return $this->xml;
}
}
}
if ($big != "")
{
// Now for the fun
//echo '<xmp>'.$soapclient->request.'</xmp>';
//echo '<xmp>'.$soapclient->response.'</xmp>';
// Metadata about result
$serviceData = $big['serviceData'];
//print_r($big);
// Search result
$this->ReportTimeUsed();
//$this->EndXML();
$myxml = "<?xml version='1.0' encoding='utf-8'?>\n";
$myxml .= "<Result>\n";
// Put out from array
$name = base64_decode($big["nameString"]);
$namesAuthority = base64_decode ($big["authorityString"]);
// Watch out for '&' in authority
$namesAuthority = htmlspecialchars ($namesAuthority, ENT_NOQUOTES, UTF-8);
$rank = ucfirst($big["defaultRankName"]);
$status = $big['availability'];
// Make XML
$myxml .= "<taxon authority=\"$this->authority\" namespace=\"$this->namespace\" id=\"$id\">\n";
$myxml .= " <name>$name</name>\n";
$myxml .= " <author>$namesAuthority</author>\n";
$myxml .= " <rank>$rank</rank>\n";
$myxml .= " <status>$status</status>\n";
$vernacularNames =$big ["vernacularNames" ];
// print_r($vernacularNames);
for($i=0; $i<count($vernacularNames); $i++)
{
$nameString = base64_decode($vernacularNames[$i]["nameString"]);
$languageCode = $vernacularNames[$i]["languageCode"];
$myxml .= "<commonname xml:lang=\"$languageCode\">$nameString</commonname>\n";
}
$myxml .= "<url>http://www.ubio.org/SOAPbrowser/index.php?func=name_detail&ubioID=$id</url>\n";
$myxml .= "</taxon>\n";
$myxml .= "</Result>\n";
$this->xml = $myxml;
//echo $this->xml;
$this->StoreDataInCache ("GetDataForID", "txt", $id, serialize($big));
}
return $this->xml;
}
//----------------------------------------------------------------------------
/**
* @brief Searches uBio for a name.
*
* @param name The taxon name to search for
* @param qualifier Kind of search (default is exact)
* @param max_results The maximum number of records to return (default is 1)
*/
function NameSearch ($name, $qualifier = EXACT, $max_results = 1)
{
global $config;
$id = nameToSafe ($name);
//echo $id;
$big = "";
$this->StartTimer();
$data = $this->GetDataFromCache ("NameSearch", "txt", $id);
if ($data != "")
{
//echo "cache\n";
$big = unserialize($data);
$this->StopTimer();
}
else
{
$searchQualifier = "contains";
if ($qualifier == EXACT) {$searchQualifier = "exact"; }
// Search parameters.
$args = array(
"string"=>$name,
"vernacularFlag"=>0,
"scientificFlag"=>1,
"clientVersion"=>"0.1",
"requestorIP"=>$_SERVER["SERVER_ADDR"],
"order"=>"",
"searchQualifier"=>$searchQualifier,
"searchLimit"=>"",
"keyCode"=>$config["uBio_key"],
);
//print_r($args);
// $parameters = array('args'=>$args);
// uBio data structure changed!
$parameters = $args;
// Proxy settings
$proxyhost = '';
$proxyport = '';
if ($config['proxy_name'] != '')
{
$proxyhost = $config['proxy_name'];
$proxyport = $config['proxy_port'];
}
if ($config['soap_proxy_name'] != '')
{
$proxyhost = $config['soap_proxy_name'];
$proxyport = $config['soap_proxy_port'];
}
// Create SOAP client from WSDL
$soapclient = new soapclient($this->wsdl, false);
if ($soapclient->fault)
{
//print "error\n";
$this->Error ("SOAP", $soapclient->getError());
$this->EndXML();
return $this->xml;
}
//$soapclient->soap_defencoding = 'UTF-8';
$soapclient->debug_flag=true;
$soapclient->setHTTPProxy ($proxyhost, $proxyport);
// Make the call
$big = $soapclient->call('namebank_search', $parameters);
$this->StopTimer();
// echo '<xmp>'.$soapclient->response.'</xmp>';
if ($big == '')
{
// If the MySQL database server is down, then we don't get a
// SOAP error but a MySQL error message in HTML.
//echo '<xmp>'.$soapclient->response.'</xmp>';
if (preg_match("/MySQL Error:/m",$soapclient->response))
{
$this->Error ("MySQL Error", "Problem with uBio database");
}
else
{
$this->Error ("Unknown", "Badness happened");
}
$this->ReportTimeUsed();
$this->EndXML();
return $this->xml;
}
//print_r($big);
//--------------------------------------------------------------------------------------------
// Check for a fault
if ($soapclient->fault)
{
$this->Error ("SOAP", $soapclient->getError());
$this->ReportTimeUsed();
$this->EndXML();
return $this->xml;
} else
{
// Check for errors
$err = $soapclient->getError();
if ($err)
{
$this->Error ("SOAP", $soapclient->getError());
$this->ReportTimeUsed();
$this->EndXML();
return $this->xml;
}
else
{
$this->StoreDataInCache ("NameSearch", "txt", $id, serialize($big));
}
}
}
if ($big != "")
{
// Now for the fun
// echo '<xmp>'.$soapclient->request.'</xmp>';
// echo '<xmp>'.$soapclient->response.'</xmp>';
// Metadata about result
$serviceData = $big['matching_names'];
// Search result
$this->ReportTimeUsed();
if( $big ["scientificNames" ])
{
$seniorArray =$big ["scientificNames" ];
//print_r($seniorArray);
for($i=0; $i<count($seniorArray); $i++) {
$ubioID =$seniorArray[$i]["namebankID"];
$namesAuthority = base64_decode($seniorArray[$i]["authorityString"]);
// Watch out for '&' in authority
$namesAuthority = htmlspecialchars ($namesAuthority, ENT_NOQUOTES, UTF-8);
// Set the name to be empty when doing Species 2000 names,
// because there seems to be a problem with entities in some
// author names.
$namesAuthority = "";
$name = base64_decode($seniorArray[$i]["nameString"]);
$packageID = $seniorArray[$i]["packageID"];
$package = $seniorArray[$i]["packageName"];
$rank = ucfirst($seniorArray[$i]["rankName"]);
$date = $serviceData['dateStamp'];
$version = $serviceData['currentVersion'];
$this->xml .= "<taxon authority=\"$this->authority\" namespace=\"$this->namespace\" id=\"$ubioID\">\n";
$this->xml .= " <name>$name</name>\n";
$this->xml .= " <author>$namesAuthority</author>\n";
$this->xml .= " <rank>$rank</rank>\n";
$this->xml .= " <kingdom></kingdom>\n";
$this->xml .= " <rank>$rank</rank>\n";
$this->xml .= " <date>$date</date>\n";
$this->xml .= " <version>$version</version>\n";
$this->xml .= " <url>http://www.ubio.org/SOAPbrowser/index.php?func=name_detail&ubioID=$ubioID</url>\n";
$this->xml .= "</taxon>\n";
}
}
else
{
//echo "No name matching "$string" found.<br/>";
}
$this->EndXML();
}
return $this->xml;
}
}
?>