diff --git a/classes/ChecklistVoucherReport.php b/classes/ChecklistVoucherReport.php
index eac7448bfc..fb25ed3018 100644
--- a/classes/ChecklistVoucherReport.php
+++ b/classes/ChecklistVoucherReport.php
@@ -271,8 +271,6 @@ private function getMissingTaxaBaseSql($sqlFrag){
public function getMissingProblemTaxa(){
$retArr = Array();
if($sqlFrag = $this->getSqlFrag()){
- //Make sure tidinterpreted are valid
- //$this->conn->query('UPDATE omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname SET o.tidinterpreted = t.tid WHERE o.tidinterpreted IS NULL');
//Grab records
$sql = 'SELECT DISTINCT o.occid, c.institutioncode, c.collectioncode, o.catalognumber, o.sciname, o.recordedby, o.recordnumber, o.eventdate, '.
'CONCAT_WS("; ",o.country, o.stateprovince, o.county, o.locality) as locality '.
diff --git a/classes/ImageLocalProcessor.php b/classes/ImageLocalProcessor.php
index 09f799fb8f..fb1708e450 100644
--- a/classes/ImageLocalProcessor.php
+++ b/classes/ImageLocalProcessor.php
@@ -1557,7 +1557,8 @@ private function updateCollectionStats(){
$this->logOrEcho('Cleaning house...');
$collString = implode(',',$this->collProcessedArr);
- if(!$occurMain->generalOccurrenceCleaning($collString)){
+ $occurMain->setCollidStr($collString);
+ if(!$occurMain->generalOccurrenceCleaning()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->logOrEcho($errorStr,1);
@@ -1570,7 +1571,8 @@ private function updateCollectionStats(){
$this->logOrEcho('Updating statistics...');
foreach($this->collProcessedArr as $collid){
- if(!$occurMain->updateCollectionStats($collid)){
+ $occurMain->setCollidStr($collid);
+ if(!$occurMain->updateCollectionStatsBasic()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->logOrEcho($errorStr,1);
diff --git a/classes/ImageProcessor.php b/classes/ImageProcessor.php
index 8ec52c8f55..0b13aaba43 100644
--- a/classes/ImageProcessor.php
+++ b/classes/ImageProcessor.php
@@ -347,7 +347,8 @@ public function loadFileData($postArr){
$occurMain = new OccurrenceMaintenance($this->conn);
$this->logOrEcho('Updating statistics...');
- if(!$occurMain->updateCollectionStats($this->collid)){
+ $occurMain->setCollidStr($this->collid);
+ if(!$occurMain->updateCollectionStatsBasic()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->logOrEcho($errorStr,1);
@@ -545,7 +546,8 @@ private function cleanHouse($collList){
/*
$this->logOrEcho('General cleaning...',2);
$collString = implode(',',$collList);
- if(!$occurMain->generalOccurrenceCleaning($collString)){
+ $occurMain->setCollidStr($collString);
+ if(!$occurMain->generalOccurrenceCleaning()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->logOrEcho($errorStr,1);
@@ -559,7 +561,8 @@ private function cleanHouse($collList){
if($collList){
$this->logOrEcho('Updating collection statistics...',2);
foreach($collList as $collid){
- if(!$occurMain->updateCollectionStats($collid)){
+ $occurMain->setCollidStr($collid);
+ if(!$occurMain->updateCollectionStatsBasic()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->logOrEcho($errorStr,1);
diff --git a/classes/OccurrenceCollectionProfile.php b/classes/OccurrenceCollectionProfile.php
index bdded68a8b..45965a91b8 100644
--- a/classes/OccurrenceCollectionProfile.php
+++ b/classes/OccurrenceCollectionProfile.php
@@ -507,6 +507,7 @@ public function getBasicStats(){
public function updateStatistics($verbose = false){
$occurMaintenance = new OccurrenceMaintenance();
+ $occurMaintenance->setCollidStr($this->collid);
if($verbose){
echo '
';
$occurMaintenance->setVerbose(true);
@@ -514,13 +515,14 @@ public function updateStatistics($verbose = false){
flush();
ob_flush();
}
- $occurMaintenance->generalOccurrenceCleaning($this->collid);
+ $occurMaintenance->generalOccurrenceCleaning();
+ $occurMaintenance->batchUpdateGeoreferenceIndex();
if($verbose){
echo 'Updating statistics... ';
flush();
ob_flush();
}
- $occurMaintenance->updateCollectionStats($this->collid, true);
+ $occurMaintenance->updateCollectionStatsFull();
if($verbose){
echo 'Finished updating collection statistics ';
flush();
@@ -602,7 +604,8 @@ public function batchUpdateStatistics($collId){
echo 'Cleaning statistics for: '.$r->collectionname.' ';
flush();
ob_flush();
- $occurMaintenance->updateCollectionStats($r->collid, true);
+ $occurMaintenance->setCollidStr($r->collid);
+ $occurMaintenance->updateCollectionStatsFull();
}
$rs->free();
echo 'Statistics update complete! ';
diff --git a/classes/OccurrenceMaintenance.php b/classes/OccurrenceMaintenance.php
index 6b495dd3b3..a45de65fca 100644
--- a/classes/OccurrenceMaintenance.php
+++ b/classes/OccurrenceMaintenance.php
@@ -5,6 +5,7 @@ class OccurrenceMaintenance {
protected $conn;
private $destructConn = true;
+ private $collidStr = null;
private $verbose = false; // 0 = silent, 1 = echo as list item
private $errorArr = array();
@@ -27,71 +28,35 @@ public function __destruct(){
}
//General cleaning functions
- public function generalOccurrenceCleaning($collId){
+ public function generalOccurrenceCleaning(){
set_time_limit(600);
$status = true;
- /*
- $this->outputMsg('Updating null families of family rank identifications... ',1);
- $occidArr = array();
- $sql = 'SELECT occid FROM omoccurrences WHERE (family IS NULL) AND collid IN('.$collId.') AND (sciname LIKE "%aceae" OR sciname LIKE "%idae")';
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $occidArr[] = $r->occid;
- }
- $rs->free();
- if($occidArr){
- $sql = 'UPDATE omoccurrences SET family = sciname WHERE occid IN('.implode(',',$occidArr).')';
- if(!$this->conn->query($sql)){
- $this->errorArr[] = 'WARNING: unable to update family; '.$this->conn->error;
- if($this->verbose) $this->outputMsg($this->errorArr,2);
- $status = false;
- }
- }
- unset($occidArr);
- */
+ $this->indexOccurrencesToTaxa();
//Update NULL sciname with family designations when family field is not null
$occidArr = array();
$this->outputMsg('Updating null scientific names of family rank identifications... ',1);
- $sql = 'SELECT occid FROM omoccurrences WHERE family IS NOT NULL AND sciname IS NULL AND collid IN('.$collId.')';
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $occidArr[] = $r->occid;
- }
- $rs->free();
- if($occidArr){
- $sql = 'UPDATE omoccurrences SET sciname = family WHERE occid IN('.implode(',',$occidArr).') ';
- if(!$this->conn->query($sql)){
- $errStr = 'WARNING: unable to update sciname using family; '.$this->conn->error;
- $this->errorArr[] = $errStr;
- if($this->verbose) $this->outputMsg($errStr,2);
- $status = false;
- }
- }
- unset($occidArr);
-
- //Update tidInterpreted values by matching on sciname
- $occidArr = array();
- $this->outputMsg('Indexing valid scientific names (e.g. populating tidinterpreted)... ',1);
- $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname WHERE o.collid IN('.$collId.') AND o.TidInterpreted IS NULL';
+ $sql = 'SELECT occid FROM omoccurrences WHERE family IS NOT NULL AND sciname IS NULL ';
+ if($this->collidStr) $sql .= 'AND collid IN('.$this->collidStr.')';
$rs = $this->conn->query($sql);
while($r = $rs->fetch_object()){
$occidArr[] = $r->occid;
if(count($occidArr) > 1000){
- $this->batchUpdateTidInterpreted($occidArr);
+ $this->batchScinameWithFamily($occidArr);
unset($occidArr);
$occidArr = array();
}
}
$rs->free();
- $this->batchUpdateTidInterpreted($occidArr);
+ $this->batchScinameWithFamily($occidArr);
unset($occidArr);
//Update NULL image tids with non-NULL occurrence tids
$occidArr = array();
- if($this->verbose) $this->outputMsg('Updating and indexing occurrence images... ',1);
- $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN images i ON o.occid = i.occid WHERE o.collid IN('.$collId.') AND (i.tid IS NULL) AND (o.tidinterpreted IS NOT NULL)';
+ $this->outputMsg('Updating and indexing occurrence images... ',1);
+ $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN images i ON o.occid = i.occid WHERE (i.tid IS NULL) AND (o.tidinterpreted IS NOT NULL) ';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.')';
$rs = $this->conn->query($sql);
while($r = $rs->fetch_object()){
$occidArr[] = $r->occid;
@@ -107,9 +72,9 @@ public function generalOccurrenceCleaning($collId){
//Update NULL families with taxstatus family values
$occidArr = array();
- if($this->verbose) $this->outputMsg('Updating null families using taxonomic thesaurus... ',1);
- $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN taxstatus ts ON o.tidinterpreted = ts.tid '.
- 'WHERE o.collid IN('.$collId.') AND (ts.taxauthid = 1) AND (ts.family IS NOT NULL) AND (o.family IS NULL)';
+ $this->outputMsg('Updating null families using taxonomic thesaurus... ',1);
+ $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN taxstatus ts ON o.tidinterpreted = ts.tid WHERE (ts.taxauthid = 1) AND (ts.family IS NOT NULL) AND (o.family IS NULL)';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.')';
$rs = $this->conn->query($sql);
while($r = $rs->fetch_object()){
$occidArr[] = $r->occid;
@@ -126,8 +91,8 @@ public function generalOccurrenceCleaning($collId){
//Updating records with null author
$occidArr = array();
$this->outputMsg('Updating null scientific authors using taxonomic thesaurus... ',1);
- $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN taxa t ON o.tidinterpreted = t.tid '.
- 'WHERE o.scientificNameAuthorship IS NULL AND t.author IS NOT NULL AND o.collid IN('.$collId.')';
+ $sql = 'SELECT o.occid FROM omoccurrences o INNER JOIN taxa t ON o.tidinterpreted = t.tid WHERE o.scientificNameAuthorship IS NULL AND t.author IS NOT NULL ';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.')';
$rs = $this->conn->query($sql);
while($r = $rs->fetch_object()){
$occidArr[] = $r->occid;
@@ -139,37 +104,93 @@ public function generalOccurrenceCleaning($collId){
$rs->free();
if(isset($occidArr)) $this->batchUpdateAuthor($occidArr);
- /*
- if($this->verbose) $this->outputMsg('Updating georeference index... ',1);
- $sql = 'INSERT IGNORE INTO omoccurgeoindex(tid,decimallatitude,decimallongitude)
- SELECT DISTINCT o.tidinterpreted, round(o.decimallatitude,2), round(o.decimallongitude,2)
- FROM omoccurrences o
- WHERE (o.tidinterpreted IS NOT NULL) AND (o.decimallatitude between -90 and 90) AND (o.decimallongitude between -180 and 180)
- AND (o.cultivationStatus IS NULL OR o.cultivationStatus = 0) AND (o.coordinateUncertaintyInMeters IS NULL OR o.coordinateUncertaintyInMeters < 10000) ';
- if(!$this->conn->query($sql)){
- $errStr = 'WARNING: unable to update georeference index; '.$this->conn->error;
- $this->errorArr[] = $errStr;
- if($this->verbose) $this->outputMsg($errStr,2);
- $status = false;
+ return $status;
+ }
+
+ public function indexOccurrencesToTaxa(){
+ $this->outputMsg('Indexing validated scientific names (e.g. populating tidInterpreted)... ', 1);
+
+ //Avoid using straight UPDATE SQL since they will often lock omoccurrences table for a significant amount of time when database is large
+ $occidArr = array();
+ //Index based on matching sciname and author
+ $activeTid = 0;
+ $sql = 'SELECT t.tid, o.occid
+ FROM omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname AND o.scientificnameauthorship = t.author
+ WHERE (o.TidInterpreted IS NULL) ';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.') ';
+ $sql .= 'ORDER BY t.tid';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ if($occidArr && $r->tid != $activeTid) $this->batchUpdateTidInterpreted($occidArr);
+ $activeTid = $r->tid;
+ $occidArr[$r->tid][] = $r->occid;
}
- */
+ $rs->free();
+ $this->batchUpdateTidInterpreted($occidArr);
- return $status;
+ //Index base on matching sciname and family to improve correct match when cross kingdom homonyms exist
+ $activeTid = 0;
+ $sql = 'SELECT t.tid, o.occid
+ FROM omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname
+ INNER JOIN taxaenumtree e ON t.tid = e.tid
+ INNER JOIN taxa t2 ON e.parenttid = t2.tid
+ WHERE (o.TidInterpreted IS NULL) AND (t2.rankid = 140) AND (t2.sciname = o.family) ';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.') ';
+ $sql .= 'ORDER BY t.tid';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ if($occidArr && $r->tid != $activeTid) $this->batchUpdateTidInterpreted($occidArr);
+ $activeTid = $r->tid;
+ $occidArr[$r->tid][] = $r->occid;
+ }
+ $rs->free();
+ $this->batchUpdateTidInterpreted($occidArr);
+
+ //Update remaining taxa that can only be match on scientific name
+ $activeTid = 0;
+ $sql = 'SELECT t.tid, o.occid FROM omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname WHERE o.TidInterpreted IS NULL ';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.') ';
+ $sql .= 'ORDER BY t.tid';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ if($occidArr && $r->tid != $activeTid) $this->batchUpdateTidInterpreted($occidArr);
+ $activeTid = $r->tid;
+ $occidArr[$r->tid][] = $r->occid;
+ }
+ $rs->free();
+ $this->batchUpdateTidInterpreted($occidArr);
+
+ //Match subgeneric names
+ $activeTid = 0;
+ $sql = 'SELECT t.tid, o.occid
+ FROM omoccurrences o INNER JOIN taxa t ON CONCAT(SUBSTRING_INDEX(o.sciname, " (", 1), " ", SUBSTRING_INDEX(o.sciname, ") ", -1)) = t.sciname
+ WHERE o.tidinterpreted IS NULL AND o.sciname LIKE "% (%) %" ';
+ if($this->collidStr) $sql .= 'AND o.collid IN('.$this->collidStr.') ';
+ $sql .= 'ORDER BY t.tid';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ if($occidArr && $r->tid != $activeTid) $this->batchUpdateTidInterpreted($occidArr);
+ $activeTid = $r->tid;
+ $occidArr[$r->tid][] = $r->occid;
+ }
+ $rs->free();
+ $this->batchUpdateTidInterpreted($occidArr);
}
- private function batchUpdateTidInterpreted($occidArr){
+ private function batchUpdateTidInterpreted(&$occidArr){
$status = false;
- if($occidArr){
- $sql = 'UPDATE omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname SET o.TidInterpreted = t.tid WHERE o.occid IN('.implode(',',$occidArr).') ';
+ foreach($occidArr as $tid => $idArr){
+ $sql = 'UPDATE omoccurrences SET tidInterpreted = '.$tid.' WHERE occid IN('.implode(',',$idArr).') ';
if($this->conn->query($sql)){
$status = true;
}
else{
$this->errorArr[] = 'WARNING: unable to update tidinterpreted; '.$this->conn->error;
- if($this->verbose) $this->outputMsg($this->errorArr,2);
+ $this->outputMsg($this->errorArr,2);
$status = false;
}
}
+ unset($occidArr);
return $status;
}
@@ -182,7 +203,23 @@ private function batchUpdateImageTid($occidArr){
}
else{
$this->errorArr[] = 'WARNING: unable to update image tid field; '.$this->conn->error;
- if($this->verbose) $this->outputMsg($this->errorArr,2);
+ $this->outputMsg($this->errorArr,2);
+ $status = false;
+ }
+ }
+ return $status;
+ }
+
+ private function batchScinameWithFamily($occidArr){
+ $status = false;
+ if($occidArr){
+ $sql = 'UPDATE omoccurrences SET sciname = family WHERE occid IN('.implode(',',$occidArr).') ';
+ if($this->conn->query($sql)){
+ $status = true;
+ }
+ else{
+ $this->errorArr[] = 'WARNING: unable to update sciname using family; '.$this->conn->error;
+ $this->outputMsg($this->errorArr,2);
$status = false;
}
}
@@ -198,7 +235,7 @@ private function batchUpdateFamily($occidArr){
}
else{
$this->errorArr[] = 'WARNING: unable to update family in omoccurrence table; '.$this->conn->error;
- if($this->verbose) $this->outputMsg($this->errorArr,2);
+ $this->outputMsg($this->errorArr,2);
$status = false;
}
}
@@ -214,25 +251,45 @@ private function batchUpdateAuthor($occidArr){
}
else{
$this->errorArr[] = 'WARNING: unable to update author; '.$this->conn->error;
- if($this->verbose) $this->outputMsg($this->errorArr,2);
+ $this->outputMsg($this->errorArr,2);
$status = false;
}
}
return $status;
}
+ public function batchUpdateGeoreferenceIndex(){
+ $status = false;
+ $this->outputMsg('Updating georeference index... ',1);
+ $sql = 'INSERT IGNORE INTO omoccurgeoindex(tid,decimallatitude,decimallongitude)
+ SELECT DISTINCT o.tidinterpreted, round(o.decimallatitude,2), round(o.decimallongitude,2)
+ FROM omoccurrences o
+ WHERE (o.tidinterpreted IS NOT NULL) AND (o.decimallatitude between -90 and 90) AND (o.decimallongitude between -180 and 180)
+ AND (o.cultivationStatus IS NULL OR o.cultivationStatus = 0) AND (o.coordinateUncertaintyInMeters IS NULL OR o.coordinateUncertaintyInMeters < 10000) ';
+ if($this->conn->query($sql)){
+ $status = true;
+ }
+ else{
+ $errStr = 'WARNING: unable to update georeference index; '.$this->conn->error;
+ $this->errorArr[] = $errStr;
+ $this->outputMsg($errStr,2);
+ }
+ return $status;
+ }
+
+
//Protect Rare species data
- public function protectRareSpecies($collid = 0){
+ public function protectRareSpecies(){
$status = 0;
- $status = $this->protectGlobalSpecies($collid);
+ $status = $this->protectGlobalSpecies();
$status += $this->batchProtectStateRareSpecies();
return $status;
}
- public function protectGlobalSpecies($collid = 0){
+ public function protectGlobalSpecies(){
$status = 0;
//protect globally rare species
- if($this->verbose) $this->outputMsg('Protecting globally rare species... ',1);
+ $this->outputMsg('Protecting globally rare species... ',1);
//Only protect names on list and synonym of accepted names
$sensitiveArr = $this->getSensitiveTaxa();
@@ -240,14 +297,14 @@ public function protectGlobalSpecies($collid = 0){
$sql = 'UPDATE omoccurrences '.
'SET LocalitySecurity = 1 '.
'WHERE (LocalitySecurity IS NULL OR LocalitySecurity = 0) AND (localitySecurityReason IS NULL) AND (tidinterpreted IN('.implode(',',$sensitiveArr).')) ';
- if($collid) $sql .= 'AND (collid = '.$collid.') ';
+ if($this->collidStr) $sql .= 'AND collid IN('.$this->collidStr.')';
if($this->conn->query($sql)){
$status += $this->conn->affected_rows;
}
else{
$errStr = 'WARNING: unable to protect globally rare species; '.$this->conn->error;
$this->errorArr[] = $errStr;
- if($this->verbose) $this->outputMsg($errStr,2);
+ $this->outputMsg($errStr,2);
$status = false;
}
}
@@ -278,7 +335,7 @@ private function getSensitiveTaxa(){
public function batchProtectStateRareSpecies(){
$status = 0;
//Protect state level rare species
- if($this->verbose) $this->outputMsg('Protecting state level rare species... ',1);
+ $this->outputMsg('Protecting state level rare species... ',1);
$sql = 'SELECT clid, locality FROM fmchecklists WHERE type = "rarespp"';
$rs = $this->conn->query($sql);
while($r = $rs->fetch_object()){
@@ -310,7 +367,7 @@ public function protectStateRareSpecies($clid,$locality){
else{
$errStr = 'WARNING: unable to protect state level rare species; '.$this->conn->error;
$this->errorArr[] = $errStr;
- if($this->verbose) $this->outputMsg($errStr,2);
+ $this->outputMsg($errStr,2);
$status = false;
}
}
@@ -336,165 +393,160 @@ public function getStateProtectionCount($clid, $state){
}
//Update statistics
- public function updateCollectionStats($collid, $full = false){
- set_time_limit(600);
- $recordCnt = 0;
- $georefCnt = 0;
- $familyCnt = 0;
- $genusCnt = 0;
- $speciesCnt = 0;
- if($full){
- $statsArr = Array();
- if($this->verbose) $this->outputMsg('Calculating specimen, georeference, family, genera, and species counts... ',1);
- $sql = 'SELECT COUNT(o.occid) AS SpecimenCount, COUNT(o.decimalLatitude) AS GeorefCount, '.
- 'COUNT(DISTINCT o.family) AS FamilyCount, COUNT(o.typeStatus) AS TypeCount, '.
- 'COUNT(DISTINCT CASE WHEN t.RankId >= 180 THEN t.UnitName1 ELSE NULL END) AS GeneraCount, '.
- 'COUNT(CASE WHEN t.RankId >= 220 THEN o.occid ELSE NULL END) AS SpecimensCountID, '.
- 'COUNT(DISTINCT CASE WHEN t.RankId = 220 THEN t.SciName ELSE NULL END) AS SpeciesCount, '.
- 'COUNT(DISTINCT CASE WHEN t.RankId >= 220 THEN t.SciName ELSE NULL END) AS TotalTaxaCount '.
- 'FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID '.
- 'WHERE (o.collid IN('.$collid.')) ';
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $recordCnt = $r->SpecimenCount;
- $georefCnt = $r->GeorefCount;
- $familyCnt = $r->FamilyCount;
- $genusCnt = $r->GeneraCount;
- $speciesCnt = $r->SpeciesCount;
- $statsArr['SpecimensCountID'] = $r->SpecimensCountID;
- $statsArr['TotalTaxaCount'] = $r->TotalTaxaCount;
- $statsArr['TypeCount'] = $r->TypeCount;
- }
- $rs->free();
-
- if($this->verbose) $this->outputMsg('Calculating number of specimens imaged... ',1);
- $sql = 'SELECT count(DISTINCT o.occid) as imgspeccnt, count(DISTINCT i.imgid) AS imgcnt '.
- 'FROM omoccurrences o INNER JOIN images i ON o.occid = i.occid '.
- 'WHERE (o.collid IN('.$collid.')) ';
- $rs = $this->conn->query($sql);
- if($r = $rs->fetch_object()){
- $statsArr['imgcnt'] = $r->imgcnt.':'.$r->imgspeccnt;
- }
- $rs->free();
-
- if($this->verbose) $this->outputMsg('Calculating genetic resources counts... ',1);
- $sql = 'SELECT COUNT(CASE WHEN g.resourceurl LIKE "%boldsystems%" THEN o.occid ELSE NULL END) AS boldcnt, '.
- 'COUNT(CASE WHEN g.resourceurl LIKE "%ncbi%" THEN o.occid ELSE NULL END) AS gencnt, '.
- 'COUNT(CASE WHEN g.resourceurl NOT LIKE "%boldsystems%" AND g.resourceurl NOT LIKE "%ncbi%" THEN o.occid ELSE NULL END) AS geneticcnt '.
- 'FROM omoccurrences o INNER JOIN omoccurgenetic g ON o.occid = g.occid '.
- 'WHERE (o.collid IN('.$collid.')) ';
- $rs = $this->conn->query($sql);
- if($r = $rs->fetch_object()){
- $statsArr['boldcnt'] = $r->boldcnt;
- $statsArr['gencnt'] = $r->gencnt;
- $statsArr['geneticcnt'] = $r->geneticcnt;
- }
- $rs->free();
-
- if($this->verbose) $this->outputMsg('Calculating reference counts... ',1);
- $sql = 'SELECT count(r.occid) as refcnt '.
- 'FROM omoccurrences o INNER JOIN referenceoccurlink r ON o.occid = r.occid '.
- 'WHERE (o.collid IN('.$collid.')) ';
- $rs = $this->conn->query($sql);
- if($r = $rs->fetch_object()){
- $statsArr['refcnt'] = $r->refcnt;
- }
- $rs->free();
-
- if($this->verbose) $this->outputMsg('Calculating counts per family... ',1);
- $sql = 'SELECT o.family, COUNT(o.occid) AS SpecimensPerFamily, COUNT(o.decimalLatitude) AS GeorefSpecimensPerFamily, '.
- 'COUNT(CASE WHEN t.RankId >= 220 THEN o.occid ELSE NULL END) AS IDSpecimensPerFamily, '.
- 'COUNT(CASE WHEN t.RankId >= 220 AND o.decimalLatitude IS NOT NULL THEN o.occid ELSE NULL END) AS IDGeorefSpecimensPerFamily '.
- 'FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID '.
- 'WHERE (o.collid IN('.$collid.')) '.
- 'GROUP BY o.family ';
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $family = str_replace(array('"',"'"),"",$r->family);
- if($family){
- $statsArr['families'][$family]['SpecimensPerFamily'] = $r->SpecimensPerFamily;
- $statsArr['families'][$family]['GeorefSpecimensPerFamily'] = $r->GeorefSpecimensPerFamily;
- $statsArr['families'][$family]['IDSpecimensPerFamily'] = $r->IDSpecimensPerFamily;
- $statsArr['families'][$family]['IDGeorefSpecimensPerFamily'] = $r->IDGeorefSpecimensPerFamily;
- }
- }
- $rs->free();
-
- if($this->verbose) $this->outputMsg('Calculating counts per country... ',1);
- $sql = 'SELECT o.country, COUNT(o.occid) AS CountryCount, COUNT(o.decimalLatitude) AS GeorefSpecimensPerCountry, '.
- 'COUNT(CASE WHEN t.RankId >= 220 THEN o.occid ELSE NULL END) AS IDSpecimensPerCountry, '.
- 'COUNT(CASE WHEN t.RankId >= 220 AND o.decimalLatitude IS NOT NULL THEN o.occid ELSE NULL END) AS IDGeorefSpecimensPerCountry '.
- 'FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID '.
- 'WHERE (o.collid IN('.$collid.')) '.
- 'GROUP BY o.country ';
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $country = str_replace(array('"',"'"),"",$r->country);
- if($country){
- $statsArr['countries'][$country]['CountryCount'] = $r->CountryCount;
- $statsArr['countries'][$country]['GeorefSpecimensPerCountry'] = $r->GeorefSpecimensPerCountry;
- $statsArr['countries'][$country]['IDSpecimensPerCountry'] = $r->IDSpecimensPerCountry;
- $statsArr['countries'][$country]['IDGeorefSpecimensPerCountry'] = $r->IDGeorefSpecimensPerCountry;
+ public function updateCollectionStatsFull(){
+ if($this->collidStr){
+ set_time_limit(600);
+ $collArr = explode(',', $this->collidStr);
+ foreach($collArr as $collid){
+ if(is_numeric($collid)){
+ $statsArr = Array();
+ $this->outputMsg('Calculating specimen, georeference, family, genera, and species counts... ', 1);
+ $sql = 'SELECT COUNT(CASE WHEN t.RankId >= 220 THEN o.occid ELSE NULL END) AS SpecimensCountID,
+ COUNT(DISTINCT CASE WHEN t.RankId >= 220 THEN t.SciName ELSE NULL END) AS TotalTaxaCount, COUNT(o.typeStatus) AS TypeCount
+ FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID
+ WHERE o.collid IN('.$collid.')';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ $statsArr['SpecimensCountID'] = $r->SpecimensCountID;
+ $statsArr['TotalTaxaCount'] = $r->TotalTaxaCount;
+ $statsArr['TypeCount'] = $r->TypeCount;
+ }
+ $rs->free();
+
+ $this->outputMsg('Calculating number of specimens imaged... ', 1);
+ $sql = 'SELECT count(DISTINCT o.occid) as imgspeccnt, count(DISTINCT i.imgid) AS imgcnt
+ FROM omoccurrences o INNER JOIN images i ON o.occid = i.occid
+ WHERE o.collid = '.$collid;
+ $rs = $this->conn->query($sql);
+ if($r = $rs->fetch_object()){
+ $statsArr['imgcnt'] = $r->imgcnt.':'.$r->imgspeccnt;
+ }
+ $rs->free();
+
+ $this->outputMsg('Calculating genetic resources counts... ', 1);
+ $sql = 'SELECT COUNT(CASE WHEN g.resourceurl LIKE "%boldsystems%" THEN o.occid ELSE NULL END) AS boldcnt,
+ COUNT(CASE WHEN g.resourceurl LIKE "%ncbi%" THEN o.occid ELSE NULL END) AS gencnt,
+ COUNT(CASE WHEN g.resourceurl NOT LIKE "%boldsystems%" AND g.resourceurl NOT LIKE "%ncbi%" THEN o.occid ELSE NULL END) AS geneticcnt
+ FROM omoccurrences o INNER JOIN omoccurgenetic g ON o.occid = g.occid
+ WHERE o.collid = '.$collid;
+ $rs = $this->conn->query($sql);
+ if($r = $rs->fetch_object()){
+ $statsArr['boldcnt'] = $r->boldcnt;
+ $statsArr['gencnt'] = $r->gencnt;
+ $statsArr['geneticcnt'] = $r->geneticcnt;
+ }
+ $rs->free();
+
+ $this->outputMsg('Calculating reference counts... ', 1);
+ $sql = 'SELECT count(r.occid) as refcnt FROM omoccurrences o INNER JOIN referenceoccurlink r ON o.occid = r.occid WHERE o.collid = '.$collid;
+ $rs = $this->conn->query($sql);
+ if($r = $rs->fetch_object()){
+ $statsArr['refcnt'] = $r->refcnt;
+ }
+ $rs->free();
+
+ $this->outputMsg('Calculating counts per family... ', 1);
+ $sql = 'SELECT o.family, COUNT(o.occid) AS SpecimensPerFamily, COUNT(o.decimalLatitude) AS GeorefSpecimensPerFamily,
+ COUNT(CASE WHEN t.RankId >= 220 THEN o.occid ELSE NULL END) AS IDSpecimensPerFamily,
+ COUNT(CASE WHEN t.RankId >= 220 AND o.decimalLatitude IS NOT NULL THEN o.occid ELSE NULL END) AS IDGeorefSpecimensPerFamily
+ FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID
+ WHERE o.collid = '.$collid.' GROUP BY o.family ';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ $family = str_replace(array('"',"'"),"",$r->family);
+ if($family){
+ $statsArr['families'][$family]['SpecimensPerFamily'] = $r->SpecimensPerFamily;
+ $statsArr['families'][$family]['GeorefSpecimensPerFamily'] = $r->GeorefSpecimensPerFamily;
+ $statsArr['families'][$family]['IDSpecimensPerFamily'] = $r->IDSpecimensPerFamily;
+ $statsArr['families'][$family]['IDGeorefSpecimensPerFamily'] = $r->IDGeorefSpecimensPerFamily;
+ }
+ }
+ $rs->free();
+
+ $this->outputMsg('Calculating counts per country... ', 1);
+ $sql = 'SELECT o.country, COUNT(o.occid) AS CountryCount, COUNT(o.decimalLatitude) AS GeorefSpecimensPerCountry,
+ COUNT(CASE WHEN t.RankId >= 220 THEN o.occid ELSE NULL END) AS IDSpecimensPerCountry,
+ COUNT(CASE WHEN t.RankId >= 220 AND o.decimalLatitude IS NOT NULL THEN o.occid ELSE NULL END) AS IDGeorefSpecimensPerCountry
+ FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID
+ WHERE o.collid = '.$collid.' GROUP BY o.country ';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ $country = str_replace(array('"',"'"),"",$r->country);
+ if($country){
+ $statsArr['countries'][$country]['CountryCount'] = $r->CountryCount;
+ $statsArr['countries'][$country]['GeorefSpecimensPerCountry'] = $r->GeorefSpecimensPerCountry;
+ $statsArr['countries'][$country]['IDSpecimensPerCountry'] = $r->IDSpecimensPerCountry;
+ $statsArr['countries'][$country]['IDGeorefSpecimensPerCountry'] = $r->IDGeorefSpecimensPerCountry;
+ }
+ }
+ $rs->free();
+
+ if($statsArr) $this->updateCollectionStats(array('dynamicProperties' => json_encode($statsArr)), $collid);
+ $this->updateCollectionStatsBasic($collid);
}
}
- $rs->free();
-
- $returnArrJson = json_encode($statsArr);
- $sql = 'UPDATE omcollectionstats '.
- "SET dynamicProperties = '".$this->cleanInStr($returnArrJson)."' ".
- 'WHERE collid IN('.$collid.') ';
- if(!$this->conn->query($sql)){
- $errStr = 'WARNING: unable to update collection stats table [1]; '.$this->conn->error;
- $this->errorArr[] = $errStr;
- if($this->verbose) $this->outputMsg($errStr,2);
- }
}
- else{
- if($this->verbose) $this->outputMsg('Calculating specimen, georeference, family, genera, and species counts... ',1);
+ }
+
+ public function updateCollectionStatsBasic($collid){
+ if(is_numeric($collid)){
+ $this->outputMsg('Calculating specimen, georeference, family, genera, and species counts... ',1);
+ $statArr = array();
$sql = 'SELECT COUNT(o.occid) AS SpecimenCount, COUNT(o.decimalLatitude) AS GeorefCount, COUNT(DISTINCT o.family) AS FamilyCount, '.
'COUNT(DISTINCT CASE WHEN t.RankId >= 180 THEN t.UnitName1 ELSE NULL END) AS GeneraCount, '.
'COUNT(DISTINCT CASE WHEN t.RankId = 220 THEN t.SciName ELSE NULL END) AS SpeciesCount '.
'FROM omoccurrences o LEFT JOIN taxa t ON o.tidinterpreted = t.TID '.
- 'WHERE (o.collid IN('.$collid.')) ';
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $recordCnt = $r->SpecimenCount;
- $georefCnt = $r->GeorefCount;
- $familyCnt = $r->FamilyCount;
- $genusCnt = $r->GeneraCount;
- $speciesCnt = $r->SpeciesCount;
+ 'WHERE o.collid = ?';
+ if($stmt = $this->conn->prepare($sql)){
+ $stmt->bind_param('i', $collid);
+ $stmt->execute();
+ $stmt->bind_result($recCnt, $georefCnt, $familyCnt, $genusCnt, $speciesCnt);
+ if($stmt->fetch()){
+ $statArr['recordcnt'] = $recCnt;
+ $statArr['georefcnt'] = $georefCnt;
+ $statArr['familycnt'] = $familyCnt;
+ $statArr['genuscnt'] = $genusCnt;
+ $statArr['speciescnt'] = $speciesCnt;
+ }
+ $stmt->close();
}
- }
-
- $sql = 'UPDATE omcollectionstats cs '.
- 'SET cs.recordcnt = '.$recordCnt.',cs.georefcnt = '.$georefCnt.',cs.familycnt = '.$familyCnt.',cs.genuscnt = '.$genusCnt.
- ',cs.speciescnt = '.$speciesCnt.', cs.datelastmodified = CURDATE() '.
- 'WHERE cs.collid IN('.$collid.')';
- if(!$this->conn->query($sql)){
- $errStr = 'WARNING: unable to update collection stats table [2]; '.$this->conn->error;
- $this->errorArr[] = $errStr;
- if($this->verbose) $this->outputMsg($errStr,2);
+ if($statArr) $this->updateCollectionStats($statArr, $collid);
}
}
- //Misc support functions
- public function getCollectionMetadata($collid){
- $retArr = array();
- if(is_numeric($collid)){
- $sql = 'SELECT institutioncode, collectioncode, collectionname, colltype, managementtype '.
- 'FROM omcollections '.
- 'WHERE collid = '.$collid;
- $rs = $this->conn->query($sql);
- while($r = $rs->fetch_object()){
- $retArr['instcode'] = $r->institutioncode;
- $retArr['collcode'] = $r->collectioncode;
- $retArr['collname'] = $r->collectionname;
- $retArr['colltype'] = $r->colltype;
- $retArr['mantype'] = $r->managementtype;
+ private function updateCollectionStats($inputData, $collid){
+ $status = false;
+ if($inputData){
+ $paramArr = array();
+ $type = '';
+ $sql = 'UPDATE omcollectionstats SET ';
+ foreach($inputData as $field => $value){
+ $sql .= $field.' = ?, ';
+ if($field == 'dynamicProperties') $type .= 's';
+ else $type .= 'i';
+ $paramArr[] = $value;
+ }
+ $sql .= ' datelastmodified = NOW() WHERE collid = ?';
+ $type .= 'i';
+ $paramArr[] = $collid;
+ if($stmt = $this->conn->prepare($sql)){
+ $stmt->bind_param($type, ...$paramArr);
+ $stmt->execute();
+ if($stmt->error){
+ $errStr = 'ERROR updating collection stats table: '.$stmt->error;
+ $this->errorArr[] = $errStr;
+ $this->outputMsg($errStr,2);
+ }
+ else $status = true;
+ $stmt->close();
}
- $rs->free();
}
- return $retArr;
+ return $status;
+ }
+
+ //Setters and getters
+ public function setCollidStr($idStr){
+ if($idStr && preg_match('/^[\d,]+$/', $idStr)) $this->collidStr = $idStr;
}
public function setVerbose($v){
@@ -510,17 +562,13 @@ public function getErrorArr(){
return $this->errorArr;
}
+ //Misc support functions
private function outputMsg($str, $indent = 0){
- if($this->verbose) echo ''.$str.' ';
- ob_flush();
- flush();
- }
-
- private function cleanInStr($inStr){
- $retStr = trim($inStr);
- $retStr = preg_replace('/\s\s+/', ' ',$retStr);
- $retStr = $this->conn->real_escape_string($retStr);
- return $retStr;
+ if($this->verbose){
+ echo ''.$str.' ';
+ ob_flush();
+ flush();
+ }
}
}
?>
\ No newline at end of file
diff --git a/classes/SpecUploadBase.php b/classes/SpecUploadBase.php
index d60340ddf1..d5b6e2f070 100644
--- a/classes/SpecUploadBase.php
+++ b/classes/SpecUploadBase.php
@@ -1499,8 +1499,9 @@ protected function finalCleanup(){
//Do some more cleaning of the data after it has been indexed in the omoccurrences table
$occurMain = new OccurrenceMaintenance($this->conn);
+ $occurMain->setCollidStr($this->collId);
- if(!$occurMain->generalOccurrenceCleaning($this->collId)){
+ if(!$occurMain->generalOccurrenceCleaning()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->outputMsg(''.$errorStr.' ',1);
@@ -1508,10 +1509,10 @@ protected function finalCleanup(){
}
$this->outputMsg('Protecting sensitive species... ');
- $protectCnt = $occurMain->protectRareSpecies($this->collId);
+ $protectCnt = $occurMain->protectRareSpecies();
$this->outputMsg('Updating statistics... ');
- if(!$occurMain->updateCollectionStats($this->collId)){
+ if(!$occurMain->updateCollectionStatsFull()){
$errorArr = $occurMain->getErrorArr();
foreach($errorArr as $errorStr){
$this->outputMsg(''.$errorStr.' ',1);
diff --git a/classes/TPDescEditorManager.php b/classes/TPDescEditorManager.php
index c4817196af..800a1726a7 100644
--- a/classes/TPDescEditorManager.php
+++ b/classes/TPDescEditorManager.php
@@ -14,8 +14,8 @@ public function __destruct(){
public function getDescriptions(){
$descrArr = Array();
$langArr = false;
- $sql = 'SELECT p.tdProfileID, IFNULL(p.caption, d.caption) as caption, IFNULL(p.publication, d.source) AS source, IFNULL(p.urlTemplate, d.sourceurl) AS sourceurl,
- IFNULL(p.defaultDisplayLevel, d.displaylevel) AS displaylevel, t.tid, t.sciname, d.tdbid, d.notes, l.langid, d.language
+ $sql = 'SELECT p.tdProfileID, IFNULL(d.caption, p.caption) as caption, IFNULL(d.source, p.publication) AS source, IFNULL(d.sourceurl, p.urlTemplate) AS sourceurl,
+ IFNULL(d.displaylevel, p.defaultDisplayLevel) AS displaylevel, t.tid, t.sciname, d.tdbid, d.notes, l.langid, d.language
FROM taxadescrprofile p INNER JOIN taxadescrblock d ON p.tdProfileID = d.tdProfileID
LEFT JOIN adminlanguages l ON p.langid = l.langid ';
if($this->acceptance){
diff --git a/classes/TaxonProfile.php b/classes/TaxonProfile.php
index efbb9d9b0c..b2d02f4869 100644
--- a/classes/TaxonProfile.php
+++ b/classes/TaxonProfile.php
@@ -340,8 +340,8 @@ private function getDescriptions(){
$retArr = Array();
if($this->tid){
$rsArr = array();
- $sql = 'SELECT p.tdProfileID, IFNULL(p.caption, d.caption) as caption, IFNULL(p.publication, d.source) AS source, IFNULL(p.urlTemplate, d.sourceurl) AS sourceurl,
- IFNULL(p.defaultDisplayLevel, d.displaylevel) AS displaylevel, d.tid, d.tdbid, s.tdsid, s.heading, s.statement, s.displayheader, d.language, p.langid
+ $sql = 'SELECT p.tdProfileID, IFNULL(d.caption, p.caption) as caption, IFNULL(d.source, p.publication) AS source, IFNULL(d.sourceurl, p.urlTemplate) AS sourceurl,
+ IFNULL(d.displaylevel, p.defaultDisplayLevel) AS displaylevel, d.tid, d.tdbid, s.tdsid, s.heading, s.statement, s.displayheader, d.language, p.langid
FROM taxadescrprofile p INNER JOIN taxadescrblock d ON p.tdProfileID = d.tdProfileID
INNER JOIN taxadescrstmts s ON d.tdbid = s.tdbid
LEFT JOIN adminlanguages l ON p.langid = l.langid ';
@@ -482,6 +482,23 @@ public function getLinkArr(){
return $this->linkArr;
}
+ public function getResourceLinkArr(){
+ $retArr = array();
+ if($this->tid){
+ $sql = 'SELECT taxaResourceID, sourceName, sourceIdentifier, sourceGuid, url, notes FROM taxaresourcelinks WHERE tid = '.$this->tid.' ORDER BY ranking, sourceName';
+ $rs = $this->conn->query($sql);
+ while($r = $rs->fetch_object()){
+ $retArr[$r->taxaResourceID]['name'] = $r->sourceName;
+ $retArr[$r->taxaResourceID]['id'] = $r->sourceIdentifier;
+ $retArr[$r->taxaResourceID]['guid'] = $r->sourceGuid;
+ $retArr[$r->taxaResourceID]['url'] = $r->url;
+ $retArr[$r->taxaResourceID]['notes'] = $r->notes;
+ }
+ $rs->free();
+ }
+ return $retArr;
+ }
+
//Set children data for taxon higher than species level
public function getSppArray($page, $taxaLimit, $pid, $clid){
if(!$this->sppArray && $this->tid){
diff --git a/classes/TaxonomyCleaner.php b/classes/TaxonomyCleaner.php
index e824d19c33..0bf44d0328 100644
--- a/classes/TaxonomyCleaner.php
+++ b/classes/TaxonomyCleaner.php
@@ -3,6 +3,7 @@
include_once($SERVER_ROOT.'/classes/Manager.php');
include_once($SERVER_ROOT.'/classes/TaxonomyUtilities.php');
include_once($SERVER_ROOT.'/classes/TaxonomyHarvester.php');
+include_once($SERVER_ROOT.'/classes/OccurrenceMaintenance.php');
class TaxonomyCleaner extends Manager{
@@ -306,42 +307,10 @@ private function indexOccurrenceTaxa(){
flush();
ob_flush();
- $sql = 'UPDATE omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname '.
- 'SET o.tidinterpreted = t.tid '.
- 'WHERE (o.collid IN('.$this->collid.')) AND (o.tidinterpreted IS NULL) ';
- //echo $sql;
- if($this->conn->query($sql)){
- $this->logOrEcho('Indexing names based on exact matches... ' . $this->conn->affected_rows.' occurrence records mapped', 1);
- }
- else{
- $this->logOrEcho('ERROR linking new data to occurrences: '.$this->conn->error, 1);
- }
- flush();
- ob_flush();
-
- $sql = 'UPDATE omoccurrences o INNER JOIN taxa t ON o.tidinterpreted = t.tid
- SET o.scientificNameAuthorship = t.author
- WHERE (o.collid IN('.$this->collid.')) AND (o.scientificNameAuthorship IS NULL) AND (t.author IS NOT NULL) ';
- if($this->conn->query($sql)){
- $this->logOrEcho('Populating null scientific authors within occurrence tables... ' . $this->conn->affected_rows.' occurrence records populated', 1);
- }
- else{
- $this->logOrEcho('ERROR updating authors: '.$this->conn->error, 1);
- }
- flush();
- ob_flush();
-
- $sql = 'UPDATE omoccurrences o INNER JOIN taxstatus ts ON o.tidinterpreted = ts.tid
- SET o.family = ts.family
- WHERE (o.collid IN('.$this->collid.')) AND (o.family IS NULL) AND (ts.family IS NOT NULL) ';
- if($this->conn->query($sql)){
- $this->logOrEcho('Populating null family names within occurrence tables... ' . $this->conn->affected_rows . ' occurrence records populated', 1);
- }
- else{
- $this->logOrEcho('ERROR updating family occurrences: '.$this->conn->error, 1);
- }
- flush();
- ob_flush();
+ $occurMaintenance = new OccurrenceMaintenance($this->conn);
+ $occurMaintenance->setCollidStr($this->collid);
+ $occurMaintenance->setVerbose(true);
+ $occurMaintenance->generalOccurrenceCleaning();
}
public function remapOccurrenceTaxon($collid, $oldSciname, $tid, $idQualifier = ''){
diff --git a/classes/TaxonomyCleanerOccurrences.php b/classes/TaxonomyCleanerOccurrences.php
index b006988f0b..4def13c06d 100644
--- a/classes/TaxonomyCleanerOccurrences.php
+++ b/classes/TaxonomyCleanerOccurrences.php
@@ -1,10 +1,10 @@
conn->query($sql);
- }
-
public function verifyCollectionTaxa($collId){
//Grab list of taxa, check each one, add valid taxa to taxonomic thesaurus, return number added and number problematic remaining
$numGood = 0;
$numBad = 0;
$sql = 'SELECT DISTINCT o.sciname FROM omoccurrences o '.
'WHERE o.tidinterpreted IS NULL AND o.sciname IS NOT NULL ';
- if($collId && is_numeric($collId)) $sql .= 'AND (o.collid = '.$collId.') ';
+ if($collId && is_numeric($collId)) $sql .= 'AND (o.collid = '.$collId.') ';
$sql .= 'ORDER BY o.sciname LIMIT 1';
//echo ''.$sql.'
';
$rs = $this->conn->query($sql);
@@ -42,22 +33,22 @@ public function verifyCollectionTaxa($collId){
//Default to internal system's taxonomy
//1. Go through external synonyms
//2. If one is found and taxonomically tested, add new name linked to the accepted name of that taxon
- //3. Add and link rest of the Synonyms to this name
+ //3. Add and link rest of the Synonyms to this name
//Default to external system's taxonomy
//1. Add name as accepted
//2. Go through synonyms and add linked to new name
- //3. If synonym already exists, link to accetped name
+ //3. If synonym already exists, link to accetped name
//External is not accepted
//1. Grab and test external accepted name
//Default to internal system's taxonomy
- //2a. Accepted name does not exist: Go through synonyms and test,
+ //2a. Accepted name does not exist: Go through synonyms and test,
//3a. If one exists, map all to this accepted taxon
//3b. If not, add accepted name and link all to it (including synonyms)
- //2b. Accepted name exists: Link all to it (including synonyms)
+ //2b. Accepted name exists: Link all to it (including synonyms)
//Default to external system's taxonomy
//4a. External accepted does not exist: add name and link all to it (including synonyms that don't exist)
//4b. External accepted does exists...
-
+
}
else{
//Name is not good, mark as so
@@ -95,7 +86,7 @@ private function getHierarchy($tid){
if($targetTid == $parentTid) break;
$targetTid = $parentTid;
}while($targetTid && $parCnt < 16);
-
+
return implode(",",array_reverse($parentArr));
}
@@ -112,7 +103,7 @@ public function getCollectionName(){
}
return $retStr;
}
-
+
public function getTaxaList($index = 0){
$retArr = array();
$sql = 'SELECT sciname '.
@@ -128,7 +119,7 @@ public function getTaxaList($index = 0){
}
return $retArr;
}
-
+
public function analyzeTaxa($startIndex = 0, $limit = 10){
$retArr = array();
$sql = 'SELECT sciname '.
@@ -141,11 +132,11 @@ public function analyzeTaxa($startIndex = 0, $limit = 10){
$sn = $row->sciname;
$sxArr[$sn] = $sn;
//Check name through Catalog of Life
-
+
//Check for near match using SoundEx
$sxArr = $this->getSoundexMatch($sn);
if($sxArr) $retArr[$sn]['soundex'] = $sxArr;
-
+
}
$rs->close();
}
@@ -167,7 +158,7 @@ public function getTaxaCount(){
}
return $retStr;
}
-
+
public function setCollId($id){
if(is_numeric($id)){
$this->collId = $id;
diff --git a/classes/TaxonomyHarvester.php b/classes/TaxonomyHarvester.php
index 4cf66c7bd6..296b6073a3 100644
--- a/classes/TaxonomyHarvester.php
+++ b/classes/TaxonomyHarvester.php
@@ -137,9 +137,13 @@ private function addSciname($taxonArr, $resourceKey){
*/
private function addColTaxon($taxonArr){
$tid = 0;
+ if(preg_match('/^[A-Z){1}[a-z]+\s{1}\(([A-Z){1}[a-z]+)\)$/', $taxonArr['sciname'], $m)){
+ //Remove Genus from subgeneric name
+ $taxonArr['sciname'] = $m[1];
+ }
$sciName = $taxonArr['sciname'];
if($sciName){
- //$url = 'https://api.catalogueoflife.org/nameusage/search?content=SCIENTIFIC_NAME&q='.str_replace(' ','%20'.,$adjustedName).'&offset=0&limit=10';
+ //$url = 'https://api.catalogueoflife.org/nameusage/search?content=SCIENTIFIC_NAME&q='.str_replace(' ','%20',$sciName).'&offset=0&limit=10';
$url = 'https://webservice.catalogueoflife.org/col/webservice?response=full&format=json&name='.str_replace(' ','%20',$sciName);
//echo $url.' ';
$retArr = $this->getContentString($url);
@@ -147,16 +151,16 @@ private function addColTaxon($taxonArr){
$resultArr = json_decode($content,true);
$numResults = $resultArr['number_of_results_returned'];
if($numResults){
+ //Evaluate and rank each result to determine which is the best suited target
$adjustedName = $sciName;
if(isset($taxonArr['rankid']) && $taxonArr['rankid'] > 220) $adjustedName = trim($taxonArr['unitname1'].' '.$taxonArr['unitname2'].' '.$taxonArr['unitname3']);
$targetKey = 0;
$submitArr = array();
- $rankArr = array();
+ $rankingArr = array();
foreach($resultArr['result'] as $k => $tArr){
- //Evaluate and rank each result to determine which is the best suited target
- $rankArr[$k] = 0;
+ $rankingArr[$k] = 0;
if($sciName != $tArr['name'] && $adjustedName != $tArr['name']){
- unset($rankArr[$k]);
+ unset($rankingArr[$k]);
continue;
}
$this->setColClassification($tArr,$taxonArr);
@@ -164,7 +168,7 @@ private function addColTaxon($taxonArr){
$taxonKingdom = $this->getColParent($tArr, 'Kingdom');
if($this->kingdomName && $taxonKingdom && $this->kingdomName != $taxonKingdom){
//Skip if kingdom doesn't match target kingdom
- unset($rankArr[$k]);
+ unset($rankingArr[$k]);
$msg = $sciName;
$id = '';
if(isset($resultArr['result'][$k]['id'])){
@@ -177,15 +181,16 @@ private function addColTaxon($taxonArr){
}
if($taxonArr['unitind3'] && isset($tArr['infraspeciesMarker']) && $taxonArr['unitind3'] != $tArr['infraspeciesMarker']){
//Skip because it's not the correct infraspecific rank
- unset($rankArr[$k]);
+ unset($rankingArr[$k]);
continue;
}
- if($this->defaultFamily && $this->defaultFamily == $this->getColParent($tArr, 'Family')) $rankArr[$k] += 2;
- if($tArr['name_status'] == 'accepted name') $rankArr[$k] += 2;
+ if(isset($taxonArr['taxonRank']) && isset($tArr['rank']) && $taxonArr['taxonRank'] == $tArr['rank']) $rankingArr[$k] += 2;
+ if($this->defaultFamily && $this->defaultFamily == $this->getColParent($tArr, 'Family')) $rankingArr[$k] += 2;
+ if($tArr['name_status'] == 'accepted name') $rankingArr[$k] += 2;
if(isset($tArr['author']) && $tArr['author']){
if(stripos($tArr['author'],'nom. illeg.') !== false){
//Skip if name is an illegal homonym
- unset($rankArr[$k]);
+ unset($rankingArr[$k]);
continue;
}
//Gets 2 points if author is the same, 1 point if 80% similar
@@ -194,18 +199,29 @@ private function addColTaxon($taxonArr){
$author2 = str_replace(array(' ','.'), '', $tArr['author']);
$percent = 0;
similar_text($author1, $author2, $percent);
- if($author1 == $author2) $rankArr[$k] += 2;
- elseif($percent > 80) $rankArr[$k] += 1;
+ if($author1 == $author2) $rankingArr[$k] += 2;
+ elseif($percent > 80) $rankingArr[$k] += 1;
}
}
$submitArr[$k] = $resultArr['result'][$k];
}
- if($rankArr){
- asort($rankArr);
- end($rankArr);
- $targetKey = key($rankArr);
- if(isset($rankArr[0]) && $rankArr[$targetKey] == $rankArr[0]) $targetKey = 0;
+ if($rankingArr){
+ asort($rankingArr);
+ end($rankingArr);
+ $targetKey = key($rankingArr);
+ if(isset($rankingArr[0]) && $rankingArr[$targetKey] == $rankingArr[0]) $targetKey = 0;
}
+ //If taxon has an accepted taxon that is the same taxon with a subgeneric linkage, use the taxon object to be submitted
+ if(isset($submitArr[$targetKey]['accepted_name'])){
+ if(preg_match('/^([A-Z]{1}[a-z]+)\s{1}\(\D+\)\s{1}([a-z .]+)/', $submitArr[$targetKey]['accepted_name']['name'], $m)){
+ $acceptedBaseName = $m[1].' '.$m[2];
+ if($submitArr[$targetKey]['name'] == $acceptedBaseName){
+ $submitArr[0] = $submitArr[$targetKey]['accepted_name'];
+ $targetKey = 0;
+ }
+ }
+ }
+ //Process selected result
$this->logOrEcho(''.$sciName.' found within Catalog of Life',2);
if(array_key_exists($targetKey, $submitArr) && $submitArr[$targetKey]){
$tid = $this->addColTaxonByResult($submitArr[$targetKey]);
@@ -222,7 +238,14 @@ private function addColTaxonByResult($baseArr){
$taxonArr = array();
if($baseArr){
$taxonArr = $this->translateColNode($baseArr);
- $this->setColClassification($baseArr,$taxonArr);
+ $this->setColClassification($baseArr, $taxonArr);
+ if($taxonArr['rankid'] == 190){
+ if(!strpos($taxonArr['sciname'], ' (') && isset($baseArr['formattedClassification'][180]['sciname'])){
+ $reformattedName = $baseArr['formattedClassification'][180]['sciname'].' ('.$taxonArr['sciname'].')';
+ $taxonArr['sciname'] = $reformattedName;
+ $taxonArr['unitname1'] = $reformattedName;
+ }
+ }
if(isset($baseArr['formattedClassification'][140]['sciname'])) $taxonArr['family'] = $baseArr['formattedClassification'][140]['sciname'];
$tidAccepted = 0;
if($baseArr['name_status'] == 'synonym' && isset($baseArr['accepted_name'])){
@@ -276,75 +299,68 @@ private function addColTaxonByResult($baseArr){
}
private function addColTaxonById($taxonArr){
- $tid = 0;
- if($taxonArr['id']){
- $url = 'https://webservice.catalogueoflife.org/col/webservice?response=full&format=json&id='.$taxonArr['id'];
- //echo $url.' ';
- $retArr = $this->getContentString($url);
- $content = $retArr['str'];
- $resultArr = json_decode($content,true);
- if(isset($resultArr['result'][0])){
- $baseArr = $resultArr['result'][0];
- if(isset($taxonArr['datasetKey'])) $baseArr['datasetKey'] = $taxonArr['datasetKey'];
- if(isset($taxonArr['formattedClassification'])) $baseArr['formattedClassification'] = $taxonArr['formattedClassification'];
- $tid = $this->addColTaxonByResult($baseArr);
- }
- else{
- $this->logOrEcho('Targeted taxon return does not exist(2)',2);
- }
- }
- else{
- $this->logOrEcho('ERROR harvesting COL name: null input identifier',1);
- }
- return $tid;
+ $tid = 0;
+ if($taxonArr['id']){
+ $url = 'https://webservice.catalogueoflife.org/col/webservice?response=full&format=json&id='.$taxonArr['id'];
+ $retArr = $this->getContentString($url);
+ $content = $retArr['str'];
+ $resultArr = json_decode($content,true);
+ if(isset($resultArr['result'][0])){
+ $baseArr = $resultArr['result'][0];
+ if(isset($taxonArr['datasetKey'])) $baseArr['datasetKey'] = $taxonArr['datasetKey'];
+ if(isset($taxonArr['formattedClassification'])) $baseArr['formattedClassification'] = $taxonArr['formattedClassification'];
+ $tid = $this->addColTaxonByResult($baseArr);
+ }
+ else{
+ $this->logOrEcho('Targeted taxon return does not exist(2)',2);
+ }
+ }
+ else{
+ $this->logOrEcho('ERROR harvesting COL name: null input identifier',1);
+ }
+ return $tid;
}
private function translateColNode($nodeArr){
+ //Translates COL output from v1 (webservices) or v2 (api) to a Symbiota taxon object
$taxonArr = array();
if(isset($nodeArr['id'])) $taxonArr['id'] = $nodeArr['id'];
if(isset($nodeArr['name'])) $taxonArr['sciname'] = $nodeArr['name'];
+ elseif(isset($nodeArr['name']['scientificName'])) $taxonArr['sciname'] = $nodeArr['name']['scientificName'];
if(isset($nodeArr['rank'])) $taxonArr['taxonRank'] = $nodeArr['rank'];
+ elseif(isset($nodeArr['name']['rank'])) $taxonArr['taxonRank'] = $nodeArr['name']['rank'];
if(isset($nodeArr['genus'])) $taxonArr['unitname1'] = $nodeArr['genus'];
+ elseif(isset($nodeArr['name']['genus'])) $taxonArr['unitname1'] = $nodeArr['name']['genus'];
+ elseif(isset($nodeArr['name']['uninomial'])) $taxonArr['unitname1'] = $nodeArr['name']['uninomial'];
if(isset($nodeArr['species'])) $taxonArr['unitname2'] = $nodeArr['species'];
+ elseif(isset($nodeArr['name']['specificEpithet'])) $taxonArr['unitname2'] = $nodeArr['name']['specificEpithet'];
if(isset($nodeArr['infraspecies'])) $taxonArr['unitname3'] = $nodeArr['infraspecies'];
+ elseif(isset($nodeArr['name']['infraSpecificEpithet'])) $taxonArr['unitname3'] = $nodeArr['name']['infraSpecificEpithet'];
if(isset($nodeArr['infraspeciesMarker'])){
$taxonArr['unitind3'] = $nodeArr['infraspeciesMarker'];
$taxonArr['sciname'] = trim($taxonArr['unitname1'].' '.$taxonArr['unitname2'].($taxonArr['unitind3']?' '.$taxonArr['unitind3']:'').' '.$taxonArr['unitname3']);
}
if(isset($nodeArr['author'])) $taxonArr['author'] = $nodeArr['author'];
+ elseif(isset($nodeArr['name']['authorship'])) $taxonArr['author'] = $nodeArr['name']['authorship'];
if(isset($nodeArr['source_database'])) $taxonArr['source'] = $nodeArr['source_database'];
- if(isset($nodeArr['source_database_url'])) $taxonArr['sourceURL'] = $nodeArr['source_database_url'];
+ elseif(isset($nodeArr['datasetKey'])) $taxonArr['source'] = 'https://www.catalogueoflife.org/data/dataset/'.$nodeArr['datasetKey'].' ';
+ if(isset($nodeArr['online_resource'])) $taxonArr['sourceURL'] = $nodeArr['online_resource'];
+ elseif(isset($nodeArr['link'])) $taxonArr['sourceURL'] = $nodeArr['link'];
+ if(isset($nodeArr['url'])) $taxonArr['resourceURL'] = $nodeArr['url'];
$rankID = $this->getRankIdByTaxonArr($taxonArr);
if($rankID){
$taxonArr['rankid'] = $rankID;
+ if($rankID > 190){
+ if(preg_match('/^([A-Z]{1}[a-z]+)\s{1}\(\D+\)\s{1}(.*)/', $taxonArr['sciname'], $m)){
+ $taxonArr['sciname'] = $m[1].' '.$m[2];
+ }
+ }
if(!isset($taxonArr['unitname1'])) $taxonArr = array_merge(TaxonomyUtilities::parseScientificName($taxonArr['sciname'],$this->conn,$taxonArr['rankid'],$this->kingdomName),$taxonArr);
}
//$this->buildTaxonArr($taxonArr);
return $taxonArr;
}
- private function translateColApiNode($nodeArr){
- $taxonArr = array();
- if(isset($nodeArr['id'])) $taxonArr['id'] = $nodeArr['id'];
- if(isset($nodeArr['name']['scientificName'])) $taxonArr['sciname'] = $nodeArr['name']['scientificName'];
- if(isset($nodeArr['name']['rank'])) $taxonArr['taxonRank'] = $nodeArr['name']['rank'];
- if(isset($nodeArr['name']['genus'])) $taxonArr['unitname1'] = $nodeArr['name']['genus'];
- elseif(isset($nodeArr['name']['uninomial'])) $taxonArr['unitname1'] = $nodeArr['name']['uninomial'];
- if(isset($nodeArr['name']['specificEpithet'])) $taxonArr['unitname2'] = $nodeArr['name']['specificEpithet'];
- if(isset($nodeArr['name']['infraSpecificEpithet'])) $taxonArr['unitname3'] = $nodeArr['name']['infraSpecificEpithet'];
- if(isset($nodeArr['name']['authorship'])) $taxonArr['author'] = $nodeArr['name']['authorship'];
- if(isset($nodeArr['datasetKey'])) $taxonArr['source'] = 'https://www.catalogueoflife.org/data/dataset/'.$nodeArr['datasetKey'].' ';
- if(isset($nodeArr['link'])) $taxonArr['sourceURL'] = $nodeArr['link'];
- $rankID = $this->getRankIdByTaxonArr($taxonArr);
- if($rankID) $taxonArr['rankid'] = $rankID;
- if(isset($taxonArr['unitname3']) && $taxonArr['unitname3'] && ($this->kingdomName == 'Plantae' || $this->kingdomName == 'Fungi')){
- if($taxonArr['rankid'] == 230) $taxonArr['unitind3'] = 'subsp.';
- if($taxonArr['rankid'] == 240) $taxonArr['unitind3'] = 'var.';
- if($taxonArr['rankid'] == 260) $taxonArr['unitind3'] = 'f.';
- }
- return $taxonArr;
- }
-
private function setColClassification(&$tArr, $subjectTaxonArr){
if(isset($tArr['formattedClassification'])) return true;
$classificationArr = array();
@@ -363,7 +379,7 @@ private function setColClassification(&$tArr, $subjectTaxonArr){
$resultArr = json_decode($content,true);
if(isset($resultArr['total']) && $resultArr['total']){
foreach($resultArr['result'] as $k => $rArr){
- if($rArr['id'] == $tArr['id'] && isset($rArr['classification'])){
+ if(isset($rArr['id']) && $rArr['id'] == $tArr['id'] && isset($rArr['classification'])){
$activeClassArr = $rArr['classification'];
if(!isset($tArr['datasetKey']) || (isset($rArr['usage']['datasetKey']) && $rArr['usage']['datasetKey'] == $tArr['datasetKey'] )) break;
}
@@ -397,6 +413,9 @@ private function setColClassification(&$tArr, $subjectTaxonArr){
}
krsort($classificationArr);
}
+ if(isset($classificationArr[190]['sciname']) && !strpos($classificationArr[190]['sciname'], ' (')){
+ if(isset($classificationArr[180])) $classificationArr[190]['sciname'] = $classificationArr[180]['sciname'].' ('.$classificationArr[190]['sciname'].')';
+ }
if($classificationArr) $tArr['formattedClassification'] = $classificationArr;
}
@@ -515,7 +534,7 @@ private function addColChildern($id, $datasetKey, $nodeSciname, $parentTid, $ran
$this->logOrEcho($nodeArr['labelHtml'].' ('.$nodeArr['status'].') skipped due to extinct status',2);
continue;
}
- $taxonArr = $this->translateColApiNode($nodeArr);
+ $taxonArr = $this->translateColNode($nodeArr);
$tid = $this->getTid($taxonArr);
if($tid){
$display = ''.$nodeArr['labelHtml'].' ';
@@ -1150,9 +1169,9 @@ private function loadNewTaxon($taxonArr, $tidAccepted = 0){
}
if($loadTaxon){
if(!$newTid){
- if(isset($taxonArr['source']) && strlen($taxonArr['source']) > $this->taxaFieldArr['source']['size']){
- $taxonArr['source'] = substr($taxonArr['source'],0,$this->taxaFieldArr['source']['size']);
- }
+ if(isset($taxonArr['source']) && strlen($taxonArr['source']) > $this->taxaFieldArr['source']['size']){
+ $taxonArr['source'] = substr($taxonArr['source'],0,$this->taxaFieldArr['source']['size']);
+ }
$sqlInsert = 'INSERT INTO taxa(sciname, unitind1, unitname1, unitind2, unitname2, unitind3, unitname3, author, rankid, source, modifiedUid) '.
'VALUES("'.$this->cleanInStr($taxonArr['sciname']).'",'.
(isset($taxonArr['unitind1']) && $taxonArr['unitind1']?'"'.$this->cleanInStr($taxonArr['unitind1']).'"':'NULL').',"'.
@@ -1232,6 +1251,15 @@ private function loadNewTaxon($taxonArr, $tidAccepted = 0){
}
$this->logOrEcho('Taxon '.$taxonDisplay.' added to thesaurus as '.$accStr,2);
}
+ //Load taxonomic resources identifiers
+ if(isset($taxonArr['resourceURL'])){
+ $this->insertTaxonomicResource($newTid, 'Catalog of Life', $taxonArr['id'], $taxonArr['resourceURL']);
+ }
+ if(isset($taxonArr['sourceURL'])){
+ if(preg_match('/molluscabase.+\D+(\d+)$/', $taxonArr['sourceURL'], $m)){
+ $this->insertTaxonomicResource($newTid, 'MolluscaBase', $m[1], $taxonArr['sourceURL']);
+ }
+ }
}
}
//Add Synonyms
@@ -1361,6 +1389,15 @@ private function getParentArr($taxonArr){
return $parArr;
}
+ private function insertTaxonomicResource($tid, $sourceName, $sourceIdentifier, $sourceUrl){
+ $sql = 'INSERT INTO taxaresourcelinks(tid, sourceName, sourceIdentifier, url) VALUES(?, ?, ?, ?)';
+ if($stmt = $this->conn->prepare($sql)){
+ $stmt->bind_param('isss', $tid, $sourceName, $sourceIdentifier, $sourceUrl);
+ $stmt->execute();
+ $stmt->close();
+ }
+ }
+
//Misc functions
public function buildTaxonArr(&$taxonArr){
if(is_array($taxonArr)){
diff --git a/classes/TaxonomyUpload.php b/classes/TaxonomyUpload.php
index bd20749c46..408831a8d5 100644
--- a/classes/TaxonomyUpload.php
+++ b/classes/TaxonomyUpload.php
@@ -2,6 +2,7 @@
include_once($SERVER_ROOT.'/config/dbconnection.php');
include_once($SERVER_ROOT.'/classes/TaxonomyUtilities.php');
include_once($SERVER_ROOT.'/classes/TaxonomyHarvester.php');
+include_once($SERVER_ROOT.'/classes/OccurrenceMaintenance.php');
class TaxonomyUpload{
@@ -810,21 +811,10 @@ public function transferUpload(){
TaxonomyUtilities::buildHierarchyEnumTree($this->conn, $this->taxAuthId);
//Update occurrences with new tids
- TaxonomyUtilities::linkOccurrenceTaxa($this->conn);
-
- //Update occurrence images with new tids
- $sql2 = 'UPDATE images i INNER JOIN omoccurrences o ON i.occid = o.occid '.
- 'SET i.tid = o.TidInterpreted '.
- 'WHERE (i.tid IS NULL) AND (o.TidInterpreted IS NOT NULL)';
- $this->conn->query($sql2);
-
- //Update geo lookup table
- $sql3 = 'INSERT IGNORE INTO omoccurgeoindex(tid,decimallatitude,decimallongitude) '.
- 'SELECT DISTINCT o.tidinterpreted, round(o.decimallatitude,2), round(o.decimallongitude,2) '.
- 'FROM omoccurrences o '.
- 'WHERE (o.tidinterpreted IS NOT NULL) AND (o.decimallatitude between -90 and 90) AND (o.decimallongitude between -180 and 180) '.
- 'AND (o.cultivationStatus IS NULL OR o.cultivationStatus = 0) AND (o.coordinateUncertaintyInMeters IS NULL OR o.coordinateUncertaintyInMeters < 10000) ';
- $this->conn->query($sql3);
+ $occurMaintenance = new OccurrenceMaintenance($this->conn);
+ $occurMaintenance->setCollidStr($this->collid);
+ $occurMaintenance->generalOccurrenceCleaning();
+ $occurMaintenance->batchUpdateGeoreferenceIndex();
}
private function transferVernaculars($secondRound = 0){
diff --git a/classes/TaxonomyUtilities.php b/classes/TaxonomyUtilities.php
index 16e9664a73..10f979ee57 100644
--- a/classes/TaxonomyUtilities.php
+++ b/classes/TaxonomyUtilities.php
@@ -339,28 +339,5 @@ private static function loadTaxonIntoNestedTree($conn, $tid, $taxAuthId, $startI
return $endIndex;
}
*/
-
- public static function linkOccurrenceTaxa($conn = null){
- if(!$conn) $conn = MySQLiConnectionFactory::getCon('write');
-
- $sql1 = 'UPDATE omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname AND o.scientificnameauthorship = t.author SET o.TidInterpreted = t.tid WHERE (o.TidInterpreted IS NULL)';
- if(!$conn->query($sql1)){
- echo 'ERROR indexing occurrences by matching sciname and author
';
- }
-
- $sql2 = 'UPDATE omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname '.
- 'INNER JOIN taxaenumtree e ON t.tid = e.tid '.
- 'INNER JOIN taxa t2 ON e.parenttid = t2.tid '.
- 'SET o.TidInterpreted = t.tid '.
- 'WHERE (o.TidInterpreted IS NULL) AND (t2.rankid = 140) AND (t.sciname = o.family)';
- if(!$conn->query($sql2)){
- echo 'ERROR indexing occurrences by matching sciname and family
';
- }
-
- $sql3 = 'UPDATE omoccurrences o INNER JOIN taxa t ON o.sciname = t.sciname SET o.TidInterpreted = t.tid WHERE (o.TidInterpreted IS NULL)';
- if(!$conn->query($sql3)){
- echo 'ERROR indexing occurrences by matching just sciname
';
- }
- }
}
?>
\ No newline at end of file
diff --git a/collections/download/index.php b/collections/download/index.php
index 6863cb1831..8b98704769 100644
--- a/collections/download/index.php
+++ b/collections/download/index.php
@@ -195,6 +195,9 @@ function closePage(timeToClose){
Download Data
+
+ * There is a 1,000,000 record limit to occurrence downloads
+
diff --git a/collections/specprocessor/rpc/coge_build_dwca.php b/collections/specprocessor/rpc/coge_build_dwca.php
index b2f1d23ecd..92a903f0ac 100644
--- a/collections/specprocessor/rpc/coge_build_dwca.php
+++ b/collections/specprocessor/rpc/coge_build_dwca.php
@@ -46,7 +46,7 @@
if(substr($tPath,-1) != '/' && substr($tPath,-1) != '\\'){
$tPath .= '/';
}
- $pathFrag = 'temp/data/geolocate/';
+ $pathFrag = 'temp/data/';
$tPath .= $pathFrag;
$dwcaHandler->setTargetPath($tPath);
$cnt = $dwcaHandler->getOccurrenceCnt();
diff --git a/config/symbbase.php b/config/symbbase.php
index f1e1b3fdc5..1e2079a44a 100644
--- a/config/symbbase.php
+++ b/config/symbbase.php
@@ -2,7 +2,7 @@
header('X-Frame-Options: DENY');
header('Cache-control: private'); // IE 6 FIX
date_default_timezone_set('America/Phoenix');
-$CODE_VERSION = '3.0.5';
+$CODE_VERSION = '3.0.7';
if(!isset($CLIENT_ROOT) && isset($clientRoot)) $CLIENT_ROOT = $clientRoot;
if(substr($CLIENT_ROOT,-1) == '/') $CLIENT_ROOT = substr($CLIENT_ROOT,0,strlen($CLIENT_ROOT)-1);
diff --git a/taxa/resourcetab.php b/taxa/resourcetab.php
index af81f764a6..3c600be3fe 100644
--- a/taxa/resourcetab.php
+++ b/taxa/resourcetab.php
@@ -24,6 +24,7 @@
?>
';
echo '
'.(isset($LANG['INTERNAL_RESOURCES'])?$LANG['INTERNAL_RESOURCES']:'Internal Resources').'
';
echo '
';
$occNum = $taxonManager->getOccTaxonInDbCnt();
@@ -37,9 +38,11 @@
}
echo 'Taxonomic Tree ';
echo ' ';
+ echo '
';
//TODO: list other internal resources such as Taxon Traits, etc
if($linkArr = $taxonManager->getLinkArr()){
+ echo '';
echo '
'.(isset($LANG['EXTERNAL_RESOURCES'])?$LANG['EXTERNAL_RESOURCES']:'External Resources').'
';
echo '
';
foreach($linkArr as $linkObj){
@@ -47,6 +50,18 @@
if($linkObj['notes']) echo ''.$linkObj['notes'].' ';
}
echo ' ';
+ echo '
';
+ }
+ if($resourceArr = $taxonManager->getResourceLinkArr()){
+ echo '';
+ echo '
'.(isset($LANG['TAXONOMIC_RESOURCES'])?$LANG['TAXONOMIC_RESOURCES']:'Taxonomic Resources').'
';
+ echo '
';
+ echo '
';
}
?>
\ No newline at end of file