/** * Create the chart controller * * @param int $show_full needed for use by charts module */ public function __construct($show_full = 1) { global $WT_TREE; parent::__construct(); $rootid = Filter::get('rootid', WT_REGEX_XREF); $this->root = Individual::getInstance($rootid, $WT_TREE); if (!$this->root) { // Missing root individual? Show the chart for someone. $this->root = $this->getSignificantIndividual(); } if (!$this->root || !$this->root->canShowName()) { http_response_code(404); $this->error_message = I18N::translate('This individual does not exist or you do not have permission to view it.'); } // Extract parameter from form if ($show_full) { $this->show_full = Filter::getInteger('show_full', 0, 1, $WT_TREE->getPreference('PEDIGREE_FULL_DETAILS')); } else { $this->show_full = 0; } $this->box = new \stdClass(); if ($this->showFull()) { $this->box->width = Theme::theme()->parameter('chart-box-x'); $this->box->height = Theme::theme()->parameter('chart-box-y'); } else { $this->box->width = Theme::theme()->parameter('compact-chart-box-x'); $this->box->height = Theme::theme()->parameter('compact-chart-box-y'); } }
/** * AdminConfig@index */ public function index() { global $WT_TREE; $action = Filter::post('action'); if ($action == 'update' && Filter::checkCsrf()) { $this->update(); } Theme::theme(new AdministrationTheme())->init($WT_TREE); $ctrl = new PageController(); $ctrl->restrictAccess(Auth::isAdmin())->setPageTitle($this->module->getTitle()); $view_bag = new ViewBag(); $view_bag->set('title', $ctrl->getPageTitle()); $view_bag->set('module', $this->module); ViewFactory::make('AdminConfig', $this, $ctrl, $view_bag)->render(); }
/** * Translation@status */ public function status() { global $WT_TREE; $table_id = \Rhumsaa\Uuid\Uuid::uuid4(); Theme::theme(new AdministrationTheme())->init($WT_TREE); $ctrl = new PageController(); $ctrl->restrictAccess(Auth::isAdmin())->setPageTitle(I18N::translate('Translations status'))->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL)->addInlineJavascript(' //Datatable initialisation jQuery.fn.dataTableExt.oSort["unicode-asc" ]=function(a,b) {return a.replace(/<[^<]*>/, "").localeCompare(b.replace(/<[^<]*>/, ""))}; jQuery.fn.dataTableExt.oSort["unicode-desc" ]=function(a,b) {return b.replace(/<[^<]*>/, "").localeCompare(a.replace(/<[^<]*>/, ""))}; jQuery.fn.dataTableExt.oSort["num-html-asc" ]=function(a,b) {a=parseFloat(a.replace(/<[^<]*>/, "")); b=parseFloat(b.replace(/<[^<]*>/, "")); return (a<b) ? -1 : (a>b ? 1 : 0);}; jQuery.fn.dataTableExt.oSort["num-html-desc"]=function(a,b) {a=parseFloat(a.replace(/<[^<]*>/, "")); b=parseFloat(b.replace(/<[^<]*>/, "")); return (a>b) ? -1 : (a<b ? 1 : 0);}; jQuery("#table_missing_' . $table_id . '").DataTable({ ' . I18N::datatablesI18N() . ', sorting: [[0, "asc"]], pageLength: 15, columns: [ /* 0 Message */ null, /* 1 Reference */ null ], }); jQuery("#table_nonused_' . $table_id . '").DataTable({ ' . I18N::datatablesI18N() . ', sorting: [[0, "asc"]], pageLength: 15, columns: [ /* 0 Message */ null, /* 1 Reference */ null ], }); '); $source_code_paths = array(WT_ROOT . 'vendor/jon48/webtrees-lib/src', WT_ROOT . 'vendor/jon48/webtrees-tools/src/app'); $analyzer = new TranslationsAnalyzer($source_code_paths); $analyzer->load(); $locale = $analyzer->getLocale(); $view_bag = new ViewBag(); $view_bag->set('table_id', $table_id); $view_bag->set('module', $this->module); $view_bag->set('source_code_paths', $source_code_paths); $view_bag->set('title', $ctrl->getPageTitle() . ' - ' . I18N::languageName($locale->languageTag())); $view_bag->set('missing_translations', $analyzer->getMissingTranslations()); $view_bag->set('non_used_translations', $analyzer->getMajNonUsedTranslations()); $view_bag->set('loading_stats', $analyzer->getLoadingStatistics()); ViewFactory::make('TranslationStatus', $this, $ctrl, $view_bag)->render(); }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; $title = $this->getTitle(); $menu = Theme::theme()->menuThemes(); if ($menu) { $content = '<div class="center theme_form">' . $menu . '</div><br>'; if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } } else { return ''; } }
/** * print a child ascendancy * * @param Individual $individual * @param int $sosa child sosa number * @param int $depth the ascendancy depth to show */ public function printChildAscendancy(Individual $individual, $sosa, $depth) { echo '<li>'; echo '<table><tbody><tr><td>'; if ($sosa === 1) { echo '<img src="', Theme::theme()->parameter('image-spacer'), '" height="3" width="', Theme::theme()->parameter('chart-descendancy-indent'), '"></td><td>'; } else { echo '<img src="', Theme::theme()->parameter('image-spacer'), '" height="3" width="2" alt="">'; echo '<img src="', Theme::theme()->parameter('image-hline'), '" height="3" width="', Theme::theme()->parameter('chart-descendancy-indent') - 2, '"></td><td>'; } FunctionsPrint::printPedigreePerson($individual, $this->showFull()); echo '</td><td>'; if ($sosa > 1) { FunctionsCharts::printUrlArrow('?rootid=' . $individual->getXref() . '&PEDIGREE_GENERATIONS=' . $this->generations . '&show_full=' . $this->showFull() . '&chart_style=' . $this->chart_style . '&ged=' . $individual->getTree()->getNameUrl(), I18N::translate('Ancestors of %s', $individual->getFullName()), 3); } echo '</td><td class="details1"> <span class="person_box' . ($sosa === 1 ? 'NN' : ($sosa % 2 ? 'F' : '')) . '">', I18N::number($sosa), '</span> '; echo '</td><td class="details1"> ', FunctionsCharts::getSosaName($sosa), '</td>'; echo '</tr></tbody></table>'; // Parents $family = $individual->getPrimaryChildFamily(); if ($family && $depth > 0) { // Marriage details echo '<span class="details1">'; echo '<img src="', Theme::theme()->parameter('image-spacer'), '" height="2" width="', Theme::theme()->parameter('chart-descendancy-indent'), '" alt=""><a href="#" onclick="return expand_layer(\'sosa_', $sosa, '\');" class="top"><i id="sosa_', $sosa, '_img" class="icon-minus" title="', I18N::translate('View family'), '"></i></a>'; echo ' <span class="person_box">', I18N::number($sosa * 2), '</span> ', I18N::translate('and'); echo ' <span class="person_boxF">', I18N::number($sosa * 2 + 1), '</span>'; if ($family->canShow()) { foreach ($family->getFacts(WT_EVENTS_MARR) as $fact) { echo ' <a href="', $family->getHtmlUrl(), '" class="details1">', $fact->summary(), '</a>'; } } echo '</span>'; // display parents recursively - or show empty boxes echo '<ul id="sosa_', $sosa, '" class="generation">'; if ($family->getHusband()) { $this->printChildAscendancy($family->getHusband(), $sosa * 2, $depth - 1); } if ($family->getWife()) { $this->printChildAscendancy($family->getWife(), $sosa * 2 + 1, $depth - 1); } echo '</ul>'; } echo '</li>'; }
/** * print the information for an individual chart box * * find and print a given individuals information for a pedigree chart * * @param Individual $person The person to print * @param int $show_full The style to print the box in, 0 for smaller boxes, 1 for larger boxes */ public static function printPedigreePerson(Individual $person = null, $show_full = 1) { switch ($show_full) { case 0: if ($person) { echo Theme::theme()->individualBoxSmall($person); } else { echo Theme::theme()->individualBoxSmallEmpty(); } break; case 1: if ($person) { echo Theme::theme()->individualBox($person); } else { echo Theme::theme()->individualBoxEmpty(); } break; } }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $WT_TREE; $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; $title = '<span dir="auto">' . I18N::translate('Welcome %s', Auth::user()->getRealNameHtml()) . '</span>'; $content = '<table><tr>'; $content .= '<td><a href="edituser.php"><i class="icon-mypage"></i><br>' . I18N::translate('My account') . '</a></td>'; $gedcomid = $WT_TREE->getUserPreference(Auth::user(), 'gedcomid'); if ($gedcomid) { $content .= '<td><a href="pedigree.php?rootid=' . $gedcomid . '&ged=' . $WT_TREE->getNameUrl() . '"><i class="icon-pedigree"></i><br>' . I18N::translate('My pedigree') . '</a></td>'; $content .= '<td><a href="individual.php?pid=' . $gedcomid . '&ged=' . $WT_TREE->getNameUrl() . '"><i class="icon-indis"></i><br>' . I18N::translate('My individual record') . '</a></td>'; } $content .= '</tr></table>'; if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $controller, $WT_TREE; $indi_xref = $controller->getSignificantIndividual()->getXref(); $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; $title = $WT_TREE->getTitleHtml(); $content = '<table><tr>'; $content .= '<td><a href="pedigree.php?rootid=' . $indi_xref . '&ged=' . $WT_TREE->getNameUrl() . '"><i class="icon-pedigree"></i><br>' . I18N::translate('Default chart') . '</a></td>'; $content .= '<td><a href="individual.php?pid=' . $indi_xref . '&ged=' . $WT_TREE->getNameUrl() . '"><i class="icon-indis"></i><br>' . I18N::translate('Default individual') . '</a></td>'; if (Site::getPreference('USE_REGISTRATION_MODULE') && !Auth::check()) { $content .= '<td><a href="' . WT_LOGIN_URL . '?action=register"><i class="icon-user_add"></i><br>' . I18N::translate('Request new user account') . '</a></td>'; } $content .= "</tr>"; $content .= "</table>"; if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }
/** * WelcomeBlock@index * * @param PageController $parent_controller * @param Tree $tree * @param string $block_id * @param string $template * @return $string */ public function index(PageController $parent_controller, Tree $tree, $block_id, $template) { $view_bag = new ViewBag(); if ($parent_controller && $tree) { $view_bag->set('tree', $tree); $view_bag->set('indi', $parent_controller->getSignificantIndividual()); $id = $this->module->getName() . $block_id; $class = $this->module->getName() . '_block'; $parent_controller->addInlineJavascript(' jQuery("#maj-new_passwd").hide(); jQuery("#maj-passwd_click").click(function() { jQuery("#maj-new_passwd").slideToggle(100, function() { jQuery("#maj-new_passwd_username").focus(); }); return false; }); '); if (Auth::isAdmin()) { $title = '<a class="icon-admin" title="' . I18N::translate('Configure') . '" href="block_edit.php?block_id=' . $block_id . '&ged=' . $tree->getNameHtml() . '&ctype=gedcom"></a>'; } else { $title = ''; } $title .= '<span dir="auto">' . $tree->getTitleHtml() . '</span>'; $piwik_enabled = $this->module->getBlockSetting($block_id, 'piwik_enabled', false); $view_bag->set('piwik_enabled', $piwik_enabled); if ($piwik_enabled) { $parent_controller->addInlineJavascript('$("#piwik_stats") .load("module.php?mod=' . $this->module->getName() . '&mod_action=Piwik&block_id=' . $block_id . '");'); } $content = ViewFactory::make('WelcomeBlock', $this, new BaseController(), $view_bag)->getHtmlPartial(); if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } } }
/** * Generate both the HTML and PNG components of the fan chart * * The HTML and PNG components both require the same co-ordinate calculations, * so we generate them using the same code, but we send them in separate * HTTP requests. * * @param string $what "png" or "html" * * @return string */ public function generateFanChart($what) { $treeid = $this->sosaAncestors($this->generations); $fanw = 640 * $this->fan_width / 100; $fandeg = 90 * $this->fan_style; $html = ''; $treesize = count($treeid) + 1; // generations count $gen = log($treesize) / log(2) - 1; $sosa = $treesize - 1; // fan size if ($fandeg == 0) { $fandeg = 360; } $fandeg = min($fandeg, 360); $fandeg = max($fandeg, 90); $cx = $fanw / 2 - 1; // center x $cy = $cx; // center y $rx = $fanw - 1; $rw = $fanw / ($gen + 1); $fanh = $fanw; // fan height if ($fandeg == 180) { $fanh = round($fanh * ($gen + 1) / ($gen * 2)); } if ($fandeg == 270) { $fanh = round($fanh * 0.86); } $scale = $fanw / 640; // image init $image = ImageCreate($fanw, $fanh); $white = ImageColorAllocate($image, 0xff, 0xff, 0xff); ImageFilledRectangle($image, 0, 0, $fanw, $fanh, $white); ImageColorTransparent($image, $white); $color = ImageColorAllocate($image, hexdec(substr(Theme::theme()->parameter('chart-font-color'), 0, 2)), hexdec(substr(Theme::theme()->parameter('chart-font-color'), 2, 2)), hexdec(substr(Theme::theme()->parameter('chart-font-color'), 4, 2))); $bgcolor = ImageColorAllocate($image, hexdec(substr(Theme::theme()->parameter('chart-background-u'), 0, 2)), hexdec(substr(Theme::theme()->parameter('chart-background-u'), 2, 2)), hexdec(substr(Theme::theme()->parameter('chart-background-u'), 4, 2))); $bgcolorM = ImageColorAllocate($image, hexdec(substr(Theme::theme()->parameter('chart-background-m'), 0, 2)), hexdec(substr(Theme::theme()->parameter('chart-background-m'), 2, 2)), hexdec(substr(Theme::theme()->parameter('chart-background-m'), 4, 2))); $bgcolorF = ImageColorAllocate($image, hexdec(substr(Theme::theme()->parameter('chart-background-f'), 0, 2)), hexdec(substr(Theme::theme()->parameter('chart-background-f'), 2, 2)), hexdec(substr(Theme::theme()->parameter('chart-background-f'), 4, 2))); // imagemap $imagemap = '<map id="fanmap" name="fanmap">'; // loop to create fan cells while ($gen >= 0) { // clean current generation area $deg2 = 360 + ($fandeg - 180) / 2; $deg1 = $deg2 - $fandeg; ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bgcolor, IMG_ARC_PIE); $rx -= 3; // calculate new angle $p2 = pow(2, $gen); $angle = $fandeg / $p2; $deg2 = 360 + ($fandeg - 180) / 2; $deg1 = $deg2 - $angle; // special case for rootid cell if ($gen == 0) { $deg1 = 90; $deg2 = 360 + $deg1; } // draw each cell while ($sosa >= $p2) { $person = $treeid[$sosa]; if ($person) { $name = $person->getFullName(); $addname = $person->getAddName(); $text = I18N::reverseText($name); if ($addname) { $text .= "\n" . I18N::reverseText($addname); } $text .= "\n" . I18N::reverseText($person->getLifeSpan()); switch ($person->getSex()) { case 'M': $bg = $bgcolorM; break; case 'F': $bg = $bgcolorF; break; default: $bg = $bgcolor; break; } ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bg, IMG_ARC_PIE); // split and center text by lines $wmax = (int) ($angle * 7 / Theme::theme()->parameter('chart-font-size') * $scale); $wmax = min($wmax, 35 * $scale); if ($gen == 0) { $wmax = min($wmax, 17 * $scale); } $text = $this->splitAlignText($text, $wmax); // text angle $tangle = 270 - ($deg1 + $angle / 2); if ($gen == 0) { $tangle = 0; } // calculate text position $deg = $deg1 + 0.44; if ($deg2 - $deg1 > 40) { $deg = $deg1 + ($deg2 - $deg1) / 11; } if ($deg2 - $deg1 > 80) { $deg = $deg1 + ($deg2 - $deg1) / 7; } if ($deg2 - $deg1 > 140) { $deg = $deg1 + ($deg2 - $deg1) / 4; } if ($gen == 0) { $deg = 180; } $rad = deg2rad($deg); $mr = ($rx - $rw / 4) / 2; if ($gen > 0 && $deg2 - $deg1 > 80) { $mr = $rx / 2; } $tx = $cx + $mr * cos($rad); $ty = $cy - $mr * -sin($rad); if ($sosa == 1) { $ty -= $mr / 2; } // print text ImageTtfText($image, Theme::theme()->parameter('chart-font-size'), $tangle, $tx, $ty, $color, Theme::theme()->parameter('chart-font-name'), $text); $imagemap .= '<area shape="poly" coords="'; // plot upper points $mr = $rx / 2; $deg = $deg1; while ($deg <= $deg2) { $rad = deg2rad($deg); $tx = round($cx + $mr * cos($rad)); $ty = round($cy - $mr * -sin($rad)); $imagemap .= "{$tx},{$ty},"; $deg += ($deg2 - $deg1) / 6; } // plot lower points $mr = ($rx - $rw) / 2; $deg = $deg2; while ($deg >= $deg1) { $rad = deg2rad($deg); $tx = round($cx + $mr * cos($rad)); $ty = round($cy - $mr * -sin($rad)); $imagemap .= "{$tx},{$ty},"; $deg -= ($deg2 - $deg1) / 6; } // join first point $mr = $rx / 2; $deg = $deg1; $rad = deg2rad($deg); $tx = round($cx + $mr * cos($rad)); $ty = round($cy - $mr * -sin($rad)); $imagemap .= "{$tx},{$ty}"; // add action url $pid = $person->getXref(); $imagemap .= '" href="#' . $pid . '"'; $tempURL = 'fanchart.php?rootid=' . $pid . '&generations=' . $this->generations . '&fan_width=' . $this->fan_width . '&fan_style=' . $this->fan_style . '&ged=' . $person->getTree()->getNameUrl(); $html .= '<div id="' . $pid . '" class="fan_chart_menu">'; $html .= '<div class="person_box"><div class="details1">'; $html .= '<a href="' . $person->getHtmlUrl() . '" class="name1">' . $name; if ($addname) { $html .= $addname; } $html .= '</a>'; $html .= '<ul class="charts">'; $html .= '<li><a href="pedigree.php?rootid=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '" >' . I18N::translate('Pedigree') . '</a></li>'; if (Module::getModuleByName('googlemap')) { $html .= '<li><a href="module.php?mod=googlemap&mod_action=pedigree_map&rootid=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '">' . I18N::translate('Pedigree map') . '</a></li>'; } $gedcomid = $person->getTree()->getUserPreference(Auth::user(), 'gedcomid'); if ($gedcomid && $gedcomid != $pid) { $html .= '<li><a href="relationship.php?pid1=' . $gedcomid . '&pid2=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '">' . I18N::translate('Relationship to me') . '</a></li>'; } $html .= '<li><a href="descendancy.php?rootid=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '" >' . I18N::translate('Descendants') . '</a></li>'; $html .= '<li><a href="ancestry.php?rootid=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '">' . I18N::translate('Ancestors') . '</a></li>'; $html .= '<li><a href="compact.php?rootid=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '">' . I18N::translate('Compact tree') . '</a></li>'; $html .= '<li><a href="' . $tempURL . '">' . I18N::translate('Fan chart') . '</a></li>'; $html .= '<li><a href="hourglass.php?rootid=' . $pid . '&ged=' . $person->getTree()->getNameUrl() . '">' . I18N::translate('Hourglass chart') . '</a></li>'; if (Module::getModuleByName('tree')) { $html .= '<li><a href="module.php?mod=tree&mod_action=treeview&ged=' . $person->getTree()->getNameUrl() . '&rootid=' . $pid . '">' . I18N::translate('Interactive tree') . '</a></li>'; } $html .= '</ul>'; // spouse(s) and children foreach ($person->getSpouseFamilies() as $family) { $spouse = $family->getSpouse($person); if ($spouse) { $html .= '<a href="' . $spouse->getHtmlUrl() . '" class="name1">' . $spouse->getFullName() . '</a>'; $kids = $family->getChildren(); if ($kids) { $html .= '<ul class="children">'; foreach ($kids as $child) { $html .= '<li><a href="' . $child->getHtmlUrl() . '" class="name1">' . $child->getFullName() . '</a></li>'; } $html .= '</ul>'; } } } // siblings foreach ($person->getChildFamilies() as $family) { $children = $family->getChildren(); if ($children) { $html .= '<div class="name1">'; // With two children in a family, you have only one sibling. $html .= count($children) > 2 ? I18N::translate('Siblings') : I18N::translate('Sibling'); $html .= '</div>'; $html .= '<ul class="siblings">'; foreach ($children as $sibling) { if ($sibling !== $person) { $html .= '<li><a href="' . $sibling->getHtmlUrl() . '" class="name1"> ' . $sibling->getFullName() . '</a></li>'; } } $html .= '</ul>'; } } $html .= '</div></div>'; $html .= '</div>'; $imagemap .= ' alt="' . strip_tags($person->getFullName()) . '" title="' . strip_tags($person->getFullName()) . '">'; } $deg1 -= $angle; $deg2 -= $angle; $sosa--; } $rx -= $rw; $gen--; } $imagemap .= '</map>'; switch ($what) { case 'html': return $html . $imagemap . '<div id="fan_chart_img"><img src="' . WT_SCRIPT_NAME . '?rootid=' . $this->root->getXref() . '&fan_style=' . $this->fan_style . '&generations=' . $this->generations . '&fan_width=' . $this->fan_width . '&img=1" width="' . $fanw . '" height="' . $fanh . '" alt="' . strip_tags($this->getPageTitle()) . '" usemap="#fanmap"></div>'; case 'png': ImageStringUp($image, 1, $fanw - 10, $fanh / 3, WT_BASE_URL, $color); ob_start(); ImagePng($image); ImageDestroy($image); return ob_get_clean(); default: throw new \InvalidArgumentException(__METHOD__ . ' ' . $what); } }
/** * Load this sidebar synchronously. * * @return string */ public function getSidebarContent() { global $controller, $WT_TREE; // Fetch a list of the initial letters of all surnames in the database $initials = QueryName::surnameAlpha($WT_TREE, true, false, false); $controller->addInlineJavascript(' var loadedNames = new Array(); function isearchQ() { var query = jQuery("#sb_indi_name").val(); if (query.length>1) { jQuery("#sb_indi_content").load("module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=individuals&search="+query); } } var timerid = null; jQuery("#sb_indi_name").keyup(function(e) { if (timerid) window.clearTimeout(timerid); timerid = window.setTimeout("isearchQ()", 500); }); jQuery("#sb_content_individuals").on("click", ".sb_indi_letter", function() { jQuery("#sb_indi_content").load(this.href); return false; }); jQuery("#sb_content_individuals").on("click", ".sb_indi_surname", function() { var element = jQuery(this); var surname = element.data("surname"); var alpha = element.data("alpha"); if (!loadedNames[surname]) { jQuery.ajax({ url: "module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=individuals&alpha=" + encodeURIComponent(alpha) + "&surname=" + encodeURIComponent(surname), cache: false, success: function(html) { jQuery("div.name_tree_div", element.closest("li")) .html(html) .show("fast") .css("list-style-image", "url(' . Theme::theme()->parameter('image-minus') . ')"); loadedNames[surname]=2; } }); } else if (loadedNames[surname]==1) { loadedNames[surname]=2; jQuery("div.name_tree_div", jQuery(this).closest("li")) .show() .css("list-style-image", "url(' . Theme::theme()->parameter('image-minus') . ')"); } else { loadedNames[surname]=1; jQuery("div.name_tree_div", jQuery(this).closest("li")) .hide("fast") .css("list-style-image", "url(' . Theme::theme()->parameter('image-plus') . ')"); } return false; }); '); $out = '<form method="post" action="module.php?mod=' . $this->getName() . '&mod_action=ajax" onsubmit="return false;"><input type="search" name="sb_indi_name" id="sb_indi_name" placeholder="' . I18N::translate('Search') . '"><p>'; foreach ($initials as $letter => $count) { switch ($letter) { case '@': $html = I18N::translateContext('Unknown surname', '…'); break; case ',': $html = I18N::translate('None'); break; case ' ': $html = ' '; break; default: $html = $letter; break; } $html = '<a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=individuals&alpha=' . urlencode($letter) . '" class="sb_indi_letter">' . $html . '</a>'; $out .= $html . " "; } $out .= '</p>'; $out .= '<div id="sb_indi_content">'; $out .= '</div></form>'; return $out; }
$sortkey = 100000000.0; // birth date missing => sort last } $children[$child->getXref()] = $sortkey; } if ($option === 'bybirth') { asort($children); } $i = 0; foreach ($children as $id => $child) { echo '<li style="cursor:move; margin-bottom:2px; position:relative;"'; if (!in_array($id, $ids)) { echo ' class="facts_value new"'; } echo ' id="li_', $id, '">'; echo Theme::theme()->individualBoxLarge(Individual::getInstance($id, $WT_TREE)); echo '<input type="hidden" name="order[', $id, ']" value="', $i, '">'; echo '</li>'; $i++; } echo '</ul>'; ?> <table> <?php echo keep_chan($family); ?> </table> <p id="save-cancel"> <input type="submit" class="save" value="<?php echo I18N::translate('save'); ?>
echo I18N::translate('Site members can send each other messages. You can choose to how these messages are sent to you, or choose not receive them at all.'); ?> </p> </div> </div> <!-- THEME --> <div class="form-group"> <label class="control-label col-sm-3" for="theme"> <?php echo I18N::translate('Theme'); ?> </label> <div class="col-sm-9"> <?php echo FunctionsEdit::selectEditControl('theme', Theme::themeNames(), I18N::translate('<default theme>'), $user->getPreference('theme'), 'class="form-control"'); ?> </div> </div> <!-- COMMENTS --> <div class="form-group"> <label class="control-label col-sm-3" for="comment"> <?php echo I18N::translate('Administrator comments on user'); ?> </label> <div class="col-sm-9"> <textarea class="form-control" id="comment" name="comment" rows="5" maxlength="255"><?php echo Filter::escapeHtml($user->getPreference('comment')); ?>
echo Filter::escapeHtml(Site::getPreference('SMTP_HELO')); ?> " placeholder="localhost" maxlength="255" pattern="[a-z0-9-]+(\.[a-z0-9-]+)*"> <p class="small text-muted"> <?php echo I18N::translate('Many mail servers require that the sending server identifies itself correctly, using a valid domain name.'); ?> </p> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <p class="small text-muted"> <?php echo Theme::theme()->htmlAlert(I18N::translate('To use a Google mail account, use the following settings: server=smtp.gmail.com, port=587, security=tls, username=xxxxx@gmail.com, password=[your gmail password]'), 'info', false); ?> </p> </div> </div> <?php } elseif (Filter::get('action') === 'login') { ?> <input type="hidden" name="action" value="login"> <!-- LOGIN_URL --> <div class="form-group"> <label for="LOGIN_URL" class="col-sm-3 control-label"> <?php echo I18N::translate('Login URL');
/** * Print empty box */ private function printEmptyBox() { echo $this->showFull() ? Theme::theme()->individualBoxEmpty() : Theme::theme()->individualBoxSmallEmpty(); }
/** * Print a fact record, for the individual/family/source/repository/etc. pages. * * Although a Fact has a parent object, we also need to know * the GedcomRecord for which we are printing it. For example, * we can show the death of X on the page of Y, or the marriage * of X+Y on the page of Z. We need to know both records to * calculate ages, relationships, etc. * * @param Fact $fact * @param GedcomRecord $record */ public static function printFact(Fact $fact, GedcomRecord $record) { static $n_chil = 0, $n_gchi = 0; $parent = $fact->getParent(); // Some facts don't get printed here ... switch ($fact->getTag()) { case 'NOTE': self::printMainNotes($fact, 1); return; case 'SOUR': self::printMainSources($fact, 1); return; case 'OBJE': self::printMainMedia($fact, 1); return; case 'FAMC': case 'FAMS': case 'CHIL': case 'HUSB': case 'WIFE': // These are internal links, not facts return; case '_WT_OBJE_SORT': // These links are used internally to record the sort order. return; default: // Hide unrecognized/custom tags? if ($fact->getParent()->getTree()->getPreference('HIDE_GEDCOM_ERRORS') && !GedcomTag::isTag($fact->getTag())) { return; } break; } // Who is this fact about? Need it to translate fact label correctly if ($parent instanceof Family && $record instanceof Individual) { // Family event $label_person = $fact->getParent()->getSpouse($record); } else { // Individual event $label_person = $parent; } // New or deleted facts need different styling $styleadd = ''; if ($fact->isPendingAddition()) { $styleadd = 'new'; } if ($fact->isPendingDeletion()) { $styleadd = 'old'; } // Event of close relative if (preg_match('/^_[A-Z_]{3,5}_[A-Z0-9]{4}$/', $fact->getTag())) { $styleadd = trim($styleadd . ' rela'); } // Event of close associates if ($fact->getFactId() == 'asso') { $styleadd = trim($styleadd . ' rela'); } // historical facts if ($fact->getFactId() == 'histo') { $styleadd = trim($styleadd . ' histo'); } // Does this fact have a type? if (preg_match('/\\n2 TYPE (.+)/', $fact->getGedcom(), $match)) { $type = $match[1]; } else { $type = ''; } switch ($fact->getTag()) { case 'EVEN': case 'FACT': if (GedcomTag::isTag($type)) { // Some users (just Meliza?) use "1 EVEN/2 TYPE BIRT". Translate the TYPE. $label = GedcomTag::getLabel($type, $label_person); $type = ''; // Do not print this again } elseif ($type) { // We don't have a translation for $type - but a custom translation might exist. $label = I18N::translate(Filter::escapeHtml($type)); $type = ''; // Do not print this again } else { // An unspecified fact/event $label = $fact->getLabel(); } break; case 'MARR': // This is a hack for a proprietory extension. Is it still used/needed? $utype = strtoupper($type); if ($utype == 'CIVIL' || $utype == 'PARTNERS' || $utype == 'RELIGIOUS') { $label = GedcomTag::getLabel('MARR_' . $utype, $label_person); $type = ''; // Do not print this again } else { $label = $fact->getLabel(); } break; default: // Normal fact/event $label = $fact->getLabel(); break; } echo '<tr class="', $styleadd, '">'; echo '<td class="descriptionbox width20">'; if ($fact->getParent()->getTree()->getPreference('SHOW_FACT_ICONS')) { echo Theme::theme()->icon($fact), ' '; } if ($fact->getFactId() != 'histo' && $fact->canEdit()) { ?> <a href="#" title="<?php echo I18N::translate('Edit'); ?> " onclick="return edit_record('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><?php echo $label; ?> </a> <div class="editfacts"> <div class="editlink"> <a href="#" title="<?php echo I18N::translate('Edit'); ?> " class="editicon" onclick="return edit_record('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo I18N::translate('Edit'); ?> </span></a> </div> <div class="copylink"> <a href="#" title="<?php echo I18N::translate('Copy'); ?> " class="copyicon" onclick="return copy_fact('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo I18N::translate('Copy'); ?> </span></a> </div> <div class="deletelink"> <a href="#" title="<?php echo I18N::translate('Delete'); ?> " class="deleteicon" onclick="return delete_fact('<?php echo I18N::translate('Are you sure you want to delete this fact?'); ?> ', '<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo I18N::translate('Delete'); ?> </span></a> </div> </div> <?php } else { echo $label; } switch ($fact->getTag()) { case '_BIRT_CHIL': echo '<br>', I18N::translate('#%s', ++$n_chil); break; case '_BIRT_GCHI': case '_BIRT_GCH1': case '_BIRT_GCH2': echo '<br>', I18N::translate('#%s', ++$n_gchi); break; } echo '</td><td class="optionbox ', $styleadd, ' wrap">'; // Event from another record? if ($parent !== $record) { if ($parent instanceof Family) { foreach ($parent->getSpouses() as $spouse) { if ($record !== $spouse) { echo '<a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> — '; } } echo '<a href="', $parent->getHtmlUrl(), '">', I18N::translate('View family'), '</a><br>'; } elseif ($parent instanceof Individual) { echo '<a href="', $parent->getHtmlUrl(), '">', $parent->getFullName(), '</a><br>'; } } // Print the value of this fact/event switch ($fact->getTag()) { case 'ADDR': echo $fact->getValue(); break; case 'AFN': echo '<div class="field"><a href="https://familysearch.org/search/tree/results#count=20&query=afn:', rawurlencode($fact->getValue()), '" target="new">', Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'ASSO': // we handle this later, in format_asso_rela_record() break; case 'EMAIL': case 'EMAI': case '_EMAIL': echo '<div class="field"><a href="mailto:', Filter::escapeHtml($fact->getValue()), '">', Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'FILE': if (Auth::isEditor($fact->getParent()->getTree())) { echo '<div class="field">', Filter::escapeHtml($fact->getValue()), '</div>'; } break; case 'RESN': echo '<div class="field">'; switch ($fact->getValue()) { case 'none': // Note: "1 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private record to public". echo '<i class="icon-resn-none"></i> ', I18N::translate('Show to visitors'); break; case 'privacy': echo '<i class="icon-class-none"></i> ', I18N::translate('Show to members'); break; case 'confidential': echo '<i class="icon-confidential-none"></i> ', I18N::translate('Show to managers'); break; case 'locked': echo '<i class="icon-locked-none"></i> ', I18N::translate('Only managers can edit'); break; default: echo Filter::escapeHtml($fact->getValue()); break; } echo '</div>'; break; case 'PUBL': // Publication details might contain URLs. echo '<div class="field">', Filter::expandUrls($fact->getValue()), '</div>'; break; case 'REPO': if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $fact->getValue(), $match)) { self::printRepositoryRecord($match[1]); } else { echo '<div class="error">', Filter::escapeHtml($fact->getValue()), '</div>'; } break; case 'URL': case '_URL': case 'WWW': echo '<div class="field"><a href="', Filter::escapeHtml($fact->getValue()), '">', Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'TEXT': // 0 SOUR / 1 TEXT echo '<div class="field">', nl2br(Filter::escapeHtml($fact->getValue()), false), '</div>'; break; default: // Display the value for all other facts/events switch ($fact->getValue()) { case '': // Nothing to display break; case 'N': // Not valid GEDCOM echo '<div class="field">', I18N::translate('No'), '</div>'; break; case 'Y': // Do not display "Yes". break; default: if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $fact->getValue(), $match)) { $target = GedcomRecord::getInstance($match[1], $fact->getParent()->getTree()); if ($target) { echo '<div><a href="', $target->getHtmlUrl(), '">', $target->getFullName(), '</a></div>'; } else { echo '<div class="error">', Filter::escapeHtml($fact->getValue()), '</div>'; } } else { echo '<div class="field"><span dir="auto">', Filter::escapeHtml($fact->getValue()), '</span></div>'; } break; } break; } // Print the type of this fact/event if ($type) { $utype = strtoupper($type); // Events of close relatives, e.g. _MARR_CHIL if (substr($fact->getTag(), 0, 6) == '_MARR_' && ($utype == 'CIVIL' || $utype == 'PARTNERS' || $utype == 'RELIGIOUS')) { // Translate MARR/TYPE using the code that supports MARR_CIVIL, etc. tags $type = GedcomTag::getLabel('MARR_' . $utype); } else { // Allow (custom) translations for other types $type = I18N::translate($type); } echo GedcomTag::getLabelValue('TYPE', Filter::escapeHtml($type)); } // Print the date of this fact/event echo FunctionsPrint::formatFactDate($fact, $record, true, true); // Print the place of this fact/event echo '<div class="place">', FunctionsPrint::formatFactPlace($fact, true, true, true), '</div>'; // A blank line between the primary attributes (value, date, place) and the secondary ones echo '<br>'; $addr = $fact->getAttribute('ADDR'); if ($addr) { echo GedcomTag::getLabelValue('ADDR', $addr); } // Print the associates of this fact/event if ($fact->getFactId() !== 'asso') { echo self::formatAssociateRelationship($fact); } // Print any other "2 XXXX" attributes, in the order in which they appear. preg_match_all('/\\n2 (' . WT_REGEX_TAG . ') (.+)/', $fact->getGedcom(), $matches, PREG_SET_ORDER); foreach ($matches as $match) { switch ($match[1]) { case 'DATE': case 'TIME': case 'AGE': case 'PLAC': case 'ADDR': case 'ALIA': case 'ASSO': case '_ASSO': case 'DESC': case 'RELA': case 'STAT': case 'TEMP': case 'TYPE': case 'FAMS': case 'CONT': // These were already shown at the beginning break; case 'NOTE': case 'OBJE': case 'SOUR': // These will be shown at the end break; case 'EVEN': // 0 SOUR / 1 DATA / 2 EVEN / 3 DATE / 3 PLAC $events = array(); foreach (preg_split('/ *, */', $match[2]) as $event) { $events[] = GedcomTag::getLabel($event); } if (count($events) == 1) { echo GedcomTag::getLabelValue('EVEN', $event); } else { echo GedcomTag::getLabelValue('EVEN', implode(I18N::$list_separator, $events)); } if (preg_match('/\\n3 DATE (.+)/', $fact->getGedcom(), $date_match)) { $date = new Date($date_match[1]); echo GedcomTag::getLabelValue('DATE', $date->display()); } if (preg_match('/\\n3 PLAC (.+)/', $fact->getGedcom(), $plac_match)) { echo GedcomTag::getLabelValue('PLAC', $plac_match[1]); } break; case 'FAMC': // 0 INDI / 1 ADOP / 2 FAMC / 3 ADOP $family = Family::getInstance(str_replace('@', '', $match[2]), $fact->getParent()->getTree()); if ($family) { echo GedcomTag::getLabelValue('FAM', '<a href="' . $family->getHtmlUrl() . '">' . $family->getFullName() . '</a>'); if (preg_match('/\\n3 ADOP (HUSB|WIFE|BOTH)/', $fact->getGedcom(), $match)) { echo GedcomTag::getLabelValue('ADOP', GedcomCodeAdop::getValue($match[1], $label_person)); } } else { echo GedcomTag::getLabelValue('FAM', '<span class="error">' . $match[2] . '</span>'); } break; case '_WT_USER': $user = User::findByIdentifier($match[2]); // may not exist if ($user) { echo GedcomTag::getLabelValue('_WT_USER', $user->getRealNameHtml()); } else { echo GedcomTag::getLabelValue('_WT_USER', Filter::escapeHtml($match[2])); } break; case 'RESN': switch ($match[2]) { case 'none': // Note: "2 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private fact to public". echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-none"></i> ' . I18N::translate('Show to visitors')); break; case 'privacy': echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-privacy"></i> ' . I18N::translate('Show to members')); break; case 'confidential': echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-confidential"></i> ' . I18N::translate('Show to managers')); break; case 'locked': echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-locked"></i> ' . I18N::translate('Only managers can edit')); break; default: echo GedcomTag::getLabelValue('RESN', Filter::escapeHtml($match[2])); break; } break; case 'CALN': echo GedcomTag::getLabelValue('CALN', Filter::expandUrls($match[2])); break; case 'FORM': // 0 OBJE / 1 FILE / 2 FORM / 3 TYPE echo GedcomTag::getLabelValue('FORM', $match[2]); if (preg_match('/\\n3 TYPE (.+)/', $fact->getGedcom(), $type_match)) { echo GedcomTag::getLabelValue('TYPE', GedcomTag::getFileFormTypeValue($type_match[1])); } break; case 'URL': case '_URL': case 'WWW': $link = '<a href="' . Filter::escapeHtml($match[2]) . '">' . Filter::escapeHtml($match[2]) . '</a>'; echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], $link); break; default: if (!$fact->getParent()->getTree()->getPreference('HIDE_GEDCOM_ERRORS') || GedcomTag::isTag($match[1])) { if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $match[2], $xmatch)) { // Links $linked_record = GedcomRecord::getInstance($xmatch[1], $fact->getParent()->getTree()); if ($linked_record) { $link = '<a href="' . $linked_record->getHtmlUrl() . '">' . $linked_record->getFullName() . '</a>'; echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], $link); } else { echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], Filter::escapeHtml($match[2])); } } else { // Non links echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], Filter::escapeHtml($match[2])); } } break; } } echo self::printFactSources($fact->getGedcom(), 2); echo FunctionsPrint::printFactNotes($fact->getGedcom(), 2); self::printMediaLinks($fact->getGedcom(), 2); echo '</td></tr>'; }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $controller; $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; $controller->addInlineJavascript(' jQuery("#new_passwd").hide(); jQuery("#passwd_click").click(function() { jQuery("#new_passwd").slideToggle(100, function() { jQuery("#new_passwd_username").focus(); }); return false; }); '); if (Auth::check()) { $title = I18N::translate('Logout'); $content = '<div class="center"><form method="post" action="logout.php" name="logoutform" onsubmit="return true;">'; $content .= '<br><a href="../../edituser.php" class="name2">' . I18N::translate('Logged in as ') . ' ' . Auth::user()->getRealNameHtml() . '</a><br><br>'; $content .= '<input type="submit" value="' . I18N::translate('Logout') . '">'; $content .= '<br><br></form></div>'; } else { $title = I18N::translate('Login'); $content = '<div id="login-box"> <form id="login-form" name="login-form" method="post" action="' . WT_LOGIN_URL . '"> <input type="hidden" name="action" value="login">'; $content .= '<div> <label for="username">' . I18N::translate('Username') . '<input type="text" id="username" name="username" class="formField"> </label> </div> <div> <label for="password">' . I18N::translate('Password') . '<input type="password" id="password" name="password" class="formField"> </label> </div> <div> <input type="submit" value="' . I18N::translate('Login') . '"> </div> <div> <a href="#" id="passwd_click">' . I18N::translate('Request new password') . '</a> </div>'; if (Site::getPreference('USE_REGISTRATION_MODULE')) { $content .= '<div><a href="' . WT_LOGIN_URL . '?action=register">' . I18N::translate('Request new user account') . '</a></div>'; } $content .= '</form>'; // close "login-form" // hidden New Password block $content .= '<div id="new_passwd"> <form id="new_passwd_form" name="new_passwd_form" action="' . WT_LOGIN_URL . '" method="post"> <input type="hidden" name="time" value=""> <input type="hidden" name="action" value="requestpw"> <h4>' . I18N::translate('Lost password request') . '</h4> <div> <label for="new_passwd_username">' . I18N::translate('Username or email address') . '<input type="text" id="new_passwd_username" name="new_passwd_username" value=""> </label> </div> <div><input type="submit" value="' . I18N::translate('continue') . '"></div> </form> </div>'; //"new_passwd" $content .= '</div>'; //"login-box" } if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }
<div class="label"> <label for="form_theme"> <?php echo I18N::translate('Theme'); ?> </label> </div> <div class="value"> <select id="form_theme" name="form_theme"> <option value=""> <?php echo Filter::escapeHtml(I18N::translate('<default theme>')); ?> </option> <?php foreach (Theme::themeNames() as $theme_id => $theme_name) { ?> <option value="<?php echo $theme_id; ?> " <?php echo $theme_id === Auth::user()->getPreference('theme') ? 'selected' : ''; ?> > <?php echo $theme_name; ?> </option> <?php } ?>
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $ctype, $WT_TREE; switch (Filter::get('action')) { case 'deletenews': $news_id = Filter::getInteger('news_id'); if ($news_id) { Database::prepare("DELETE FROM `##news` WHERE news_id = ?")->execute(array($news_id)); } break; } $articles = Database::prepare("SELECT SQL_CACHE news_id, user_id, gedcom_id, UNIX_TIMESTAMP(updated) + :offset AS updated, subject, body FROM `##news` WHERE user_id = :user_id ORDER BY updated DESC")->execute(array('offset' => WT_TIMESTAMP_OFFSET, 'user_id' => Auth::id()))->fetchAll(); $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; $title = $this->getTitle(); $content = ''; if (empty($articles)) { $content .= '<p>' . I18N::translate('You have not created any journal items.') . '</p>'; } foreach ($articles as $article) { $content .= '<div class="journal_box">'; $content .= '<div class="news_title">' . Filter::escapeHtml($article->subject) . '</div>'; $content .= '<div class="news_date">' . FunctionsDate::formatTimestamp($article->updated) . '</div>'; if ($article->body == strip_tags($article->body)) { $article->body = nl2br($article->body, false); } $content .= $article->body; $content .= '<a href="#" onclick="window.open(\'editnews.php?news_id=\'+' . $article->news_id . ', \'_blank\', indx_window_specs); return false;">' . I18N::translate('Edit') . '</a>'; $content .= ' | '; $content .= '<a href="index.php?action=deletenews&news_id=' . $article->news_id . '&ctype=' . $ctype . '&ged=' . $WT_TREE->getNameHtml() . '" onclick="return confirm(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeHtml($article->subject)) . "');\">" . I18N::translate('Delete') . '</a><br>'; $content .= '</div><br>'; } $content .= '<p><a href="#" onclick="window.open(\'editnews.php?user_id=' . Auth::id() . '\', \'_blank\', indx_window_specs); return false;">' . I18N::translate('Add a journal entry') . '</a></p>'; if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }
/** * Build a map for an individual. * * @param Individual $indi */ private function buildIndividualMap(Individual $indi) { $GM_MAX_ZOOM = $this->getSetting('GM_MAX_ZOOM'); $indifacts = $indi->getFacts(); foreach ($indi->getSpouseFamilies() as $family) { $indifacts = array_merge($indifacts, $family->getFacts()); } Functions::sortFacts($indifacts); // Create the markers list array $gmarks = array(); $i = 0; foreach ($indifacts as $fact) { if (!$fact->getPlace()->isEmpty()) { $ctla = preg_match("/\\d LATI (.*)/", $fact->getGedcom(), $match1); $ctlo = preg_match("/\\d LONG (.*)/", $fact->getGedcom(), $match2); if ($fact->getParent() instanceof Family) { $spouse = $fact->getParent()->getSpouse($indi); } else { $spouse = null; } if ($ctla && $ctlo) { $i++; $gmarks[$i] = array('class' => 'optionbox', 'date' => $fact->getDate()->display(true), 'fact_label' => $fact->getLabel(), 'image' => $spouse ? $spouse->displayImage() : Theme::theme()->icon($fact), 'info' => $fact->getValue(), 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $match1[1]), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $match2[1]), 'name' => $spouse ? '<a href="' . $spouse->getHtmlUrl() . '"' . $spouse->getFullName() . '</a>' : '', 'pl_icon' => '', 'place' => $fact->getPlace()->getFullName(), 'sv_bearing' => '0', 'sv_elevation' => '0', 'sv_lati' => '0', 'sv_long' => '0', 'sv_zoom' => '0', 'tooltip' => $fact->getPlace()->getGedcomName()); } else { $latlongval = $this->getLatitudeAndLongitudeFromPlaceLocation($fact->getPlace()->getGedcomName()); if ($latlongval && $latlongval->pl_lati && $latlongval->pl_long) { $i++; $gmarks[$i] = array('class' => 'optionbox', 'date' => $fact->getDate()->display(true), 'fact_label' => $fact->getLabel(), 'image' => $spouse ? $spouse->displayImage() : Theme::theme()->icon($fact), 'info' => $fact->getValue(), 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $latlongval->pl_lati), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $latlongval->pl_long), 'name' => $spouse ? '<a href="' . $spouse->getHtmlUrl() . '"' . $spouse->getFullName() . '</a>' : '', 'pl_icon' => $latlongval->pl_icon, 'place' => $fact->getPlace()->getFullName(), 'sv_bearing' => $latlongval->sv_bearing, 'sv_elevation' => $latlongval->sv_elevation, 'sv_lati' => $latlongval->sv_lati, 'sv_long' => $latlongval->sv_long, 'sv_zoom' => $latlongval->sv_zoom, 'tooltip' => $fact->getPlace()->getGedcomName()); if ($GM_MAX_ZOOM > $latlongval->pl_zoom) { $GM_MAX_ZOOM = $latlongval->pl_zoom; } } } } } // Add children to the markers list array foreach ($indi->getSpouseFamilies() as $family) { foreach ($family->getChildren() as $child) { $birth = $child->getFirstFact('BIRT'); if ($birth) { $birthrec = $birth->getGedcom(); if (!$birth->getPlace()->isEmpty()) { $ctla = preg_match('/\\n4 LATI (.+)/', $birthrec, $match1); $ctlo = preg_match('/\\n4 LONG (.+)/', $birthrec, $match2); if ($ctla && $ctlo) { $i++; $gmarks[$i] = array('date' => $birth->getDate()->display(true), 'image' => $child->displayImage(), 'info' => '', 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $match1[1]), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $match2[1]), 'name' => '<a href="' . $child->getHtmlUrl() . '"' . $child->getFullName() . '</a>', 'pl_icon' => '', 'place' => $birth->getPlace()->getFullName(), 'sv_bearing' => '0', 'sv_elevation' => '0', 'sv_lati' => '0', 'sv_long' => '0', 'sv_zoom' => '0', 'tooltip' => $birth->getPlace()->getGedcomName()); switch ($child->getSex()) { case 'F': $gmarks[$i]['fact_label'] = I18N::translate('daughter'); $gmarks[$i]['class'] = 'person_boxF'; break; case 'M': $gmarks[$i]['fact_label'] = I18N::translate('son'); $gmarks[$i]['class'] = 'person_box'; break; default: $gmarks[$i]['fact_label'] = I18N::translate('child'); $gmarks[$i]['class'] = 'person_boxNN'; break; } } else { $latlongval = $this->getLatitudeAndLongitudeFromPlaceLocation($birth->getPlace()->getGedcomName()); if ($latlongval && $latlongval->pl_lati && $latlongval->pl_long) { $i++; $gmarks[$i] = array('date' => $birth->getDate()->display(true), 'image' => $child->displayImage(), 'info' => '', 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $latlongval->pl_lati), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $latlongval->pl_long), 'name' => '<a href="' . $child->getHtmlUrl() . '"' . $child->getFullName() . '</a>', 'pl_icon' => $latlongval->pl_icon, 'place' => $birth->getPlace()->getFullName(), 'sv_bearing' => $latlongval->sv_bearing, 'sv_elevation' => $latlongval->sv_elevation, 'sv_lati' => $latlongval->sv_lati, 'sv_long' => $latlongval->sv_long, 'sv_zoom' => $latlongval->sv_zoom, 'tooltip' => $birth->getPlace()->getGedcomName()); switch ($child->getSex()) { case 'M': $gmarks[$i]['fact_label'] = I18N::translate('son'); $gmarks[$i]['class'] = 'person_box'; break; case 'F': $gmarks[$i]['fact_label'] = I18N::translate('daughter'); $gmarks[$i]['class'] = 'person_boxF'; break; default: $gmarks[$i]['fact_label'] = I18N::translate('child'); $gmarks[$i]['class'] = 'option_boxNN'; break; } if ($GM_MAX_ZOOM > $latlongval->pl_zoom) { $GM_MAX_ZOOM = $latlongval->pl_zoom; } } } } } } } // *** ENABLE STREETVIEW *** $STREETVIEW = $this->getSetting('GM_USE_STREETVIEW'); ?> <script> // this variable will collect the html which will eventually be placed in the side_bar var side_bar_html = ''; var map_center = new google.maps.LatLng(0,0); var gmarkers = []; var gicons = []; var map = null; var head = ''; var dir = ''; var svzoom = ''; var infowindow = new google.maps.InfoWindow({}); gicons["red"] = new google.maps.MarkerImage("https://maps.google.com/mapfiles/marker.png", new google.maps.Size(20, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34) ); var iconImage = new google.maps.MarkerImage("https://maps.google.com/mapfiles/marker.png", new google.maps.Size(20, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34) ); var iconShadow = new google.maps.MarkerImage("https://www.google.com/mapfiles/shadow50.png", new google.maps.Size(37, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34) ); var iconShape = { coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0], type: "poly" }; function getMarkerImage(iconColor) { if (typeof(iconColor) === 'undefined' || iconColor === null) { iconColor = 'red'; } if (!gicons[iconColor]) { gicons[iconColor] = new google.maps.MarkerImage('//maps.google.com/mapfiles/marker'+ iconColor +'.png', new google.maps.Size(20, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34)); } return gicons[iconColor]; } var sv2_bear = null; var sv2_elev = null; var sv2_zoom = null; var placer = null; // A function to create the marker and set up the event window function createMarker(latlng, html, tooltip, sv_lati, sv_long, sv_bearing, sv_elevation, sv_zoom, sv_point, marker_icon) { var contentString = '<div id="iwcontent">'+html+'</div>'; // Use flag icon (if defined) instead of regular marker icon if (marker_icon) { var icon_image = new google.maps.MarkerImage(WT_STATIC_URL+WT_MODULES_DIR+'googlemap/'+marker_icon, new google.maps.Size(25, 15), new google.maps.Point(0,0), new google.maps.Point(12, 15)); var icon_shadow = new google.maps.MarkerImage(WT_STATIC_URL+WT_MODULES_DIR+'googlemap/images/flag_shadow.png', new google.maps.Size(35, 45), // Shadow size new google.maps.Point(0,0), // Shadow origin new google.maps.Point(1, 45) // Shadow anchor is base of flagpole ); } else { var icon_image = getMarkerImage('red'); var icon_shadow = iconShadow; } // Decide if marker point is Regular (latlng) or StreetView (sv_point) derived if (sv_point == '(0, 0)' || sv_point == '(null, null)') { placer = latlng; } else { placer = sv_point; } // Define the marker var marker = new google.maps.Marker({ position: placer, icon: icon_image, shadow: icon_shadow, map: map, title: tooltip, zIndex: Math.round(latlng.lat()*-100000)<<5 }); // Store the tab and event info as marker properties marker.sv_lati = sv_lati; marker.sv_long = sv_long; marker.sv_point = sv_point; if (sv_bearing == '') { marker.sv_bearing = 0; } else { marker.sv_bearing = sv_bearing; } if (sv_elevation == '') { marker.sv_elevation = 5; } else { marker.sv_elevation = sv_elevation; } if (sv_zoom == '' || sv_zoom == 0 || sv_zoom == 1) { marker.sv_zoom = 1.2; } else { marker.sv_zoom = sv_zoom; } marker.sv_latlng = new google.maps.LatLng(sv_lati, sv_long); gmarkers.push(marker); // Open infowindow when marker is clicked google.maps.event.addListener(marker, 'click', function() { infowindow.close(); infowindow.setContent(contentString); infowindow.open(map, marker); var panoramaOptions = { position: marker.position, mode: 'html5', navigationControl: false, linksControl: false, addressControl: false, pov: { heading: sv_bearing, pitch: sv_elevation, zoom: sv_zoom } }; // Use jquery for info window tabs google.maps.event.addListener(infowindow, 'domready', function() { //jQuery code here jQuery('#EV').click(function() { document.tabLayerEV = document.getElementById("EV"); document.tabLayerEV.style.background = '#ffffff'; document.tabLayerEV.style.paddingBottom = '1px'; <?php if ($STREETVIEW) { ?> document.tabLayerSV = document.getElementById("SV"); document.tabLayerSV.style.background = '#cccccc'; document.tabLayerSV.style.paddingBottom = '0px'; <?php } ?> document.panelLayer1 = document.getElementById("pane1"); document.panelLayer1.style.display = 'block'; <?php if ($STREETVIEW) { ?> document.panelLayer2 = document.getElementById("pane2"); document.panelLayer2.style.display = 'none'; <?php } ?> }); jQuery('#SV').click(function() { document.tabLayerEV = document.getElementById("EV"); document.tabLayerEV.style.background = '#cccccc'; document.tabLayerEV.style.paddingBottom = '0px'; <?php if ($STREETVIEW) { ?> document.tabLayerSV = document.getElementById("SV"); document.tabLayerSV.style.background = '#ffffff'; document.tabLayerSV.style.paddingBottom = '1px'; <?php } ?> document.panelLayer1 = document.getElementById("pane1"); document.panelLayer1.style.display = 'none'; <?php if ($STREETVIEW) { ?> document.panelLayer2 = document.getElementById("pane2"); document.panelLayer2.style.display = 'block'; <?php } ?> var panorama = new google.maps.StreetViewPanorama(document.getElementById("pano"), panoramaOptions); setTimeout(function() { panorama.setVisible(true); }, 100); setTimeout(function() { panorama.setVisible(true); }, 500); }); }); }); } // Opens Marker infowindow when corresponding Sidebar item is clicked function myclick(i) { infowindow.close(); google.maps.event.trigger(gmarkers[i], 'click'); return false; } // Home control // returns the user to the original map position ... loadMap() function // This constructor takes the control DIV as an argument. function HomeControl(controlDiv, map) { // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control from the edge of the map controlDiv.style.paddingTop = '5px'; controlDiv.style.paddingRight = '0px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = 'white'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '2px'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = ''; controlDiv.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingLeft = '15px'; controlText.style.paddingRight = '15px'; controlText.innerHTML = '<b><?php echo I18N::translate('Redraw map'); ?> </b>'; controlUI.appendChild(controlText); // Setup the click event listeners: simply set the map to original LatLng google.maps.event.addDomListener(controlUI, 'click', function() { loadMap(); }); } function loadMap() { // Create the map and mapOptions var mapOptions = { zoom: 7, center: map_center, mapTypeId: google.maps.MapTypeId.<?php echo $this->getSetting('GM_MAP_TYPE'); ?> , mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU // DEFAULT, DROPDOWN_MENU, HORIZONTAL_BAR }, navigationControl: true, navigationControlOptions: { position: google.maps.ControlPosition.TOP_RIGHT, // BOTTOM, BOTTOM_LEFT, LEFT, TOP, etc style: google.maps.NavigationControlStyle.SMALL // ANDROID, DEFAULT, SMALL, ZOOM_PAN }, streetViewControl: false, // Show Pegman or not scrollwheel: false }; map = new google.maps.Map(document.getElementById('map_pane'), mapOptions); // Close any infowindow when map is clicked google.maps.event.addListener(map, 'click', function() { infowindow.close(); }); // Create the Home DIV and call the HomeControl() constructor in this DIV. var homeControlDiv = document.createElement('DIV'); var homeControl = new HomeControl(homeControlDiv, map); homeControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); // Add the markers to the map from the $gmarks array var locations = [ <?php foreach ($gmarks as $n => $gmark) { ?> <?php echo $n ? ',' : ''; ?> { "event": "<?php echo Filter::escapeJs($gmark['fact_label']); ?> ", "lat": "<?php echo Filter::escapeJs($gmark['lat']); ?> ", "lng": "<?php echo Filter::escapeJs($gmark['lng']); ?> ", "date": "<?php echo Filter::escapeJs($gmark['date']); ?> ", "info": "<?php echo Filter::escapeJs($gmark['info']); ?> ", "name": "<?php echo Filter::escapeJs($gmark['name']); ?> ", "place": "<?php echo Filter::escapeJs($gmark['place']); ?> ", "tooltip": "<?php echo Filter::escapeJs($gmark['tooltip']); ?> ", "image": "<?php echo Filter::escapeJs($gmark['image']); ?> ", "pl_icon": "<?php echo Filter::escapeJs($gmark['pl_icon']); ?> ", "sv_lati": "<?php echo Filter::escapeJs($gmark['sv_lati']); ?> ", "sv_long": "<?php echo Filter::escapeJs($gmark['sv_long']); ?> ", "sv_bearing": "<?php echo Filter::escapeJs($gmark['sv_bearing']); ?> ", "sv_elevation": "<?php echo Filter::escapeJs($gmark['sv_elevation']); ?> ", "sv_zoom": "<?php echo Filter::escapeJs($gmark['sv_zoom']); ?> " } <?php } ?> ]; // Group the markers by location var location_groups = []; for (var key in locations) { if (!location_groups.hasOwnProperty(locations[key].place)) { location_groups[locations[key].place] = []; } location_groups[locations[key].place].push(locations[key]); } // Set the Marker bounds var bounds = new google.maps.LatLngBounds (); var key; // Iterate over each location for (key in location_groups) { var locations = location_groups[key]; // Iterate over each marker at this location var event_details = ''; for (var j in locations) { var location = locations[j]; if (location.info && location.name) { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span> ' + location.info + '<br><b>' + location.name + '</b><br>' + location.date + '<br></p></td></tr></table>'; } else if (location.name) { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span><br><b>' + location.name + '</b><br>' + location.date + '<br></p></td></tr></table>'; } else if (location.info) { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span> ' + location.info + '<br>' + location.date + '<br></p></td></tr></table>'; } else { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span><br>' + location.date + '<br></p></td></tr></table>'; } } // All locations are the same in each group, so create a marker with the first var location = location_groups[key][0]; var html = '<div class="infowindow">' + '<div id="gmtabs">' + '<ul class="tabs" >' + '<li><a href="#event" id="EV"><?php echo I18N::translate('Events'); ?> </a></li>' + <?php if ($STREETVIEW) { ?> '<li><a href="#sview" id="SV"><?php echo I18N::translate('Google Street View™'); ?> </a></li>' + <?php } ?> '</ul>' + '<div class="panes">' + '<div id="pane1">' + '<h4 id="iwhead">' + location.place + '</h4>' + event_details + '</div>' + <?php if ($STREETVIEW) { ?> '<div id="pane2">' + '<h4 id="iwhead">' + location.place + '</h4>' + '<div id="pano"></div>' + '</div>' + <?php } ?> '</div>' + '</div>' + '</div>'; // create the marker var point = new google.maps.LatLng(location.lat, location.lng); // Place Latitude, Longitude var sv_point = new google.maps.LatLng(location.sv_lati, location.sv_long); // StreetView Latitude and Longitide var zoomLevel = <?php echo $GM_MAX_ZOOM; ?> ; var marker = createMarker(point, html, location.tooltip, location.sv_lati, location.sv_long, location.sv_bearing, location.sv_elevation, location.sv_zoom, sv_point, location.pl_icon); // if streetview coordinates are available, use them for marker, // else use the place coordinates if (sv_point && sv_point != "(0, 0)") { var myLatLng = sv_point; } else { var myLatLng = point; } // Correct zoom level when only one marker is present if (location_groups.length == 1) { bounds.extend(myLatLng); map.setZoom(zoomLevel); map.setCenter(myLatLng); } else { bounds.extend(myLatLng); map.fitBounds(bounds); // Correct zoom level when multiple markers have the same coordinates var listener1 = google.maps.event.addListenerOnce(map, "idle", function() { if (map.getZoom() > zoomLevel) { map.setZoom(zoomLevel); } google.maps.event.removeListener(listener1); }); } } // end loop through location markers } // end loadMap() </script> <?php // Create the normal googlemap sidebar of events and children echo '<div style="overflow: auto; overflow-x: hidden; overflow-y: auto; height:', $this->getSetting('GM_YSIZE'), 'px;"><table class="facts_table">'; foreach ($gmarks as $key => $gmark) { echo '<tr>'; echo '<td class="facts_label">'; echo '<a href="#" onclick="return myclick(\'', Filter::escapeHtml($key), '\')">', $gmark['fact_label'], '</a></td>'; echo '<td class="', $gmark['class'], '" style="white-space: normal">'; if ($gmark['info']) { echo '<span class="field">', Filter::escapeHtml($gmark['info']), '</span><br>'; } if ($gmark['name']) { echo $gmark['name'], '<br>'; } echo $gmark['place'], '<br>'; if ($gmark['date']) { echo $gmark['date'], '<br>'; } echo '</td>'; echo '</tr>'; } echo '</table></div><br>'; }
/** * Determine which javascript file we need * * @param type $controller * @param type $page * * @return inline and/or external Javascript */ protected function includeJs($controller, $page) { switch ($page) { case 'admin': $controller->addInlineJavascript(' var ModuleDir = "' . $this->directory . '"; var ModuleName = "' . $this->getName() . '"; var ThemeID = "' . Theme::theme()->themeId() . '"; ', BaseController::JS_PRIORITY_HIGH); $controller->addExternalJavascript(WT_AUTOCOMPLETE_JS_URL)->addInlineJavascript('autocomplete();')->addExternalJavascript($this->directory . '/js/admin.js'); break; case 'menu': $controller->addInlineJavascript(' var ModuleDir = "' . $this->directory . '"; var ModuleName = "' . $this->getName() . '"; var ThemeID = "' . Theme::theme()->themeId() . '"; ', BaseController::JS_PRIORITY_HIGH); $controller->addInlineJavascript('jQuery(".fancy-treeview-script").remove();', BaseController::JS_PRIORITY_LOW); break; case 'page': $controller->addInlineJavascript(' var PageTitle = "' . urlencode(strip_tags($controller->getPageTitle())) . '"; var RootID = "' . $this->rootId() . '"; var OptionsNumBlocks = ' . $this->options('numblocks') . '; var TextFollow = "' . I18N::translate('follow') . '"; var TextOk = "' . I18N::translate('ok') . '"; var TextCancel = "' . I18N::translate('cancel') . '"; ', BaseController::JS_PRIORITY_HIGH)->addExternalJavascript(WT_AUTOCOMPLETE_JS_URL)->addInlineJavascript('autocomplete();')->addExternalJavascript($this->directory . '/js/page.js'); if ($this->options('show_pdf_icon') >= Auth::accessLevel($this->tree)) { $controller->addExternalJavascript($this->directory . '/js/pdf.js'); } // some files needs an extra js script if ($this->theme()) { $js = $this->theme() . '/' . basename($this->theme()) . '.js'; if (file_exists($js)) { $controller->addExternalJavascript($js); } } if ($this->options('show_userform') >= Auth::accessLevel($this->tree)) { $this->includeJsInline($controller); } break; case 'tab': $controller->addInlineJavascript(' jQuery("a[href$=' . $this->getName() . ']").text("' . $this->getTabTitle() . '"); '); break; } }
/** * Print a fact for an individual. * * @param Fact $event */ public function printTimeFact(Fact $event) { global $basexoffset, $baseyoffset, $factcount, $placements; $desc = $event->getValue(); // check if this is a family fact $gdate = $event->getDate(); $date = $gdate->minimumDate(); $date = $date->convertToCalendar('gregorian'); $year = $date->y; $month = max(1, $date->m); $day = max(1, $date->d); $xoffset = $basexoffset + 22; $yoffset = $baseyoffset + ($year - $this->baseyear) * $this->scale - $this->scale; $yoffset = $yoffset + $month / 12 * $this->scale; $yoffset = $yoffset + $day / 30 * ($this->scale / 12); $yoffset = (int) $yoffset; $place = (int) ($yoffset / $this->bheight); $i = 1; $j = 0; $tyoffset = 0; while (isset($placements[$place])) { if ($i === $j) { $tyoffset = $this->bheight * $i; $i++; } else { $tyoffset = -1 * $this->bheight * $j; $j++; } $place = (int) (($yoffset + $tyoffset) / $this->bheight); } $yoffset += $tyoffset; $xoffset += abs($tyoffset); $placements[$place] = $yoffset; echo "<div id=\"fact{$factcount}\" style=\"position:absolute; " . (I18N::direction() === 'ltr' ? 'left: ' . $xoffset : 'right: ' . $xoffset) . 'px; top:' . $yoffset . "px; font-size: 8pt; height: " . $this->bheight . "px;\" onmousedown=\"factMouseDown(this, '" . $factcount . "', " . ($yoffset - $tyoffset) . ");\">"; echo '<table cellspacing="0" cellpadding="0" border="0" style="cursor: hand;"><tr><td>'; echo '<img src="' . Theme::theme()->parameter('image-hline') . '" name="boxline' . $factcount . '" id="boxline' . $factcount . '" height="3" width="10" style="padding-'; if (I18N::direction() === 'ltr') { echo 'left: 3px;">'; } else { echo 'right: 3px;">'; } $col = array_search($event->getParent(), $this->people); if ($col === false) { // Marriage event - use the color of the husband $col = array_search($event->getParent()->getHusband(), $this->people); } if ($col === false) { // Marriage event - use the color of the wife $col = array_search($event->getParent()->getWife(), $this->people); } $col = $col % 6; echo '</td><td class="person' . $col . '">'; if (count($this->people) > 6) { // We only have six colours, so show naes if more than this number echo $event->getParent()->getFullName() . ' — '; } $record = $event->getParent(); echo $event->getLabel(); echo ' — '; if ($record instanceof Individual) { echo FunctionsPrint::formatFactDate($event, $record, false, false); } elseif ($record instanceof Family) { echo $gdate->display(); if ($record->getHusband() && $record->getHusband()->getBirthDate()->isOK()) { $ageh = FunctionsDate::getAgeAtEvent(Date::getAgeGedcom($record->getHusband()->getBirthDate(), $gdate)); } else { $ageh = null; } if ($record->getWife() && $record->getWife()->getBirthDate()->isOK()) { $agew = FunctionsDate::getAgeAtEvent(Date::getAgeGedcom($record->getWife()->getBirthDate(), $gdate)); } else { $agew = null; } if ($ageh && $agew) { echo '<span class="age"> ', I18N::translate('Husband’s age'), ' ', $ageh, ' ', I18N::translate('Wife’s age'), ' ', $agew, '</span>'; } elseif ($ageh) { echo '<span class="age"> ', I18N::translate('Age'), ' ', $ageh, '</span>'; } elseif ($agew) { echo '<span class="age"> ', I18N::translate('Age'), ' ', $ageh, '</span>'; } } echo ' ' . Filter::escapeHtml($desc); if (!$event->getPlace()->isEmpty()) { echo ' — ' . $event->getPlace()->getShortName(); } // Print spouses names for family events if ($event->getParent() instanceof Family) { echo ' — <a href="', $event->getParent()->getHtmlUrl(), '">', $event->getParent()->getFullName(), '</a>'; } echo '</td></tr></table>'; echo '</div>'; if (I18N::direction() === 'ltr') { $img = 'image-dline2'; $ypos = '0%'; } else { $img = 'image-dline'; $ypos = '100%'; } $dyoffset = $yoffset - $tyoffset + $this->bheight / 3; if ($tyoffset < 0) { $dyoffset = $yoffset + $this->bheight / 3; if (I18N::direction() === 'ltr') { $img = 'image-dline'; $ypos = '100%'; } else { $img = 'image-dline2'; $ypos = '0%'; } } // Print the diagonal line echo '<div id="dbox' . $factcount . '" style="position:absolute; ' . (I18N::direction() === 'ltr' ? 'left: ' . ($basexoffset + 25) : 'right: ' . ($basexoffset + 25)) . 'px; top:' . $dyoffset . 'px; font-size: 8pt; height: ' . abs($tyoffset) . 'px; width: ' . abs($tyoffset) . 'px;'; echo ' background-image: url(\'' . Theme::theme()->parameter($img) . '\');'; echo ' background-position: 0% ' . $ypos . ';">'; echo '</div>'; }
p1.position().left + (boxWidth / 2) + addOffset, p1.position().top + boxHeight, p2.position().left + (boxWidth / 2) - addOffset, p0.position().top + bHeight ); } break; } // Set line styles & draw them ctx.strokeStyle = canvas.css("color"); ctx.lineWidth = ' . Theme::theme()->parameter('line-width') . '; ctx.shadowColor = ' . json_encode(Theme::theme()->parameter('shadow-color')) . '; ctx.shadowBlur = ' . Theme::theme()->parameter('shadow-blur') . '; ctx.shadowOffsetX = ' . Theme::theme()->parameter('shadow-offset-x') . '; ctx.shadowOffsetY = ' . Theme::theme()->parameter('shadow-offset-y') . '; ctx.stroke(); })(); '); ?> <div id="pedigree-page"> <h2><?php echo $controller->getPageTitle(); ?> </h2> <form name="people" id="people" method="get" action="?"> <input type="hidden" name="ged" value="<?php echo $WT_TREE->getNameHtml(); ?> ">
http_response_code(404); $controller->pageHeader(); echo '<p class="ui-state-error">', I18N::translate('This family does not exist or you do not have permission to view it.'), '</p>'; return; } ?> <div id="family-page"> <h2><?php echo $controller->record->getFullName(); ?> </h2> <table id="family-table" align="center" width="95%"> <tr valign="top"> <td valign="top" style="width: <?php echo Theme::theme()->parameter('chart-box-x') + 30; ?> px;"><!--//List of children//--> <?php FunctionsCharts::printFamilyChildren($controller->record); ?> </td> <td> <!--//parents pedigree chart and Family Details//--> <table width="100%"> <tr> <td class="subheaders" valign="top"><?php echo I18N::translate('Parents'); ?> </td> <td class="subheaders" valign="top"><?php echo I18N::translate('Grandparents');
public function getMenu() { global $controller, $WT_TREE; $menu_titles = $this->getMenuList(); $lang = ''; $min_block = webtrees\Database::prepare("SELECT MIN(block_order) FROM `##block` WHERE module_name=?")->execute(array($this->getName()))->fetchOne(); foreach ($menu_titles as $items) { $languages = $this->getBlockSetting($items->block_id, 'languages'); if (in_array(WT_LOCALE, explode(',', $languages))) { $lang = WT_LOCALE; } else { $lang = ''; } } $default_block = webtrees\Database::prepare("SELECT ##block.block_id FROM `##block`, `##block_setting` WHERE block_order=? AND module_name=? AND ##block.block_id = ##block_setting.block_id AND ##block_setting.setting_value LIKE ?")->execute(array($min_block, $this->getName(), '%' . $lang . '%'))->fetchOne(); $main_menu_address = webtrees\Database::prepare("SELECT setting_value FROM `##block_setting` WHERE block_id=? AND setting_name=?")->execute(array($default_block, 'menu_address'))->fetchOne(); if (count($menu_titles) > 1) { $main_menu_title = $this->getMenuTitle(); } else { $main_menu_title = webtrees\Database::prepare("SELECT setting_value FROM `##block_setting` WHERE block_id=? AND setting_name=?")->execute(array($default_block, 'menu_title'))->fetchOne(); } if (webtrees\Auth::isSearchEngine()) { return null; } if (file_exists(WT_MODULES_DIR . $this->getName() . '/themes/' . webtrees\Theme::theme()->themeId() . '/')) { echo '<link rel="stylesheet" href="' . WT_MODULES_DIR . $this->getName() . '/themes/' . webtrees\Theme::theme()->themeId() . '/style.css" type="text/css">'; } else { echo '<link rel="stylesheet" href="' . WT_MODULES_DIR . $this->getName() . '/themes/webtrees/style.css" type="text/css">'; } //-- main menu item $menu = new webtrees\Menu($main_menu_title, $main_menu_address, $this->getName()); $menu->addClass('menuitem', 'menuitem_hover', ''); foreach ($menu_titles as $items) { if (count($menu_titles) > 1) { $languages = $this->getBlockSetting($items->block_id, 'languages'); if ((!$languages || in_array(WT_LOCALE, explode(',', $languages))) && $items->menu_access >= webtrees\Auth::accessLevel($WT_TREE)) { $submenu = new webtrees\Menu(webtrees\I18N::translate($items->menu_title), $items->menu_address, $this->getName() . '-' . str_replace(' ', '', $items->menu_title)); $menu->addSubmenu($submenu); } } } if (webtrees\Auth::isAdmin()) { $submenu = new webtrees\Menu(webtrees\I18N::translate('Edit menus'), $this->getConfigLink(), $this->getName() . '-edit'); $menu->addSubmenu($submenu); } return $menu; }
/** * Create a link to contact the genealogy contact. * * @return string */ public function contactGedcom() { $user_id = $this->tree->getPreference('CONTACT_USER_ID'); $user = User::find($user_id); if ($user) { return Theme::theme()->contactLink($user); } else { return $user_id; } }
/** * Generate the HTML content of this tab. * * @return string */ public function getTabContent() { global $WT_TREE, $controller; $html = '<div id="' . $this->getName() . '_content">'; //Show Lightbox-Album header Links if (Auth::isEditor($WT_TREE)) { $html .= '<table class="facts_table"><tr><td class="descriptionbox rela">'; // Add a new media object if ($WT_TREE->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($WT_TREE)) { $html .= '<span><a href="#" onclick="window.open(\'addmedia.php?action=showmediaform&linktoid=' . $controller->record->getXref() . '\', \'_blank\', \'resizable=1,scrollbars=1,top=50,height=780,width=600\');return false;">'; $html .= '<img src="' . Theme::theme()->assetUrl() . 'images/image_add.png" id="head_icon" class="icon" title="' . I18N::translate('Add a new media object') . '" alt="' . I18N::translate('Add a new media object') . '">'; $html .= I18N::translate('Add a new media object'); $html .= '</a></span>'; // Link to an existing item $html .= '<span><a href="#" onclick="window.open(\'inverselink.php?linktoid=' . $controller->record->getXref() . '&linkto=person\', \'_blank\', \'resizable=1,scrollbars=1,top=50,height=300,width=450\');">'; $html .= '<img src="' . Theme::theme()->assetUrl() . 'images/image_link.png" id="head_icon" class="icon" title="' . I18N::translate('Link to an existing media object') . '" alt="' . I18N::translate('Link to an existing media object') . '">'; $html .= I18N::translate('Link to an existing media object'); $html .= '</a></span>'; } if (Auth::isManager($WT_TREE) && $this->getMedia()) { // Popup Reorder Media $html .= '<span><a href="#" onclick="reorder_media(\'' . $controller->record->getXref() . '\')">'; $html .= '<img src="' . Theme::theme()->assetUrl() . 'images/images.png" id="head_icon" class="icon" title="' . I18N::translate('Re-order media') . '" alt="' . I18N::translate('Re-order media') . '">'; $html .= I18N::translate('Re-order media'); $html .= '</a></span>'; } $html .= '</td></tr></table>'; } // Used when sorting media on album tab page $html .= '<table class="facts_table"><tr><td class="facts_value">'; // one-cell table - for presentation only $html .= '<ul class="album-list">'; foreach ($this->getMedia() as $media) { //View Edit Menu ---------------------------------- //Get media item Notes $haystack = $media->getGedcom(); $needle = '1 NOTE'; $before = substr($haystack, 0, strpos($haystack, $needle)); $after = substr(strstr($haystack, $needle), strlen($needle)); $notes = FunctionsPrint::printFactNotes($before . $needle . $after, 1, true); // Prepare Below Thumbnail menu ---------------------------------------------------- $menu = new Menu('<div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap">' . $media->getFullName() . '</div>'); $menu->addClass('', 'submenu'); // View Notes if (strpos($media->getGedcom(), "\n1 NOTE")) { $submenu = new Menu(I18N::translate('View notes'), '#', '', array('onclick' => 'modalNotes("' . Filter::escapeJs($notes) . '","' . I18N::translate('View notes') . '"); return false;')); $submenu->addClass("submenuitem"); $menu->addSubmenu($submenu); } //View Details $submenu = new Menu(I18N::translate('View details'), $media->getHtmlUrl()); $submenu->addClass("submenuitem"); $menu->addSubmenu($submenu); //View Sources foreach ($media->getFacts('SOUR') as $source_fact) { $source = $source_fact->getTarget(); if ($source && $source->canShow()) { $submenu = new Menu(I18N::translate('Source') . ' – ' . $source->getFullName(), $source->getHtmlUrl()); $submenu->addClass('submenuitem'); $menu->addSubmenu($submenu); } } if (Auth::isEditor($media->getTree())) { // Edit Media $submenu = new Menu(I18N::translate('Edit media'), '#', '', array('onclick' => 'return window.open("addmedia.php?action=editmedia&pid=' . $media->getXref() . '", "_blank", edit_window_specs);')); $submenu->addClass("submenuitem"); $menu->addSubmenu($submenu); if (Auth::isAdmin()) { if (Module::getModuleByName('GEDFact_assistant')) { $submenu = new Menu(I18N::translate('Manage links'), '#', '', array('onclick' => 'return window.open("inverselink.php?mediaid=' . $media->getXref() . '&linkto=manage", "_blank", find_window_specs);')); $submenu->addClass("submenuitem"); $menu->addSubmenu($submenu); } else { $submenu = new Menu(I18N::translate('Link this media object to an individual'), '#', 'menu-obje-link-indi', array('onclick' => 'return ilinkitem("' . $media->getXref() . '","person");')); $submenu->addClass('submenuitem'); $menu->addSubmenu($submenu); $submenu = new Menu(I18N::translate('Link this media object to a family'), '#', 'menu-obje-link-fam', array('onclick' => 'return ilinkitem("' . $media->getXref() . '","family");')); $submenu->addClass('submenuitem'); $menu->addSubmenu($submenu); $submenu = new Menu(I18N::translate('Link this media object to a source'), '#', 'menu-obje-link-sour', array('onclick' => 'return ilinkitem("' . $media->getXref() . '","source");')); $submenu->addClass('submenuitem'); $menu->addSubmenu($submenu); } $submenu = new Menu(I18N::translate('Unlink media'), '#', '', array('onclick' => 'return unlink_media("' . I18N::translate('Are you sure you want to remove links to this media object?') . '", "' . $controller->record->getXref() . '", "' . $media->getXref() . '");')); $submenu->addClass("submenuitem"); $menu->addSubmenu($submenu); } } $html .= '<li class="album-list-item">'; $html .= '<div class="album-image">' . $media->displayImage() . '</div>'; $html .= '<div class="album-title">' . $menu->getMenu() . '</div>'; $html .= '</li>'; } $html .= '</ul>'; $html .= '</td></tr></table>'; return $html; }
} } } } } else { http_response_code(406); } break; case 'reject-changes': // Reject all the pending changes for a record $record = GedcomRecord::getInstance(Filter::post('xref', WT_REGEX_XREF), $WT_TREE); if ($record && $record->canEdit() && Auth::isModerator($record->getTree())) { FlashMessages::addMessage(I18N::translate('The changes to “%s” have been rejected.', $record->getFullName())); FunctionsImport::rejectAllChanges($record); } else { http_response_code(406); } break; case 'theme': // Change the current theme $theme = Filter::post('theme'); if (Site::getPreference('ALLOW_USER_THEMES') && array_key_exists($theme, Theme::themeNames())) { Session::put('theme_id', $theme); // Remember our selection Auth::user()->setPreference('theme', $theme); } else { // Request for a non-existant theme. http_response_code(406); } break; }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $ctype, $WT_TREE; $num = $this->getBlockSetting($block_id, 'num', '10'); $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', 'table'); $block = $this->getBlockSetting($block_id, 'block', '0'); foreach (array('num', 'infoStyle', 'block') as $name) { if (array_key_exists($name, $cfg)) { ${$name} = $cfg[$name]; } } $stats = new Stats($WT_TREE); $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; if ($ctype === 'gedcom' && Auth::isManager($WT_TREE) || $ctype === 'user' && Auth::check()) { $title = '<a class="icon-admin" title="' . I18N::translate('Configure') . '" href="block_edit.php?block_id=' . $block_id . '&ged=' . $WT_TREE->getNameHtml() . '&ctype=' . $ctype . '"></a>'; } else { $title = ''; } if ($num == 1) { // I18N: i.e. most popular given name. $title .= I18N::translate('Top given name'); } else { // I18N: Title for a list of the most common given names, %s is a number. Note that a separate translation exists when %s is 1 $title .= I18N::plural('Top %s given name', 'Top %s given names', $num, I18N::number($num)); } $content = '<div class="normal_inner_block">'; //Select List or Table switch ($infoStyle) { case "list": // Output style 1: Simple list style. Better suited to left side of page. if (I18N::direction() === 'ltr') { $padding = 'padding-left: 15px'; } else { $padding = 'padding-right: 15px'; } $params = array(1, $num, 'rcount'); // List Female names $totals = $stats->commonGivenFemaleTotals($params); if ($totals) { $content .= '<b>' . I18N::translate('Females') . '</b><div class="wrap" style="' . $padding . '">' . $totals . '</div><br>'; } // List Male names $totals = $stats->commonGivenMaleTotals($params); if ($totals) { $content .= '<b>' . I18N::translate('Males') . '</b><div class="wrap" style="' . $padding . '">' . $totals . '</div><br>'; } break; case "table": // Style 2: Tabular format. Narrow, 2 or 3 column table, good on right side of page $params = array(1, $num, 'rcount'); $content .= '<table style="margin:auto;"> <tr valign="top"> <td>' . $stats->commonGivenFemaleTable($params) . '</td> <td>' . $stats->commonGivenMaleTable($params) . '</td>'; $content .= '</tr></table>'; break; } $content .= "</div>"; if ($template) { if ($block) { $class .= ' small_inner_block'; } return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $WT_TREE, $ctype; $show_last_update = $this->getBlockSetting($block_id, 'show_last_update', '1'); $show_common_surnames = $this->getBlockSetting($block_id, 'show_common_surnames', '1'); $stat_indi = $this->getBlockSetting($block_id, 'stat_indi', '1'); $stat_fam = $this->getBlockSetting($block_id, 'stat_fam', '1'); $stat_sour = $this->getBlockSetting($block_id, 'stat_sour', '1'); $stat_media = $this->getBlockSetting($block_id, 'stat_media', '1'); $stat_repo = $this->getBlockSetting($block_id, 'stat_repo', '1'); $stat_surname = $this->getBlockSetting($block_id, 'stat_surname', '1'); $stat_events = $this->getBlockSetting($block_id, 'stat_events', '1'); $stat_users = $this->getBlockSetting($block_id, 'stat_users', '1'); $stat_first_birth = $this->getBlockSetting($block_id, 'stat_first_birth', '1'); $stat_last_birth = $this->getBlockSetting($block_id, 'stat_last_birth', '1'); $stat_first_death = $this->getBlockSetting($block_id, 'stat_first_death', '1'); $stat_last_death = $this->getBlockSetting($block_id, 'stat_last_death', '1'); $stat_long_life = $this->getBlockSetting($block_id, 'stat_long_life', '1'); $stat_avg_life = $this->getBlockSetting($block_id, 'stat_avg_life', '1'); $stat_most_chil = $this->getBlockSetting($block_id, 'stat_most_chil', '1'); $stat_avg_chil = $this->getBlockSetting($block_id, 'stat_avg_chil', '1'); // This can be overriden when embedding in an HTML block $block = '0'; $stat_link = '1'; foreach (array('show_common_surnames', 'stat_indi', 'stat_fam', 'stat_sour', 'stat_media', 'stat_surname', 'stat_events', 'stat_users', 'stat_first_birth', 'stat_last_birth', 'stat_first_death', 'stat_last_death', 'stat_long_life', 'stat_avg_life', 'stat_most_chil', 'stat_avg_chil', 'stat_link', 'block') as $name) { if (array_key_exists($name, $cfg)) { ${$name} = $cfg[$name]; } } $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; if ($ctype === 'gedcom' && Auth::isManager($WT_TREE) || $ctype === 'user' && Auth::check()) { $title = '<a class="icon-admin" title="' . I18N::translate('Configure') . '" href="block_edit.php?block_id=' . $block_id . '&ged=' . $WT_TREE->getNameHtml() . '&ctype=' . $ctype . '"></a>'; } else { $title = ''; } $title .= $this->getTitle(); $stats = new Stats($WT_TREE); $content = '<b>' . $WT_TREE->getTitleHtml() . '</b><br>'; if ($show_last_update) { $content .= '<div>' . I18N::translate('This family tree was last updated on %s.', strip_tags($stats->gedcomUpdated())) . '</div>'; } /** Responsive Design */ $content .= '<div class="stat-table1">'; if ($stat_indi) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Individuals') . '</div><div class="facts_value stats_value stat-cell"><a href="' . "indilist.php?surname_sublist=no&ged=" . $WT_TREE->getNameUrl() . '">' . $stats->totalIndividuals() . '</a></div></div>'; $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Males') . '</div><div class="facts_value stats_value stat-cell">' . $stats->totalSexMales() . '<br>' . $stats->totalSexMalesPercentage() . '</div></div>'; $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Females') . '</div><div class="facts_value stats_value stat-cell">' . $stats->totalSexFemales() . '<br>' . $stats->totalSexFemalesPercentage() . '</div></div>'; } if ($stat_surname) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Total surnames') . '</div><div class="facts_value stats_value stat-cell"><a href="indilist.php?show_all=yes&surname_sublist=yes&ged=' . $WT_TREE->getNameUrl() . '">' . $stats->totalSurnames() . '</a></div></div>'; } if ($stat_fam) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Families') . '</div><div class="facts_value stats_value stat-cell"><a href="famlist.php?ged=' . $WT_TREE->getNameUrl() . '">' . $stats->totalFamilies() . '</a></div></div>'; } if ($stat_sour) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Sources') . '</div><div class="facts_value stats_value stat-cell"><a href="sourcelist.php?ged=' . $WT_TREE->getNameUrl() . '">' . $stats->totalSources() . '</a></div></div>'; } if ($stat_media) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Media objects') . '</div><div class="facts_value stats_value stat-cell"><a href="medialist.php?ged=' . $WT_TREE->getNameUrl() . '">' . $stats->totalMedia() . '</a></div></div>'; } if ($stat_repo) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Repositories') . '</div><div class="facts_value stats_value stat-cell"><a href="repolist.php?ged=' . $WT_TREE->getNameUrl() . '">' . $stats->totalRepositories() . '</a></div></div>'; } if ($stat_events) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Total events') . '</div><div class="facts_value stats_value stat-cell">' . $stats->totalEvents() . '</div></div>'; } if ($stat_users) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Total users') . '</div><div class="facts_value stats_value stat-cell">'; if (Auth::isManager($WT_TREE)) { $content .= '<a href="admin_users.php">' . $stats->totalUsers() . '</a>'; } else { $content .= $stats->totalUsers(); } $content .= '</div></div>'; } if (!$block) { $content .= '</div><div class="facts_table stat-table2">'; } if ($stat_first_birth) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Earliest birth year') . '</div><div class="facts_value stats_value stat-cell">' . $stats->firstBirthYear() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . $stats->firstBirth() . '</div>'; } $content .= '</div>'; } if ($stat_last_birth) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Latest birth year') . '</div><div class="facts_value stats_value stat-cell">' . $stats->lastBirthYear() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . $stats->lastBirth() . '</div>'; } $content .= '</div>'; } if ($stat_first_death) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Earliest death year') . '</div><div class="facts_value stats_value stat-cell">' . $stats->firstDeathYear() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . $stats->firstDeath() . '</div>'; } $content .= '</div>'; } if ($stat_last_death) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Latest death year') . '</div><div class="facts_value stats_value stat-cell">' . $stats->lastDeathYear() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . $stats->lastDeath() . '</div>'; } $content .= '</div>'; } if ($stat_long_life) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Individual who lived the longest') . '</div><div class="facts_value stats_value stat-cell">' . $stats->longestLifeAge() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . $stats->longestLife() . '</div>'; } $content .= '</div>'; } if ($stat_avg_life) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Average age at death') . '</div><div class="facts_value stats_value stat-cell">' . $stats->averageLifespan() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . I18N::translate('Males') . ': ' . $stats->averageLifespanMale(); $content .= ' ' . I18N::translate('Females') . ': ' . $stats->averageLifespanFemale() . '</div>'; } $content .= '</div>'; } if ($stat_most_chil && !$block) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Family with the most children') . '</div><div class="facts_value stats_value stat-cell">' . $stats->largestFamilySize() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left">' . $stats->largestFamily() . '</div>'; } $content .= '</div>'; } if ($stat_avg_chil) { $content .= '<div class="stat-row"><div class="facts_label stat-cell">' . I18N::translate('Average number of children per family') . '</div><div class="facts_value stats_value stat-cell">' . $stats->averageChildren() . '</div>'; if (!$block) { $content .= '<div class="facts_value stat-cell left"></div>'; } $content .= '</div>'; } $content .= '</div>'; if ($stat_link) { $content .= '<div class="clearfloat"><a href="statistics.php?ged=' . $WT_TREE->getNameUrl() . '" rel="nofollow"><b>' . I18N::translate('View statistics as graphs') . '</b></a></div>'; } if ($show_common_surnames) { $surnames = FunctionsDb::getCommonSurnames($WT_TREE->getPreference('COMMON_NAMES_THRESHOLD'), $WT_TREE); if (count($surnames) > 0) { $content .= '<div class="clearfloat"><p><b>' . I18N::translate('Most common surnames') . '</b></p>'; $content .= '<div class="common_surnames">'; $i = 0; foreach ($surnames as $indexval => $surname) { if (stristr($surname['name'], '@N.N') === false) { if ($i > 0) { $content .= ', '; } $content .= '<a href="' . "indilist.php?ged=" . $WT_TREE->getNameUrl() . "&surname=" . rawurlencode($surname['name']) . '">' . $surname['name'] . '</a>'; $i++; } } $content .= '</div>'; } } if ($template) { return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }