action = WT_Filter::post('action', 'advanced|general|soundex|replace'); if (!$this->action) { $this->action = WT_Filter::get('action', 'advanced|general|soundex|replace', 'general'); } $topsearch = WT_Filter::postBool('topsearch'); if ($topsearch) { $this->isPostBack = true; $this->srfams = 'yes'; $this->srindi = 'yes'; $this->srsour = 'yes'; $this->srnote = 'yes'; } // Get the query $this->query = WT_Filter::post('query', '.{2,}'); $this->myquery = WT_Filter::escapeHtml($this->query); $this->replace = WT_Filter::post('replace'); $this->replaceNames = WT_Filter::postBool('replaceNames'); $this->replacePlaces = WT_Filter::postBool('replacePlaces'); $this->replacePlacesWord = WT_Filter::postBool('replacePlacesWord'); $this->replaceAll = WT_Filter::postBool('replaceAll'); // TODO: fetch each variable independently, using appropriate validation // Aquire all the variables values from the $_REQUEST $varNames = array ("isPostBack", "srfams", "srindi", "srsour", "srnote", "view", "soundex", "subaction", "nameprt", "showasso", "resultsPageNum", "resultsPerPage", "totalResults", "totalGeneralResults", "indiResultsPrinted", "famResultsPrinted", "srcResultsPrinted", "myindilist", "mysourcelist", "mynotelist", "myfamlist"); $this->setRequestValues($varNames); if (!$this->isPostBack) { // Enable the default gedcom for search $str = str_replace(array (".", "-", " "), array ("_", "_", "_"), WT_GEDCOM); $_REQUEST["$str"] = $str; } // Retrieve the gedcoms to search in if (count(WT_Tree::getAll())>1 && WT_Site::preference('ALLOW_CHANGE_GEDCOM')) { foreach (WT_Tree::getAll() as $tree) { $str = str_replace(array (".", "-", " "), array ("_", "_", "_"), $tree->tree_name); if (isset ($_REQUEST["$str"]) || $topsearch) { $this->sgeds[$tree->tree_id] = $tree->tree_name; $_REQUEST["$str"] = 'yes'; } } } else { $this->sgeds[WT_GED_ID] = WT_GEDCOM; } // vars use for soundex search $this->firstname = WT_Filter::post('firstname'); $this->lastname = WT_Filter::post('lastname'); $this->place = WT_Filter::post('place'); $this->year = WT_Filter::post('year'); // Set the search result titles for soundex searches if ($this->firstname || $this->lastname || $this->place) { $this->myquery = WT_Filter::escapeHtml(implode(' ', array($this->firstname, $this->lastname, $this->place))); }; if (!empty ($_REQUEST["name"])) { $this->name = $_REQUEST["name"]; $this->myname = $this->name; } else { $this->name=""; $this->myname = ""; } if (!empty ($_REQUEST["birthdate"])) { $this->birthdate = $_REQUEST["birthdate"]; $this->mybirthdate = $this->birthdate; } else { $this->birthdate=""; $this->mybirthdate = ""; } if (!empty ($_REQUEST["birthplace"])) { $this->birthplace = $_REQUEST["birthplace"]; $this->mybirthplace = $this->birthplace; } else { $this->birthplace=""; $this->mybirthplace = ""; } if (!empty ($_REQUEST["deathdate"])) { $this->deathdate = $_REQUEST["deathdate"]; $this->mydeathdate = $this->deathdate; } else { $this->deathdate=""; $this->mydeathdate = ""; } if (!empty ($_REQUEST["deathplace"])) { $this->deathplace = $_REQUEST["deathplace"]; $this->mydeathplace = $this->deathplace; } else { $this->deathplace=""; $this->mydeathplace = ""; } if (!empty ($_REQUEST["gender"])) { $this->gender = $_REQUEST["gender"]; $this->mygender = $this->gender; } else { $this->gender=""; $this->mygender = ""; } $this->inputFieldNames[] = "action"; $this->inputFieldNames[] = "isPostBack"; $this->inputFieldNames[] = "resultsPerPage"; $this->inputFieldNames[] = "query"; $this->inputFieldNames[] = "srindi"; $this->inputFieldNames[] = "srfams"; $this->inputFieldNames[] = "srsour"; $this->inputFieldNames[] = "srnote"; $this->inputFieldNames[] = "showasso"; $this->inputFieldNames[] = "firstname"; $this->inputFieldNames[] = "lastname"; $this->inputFieldNames[] = "place"; $this->inputFieldNames[] = "year"; $this->inputFieldNames[] = "soundex"; $this->inputFieldNames[] = "nameprt"; $this->inputFieldNames[] = "subaction"; $this->inputFieldNames[] = "name"; $this->inputFieldNames[] = "birthdate"; $this->inputFieldNames[] = "birthplace"; $this->inputFieldNames[] = "deathdate"; $this->inputFieldNames[] = "deathplace"; $this->inputFieldNames[] = "gender"; // Get the search results based on the action if ($topsearch) { $this->TopSearch(); } // If we want to show associated persons, build the list switch ($this->action) { case 'general': $this->setPageTitle(WT_I18N::translate('General search')); $this->GeneralSearch(); break; case 'soundex': $this->setPageTitle(WT_I18N::translate('Phonetic search')); $this->SoundexSearch(); break; case 'replace': $this->setPageTitle(WT_I18N::translate('Search and replace')); $this->SearchAndReplace(); return; } } /** * setRequestValues - Checks if the variable names ($varNames) are in * the $_REQUEST and if so assigns their values to * $this based on the variable name ($this->$varName). * * @param array $varNames - Array of variable names(strings). */ function setRequestValues($varNames) { foreach ($varNames as $key => $varName) { if (isset ($_REQUEST[$varName])) { if ($varName=='action' && $_REQUEST[$varName]=='replace' && !WT_USER_CAN_EDIT) { $this->action='general'; continue; } $this->$varName = $_REQUEST[$varName]; } } } /** * Handles searches entered in the top search box in the themes and * prepares the search to do a general search on individuals, families and sources. */ function TopSearch() { // first set some required variables. Search only in current gedcom, only in individuals. $this->srindi = "yes"; // Enable the default gedcom for search $str = str_replace(array (".", "-", " "), array ("_", "_", "_"), WT_GEDCOM); $_REQUEST["$str"] = "yes"; // Then see if an ID is typed in. If so, we might want to jump there. if (isset ($this->query)) { $record=WT_GedcomRecord::getInstance($this->query); if ($record && $record->canShow()) { header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$record->getRawUrl()); exit; } } } /** * Gathers results for a general search */ function GeneralSearch() { global $GEDCOM; $oldged = $GEDCOM; // Split search terms into an array $query_terms=array(); $query=$this->query; // Words in double quotes stay together while (preg_match('/"([^"]+)"/', $query, $match)) { $query_terms[]=trim($match[1]); $query=str_replace($match[0], '', $query); } // Other words get treated separately while (preg_match('/[\S]+/', $query, $match)) { $query_terms[]=trim($match[0]); $query=str_replace($match[0], '', $query); } //-- perform the search if ($query_terms && $this->sgeds) { // Write a log entry $logstring = "Type: General\nQuery: ".$this->query; AddToSearchlog($logstring, $this->sgeds); // Search the individuals if (isset ($this->srindi)) { $this->myindilist=search_indis($query_terms, array_keys($this->sgeds), 'AND'); } else { $this->myindilist=array(); } // Search the fams if (isset ($this->srfams)) { $this->myfamlist=array_merge( search_fams($query_terms, array_keys($this->sgeds), 'AND'), search_fams_names($query_terms, array_keys($this->sgeds), 'AND') ); $this->myfamlist=array_unique($this->myfamlist); } else { $this->myfamlist=array(); } // Search the sources if (isset ($this->srsour)) { if (!empty ($this->query)) $this->mysourcelist=search_sources($query_terms, array_keys($this->sgeds), 'AND'); } else { $this->mysourcelist=array(); } // Search the notes if (isset ($this->srnote)) { if (!empty ($this->query)) $this->mynotelist=search_notes($query_terms, array_keys($this->sgeds), 'AND'); } else { $this->mynotelist=array(); } // If only 1 item is returned, automatically forward to that item // If ID cannot be displayed, continue to the search page. if (count($this->myindilist)==1 && !$this->myfamlist && !$this->mysourcelist && !$this->mynotelist) { $indi=$this->myindilist[0]; if ($indi->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$indi->getRawUrl()); exit; } } if (!$this->myindilist && count($this->myfamlist)==1 && !$this->mysourcelist && !$this->mynotelist) { $fam=$this->myfamlist[0]; if ($fam->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$fam->getRawUrl()); exit; } } if (!$this->myindilist && !$this->myfamlist && count($this->mysourcelist)==1 && !$this->mynotelist) { $sour=$this->mysourcelist[0]; if ($sour->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$sour->getRawUrl()); exit; } } if (!$this->myindilist && !$this->myfamlist && !$this->mysourcelist && count($this->mynotelist)==1) { $note=$this->mynotelist[0]; if ($note->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$note->getRawUrl()); exit; } } } } /** * Preforms a search and replace */ function SearchAndReplace() { global $GEDCOM, $manual_save, $STANDARD_NAME_FACTS, $ADVANCED_NAME_FACTS; $this->sgeds = array(WT_GED_ID=>WT_GEDCOM); $this->srindi = "yes"; $this->srfams = "yes"; $this->srsour = "yes"; $this->srnote = "yes"; $oldquery = $this->query; $this->GeneralSearch(); //-- don't try to make any changes if nothing was found if (!$this->myindilist && !$this->myfamlist && !$this->mysourcelist && !$this->mynotelist) { return; } AddToLog("Search And Replace old:".$oldquery." new:".$this->replace, 'edit'); $manual_save = true; // Include edit functions. require_once WT_ROOT.'includes/functions/functions_edit.php'; // These contain the search query and the replace string // $this->replace; // $this->query; // These contain the search results // We need to iterate through them and do the replaces //$this->myindilist; $adv_name_tags = preg_split("/[\s,;: ]+/", $ADVANCED_NAME_FACTS); $name_tags = array_unique(array_merge($STANDARD_NAME_FACTS, $adv_name_tags)); $name_tags[] = "_MARNM"; foreach ($this->myindilist as $id=>$record) { $oldRecord = $record->getGedcom(); $newRecord = $oldRecord; if ($this->replaceAll) { $newRecord = preg_replace("~".$oldquery."~i", $this->replace, $newRecord); } else { if ($this->replaceNames) { foreach ($name_tags as $f=>$tag) { $newRecord = preg_replace("~(\d) ".$tag." (.*)".$oldquery."(.*)~i", "$1 ".$tag." $2".$this->replace."$3", $newRecord); } } if ($this->replacePlaces) { if ($this->replacePlacesWord) $newRecord = preg_replace('~(\d) PLAC (.*)([,\W\s])'.$oldquery.'([,\W\s])~i', "$1 PLAC $2$3".$this->replace."$4",$newRecord); else $newRecord = preg_replace("~(\d) PLAC (.*)".$oldquery."(.*)~i", "$1 PLAC $2".$this->replace."$3",$newRecord); } } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { $record->updateRecord($newRecord, true); } else { unset($this->myindilist[$id]); } } foreach ($this->myfamlist as $id=>$record) { $oldRecord = $record->getGedcom(); $newRecord = $oldRecord; if ($this->replaceAll) { $newRecord = preg_replace("~".$oldquery."~i", $this->replace, $newRecord); } else { if ($this->replacePlaces) { if ($this->replacePlacesWord) $newRecord = preg_replace('~(\d) PLAC (.*)([,\W\s])'.$oldquery.'([,\W\s])~i', "$1 PLAC $2$3".$this->replace."$4",$newRecord); else $newRecord = preg_replace("~(\d) PLAC (.*)".$oldquery."(.*)~i", "$1 PLAC $2".$this->replace."$3",$newRecord); } } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { $record->updateRecord($newRecord, true); } else { unset($this->myfamlist[$id]); } } foreach ($this->mysourcelist as $id=>$record) { $oldRecord = $record->getGedcom(); $newRecord = $oldRecord; if ($this->replaceAll) { $newRecord = preg_replace("~".$oldquery."~i", $this->replace, $newRecord); } else { if ($this->replaceNames) { $newRecord = preg_replace("~(\d) TITL (.*)".$oldquery."(.*)~i", "$1 TITL $2".$this->replace."$3", $newRecord); $newRecord = preg_replace("~(\d) ABBR (.*)".$oldquery."(.*)~i", "$1 ABBR $2".$this->replace."$3", $newRecord); } if ($this->replacePlaces) { if ($this->replacePlacesWord) $newRecord = preg_replace('~(\d) PLAC (.*)([,\W\s])'.$oldquery.'([,\W\s])~i', "$1 PLAC $2$3".$this->replace."$4",$newRecord); else $newRecord = preg_replace("~(\d) PLAC (.*)".$oldquery."(.*)~i", "$1 PLAC $2".$this->replace."$3",$newRecord); } } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { $record->updateRecord($newRecord, true); } else { unset($this->mysourcelist[$id]); } } foreach ($this->mynotelist as $id=>$record) { $oldRecord = $record->getGedcom(); $newRecord = $oldRecord; if ($this->replaceAll) { $newRecord = preg_replace("~".$oldquery."~i", $this->replace, $newRecord); } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { $record->updateRecord($newRecord, true); } else { unset($this->mynotelist[$id]); } } } /** * Gathers results for a soundex search * * TODO * ==== * Does not search on the selected gedcoms, searches on all the gedcoms * Does not work on first names, instead of the code, value array is used in the search * Returns all the names even when Names with hit selected * Does not sort results by first name * Does not work on separate double word surnames * Does not work on duplicate code values of the searched text and does not give the correct code * Cohen should give DM codes 556000, 456000, 460000 and 560000, in 4.1 we search only on 560000?? * * The names' Soundex SQL table contains all the soundex values twice * The places table contains only one value * * The code should be improved - see RFE * */ function SoundexSearch() { if (((!empty ($this->lastname)) || (!empty ($this->firstname)) || (!empty ($this->place))) && (count($this->sgeds) > 0)) { $logstring = "Type: Soundex\n"; if (!empty ($this->lastname)) $logstring .= "Last name: ".$this->lastname."\n"; if (!empty ($this->firstname)) $logstring .= "First name: ".$this->firstname."\n"; if (!empty ($this->place)) $logstring .= "Place: ".$this->place."\n"; if (!empty ($this->year)) $logstring .= "Year: ".$this->year."\n"; AddToSearchlog($logstring, $this->sgeds); if ($this->sgeds) { $this->myindilist=search_indis_soundex($this->soundex, $this->lastname, $this->firstname, $this->place, array_keys($this->sgeds)); } else { $this->myindilist=array(); } } // Now we have the final list of individuals to be printed. // We may add the assos at this point. if ($this->showasso == 'on') { foreach ($this->myindilist as $indi) { foreach ($indi->linkedIndividuals('ASSO') as $asso) { $this->myindilist[]=$asso; } foreach ($indi->linkedIndividuals('_ASSO') as $asso) { $this->myindilist[]=$asso; } foreach ($indi->linkedFamilies('ASSO') as $asso) { $this->myfamlist[]=$asso; } foreach ($indi->linkedFamilies('_ASSO') as $asso) { $this->myfamlist[]=$asso; } } } //-- if only 1 item is returned, automatically forward to that item if (count($this->myindilist)==1 && $this->action!="replace") { $indi=$this->myindilist[0]; header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$indi->getRawUrl()); exit; } usort($this->myindilist, array('WT_GedcomRecord', 'Compare')); usort($this->myfamlist, array('WT_GedcomRecord', 'Compare')); } function printResults() { require_once WT_ROOT.'includes/functions/functions_print_lists.php'; global $GEDCOM; $somethingPrinted = false; // whether anything printed // ---- section to search and display results on a general keyword search if ($this->action=="general" || $this->action=="soundex" || $this->action=="replace") { if ($this->myindilist || $this->myfamlist || $this->mysourcelist || $this->mynotelist) { $this->addInlineJavascript('jQuery("#search-result-tabs").tabs();'); $this->addInlineJavascript('jQuery("#search-result-tabs").css("visibility", "visible");'); $this->addInlineJavascript('jQuery(".loading-image").css("display", "none");'); echo '
'; echo '
 
'; echo '
'; // individual results echo '
'; // Split individuals by tree $trees=WT_Tree::getAll(); foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->myindilist as $individual) { if ($individual->getGedcomId()==$ged_id) { $datalist[]=$individual; } } if ($datalist) { $somethingPrinted = true; usort($datalist, array('WT_GedcomRecord', 'Compare')); $GEDCOM=$gedcom; load_gedcom_settings($ged_id); echo '

', $this->myquery, ' @ ', $trees[$ged_id]->tree_title_html, '

', format_indi_table($datalist); echo '
';//indi-acc_content } } echo '
';//#searchAccordion-indi $this->addInlineJavascript('jQuery("#searchAccordion-indi").accordion({active:0, heightStyle: "content", collapsible: true, icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});'); // family results echo '
'; // Split families by gedcom foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->myfamlist as $family) { if ($family->getGedcomId()==$ged_id) { $datalist[]=$family; } } if ($datalist) { $somethingPrinted = true; usort($datalist, array('WT_GedcomRecord', 'Compare')); $GEDCOM=$gedcom; load_gedcom_settings($ged_id); echo '

', $this->myquery, ' @ ', $trees[$ged_id]->tree_title_html, '

', format_fam_table($datalist); echo '
';//fam-acc_content } } echo '
';//#searchAccordion-fam $this->addInlineJavascript('jQuery("#searchAccordion-fam").accordion({active:0, heightStyle: "content", collapsible: true, icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});'); // source results echo '
'; // Split sources by gedcom foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->mysourcelist as $source) { if ($source->getGedcomId()==$ged_id) { $datalist[]=$source; } } if ($datalist) { $somethingPrinted = true; usort($datalist, array('WT_GedcomRecord', 'Compare')); $GEDCOM=$gedcom; load_gedcom_settings($ged_id); echo '

', $this->myquery, ' @ ', $trees[$ged_id]->tree_title_html, '

', format_sour_table($datalist); echo '
';//fam-acc_content } } echo '
';//#searchAccordion-source $this->addInlineJavascript('jQuery("#searchAccordion-source").accordion({active:0, heightStyle: "content", collapsible: true, icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});'); // note results echo '
'; // Split notes by gedcom foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->mynotelist as $note) { if ($note->getGedcomId()==$ged_id) { $datalist[]=$note; } } if ($datalist) { $somethingPrinted = true; usort($datalist, array('WT_GedcomRecord', 'Compare')); $GEDCOM=$gedcom; load_gedcom_settings($ged_id); echo '

', $this->myquery, ' @ ', $trees[$ged_id]->tree_title_html, '

', format_note_table($datalist); echo '
';//note-acc_content } } echo '
';//#searchAccordion-note $this->addInlineJavascript('jQuery("#searchAccordion-note").accordion({active:0, heightStyle: "content", collapsible: true, icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});'); $GEDCOM=WT_GEDCOM; load_gedcom_settings(WT_GED_ID); echo '
'; //#search-result-tabs } elseif (isset ($this->query)) { echo '
'.WT_I18N::translate('No results found.').'
'; if (!isset ($this->srindi) && !isset ($this->srfams) && !isset ($this->srsour) && !isset ($this->srnote)) { echo ''.WT_I18N::translate('Be sure to select an option to search for.').'
'; } echo '
'; } } return $somethingPrinted; // whether anything printed } }