diff --git a/classes/AssociationManager.php b/classes/AssociationManager.php
index 654de72287..00fd1f9e7f 100644
--- a/classes/AssociationManager.php
+++ b/classes/AssociationManager.php
@@ -1,5 +1,7 @@
isEditor = true;
@@ -44,35 +47,122 @@ public function getRelationshipTypes(){
}
}
- public function getAssociatedRecords($associationArr){
- $sql='';
-
- if(array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'none'){
- $familyJoinStr = '';
- $shouldUseFamily = array_key_exists('associated-taxa', $associationArr) && $associationArr['associated-taxa'] == '3';
- if($shouldUseFamily) $familyJoinStr = 'LEFT JOIN taxstatus ts ON o.tidinterpreted = ts.tid';
-
-
- // "Forward" association
- $relationshipType = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? $associationArr['relationship'] : 'IS NOT NULL';
- $relationshipStr = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? ("='" . $relationshipType . "'") : (' IS NOT NULL');
- // $sql .= "AND (o.occid IN (SELECT DISTINCT o.occid FROM omoccurrences o INNER JOIN omoccurassociations oa on o.occid=oa.occid WHERE oa.relationship" . $relationshipStr . " ";
- $sql .= "AND (o.occid IN (SELECT DISTINCT o.occid FROM omoccurrences o INNER JOIN omoccurassociations oa on o.occid=oa.occid " . $familyJoinStr . " WHERE oa.relationship" . $relationshipStr . " ";
- $sql .= $this->getAssociatedTaxonWhereFrag($associationArr) . ')';
-
- // @TODO handle situation where the associationType is external and there's no occidAssociate; pull resourceUrl instead?
- //something like:
- // $sql =. 'SELECT DISTINCT resourceUrl from omoccurassociations WHERE associationType="externalOccurrence" AND occidAssociate IS NULL AND relationship = ' . $relationshipType . ' AND ';
-
- // "Reverse" association
- $reverseAssociationType = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? $this->getInverseRelationshipOf($relationshipType) : 'IS NOT NULL';
- $reverseRelationshipStr = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? ("='" . $reverseAssociationType . "'") : (' IS NOT NULL');
- $sql .= " OR o.occid IN (SELECT DISTINCT oa.occidAssociate FROM omoccurrences o INNER JOIN omoccurassociations oa on o.occid=oa.occid INNER JOIN omoccurdeterminations od ON oa.occid=od.occid " . $familyJoinStr . " where oa.relationship " . $reverseRelationshipStr . " "; //isCurrent="1" AND my thought was that we want these results to be as relaxed as possible
- $sql .= $this->getAssociatedTaxonWhereFrag($associationArr) . ')';
+ public function establishInverseRelationshipRecords(){
+ $sql = "SELECT * FROM omoccurassociations where occid IS NOT NULL AND occidAssociate IS NOT NULL;";
+ if($statement = $this->conn->prepare($sql)){
+ $statement->execute();
+ $result = $statement->get_result();
+ while ($row = $result->fetch_assoc()) {
+ // $returnVal = $row['inverseRelationship'];
+ if(!$this->hasInverseRecord($row)){
+ $this->createInverseRecord($row);
+ }
+ // if that record has an inverse present, do nothing
+ // else, create an inverse record
+ }
+ $statement->close();
+ // return $returnVal;
+ }else{
+ return '';
+ }
+ }
+
+ private function hasInverseRecord($record){
+ // var_dump($record);
+ $sql = "SELECT * FROM omoccurassociations WHERE occidAssociate = ? AND occid = ? and relationship = ?;";
+ $recordOccid = array_key_exists('occid', $record) ? $record['occid'] : '';
+ $recordOccidAssociate = array_key_exists('occidAssociate', $record) ? $record['occidAssociate'] : '';
+ $relationship = array_key_exists('relationship', $record) ? $record['relationship'] : '';
+ $inverseRelationship = $this->getInverseRelationshipOf($relationship);
+ if($statement = $this->conn->prepare($sql)){
+ $statement->bind_param('iis', $recordOccid, $recordOccidAssociate, $inverseRelationship);
+ $statement->execute();
+ $result = $statement->get_result();
+ $returnVal = false;
+ if ($row = $result->fetch_assoc()) {
+ // $returnVal = $row['inverseRelationship'];
+ $returnVal = true;
+ }
+ $statement->close();
+ return $returnVal;
+ }else{
+ return '';
+ }
+ }
+ public function createInverseRecord($record){
+ $recordOccid = array_key_exists('occid', $record) ? $record['occid'] : '';
+ $recordOccidAssociate = array_key_exists('occidAssociate', $record) ? $record['occidAssociate'] : '';
+ $relationship = array_key_exists('relationship', $record) ? $record['relationship'] : '';
+ $inverseRelationship = $this->getInverseRelationshipOf($relationship);
+ $verbatimsciname = $this->getCorrespondingVerbatimsciname($recordOccid);
+ $createdUid = $GLOBALS['SYMB_UID'];
+ $basisOfRecord = 'scriptGenerated';
+ $sql = 'INSERT INTO omoccurassociations(occid, occidAssociate, relationship, basisOfRecord, createdUid, verbatimsciname)';
+ $sql .= ' VALUES(?,?,?,?,?,?);';
+ $returnVal = false;
+ // $this->resetConnection();
+ $shouldCreateInverseRecord = !empty($recordOccid) && !empty($recordOccidAssociate) && !empty($relationship) && !empty($inverseRelationship) && !empty($recordOccid);
+ if($shouldCreateInverseRecord && $statement = $this->conn->prepare($sql)){
+ $statement->bind_param('iissis', $recordOccidAssociate, $recordOccid, $inverseRelationship, $basisOfRecord, $createdUid, $verbatimsciname);
+ if($statement->execute()){
+ $returnVal = true;
+ }
+ $statement->close();
+ }
+ // $this->resetConnectionToRead();
+ return $returnVal;
+ }
+
+ private function getCorrespondingVerbatimsciname($targetOccid){
+ $sql = 'SELECT sciname from omoccurrences where occid=?';
+ $returnVal = '';
+ if($statement = $this->conn->prepare($sql)){
+ $statement->bind_param('s', $targetOccid);
+ $statement->execute();
+ $result = $statement->get_result();
+ if ($row = $result->fetch_assoc()) {
+ $returnVal = array_key_exists('sciname', $row) ? $row['sciname'] : '';
+ }
+ $statement->close();
}
- return $sql;
+ return $returnVal;
}
+ // protected function resetConnection(){
+ // $this->conn = MySQLiConnectionFactory::getCon('write');
+ // }
+
+ // protected function resetConnectionToRead(){
+ // $this->conn = MySQLiConnectionFactory::getCon('readonly');
+ // }
+
+ public function getAssociatedRecords($associationArr) {
+ $sql = '';
+
+ if (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'none') {
+ $familyJoinStr = '';
+ $shouldUseFamily = array_key_exists('associated-taxa', $associationArr) && $associationArr['associated-taxa'] == '3';
+ if ($shouldUseFamily) $familyJoinStr = 'LEFT JOIN taxstatus ts ON o.tidinterpreted = ts.tid';
+
+ // "Forward" association
+ $relationshipType = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? $associationArr['relationship'] : 'IS NOT NULL';
+ $relationshipStr = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? ("='" . $relationshipType . "'") : ' IS NOT NULL';
+
+ $forwardSql = "SELECT o.occid FROM omoccurrences o INNER JOIN omoccurassociations oa ON o.occid = oa.occid " . $familyJoinStr . " WHERE oa.relationship " . $relationshipStr . " ";
+ $forwardSql .= $this->getAssociatedTaxonWhereFrag($associationArr);
+
+ // "Reverse" association
+ $reverseAssociationType = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? $this->getInverseRelationshipOf($relationshipType) : 'IS NOT NULL';
+ $reverseRelationshipStr = (array_key_exists('relationship', $associationArr) && $associationArr['relationship'] !== 'any') ? ("='" . $reverseAssociationType . "'") : ' IS NOT NULL';
+
+ $reverseSql = "SELECT oa.occidAssociate FROM omoccurrences o INNER JOIN omoccurassociations oa ON o.occid = oa.occid INNER JOIN omoccurdeterminations od ON oa.occid = od.occid " . $familyJoinStr . " WHERE oa.relationship " . $reverseRelationshipStr . " ";
+ $reverseSql .= $this->getAssociatedTaxonWhereFrag($associationArr);
+
+ $sql .= "AND (o.occid IN (SELECT occid FROM ( " . $forwardSql . " UNION " . $reverseSql . " ) AS occids)";
+ }
+ return $sql;
+}
+
public function getAssociatedTaxonWhereFrag($associationArr){
$sqlWhereTaxa = '';
if(isset($associationArr['taxa'])){
@@ -122,21 +212,21 @@ public function getAssociatedTaxonWhereFrag($associationArr){
//Return matches that are not linked to thesaurus
if($rankid > 179){
if($this->exactMatchOnly) $sqlWhereTaxa .= 'OR (o.sciname = "' . $term . '") ';
- else $sqlWhereTaxa .= "OR (o.sciname LIKE '" . $term . "%') ";
+ else $sqlWhereTaxa .= "OR (o.sciname LIKE '" . $term . "%') OR (oa.verbatimsciname LIKE '" . $term . "%') ";
}
}
else{
//Protect against someone trying to download big pieces of the occurrence table through the user interface
if(strlen($term) < 4) $term .= ' ';
if($this->exactMatchOnly){
- $sqlWhereTaxa .= 'OR (o.sciname = "' . $term . '") ';
+ $sqlWhereTaxa .= 'OR (o.sciname = "' . $term . '") OR (oa.verbatimsciname LIKE "' . $term . '%") ';
}
else{
- $sqlWhereTaxa .= 'OR (o.sciname LIKE "' . $term . '%") ';
+ $sqlWhereTaxa .= 'OR (o.sciname LIKE "' . $term . '%") OR (oa.verbatimsciname LIKE "' . $term . '%") ';
if(!strpos($term,' _ ')){
//Accommodate for formats of hybrid designations within input and target data (e.g. x, multiplication sign, etc)
$term2 = preg_replace('/^([^\s]+\s{1})/', '$1 _ ', $term);
- $sqlWhereTaxa .= "OR (o.sciname LIKE '" . $term2 . "%') ";
+ $sqlWhereTaxa .= "OR (o.sciname LIKE '" . $term2 . "%') OR (oa.verbatimsciname LIKE '" . $term . "%') ";
}
}
}
diff --git a/classes/OccurrenceListManager.php b/classes/OccurrenceListManager.php
index 687e794b6f..89b0f13d28 100644
--- a/classes/OccurrenceListManager.php
+++ b/classes/OccurrenceListManager.php
@@ -40,7 +40,7 @@ public function getSpecimenMap($pageRequest,$cntPerPage){
$pageRequest = ($pageRequest - 1)*$cntPerPage;
}
$sql .= ' LIMIT ' . $pageRequest . ',' . $cntPerPage;
- // echo '
Spec sql: ' . $sql . '
'; exit;
+ // echo 'Spec sql: ' . $sql . '
'; exit; // @TODO HERE
$result = $this->conn->query($sql);
if($result){
$securityCollArr = array();
@@ -125,7 +125,7 @@ private function setImages($occArr,&$retArr){
private function setRecordCnt($sqlWhere){
if($sqlWhere){
$sql = "SELECT COUNT(DISTINCT o.occid) AS cnt FROM omoccurrences o ".$this->getTableJoins($sqlWhere).$sqlWhere;
- // echo "Count sql: ".$sql."
";
+ // echo "Count sql: ".$sql."
"; exit;
$result = $this->conn->query($sql);
if($result){
if($row = $result->fetch_object()){
diff --git a/classes/OccurrenceManager.php b/classes/OccurrenceManager.php
index 6a3ef03dc4..8635345ad0 100644
--- a/classes/OccurrenceManager.php
+++ b/classes/OccurrenceManager.php
@@ -21,6 +21,7 @@ class OccurrenceManager extends OccurrenceTaxaManager {
public function __construct($type='readonly'){
parent::__construct($type);
if(array_key_exists('reset',$_REQUEST) && $_REQUEST['reset']) $this->reset();
+ $this->associationManager = new AssociationManager();
$this->readRequestVariables();
$langTag = '';
if(!empty($GLOBALS['LANG_TAG'])) $langTag = $GLOBALS['LANG_TAG'];
@@ -28,7 +29,6 @@ public function __construct($type='readonly'){
include_once($GLOBALS['SERVER_ROOT'] . '/content/lang/classes/OccurrenceManager.' . $langTag . '.php');
else include_once($GLOBALS['SERVER_ROOT'] . '/content/lang/classes/OccurrenceManager.en.php');
$this->LANG = $LANG;
- $this->associationManager = new AssociationManager();
}
public function __destruct(){
@@ -60,15 +60,11 @@ public function getSqlWhere(){
protected function setSqlWhere(){
$sqlWhere = '';
- // var_dump($this->searchTermArr);
- // $deleteMe = $this->associationManager->getAssociatedTaxonWhereFrag($this->associationArr);
- // var_dump($deleteMe);
if(array_key_exists("targetclid",$this->searchTermArr) && is_numeric($this->searchTermArr["targetclid"])){
if(!$this->voucherManager){
$this->setChecklistVariables($this->searchTermArr['targetclid']);
}
$voucherVariableArr = $this->voucherManager->getQueryVariableArr();
- // var_dump($voucherVariableArr);
if($voucherVariableArr){
if(isset($voucherVariableArr['association-type'])) $this->searchTermArr['association-type'] = $voucherVariableArr['association-type'];
if(isset($voucherVariableArr['taxontype-association'])) $this->searchTermArr['taxontype-association'] = $voucherVariableArr['taxontype-association'];
@@ -129,11 +125,8 @@ protected function setSqlWhere(){
$this->displaySearchArr[] = $this->LANG['DATASETS'] . ': ' . $this->getDatasetTitle($this->searchTermArr['datasetid']);
}
$sqlWhere .= $this->getTaxonWhereFrag();
- // echo "this dot getTaxonWhereFrag() is: " . $this->getTaxonWhereFrag() . "
";
- // echo "sqlWhere before getting the association taxa is: " . $sqlWhere . "
";
$hasValidRelationship = isset(($this->associationArr['relationship'])) && $this->associationArr['relationship']!=='none';
- // $hasValidAssociatedTaxon = isset($this->associationArr['search']);
- if($hasValidRelationship){ // || $hasValidAssociatedTaxon // @TODO
+ if($hasValidRelationship){
$sqlWhere = substr_replace($sqlWhere,'',-1);
$sqlWhere .= $this->associationManager->getAssociatedRecords($this->associationArr) . ')';
}
@@ -547,7 +540,6 @@ protected function getTableJoins($sqlWhere){
$sqlJoin .= 'INNER JOIN taxaenumtree e ON o.tidinterpreted = e.tid ';
}
if(strpos($sqlWhere,'ts.family')){
- echo 'ts.family entered';
$sqlJoin .= 'LEFT JOIN taxstatus ts ON o.tidinterpreted = ts.tid ';
}
if(strpos($sqlWhere,'ds.datasetid')){
@@ -668,7 +660,6 @@ public function getQueryTermStr(){
$retStr .= '&taxontype=1';
}
}
- // var_dump($this->associationArr);
$patternOfOnlyLettersDigitsAndSpaces = '/^[a-zA-Z0-9\s\-]*$/'; // TOOD accommodate symbols associated with extinct taxa, hybrid crosses, and abbreviations with periods, e.g. "var."?
if(isset($this->associationArr['search'])){
if (preg_match($patternOfOnlyLettersDigitsAndSpaces, $this->associationArr['search'])==1) {
@@ -715,11 +706,9 @@ private function getDatasetTitle($dsIdStr){
}
protected function readRequestVariables(){
- // var_dump($_REQUEST); // @TODO this is an intervention point
if(array_key_exists('searchvar',$_REQUEST)){
$parsedArr = array();
$taxaArr = array();
- // parse_str($_REQUEST['searchvar'], $parsedArr);
$searchVar = str_replace('&', '&', $_REQUEST['searchvar']);
parse_str($searchVar, $parsedArr);
@@ -735,7 +724,6 @@ protected function readRequestVariables(){
unset($parsedArr['taxontype']);
}
$this->setTaxonRequestVariable($taxaArr);
- // $this->setAssociationRequestVariable();
}
foreach($parsedArr as $k => $v){
$k = $this->cleanInputStr($k);
@@ -776,7 +764,6 @@ protected function readRequestVariables(){
if($hasEverythingRequiredForAssociationSearch){
$this->setAssociationRequestVariable();
}
- // var_dump($this->searchTermArr);
if(array_key_exists('country',$_REQUEST)){
$country = $this->cleanInputStr($_REQUEST['country']);
if($country){
@@ -1010,7 +997,6 @@ protected function readRequestVariables(){
$this->searchTermArr['footprintwkt'] = $this->cleanInputStr($_REQUEST['footprintwkt']);
}
- // var_dump($this->searchTermArr);
}
private function setChecklistVariables($clid){
diff --git a/classes/OccurrenceTaxaManager.php b/classes/OccurrenceTaxaManager.php
index 11ad552e6a..bab1d9ae2e 100644
--- a/classes/OccurrenceTaxaManager.php
+++ b/classes/OccurrenceTaxaManager.php
@@ -60,8 +60,6 @@ public function setAssociationRequestVariable($inputArr = null, $exactMatchOnly
$this->associationArr['relationship'] = $associationTypeStr;
}
- // $taxonTypeAssociationStr = $this->cleanAndAssignGeneric('taxontype-association', $inputArr);
-
if($associatedTaxonStr){
$this->associationArr['search'] = $associatedTaxonStr;
$this->setAssociationUseThes($inputArr, 'usethes-associations');
@@ -82,14 +80,10 @@ public function setAssociationRequestVariable($inputArr = null, $exactMatchOnly
}
- // @TODO $taxonType2Str
- // var_dump($this->associationArr['taxa']);
-
- // LEFT OFF HERE figuring out the remaining TODOs here and testing it out
}
protected function processSingleTerm($searchTerm, $searchTermkey, $defaultTaxaType){
- $this->associationTaxaSearchTerms[$searchTermkey] = $searchTerm; // @TODO generalize
+ $this->associationTaxaSearchTerms[$searchTermkey] = $searchTerm;
$taxaType = $defaultTaxaType;
if($defaultTaxaType == TaxaSearchType::ANY_NAME) {
$searchTermName = explode(': ',$searchTerm);
@@ -100,7 +94,7 @@ protected function processSingleTerm($searchTerm, $searchTermkey, $defaultTaxaTy
$taxaType = TaxaSearchType::SCIENTIFIC_NAME;
}
}
- $this->setSciNamesByVerns($searchTerm, $this->associationArr); // @TODO test whether this works
+ $this->setSciNamesByVerns($searchTerm, $this->associationArr);
$this->setTaxonRankAndType($searchTerm, $taxaType, 'usethes-associations');
}
@@ -123,7 +117,7 @@ protected function setTaxonRankAndType($searchTerm, $taxaType, $useThesId='useth
if($this->associationArr[$useThesId]){
$sql .= 'INNER JOIN taxstatus ts ON t.tid = ts.tidaccepted
INNER JOIN taxa t2 ON ts.tid = t2.tid
- WHERE (ts.taxauthid = ?) AND (t2.sciname IN(?))'; // @TODO does this work?
+ WHERE (ts.taxauthid = ?) AND (t2.sciname IN(?))';
$typeStr .= 'is';
array_push($bindingArr, $this->taxAuthId, $this->cleanInStr($searchTerm));
} else{
@@ -132,10 +126,7 @@ protected function setTaxonRankAndType($searchTerm, $taxaType, $useThesId='useth
array_push($bindingArr, $this->cleanInStr($searchTerm));
}
}
- // var_dump($sql);
if ($statement = $this->conn->prepare($sql)) {
- // var_dump($typeStr);
- // var_dump(...$bindingArr);
$statement->bind_param($typeStr,...$bindingArr);
$statement->execute();
$result = $statement->get_result();
@@ -162,7 +153,7 @@ protected function setTaxonRankAndType($searchTerm, $taxaType, $useThesId='useth
protected function setAssociationSynonyms(){
if(isset($this->associationArr['taxa'])){
- foreach($this->associationArr['taxa'] as $searchStr => $searchArr){ // @TODO LEFT OFF HERE
+ foreach($this->associationArr['taxa'] as $searchStr => $searchArr){
if(isset($searchArr['tid']) && $searchArr['tid']){
foreach($searchArr['tid'] as $tid => $rankid){
$accArr = array();
@@ -195,7 +186,7 @@ protected function addAcceptedChildrenToArray($tid, $rankid, $accArr, $searchStr
$accArr[] = $r1['tid'];
if(!isset($this->associationArr['taxa'][$r1['sciname']])){
if($rankid == 220) $this->associationArr['taxa'][$r1['sciname']]['tid'][$r1['tid']] = $r1['rankid'];
- else $this->associationArr['taxa'][$searchStr]['TID_BATCH'][$r1['tid']] = ''; // @TODO generalize and use in setSynonyms as well to DRY up code
+ else $this->associationArr['taxa'][$searchStr]['TID_BATCH'][$r1['tid']] = '';
}
}
}
@@ -218,7 +209,7 @@ protected function addSynonymsOfAcceptedTaxaToArray($accArr, $rankid, $searchStr
$result = $statement2->get_result();
if($result->num_rows > 0){
while($r2 = $result->fetch_assoc()){
- if($rankid >= 220) $this->associationArr['taxa'][$r2['accepted']]['synonyms'][$r2['tid']] = $r2['sciname']; // @TODO generalize and use in setSynonyms as well to DRY up code
+ if($rankid >= 220) $this->associationArr['taxa'][$r2['accepted']]['synonyms'][$r2['tid']] = $r2['sciname'];
else $this->associationArr['taxa'][$searchStr]['TID_BATCH'][$r2['tid']] = '';
}
}
@@ -227,7 +218,7 @@ protected function addSynonymsOfAcceptedTaxaToArray($accArr, $rankid, $searchStr
}
protected function setAssociationUseThes($inputArr = null, $useThesId='usethes'){
- $this->associationArr[$useThesId] = 0; // @TODO generalize and use in setTaxonRequestVariable as well to DRY up code
+ $this->associationArr[$useThesId] = 0;
if(isset($inputArr[$useThesId]) && $inputArr[$useThesId]){
$this->associationArr[$useThesId] = 1;
}
@@ -236,7 +227,7 @@ protected function setAssociationUseThes($inputArr = null, $useThesId='usethes')
}
}
- protected function setAndGetAssociationDefaultTaxaType($inputArr = null){ // @TOD generalize this work with setTaxonRequestVariable as well
+ protected function setAndGetAssociationDefaultTaxaType($inputArr = null){
$defaultTaxaType = TaxaSearchType::SCIENTIFIC_NAME;
if(isset($inputArr['associated-taxa']) && is_numeric($inputArr['associated-taxa'])){
$defaultTaxaType = $inputArr['associated-taxa'];
@@ -375,20 +366,20 @@ private function setSciNamesByVerns(&$searchTerm, &$alternateTaxaArr = null) {
while($row = $result->fetch_object()){
$vernName = $row->VernacularName;
if($row->rankid == 140){
- if(array_key_exists('taxa', $alternateTaxaArr)){
- $alternateTaxaArr['taxa'][$vernName]['families'][] = $row->sciname; // @TODO check that these values update correctly
+ if(is_array($alternateTaxaArr) && array_key_exists('taxa', $alternateTaxaArr)){
+ $alternateTaxaArr['taxa'][$vernName]['families'][] = $row->sciname;
} else{
$this->taxaArr['taxa'][$vernName]['families'][] = $row->sciname;
}
}
else{
- if(array_key_exists('taxa', $alternateTaxaArr)){
+ if(is_array($alternateTaxaArr) && array_key_exists('taxa', $alternateTaxaArr)){
$alternateTaxaArr['taxa'][$vernName]['scinames'][] = $row->sciname;
}else{
$this->taxaArr['taxa'][$vernName]['scinames'][] = $row->sciname;
}
}
- if(array_key_exists('taxa', $alternateTaxaArr)){
+ if(is_array($alternateTaxaArr) && array_key_exists('taxa', $alternateTaxaArr)){
$alternateTaxaArr['taxa'][$vernName]['tid'][$row->tid] = $row->rankid;
}else{
$this->taxaArr['taxa'][$vernName]['tid'][$row->tid] = $row->rankid;
@@ -446,120 +437,9 @@ private function setSynonyms(){
}
}
- // public function getAssociatedTaxonWhereFrag(){
- // $sqlWhereTaxa = '';
- // if(isset($this->associationArr['taxa'])){
- // // var_dump($this->associationArr);
- // $tidInArr = array();
- // $taxonType = $this->associationArr['associated-taxa'];
- // foreach($this->associationArr['taxa'] as $searchTaxon => $searchArr){
- // if(isset($searchArr['taxontype'])) $taxonType = $searchArr['taxontype'];
- // if($taxonType == TaxaSearchType::TAXONOMIC_GROUP){
- // //Class, order, or other higher rank
- // if(isset($searchArr['tid'])){
- // $tidArr = array_keys($searchArr['tid']);
- // //$sqlWhereTaxa .= 'OR (o.tidinterpreted IN(SELECT DISTINCT tid FROM taxaenumtree WHERE (taxauthid = '.$this->taxAuthId.') AND (parenttid IN('.trim($tidStr,',').') OR (tid = '.trim($tidStr,',').')))) ';
- // $sqlWhereTaxa .= 'OR (e.parenttid IN('.implode(',', $tidArr).') ';
- // $sqlWhereTaxa .= 'OR (e.tid IN('.implode(',', $tidArr).')) ';
- // if(isset($searchArr['synonyms'])) $sqlWhereTaxa .= 'OR (e.tid IN('.implode(',',array_keys($searchArr['synonyms'])).')) ';
- // //$tidInArr = array_merge($tidInArr,$tidArr);
- // //if(isset($searchArr['synonyms'])) $tidInArr = array_merge($tidInArr,array_keys($searchArr['synonyms']));
- // $sqlWhereTaxa .= ') ';
- // }
- // else{
- // //Unable to find higher taxon within taxonomic tree, thus return nothing
- // $sqlWhereTaxa .= 'OR (o.tidinterpreted = 0) ';
- // }
- // }
- // elseif($taxonType == TaxaSearchType::FAMILY_ONLY){
- // //$sqlWhereTaxa .= 'OR ((o.family = "'.$searchTaxon.'") OR (o.sciname = "'.$searchTaxon.'")) ';
- // //$sqlWhereTaxa .= 'OR (((ts.family = "'.$searchTaxon.'") AND (ts.taxauthid = '.$this->taxAuthId.')) OR (o.family = "'.$searchTaxon.'") OR (o.sciname = "'.$searchTaxon.'")) ';
- // //$sqlWhereTaxa .= 'OR (((ts.family = "'.$searchTaxon.'") AND (ts.taxauthid = '.$this->taxAuthId.')) OR o.sciname = "'.$searchTaxon.'") ';
- // if(isset($searchArr['tid'])){
- // $tidArr = array_keys($searchArr['tid']);
- // $sqlWhereTaxa .= 'OR ((ts.family = "'.$searchTaxon.'") OR (ts.tid IN('.implode(',', $tidArr).'))) ';
- // }
- // else{
- // $sqlWhereTaxa .= 'OR ((o.family = "'.$searchTaxon.'") OR (o.sciname = "'.$searchTaxon.'")) ';
- // }
- // }
- // else{
- // if($taxonType == TaxaSearchType::COMMON_NAME){
- // $famArr = $this->setCommonNameWhereTerms($searchArr, $tidInArr);
- // if($famArr) $sqlWhereTaxa .= 'OR (o.family IN("'.implode('","',$famArr).'")) ';
- // }
- // if(isset($searchArr['TID_BATCH'])){
- // $tidInArr = array_merge($tidInArr, array_keys($searchArr['TID_BATCH']));
- // if(isset($searchArr['tid'])) $tidInArr = array_merge($tidInArr, array_keys($searchArr['tid']));
- // }
- // else{
- // $term = $this->cleanInStr(trim($searchTaxon,'%'));
- // //$term = preg_replace('/\s{1}.{1,2}\s{1}/', ' _ ', $term);
- // $term = preg_replace(array('/\s{1}x\s{1}/','/\s{1}X\s{1}/','/\s{1}\x{00D7}\s{1}/u'), ' _ ', $term);
- // if(array_key_exists('tid',$searchArr)){
- // $rankid = current($searchArr['tid']);
- // $tidArr = array_keys($searchArr['tid']);
- // //$sqlWhereTaxa .= "OR (o.tidinterpreted IN(".implode(',',$tidArr).")) ";
- // $tidInArr = array_merge($tidInArr, $tidArr);
- // //Return matches that are not linked to thesaurus
- // if($rankid > 179){
- // if($this->exactMatchOnly) $sqlWhereTaxa .= 'OR (o.sciname = "' . $term . '") ';
- // else $sqlWhereTaxa .= 'OR (o.sciname LIKE "' . $term . '%") ';
- // }
- // }
- // else{
- // //Protect against someone trying to download big pieces of the occurrence table through the user interface
- // if(strlen($term) < 4) $term .= ' ';
- // /*
- // if(strpos($term, ' ') || strpos($term, '%')){
- // //Return matches for "Pinus a"
- // $sqlWhereTaxa .= "OR (o.sciname LIKE '" . $term . "%') ";
- // }
- // else{
- // $sqlWhereTaxa .= "OR (o.sciname LIKE '" . $term . " %') ";
- // }
- // */
- // if($this->exactMatchOnly){
- // $sqlWhereTaxa .= 'OR (o.sciname = "' . $term . '") ';
- // }
- // else{
- // $sqlWhereTaxa .= 'OR (o.sciname LIKE "' . $term . '%") ';
- // if(!strpos($term,' _ ')){
- // //Accommodate for formats of hybrid designations within input and target data (e.g. x, multiplication sign, etc)
- // $term2 = preg_replace('/^([^\s]+\s{1})/', '$1 _ ', $term);
- // $sqlWhereTaxa .= 'OR (o.sciname LIKE "' . $term2 . '%") ';
- // }
- // }
- // }
- // }
- // if(array_key_exists('synonyms',$searchArr)){
- // $synArr = $searchArr['synonyms'];
- // if($synArr){
- // if($taxonType == TaxaSearchType::SCIENTIFIC_NAME || $taxonType == TaxaSearchType::COMMON_NAME){
- // foreach($synArr as $synTid => $sciName){
- // if(strpos($sciName,'aceae') || strpos($sciName,'idae')){
- // $sqlWhereTaxa .= 'OR (o.family = "' . $sciName . '") ';
- // }
- // }
- // }
- // //$sqlWhereTaxa .= 'OR (o.tidinterpreted IN('.implode(',',array_keys($synArr)).')) ';
- // $tidInArr = array_merge($tidInArr,array_keys($synArr));
- // }
- // }
- // }
- // }
- // if($tidInArr) $sqlWhereTaxa .= 'OR (o.tidinterpreted IN('.implode(',',array_unique($tidInArr)).')) ';
- // $sqlWhereTaxa = 'AND ('.trim(substr($sqlWhereTaxa,3)).') ';
- // if(strpos($sqlWhereTaxa,'e.parenttid')) $sqlWhereTaxa .= 'AND (e.taxauthid = '.$this->taxAuthId.') ';
- // if(strpos($sqlWhereTaxa,'ts.family')) $sqlWhereTaxa .= 'AND (ts.taxauthid = '.$this->taxAuthId.') ';
- // }
- // if($sqlWhereTaxa) return $sqlWhereTaxa;
- // else return false;
- // }
public function getTaxonWhereFrag(){
$sqlWhereTaxa = '';
- // var_dump($this->taxaArr);
if(isset($this->taxaArr['taxa'])){
$tidInArr = array();
$taxonType = $this->taxaArr['taxontype'];
@@ -570,12 +450,9 @@ public function getTaxonWhereFrag(){
//Class, order, or other higher rank
if(isset($searchArr['tid'])){
$tidArr = array_keys($searchArr['tid']);
- //$sqlWhereTaxa .= 'OR (o.tidinterpreted IN(SELECT DISTINCT tid FROM taxaenumtree WHERE (taxauthid = '.$this->taxAuthId.') AND (parenttid IN('.trim($tidStr,',').') OR (tid = '.trim($tidStr,',').')))) ';
$sqlWhereTaxa .= 'OR (e.parenttid IN('.implode(',', $tidArr).') ';
$sqlWhereTaxa .= 'OR (e.tid IN('.implode(',', $tidArr).')) ';
if(isset($searchArr['synonyms'])) $sqlWhereTaxa .= 'OR (e.tid IN('.implode(',',array_keys($searchArr['synonyms'])).')) ';
- //$tidInArr = array_merge($tidInArr,$tidArr);
- //if(isset($searchArr['synonyms'])) $tidInArr = array_merge($tidInArr,array_keys($searchArr['synonyms']));
$sqlWhereTaxa .= ') ';
}
else{
@@ -584,9 +461,6 @@ public function getTaxonWhereFrag(){
}
}
elseif($taxonType == TaxaSearchType::FAMILY_ONLY){
- //$sqlWhereTaxa .= 'OR ((o.family = "'.$searchTaxon.'") OR (o.sciname = "'.$searchTaxon.'")) ';
- //$sqlWhereTaxa .= 'OR (((ts.family = "'.$searchTaxon.'") AND (ts.taxauthid = '.$this->taxAuthId.')) OR (o.family = "'.$searchTaxon.'") OR (o.sciname = "'.$searchTaxon.'")) ';
- //$sqlWhereTaxa .= 'OR (((ts.family = "'.$searchTaxon.'") AND (ts.taxauthid = '.$this->taxAuthId.')) OR o.sciname = "'.$searchTaxon.'") ';
if(isset($searchArr['tid'])){
$tidArr = array_keys($searchArr['tid']);
$sqlWhereTaxa .= 'OR ((ts.family = "'.$cleanedSearchTaxon.'") OR (ts.tid IN('.implode(',', $tidArr).'))) ';
@@ -606,12 +480,10 @@ public function getTaxonWhereFrag(){
}
else{
$term = $this->cleanInStr(trim($searchTaxon,'%'));
- //$term = preg_replace('/\s{1}.{1,2}\s{1}/', ' _ ', $term);
$term = preg_replace(array('/\s{1}x\s{1}/','/\s{1}X\s{1}/','/\s{1}\x{00D7}\s{1}/u'), ' _ ', $term);
if(array_key_exists('tid',$searchArr)){
$rankid = current($searchArr['tid']);
$tidArr = array_keys($searchArr['tid']);
- //$sqlWhereTaxa .= "OR (o.tidinterpreted IN(".implode(',',$tidArr).")) ";
$tidInArr = array_merge($tidInArr, $tidArr);
//Return matches that are not linked to thesaurus
if($rankid > 179){
@@ -722,7 +594,7 @@ public function getTaxaSearchStr(){
public function getAssociationSearchStr(){
$str = '';
- if(isset($this->associationArr['relationship'])){
+ if(isset($this->associationArr['relationship']) && $this->associationArr['relationship'] != 'none'){
$str = 'Taxa that have the following association: ';
$str .= $this->associationArr['relationship'];
}
diff --git a/classes/OmAssociations.php b/classes/OmAssociations.php
index ccc3b3ecb7..72fa827d9d 100644
--- a/classes/OmAssociations.php
+++ b/classes/OmAssociations.php
@@ -2,6 +2,7 @@
include_once('Manager.php');
include_once('OccurrenceUtilities.php');
include_once('UuidFactory.php');
+include_once('AssociationManager.php');
class OmAssociations extends Manager{
@@ -24,11 +25,14 @@ public function __destruct(){
parent::__destruct();
}
- public function getAssociationArr($filter = null){
+ public function getAssociationArr($filter = null, $excludeScriptGenerated = true){
$retArr = array();
$relOccidArr = array();
$uidArr = array();
$sql = 'SELECT assocID, occid, '.implode(', ', array_keys($this->schemaMap)).', modifiedUid, modifiedTimestamp, createdUid, initialTimestamp FROM omoccurassociations WHERE ';
+ if($excludeScriptGenerated){
+ $sql .= "basisOfRecord IS NULL OR basisOfRecord != 'scriptGenerated' AND ";
+ }
if($this->assocID) $sql .= '(assocID = '.$this->assocID.') ';
elseif($filter == 'FULL')$sql .= '(occid = '.$this->occid.' OR occidAssociate = '.$this->occid.') ';
elseif($this->occid) $sql .= '(occid = '.$this->occid.') ';
@@ -37,6 +41,7 @@ public function getAssociationArr($filter = null){
$sql .= 'AND '.$field.' = "'.$this->cleanInStr($cond).'" ';
}
}
+ echo 'sql is: ' . $sql;
if($rs = $this->conn->query($sql)){
while($r = $rs->fetch_assoc()){
$retArr[$r['assocID']] = $r;
@@ -120,6 +125,7 @@ public function insertAssociation($inputArr){
$paramArr[] = $value;
}
$sql .= ') VALUES('.trim($sqlValues, ', ').') ';
+ $insertedRecord = null;
if($stmt = $this->conn->prepare($sql)){
$stmt->bind_param($this->typeStr, ...$paramArr);
try{
@@ -127,6 +133,19 @@ public function insertAssociation($inputArr){
if($stmt->affected_rows || !$stmt->error){
$this->assocID = $stmt->insert_id;
$status = true;
+
+ $fetchSql = 'SELECT * FROM omoccurassociations WHERE assocID = ?';
+ if ($fetchStmt = $this->conn->prepare($fetchSql)) {
+ $fetchStmt->bind_param('i', $this->assocID);
+ $fetchStmt->execute();
+ $result = $fetchStmt->get_result();
+ if ($result->num_rows > 0) {
+ $insertedRecord = $result->fetch_assoc();
+ } else {
+ $this->errorMessage = 'Record not found after insertion.';
+ }
+ $fetchStmt->close();
+ }
}
else $this->errorMessage = $stmt->error;
}
@@ -139,6 +158,11 @@ public function insertAssociation($inputArr){
}
else $this->errorMessage = 'ERROR preparing statement for omoccurassociations insert: '.$this->conn->error;
}
+
+ if($status == true){
+ $associationManager = new AssociationManager;
+ $associationManager->createInverseRecord($insertedRecord);
+ }
return $status;
}
diff --git a/collections/list.php b/collections/list.php
index cc5837bd31..c73ecec28f 100644
--- a/collections/list.php
+++ b/collections/list.php
@@ -3,8 +3,8 @@
if ($LANG_TAG != 'en' && file_exists($SERVER_ROOT . '/content/lang/collections/list.' . $LANG_TAG . '.php')) include_once($SERVER_ROOT . '/content/lang/collections/list.' . $LANG_TAG . '.php');
else include_once($SERVER_ROOT . '/content/lang/collections/list.en.php');
include_once($SERVER_ROOT . '/classes/OccurrenceListManager.php');
+include_once($SERVER_ROOT.'/classes/AssociationManager.php');
header("Content-Type: text/html; charset=" . $CHARSET);
-// var_dump($_REQUEST);
$taxonFilter = array_key_exists('taxonfilter', $_REQUEST) ? filter_var($_REQUEST['taxonfilter'], FILTER_SANITIZE_NUMBER_INT) : 0;
$targetTid = array_key_exists('targettid', $_REQUEST) ? filter_var($_REQUEST['targettid'], FILTER_SANITIZE_NUMBER_INT) : '';
$tabIndex = array_key_exists('tabindex', $_REQUEST) ? filter_var($_REQUEST['tabindex'], FILTER_SANITIZE_NUMBER_INT) : 1;
@@ -13,13 +13,23 @@
$datasetid = array_key_exists('datasetid', $_REQUEST) ? filter_var($_REQUEST['datasetid'], FILTER_SANITIZE_NUMBER_INT) : '';
$comingFrom = array_key_exists('comingFrom', $_REQUEST) ? htmlspecialchars($_REQUEST['comingFrom'], HTML_SPECIAL_CHARS_FLAGS) : '';
$_SESSION['datasetid'] = filter_var($datasetid, FILTER_SANITIZE_NUMBER_INT);
+$associationManager = new AssociationManager();
+$shouldEstablishInverseRelationshipRecords = array_key_exists('establishInverseRelationshipRecords', $_REQUEST) ? true : false;
+if($shouldEstablishInverseRelationshipRecords){
+ echo 'Establishing Inverse Relationship Records...
';
+ $associationManager->establishInverseRelationshipRecords();
+ if($comingFrom === 'search/index.php'){
+ header('Location: search/index.php');
+ } else{
+ header('Location: harvestparams.php');
+ }
+}
+
$collManager = new OccurrenceListManager();
$searchVar = $collManager->getQueryTermStr();
-// var_dump($searchVar);
if ($targetTid && array_key_exists('mode', $_REQUEST)) $searchVar .= '&mode=voucher&targettid=' . $targetTid;
$occurArr = $collManager->getSpecimenMap($pageNumber, $cntPerPage);
-// var_dump($occurArr);
$SHOULD_INCLUDE_CULTIVATED_AS_DEFAULT = $SHOULD_INCLUDE_CULTIVATED_AS_DEFAULT ?? false;
$SHOULD_USE_HARVESTPARAMS = $SHOULD_USE_HARVESTPARAMS ?? false;
@@ -66,6 +76,23 @@
});
});
+ // function establishInverseRelationshipRecords() {
+ // console.log('deleteMe got here in establishInverseRelationshipRecords');
+ // $.ajax({
+ // url: 'list.php',
+ // type: 'post',
+ // data: { action: 'establishInverseRelationshipRecords' },
+ // success: function(response) {
+ // console.log('deleteMe success');
+ // console.log(response);
+ // },
+ // error: function(xhr, status, error) {
+ // console.log('deleteMe failure');
+ // console.error(xhr.responseText);
+ // }
+ // });
+ // }
+
function validateOccurListForm(f) {
if (f.targetdatasetid.value == "") {
alert("");
@@ -227,6 +254,18 @@ function displayDatasetTools() {
if ($associationSearchStr = $collManager->getAssociationSearchStr()) {
if (strlen($associationSearchStr) > 300) $associationSearchStr = substr($associationSearchStr, 0, 300) . '... (' . htmlspecialchars($LANG['SHOW_ALL'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE) . ')' . substr($taxaSearchStr, 300) . ''; // @TODO wouldn't this truncate in either case?
echo '' . $LANG['ASSOCIATIONS'] . ': ' . $associationSearchStr . '
';
+ // echo '' . "Didn't find what you were looking for? Try " . '' . ". Note that this may take serveral minutes." . '
';
+ ?>
+
+ Didn't find what you were looking for?
+
+ And try your search again. Note that this may take serveral minutes.
+
+ getLocalSearchStr()) {
echo '' . $LANG['SEARCH_CRITERIA'] . ': ' . $localSearchStr . '
';
diff --git a/collections/search/index.php b/collections/search/index.php
index 86c64cd4be..8ffc82bed7 100644
--- a/collections/search/index.php
+++ b/collections/search/index.php
@@ -31,6 +31,7 @@
$specArr = (isset($collList['spec'])?$collList['spec']:null);
$obsArr = (isset($collList['obs'])?$collList['obs']:null);
$associationManager = new AssociationManager();
+$relationshipTypes = $associationManager->getRelationshipTypes();
?>
diff --git a/collections/search/js/searchform.js b/collections/search/js/searchform.js
index 15fa4e11fd..f3d950810d 100644
--- a/collections/search/js/searchform.js
+++ b/collections/search/js/searchform.js
@@ -171,7 +171,6 @@ function addChip(element) {
}
function handleRemoval(element, inputChip) {
- console.log("deleteMe handleRemoval clicked");
element.type === "checkbox"
? (element.checked = false)
: (element.value = element.defaultValue);
@@ -193,13 +192,6 @@ function handleRemoval(element, inputChip) {
collection.checked = false;
});
}
- // if (element?.getAttribute("id")?.startsWith("materialsampletype")) {
- // // if they close a materialsampletype chip, revert to the none option selected
- // const targetIndex = document.getElementById(
- // "materialsampletype-none"
- // ).selectedIndex;
- // document.getElementById("materialsampletype").selectedIndex = targetIndex;
- // }
setAssociationRelationshipTypeToDefault(element);
setMaterialSampleToDefault(element);
setTaxonTypeToDefault(element);
diff --git a/config/schema/3.0/patches/db_schema_patch-3.1.sql b/config/schema/3.0/patches/db_schema_patch-3.1.sql
index 84d3cb542d..ed887ae087 100644
--- a/config/schema/3.0/patches/db_schema_patch-3.1.sql
+++ b/config/schema/3.0/patches/db_schema_patch-3.1.sql
@@ -274,3 +274,5 @@ CREATE TABLE `usersthirdpartyauth` (
ALTER TABLE `omoccurresource`
RENAME TO `deprecated_omoccurresource` ;
+# We need to relax this if we want inverse relationship entries in omoccurassociations for derivedFromSameIndividual
+ALTER TABLE omoccurassociations DROP INDEX UQ_omoccurassoc_sciname, ADD INDEX `UQ_omoccurassoc_sciname` (`occid`, `verbatimSciname`, `associationType`) USING BTREE;
\ No newline at end of file
diff --git a/content/lang/collections/search/index.es.php b/content/lang/collections/search/index.es.php
index 56839f977a..5612ab5847 100644
--- a/content/lang/collections/search/index.es.php
+++ b/content/lang/collections/search/index.es.php
@@ -115,4 +115,7 @@
$LANG['EXPAND_ALL_SECTIONS'] = 'Expandir todas las secciones';
$LANG['COLLAPSE_ALL_SECTIONS'] = 'Contraer todas las secciones';
$LANG['ASSOCIATIONS'] = 'Asociaciones';
+$LANG['ASSOCIATION_DESCRIPTION'] = 'Encuentre todas las apariciones de taxones que tengan la siguiente asociación';
+$LANG['ASSOCIATION_DESCRIPTION_2'] = 'con el siguiente taxon';
+$LANG['ASSOCIATION_TYPE'] = 'Tipo de asociación';
?>
diff --git a/content/lang/collections/search/index.fr.php b/content/lang/collections/search/index.fr.php
index 679b37f1ff..892b06768b 100644
--- a/content/lang/collections/search/index.fr.php
+++ b/content/lang/collections/search/index.fr.php
@@ -116,5 +116,8 @@
$LANG['EXPAND_ALL_SECTIONS'] = 'Développer toutes les sections';
$LANG['COLLAPSE_ALL_SECTIONS'] = 'Réduire toutes les sections';
$LANG['ASSOCIATIONS'] = 'Les associations';
+$LANG['ASSOCIATION_DESCRIPTION'] = 'Trouver toutes les occurrences de taxons qui ont l\'association suivante';
+$LANG['ASSOCIATION_DESCRIPTION_2'] = 'avec le taxon suivant';
+$LANG['ASSOCIATION_TYPE'] = 'Type d\'association';
?>