_gedcom = $gedcom; $this->_ged_id = get_id_from_gedcom($gedcom); $this->_gedcom_url = rawurlencode($gedcom); } /** * Return a string of all supported tags and an example of its output in table row form. */ function getAllTagsTable() { $examples = array(); foreach (get_class_methods($this) as $method) { if (in_array($method, self::$_not_allowed) || $method[0] == '_' || $method == 'getAllTagsTable' || $method == 'getAllTagsText') { continue; } $examples[$method] = $this->$method(); if (stristr($method, 'highlight')) { $examples[$method]=str_replace(array(' align="left"', ' align="right"'), '', $examples[$method]); } } ksort($examples); $html = ''; foreach ($examples as $tag=>$value) { $html .= ''; $html .= '' . $tag . ''; $html .= '' . $value . ''; $html .= ''; } return ''. ''. ''. ''. ''. ''. $html. '
' . WT_I18N::translate('Embedded variable') . '' . WT_I18N::translate('Resulting value') . '
'; } /** * Return a string of all supported tags in plain text. */ function getAllTagsText() { $examples = array(); foreach (get_class_methods($this) as $method) { if (in_array($method, self::$_not_allowed) || $method[0] == '_' || $method == 'getAllTagsTable' || $method == 'getAllTagsText') { continue; } $examples[$method] = $method; } ksort($examples); return implode('
', $examples); } /* * Get tags and their parsed results. */ function getTags($text) { static $funcs; // Retrive all class methods isset($funcs) or $funcs = get_class_methods($this); // Extract all tags from the provided text $ct = preg_match_all("/#([^#]+)(?=#)/", (string)$text, $match); $tags = $match[1]; $c = count($tags); $new_tags = array(); // tag to replace $new_values = array(); // value to replace it with /* * Parse block tags. */ for ($i=0; $i < $c; $i++) { $full_tag = $tags[$i]; // Added for new parameter support $params = explode(':', $tags[$i]); if (count($params) > 1) { $tags[$i] = array_shift($params); } else { $params = array(); } // Skip non-tags and non-allowed tags if ($tags[$i][0] == '_' || in_array($tags[$i], self::$_not_allowed)) { continue; } // Generate the replacement value for the tag if (method_exists($this, $tags[$i])) { $new_tags[] = "#{$full_tag}#"; $new_values[]=call_user_func_array(array($this, $tags[$i]), array($params)); } elseif ($tags[$i] == 'help') { // re-merge, just in case $new_tags[] = "#{$full_tag}#"; $new_values[] = help_link(join(':', $params)); } } return array($new_tags, $new_values); } /* * Embed tags in text */ function embedTags($text) { if (strpos($text, '#')!==false) { list($new_tags, $new_values) = $this->getTags($text); $text = str_replace($new_tags, $new_values, $text); } return $text; } /////////////////////////////////////////////////////////////////////////////// // GEDCOM // /////////////////////////////////////////////////////////////////////////////// function gedcomFilename() {return get_gedcom_from_id($this->_ged_id);} function gedcomID() {return $this->_ged_id;} function gedcomTitle() { $trees=WT_Tree::getAll(); return $trees[$this->_ged_id]->tree_title_html; } function _gedcomHead() { $title = ""; $version = ''; $source = ''; $head = WT_GedcomRecord::getInstance('HEAD'); $sour = $head->getFactByType('SOUR'); if ($sour) { $source = $sour->getValue(); $title = $sour->getAttribute('NAME'); $version = $sour->getAttribute('VERS'); } return array($title, $version, $source); } function gedcomCreatedSoftware() { $head=self::_gedcomHead(); return $head[0]; } function gedcomCreatedVersion() { $head=self::_gedcomHead(); // fix broken version string in Family Tree Maker if (strstr($head[1], 'Family Tree Maker ')) { $p=strpos($head[1], '(') + 1; $p2=strpos($head[1], ')'); $head[1]=substr($head[1], $p, ($p2 - $p)); } // Fix EasyTree version if ($head[2]=='EasyTree') { $head[1]=substr($head[1], 1); } return $head[1]; } function gedcomDate() { global $DATE_FORMAT; $head = WT_GedcomRecord::getInstance('HEAD'); $fact = $head->getFactByType('DATE'); if ($fact) { $date=new WT_Date($fact->getValue()); return $date->Display(false, $DATE_FORMAT); // Override $PUBLIC_DATE_FORMAT } return ''; } function gedcomUpdated() { $row= WT_DB::prepare("SELECT SQL_CACHE d_year, d_month, d_day FROM `##dates` WHERE d_julianday1 = ( SELECT max( d_julianday1 ) FROM `##dates` WHERE d_file =? AND d_fact=? ) LIMIT 1") ->execute(array($this->_ged_id, 'CHAN')) ->fetchOneRow(); if ($row) { $date=new WT_Date("{$row->d_day} {$row->d_month} {$row->d_year}"); return $date->Display(false); } else { return self::gedcomDate(); } } function gedcomRootID() { $root = WT_Individual::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); $root = substr($root, 0, stripos($root, "@") ); return $root; } /////////////////////////////////////////////////////////////////////////////// // Totals // /////////////////////////////////////////////////////////////////////////////// function _getPercentage($total, $type) { switch($type) { default: case 'all': $type = $this->_totalIndividuals() + $this->_totalFamilies() + $this->_totalSources(); break; case 'individual': $type = $this->_totalIndividuals(); break; case 'family': $type = $this->_totalFamilies(); break; case 'source': $type = $this->_totalSources(); break; case 'note': $type = $this->_totalNotes(); break; default: return WT_I18N::percentage(0, 1); } if ($type==0) { return WT_I18N::percentage(0, 1); } else { return WT_I18N::percentage($total / $type, 1); } } function totalRecords() { return WT_I18N::number($this->_totalIndividuals() + $this->_totalFamilies() + $this->_totalSources()); } function _totalIndividuals() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##individuals` WHERE i_file=?") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalIndividuals() { return WT_I18N::number($this->_totalIndividuals()); } function _totalIndisWithSources() { $rows=self::_runSQL("SELECT SQL_CACHE COUNT(DISTINCT i_id) AS tot FROM `##link`, `##individuals` WHERE i_id=l_from AND i_file=l_file AND l_file=".$this->_ged_id." AND l_type='SOUR'"); return $rows[0]['tot']; } function totalIndisWithSources() { return WT_I18N::number(self::_totalIndisWithSources()); } function chartIndisWithSources($params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot_indi = $this->_totalIndividuals(); if ($tot_indi==0) { return ''; } else { $tot_sindi_per = round($this->_totalIndisWithSources()/$tot_indi, 3); $chd = self::_array_to_extended_encoding(array(100-100*$tot_sindi_per, 100*$tot_sindi_per)); $chl = WT_I18N::translate('Without sources').' - '.WT_I18N::percentage(1-$tot_sindi_per,1).'|'. WT_I18N::translate('With sources').' - '.WT_I18N::percentage($tot_sindi_per,1); $chart_title = WT_I18N::translate('Individuals with sources'); return ''.$chart_title.''; } } function totalIndividualsPercentage() { return $this->_getPercentage($this->_totalIndividuals(), 'all'); } function _totalFamilies() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##families` WHERE f_file=?") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalFamilies() { return WT_I18N::number($this->_totalFamilies()); } function _totalFamsWithSources() { $rows=self::_runSQL("SELECT SQL_CACHE COUNT(DISTINCT f_id) AS tot FROM `##link`, `##families` WHERE f_id=l_from AND f_file=l_file AND l_file=".$this->_ged_id." AND l_type='SOUR'"); return $rows[0]['tot']; } function totalFamsWithSources() { return WT_I18N::number(self::_totalFamsWithSources()); } function chartFamsWithSources($params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot_fam = $this->_totalFamilies(); if ($tot_fam==0) { return ''; } else { $tot_sfam_per = round($this->_totalFamsWithSources()/$tot_fam, 3); $chd = self::_array_to_extended_encoding(array(100-100*$tot_sfam_per, 100*$tot_sfam_per)); $chl = WT_I18N::translate('Without sources').' - '.WT_I18N::percentage(1-$tot_sfam_per,1).'|'. WT_I18N::translate('With sources').' - '.WT_I18N::percentage($tot_sfam_per,1); $chart_title = WT_I18N::translate('Families with sources'); return "\"".$chart_title."\""; } } function totalFamiliesPercentage() { return $this->_getPercentage($this->_totalFamilies(), 'all'); } function _totalSources() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##sources` WHERE s_file=?") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalSources() { return WT_I18N::number($this->_totalSources()); } function totalSourcesPercentage() { return $this->_getPercentage($this->_totalSources(), 'all'); } function _totalNotes() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##other` WHERE o_type='NOTE' AND o_file=?") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalNotes() { return WT_I18N::number($this->_totalNotes()); } function totalNotesPercentage() { return $this->_getPercentage($this->_totalNotes(), 'all'); } function _totalRepositories() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##other` WHERE o_type='REPO' AND o_file=?") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalRepositories() { return WT_I18N::number($this->_totalRepositories()); } function totalRepositoriesPercentage() { return $this->_getPercentage($this->_totalRepositories(), 'all'); } function totalSurnames($params = null) { if ($params) { $qs=implode(',', array_fill(0, count($params), '?')); $opt="IN ({$qs})"; $vars=$params; $distinct=''; } else { $opt ="IS NOT NULL"; $vars=''; $distinct='DISTINCT'; } $vars[]=$this->_ged_id; $total= WT_DB::prepare( "SELECT SQL_CACHE COUNT({$distinct} n_surn COLLATE '".WT_I18N::$collation."')". " FROM `##name`". " WHERE n_surn COLLATE '".WT_I18N::$collation."' {$opt} AND n_file=?") ->execute($vars) ->fetchOne(); return WT_I18N::number($total); } function totalGivennames($params = null) { if ($params) { $qs=implode(',', array_fill(0, count($params), '?')); $opt="IN ({$qs})"; $vars=$params; $distinct=''; } else { $opt ="IS NOT NULL"; $vars=''; $distinct='DISTINCT'; } $vars[]=$this->_ged_id; $total= WT_DB::prepare("SELECT SQL_CACHE COUNT({$distinct} n_givn) FROM `##name` WHERE n_givn {$opt} AND n_file=?") ->execute($vars) ->fetchOne(); return WT_I18N::number($total); } function totalEvents($params = null) { $sql="SELECT SQL_CACHE COUNT(*) AS tot FROM `##dates` WHERE d_file=?"; $vars=array($this->_ged_id); $no_types=array('HEAD', 'CHAN'); if ($params) { $types=array(); foreach ($params as $type) { if (substr($type, 0, 1)=='!') { $no_types[]=substr($type, 1); } else { $types[]=$type; } } if ($types) { $sql.=' AND d_fact IN ('.implode(', ', array_fill(0, count($types), '?')).')'; $vars=array_merge($vars, $types); } } $sql.=' AND d_fact NOT IN ('.implode(', ', array_fill(0, count($no_types), '?')).')'; $vars=array_merge($vars, $no_types); return WT_I18N::number(WT_DB::prepare($sql)->execute($vars)->fetchOne()); } function totalEventsBirth() { return $this->totalEvents(explode('|',WT_EVENTS_BIRT)); } function totalBirths() { return $this->totalEvents(array('BIRT')); } function totalEventsDeath() { return $this->totalEvents(explode('|',WT_EVENTS_DEAT)); } function totalDeaths() { return $this->totalEvents(array('DEAT')); } function totalEventsMarriage() { return $this->totalEvents(explode('|',WT_EVENTS_MARR)); } function totalMarriages() { return $this->totalEvents(array('MARR')); } function totalEventsDivorce() { return $this->totalEvents(explode('|',WT_EVENTS_DIV)); } function totalDivorces() { return $this->totalEvents(array('DIV')); } function totalEventsOther() { $facts = array_merge(explode('|', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT)); $no_facts = array(); foreach ($facts as $fact) { $fact = '!'.str_replace('\'', '', $fact); $no_facts[] = $fact; } return $this->totalEvents($no_facts); } function _totalSexMales() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##individuals` WHERE i_file=? AND i_sex=?") ->execute(array($this->_ged_id, 'M')) ->fetchOne(); } function totalSexMales() { return WT_I18N::number($this->_totalSexMales()); } function totalSexMalesPercentage() { return $this->_getPercentage($this->_totalSexMales(), 'individual'); } function _totalSexFemales() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##individuals` WHERE i_file=? AND i_sex=?") ->execute(array($this->_ged_id, 'F')) ->fetchOne(); } function totalSexFemales() { return WT_I18N::number($this->_totalSexFemales()); } function totalSexFemalesPercentage() { return $this->_getPercentage($this->_totalSexFemales(), 'individual'); } function _totalSexUnknown() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##individuals` WHERE i_file=? AND i_sex=?") ->execute(array($this->_ged_id, 'U')) ->fetchOne(); } function totalSexUnknown() { return WT_I18N::number($this->_totalSexUnknown()); } function totalSexUnknownPercentage() { return $this->_getPercentage($this->_totalSexUnknown(), 'individual'); } function chartSex($params=null) { global $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_female = strtolower($params[1]);} else {$color_female = 'ffd1dc';} if (isset($params[2]) && $params[2] != '') {$color_male = strtolower($params[2]);} else {$color_male = '84beff';} if (isset($params[3]) && $params[3] != '') {$color_unknown = strtolower($params[3]);} else {$color_unknown = '777777';} $sizes = explode('x', $size); // Raw data - for calculation $tot_f = $this->_totalSexFemales(); $tot_m = $this->_totalSexMales(); $tot_u = $this->_totalSexUnknown(); $tot=$tot_f+$tot_m+$tot_u; // I18N data - for display $per_f = $this->totalSexFemalesPercentage(); $per_m = $this->totalSexMalesPercentage(); $per_u = $this->totalSexUnknownPercentage(); if ($tot==0) { return ''; } else if ($tot_u > 0) { $chd = self::_array_to_extended_encoding(array(4095*$tot_u/$tot, 4095*$tot_f/$tot, 4095*$tot_m/$tot)); $chl = WT_I18N::translate_c('unknown people', 'Unknown').' - '.$per_u.'|'. WT_I18N::translate('Females').' - '.$per_f.'|'. WT_I18N::translate('Males').' - '.$per_m; $chart_title = WT_I18N::translate('Males').' - '.$per_m.WT_I18N::$list_separator. WT_I18N::translate('Females').' - '.$per_f.WT_I18N::$list_separator. WT_I18N::translate_c('unknown people', 'Unknown').' - '.$per_u; return "\"".$chart_title."\""; } else { $chd = self::_array_to_extended_encoding(array(4095*$tot_f/$tot, 4095*$tot_m/$tot)); $chl = WT_I18N::translate('Females').' - '.$per_f.'|'. WT_I18N::translate('Males').' - '.$per_m; $chart_title = WT_I18N::translate('Males').' - '.$per_m.WT_I18N::$list_separator. WT_I18N::translate('Females').' - '.$per_f; return "\"".$chart_title."\""; } } // The totalLiving/totalDeceased queries assume that every dead person will // have a DEAT record. It will not include individuals who were born more // than MAX_ALIVE_AGE years ago, and who have no DEAT record. // A good reason to run the “Add missing DEAT records” batch-update! // However, SQL cannot provide the same logic used by Person::isDead(). function _totalLiving() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##individuals` WHERE i_file=? AND i_gedcom NOT REGEXP '\\n1 (".WT_EVENTS_DEAT.")'") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalLiving() { return WT_I18N::number($this->_totalLiving()); } function totalLivingPercentage() { return $this->_getPercentage($this->_totalLiving(), 'individual'); } function _totalDeceased() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##individuals` WHERE i_file=? AND i_gedcom REGEXP '\\n1 (".WT_EVENTS_DEAT.")'") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalDeceased() { return WT_I18N::number($this->_totalDeceased()); } function totalDeceasedPercentage() { return $this->_getPercentage($this->_totalDeceased(), 'individual'); } function chartMortality($params=null) { global $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_living = strtolower($params[1]);} else {$color_living = 'ffffff';} if (isset($params[2]) && $params[2] != '') {$color_dead = strtolower($params[2]);} else {$color_dead = 'cccccc';} $sizes = explode('x', $size); // Raw data - for calculation $tot_l = $this->_totalLiving(); $tot_d = $this->_totalDeceased(); $tot=$tot_l+$tot_d; // I18N data - for display $per_l = $this->totalLivingPercentage(); $per_d = $this->totalDeceasedPercentage(); if ($tot==0) { return ''; } else { $chd = self::_array_to_extended_encoding(array(4095*$tot_l/$tot, 4095*$tot_d/$tot)); $chl = WT_I18N::translate('Living').' - '.$per_l.'|'. WT_I18N::translate('Dead').' - '.$per_d.'|'; $chart_title = WT_I18N::translate('Living').' - '.$per_l.WT_I18N::$list_separator. WT_I18N::translate('Dead').' - '.$per_d; return "\"".$chart_title."\""; } } static function totalUsers($params=null) { if (!empty($params[0])) { $total=get_user_count() + (int)$params[0]; } else { $total=get_user_count(); } return WT_I18N::number($total); } static function totalAdmins() { return WT_I18N::number(get_admin_user_count()); } static function totalNonAdmins() { return WT_I18N::number(get_non_admin_user_count()); } function _totalMediaType($type='all') { if (!in_array($type, self::$_media_types) && $type != 'all' && $type != 'unknown') { return 0; } $sql="SELECT SQL_CACHE COUNT(*) AS tot FROM `##media` WHERE m_file=?"; $vars=array($this->_ged_id); if ($type != 'all') { if ($type=='unknown') { // There has to be a better way then this :( foreach (self::$_media_types as $t) { $sql.=" AND (m_gedcom NOT LIKE ? AND m_gedcom NOT LIKE ?)"; $vars[]="%3 TYPE {$t}%"; $vars[]="%1 _TYPE {$t}%"; } } else { $sql.=" AND (m_gedcom LIKE ? OR m_gedcom LIKE ?)"; $vars[]="%3 TYPE {$type}%"; $vars[]="%1 _TYPE {$type}%"; } } return WT_DB::prepare($sql)->execute($vars)->fetchOne(); } function totalMedia() {return WT_I18N::number($this->_totalMediaType('all'));} function totalMediaAudio() {return WT_I18N::number($this->_totalMediaType('audio'));} function totalMediaBook() {return WT_I18N::number($this->_totalMediaType('book'));} function totalMediaCard() {return WT_I18N::number($this->_totalMediaType('card'));} function totalMediaCertificate() {return WT_I18N::number($this->_totalMediaType('certificate'));} function totalMediaCoatOfArms() {return WT_I18N::number($this->_totalMediaType('coat'));} function totalMediaDocument() {return WT_I18N::number($this->_totalMediaType('document'));} function totalMediaElectronic() {return WT_I18N::number($this->_totalMediaType('electronic'));} function totalMediaMagazine() {return WT_I18N::number($this->_totalMediaType('magazine'));} function totalMediaManuscript() {return WT_I18N::number($this->_totalMediaType('manuscript'));} function totalMediaMap() {return WT_I18N::number($this->_totalMediaType('map'));} function totalMediaFiche() {return WT_I18N::number($this->_totalMediaType('fiche'));} function totalMediaFilm() {return WT_I18N::number($this->_totalMediaType('film'));} function totalMediaNewspaper() {return WT_I18N::number($this->_totalMediaType('newspaper'));} function totalMediaPainting() {return WT_I18N::number($this->_totalMediaType('painting'));} function totalMediaPhoto() {return WT_I18N::number($this->_totalMediaType('photo'));} function totalMediaTombstone() {return WT_I18N::number($this->_totalMediaType('tombstone'));} function totalMediaVideo() {return WT_I18N::number($this->_totalMediaType('video'));} function totalMediaOther() {return WT_I18N::number($this->_totalMediaType('other'));} function totalMediaUnknown() {return WT_I18N::number($this->_totalMediaType('unknown'));} function chartMedia($params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot = $this->_totalMediaType('all'); // Beware divide by zero if ($tot==0) return WT_I18N::translate('None'); // Build a table listing only the media types actually present in the GEDCOM $mediaCounts = array(); $mediaTypes = ""; $chart_title = ""; $c = 0; $max = 0; $media=array(); foreach (self::$_media_types as $type) { $count = $this->_totalMediaType($type); if ($count>0) { $media[$type] = $count; if ($count > $max) { $max = $count; } $c += $count; } } $count = $this->_totalMediaType('unknown'); if ($count>0) { $media['unknown'] = $tot-$c; if ($tot-$c > $max) { $max = $count; } } if (($max/$tot)>0.6 && count($media)>10) { arsort($media); $media = array_slice($media, 0, 10); $c = $tot; foreach ($media as $cm) { $c -= $cm; } if (isset($media['other'])) { $media['other'] += $c; } else { $media['other'] = $c; } } asort($media); foreach ($media as $type=>$count) { $mediaCounts[] = round(100 * $count / $tot, 0); $mediaTypes .= WT_Gedcom_Tag::getFileFormTypeValue($type).' - '.WT_I18N::number($count).'|'; $chart_title .= WT_Gedcom_Tag::getFileFormTypeValue($type).' ('.$count.'), '; } $chart_title = substr($chart_title,0,-2); $chd = self::_array_to_extended_encoding($mediaCounts); $chl = substr($mediaTypes,0,-1); return "\"".$chart_title."\""; } /////////////////////////////////////////////////////////////////////////////// // Birth & Death // /////////////////////////////////////////////////////////////////////////////// function _mortalityQuery($type='full', $life_dir='ASC', $birth_death='BIRT') { global $listDir; if ($birth_death == 'MARR') { $query_field = "'MARR'"; } else if ($birth_death == 'DIV') { $query_field = "'DIV'"; } else if ($birth_death == 'BIRT') { $query_field = "'BIRT'"; } else { $birth_death = 'DEAT'; $query_field = "'DEAT'"; } if ($life_dir == 'ASC') { $dmod = 'MIN'; } else { $dmod = 'MAX'; $life_dir = 'DESC'; } $rows=self::_runSQL( "SELECT SQL_CACHE d_year, d_type, d_fact, d_gid". " FROM `##dates`". " WHERE d_file={$this->_ged_id} AND d_fact IN ({$query_field}) AND d_julianday1=(". " SELECT {$dmod}( d_julianday1 )". " FROM `##dates`". " WHERE d_file={$this->_ged_id} AND d_fact IN ({$query_field}) AND d_julianday1<>0 )". " LIMIT 1" ); if (!isset($rows[0])) {return '';} $row=$rows[0]; $record=WT_GedcomRecord::getInstance($row['d_gid']); switch($type) { default: case 'full': if ($record->canShow()) { $result=$record->format_list('span', false, $record->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); } break; case 'year': $date=new WT_Date($row['d_type'].' '.$row['d_year']); $result=$date->Display(true); break; case 'name': $result="getHtmlUrl()."\">".$record->getFullName().""; break; case 'place': $fact=WT_GedcomRecord::getInstance($row['d_gid'])->getFactByType($row['d_fact']); if ($fact) { $result=format_fact_place($fact, true, true, true); } else { $result=WT_I18N::translate('Private'); } break; } return $result; } function _statsPlaces($what='ALL', $fact=false, $parent=0, $country=false) { if ($fact) { if ($what=='INDI') { $rows= WT_DB::prepare("SELECT i_gedcom AS ged FROM `##individuals` WHERE i_file=?") ->execute(array($this->_ged_id)) ->fetchAll(); } else if ($what=='FAM') { $rows= WT_DB::prepare("SELECT f_gedcom AS ged FROM `##families` WHERE f_file=?") ->execute(array($this->_ged_id)) ->fetchAll(); } $placelist = array(); foreach ($rows as $row) { if (preg_match('/\n1 {$fact}(?:\n[2-9].*)*\n2 PLAC (.+)}/', $row->ged, $match)) { if ($country) { $tmp=explode(WT_Place::GEDCOM_SEPARATOR, $match[1]); $place = end($tmp); } else { $place = $match[1]; } if (!isset($placelist[$place])) { $placelist[$place] = 1; } else { $placelist[$place] ++; } } } return $placelist; } // used by placehierarchy googlemap module else if ($parent>0) { if ($what=='INDI') { $join = " JOIN `##individuals` ON pl_file = i_file AND pl_gid = i_id"; } else if ($what=='FAM') { $join = " JOIN `##families` ON pl_file = f_file AND pl_gid = f_id"; } else { $join = ""; } $rows=self::_runSQL( " SELECT SQL_CACHE". " p_place AS place,". " COUNT(*) AS tot". " FROM". " `##places`". " JOIN `##placelinks` ON pl_file=p_file AND p_id=pl_p_id". $join. " WHERE". " p_id={$parent} AND". " p_file={$this->_ged_id}". " GROUP BY place" ); if (!isset($rows[0])) {return '';} return $rows; } else { if ($what=='INDI') { $join = " JOIN `##individuals` ON pl_file = i_file AND pl_gid = i_id"; } else if ($what=='FAM') { $join = " JOIN `##families` ON pl_file = f_file AND pl_gid = f_id"; } else { $join = ""; } $rows=self::_runSQL( " SELECT SQL_CACHE". " p_place AS country,". " COUNT(*) AS tot". " FROM". " `##places`". " JOIN `##placelinks` ON pl_file=p_file AND p_id=pl_p_id". $join. " WHERE". " p_file={$this->_ged_id}". " AND p_parent_id='0'". " GROUP BY country ORDER BY tot DESC, country ASC" ); if (!isset($rows[0])) {return '';} return $rows; } } function _totalPlaces() { return WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##places` WHERE p_file=?") ->execute(array($this->_ged_id)) ->fetchOne(); } function totalPlaces() { return WT_I18n::number($this->_totalPlaces()); } function chartDistribution($params = null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_CHART_COLOR3, $WT_STATS_MAP_X, $WT_STATS_MAP_Y; if ($params !== null && isset($params[0])) {$chart_shows = $params[0];} else {$chart_shows='world';} if ($params !== null && isset($params[1])) {$chart_type = $params[1];} else {$chart_type='';} if ($params !== null && isset($params[2])) {$surname = $params[2];} else {$surname='';} if ($this->_totalPlaces()==0) { return ''; } // Get the country names for each language $country_to_iso3166=array(); foreach (WT_I18N::installed_languages() as $code=>$lang) { WT_I18N::init($code); $countries=self::get_all_countries(); foreach (self::iso3166() as $three=>$two) { $country_to_iso3166[$three]=$two; $country_to_iso3166[$countries[$three]]=$two; } } WT_I18N::init(WT_LOCALE); switch ($chart_type) { case 'surname_distribution_chart': if ($surname=="") $surname = $this->getCommonSurname(); $chart_title=WT_I18N::translate('Surname distribution chart').': '.$surname; // Count how many people are events in each country $surn_countries=array(); $indis = WT_Query_Name::individuals(utf8_strtoupper($surname), '', '', false, false, WT_GED_ID); foreach ($indis as $person) { if (preg_match_all('/^2 PLAC (?:.*, *)*(.*)/m', $person->getGedcom(), $matches)) { // webtrees uses 3 letter country codes and localised country names, but google uses 2 letter codes. foreach ($matches[1] as $country) { $country=trim($country); if (array_key_exists($country, $country_to_iso3166)) { if (array_key_exists($country_to_iso3166[$country], $surn_countries)) { $surn_countries[$country_to_iso3166[$country]]++; } else { $surn_countries[$country_to_iso3166[$country]]=1; } } } } }; break; case 'birth_distribution_chart': $chart_title=WT_I18N::translate('Birth by country'); // Count how many people were born in each country $surn_countries=array(); $b_countries=$this->_statsPlaces('INDI', 'BIRT', 0, true); foreach ($b_countries as $place=>$count) { $country=$place; if (array_key_exists($country, $country_to_iso3166)) { if (!isset($surn_countries[$country_to_iso3166[$country]])) { $surn_countries[$country_to_iso3166[$country]]=$count; } else { $surn_countries[$country_to_iso3166[$country]]+=$count; } } } break; case 'death_distribution_chart': $chart_title=WT_I18N::translate('Death by country'); // Count how many people were death in each country $surn_countries=array(); $d_countries=$this->_statsPlaces('INDI', 'DEAT', 0, true); foreach ($d_countries as $place=>$count) { $country=$place; if (array_key_exists($country, $country_to_iso3166)) { if (!isset($surn_countries[$country_to_iso3166[$country]])) { $surn_countries[$country_to_iso3166[$country]]=$count; } else { $surn_countries[$country_to_iso3166[$country]]+=$count; } } } break; case 'marriage_distribution_chart': $chart_title=WT_I18N::translate('Marriage by country'); // Count how many families got marriage in each country $surn_countries=array(); $m_countries=$this->_statsPlaces('FAM'); // webtrees uses 3 letter country codes and localised country names, but google uses 2 letter codes. foreach ($m_countries as $place) { $country=trim($place['country']); if (!isset($surn_countries[$country_to_iso3166[$country]])) { $surn_countries[$country_to_iso3166[$country]]=$place['tot']; } else { $surn_countries[$country_to_iso3166[$country]]+=$place['tot']; } } break; case 'indi_distribution_chart': default: $chart_title=WT_I18N::translate('Individual distribution chart'); // Count how many people are events in each country $surn_countries=array(); $a_countries=$this->_statsPlaces('INDI'); // webtrees uses 3 letter country codes and localised country names, but google uses 2 letter codes. foreach ($a_countries as $place) { $country=trim($place['country']); if (array_key_exists($country, $country_to_iso3166)) { if (!isset($surn_countries[$country_to_iso3166[$country]])) { $surn_countries[$country_to_iso3166[$country]]=$place['tot']; } else { $surn_countries[$country_to_iso3166[$country]]+=$place['tot']; } } } break; } $chart_url ="https://chart.googleapis.com/chart?cht=t&chtm=".$chart_shows; $chart_url.="&chco=".$WT_STATS_CHART_COLOR1.",".$WT_STATS_CHART_COLOR3.",".$WT_STATS_CHART_COLOR2; // country colours $chart_url.="&chf=bg,s,ECF5FF"; // sea colour $chart_url.="&chs=".$WT_STATS_MAP_X."x".$WT_STATS_MAP_Y; $chart_url.="&chld=".implode('', array_keys($surn_countries))."&chd=s:"; foreach ($surn_countries as $count) { $chart_url.=substr(WT_GOOGLE_CHART_ENCODING, (int)($count/max($surn_countries)*61), 1); } $chart = '
'; $chart .= ''.$chart_title.'

'; $chart .= '
'.$chart_title.'
'; $chart .= ''; $chart .= ''; $chart .= ''; $chart .= ''; $chart .= '
'.WT_I18N::translate('Highest population').'  '.WT_I18N::translate('Lowest population').'  '.WT_I18N::translate('Nobody at all').'  
'; return $chart; } function commonCountriesList() { $countries = $this->_statsPlaces(); if (!is_array($countries)) return ''; $top10 = array(); $i = 1; // Get the country names for each language $country_names=array(); foreach (WT_I18N::installed_languages() as $code=>$lang) { WT_I18N::init($code); $all_countries = self::get_all_countries(); foreach ($all_countries as $country_code=>$country_name) { $country_names[$country_name]=$country_code; } } WT_I18N::init(WT_LOCALE); $all_db_countries=array(); foreach ($countries as $place) { $country=trim($place['country']); if (array_key_exists($country, $country_names)) { if (!isset($all_db_countries[$country_names[$country]][$country])) { $all_db_countries[$country_names[$country]][$country]=$place['tot']; } else { $all_db_countries[$country_names[$country]][$country]+=$place['tot']; } } } // get all the user’s countries names $all_countries = self::get_all_countries(); foreach ($all_db_countries as $country_code=>$country) { $top10[]='
  • '; foreach ($country as $country_name=>$tot) { $tmp=new WT_Place($country_name, $this->_ged_id); $place = ''.$all_countries[$country_code].''; $top10[].=$place.' - '.WT_I18N::number($tot); } $top10[].='
  • '; if ($i++==10) break; } $top10=join('', $top10); return ''; } function commonBirthPlacesList() { $places = $this->_statsPlaces('INDI', 'BIRT'); $top10 = array(); $i = 1; arsort($places); foreach ($places as $place=>$count) { $tmp=new WT_Place($place, $this->_ged_id); $place = '' . $tmp->getFullName() . ''; $top10[]='
  • '.$place.' - '.WT_I18N::number($count).'
  • '; if ($i++==10) break; } $top10=join('', $top10); return ''; } function commonDeathPlacesList() { $places = $this->_statsPlaces('INDI', 'DEAT'); $top10 = array(); $i = 1; arsort($places); foreach ($places as $place=>$count) { $tmp=new WT_Place($place, $this->_ged_id); $place = '' . $tmp->getFullName() . ''; $top10[]='
  • '.$place.' - '.WT_I18N::number($count).'
  • '; if ($i++==10) break; } $top10=join('', $top10); return ''; } function commonMarriagePlacesList() { $places = $this->_statsPlaces('FAM', 'MARR'); $top10 = array(); $i = 1; arsort($places); foreach ($places as $place=>$count) { $tmp=new WT_Place($place, $this->_ged_id); $place = '' . $tmp->getFullName() . ''; $top10[]='
  • '.$place.' - '.WT_I18N::number($count).'
  • '; if ($i++==10) break; } $top10=join('', $top10); return ''; } function _statsBirth($simple=true, $sex=false, $year1=-1, $year2=-1, $params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($simple) { $sql = "SELECT SQL_CACHE FLOOR(d_year/100+1) AS century, COUNT(*) AS total FROM `##dates` ". "WHERE ". "d_file={$this->_ged_id} AND ". "d_year<>0 AND ". "d_fact='BIRT' AND ". "d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; } else if ($sex) { $sql = "SELECT SQL_CACHE d_month, i_sex, COUNT(*) AS total FROM `##dates` ". "JOIN `##individuals` ON d_file = i_file AND d_gid = i_id ". "WHERE ". "d_file={$this->_ged_id} AND ". "d_fact='BIRT' AND ". "d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; } else { $sql = "SELECT SQL_CACHE d_month, COUNT(*) AS total FROM `##dates` ". "WHERE ". "d_file={$this->_ged_id} AND ". "d_fact='BIRT' AND ". "d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; } if ($year1>=0 && $year2>=0) { $sql .= " AND d_year BETWEEN '{$year1}' AND '{$year2}'"; } if ($simple) { $sql .= " GROUP BY century ORDER BY century"; } else { $sql .= " GROUP BY d_month"; if ($sex) $sql .= ", i_sex"; } $rows=self::_runSQL($sql); if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot = 0; foreach ($rows as $values) { $tot += $values['total']; } // Beware divide by zero if ($tot==0) return ''; $centuries = ""; foreach ($rows as $values) { $counts[] = round(100 * $values['total'] / $tot, 0); $centuries .= self::_centuryName($values['century']).' - '.WT_I18N::number($values['total']).'|'; } $chd = self::_array_to_extended_encoding($counts); $chl = rawurlencode(substr($centuries,0,-1)); return "\"".WT_I18N::translate('Births"; } if (!isset($rows)) return 0; return $rows; } function _statsDeath($simple=true, $sex=false, $year1=-1, $year2=-1, $params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($simple) { $sql = "SELECT SQL_CACHE FLOOR(d_year/100+1) AS century, COUNT(*) AS total FROM `##dates` ". "WHERE ". "d_file={$this->_ged_id} AND ". 'd_year<>0 AND '. "d_fact='DEAT' AND ". "d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; } else if ($sex) { $sql = "SELECT SQL_CACHE d_month, i_sex, COUNT(*) AS total FROM `##dates` ". "JOIN `##individuals` ON d_file = i_file AND d_gid = i_id ". "WHERE ". "d_file={$this->_ged_id} AND ". "d_fact='DEAT' AND ". "d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; } else { $sql = "SELECT SQL_CACHE d_month, COUNT(*) AS total FROM `##dates` ". "WHERE ". "d_file={$this->_ged_id} AND ". "d_fact='DEAT' AND ". "d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; } if ($year1>=0 && $year2>=0) { $sql .= " AND d_year BETWEEN '{$year1}' AND '{$year2}'"; } if ($simple) { $sql .= " GROUP BY century ORDER BY century"; } else { $sql .= " GROUP BY d_month"; if ($sex) $sql .= ", i_sex"; } $rows=self::_runSQL($sql); if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot = 0; foreach ($rows as $values) { $tot += $values['total']; } // Beware divide by zero if ($tot==0) return ''; $centuries = ""; foreach ($rows as $values) { $counts[] = round(100 * $values['total'] / $tot, 0); $centuries .= self::_centuryName($values['century']).' - '.WT_I18N::number($values['total']).'|'; } $chd = self::_array_to_extended_encoding($counts); $chl = rawurlencode(substr($centuries,0,-1)); return "\"".WT_I18N::translate('Deaths"; } if (!isset($rows)) {return 0;} return $rows; } // // Birth // function firstBirth() { return $this->_mortalityQuery('full', 'ASC', 'BIRT'); } function firstBirthYear() { return $this->_mortalityQuery('year', 'ASC', 'BIRT'); } function firstBirthName() { return $this->_mortalityQuery('name', 'ASC', 'BIRT'); } function firstBirthPlace() { return $this->_mortalityQuery('place', 'ASC', 'BIRT'); } function lastBirth() { return $this->_mortalityQuery('full', 'DESC', 'BIRT'); } function lastBirthYear() { return $this->_mortalityQuery('year', 'DESC', 'BIRT'); } function lastBirthName() { return $this->_mortalityQuery('name', 'DESC', 'BIRT'); } function lastBirthPlace() { return $this->_mortalityQuery('place', 'DESC', 'BIRT'); } function statsBirth($params=null) {return $this->_statsBirth(true, false, -1, -1, $params);} // // Death // function firstDeath() { return $this->_mortalityQuery('full', 'ASC', 'DEAT'); } function firstDeathYear() { return $this->_mortalityQuery('year', 'ASC', 'DEAT'); } function firstDeathName() { return $this->_mortalityQuery('name', 'ASC', 'DEAT'); } function firstDeathPlace() { return $this->_mortalityQuery('place', 'ASC', 'DEAT'); } function lastDeath() { return $this->_mortalityQuery('full', 'DESC', 'DEAT'); } function lastDeathYear() { return $this->_mortalityQuery('year', 'DESC', 'DEAT'); } function lastDeathName() { return $this->_mortalityQuery('name', 'DESC', 'DEAT'); } function lastDeathPlace() { return $this->_mortalityQuery('place', 'DESC', 'DEAT'); } function statsDeath($params=null) { return $this->_statsDeath(true, false, -1, -1, $params); } /////////////////////////////////////////////////////////////////////////////// // Lifespan // /////////////////////////////////////////////////////////////////////////////// function _longlifeQuery($type='full', $sex='F') { global $listDir; $sex_search = ' 1=1'; if ($sex == 'F') { $sex_search = " i_sex='F'"; } elseif ($sex == 'M') { $sex_search = " i_sex='M'"; } $rows=self::_runSQL( " SELECT SQL_CACHE". " death.d_gid AS id,". " death.d_julianday2-birth.d_julianday1 AS age". " FROM". " `##dates` AS death,". " `##dates` AS birth,". " `##individuals` AS indi". " WHERE". " indi.i_id=birth.d_gid AND". " birth.d_gid=death.d_gid AND". " death.d_file={$this->_ged_id} AND". " birth.d_file=death.d_file AND". " birth.d_file=indi.i_file AND". " birth.d_fact='BIRT' AND". " death.d_fact='DEAT' AND". " birth.d_julianday1<>0 AND". " death.d_julianday1>birth.d_julianday2 AND". $sex_search. " ORDER BY". " age DESC LIMIT 1" ); if (!isset($rows[0])) {return '';} $row = $rows[0]; $person=WT_Individual::getInstance($row['id']); switch($type) { default: case 'full': if ($person->canShowName()) { $result=$person->format_list('span', false, $person->getFullName()); } else { $result= WT_I18N::translate('This information is private and cannot be shown.'); } break; case 'age': $result=WT_I18N::number((int)($row['age']/365.25)); break; case 'name': $result="getHtmlUrl()."\">".$person->getFullName().""; break; } return $result; } function _topTenOldest($type='list', $sex='BOTH', $params=null) { global $TEXT_DIRECTION; if ($sex == 'F') { $sex_search = " AND i_sex='F' "; } elseif ($sex == 'M') { $sex_search = " AND i_sex='M' "; } else { $sex_search = ''; } if ($params !== null && isset($params[0])) {$total = $params[0];} else {$total = 10;} $total=(int)$total; $rows=self::_runSQL( "SELECT SQL_CACHE ". " MAX(death.d_julianday2-birth.d_julianday1) AS age, ". " death.d_gid AS deathdate ". "FROM ". " `##dates` AS death, ". " `##dates` AS birth, ". " `##individuals` AS indi ". "WHERE ". " indi.i_id=birth.d_gid AND ". " birth.d_gid=death.d_gid AND ". " death.d_file={$this->_ged_id} AND ". " birth.d_file=death.d_file AND ". " birth.d_file=indi.i_file AND ". " birth.d_fact='BIRT' AND ". " death.d_fact='DEAT' AND ". " birth.d_julianday1<>0 AND ". " death.d_julianday1>birth.d_julianday2 ". $sex_search. "GROUP BY deathdate ". "ORDER BY age DESC ". "LIMIT ".$total ); if (!isset($rows[0])) {return '';} $top10 = array(); foreach ($rows as $row) { $person = WT_Individual::getInstance($row['deathdate']); $age = $row['age']; if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $age = get_age_at_event($age, true); if ($person->canShow()) { if ($type == 'list') { $top10[]="
  • getHtmlUrl()."\">".$person->getFullName()." (".$age.")"."
  • "; } else { $top10[]="getHtmlUrl()."\">".$person->getFullName()." (".$age.")"; } } } if ($type == 'list') { $top10=join('', $top10); } else { $top10=join(' ', $top10); } if ($TEXT_DIRECTION=='rtl') { $top10=str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function _topTenOldestAlive($type='list', $sex='BOTH', $params=null) { global $TEXT_DIRECTION; if (!WT_USER_CAN_ACCESS) return WT_I18N::translate('This information is private and cannot be shown.'); if ($sex == 'F') { $sex_search = " AND i_sex='F'"; } elseif ($sex == 'M') { $sex_search = " AND i_sex='M'"; } else { $sex_search = ''; } if ($params !== null && isset($params[0])) {$total = $params[0];} else {$total = 10;} $total=(int)$total; $rows=self::_runSQL( "SELECT SQL_CACHE". " birth.d_gid AS id,". " MIN(birth.d_julianday1) AS age". " FROM". " `##dates` AS birth,". " `##individuals` AS indi". " WHERE". " indi.i_id=birth.d_gid AND". " indi.i_gedcom NOT REGEXP '\\n1 (".WT_EVENTS_DEAT.")' AND". " birth.d_file={$this->_ged_id} AND". " birth.d_fact='BIRT' AND". " birth.d_file=indi.i_file AND". " birth.d_julianday1<>0". $sex_search. " GROUP BY id". " ORDER BY age". " ASC LIMIT ".$total ); if (!isset($rows)) {return 0;} $top10 = array(); foreach ($rows as $row) { $person=WT_Individual::getInstance($row['id']); $age = (WT_CLIENT_JD-$row['age']); if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $age = get_age_at_event($age, true); if ($type == 'list') { $top10[]="
  • getHtmlUrl()."\">".$person->getFullName()." (".$age.")"."
  • "; } else { $top10[]="getHtmlUrl()."\">".$person->getFullName()." (".$age.")"; } } if ($type == 'list') { $top10=join('', $top10); } else { $top10=join(';  ', $top10); } if ($TEXT_DIRECTION=='rtl') { $top10=str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function _averageLifespanQuery($sex='BOTH', $show_years=false) { if ($sex == 'F') { $sex_search = " AND i_sex='F' "; } elseif ($sex == 'M') { $sex_search = " AND i_sex='M' "; } else { $sex_search = ''; } $rows=self::_runSQL( "SELECT SQL_CACHE ". " AVG(death.d_julianday2-birth.d_julianday1) AS age ". "FROM ". " `##dates` AS death, ". " `##dates` AS birth, ". " `##individuals` AS indi ". "WHERE ". " indi.i_id=birth.d_gid AND ". " birth.d_gid=death.d_gid AND ". " death.d_file=".$this->_ged_id. " AND ". " birth.d_file=death.d_file AND ". " birth.d_file=indi.i_file AND ". " birth.d_fact='BIRT' AND ". " death.d_fact='DEAT' AND ". " birth.d_julianday1<>0 AND ". " death.d_julianday1>birth.d_julianday2 ". $sex_search ); if (!isset($rows[0])) {return '';} $row = $rows[0]; $age = $row['age']; if ($show_years) { if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else if (!empty($age)) { $age = $age.'d'; } return get_age_at_event($age, true); } else { return WT_I18N::number($age/365.25); } } function _statsAge($simple=true, $related='BIRT', $sex='BOTH', $year1=-1, $year2=-1, $params=null) { if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = '230x250';} $sizes = explode('x', $size); $rows=self::_runSQL( "SELECT SQL_CACHE". " ROUND(AVG(death.d_julianday2-birth.d_julianday1)/365.25,1) AS age,". " FLOOR(death.d_year/100+1) AS century,". " i_sex AS sex". " FROM". " `##dates` AS death,". " `##dates` AS birth,". " `##individuals` AS indi". " WHERE". " indi.i_id=birth.d_gid AND". " birth.d_gid=death.d_gid AND". " death.d_file={$this->_ged_id} AND". " birth.d_file=death.d_file AND". " birth.d_file=indi.i_file AND". " birth.d_fact='BIRT' AND". " death.d_fact='DEAT' AND". " birth.d_julianday1<>0 AND". " birth.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND". " death.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND". " death.d_julianday1>birth.d_julianday2". " GROUP BY century, sex ORDER BY century, sex"); if (empty($rows)) return ''; $chxl = '0:|'; $countsm = ''; $countsf = ''; $countsa = ''; foreach ($rows as $values) { $out[$values['century']][$values['sex']]=$values['age']; } foreach ($out as $century=>$values) { if ($sizes[0]<980) $sizes[0] += 50; $chxl .= self::_centuryName($century).'|'; $average = 0; if (isset($values['F'])) { $countsf .= $values['F'].','; $average = $values['F']; } else { $countsf .= '0,'; } if (isset($values['M'])) { $countsm .= $values['M'].','; if ($average==0) $countsa .= $values['M'].','; else $countsa .= (($values['M']+$average)/2).','; } else { $countsm .= '0,'; if ($average==0) $countsa .= '0,'; else $countsa .= $values['F'].','; } } $countsm = substr($countsm,0,-1); $countsf = substr($countsf,0,-1); $countsa = substr($countsa,0,-1); $chd = 't2:'.$countsm.'|'.$countsf.'|'.$countsa; $decades=''; for ($i=0; $i<=100; $i+=10) { $decades.='|'.WT_I18N::number($i); } $chxl .= '1:||'.WT_I18N::translate('century').'|2:'.$decades.'|3:||'.WT_I18N::translate('Age').'|'; $title = WT_I18N::translate('Average age related to death century'); if (count($rows)>6 || utf8_strlen($title)<30) { $chtt = $title; } else { $offset = 0; $counter = array(); while ($offset = strpos($title, ' ', $offset + 1)) { $counter[] = $offset; } $half = (int)(count($counter)/2); $chtt = substr_replace($title, '|', $counter[$half], 1); } return '\"".WT_I18N::translate('Average"; } else { $sex_search = ''; $years = ''; if ($sex == 'F') { $sex_search = " AND i_sex='F'"; } elseif ($sex == 'M') { $sex_search = " AND i_sex='M'"; } if ($year1>=0 && $year2>=0) { if ($related=='BIRT') { $years = " AND birth.d_year BETWEEN '{$year1}' AND '{$year2}'"; } else if ($related=='DEAT') { $years = " AND death.d_year BETWEEN '{$year1}' AND '{$year2}'"; } } $rows=self::_runSQL( "SELECT SQL_CACHE". " death.d_julianday2-birth.d_julianday1 AS age". " FROM". " `##dates` AS death,". " `##dates` AS birth,". " `##individuals` AS indi". " WHERE". " indi.i_id=birth.d_gid AND". " birth.d_gid=death.d_gid AND". " death.d_file={$this->_ged_id} AND". " birth.d_file=death.d_file AND". " birth.d_file=indi.i_file AND". " birth.d_fact='BIRT' AND". " death.d_fact='DEAT' AND". " birth.d_julianday1<>0 AND". " death.d_julianday1>birth.d_julianday2". $years. $sex_search. " ORDER BY age DESC"); if (!isset($rows)) {return 0;} return $rows; } } // Both Sexes function statsAge($params=null) {return $this->_statsAge(true, 'BIRT', 'BOTH', -1, -1, $params);} function longestLife() { return $this->_longlifeQuery('full', 'BOTH'); } function longestLifeAge() { return $this->_longlifeQuery('age', 'BOTH'); } function longestLifeName() { return $this->_longlifeQuery('name', 'BOTH'); } function topTenOldest($params=null) { return $this->_topTenOldest('nolist', 'BOTH', $params); } function topTenOldestList($params=null) { return $this->_topTenOldest('list', 'BOTH', $params); } function topTenOldestAlive($params=null) { return $this->_topTenOldestAlive('nolist', 'BOTH', $params); } function topTenOldestListAlive($params=null) { return $this->_topTenOldestAlive('list', 'BOTH', $params); } function averageLifespan($show_years=false) { return $this->_averageLifespanQuery('BOTH', $show_years); } // Female Only function longestLifeFemale() { return $this->_longlifeQuery('full', 'F'); } function longestLifeFemaleAge() { return $this->_longlifeQuery('age', 'F'); } function longestLifeFemaleName() { return $this->_longlifeQuery('name', 'F'); } function topTenOldestFemale($params=null) { return $this->_topTenOldest('nolist', 'F', $params); } function topTenOldestFemaleList($params=null) { return $this->_topTenOldest('list', 'F', $params); } function topTenOldestFemaleAlive($params=null) { return $this->_topTenOldestAlive('nolist', 'F', $params); } function topTenOldestFemaleListAlive($params=null) { return $this->_topTenOldestAlive('list', 'F', $params); } function averageLifespanFemale($show_years=false) { return $this->_averageLifespanQuery('F', $show_years); } // Male Only function longestLifeMale() { return $this->_longlifeQuery('full', 'M'); } function longestLifeMaleAge() { return $this->_longlifeQuery('age', 'M'); } function longestLifeMaleName() { return $this->_longlifeQuery('name', 'M'); } function topTenOldestMale($params=null) { return $this->_topTenOldest('nolist', 'M', $params); } function topTenOldestMaleList($params=null) { return $this->_topTenOldest('list', 'M', $params); } function topTenOldestMaleAlive($params=null) { return $this->_topTenOldestAlive('nolist', 'M', $params); } function topTenOldestMaleListAlive($params=null) { return $this->_topTenOldestAlive('list', 'M', $params); } function averageLifespanMale($show_years=false) {return $this->_averageLifespanQuery('M', $show_years);} /////////////////////////////////////////////////////////////////////////////// // Events // /////////////////////////////////////////////////////////////////////////////// function _eventQuery($type, $direction, $facts) { global $listDir; $eventTypes = array( 'BIRT'=>WT_I18N::translate('birth'), 'DEAT'=>WT_I18N::translate('death'), 'MARR'=>WT_I18N::translate('marriage'), 'ADOP'=>WT_I18N::translate('adoption'), 'BURI'=>WT_I18N::translate('burial'), 'CENS'=>WT_I18N::translate('census added') ); $fact_query = "IN ('".str_replace('|', "','", $facts)."')"; if ($direction != 'ASC') {$direction = 'DESC';} $rows=self::_runSQL('' .' SELECT SQL_CACHE' .' d_gid AS id,' .' d_year AS year,' .' d_fact AS fact,' .' d_type AS type' .' FROM' ." `##dates`" .' WHERE' ." d_file={$this->_ged_id} AND" ." d_gid<>'HEAD' AND" ." d_fact {$fact_query} AND" .' d_julianday1<>0' .' ORDER BY' ." d_julianday1 {$direction}, d_type LIMIT 1" ); if (!isset($rows[0])) {return '';} $row=$rows[0]; $record=WT_GedcomRecord::getInstance($row['id']); switch($type) { default: case 'full': if ($record->canShow()) { $result=$record->format_list('span', false, $record->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); } break; case 'year': $date=new WT_Date($row['type'].' '.$row['year']); $result=$date->Display(true); break; case 'type': if (isset($eventTypes[$row['fact']])) { $result=$eventTypes[$row['fact']]; } else { $result=WT_Gedcom_Tag::getLabel($row['fact']); } break; case 'name': $result="getHtmlUrl()."\">".$record->getFullName().""; break; case 'place': $fact=$record->getFactByType($row['fact']); if ($fact) { $result=format_fact_place($fact, true, true, true); } else { $result=WT_I18N::translate('Private'); } break; } return $result; } function firstEvent() { return $this->_eventQuery('full', 'ASC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function firstEventYear() { return $this->_eventQuery('year', 'ASC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function firstEventType() { return $this->_eventQuery('type', 'ASC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function firstEventName() { return $this->_eventQuery('name', 'ASC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function firstEventPlace() { return $this->_eventQuery('place', 'ASC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function lastEvent() { return $this->_eventQuery('full', 'DESC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function lastEventYear() { return $this->_eventQuery('year', 'DESC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function lastEventType() { return $this->_eventQuery('type', 'DESC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function lastEventName() { return $this->_eventQuery('name', 'DESC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } function lastEventPlace() { return $this->_eventQuery('place', 'DESC', WT_EVENTS_BIRT.'|'.WT_EVENTS_MARR.'|'.WT_EVENTS_DIV.'|'.WT_EVENTS_DEAT); } /////////////////////////////////////////////////////////////////////////////// // Marriage // /////////////////////////////////////////////////////////////////////////////// /* * Query the database for marriage tags. */ function _marriageQuery($type='full', $age_dir='ASC', $sex='F', $show_years=false) { if ($sex == 'F') {$sex_field = 'f_wife';} else {$sex_field = 'f_husb';} if ($age_dir != 'ASC') {$age_dir = 'DESC';} $rows=self::_runSQL( " SELECT SQL_CACHE fam.f_id AS famid, fam.{$sex_field}, married.d_julianday2-birth.d_julianday1 AS age, indi.i_id AS i_id". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS birth ON birth.d_file = {$this->_ged_id}". " LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}". " LEFT JOIN `##individuals` AS indi ON indi.i_file = {$this->_ged_id}". " WHERE". " birth.d_gid = indi.i_id AND". " married.d_gid = fam.f_id AND". " indi.i_id = fam.{$sex_field} AND". " fam.f_file = {$this->_ged_id} AND". " birth.d_fact = 'BIRT' AND". " married.d_fact = 'MARR' AND". " birth.d_julianday1 <> 0 AND". " married.d_julianday2 > birth.d_julianday1 AND". " i_sex='{$sex}'". " ORDER BY". " married.d_julianday2-birth.d_julianday1 {$age_dir} LIMIT 1" ); if (!isset($rows[0])) {return '';} $row=$rows[0]; if (isset($row['famid'])) $family=WT_Family::getInstance($row['famid']); if (isset($row['i_id'])) $person=WT_Individual::getInstance($row['i_id']); switch($type) { default: case 'full': if ($family->canShow()) { $result=$family->format_list('span', false, $person->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); } break; case 'name': $result=''.$person->getFullName().''; break; case 'age': $age = $row['age']; if ($show_years) { if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $result = get_age_at_event($age, true); } else { $result = (int)($age/365.25); } break; } return $result; } function _ageOfMarriageQuery($type='list', $age_dir='ASC', $params=null) { global $TEXT_DIRECTION; if ($params !== null && isset($params[0])) {$total = $params[0];} else {$total = 10;} if ($age_dir != 'ASC') {$age_dir = 'DESC';} $hrows=self::_runSQL( " SELECT SQL_CACHE DISTINCT fam.f_id AS family, MIN(husbdeath.d_julianday2-married.d_julianday1) AS age". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}". " LEFT JOIN `##dates` AS husbdeath ON husbdeath.d_file = {$this->_ged_id}". " WHERE". " fam.f_file = {$this->_ged_id} AND". " husbdeath.d_gid = fam.f_husb AND". " husbdeath.d_fact = 'DEAT' AND". " married.d_gid = fam.f_id AND". " married.d_fact = 'MARR' AND". " married.d_julianday1 < husbdeath.d_julianday2 AND". " married.d_julianday1 <> 0". " GROUP BY family". " ORDER BY age {$age_dir}"); $wrows=self::_runSQL( " SELECT SQL_CACHE DISTINCT fam.f_id AS family, MIN(wifedeath.d_julianday2-married.d_julianday1) AS age". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}". " LEFT JOIN `##dates` AS wifedeath ON wifedeath.d_file = {$this->_ged_id}". " WHERE". " fam.f_file = {$this->_ged_id} AND". " wifedeath.d_gid = fam.f_wife AND". " wifedeath.d_fact = 'DEAT' AND". " married.d_gid = fam.f_id AND". " married.d_fact = 'MARR' AND". " married.d_julianday1 < wifedeath.d_julianday2 AND". " married.d_julianday1 <> 0". " GROUP BY family". " ORDER BY age {$age_dir}"); $drows=self::_runSQL( " SELECT SQL_CACHE DISTINCT fam.f_id AS family, MIN(divorced.d_julianday2-married.d_julianday1) AS age". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}". " LEFT JOIN `##dates` AS divorced ON divorced.d_file = {$this->_ged_id}". " WHERE". " fam.f_file = {$this->_ged_id} AND". " married.d_gid = fam.f_id AND". " married.d_fact = 'MARR' AND". " divorced.d_gid = fam.f_id AND". " divorced.d_fact IN ('DIV', 'ANUL', '_SEPR', '_DETS') AND". " married.d_julianday1 < divorced.d_julianday2 AND". " married.d_julianday1 <> 0". " GROUP BY family". " ORDER BY age {$age_dir}"); if (!isset($hrows) && !isset($wrows) && !isset($drows)) {return 0;} $rows = array(); foreach ($drows as $family) { $rows[$family['family']] = $family['age']; } foreach ($hrows as $family) { if (!isset($rows[$family['family']])) $rows[$family['family']] = $family['age']; } foreach ($wrows as $family) { if (!isset($rows[$family['family']])) { $rows[$family['family']] = $family['age']; } elseif ($rows[$family['family']] > $family['age']) { $rows[$family['family']] = $family['age']; } } if ($age_dir == 'DESC') {arsort($rows);} else {asort($rows);} $top10 = array(); $i = 0; foreach ($rows as $fam=>$age) { $family = WT_Family::getInstance($fam); if ($type == 'name') { return $family->format_list('span', false, $family->getFullName()); } if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $age = get_age_at_event($age, true); if ($type == 'age') { return $age; } $husb = $family->getHusband(); $wife = $family->getWife(); if (($husb->getAllDeathDates() && $wife->getAllDeathDates()) || !$husb->isDead() || !$wife->isDead()) { if ($family->canShow()) { if ($type == 'list') { $top10[] = "
  • getHtmlUrl()."\">".$family->getFullName()." (".$age.")"."
  • "; } else { $top10[] = "getHtmlUrl()."\">".$family->getFullName()." (".$age.")"; } } if (++$i==$total) break; } } if ($type == 'list') { $top10=join('', $top10); } else { $top10 = join(';  ', $top10); } if ($TEXT_DIRECTION == 'rtl') { $top10 = str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function _ageBetweenSpousesQuery($type='list', $age_dir='DESC', $params=null) { global $TEXT_DIRECTION; if ($params !== null && isset($params[0])) {$total = $params[0];} else {$total = 10;} if ($age_dir=='DESC') { $query1 = ' MIN(wifebirth.d_julianday2-husbbirth.d_julianday1) AS age'; $query2 = ' wifebirth.d_julianday2 >= husbbirth.d_julianday1 AND husbbirth.d_julianday1 <> 0'; } else { $query1 = ' MIN(husbbirth.d_julianday2-wifebirth.d_julianday1) AS age'; $query2 = ' wifebirth.d_julianday1 < husbbirth.d_julianday2 AND wifebirth.d_julianday1 <> 0'; } $total=(int)$total; $rows=self::_runSQL( " SELECT SQL_CACHE fam.f_id AS family," .$query1. " FROM `##families` AS fam". " LEFT JOIN `##dates` AS wifebirth ON wifebirth.d_file = {$this->_ged_id}". " LEFT JOIN `##dates` AS husbbirth ON husbbirth.d_file = {$this->_ged_id}". " WHERE". " fam.f_file = {$this->_ged_id} AND". " husbbirth.d_gid = fam.f_husb AND". " husbbirth.d_fact = 'BIRT' AND". " wifebirth.d_gid = fam.f_wife AND". " wifebirth.d_fact = 'BIRT' AND". $query2. " GROUP BY family". " ORDER BY age DESC LIMIT ".$total ); if (!isset($rows[0])) {return '';} $top10 = array(); foreach ($rows as $fam) { $family=WT_Family::getInstance($fam['family']); if ($fam['age']<0) break; $age = $fam['age']; if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $age = get_age_at_event($age, true); if ($family->canShow()) { if ($type == 'list') { $top10[] = "
  • getHtmlUrl()."\">".$family->getFullName()." (".$age.")"."
  • "; } else { $top10[] = "getHtmlUrl()."\">".$family->getFullName()." (".$age.")"; } } } if ($type == 'list') { $top10=join('', $top10); } else { $top10 = join(';  ', $top10); } if ($TEXT_DIRECTION == 'rtl') { $top10 = str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function _parentsQuery($type='full', $age_dir='ASC', $sex='F', $show_years=false) { if ($sex == 'F') {$sex_field = 'WIFE';} else {$sex_field = 'HUSB';} if ($age_dir != 'ASC') {$age_dir = 'DESC';} $rows=self::_runSQL( " SELECT SQL_CACHE". " parentfamily.l_to AS id,". " childbirth.d_julianday2-birth.d_julianday1 AS age". " FROM `##link` AS parentfamily". " JOIN `##link` AS childfamily ON childfamily.l_file = {$this->_ged_id}". " JOIN `##dates` AS birth ON birth.d_file = {$this->_ged_id}". " JOIN `##dates` AS childbirth ON childbirth.d_file = {$this->_ged_id}". " WHERE". " birth.d_gid = parentfamily.l_to AND". " childfamily.l_to = childbirth.d_gid AND". " childfamily.l_type = 'CHIL' AND". " parentfamily.l_type = '{$sex_field}' AND". " childfamily.l_from = parentfamily.l_from AND". " parentfamily.l_file = {$this->_ged_id} AND". " birth.d_fact = 'BIRT' AND". " childbirth.d_fact = 'BIRT' AND". " birth.d_julianday1 <> 0 AND". " childbirth.d_julianday2 > birth.d_julianday1". " ORDER BY age {$age_dir} LIMIT 1" ); if (!isset($rows[0])) {return '';} $row=$rows[0]; if (isset($row['id'])) $person=WT_Individual::getInstance($row['id']); switch($type) { default: case 'full': if ($person->canShow()) { $result=$person->format_list('span', false, $person->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); } break; case 'name': $result=''.$person->getFullName().''; break; case 'age': $age = $row['age']; if ($show_years) { if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $result = get_age_at_event($age, true); } else { $result = (int)($age/365.25); } break; } return $result; } function _statsMarr($simple=true, $first=false, $year1=-1, $year2=-1, $params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($simple) { $sql = "SELECT SQL_CACHE FLOOR(d_year/100+1) AS century, COUNT(*) AS total". " FROM `##dates`". " WHERE d_file={$this->_ged_id} AND d_year<>0 AND d_fact='MARR' AND d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; if ($year1>=0 && $year2>=0) { $sql .= " AND d_year BETWEEN '{$year1}' AND '{$year2}'"; } $sql .= " GROUP BY century ORDER BY century"; } else if ($first) { $years = ''; if ($year1>=0 && $year2>=0) { $years = " married.d_year BETWEEN '{$year1}' AND '{$year2}' AND"; } $sql= " SELECT SQL_CACHE fam.f_id AS fams, fam.f_husb, fam.f_wife, married.d_julianday2 AS age, married.d_month AS month, indi.i_id AS indi". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}". " LEFT JOIN `##individuals` AS indi ON indi.i_file = {$this->_ged_id}". " WHERE". " married.d_gid = fam.f_id AND". " fam.f_file = {$this->_ged_id} AND". " married.d_fact = 'MARR' AND". " married.d_julianday2 <> 0 AND". $years. " (indi.i_id = fam.f_husb OR indi.i_id = fam.f_wife)". " ORDER BY fams, indi, age ASC"; } else { $sql = "SELECT SQL_CACHE d_month, COUNT(*) AS total". " FROM `##dates`". " WHERE d_file={$this->_ged_id} AND d_fact='MARR'"; if ($year1>=0 && $year2>=0) { $sql .= " AND d_year BETWEEN '{$year1}' AND '{$year2}'"; } $sql .= " GROUP BY d_month"; } $rows=self::_runSQL($sql); if (!isset($rows)) {return 0;} if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot = 0; foreach ($rows as $values) { $tot += $values['total']; } // Beware divide by zero if ($tot==0) return ''; $centuries = ""; $counts=array(); foreach ($rows as $values) { $counts[] = round(100 * $values['total'] / $tot, 0); $centuries .= self::_centuryName($values['century']).' - '.WT_I18N::number($values['total']).'|'; } $chd = self::_array_to_extended_encoding($counts); $chl = substr($centuries,0,-1); return "\"".WT_I18N::translate('Marriages"; } return $rows; } function _statsDiv($simple=true, $first=false, $year1=-1, $year2=-1, $params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($simple) { $sql = "SELECT SQL_CACHE FLOOR(d_year/100+1) AS century, COUNT(*) AS total". " FROM `##dates`". " WHERE d_file={$this->_ged_id} AND d_year<>0 AND d_fact = 'DIV' AND d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')"; if ($year1>=0 && $year2>=0) { $sql .= " AND d_year BETWEEN '{$year1}' AND '{$year2}'"; } $sql .= " GROUP BY century ORDER BY century"; } else if ($first) { $years = ''; if ($year1>=0 && $year2>=0) { $years = " divorced.d_year BETWEEN '{$year1}' AND '{$year2}' AND"; } $sql= " SELECT SQL_CACHE fam.f_id AS fams, fam.f_husb, fam.f_wife, divorced.d_julianday2 AS age, divorced.d_month AS month, indi.i_id AS indi". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS divorced ON divorced.d_file = {$this->_ged_id}". " LEFT JOIN `##individuals` AS indi ON indi.i_file = {$this->_ged_id}". " WHERE". " divorced.d_gid = fam.f_id AND". " fam.f_file = {$this->_ged_id} AND". " divorced.d_fact = 'DIV' AND". " divorced.d_julianday2 <> 0 AND". $years. " (indi.i_id = fam.f_husb OR indi.i_id = fam.f_wife)". " ORDER BY fams, indi, age ASC"; } else { $sql = "SELECT SQL_CACHE d_month, COUNT(*) AS total FROM `##dates` ". "WHERE d_file={$this->_ged_id} AND d_fact = 'DIV'"; if ($year1>=0 && $year2>=0) { $sql .= " AND d_year BETWEEN '{$year1}' AND '{$year2}'"; } $sql .= " GROUP BY d_month"; } $rows=self::_runSQL($sql); if (!isset($rows)) {return 0;} if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot = 0; foreach ($rows as $values) { $tot += $values['total']; } // Beware divide by zero if ($tot==0) return ''; $centuries = ""; $counts=array(); foreach ($rows as $values) { $counts[] = round(100 * $values['total'] / $tot, 0); $centuries .= self::_centuryName($values['century']).' - '.WT_I18N::number($values['total']).'|'; } $chd = self::_array_to_extended_encoding($counts); $chl = substr($centuries,0,-1); return "\"".WT_I18N::translate('Divorces"; } return $rows; } // // Marriage // function firstMarriage() { return $this->_mortalityQuery('full', 'ASC', 'MARR'); } function firstMarriageYear() { return $this->_mortalityQuery('year', 'ASC', 'MARR'); } function firstMarriageName() { return $this->_mortalityQuery('name', 'ASC', 'MARR'); } function firstMarriagePlace() { return $this->_mortalityQuery('place', 'ASC', 'MARR'); } function lastMarriage() { return $this->_mortalityQuery('full', 'DESC', 'MARR'); } function lastMarriageYear() { return $this->_mortalityQuery('year', 'DESC', 'MARR'); } function lastMarriageName() { return $this->_mortalityQuery('name', 'DESC', 'MARR'); } function lastMarriagePlace() { return $this->_mortalityQuery('place', 'DESC', 'MARR'); } function statsMarr($params=null) {return $this->_statsMarr(true, false, -1, -1, $params);} // // Divorce // function firstDivorce() { return $this->_mortalityQuery('full', 'ASC', 'DIV'); } function firstDivorceYear() { return $this->_mortalityQuery('year', 'ASC', 'DIV'); } function firstDivorceName() { return $this->_mortalityQuery('name', 'ASC', 'DIV'); } function firstDivorcePlace() { return $this->_mortalityQuery('place', 'ASC', 'DIV'); } function lastDivorce() { return $this->_mortalityQuery('full', 'DESC', 'DIV'); } function lastDivorceYear() { return $this->_mortalityQuery('year', 'DESC', 'DIV'); } function lastDivorceName() { return $this->_mortalityQuery('name', 'DESC', 'DIV'); } function lastDivorcePlace() { return $this->_mortalityQuery('place', 'DESC', 'DIV'); } function statsDiv($params=null) {return $this->_statsDiv(true, false, -1, -1, $params);} function _statsMarrAge($simple=true, $sex='M', $year1=-1, $year2=-1, $params=null) { if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = '200x250';} $sizes = explode('x', $size); $rows=self::_runSQL( "SELECT SQL_CACHE ". " ROUND(AVG(married.d_julianday2-birth.d_julianday1-182.5)/365.25,1) AS age, ". " FLOOR(married.d_year/100+1) AS century, ". " 'M' AS sex ". "FROM `##dates` AS married ". "JOIN `##families` AS fam ON (married.d_gid=fam.f_id AND married.d_file=fam.f_file) ". "JOIN `##dates` AS birth ON (birth.d_gid=fam.f_husb AND birth.d_file=fam.f_file) ". "WHERE ". " '{$sex}' IN ('M', 'BOTH') AND ". " married.d_file={$this->_ged_id} AND married.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND married.d_fact='MARR' AND ". " birth.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND birth.d_fact='BIRT' AND ". " married.d_julianday1>birth.d_julianday1 AND birth.d_julianday1<>0 ". "GROUP BY century, sex ". "UNION ALL ". "SELECT ". " ROUND(AVG(married.d_julianday2-birth.d_julianday1-182.5)/365.25,1) AS age, ". " FLOOR(married.d_year/100+1) AS century, ". " 'F' AS sex ". "FROM `##dates` AS married ". "JOIN `##families` AS fam ON (married.d_gid=fam.f_id AND married.d_file=fam.f_file) ". "JOIN `##dates` AS birth ON (birth.d_gid=fam.f_wife AND birth.d_file=fam.f_file) ". "WHERE ". " '{$sex}' IN ('F', 'BOTH') AND ". " married.d_file={$this->_ged_id} AND married.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND married.d_fact='MARR' AND ". " birth.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND birth.d_fact='BIRT' AND ". " married.d_julianday1>birth.d_julianday1 AND birth.d_julianday1<>0 ". " GROUP BY century, sex ORDER BY century" ); if (empty($rows)) return''; $max = 0; foreach ($rows as $values) { if ($max<$values['age']) $max = $values['age']; } $chxl = '0:|'; $chmm = ''; $chmf = ''; $i = 0; $countsm = ''; $countsf = ''; $countsa = ''; foreach ($rows as $values) { $out[$values['century']][$values['sex']]=$values['age']; } foreach ($out as $century=>$values) { if ($sizes[0]<1000) $sizes[0] += 50; $chxl .= self::_centuryName($century).'|'; $average = 0; if (isset($values['F'])) { if ($max<=50) $value = $values['F']*2; else $value = $values['F']; $countsf .= $value.','; $average = $value; $chmf .= 't'.$values['F'].',000000,1,'.$i.',11,1|'; } else { $countsf .= '0,'; $chmf .= 't0,000000,1,'.$i.',11,1|'; } if (isset($values['M'])) { if ($max<=50) $value = $values['M']*2; else $value = $values['M']; $countsm .= $value.','; if ($average==0) $countsa .= $value.','; else $countsa .= (($value+$average)/2).','; $chmm .= 't'.$values['M'].',000000,0,'.$i.',11,1|'; } else { $countsm .= '0,'; if ($average==0) $countsa .= '0,'; else $countsa .= $value.','; $chmm .= 't0,000000,0,'.$i.',11,1|'; } $i++; } $countsm = substr($countsm,0,-1); $countsf = substr($countsf,0,-1); $countsa = substr($countsa,0,-1); $chmf = substr($chmf,0,-1); $chd = 't2:'.$countsm.'|'.$countsf.'|'.$countsa; if ($max<=50) $chxl .= '1:||'.WT_I18N::translate('century').'|2:|0|10|20|30|40|50|3:||'.WT_I18N::translate('Age').'|'; else $chxl .= '1:||'.WT_I18N::translate('century').'|2:|0|10|20|30|40|50|60|70|80|90|100|3:||'.WT_I18N::translate('Age').'|'; if (count($rows)>4 || utf8_strlen(WT_I18N::translate('Average age in century of marriage'))<30) { $chtt = WT_I18N::translate('Average age in century of marriage'); } else { $offset = 0; $counter = array(); while ($offset = strpos(WT_I18N::translate('Average age in century of marriage'), ' ', $offset + 1)) { $counter[] = $offset; } $half = (int)(count($counter)/2); $chtt = substr_replace(WT_I18N::translate('Average age in century of marriage'), '|', $counter[$half], 1); } return "\"".WT_I18N::translate('Average"; } else { if ($year1>=0 && $year2>=0) { $years=" married.d_year BETWEEN {$year1} AND {$year2} AND "; } else { $years=''; } $rows=self::_runSQL( "SELECT SQL_CACHE ". " fam.f_id, ". " birth.d_gid, ". " married.d_julianday2-birth.d_julianday1 AS age ". "FROM `##dates` AS married ". "JOIN `##families` AS fam ON (married.d_gid=fam.f_id AND married.d_file=fam.f_file) ". "JOIN `##dates` AS birth ON (birth.d_gid=fam.f_husb AND birth.d_file=fam.f_file) ". "WHERE ". " '{$sex}' IN ('M', 'BOTH') AND {$years} ". " married.d_file={$this->_ged_id} AND married.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND married.d_fact='MARR' AND ". " birth.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND birth.d_fact='BIRT' AND ". " married.d_julianday1>birth.d_julianday1 AND birth.d_julianday1<>0 ". "UNION ALL ". "SELECT ". " ROUND(AVG(married.d_julianday2-birth.d_julianday1-182.5)/365.25,1) AS age, ". " FLOOR(married.d_year/100+1) AS century, ". " 'F' AS sex ". "FROM `##dates` AS married ". "JOIN `##families` AS fam ON (married.d_gid=fam.f_id AND married.d_file=fam.f_file) ". "JOIN `##dates` AS birth ON (birth.d_gid=fam.f_wife AND birth.d_file=fam.f_file) ". "WHERE ". " '{$sex}' IN ('F', 'BOTH') AND {$years} ". " married.d_file={$this->_ged_id} AND married.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND married.d_fact='MARR' AND ". " birth.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND birth.d_fact='BIRT' AND ". " married.d_julianday1>birth.d_julianday1 AND birth.d_julianday1<>0 " ); return $rows; } } // // Female only // function youngestMarriageFemale() { return $this->_marriageQuery('full', 'ASC', 'F'); } function youngestMarriageFemaleName() { return $this->_marriageQuery('name', 'ASC', 'F'); } function youngestMarriageFemaleAge($show_years=false) { return $this->_marriageQuery('age', 'ASC', 'F', $show_years); } function oldestMarriageFemale() { return $this->_marriageQuery('full', 'DESC', 'F'); } function oldestMarriageFemaleName() { return $this->_marriageQuery('name', 'DESC', 'F'); } function oldestMarriageFemaleAge($show_years=false) { return $this->_marriageQuery('age', 'DESC', 'F', $show_years); } // // Male only // function youngestMarriageMale() { return $this->_marriageQuery('full', 'ASC', 'M'); } function youngestMarriageMaleName() { return $this->_marriageQuery('name', 'ASC', 'M'); } function youngestMarriageMaleAge($show_years=false) { return $this->_marriageQuery('age', 'ASC', 'M', $show_years); } function oldestMarriageMale() { return $this->_marriageQuery('full', 'DESC', 'M'); } function oldestMarriageMaleName() { return $this->_marriageQuery('name', 'DESC', 'M'); } function oldestMarriageMaleAge($show_years=false) { return $this->_marriageQuery('age', 'DESC', 'M', $show_years); } function statsMarrAge($params=null) { return $this->_statsMarrAge(true, 'BOTH', -1, -1, $params); } function ageBetweenSpousesMF ($params=null) { return $this->_ageBetweenSpousesQuery($type='nolist', $age_dir='DESC', $params=null); } function ageBetweenSpousesMFList($params=null) { return $this->_ageBetweenSpousesQuery($type='list', $age_dir='DESC', $params=null); } function ageBetweenSpousesFM ($params=null) { return $this->_ageBetweenSpousesQuery($type='nolist', $age_dir='ASC', $params=null); } function ageBetweenSpousesFMList($params=null) { return $this->_ageBetweenSpousesQuery($type='list', $age_dir='ASC', $params=null); } function topAgeOfMarriageFamily() { return $this->_ageOfMarriageQuery('name', 'DESC', array('1')); } function topAgeOfMarriage() { return $this->_ageOfMarriageQuery('age', 'DESC', array('1')); } function topAgeOfMarriageFamilies($params=null) { return $this->_ageOfMarriageQuery('nolist', 'DESC', $params); } function topAgeOfMarriageFamiliesList($params=null) { return $this->_ageOfMarriageQuery('list', 'DESC', $params); } function minAgeOfMarriageFamily() { return $this->_ageOfMarriageQuery('name', 'ASC', array('1')); } function minAgeOfMarriage() { return $this->_ageOfMarriageQuery('age', 'ASC', array('1')); } function minAgeOfMarriageFamilies ($params=null) { return $this->_ageOfMarriageQuery('nolist', 'ASC', $params); } function minAgeOfMarriageFamiliesList($params=null) { return $this->_ageOfMarriageQuery('list', 'ASC', $params); } // // Mother only // function youngestMother() { return $this->_parentsQuery('full', 'ASC', 'F'); } function youngestMotherName() { return $this->_parentsQuery('name', 'ASC', 'F'); } function youngestMotherAge($show_years=false) { return $this->_parentsQuery('age', 'ASC', 'F', $show_years); } function oldestMother() { return $this->_parentsQuery('full', 'DESC', 'F'); } function oldestMotherName() { return $this->_parentsQuery('name', 'DESC', 'F'); } function oldestMotherAge($show_years=false) { return $this->_parentsQuery('age', 'DESC', 'F', $show_years); } // // Father only // function youngestFather() { return $this->_parentsQuery('full', 'ASC', 'M'); } function youngestFatherName() { return $this->_parentsQuery('name', 'ASC', 'M'); } function youngestFatherAge($show_years=false) { return $this->_parentsQuery('age', 'ASC', 'M', $show_years); } function oldestFather() { return $this->_parentsQuery('full', 'DESC', 'M'); } function oldestFatherName() { return $this->_parentsQuery('name', 'DESC', 'M'); } function oldestFatherAge($show_years=false) { return $this->_parentsQuery('age', 'DESC', 'M', $show_years); } function totalMarriedMales() { $n=WT_DB::prepare("SELECT SQL_CACHE COUNT(DISTINCT f_husb) FROM `##families` WHERE f_file=? AND f_gedcom LIKE '%\\n1 MARR%'") ->execute(array($this->_ged_id)) ->fetchOne(); return WT_I18N::number($n); } function totalMarriedFemales() { $n=WT_DB::prepare("SELECT SQL_CACHE COUNT(DISTINCT f_wife) FROM `##families` WHERE f_file=? AND f_gedcom LIKE '%\\n1 MARR%'") ->execute(array($this->_ged_id)) ->fetchOne(); return WT_I18N::number($n); } /////////////////////////////////////////////////////////////////////////////// // Family Size // /////////////////////////////////////////////////////////////////////////////// function _familyQuery($type='full') { $rows=self::_runSQL( " SELECT SQL_CACHE f_numchil AS tot, f_id AS id". " FROM `##families`". " WHERE". " f_file={$this->_ged_id}". " AND f_numchil = (". " SELECT max( f_numchil )". " FROM `##families`" . " WHERE f_file ={$this->_ged_id}". " )". " LIMIT 1" ); if (!isset($rows[0])) {return '';} $row = $rows[0]; $family=WT_Family::getInstance($row['id']); switch($type) { default: case 'full': if ($family->canShow()) { $result=$family->format_list('span', false, $family->getFullName()); } else { $result = WT_I18N::translate('This information is private and cannot be shown.'); } break; case 'size': $result=WT_I18N::number($row['tot']); break; case 'name': $result="getHtmlUrl()."\">".$family->getFullName().''; break; } return $result; } function _topTenFamilyQuery($type='list', $params=null) { global $TEXT_DIRECTION; if ($params !== null && isset($params[0])) {$total = $params[0];} else {$total = 10;} $total=(int)$total; $rows=self::_runSQL( "SELECT SQL_CACHE f_numchil AS tot, f_id AS id". " FROM `##families`". " WHERE". " f_file={$this->_ged_id}". " ORDER BY tot DESC". " LIMIT ".$total ); if (!isset($rows[0])) {return '';} if (count($rows) < $total) {$total = count($rows);} $top10 = array(); for ($c = 0; $c < $total; $c++) { $family=WT_Family::getInstance($rows[$c]['id']); if ($family->canShow()) { if ($type == 'list') { $top10[]= '
  • '.$family->getFullName().' - '. WT_I18N::plural('%s child', '%s children', $rows[$c]['tot'], WT_I18N::number($rows[$c]['tot'])); } else { $top10[]= ''.$family->getFullName().' - '. WT_I18N::plural('%s child', '%s children', $rows[$c]['tot'], WT_I18N::number($rows[$c]['tot'])); } } } if ($type == 'list') { $top10=join('', $top10); } else { $top10 = join(';  ', $top10); } if ($TEXT_DIRECTION == 'rtl') { $top10 = str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function _ageBetweenSiblingsQuery($type='list', $params=null) { global $TEXT_DIRECTION; if ($params === null) {$params = array();} if (isset($params[0])) {$total = $params[0];} else {$total = 10;} if (isset($params[1])) {$one = $params[1];} else {$one = false;} // each family only once if true $total=(int)$total; $rows=self::_runSQL( " SELECT SQL_CACHE DISTINCT". " link1.l_from AS family,". " link1.l_to AS ch1,". " link2.l_to AS ch2,". " child1.d_julianday2-child2.d_julianday2 AS age". " FROM `##link` AS link1". " LEFT JOIN `##dates` AS child1 ON child1.d_file = {$this->_ged_id}". " LEFT JOIN `##dates` AS child2 ON child2.d_file = {$this->_ged_id}". " LEFT JOIN `##link` AS link2 ON link2.l_file = {$this->_ged_id}". " WHERE". " link1.l_file = {$this->_ged_id} AND". " link1.l_from = link2.l_from AND". " link1.l_type = 'CHIL' AND". " child1.d_gid = link1.l_to AND". " child1.d_fact = 'BIRT' AND". " link2.l_type = 'CHIL' AND". " child2.d_gid = link2.l_to AND". " child2.d_fact = 'BIRT' AND". " child1.d_julianday2 > child2.d_julianday2 AND". " child2.d_julianday2 <> 0 AND". " child1.d_gid <> child2.d_gid". " ORDER BY age DESC". " LIMIT ".$total ); if (!isset($rows[0])) {return '';} $top10 = array(); if ($one) $dist = array(); foreach ($rows as $fam) { $family = WT_Family::getInstance($fam['family']); $child1 = WT_Individual::getInstance($fam['ch1']); $child2 = WT_Individual::getInstance($fam['ch2']); if ($type == 'name') { if ($child1->canShow() && $child2->canShow()) { $return = ''.$child2->getFullName().' '; $return .= WT_I18N::translate('and').' '; $return .= ''.$child1->getFullName().''; $return .= ' ['.WT_I18N::translate('View Family').']'; } else { $return = WT_I18N::translate('This information is private and cannot be shown.'); } return $return; } $age = $fam['age']; if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; } else if ((int)($age/30.4375)>0) { $age = (int)($age/30.4375).'m'; } else { $age = $age.'d'; } $age = get_age_at_event($age, true); if ($type == 'age') { return $age; } if ($type == 'list') { if ($one && !in_array($fam['family'], $dist)) { if ($child1->canShow() && $child2->canShow()) { $return = "
  • "; $return .= "getHtmlUrl()."\">".$child2->getFullName()." "; $return .= WT_I18N::translate('and')." "; $return .= "getHtmlUrl()."\">".$child1->getFullName().""; $return .= " (".$age.")"; $return .= " getHtmlUrl()."\">[".WT_I18N::translate('View Family')."]"; $return .= '
  • '; $top10[] = $return; $dist[] = $fam['family']; } } else if (!$one && $child1->canShow() && $child2->canShow()) { $return = "
  • "; $return .= "getHtmlUrl()."\">".$child2->getFullName()." "; $return .= WT_I18N::translate('and')." "; $return .= "getHtmlUrl()."\">".$child1->getFullName().""; $return .= " (".$age.")"; $return .= " getHtmlUrl()."\">[".WT_I18N::translate('View Family')."]"; $return .= '
  • '; $top10[] = $return; } } else { if ($child1->canShow() && $child2->canShow()) { $return = $child2->format_list('span', false, $child2->getFullName()); $return .= "
    ".WT_I18N::translate('and')."
    "; $return .= $child1->format_list('span', false, $child1->getFullName()); $return .= "
    getHtmlUrl()."\">[".WT_I18N::translate('View Family')."]"; return $return; } else { return WT_I18N::translate('This information is private and cannot be shown.'); } } } if ($type == 'list') { $top10=join('', $top10); } if ($TEXT_DIRECTION == 'rtl') { $top10 = str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function _monthFirstChildQuery($simple=true, $sex=false, $year1=-1, $year2=-1, $params=null) { global $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y, $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2; if ($params === null) {$params = array();} if (isset($params[0])) {$total = $params[0];} else {$total = 10;} if (isset($params[1])) {$one = $params[1];} else {$one = false;} // each family only once if true $total=(int)$total; if ($year1>=0 && $year2>=0) { $sql_years = " AND (d_year BETWEEN '{$year1}' AND '{$year2}')"; } else { $sql_years = ''; } if ($sex) { $sql_sex1 = ', i_sex'; $sql_sex2 = " JOIN `##individuals` AS child ON child1.d_file = i_file AND child1.d_gid = child.i_id "; } else { $sql_sex1 = ''; $sql_sex2 = ''; } $sql = "SELECT SQL_CACHE d_month{$sql_sex1}, COUNT(*) AS total ". "FROM (". " SELECT family{$sql_sex1}, MIN(date) AS d_date, d_month". " FROM (". " SELECT". " link1.l_from AS family,". " link1.l_to AS child,". " child1.d_julianday2 as date,". " child1.d_month as d_month". $sql_sex1. " FROM `##link` AS link1". " LEFT JOIN `##dates` AS child1 ON child1.d_file = {$this->_ged_id}". $sql_sex2. " WHERE". " link1.l_file = {$this->_ged_id} AND". " link1.l_type = 'CHIL' AND". " child1.d_gid = link1.l_to AND". " child1.d_fact = 'BIRT' AND". " d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND". " child1.d_month <> ''". $sql_years. " ORDER BY date". " ) AS children". " GROUP BY family". ") AS first_child ". "GROUP BY d_month"; if ($sex) $sql .= ', i_sex'; $rows=self::_runSQL($sql); if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X.'x'.$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} $sizes = explode('x', $size); $tot = 0; foreach ($rows as $values) { $tot += $values['total']; } // Beware divide by zero if ($tot==0) return ''; $text = ''; foreach ($rows as $values) { $counts[] = round(100 * $values['total'] / $tot, 0); switch ($values['d_month']) { default: case 'JAN': $values['d_month'] = 1; break; case 'FEB': $values['d_month'] = 2; break; case 'MAR': $values['d_month'] = 3; break; case 'APR': $values['d_month'] = 4; break; case 'MAY': $values['d_month'] = 5; break; case 'JUN': $values['d_month'] = 6; break; case 'JUL': $values['d_month'] = 7; break; case 'AUG': $values['d_month'] = 8; break; case 'SEP': $values['d_month'] = 9; break; case 'OCT': $values['d_month'] = 10; break; case 'NOV': $values['d_month'] = 11; break; case 'DEC': $values['d_month'] = 12; break; } $text .= WT_I18N::translate(ucfirst(strtolower(($values['d_month'])))).' - '.$values['total'].'|'; } $chd = self::_array_to_extended_encoding($counts); $chl = substr($text,0,-1); return ''.WT_I18N::translate('Month of birth of first child in a relation').''; } if (!isset($rows)) return 0; return $rows; } function largestFamily() { return $this->_familyQuery('full'); } function largestFamilySize() { return $this->_familyQuery('size'); } function largestFamilyName() { return $this->_familyQuery('name'); } function topTenLargestFamily ($params=null) { return $this->_topTenFamilyQuery('nolist', $params); } function topTenLargestFamilyList($params=null) { return $this->_topTenFamilyQuery('list', $params); } function chartLargestFamilies($params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_L_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_L_CHART_X.'x'.$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} if (isset($params[3]) && $params[3] != '') {$total = strtolower($params[3]);} else {$total = 10;} $sizes = explode('x', $size); $total=(int)$total; $rows=self::_runSQL( " SELECT SQL_CACHE f_numchil AS tot, f_id AS id". " FROM `##families`". " WHERE f_file={$this->_ged_id}". " ORDER BY tot DESC". " LIMIT ".$total ); if (!isset($rows[0])) {return '';} $tot = 0; foreach ($rows as $row) {$tot += $row['tot'];} $chd = ''; $chl = array(); foreach ($rows as $row) { $family=WT_Family::getInstance($row['id']); if ($family->canShow()) { if ($tot==0) { $per = 0; } else { $per = round(100 * $row['tot'] / $tot, 0); } $chd .= self::_array_to_extended_encoding(array($per)); $chl[] = htmlspecialchars_decode(strip_tags($family->getFullName())).' - '.WT_I18N::number($row['tot']); } } $chl = rawurlencode(join('|', $chl)); return "\"".WT_I18N::translate('Largest"; } function totalChildren() { $rows=self::_runSQL("SELECT SQL_CACHE SUM(f_numchil) AS tot FROM `##families` WHERE f_file={$this->_ged_id}"); $row=$rows[0]; return WT_I18N::number($row['tot']); } function averageChildren() { $rows=self::_runSQL("SELECT SQL_CACHE AVG(f_numchil) AS tot FROM `##families` WHERE f_file={$this->_ged_id}"); $row=$rows[0]; return WT_I18N::number($row['tot'], 2); } function _statsChildren($simple=true, $sex='BOTH', $year1=-1, $year2=-1, $params=null) { if ($simple) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = '220x200';} $sizes = explode('x', $size); $max = 0; $rows=self::_runSQL( " SELECT SQL_CACHE ROUND(AVG(f_numchil),2) AS num, FLOOR(married.d_year/100+1) AS century". " FROM `##families` AS fam". " LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}". " WHERE". " married.d_gid = fam.f_id AND". " fam.f_file = {$this->_ged_id} AND". " married.d_fact = 'MARR' AND". " married.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')". " GROUP BY century". " ORDER BY century"); if (empty($rows)) return ''; foreach ($rows as $values) { if ($max<$values['num']) $max = $values['num']; } $chm = ""; $chxl = "0:|"; $i = 0; $counts=array(); foreach ($rows as $values) { if ($sizes[0]<980) $sizes[0] += 38; $chxl .= self::_centuryName($values['century'])."|"; if ($max<=5) $counts[] = round($values['num']*819.2-1, 1); else $counts[] = round($values['num']*409.6, 1); $chm .= 't'.$values['num'].',000000,0,'.$i.',11,1|'; $i++; } $chd = self::_array_to_extended_encoding($counts); $chm = substr($chm,0,-1); if ($max<=5) $chxl .= "1:||".WT_I18N::translate('century')."|2:|0|1|2|3|4|5|3:||".WT_I18N::translate('Number of children')."|"; else $chxl .= "1:||".WT_I18N::translate('century')."|2:|0|1|2|3|4|5|6|7|8|9|10|3:||".WT_I18N::translate('Number of children')."|"; return "\"".WT_I18N::translate('Average"; } else { if ($sex=='M') { $sql = "SELECT SQL_CACHE num, COUNT(*) AS total FROM ". "(SELECT count(i_sex) AS num FROM `##link` ". "LEFT OUTER JOIN `##individuals` ". "ON l_from=i_id AND l_file=i_file AND i_sex='M' AND l_type='FAMC' ". "JOIN `##families` ON f_file=l_file AND f_id=l_to WHERE f_file={$this->_ged_id} GROUP BY l_to". ") boys". " GROUP BY num". " ORDER BY num"; } elseif ($sex=='F') { $sql = "SELECT SQL_CACHE num, COUNT(*) AS total FROM ". "(SELECT count(i_sex) AS num FROM `##link` ". "LEFT OUTER JOIN `##individuals` ". "ON l_from=i_id AND l_file=i_file AND i_sex='F' AND l_type='FAMC' ". "JOIN `##families` ON f_file=l_file AND f_id=l_to WHERE f_file={$this->_ged_id} GROUP BY l_to". ") girls". " GROUP BY num". " ORDER BY num"; } else { $sql = "SELECT SQL_CACHE f_numchil, COUNT(*) AS total FROM `##families` "; if ($year1>=0 && $year2>=0) { $sql .= "AS fam LEFT JOIN `##dates` AS married ON married.d_file = {$this->_ged_id}" ." WHERE" ." married.d_gid = fam.f_id AND" ." fam.f_file = {$this->_ged_id} AND" ." married.d_fact = 'MARR' AND" ." married.d_year BETWEEN '{$year1}' AND '{$year2}'"; } else { $sql .="WHERE f_file={$this->_ged_id}"; } $sql .= " GROUP BY f_numchil"; } $rows=self::_runSQL($sql); if (!isset($rows)) {return 0;} return $rows; } } function statsChildren($params=null) {return $this->_statsChildren($simple=true, $sex='BOTH', $year1=-1, $year2=-1, $params=null);} function topAgeBetweenSiblingsName ($params=null) { return $this->_ageBetweenSiblingsQuery($type='name', $params=null); } function topAgeBetweenSiblings ($params=null) { return $this->_ageBetweenSiblingsQuery($type='age', $params=null); } function topAgeBetweenSiblingsFullName($params=null) { return $this->_ageBetweenSiblingsQuery($type='nolist', $params=null); } function topAgeBetweenSiblingsList ($params=null) { return $this->_ageBetweenSiblingsQuery($type='list', $params=null); } function noChildrenFamilies() { $rows=self::_runSQL( " SELECT SQL_CACHE". " COUNT(*) AS tot". " FROM". " `##families` AS fam". " WHERE". " f_numchil = 0 AND". " fam.f_file = {$this->_ged_id}"); $row=$rows[0]; return WT_I18N::number($row['tot']); } function noChildrenFamiliesList($params = null) { global $TEXT_DIRECTION; if (isset($params[0]) && $params[0] != '') {$type = strtolower($params[0]);} else {$type = 'list';} $rows=self::_runSQL( " SELECT SQL_CACHE f_id AS family". " FROM `##families` AS fam". " WHERE f_numchil = 0 AND fam.f_file = {$this->_ged_id}"); if (!isset($rows[0])) {return '';} $top10 = array(); foreach ($rows as $row) { $family=WT_Family::getInstance($row['family']); if ($family->canShow()) { if ($type == 'list') { $top10[] = "
  • getHtmlUrl()."\">".$family->getFullName()."
  • "; } else { $top10[] = "getHtmlUrl()."\">".$family->getFullName().""; } } } if ($type == 'list') { $top10=join('', $top10); } else { $top10 = join(';  ', $top10); } if ($TEXT_DIRECTION == 'rtl') { $top10 = str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function chartNoChildrenFamilies($params=null) { if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = '220x200';} if (isset($params[1]) && $params[1] != '') {$year1 = $params[1];} else {$year1 = -1;} if (isset($params[2]) && $params[2] != '') {$year2 = $params[2];} else {$year2 = -1;} $sizes = explode('x', $size); if ($year1>=0 && $year2>=0) { $years = " married.d_year BETWEEN '{$year1}' AND '{$year2}' AND"; } else { $years = ""; } $max = 0; $tot = 0; $rows=self::_runSQL( "SELECT SQL_CACHE". " COUNT(*) AS count,". " FLOOR(married.d_year/100+1) AS century". " FROM". " `##families` AS fam". " JOIN". " `##dates` AS married ON (married.d_file = fam.f_file AND married.d_gid = fam.f_id)". " WHERE". " f_numchil = 0 AND". " fam.f_file = {$this->_ged_id} AND". $years. " married.d_fact = 'MARR' AND". " married.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@')". " GROUP BY century ORDER BY century" ); if (empty($rows)) return ''; foreach ($rows as $values) { if ($max<$values['count']) $max = $values['count']; $tot += $values['count']; } $unknown = $this->noChildrenFamilies()-$tot; if ($unknown>$max) $max=$unknown; $chm = ""; $chxl = "0:|"; $i = 0; foreach ($rows as $values) { if ($sizes[0]<980) $sizes[0] += 38; $chxl .= self::_centuryName($values['century'])."|"; $counts[] = round(4095*$values['count']/($max+1)); $chm .= 't'.$values['count'].',000000,0,'.$i.',11,1|'; $i++; } $counts[] = round(4095*$unknown/($max+1)); $chd = self::_array_to_extended_encoding($counts); $chm .= 't'.$unknown.',000000,0,'.$i.',11,1'; $chxl .= WT_I18N::translate_c('unknown century', 'Unknown')."|1:||".WT_I18N::translate('century')."|2:|0|"; $step = $max+1; for ($d=(int)($max+1); $d>0; $d--) { if (($max+1)<($d*10+1) && fmod(($max+1),$d)==0) { $step = $d; } } if ($step==(int)($max+1)) { for ($d=(int)($max); $d>0; $d--) { if ($max<($d*10+1) && fmod($max,$d)==0) { $step = $d; } } } for ($n=$step; $n<=($max+1); $n+=$step) { $chxl .= $n."|"; } $chxl .= "3:||".WT_I18N::translate('Total families')."|"; return "\"".WT_I18N::translate('Number"; } function _topTenGrandFamilyQuery($type='list', $params=null) { global $TEXT_DIRECTION; if ($params !== null && isset($params[0])) {$total = $params[0];} else {$total = 10;} $total=(int)$total; $rows=self::_runSQL( "SELECT SQL_CACHE COUNT(*) AS tot, f_id AS id". " FROM `##families`". " JOIN `##link` AS children ON children.l_file = {$this->_ged_id}". " JOIN `##link` AS mchildren ON mchildren.l_file = {$this->_ged_id}". " JOIN `##link` AS gchildren ON gchildren.l_file = {$this->_ged_id}". " WHERE". " f_file={$this->_ged_id} AND". " children.l_from=f_id AND". " children.l_type='CHIL' AND". " children.l_to=mchildren.l_from AND". " mchildren.l_type='FAMS' AND". " mchildren.l_to=gchildren.l_from AND". " gchildren.l_type='CHIL'". " GROUP BY id". " ORDER BY tot DESC". " LIMIT ".$total ); if (!isset($rows[0])) {return '';} $top10 = array(); foreach ($rows as $row) { $family=WT_Family::getInstance($row['id']); if ($family->canShow()) { if ($type == 'list') { $top10[]= '
  • '.$family->getFullName().' - '. WT_I18N::plural('%s grandchild', '%s grandchildren', $row['tot'], WT_I18N::number($row['tot'])); } else { $top10[]= ''.$family->getFullName().' - '. WT_I18N::plural('%s grandchild', '%s grandchildren', $row['tot'], WT_I18N::number($row['tot'])); } } } if ($type == 'list') { $top10=join('', $top10); } else { $top10 = join(';  ', $top10); } if ($TEXT_DIRECTION == 'rtl') { $top10 = str_replace(array('[', ']', '(', ')', '+'), array('‏[', '‏]', '‏(', '‏)', '‏+'), $top10); } if ($type == 'list') { return ''; } return $top10; } function topTenLargestGrandFamily($params=null) {return $this->_topTenGrandFamilyQuery('nolist', $params);} function topTenLargestGrandFamilyList($params=null) {return $this->_topTenGrandFamilyQuery('list', $params);} /////////////////////////////////////////////////////////////////////////////// // Surnames // /////////////////////////////////////////////////////////////////////////////// static function _commonSurnamesQuery($type='list', $show_tot=false, $params=null) { global $SURNAME_LIST_STYLE, $GEDCOM; $ged_id=get_id_from_gedcom($GEDCOM); if (is_array($params) && isset($params[0]) && $params[0] != '') {$threshold = strtolower($params[0]);} else {$threshold = get_gedcom_setting($ged_id, 'COMMON_NAMES_THRESHOLD');} if (is_array($params) && isset($params[1]) && $params[1] != '' && $params[1] >= 0) {$maxtoshow = strtolower($params[1]);} else {$maxtoshow = false;} if (is_array($params) && isset($params[2]) && $params[2] != '') {$sorting = strtolower($params[2]);} else {$sorting = 'alpha';} $surname_list = get_common_surnames($threshold); if (count($surname_list) == 0) return ''; uasort($surname_list, array('WT_Stats', '_name_total_rsort')); if ($maxtoshow>0) $surname_list = array_slice($surname_list, 0, $maxtoshow); switch($sorting) { default: case 'alpha': uksort($surname_list, 'utf8_strcasecmp'); break; case 'count': uasort($surname_list, array('WT_Stats', '_name_total_sort')); break; case 'rcount': uasort($surname_list, array('WT_Stats', '_name_total_rsort')); break; } // Note that we count/display SPFX SURN, but sort/group under just SURN $surnames=array(); foreach (array_keys($surname_list) as $surname) { $surnames=array_merge($surnames, WT_Query_Name::surnames($surname, '', false, false, WT_GED_ID)); } return format_surname_list($surnames, ($type=='list' ? 1 : 2), $show_tot, 'indilist.php'); } function getCommonSurname() { $surnames=array_keys(get_top_surnames($this->_ged_id, 1, 1)); return array_shift($surnames); } static function commonSurnames ($params=array('','','alpha' )) { return self::_commonSurnamesQuery('nolist', false, $params); } static function commonSurnamesTotals ($params=array('','','rcount')) { return self::_commonSurnamesQuery('nolist', true, $params); } static function commonSurnamesList ($params=array('','','alpha' )) { return self::_commonSurnamesQuery('list', false, $params); } static function commonSurnamesListTotals($params=array('','','rcount')) { return self::_commonSurnamesQuery('list', true, $params); } function chartCommonSurnames($params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} if (isset($params[3]) && $params[3] != '') {$threshold = strtolower($params[3]);} else {$threshold = get_gedcom_setting($this->_ged_id, 'COMMON_NAMES_THRESHOLD');} if (isset($params[4]) && $params[4] != '') {$maxtoshow = strtolower($params[4]);} else {$maxtoshow = 7;} $sizes = explode('x', $size); $tot_indi = $this->_totalIndividuals(); $surnames = get_common_surnames($threshold); if (count($surnames) <= 0) {return '';} $SURNAME_TRADITION=get_gedcom_setting(WT_GED_ID, 'SURNAME_TRADITION'); uasort($surnames, array('WT_Stats', '_name_total_rsort')); $surnames = array_slice($surnames, 0, $maxtoshow); $all_surnames = array(); foreach (array_keys($surnames) as $n=>$surname) { if ($n>=$maxtoshow) { break; } $all_surnames = array_merge($all_surnames, WT_Query_Name::surnames(utf8_strtoupper($surname), '', false, false, WT_GED_ID)); } $tot = 0; $per = 0; foreach ($surnames as $indexval=>$surname) {$tot += $surname['match'];} $chd = ''; $chl = array(); foreach ($all_surnames as $surn=>$surns) { $count_per = 0; $max_name = 0; foreach ($surns as $spfxsurn=>$indis) { $per = count($indis); $count_per += $per; // select most common surname from all variants if ($per>$max_name) { $max_name = $per; $top_name = $spfxsurn; } } switch ($SURNAME_TRADITION) { case 'polish': // most common surname should be in male variant (Kowalski, not Kowalska) $top_name=preg_replace(array('/ska$/', '/cka$/', '/dzka$/', '/żka$/'), array('ski', 'cki', 'dzki', 'żki'), $top_name); } $per = round(100 * $count_per / $tot_indi, 0); $chd .= self::_array_to_extended_encoding($per); //ToDo: RTL names are often printed LTR when also LTR names are present $chl[] = $top_name.' - '.WT_I18N::number($count_per); } $per = round(100 * ($tot_indi-$tot) / $tot_indi, 0); $chd .= self::_array_to_extended_encoding($per); $chl[] = WT_I18N::translate('Other').' - '.WT_I18N::number($tot_indi-$tot); $chart_title=implode(WT_I18N::$list_separator, $chl); $chl=implode('|', $chl); return ''.$chart_title.''; } /////////////////////////////////////////////////////////////////////////////// // Given Names // /////////////////////////////////////////////////////////////////////////////// /* * Most Common Given Names Block * Original block created by kiwi */ static function _commonGivenQuery($sex='B', $type='list', $show_tot=false, $params=null) { global $TEXT_DIRECTION, $GEDCOM; static $sort_types = array('count'=>'asort', 'rcount'=>'arsort', 'alpha'=>'ksort', 'ralpha'=>'krsort'); static $sort_flags = array('count'=>SORT_NUMERIC, 'rcount'=>SORT_NUMERIC, 'alpha'=>SORT_STRING, 'ralpha'=>SORT_STRING); if (is_array($params) && isset($params[0]) && $params[0] != '' && $params[0] >= 0) {$threshold = strtolower($params[0]);} else {$threshold = 1;} if (is_array($params) && isset($params[1]) && $params[1] != '' && $params[1] >= 0) {$maxtoshow = strtolower($params[1]);} else {$maxtoshow = 10;} if (is_array($params) && isset($params[2]) && $params[2] != '' && isset($sort_types[strtolower($params[2])])) {$sorting = strtolower($params[2]);} else {$sorting = 'rcount';} switch ($sex) { case 'M': $sex_sql="i_sex='M'"; break; case 'F': $sex_sql="i_sex='F'"; break; case 'U': $sex_sql="i_sex='U'"; break; case 'B': $sex_sql="i_sex<>'U'"; break; } $ged_id=get_id_from_gedcom($GEDCOM); $rows=WT_DB::prepare("SELECT SQL_CACHE n_givn, COUNT(*) AS num FROM `##name` JOIN `##individuals` ON (n_id=i_id AND n_file=i_file) WHERE n_file={$ged_id} AND n_type<>'_MARNM' AND n_givn NOT IN ('@P.N.', '') AND LENGTH(n_givn)>1 AND {$sex_sql} GROUP BY n_id, n_givn") ->fetchAll(); $nameList=array(); foreach ($rows as $row) { // Split “John Thomas” into “John” and “Thomas” and count against both totals foreach (explode(' ', $row->n_givn) as $given) { // Exclude initials and particles. if (!preg_match('/^([A-Z]|[a-z]{1,3})$/', $given)) { if (array_key_exists($given, $nameList)) { $nameList[$given]+=$row->num; } else { $nameList[$given]=$row->num; } } } } arsort($nameList, SORT_NUMERIC); $nameList=array_slice($nameList, 0, $maxtoshow); if (count($nameList)==0) return ''; if ($type=='chart') return $nameList; $common = array(); foreach ($nameList as $given=>$total) { if ($maxtoshow !== -1) {if ($maxtoshow-- <= 0) {break;}} if ($total < $threshold) {break;} if ($show_tot) { $tot = ' ('.WT_I18N::number($total).')'; } else { $tot = ''; } switch ($type) { case 'table': $common[] = ''.$given.''.WT_I18N::number($total).''.$total.''; break; case 'list': $common[] = '
  • '.$given.''.$tot.'
  • '; break; case 'nolist': $common[] = ''.$given.''.$tot; break; } } if ($common) { switch ($type) { case 'table': global $controller; $table_id = 'ID'.(int)(microtime()*1000000); // lists requires a unique ID in case there are multiple lists per page $controller ->addExternalJavascript(WT_JQUERY_DATATABLES_URL) ->addInlineJavascript(' jQuery("#'.$table_id.'").dataTable({ "sDom": \'t\', "bAutoWidth":false, "bPaginate": false, "bLengthChange": false, "bFilter": false, "bInfo": false, "bJQueryUI": true, "aaSorting": [[1,"desc"]], "aoColumns": [ /* 0-name */ {}, /* 1-count */ { sClass:"center", iDataSort:2}, /* 2-COUNT */ { bVisible:false} ] }); jQuery("#'.$table_id.'").css("visibility", "visible"); '); $lookup=array('M'=>WT_I18N::translate('Male'), 'F'=>WT_I18N::translate('Female'), 'U'=>WT_I18N::translate_c('unknown gender', 'Unknown'), 'B'=>WT_I18N::translate('All')); return ''.join('', $common).'
    '.$lookup[$sex].'
    '.WT_I18N::translate('Name').''.WT_I18N::translate('Count').'COUNT
    '; case 'list': return ''; case 'nolist': return join(WT_I18N::$list_separator, $common); } } else { return ''; } } static function commonGiven ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('B', 'nolist', false, $params); } static function commonGivenTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('B', 'nolist', true, $params); } static function commonGivenList ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('B', 'list', false, $params); } static function commonGivenListTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('B', 'list', true, $params); } static function commonGivenTable ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('B', 'table', false, $params); } static function commonGivenFemale ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('F', 'nolist', false, $params); } static function commonGivenFemaleTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('F', 'nolist', true, $params); } static function commonGivenFemaleList ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('F', 'list', false, $params); } static function commonGivenFemaleListTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('F', 'list', true, $params); } static function commonGivenFemaleTable ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('F', 'table', false, $params); } static function commonGivenMale ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('M', 'nolist', false, $params); } static function commonGivenMaleTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('M', 'nolist', true, $params); } static function commonGivenMaleList ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('M', 'list', false, $params); } static function commonGivenMaleListTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('M', 'list', true, $params); } static function commonGivenMaleTable ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('M', 'table', false, $params); } static function commonGivenUnknown ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('U', 'nolist', false, $params); } static function commonGivenUnknownTotals ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('U', 'nolist', true, $params); } static function commonGivenUnknownList ($params=array(1,10,'alpha' )) { return self::_commonGivenQuery('U', 'list', false, $params); } static function commonGivenUnknownListTotals($params=array(1,10,'rcount')) { return self::_commonGivenQuery('U', 'list', true, $params); } static function commonGivenUnknownTable ($params=array(1,10,'rcount')) { return self::_commonGivenQuery('U', 'table', false, $params); } function chartCommonGiven($params=null) { global $WT_STATS_CHART_COLOR1, $WT_STATS_CHART_COLOR2, $WT_STATS_S_CHART_X, $WT_STATS_S_CHART_Y; if ($params === null) {$params = array();} if (isset($params[0]) && $params[0] != '') {$size = strtolower($params[0]);} else {$size = $WT_STATS_S_CHART_X."x".$WT_STATS_S_CHART_Y;} if (isset($params[1]) && $params[1] != '') {$color_from = strtolower($params[1]);} else {$color_from = $WT_STATS_CHART_COLOR1;} if (isset($params[2]) && $params[2] != '') {$color_to = strtolower($params[2]);} else {$color_to = $WT_STATS_CHART_COLOR2;} if (isset($params[3]) && $params[3] != '') {$threshold = strtolower($params[3]);} else {$threshold = get_gedcom_setting($this->_ged_id, 'COMMON_NAMES_THRESHOLD');} if (isset($params[4]) && $params[4] != '') {$maxtoshow = strtolower($params[4]);} else {$maxtoshow = 7;} $sizes = explode('x', $size); $tot_indi = $this->_totalIndividuals(); $given = self::_commonGivenQuery('B', 'chart'); if (!is_array($given)) return ''; $given = array_slice($given, 0, $maxtoshow); if (count($given) <= 0) {return '';} $tot = 0; foreach ($given as $givn=>$count) {$tot += $count;} $chd = ''; $chl = array(); foreach ($given as $givn=>$count) { if ($tot==0) { $per = 0; } else { $per = round(100 * $count / $tot_indi, 0); } $chd .= self::_array_to_extended_encoding($per); //ToDo: RTL names are often printed LTR when also LTR names are present $chl[] = $givn.' - '.WT_I18N::number($count); } $per = round(100 * ($tot_indi-$tot) / $tot_indi, 0); $chd .= self::_array_to_extended_encoding($per); $chl[] = WT_I18N::translate('Other').' - '.WT_I18N::number($tot_indi-$tot); $chart_title=implode(WT_I18N::$list_separator, $chl); $chl=implode('|', $chl); return "\"".$chart_title."\""; } /////////////////////////////////////////////////////////////////////////////// // Users // /////////////////////////////////////////////////////////////////////////////// static function _usersLoggedIn($type='nolist') { $content = ''; // List active users $NumAnonymous = 0; $loggedusers = array (); $x = get_logged_in_users(); foreach ($x as $user_id=>$user_name) { if (WT_USER_IS_ADMIN || get_user_setting($user_id, 'visibleonline')) { $loggedusers[$user_id] = $user_name; } else { $NumAnonymous++; } } $LoginUsers = count($loggedusers); if (($LoginUsers == 0) and ($NumAnonymous == 0)) { return WT_I18N::translate('No logged-in and no anonymous users'); } if ($NumAnonymous > 0) { $content.=''.WT_I18N::plural('%d anonymous logged-in user', '%d anonymous logged-in users', $NumAnonymous, $NumAnonymous).''; } if ($LoginUsers > 0) { if ($NumAnonymous) { if ($type == 'list') { $content .= "

    "; } else { $content .= " ".WT_I18N::translate('and')." "; } } $content.=''.WT_I18N::plural('%d logged-in user', '%d logged-in users', $LoginUsers, $LoginUsers).''; if ($type == 'list') { $content .= ''; } return $content; } static function _usersLoggedInTotal($type='all') { $anon = 0; $visible = 0; $x = get_logged_in_users(); foreach ($x as $user_id=>$user_name) { if (WT_USER_IS_ADMIN || get_user_setting($user_id, 'visibleonline')) {$visible++;} else {$anon++;} } if ($type == 'anon') {return $anon;} elseif ($type == 'visible') {return $visible;} else {return $visible + $anon;} } static function usersLoggedIn () { return self::_usersLoggedIn('nolist'); } static function usersLoggedInList() { return self::_usersLoggedIn('list' ); } static function usersLoggedInTotal () { return self::_usersLoggedInTotal('all' ); } static function usersLoggedInTotalAnon () { return self::_usersLoggedInTotal('anon' ); } static function usersLoggedInTotalVisible() { return self::_usersLoggedInTotal('visible'); } static function userID() {return getUserId();} static function userName($params=null) { if (getUserID()) { return getUserName(); } else { if (is_array($params) && isset($params[0]) && $params[0] != '') { # if #username:visitor# was specified, then "visitor" will be returned when the user is not logged in return $params[0]; } else return null; } } static function userFullName() {return getUserFullName(getUserId());} static function _getLatestUserData($type='userid', $params=null) { global $DATE_FORMAT, $TIME_FORMAT; static $user_id = null; if ($user_id === null) { $user_id=get_newest_registered_user(); } switch($type) { default: case 'userid': return $user_id; case 'username': return get_user_name($user_id); case 'fullname': return getUserFullName($user_id); case 'regdate': if (is_array($params) && isset($params[0]) && $params[0] != '') {$datestamp = $params[0];} else {$datestamp = $DATE_FORMAT;} return timestamp_to_gedcom_date(get_user_setting($user_id, 'reg_timestamp'))->Display(false, $datestamp); case 'regtime': if (is_array($params) && isset($params[0]) && $params[0] != '') {$datestamp = $params[0];} else {$datestamp = str_replace('%', '', $TIME_FORMAT);} return date($datestamp, get_user_setting($user_id, 'reg_timestamp')); case 'loggedin': if (is_array($params) && isset($params[0]) && $params[0] != '') {$yes = $params[0];} else {$yes = WT_I18N::translate('yes');} if (is_array($params) && isset($params[1]) && $params[1] != '') {$no = $params[1];} else {$no = WT_I18N::translate('no');} return WT_DB::prepare("SELECT SQL_NO_CACHE 1 FROM `##session` WHERE user_id=? LIMIT 1")->execute(array($user_id))->fetchOne() ? $yes : $no; } } static function latestUserId () { return self::_getLatestUserData('userid' ); } static function latestUserName () { return self::_getLatestUserData('username' ); } static function latestUserFullName() { return self::_getLatestUserData('fullname' ); } static function latestUserRegDate ($params=null) { return self::_getLatestUserData('regdate', $params); } static function latestUserRegTime ($params=null) { return self::_getLatestUserData('regtime', $params); } static function latestUserLoggedin($params=null) { return self::_getLatestUserData('loggedin', $params); } /////////////////////////////////////////////////////////////////////////////// // Contact // /////////////////////////////////////////////////////////////////////////////// function contactWebmaster() { return user_contact_link(get_gedcom_setting($this->_ged_id, 'WEBMASTER_USER_ID')); } function contactGedcom () { return user_contact_link(get_gedcom_setting($this->_ged_id, 'CONTACT_USER_ID' )); } /////////////////////////////////////////////////////////////////////////////// // Date & Time // /////////////////////////////////////////////////////////////////////////////// static function serverDate () { return timestamp_to_gedcom_date(WT_TIMESTAMP)->Display(false);} static function serverTime () { return date('g:i a');} static function serverTime24 () { return date('G:i');} static function serverTimezone () { return date('T');} static function browserDate () { return timestamp_to_gedcom_date(WT_CLIENT_TIMESTAMP)->Display(false);} static function browserTime () { return date('g:i a', WT_CLIENT_TIMESTAMP);} static function browserTime24 () { return date('G:i', WT_CLIENT_TIMESTAMP);} static function browserTimezone() { return date('T', WT_CLIENT_TIMESTAMP);} /////////////////////////////////////////////////////////////////////////////// // Tools // /////////////////////////////////////////////////////////////////////////////// // Older versions of webtrees allowed access to all constants and globals. // Newer version just allow access to these values: public static function WT_VERSION() { return WT_VERSION; } public static function WT_VERSION_TEXT() { return WT_VERSION_TEXT; } // These functions provide access to hitcounter // for use in the HTML block. static private function _getHitCount($page_name, $params) { if (is_array($params) && isset($params[0]) && $params[0] != '') { $page_parameter = $params[0]; } else { $page_parameter = ''; } if ($page_name===null) { // index.php?ctype=gedcom $page_name='index.php'; $page_parameter='gedcom:'.get_id_from_gedcom($page_parameter ? $page_parameter : WT_GEDCOM); } elseif ($page_name=='index.php') { // index.php?ctype=user $page_parameter='user:'.($page_parameter ? get_user_id($page_parameter) : WT_USER_ID); } else { // indi/fam/sour/etc. } $count=WT_DB::prepare( "SELECT SQL_NO_CACHE page_count FROM `##hit_counter`". " WHERE gedcom_id=? AND page_name=? AND page_parameter=?" )->execute(array(WT_GED_ID, $page_name, $page_parameter))->fetchOne(); return ''.WT_I18N::number($count).''; } static function hitCount ($params=null) {return self::_getHitCount(null, $params);} static function hitCountUser($params=null) {return self::_getHitCount('index.php', $params);} static function hitCountIndi($params=null) {return self::_getHitCount('individual.php', $params);} static function hitCountFam ($params=null) {return self::_getHitCount('family.php', $params);} static function hitCountSour($params=null) {return self::_getHitCount('source.php', $params);} static function hitCountRepo($params=null) {return self::_getHitCount('repo.php', $params);} static function hitCountNote($params=null) {return self::_getHitCount('note.php', $params);} static function hitCountObje($params=null) {return self::_getHitCount('mediaviewer.php',$params);} /* * Leave for backwards compatability? Anybody using this? */ static function _getEventType($type) { $eventTypes=array( 'BIRT'=>WT_I18N::translate('birth'), 'DEAT'=>WT_I18N::translate('death'), 'MARR'=>WT_I18N::translate('marriage'), 'ADOP'=>WT_I18N::translate('adoption'), 'BURI'=>WT_I18N::translate('burial'), 'CENS'=>WT_I18N::translate('census added') ); if (isset($eventTypes[$type])) { return $eventTypes[$type]; } return false; } // http://bendodson.com/news/google-extended-encoding-made-easy/ static function _array_to_extended_encoding($a) { $xencoding = WT_GOOGLE_CHART_ENCODING; if (!is_array($a)) { $a = array($a); } $encoding = ''; foreach ($a as $value) { if ($value<0) $value = 0; $first = (int)($value / 64); $second = $value % 64; $encoding .= $xencoding[(int)$first] . $xencoding[(int)$second]; } return $encoding; } static function _name_total_sort($a, $b) { return $a['match']-$b['match']; } static function _name_total_rsort($a, $b) { return $b['match']-$a['match']; } static function _runSQL($sql) { static $cache = array(); $id = md5($sql); if (isset($cache[$id])) { return $cache[$id]; } $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); $cache[$id]=$rows; return $rows; } // These functions provide access to additional non-stats features of webtrees // for use in the HTML block. static function _getFavorites($isged=true) { global $GEDCOM; ob_start(); if ($isged) { $class_name = 'gedcom_favorites_WT_Module'; $block = new $class_name; $content = $block->getBlock($GEDCOM); } else if (WT_USER_ID) { $class_name = 'user_favorites_WT_Module'; $block = new $class_name; $content = $block->getBlock($GEDCOM); } return ob_get_clean(); } static function gedcomFavorites() {return self::_getFavorites(true);} static function userFavorites() {return self::_getFavorites(false);} static function totalGedcomFavorites() {return count(gedcom_favorites_WT_Module::getFavorites(WT_GED_ID));} static function totalUserFavorites() {return count(user_favorites_WT_Module::getFavorites(WT_USER_ID));} /////////////////////////////////////////////////////////////////////////////// // Other blocks // // example of use: #callBlock:block_name# // /////////////////////////////////////////////////////////////////////////////// static function callBlock($params=null) { global $ctype; if ($params === null) {return '';} if (isset($params[0]) && $params[0] != '') {$block = $params[0];} else {return '';} $all_blocks=array(); foreach (WT_Module::getActiveBlocks() as $name=>$active_block) { if ($ctype=='user' && $active_block->isUserBlock() || $ctype=='gedcom' && $active_block->isGedcomBlock()) { $all_blocks[$name]=$active_block; } } if (!array_key_exists($block, $all_blocks) || $block=='html') return ''; $class_name = $block.'_WT_Module'; // Build the config array array_shift($params); $cfg = array(); foreach ($params as $config) { $bits = explode('=', $config); if (count($bits) < 2) {continue;} $v = array_shift($bits); $cfg[$v] = join('=', $bits); } $block = new $class_name; $block_id=safe_GET('block_id'); $content = $block->getBlock($block_id, false, $cfg); return $content; } function totalUserMessages() { return WT_I18N::number(count(getUserMessages(WT_USER_NAME))); } function totalUserJournal() { return WT_I18N::number(count(getUserNews(WT_USER_ID))); } function totalGedcomNews() { return WT_I18N::number(count(getUserNews(WT_GEDCOM))); } ////////////////////////////////////////////////////////////////////////////// // Country lookup data ////////////////////////////////////////////////////////////////////////////// // ISO3166 3 letter codes, with their 2 letter equivalent. // NOTE: this is not 1:1. ENG/SCO/WAL/NIR => GB // NOTE: this also includes champman codes and others. Should it? public static function iso3166() { return array( 'ABW'=>'AW', 'AFG'=>'AF', 'AGO'=>'AO', 'AIA'=>'AI', 'ALA'=>'AX', 'ALB'=>'AL', 'AND'=>'AD', 'ANT'=>'AN', 'ARE'=>'AE', 'ARG'=>'AR', 'ARM'=>'AM', 'ASM'=>'AS', 'ATA'=>'AQ', 'ATF'=>'TF', 'ATG'=>'AG', 'AUS'=>'AU', 'AUT'=>'AT', 'AZE'=>'AZ', 'BDI'=>'BI', 'BEL'=>'BE', 'BEN'=>'BJ', 'BFA'=>'BF', 'BGD'=>'BD', 'BGR'=>'BG', 'BHR'=>'BH', 'BHS'=>'BS', 'BIH'=>'BA', 'BLR'=>'BY', 'BLZ'=>'BZ', 'BMU'=>'BM', 'BOL'=>'BO', 'BRA'=>'BR', 'BRB'=>'BB', 'BRN'=>'BN', 'BTN'=>'BT', 'BVT'=>'BV', 'BWA'=>'BW', 'CAF'=>'CF', 'CAN'=>'CA', 'CCK'=>'CC', 'CHE'=>'CH', 'CHL'=>'CL', 'CHN'=>'CN', 'CHI'=>'JE', 'CIV'=>'CI', 'CMR'=>'CM', 'COD'=>'CD', 'COG'=>'CG', 'COK'=>'CK', 'COL'=>'CO', 'COM'=>'KM', 'CPV'=>'CV', 'CRI'=>'CR', 'CUB'=>'CU', 'CXR'=>'CX', 'CYM'=>'KY', 'CYP'=>'CY', 'CZE'=>'CZ', 'DEU'=>'DE', 'DJI'=>'DJ', 'DMA'=>'DM', 'DNK'=>'DK', 'DOM'=>'DO', 'DZA'=>'DZ', 'ECU'=>'EC', 'EGY'=>'EG', 'ENG'=>'GB', 'ERI'=>'ER', 'ESH'=>'EH', 'ESP'=>'ES', 'EST'=>'EE', 'ETH'=>'ET', 'FIN'=>'FI', 'FJI'=>'FJ', 'FLK'=>'FK', 'FRA'=>'FR', 'FRO'=>'FO', 'FSM'=>'FM', 'GAB'=>'GA', 'GBR'=>'GB', 'GEO'=>'GE', 'GHA'=>'GH', 'GIB'=>'GI', 'GIN'=>'GN', 'GLP'=>'GP', 'GMB'=>'GM', 'GNB'=>'GW', 'GNQ'=>'GQ', 'GRC'=>'GR', 'GRD'=>'GD', 'GRL'=>'GL', 'GTM'=>'GT', 'GUF'=>'GF', 'GUM'=>'GU', 'GUY'=>'GY', 'HKG'=>'HK', 'HMD'=>'HM', 'HND'=>'HN', 'HRV'=>'HR', 'HTI'=>'HT', 'HUN'=>'HU', 'IDN'=>'ID', 'IND'=>'IN', 'IOT'=>'IO', 'IRL'=>'IE', 'IRN'=>'IR', 'IRQ'=>'IQ', 'ISL'=>'IS', 'ISR'=>'IL', 'ITA'=>'IT', 'JAM'=>'JM', 'JOR'=>'JO', 'JPN'=>'JA', 'KAZ'=>'KZ', 'KEN'=>'KE', 'KGZ'=>'KG', 'KHM'=>'KH', 'KIR'=>'KI', 'KNA'=>'KN', 'KOR'=>'KO', 'KWT'=>'KW', 'LAO'=>'LA', 'LBN'=>'LB', 'LBR'=>'LR', 'LBY'=>'LY', 'LCA'=>'LC', 'LIE'=>'LI', 'LKA'=>'LK', 'LSO'=>'LS', 'LTU'=>'LT', 'LUX'=>'LU', 'LVA'=>'LV', 'MAC'=>'MO', 'MAR'=>'MA', 'MCO'=>'MC', 'MDA'=>'MD', 'MDG'=>'MG', 'MDV'=>'MV', 'MEX'=>'MX', 'MHL'=>'MH', 'MKD'=>'MK', 'MLI'=>'ML', 'MLT'=>'MT', 'MMR'=>'MM', 'MNG'=>'MN', 'MNP'=>'MP', 'MNT'=>'ME', 'MOZ'=>'MZ', 'MRT'=>'MR', 'MSR'=>'MS', 'MTQ'=>'MQ', 'MUS'=>'MU', 'MWI'=>'MW', 'MYS'=>'MY', 'MYT'=>'YT', 'NAM'=>'NA', 'NCL'=>'NC', 'NER'=>'NE', 'NFK'=>'NF', 'NGA'=>'NG', 'NIC'=>'NI', 'NIR'=>'GB', 'NIU'=>'NU', 'NLD'=>'NL', 'NOR'=>'NO', 'NPL'=>'NP', 'NRU'=>'NR', 'NZL'=>'NZ', 'OMN'=>'OM', 'PAK'=>'PK', 'PAN'=>'PA', 'PCN'=>'PN', 'PER'=>'PE', 'PHL'=>'PH', 'PLW'=>'PW', 'PNG'=>'PG', 'POL'=>'PL', 'PRI'=>'PR', 'PRK'=>'KP', 'PRT'=>'PO', 'PRY'=>'PY', 'PSE'=>'PS', 'PYF'=>'PF', 'QAT'=>'QA', 'REU'=>'RE', 'ROM'=>'RO', 'RUS'=>'RU', 'RWA'=>'RW', 'SAU'=>'SA', 'SCT'=>'GB', 'SDN'=>'SD', 'SEN'=>'SN', 'SER'=>'RS', 'SGP'=>'SG', 'SGS'=>'GS', 'SHN'=>'SH', 'SIC'=>'IT', 'SJM'=>'SJ', 'SLB'=>'SB', 'SLE'=>'SL', 'SLV'=>'SV', 'SMR'=>'SM', 'SOM'=>'SO', 'SPM'=>'PM', 'STP'=>'ST', 'SUN'=>'RU', 'SUR'=>'SR', 'SVK'=>'SK', 'SVN'=>'SI', 'SWE'=>'SE', 'SWZ'=>'SZ', 'SYC'=>'SC', 'SYR'=>'SY', 'TCA'=>'TC', 'TCD'=>'TD', 'TGO'=>'TG', 'THA'=>'TH', 'TJK'=>'TJ', 'TKL'=>'TK', 'TKM'=>'TM', 'TLS'=>'TL', 'TON'=>'TO', 'TTO'=>'TT', 'TUN'=>'TN', 'TUR'=>'TR', 'TUV'=>'TV', 'TWN'=>'TW', 'TZA'=>'TZ', 'UGA'=>'UG', 'UKR'=>'UA', 'UMI'=>'UM', 'URY'=>'UY', 'USA'=>'US', 'UZB'=>'UZ', 'VAT'=>'VA', 'VCT'=>'VC', 'VEN'=>'VE', 'VGB'=>'VG', 'VIR'=>'VI', 'VNM'=>'VN', 'VUT'=>'VU', 'WLF'=>'WF', 'WLS'=>'GB', 'WSM'=>'WS', 'YEM'=>'YE', 'ZAF'=>'ZA', 'ZMB'=>'ZM', 'ZWE'=>'ZW', ); } public static function get_all_countries() { return array( '???'=>WT_I18N::translate('Unknown'), 'ABW'=>WT_I18N::translate('Aruba'), 'ACA'=>WT_I18N::translate('Acadia'), 'AFG'=>WT_I18N::translate('Afghanistan'), 'AGO'=>WT_I18N::translate('Angola'), 'AIA'=>WT_I18N::translate('Anguilla'), 'ALA'=>WT_I18N::translate('Aland Islands'), 'ALB'=>WT_I18N::translate('Albania'), 'AND'=>WT_I18N::translate('Andorra'), 'ANT'=>WT_I18N::translate('Netherlands Antilles'), 'ARE'=>WT_I18N::translate('United Arab Emirates'), 'ARG'=>WT_I18N::translate('Argentina'), 'ARM'=>WT_I18N::translate('Armenia'), 'ASM'=>WT_I18N::translate('American Samoa'), 'ATA'=>WT_I18N::translate('Antarctica'), 'ATF'=>WT_I18N::translate('French Southern Territories'), 'ATG'=>WT_I18N::translate('Antigua and Barbuda'), 'AUS'=>WT_I18N::translate('Australia'), 'AUT'=>WT_I18N::translate('Austria'), 'AZE'=>WT_I18N::translate('Azerbaijan'), 'AZR'=>WT_I18N::translate('Azores'), 'BDI'=>WT_I18N::translate('Burundi'), 'BEL'=>WT_I18N::translate('Belgium'), 'BEN'=>WT_I18N::translate('Benin'), 'BFA'=>WT_I18N::translate('Burkina Faso'), 'BGD'=>WT_I18N::translate('Bangladesh'), 'BGR'=>WT_I18N::translate('Bulgaria'), 'BHR'=>WT_I18N::translate('Bahrain'), 'BHS'=>WT_I18N::translate('Bahamas'), 'BIH'=>WT_I18N::translate('Bosnia and Herzegovina'), 'BLR'=>WT_I18N::translate('Belarus'), 'BLZ'=>WT_I18N::translate('Belize'), 'BMU'=>WT_I18N::translate('Bermuda'), 'BOL'=>WT_I18N::translate('Bolivia'), 'BRA'=>WT_I18N::translate('Brazil'), 'BRB'=>WT_I18N::translate('Barbados'), 'BRN'=>WT_I18N::translate('Brunei Darussalam'), 'BTN'=>WT_I18N::translate('Bhutan'), 'BVT'=>WT_I18N::translate('Bouvet Island'), 'BWA'=>WT_I18N::translate('Botswana'), 'BWI'=>WT_I18N::translate('British West Indies'), 'CAF'=>WT_I18N::translate('Central African Republic'), 'CAN'=>WT_I18N::translate('Canada'), 'CAP'=>WT_I18N::translate('Cape Colony'), 'CAT'=>WT_I18N::translate('Catalonia'), 'CCK'=>WT_I18N::translate('Cocos (Keeling) Islands'), 'CHE'=>WT_I18N::translate('Switzerland'), 'CHI'=>WT_I18N::translate('Channel Islands'), 'CHL'=>WT_I18N::translate('Chile'), 'CHN'=>WT_I18N::translate('China'), 'CIV'=>WT_I18N::translate('Cote d\'Ivoire'), 'CMR'=>WT_I18N::translate('Cameroon'), 'COD'=>WT_I18N::translate('Congo (Kinshasa)'), 'COG'=>WT_I18N::translate('Congo (Brazzaville)'), 'COK'=>WT_I18N::translate('Cook Islands'), 'COL'=>WT_I18N::translate('Colombia'), 'COM'=>WT_I18N::translate('Comoros'), 'CPV'=>WT_I18N::translate('Cape Verde'), 'CRI'=>WT_I18N::translate('Costa Rica'), 'CSK'=>WT_I18N::translate('Czechoslovakia'), 'CUB'=>WT_I18N::translate('Cuba'), 'CXR'=>WT_I18N::translate('Christmas Island'), 'CYM'=>WT_I18N::translate('Cayman Islands'), 'CYP'=>WT_I18N::translate('Cyprus'), 'CZE'=>WT_I18N::translate('Czech Republic'), 'DEU'=>WT_I18N::translate('Germany'), 'DJI'=>WT_I18N::translate('Djibouti'), 'DMA'=>WT_I18N::translate('Dominica'), 'DNK'=>WT_I18N::translate('Denmark'), 'DOM'=>WT_I18N::translate('Dominican Republic'), 'DZA'=>WT_I18N::translate('Algeria'), 'ECU'=>WT_I18N::translate('Ecuador'), 'EGY'=>WT_I18N::translate('Egypt'), 'EIR'=>WT_I18N::translate('Eire'), 'ENG'=>WT_I18N::translate('England'), 'ERI'=>WT_I18N::translate('Eritrea'), 'ESH'=>WT_I18N::translate('Western Sahara'), 'ESP'=>WT_I18N::translate('Spain'), 'EST'=>WT_I18N::translate('Estonia'), 'ETH'=>WT_I18N::translate('Ethiopia'), 'FIN'=>WT_I18N::translate('Finland'), 'FJI'=>WT_I18N::translate('Fiji'), 'FLD'=>WT_I18N::translate('Flanders'), 'FLK'=>WT_I18N::translate('Falkland Islands'), 'FRA'=>WT_I18N::translate('France'), 'FRO'=>WT_I18N::translate('Faeroe Islands'), 'FSM'=>WT_I18N::translate('Micronesia'), 'GAB'=>WT_I18N::translate('Gabon'), 'GBR'=>WT_I18N::translate('United Kingdom'), 'GEO'=>WT_I18N::translate('Georgia'), 'GGY'=>WT_I18N::translate('Guernsey'), 'GHA'=>WT_I18N::translate('Ghana'), 'GIB'=>WT_I18N::translate('Gibraltar'), 'GIN'=>WT_I18N::translate('Guinea'), 'GLP'=>WT_I18N::translate('Guadeloupe'), 'GMB'=>WT_I18N::translate('Gambia'), 'GNB'=>WT_I18N::translate('Guinea-Bissau'), 'GNQ'=>WT_I18N::translate('Equatorial Guinea'), 'GRC'=>WT_I18N::translate('Greece'), 'GRD'=>WT_I18N::translate('Grenada'), 'GRL'=>WT_I18N::translate('Greenland'), 'GTM'=>WT_I18N::translate('Guatemala'), 'GUF'=>WT_I18N::translate('French Guiana'), 'GUM'=>WT_I18N::translate('Guam'), 'GUY'=>WT_I18N::translate('Guyana'), 'HKG'=>WT_I18N::translate('Hong Kong'), 'HMD'=>WT_I18N::translate('Heard Island and McDonald Islands'), 'HND'=>WT_I18N::translate('Honduras'), 'HRV'=>WT_I18N::translate('Croatia'), 'HTI'=>WT_I18N::translate('Haiti'), 'HUN'=>WT_I18N::translate('Hungary'), 'IDN'=>WT_I18N::translate('Indonesia'), 'IND'=>WT_I18N::translate('India'), 'IOM'=>WT_I18N::translate('Isle of Man'), 'IOT'=>WT_I18N::translate('British Indian Ocean Territory'), 'IRL'=>WT_I18N::translate('Ireland'), 'IRN'=>WT_I18N::translate('Iran'), 'IRQ'=>WT_I18N::translate('Iraq'), 'ISL'=>WT_I18N::translate('Iceland'), 'ISR'=>WT_I18N::translate('Israel'), 'ITA'=>WT_I18N::translate('Italy'), 'JAM'=>WT_I18N::translate('Jamaica'), 'JOR'=>WT_I18N::translate('Jordan'), 'JPN'=>WT_I18N::translate('Japan'), 'KAZ'=>WT_I18N::translate('Kazakhstan'), 'KEN'=>WT_I18N::translate('Kenya'), 'KGZ'=>WT_I18N::translate('Kyrgyzstan'), 'KHM'=>WT_I18N::translate('Cambodia'), 'KIR'=>WT_I18N::translate('Kiribati'), 'KNA'=>WT_I18N::translate('Saint Kitts and Nevis'), 'KOR'=>WT_I18N::translate('Korea'), 'KWT'=>WT_I18N::translate('Kuwait'), 'LAO'=>WT_I18N::translate('Laos'), 'LBN'=>WT_I18N::translate('Lebanon'), 'LBR'=>WT_I18N::translate('Liberia'), 'LBY'=>WT_I18N::translate('Libya'), 'LCA'=>WT_I18N::translate('Saint Lucia'), 'LIE'=>WT_I18N::translate('Liechtenstein'), 'LKA'=>WT_I18N::translate('Sri Lanka'), 'LSO'=>WT_I18N::translate('Lesotho'), 'LTU'=>WT_I18N::translate('Lithuania'), 'LUX'=>WT_I18N::translate('Luxembourg'), 'LVA'=>WT_I18N::translate('Latvia'), 'MAC'=>WT_I18N::translate('Macau'), 'MAR'=>WT_I18N::translate('Morocco'), 'MCO'=>WT_I18N::translate('Monaco'), 'MDA'=>WT_I18N::translate('Moldova'), 'MDG'=>WT_I18N::translate('Madagascar'), 'MDV'=>WT_I18N::translate('Maldives'), 'MEX'=>WT_I18N::translate('Mexico'), 'MHL'=>WT_I18N::translate('Marshall Islands'), 'MKD'=>WT_I18N::translate('Macedonia'), 'MLI'=>WT_I18N::translate('Mali'), 'MLT'=>WT_I18N::translate('Malta'), 'MMR'=>WT_I18N::translate('Myanmar'), 'MNG'=>WT_I18N::translate('Mongolia'), 'MNP'=>WT_I18N::translate('Northern Mariana Islands'), 'MNT'=>WT_I18N::translate('Montenegro'), 'MOZ'=>WT_I18N::translate('Mozambique'), 'MRT'=>WT_I18N::translate('Mauritania'), 'MSR'=>WT_I18N::translate('Montserrat'), 'MTQ'=>WT_I18N::translate('Martinique'), 'MUS'=>WT_I18N::translate('Mauritius'), 'MWI'=>WT_I18N::translate('Malawi'), 'MYS'=>WT_I18N::translate('Malaysia'), 'MYT'=>WT_I18N::translate('Mayotte'), 'NAM'=>WT_I18N::translate('Namibia'), 'NCL'=>WT_I18N::translate('New Caledonia'), 'NER'=>WT_I18N::translate('Niger'), 'NFK'=>WT_I18N::translate('Norfolk Island'), 'NGA'=>WT_I18N::translate('Nigeria'), 'NIC'=>WT_I18N::translate('Nicaragua'), 'NIR'=>WT_I18N::translate('Northern Ireland'), 'NIU'=>WT_I18N::translate('Niue'), 'NLD'=>WT_I18N::translate('Netherlands'), 'NOR'=>WT_I18N::translate('Norway'), 'NPL'=>WT_I18N::translate('Nepal'), 'NRU'=>WT_I18N::translate('Nauru'), 'NTZ'=>WT_I18N::translate('Neutral Zone'), 'NZL'=>WT_I18N::translate('New Zealand'), 'OMN'=>WT_I18N::translate('Oman'), 'PAK'=>WT_I18N::translate('Pakistan'), 'PAN'=>WT_I18N::translate('Panama'), 'PCN'=>WT_I18N::translate('Pitcairn'), 'PER'=>WT_I18N::translate('Peru'), 'PHL'=>WT_I18N::translate('Philippines'), 'PLW'=>WT_I18N::translate('Palau'), 'PNG'=>WT_I18N::translate('Papua New Guinea'), 'POL'=>WT_I18N::translate('Poland'), 'PRI'=>WT_I18N::translate('Puerto Rico'), 'PRK'=>WT_I18N::translate('North Korea'), 'PRT'=>WT_I18N::translate('Portugal'), 'PRY'=>WT_I18N::translate('Paraguay'), 'PSE'=>WT_I18N::translate('Occupied Palestinian Territory'), 'PYF'=>WT_I18N::translate('French Polynesia'), 'QAT'=>WT_I18N::translate('Qatar'), 'REU'=>WT_I18N::translate('Reunion'), 'ROM'=>WT_I18N::translate('Romania'), 'RUS'=>WT_I18N::translate('Russia'), 'RWA'=>WT_I18N::translate('Rwanda'), 'SAU'=>WT_I18N::translate('Saudi Arabia'), 'SCG'=>WT_I18N::translate('Serbia and Montenegro'), 'SCT'=>WT_I18N::translate('Scotland'), 'SDN'=>WT_I18N::translate('Sudan'), 'SEA'=>WT_I18N::translate('At Sea'), 'SEN'=>WT_I18N::translate('Senegal'), 'SER'=>WT_I18N::translate('Serbia'), 'SGP'=>WT_I18N::translate('Singapore'), 'SGS'=>WT_I18N::translate('South Georgia and the South Sandwich Islands'), 'SHN'=>WT_I18N::translate('Saint Helena'), 'SIC'=>WT_I18N::translate('Sicily'), 'SJM'=>WT_I18N::translate('Svalbard and Jan Mayen Islands'), 'SLB'=>WT_I18N::translate('Solomon Islands'), 'SLE'=>WT_I18N::translate('Sierra Leone'), 'SLV'=>WT_I18N::translate('El Salvador'), 'SMR'=>WT_I18N::translate('San Marino'), 'SOM'=>WT_I18N::translate('Somalia'), 'SPM'=>WT_I18N::translate('Saint Pierre and Miquelon'), 'SSD'=>WT_I18N::translate('South Sudan'), 'STP'=>WT_I18N::translate('Sao Tome and Principe'), 'SUN'=>WT_I18N::translate('USSR'), 'SUR'=>WT_I18N::translate('Suriname'), 'SVK'=>WT_I18N::translate('Slovakia'), 'SVN'=>WT_I18N::translate('Slovenia'), 'SWE'=>WT_I18N::translate('Sweden'), 'SWZ'=>WT_I18N::translate('Swaziland'), 'SYC'=>WT_I18N::translate('Seychelles'), 'SYR'=>WT_I18N::translate('Syrian Arab Republic'), 'TCA'=>WT_I18N::translate('Turks and Caicos Islands'), 'TCD'=>WT_I18N::translate('Chad'), 'TGO'=>WT_I18N::translate('Togo'), 'THA'=>WT_I18N::translate('Thailand'), 'TJK'=>WT_I18N::translate('Tajikistan'), 'TKL'=>WT_I18N::translate('Tokelau'), 'TKM'=>WT_I18N::translate('Turkmenistan'), 'TLS'=>WT_I18N::translate('Timor-Leste'), 'TON'=>WT_I18N::translate('Tonga'), 'TRN'=>WT_I18N::translate('Transylvania'), 'TTO'=>WT_I18N::translate('Trinidad and Tobago'), 'TUN'=>WT_I18N::translate('Tunisia'), 'TUR'=>WT_I18N::translate('Turkey'), 'TUV'=>WT_I18N::translate('Tuvalu'), 'TWN'=>WT_I18N::translate('Taiwan'), 'TZA'=>WT_I18N::translate('Tanzania'), 'UGA'=>WT_I18N::translate('Uganda'), 'UKR'=>WT_I18N::translate('Ukraine'), 'UMI'=>WT_I18N::translate('US Minor Outlying Islands'), 'URY'=>WT_I18N::translate('Uruguay'), 'USA'=>WT_I18N::translate('USA'), 'UZB'=>WT_I18N::translate('Uzbekistan'), 'VAT'=>WT_I18N::translate('Vatican City'), 'VCT'=>WT_I18N::translate('Saint Vincent and the Grenadines'), 'VEN'=>WT_I18N::translate('Venezuela'), 'VGB'=>WT_I18N::translate('British Virgin Islands'), 'VIR'=>WT_I18N::translate('US Virgin Islands'), 'VNM'=>WT_I18N::translate('Viet Nam'), 'VUT'=>WT_I18N::translate('Vanuatu'), 'WAF'=>WT_I18N::translate('West Africa'), 'WLF'=>WT_I18N::translate('Wallis and Futuna Islands'), 'WLS'=>WT_I18N::translate('Wales'), 'WSM'=>WT_I18N::translate('Samoa'), 'YEM'=>WT_I18N::translate('Yemen'), 'YUG'=>WT_I18N::translate('Yugoslavia'), 'ZAF'=>WT_I18N::translate('South Africa'), 'ZAR'=>WT_I18N::translate('Zaire'), 'ZMB'=>WT_I18N::translate('Zambia'), 'ZWE'=>WT_I18N::translate('Zimbabwe'), ); } // century name, English => 21st, Polish => XXI, etc. private static function _centuryName($century) { if ($century<0) { return str_replace(-$century, WT_Stats::_centuryName(-$century), /* I18N: BCE=Before the Common Era, for Julian years < 0. See http://en.wikipedia.org/wiki/Common_Era */ WT_I18N::translate('%s BCE', WT_I18N::number(-$century))); } switch ($century) { case 21: return WT_I18N::translate_c('CENTURY', '21st'); case 20: return WT_I18N::translate_c('CENTURY', '20th'); case 19: return WT_I18N::translate_c('CENTURY', '19th'); case 18: return WT_I18N::translate_c('CENTURY', '18th'); case 17: return WT_I18N::translate_c('CENTURY', '17th'); case 16: return WT_I18N::translate_c('CENTURY', '16th'); case 15: return WT_I18N::translate_c('CENTURY', '15th'); case 14: return WT_I18N::translate_c('CENTURY', '14th'); case 13: return WT_I18N::translate_c('CENTURY', '13th'); case 12: return WT_I18N::translate_c('CENTURY', '12th'); case 11: return WT_I18N::translate_c('CENTURY', '11th'); case 10: return WT_I18N::translate_c('CENTURY', '10th'); case 9: return WT_I18N::translate_c('CENTURY', '9th'); case 8: return WT_I18N::translate_c('CENTURY', '8th'); case 7: return WT_I18N::translate_c('CENTURY', '7th'); case 6: return WT_I18N::translate_c('CENTURY', '6th'); case 5: return WT_I18N::translate_c('CENTURY', '5th'); case 4: return WT_I18N::translate_c('CENTURY', '4th'); case 3: return WT_I18N::translate_c('CENTURY', '3rd'); case 2: return WT_I18N::translate_c('CENTURY', '2nd'); case 1: return WT_I18N::translate_c('CENTURY', '1st'); default: return ($century-1).'01-'.$century.'00'; } } }