<& etc. $type = WT_Filter::get('field'); switch ($type) { case 'ASSO': // Associates of an individuals, whose name contains the search terms $data = array(); // Fetch all data, regardless of privacy $rows = WT_DB::prepare( "SELECT 'INDI' AS type, i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, n_full" . " FROM `##individuals`" . " JOIN `##name` ON (i_id=n_id AND i_file=n_file)" . " WHERE (n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') OR n_surn LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%')) AND i_file=? ORDER BY n_full COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, $term, WT_GED_ID)) ->fetchAll(); // Filter for privacy and whether they could be alive at the right time $event_date = WT_Filter::get('extra'); $date = new WT_Date($event_date); $event_jd = $date->JD(); foreach ($rows as $row) { $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($person->canShow()) { if ($event_jd) { // Exclude individuals who were born after the event. $person_birth_jd = $person->getEstimatedBirthDate()->minJD(); if ($person_birth_jd && $person_birth_jd > $event_jd) { continue; } // Exclude individuals who died before the event. $person_death_jd = $person->getEstimatedDeathDate()->MaxJD(); if ($person_death_jd && $person_death_jd < $event_jd) { continue; } } // Add the age (if we have it) or the lifespan (if we do not). $label = $person->getFullName(); if ($event_jd && $person->getBirthDate()->isOK()) { $label .= ', (' . WT_I18N::translate('Age') . ' ' . $person->getBirthDate()->MinDate()->getAge(false, $event_jd) . ')'; } else { $label .= ', ' . $person->getLifeSpan() . ''; } $data[$row->xref] = array('value' => $row->xref, 'label' => $label); } } echo json_encode($data); return; case 'CEME': // Cemetery fields, that contain the search term $data = array(); // Fetch all data, regardless of privacy $rows = WT_DB::prepare( "SELECT SQL_CACHE i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom" . " FROM `##individuals`" . " WHERE i_gedcom LIKE '%\n2 CEME %' AND i_file=?" . " ORDER BY SUBSTRING_INDEX(i_gedcom, '\n2 CEME ', -1) COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array(WT_GED_ID)) ->fetchAll(); // Filter for privacy foreach ($rows as $row) { $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if (preg_match('/\n2 CEME (.*' . preg_quote($term, '/') . '.*)/i', $person->getGedcom(), $match)) { if (!in_array($match[1], $data)) { $data[] = $match[1]; } } } echo json_encode($data); return; case 'FAM': // Families, whose name contains the search terms $data = array(); // Fetch all data, regardless of privacy $rows = get_FAM_rows($term); // Filter for privacy foreach ($rows as $row) { $family = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($family->canShowName()) { $marriage_year = $family->getMarriageYear(); if ($marriage_year) { $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName() . ', ' . $marriage_year . ''); } else { $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName()); } } } echo json_encode($data); return; case 'GIVN': // Given names, that start with the search term // Do not filter by privacy. Given names on their own do not identify individuals. echo json_encode( WT_DB::prepare( "SELECT SQL_CACHE DISTINCT n_givn" . " FROM `##name`" . " WHERE n_givn LIKE CONCAT(?, '%') AND n_file=?" . " ORDER BY n_givn COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchOneColumn() ); return; case 'INDI': // Individuals, whose name contains the search terms $data = array(); // Fetch all data, regardless of privacy $rows = WT_DB::prepare( "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, n_full" . " FROM `##individuals`" . " JOIN `##name` ON (i_id=n_id AND i_file=n_file)" . " WHERE (n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') OR n_surn LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%')) AND i_file=? ORDER BY n_full COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, $term, WT_GED_ID)) ->fetchAll(); // Filter for privacy foreach ($rows as $row) { $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($person->canShowName()) { $data[] = array('value' => $row->xref, 'label' => str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row->n_full) . ', ' . $person->getLifeSpan() . ''); } } echo json_encode($data); return; case 'NOTE': // Notes which contain the search terms $data = array(); // Fetch all data, regardless of privacy $rows = get_NOTE_rows($term); // Filter for privacy foreach ($rows as $row) { $note = WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($note->canShowName()) { $data[] = array('value' => $note->getXref(), 'label' => $note->getFullName()); } } echo json_encode($data); return; case 'OBJE': $data = array(); // Fetch all data, regardless of privacy $rows = get_OBJE_rows($term); // Filter for privacy foreach ($rows as $row) { $media = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($media->canShowName()) { $data[] = array('value' => $row->xref, 'label' => ' ' . $media->getFullName()); } } echo json_encode($data); return; case 'PLAC': // Place names (with hierarchy), that include the search term // Do not filter by privacy. Place names on their own do not identify individuals. $data = array(); foreach (WT_Place::findPlaces($term, WT_GED_ID) as $place) { $data[] = $place->getGedcomName(); } if (!$data && $WT_TREE->getPreference('GEONAMES_ACCOUNT')) { // No place found? Use an external gazetteer $url = "http://api.geonames.org/searchJSON" . "?name_startsWith=" . urlencode($term) . "&lang=" . WT_LOCALE . "&fcode=CMTY&fcode=ADM4&fcode=PPL&fcode=PPLA&fcode=PPLC" . "&style=full" . "&username=" . $WT_TREE->getPreference('GEONAMES_ACCOUNT'); // try to use curl when file_get_contents not allowed if (ini_get('allow_url_fopen')) { $json = file_get_contents($url); } elseif (function_exists('curl_init')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $json = curl_exec($ch); curl_close($ch); } else { return $data; } $places = json_decode($json, true); if ($places['geonames']) { foreach ($places['geonames'] as $k => $place) { $data[] = $place['name'] . ', ' . $place['adminName2'] . ', ' . $place['adminName1'] . ', ' . $place['countryName']; } } } echo json_encode($data); return; case 'PLAC2': // Place names (without hierarchy), that include the search term // Do not filter by privacy. Place names on their own do not identify individuals. echo json_encode( WT_DB::prepare( "SELECT SQL_CACHE p_place" . " FROM `##places`" . " WHERE p_place LIKE CONCAT('%', ?, '%') AND p_file=?" . " ORDER BY p_place COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchOneColumn() ); return; case 'REPO': // Repositories, that include the search terms $data = array(); // Fetch all data, regardless of privacy $rows = get_REPO_rows($term); // Filter for privacy foreach ($rows as $row) { $record = WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($record->canShowName()) { foreach ($record->getFacts('NAME') as $fact) { $data[] = array('value' => $record->getXref(), 'label' => $fact->getValue()); } } } echo json_encode($data); return; case 'REPO_NAME': // Repository names, that include the search terms $data = array(); // Fetch all data, regardless of privacy $rows = get_REPO_rows($term); // Filter for privacy foreach ($rows as $row) { $record = WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($record->canShowName()) { $data[] = strip_tags($record->getFullName()); } } echo json_encode($data); return; case 'SOUR': // Sources, that include the search terms $data = array(); // Fetch all data, regardless of privacy $rows = get_SOUR_rows($term); // Filter for privacy foreach ($rows as $row) { $record = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($record->canShowName()) { foreach ($record->getFacts('TITL') as $fact) { $data[] = array('value' => $record->getXref(), 'label' => $fact->getValue()); } } } echo json_encode($data); return; case 'PAGE': // Citation details, for a given source, that contain the search term $data = array(); $sid = WT_Filter::get('extra', WT_REGEX_XREF); // Fetch all data, regardless of privacy $rows = WT_DB::prepare( "SELECT SQL_CACHE i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom" . " FROM `##individuals`" . " WHERE i_gedcom LIKE CONCAT('%\n_ SOUR @', ?, '@%', REPLACE(?, ' ', '%'), '%') AND i_file=?" ) ->execute(array($sid, $term, WT_GED_ID)) ->fetchAll(); // Filter for privacy foreach ($rows as $row) { $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if (preg_match('/\n1 SOUR @' . $sid . '@(?:\n[2-9].*)*\n2 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $person->getGedcom(), $match)) { $data[] = $match[1]; } if (preg_match('/\n2 SOUR @' . $sid . '@(?:\n[3-9].*)*\n3 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $person->getGedcom(), $match)) { $data[] = $match[1]; } } // Fetch all data, regardless of privacy $rows = WT_DB::prepare( "SELECT SQL_CACHE f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom" . " FROM `##families`" . " WHERE f_gedcom LIKE CONCAT('%\n_ SOUR @', ?, '@%', REPLACE(?, ' ', '%'), '%') AND f_file=?" ) ->execute(array($sid, $term, WT_GED_ID)) ->fetchAll(); // Filter for privacy foreach ($rows as $row) { $family = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if (preg_match('/\n1 SOUR @' . $sid . '@(?:\n[2-9].*)*\n2 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $family->getGedcom(), $match)) { $data[] = $match[1]; } if (preg_match('/\n2 SOUR @' . $sid . '@(?:\n[3-9].*)*\n3 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $family->getGedcom(), $match)) { $data[] = $match[1]; } } // array_unique() converts the keys from integer to string, which breaks // the JSON encoding - so need to call array_values() to convert them // back into integers. $data = array_values(array_unique($data)); echo json_encode($data); return; case 'SOUR_TITL': // Source titles, that include the search terms $data = array(); // Fetch all data, regardless of privacy $rows = WT_DB::prepare( "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom, s_name" . " FROM `##sources`" . " WHERE s_name LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND s_file=? ORDER BY s_name COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchAll(); // Filter for privacy foreach ($rows as $row) { $source = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($source->canShowName()) { $data[] = $row->s_name; } } echo json_encode($data); return; case 'SURN': // Surnames, that start with the search term // Do not filter by privacy. Surnames on their own do not identify individuals. echo json_encode( WT_DB::prepare( "SELECT SQL_CACHE DISTINCT n_surname" . " FROM `##name`" . " WHERE n_surname LIKE CONCAT(?, '%') AND n_file=?" . " ORDER BY n_surname COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchOneColumn() ); return; case 'IFSRO': $data = array(); // Fetch all data, regardless of privacy $rows = get_INDI_rows($term); // Filter for privacy foreach ($rows as $row) { $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($person->canShowName()) { $data[] = array('value' => $person->getXref(), 'label' => str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row->n_full) . ', ' . $person->getLifeSpan() . ''); } } // Fetch all data, regardless of privacy $rows = get_SOUR_rows($term); // Filter for privacy foreach ($rows as $row) { $source = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($source->canShowName()) { $data[] = array('value' => $source->getXref(), 'label' => $source->getFullName()); } } // Fetch all data, regardless of privacy $rows = get_REPO_rows($term); // Filter for privacy foreach ($rows as $row) { $repository = WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($repository->canShowName()) { $data[] = array('value' => $repository->getXref(), 'label' => $repository->getFullName()); } } // Fetch all data, regardless of privacy $rows = get_OBJE_rows($term); // Filter for privacy foreach ($rows as $row) { $media = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($media->canShowName()) { $data[] = array('value' => $media->getXref(), 'label' => ' ' . $media->getFullName()); } } // Fetch all data, regardless of privacy $rows = get_FAM_rows($term); // Filter for privacy foreach ($rows as $row) { $family = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($family->canShowName()) { $marriage_year = $family->getMarriageYear(); if ($marriage_year) { $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName() . ', ' . $marriage_year . ''); } else { $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName()); } } } // Fetch all data, regardless of privacy $rows = get_NOTE_rows($term); // Filter for privacy foreach ($rows as $row) { $note = WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($note->canShowName()) { $data[] = array('value' => $note->getXref(), 'label' => $note->getFullName()); } } echo json_encode($data); return; case 'IFS': $data = array(); // Fetch all data, regardless of privacy $rows = get_INDI_rows($term); // Filter for privacy foreach ($rows as $row) { $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($person->canShowName()) { $data[] = array('value' => $person->getXref(), 'label' => str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row->n_full) . ', ' . $person->getLifeSpan() . ''); } } // Fetch all data, regardless of privacy $rows = get_SOUR_rows($term); // Filter for privacy foreach ($rows as $row) { $source = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($source->canShowName()) { $data[] = array('value' => $source->getXref(), 'label' => $source->getFullName()); } } // Fetch all data, regardless of privacy $rows = get_FAM_rows($term); // Filter for privacy foreach ($rows as $row) { $family = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); if ($family->canShowName()) { $marriage_year = $family->getMarriageYear(); if ($marriage_year) { $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName() . ', ' . $marriage_year . ''); } else { $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName()); } } } echo json_encode($data); return; } /** * @param string $term * * @return stdClass[] */ function get_FAM_rows($term) { return WT_DB::prepare( "SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom" . " FROM `##families`" . " JOIN `##name` AS husb_name ON (f_husb=husb_name.n_id AND f_file=husb_name.n_file)" . " JOIN `##name` AS wife_name ON (f_wife=wife_name.n_id AND f_file=wife_name.n_file)" . " WHERE CONCAT(husb_name.n_full, ' ', wife_name.n_full) LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND f_file=?" . " AND husb_name.n_type<>'_MARNM' AND wife_name.n_type<>'_MARNM'" . " ORDER BY husb_name.n_sort, wife_name.n_sort COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchAll(); } /** * @param string $term * * @return stdClass[] */ function get_INDI_rows($term) { return WT_DB::prepare( "SELECT 'INDI' AS type, i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, n_full" . " FROM `##individuals`" . " JOIN `##name` ON (i_id=n_id AND i_file=n_file)" . " WHERE n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND i_file=? ORDER BY n_full COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchAll(); } /** * @param string $term * * @return stdClass[] */ function get_NOTE_rows($term) { return WT_DB::prepare( "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom" . " FROM `##other`" . " JOIN `##name` ON (o_id=n_id AND o_file=n_file)" . " WHERE o_gedcom LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND o_file=? AND o_type='NOTE'" . " ORDER BY n_full COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchAll(); } /** * @param string $term * * @return stdClass[] */ function get_OBJE_rows($term) { return WT_DB::prepare( "SELECT 'OBJE' AS type, m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom" . " FROM `##media`" . " WHERE (m_titl LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') OR m_id LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%')) AND m_file=?" ) ->execute(array($term, $term, WT_GED_ID)) ->fetchAll(); } /** * @param string $term * * @return stdClass[] */ function get_REPO_rows($term) { return WT_DB::prepare( "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom" . " FROM `##other`" . " JOIN `##name` ON (o_id=n_id AND o_file=n_file)" . " WHERE n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND o_file=? AND o_type='REPO'" . " ORDER BY n_full COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchAll(); } /** * @param string $term * * @return stdClass[] */ function get_SOUR_rows($term) { return WT_DB::prepare( "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom" . " FROM `##sources`" . " WHERE s_name LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND s_file=? ORDER BY s_name COLLATE '" . WT_I18N::$collation . "'" ) ->execute(array($term, WT_GED_ID)) ->fetchAll(); }