Ejemplo n.º 1
0
 /**
  * Calculate the shortest paths - or all paths - between two individuals.
  *
  * @param Individual $individual1
  * @param Individual $individual2
  * @param int        $recursion   How many levels of recursion to use
  * @param boo;       $ancestor    Restrict to relationships via a common ancestor
  *
  * @return string[][]
  */
 public function calculateRelationships(Individual $individual1, Individual $individual2, $recursion, $ancestor = false)
 {
     $rows = Database::prepare("SELECT l_from, l_to FROM `##link` WHERE l_file = :tree_id AND l_type IN ('FAMS', 'FAMC')")->execute(array('tree_id' => $individual1->getTree()->getTreeId()))->fetchAll();
     // Optionally restrict the graph to the ancestors of the individuals.
     if ($ancestor) {
         $ancestors = $this->allAncestors($individual1->getXref(), $individual2->getXref(), $individual1->getTree()->getTreeId());
         $exclude = $this->excludeFamilies($individual1->getXref(), $individual2->getXref(), $individual1->getTree()->getTreeId());
     } else {
         $ancestors = array();
         $exclude = array();
     }
     $graph = array();
     foreach ($rows as $row) {
         if (!$ancestors || in_array($row->l_from, $ancestors) && !in_array($row->l_to, $exclude)) {
             $graph[$row->l_from][$row->l_to] = 1;
             $graph[$row->l_to][$row->l_from] = 1;
         }
     }
     $xref1 = $individual1->getXref();
     $xref2 = $individual2->getXref();
     $dijkstra = new Dijkstra($graph);
     $paths = $dijkstra->shortestPaths($xref1, $xref2);
     // Only process each exclusion list once;
     $excluded = array();
     $queue = array();
     foreach ($paths as $path) {
         // Insert the paths into the queue, with an exclusion list.
         $queue[] = array('path' => $path, 'exclude' => array());
         // While there are un-extended paths
         while (list(, $next) = each($queue)) {
             // For each family on the path
             for ($n = count($next['path']) - 2; $n >= 1; $n -= 2) {
                 $exclude = $next['exclude'];
                 if (count($exclude) >= $recursion) {
                     continue;
                 }
                 $exclude[] = $next['path'][$n];
                 sort($exclude);
                 $tmp = implode('-', $exclude);
                 if (in_array($tmp, $excluded)) {
                     continue;
                 } else {
                     $excluded[] = $tmp;
                 }
                 // Add any new path to the queue
                 foreach ($dijkstra->shortestPaths($xref1, $xref2, $exclude) as $new_path) {
                     $queue[] = array('path' => $new_path, 'exclude' => $exclude);
                 }
             }
         }
     }
     // Extract the paths from the queue, removing duplicates.
     $paths = array();
     foreach ($queue as $next) {
         $paths[implode('-', $next['path'])] = $next['path'];
     }
     return $paths;
 }
Ejemplo n.º 2
0
 /**
  * Return a menu item for this chart.
  *
  * @param Individual $individual
  *
  * @return Menu|null
  */
 public function getChartMenu(Individual $individual)
 {
     $tree = $individual->getTree();
     $gedcomid = $tree->getUserPreference(Auth::user(), 'gedcomid');
     if ($gedcomid) {
         return new Menu(I18N::translate('Relationship to me'), 'relationship.php?pid1=' . $gedcomid . '&pid2=' . $individual->getXref() . '&ged=' . $tree->getNameUrl(), 'menu-chart-relationship', array('rel' => 'nofollow'));
     } else {
         return new Menu(I18N::translate('Relationships'), 'relationship.php?pid1=' . $individual->getXref() . '&ged=' . $tree->getNameUrl(), 'menu-chart-relationship', array('rel' => 'nofollow'));
     }
 }
 /**
  * get edit menu
  */
 public function getEditMenu()
 {
     if (!$this->record || $this->record->isPendingDeletion()) {
         return null;
     }
     // edit menu
     $menu = new Menu(I18N::translate('Edit'), '#', 'menu-record');
     // edit raw
     if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
         $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-record-editraw', array('onclick' => 'return edit_raw("' . $this->record->getXref() . '");')));
     }
     // delete
     if (Auth::isEditor($this->record->getTree())) {
         $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-record-del', array('onclick' => 'return delete_record("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");')));
     }
     // add to favorites
     if (Module::getModuleByName('user_favorites')) {
         $menu->addSubmenu(new Menu(I18N::translate('Add to favorites'), '#', 'menu-record-addfav', array('onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite" ,{xref:"' . $this->record->getXref() . '"},function(){location.reload();})')));
     }
     // Get the link for the first submenu and set it as the link for the main menu
     if ($menu->getSubmenus()) {
         $submenus = $menu->getSubmenus();
         $menu->setLink($submenus[0]->getLink());
         $menu->setAttrs($submenus[0]->getAttrs());
     }
     return $menu;
 }
Ejemplo n.º 4
0
 /**
  * Find the spouse of a person, using the Xref comparison.
  *
  * @param Individual $person
  *
  * @return Individual|null
  */
 public function getSpouseById(\Fisharebest\Webtrees\Individual $person)
 {
     if ($this->gedcomrecord->getWife() && $person->getXref() === $this->gedcomrecord->getWife()->getXref()) {
         return $this->gedcomrecord->getHusband();
     } else {
         return $this->gedcomrecord->getWife();
     }
 }
Ejemplo n.º 5
0
 /**
  * Return a menu item for this chart.
  * 
  * We can only do this if the GD2 library is installed with TrueType support.	 	 
  *
  * @return Menu|null
  */
 public function getChartMenu(Individual $individual)
 {
     if (function_exists('imagettftext')) {
         return new Menu($this->getTitle(), 'fanchart.php?rootid=' . $individual->getXref() . '&ged=' . $individual->getTree()->getNameUrl(), 'menu-chart-fanchart', array('rel' => 'nofollow'));
     } else {
         return null;
     }
 }
Ejemplo n.º 6
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     // Automatically fix broken links
     if ($this->record && $this->record->canEdit()) {
         $broken_links = 0;
         foreach ($this->record->getFacts('HUSB|WIFE|CHIL|FAMS|FAMC|REPO') as $fact) {
             if (!$fact->isPendingDeletion() && $fact->getTarget() === null) {
                 $this->record->deleteFact($fact->getFactId(), false);
                 FlashMessages::addMessage(I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $this->record->getFullName(), $fact->getValue()));
                 $broken_links = true;
             }
         }
         foreach ($this->record->getFacts('NOTE|SOUR|OBJE') as $fact) {
             // These can be links or inline.  Only delete links.
             if (!$fact->isPendingDeletion() && $fact->getTarget() === null && preg_match('/^@.*@$/', $fact->getValue())) {
                 $this->record->deleteFact($fact->getFactId(), false);
                 FlashMessages::addMessage(I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $this->record->getFullName(), $fact->getValue()));
                 $broken_links = true;
             }
         }
         if ($broken_links) {
             // Reload the updated family
             $this->record = GedcomRecord::getInstance($this->record->getXref(), $this->record->getTree());
         }
     }
     parent::__construct();
     // We want robots to index this page
     $this->setMetaRobots('index,follow');
     // Set a page title
     if ($this->record) {
         if ($this->record->canShowName()) {
             // e.g. "John Doe" or "1881 Census of Wales"
             $this->setPageTitle($this->record->getFullName());
         } else {
             // e.g. "Individual" or "Source"
             $record = $this->record;
             $this->setPageTitle(GedcomTag::getLabel($record::RECORD_TYPE));
         }
     } else {
         // No such record
         $this->setPageTitle(I18N::translate('Private'));
     }
 }
Ejemplo n.º 7
0
 /**
  * get edit menu
  */
 public function getEditMenu()
 {
     if (!$this->record || $this->record->isPendingDeletion()) {
         return null;
     }
     // edit menu
     $menu = new Menu(I18N::translate('Edit'), '#', 'menu-record');
     // edit raw
     if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
         $menu->addSubmenu(new Menu(I18N::translate('Edit the raw GEDCOM'), '#', 'menu-record-editraw', array('onclick' => 'return edit_raw("' . $this->record->getXref() . '");')));
     }
     // delete
     if (Auth::isEditor($this->record->getTree())) {
         $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-record-del', array('onclick' => 'return delete_record("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");')));
     }
     return $menu;
 }
Ejemplo n.º 8
0
 /**
  * Add a person (and optionally their immediate family members) to the pids array
  *
  * @param Individual $person
  * @param bool $add_family
  *
  * @return array
  */
 private function addFamily(Individual $person, $add_family)
 {
     $xrefs = array();
     $xrefs[] = $person->getXref();
     if ($add_family) {
         foreach ($person->getSpouseFamilies() as $family) {
             $spouse = $family->getSpouse($person);
             if ($spouse) {
                 $xrefs[] = $spouse->getXref();
                 foreach ($family->getChildren() as $child) {
                     $xrefs[] = $child->getXref();
                 }
             }
         }
         foreach ($person->getChildFamilies() as $family) {
             foreach ($family->getSpouses() as $parent) {
                 $xrefs[] = $parent->getXref();
             }
             foreach ($family->getChildren() as $sibling) {
                 if ($person !== $sibling) {
                     $xrefs[] = $sibling->getXref();
                 }
             }
         }
     }
     return $xrefs;
 }
Ejemplo n.º 9
0
 /**
  * Return a menu item for this chart.
  *
  * @return Menu|null
  */
 public function getChartMenu(Individual $individual)
 {
     return new Menu($this->getTitle(), 'compact.php?rootid=' . $individual->getXref() . '&ged=' . $individual->getTree()->getNameUrl(), 'menu-chart-compact', array('rel' => 'nofollow'));
 }
Ejemplo n.º 10
0
 /**
  * Prints descendency of passed in person
  *
  * @param Individual $person  person to print descendency for
  * @param int        $count   count of generations to print
  * @param bool       $showNav
  *
  * @return int
  */
 public function printDescendency($person, $count, $showNav = true)
 {
     global $lastGenSecondFam;
     if ($count > $this->dgenerations) {
         return 0;
     }
     $pid = $person->getXref();
     $tablealign = 'right';
     $otablealign = 'left';
     if (I18N::direction() === 'rtl') {
         $tablealign = 'left';
         $otablealign = 'right';
     }
     //-- put a space between families on the last generation
     if ($count == $this->dgenerations - 1) {
         if (isset($lastGenSecondFam)) {
             echo '<br>';
         }
         $lastGenSecondFam = true;
     }
     echo "<table id='table_{$pid}' class='hourglassChart' style='float:{$tablealign}'>";
     echo '<tr>';
     echo "<td style='text-align:{$tablealign}'>";
     $numkids = 0;
     $families = $person->getSpouseFamilies();
     $famNum = 0;
     $children = array();
     if ($count < $this->dgenerations) {
         // Put all of the children in a common array
         foreach ($families as $family) {
             $famNum++;
             foreach ($family->getChildren() as $child) {
                 $children[] = $child;
             }
         }
         $ct = count($children);
         if ($ct > 0) {
             echo "<table style='position: relative; top: auto; float: {$tablealign};'>";
             for ($i = 0; $i < $ct; $i++) {
                 $person2 = $children[$i];
                 $chil = $person2->getXref();
                 echo '<tr>';
                 echo '<td id="td_', $chil, '" class="', I18N::direction(), '" style="text-align:', $otablealign, '">';
                 $kids = $this->printDescendency($person2, $count + 1);
                 $numkids += $kids;
                 echo '</td>';
                 // Print the lines
                 if ($ct > 1) {
                     if ($i == 0) {
                         // First child
                         echo "<td style='vertical-align:bottom'><img alt='' class='line1 tvertline' id='vline_{$chil}' src='" . Theme::theme()->parameter('image-vline') . "' width='3'></td>";
                     } elseif ($i == $ct - 1) {
                         // Last child
                         echo "<td style='vertical-align:top'><img alt='' class='bvertline' id='vline_{$chil}' src='" . Theme::theme()->parameter('image-vline') . "' width='3'></td>";
                     } else {
                         // Middle child
                         echo '<td style="background: url(\'' . Theme::theme()->parameter('image-vline') . '\');"><img src=\'' . Theme::theme()->parameter('image-spacer') . '\' width="3" alt=""></td>';
                     }
                 }
                 echo '</tr>';
             }
             echo '</table>';
         }
         echo '</td>';
         echo '<td width="', $this->getBoxDimensions()->width, '">';
     }
     // Print the descendency expansion arrow
     if ($count == $this->dgenerations) {
         $numkids = 1;
         $tbwidth = $this->getBoxDimensions()->width + 16;
         for ($j = $count; $j < $this->dgenerations; $j++) {
             echo "<div style='width: ", $tbwidth, "px;'><br></div></td><td style='width:", $this->getBoxDimensions()->width, "px'>";
         }
         $kcount = 0;
         foreach ($families as $family) {
             $kcount += $family->getNumberOfChildren();
         }
         if ($kcount == 0) {
             echo "</td><td style='width:", $this->getBoxDimensions()->width, "px'>";
         } else {
             printf(self::LINK, $this->left_arrow, $pid, 'desc', $this->showFull(), $this->show_spouse);
             //-- move the arrow up to line up with the correct box
             if ($this->show_spouse) {
                 echo str_repeat('<br><br><br>', count($families));
             }
             echo "</td><td style='width:", $this->getBoxDimensions()->width, "px'>";
         }
     }
     echo '<table id="table2_' . $pid . '"><tr><td>';
     FunctionsPrint::printPedigreePerson($person, $this->showFull());
     echo '</td><td><img class="line2" src="' . Theme::theme()->parameter('image-hline') . '" width="7" height="3">';
     //----- Print the spouse
     if ($this->show_spouse) {
         foreach ($families as $family) {
             echo "</td></tr><tr><td style='text-align:{$otablealign}'>";
             //-- shrink the box for the spouses
             $tempw = $this->getBoxDimensions()->width;
             $temph = $this->getBoxDimensions()->height;
             $this->getBoxDimensions()->width -= 10;
             $this->getBoxDimensions()->height -= 10;
             FunctionsPrint::printPedigreePerson($family->getSpouse($person), $this->showFull());
             $this->getBoxDimensions()->width = $tempw;
             $this->getBoxDimensions()->height = $temph;
             $numkids += 0.95;
             echo "</td><td></td>";
         }
         //-- add offset divs to make things line up better
         if ($count == $this->dgenerations) {
             echo "<tr><td colspan '2'><div style='height:", $this->bhalfheight / 2, "px; width:", $this->getBoxDimensions()->width, "px;'><br></div>";
         }
     }
     echo "</td></tr></table>";
     // For the root person, print a down arrow that allows changing the root of tree
     if ($showNav && $count == 1) {
         // NOTE: If statement OK
         if ($person->canShowName()) {
             // -- print left arrow for decendants so that we can move down the tree
             $famids = $person->getSpouseFamilies();
             //-- make sure there is more than 1 child in the family with parents
             $cfamids = $person->getChildFamilies();
             $num = 0;
             foreach ($cfamids as $family) {
                 $num += $family->getNumberOfChildren();
             }
             if ($num > 0) {
                 echo '<div class="center" id="childarrow" style="position:absolute; width:', $this->getBoxDimensions()->width, 'px;">';
                 echo '<a href="#" class="icon-darrow"></a>';
                 echo '<div id="childbox">';
                 echo '<table class="person_box"><tr><td>';
                 foreach ($famids as $family) {
                     echo "<span class='name1'>" . I18N::translate('Family') . "</span>";
                     $spouse = $family->getSpouse($person);
                     if ($spouse) {
                         printf(self::SWITCH_LINK, $spouse->getXref(), $this->show_spouse, $this->showFull(), $this->generations, $spouse->getFullName());
                     }
                     foreach ($family->getChildren() as $child) {
                         printf(self::SWITCH_LINK, $child->getXref(), $this->show_spouse, $this->showFull(), $this->generations, $child->getFullName());
                     }
                 }
                 //-- print the siblings
                 foreach ($cfamids as $family) {
                     if ($family->getHusband() || $family->getWife()) {
                         echo "<span class='name1'>" . I18N::translate('Parents') . "</span>";
                         $husb = $family->getHusband();
                         if ($husb) {
                             printf(self::SWITCH_LINK, $husb->getXref(), $this->show_spouse, $this->showFull(), $this->generations, $husb->getFullName());
                         }
                         $wife = $family->getWife();
                         if ($wife) {
                             printf(self::SWITCH_LINK, $wife->getXref(), $this->show_spouse, $this->showFull(), $this->generations, $wife->getFullName());
                         }
                     }
                     // filter out root person from children array so only siblings remain
                     $siblings = array_filter($family->getChildren(), function (Individual $item) use($pid) {
                         return $item->getXref() != $pid;
                     });
                     $num = count($siblings);
                     if ($num) {
                         echo "<span class='name1'>";
                         echo $num > 1 ? I18N::translate('Siblings') : I18N::translate('Sibling');
                         echo "</span>";
                         foreach ($siblings as $child) {
                             printf(self::SWITCH_LINK, $child->getXref(), $this->show_spouse, $this->showFull(), $this->generations, $child->getFullName());
                         }
                     }
                 }
                 echo '</td></tr></table>';
                 echo '</div>';
                 echo '</div>';
             }
         }
     }
     echo '</td></tr></table>';
     return $numkids;
 }
Ejemplo n.º 11
0
 /**
  * print the parents table for a family
  *
  * @param Family $family family gedcom ID
  * @param int $sosa child sosa number
  * @param string $label indi label (descendancy booklet)
  * @param string $parid parent ID (descendancy booklet)
  * @param string $gparid gd-parent ID (descendancy booklet)
  * @param int $show_full large or small box
  */
 public static function printFamilyParents(Family $family, $sosa = 0, $label = '', $parid = '', $gparid = '', $show_full = 1)
 {
     if ($show_full) {
         $pbheight = Theme::theme()->parameter('chart-box-y') + 14;
     } else {
         $pbheight = Theme::theme()->parameter('compact-chart-box-y') + 14;
     }
     $husb = $family->getHusband();
     if ($husb) {
         echo '<a name="', $husb->getXref(), '"></a>';
     } else {
         $husb = new Individual('M', "0 @M@ INDI\n1 SEX M", null, $family->getTree());
     }
     $wife = $family->getWife();
     if ($wife) {
         echo '<a name="', $wife->getXref(), '"></a>';
     } else {
         $wife = new Individual('F', "0 @F@ INDI\n1 SEX F", null, $family->getTree());
     }
     if ($sosa) {
         echo '<p class="name_head">', $family->getFullName(), '</p>';
     }
     /**
      * husband side
      */
     echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr><td rowspan=\"2\">";
     echo "<table border='0'><tr>";
     if ($parid) {
         if ($husb->getXref() == $parid) {
             self::printSosaNumber($label);
         } else {
             self::printSosaNumber($label, "", "blank");
         }
     } elseif ($sosa) {
         self::printSosaNumber($sosa * 2);
     }
     if ($husb->isPendingAddtion()) {
         echo '<td valign="top" class="facts_value new">';
     } elseif ($husb->isPendingDeletion()) {
         echo '<td valign="top" class="facts_value old">';
     } else {
         echo '<td valign="top">';
     }
     FunctionsPrint::printPedigreePerson($husb, $show_full);
     echo "</td></tr></table>";
     echo "</td>";
     // husband’s parents
     $hfam = $husb->getPrimaryChildFamily();
     if ($hfam) {
         // remove the|| test for $sosa
         echo "<td rowspan=\"2\"><img src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\"></td><td rowspan=\"2\"><img src=\"" . Theme::theme()->parameter('image-vline') . "\" width=\"3\" height=\"" . ($pbheight + 9) . "\" alt=\"\"></td>";
         echo "<td><img class=\"line5\" src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\"></td><td>";
         // husband’s father
         if ($hfam && $hfam->getHusband()) {
             echo "<table border='0'><tr>";
             if ($sosa > 0) {
                 self::printSosaNumber($sosa * 4, $hfam->getHusband()->getXref(), "down");
             }
             if (!empty($gparid) && $hfam->getHusband()->getXref() == $gparid) {
                 self::printSosaNumber(trim(substr($label, 0, -3), ".") . ".");
             }
             echo "<td valign=\"top\">";
             FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
             echo "</td></tr></table>";
         } elseif ($hfam && !$hfam->getHusband()) {
             // Empty box for grandfather
             echo "<table border='0'><tr>";
             echo '<td valign="top">';
             FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
             echo '</td></tr></table>';
         }
         echo "</td>";
     }
     if ($hfam && $sosa != -1) {
         echo '<td valign="middle" rowspan="2">';
         self::printUrlArrow($sosa == 0 ? '?famid=' . $hfam->getXref() . '&amp;ged=' . $hfam->getTree()->getNameUrl() : '#' . $hfam->getXref(), $hfam->getXref(), 1);
         echo '</td>';
     }
     if ($hfam) {
         // husband’s mother
         echo "</tr><tr><td><img src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\"></td><td>";
         if ($hfam && $hfam->getWife()) {
             echo "<table border='0'><tr>";
             if ($sosa > 0) {
                 self::printSosaNumber($sosa * 4 + 1, $hfam->getWife()->getXref(), "down");
             }
             if (!empty($gparid) && $hfam->getWife()->getXref() == $gparid) {
                 self::printSosaNumber(trim(substr($label, 0, -3), ".") . ".");
             }
             echo '<td valign="top">';
             FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
             echo '</td></tr></table>';
         } elseif ($hfam && !$hfam->getWife()) {
             // Empty box for grandmother
             echo "<table border='0'><tr>";
             echo '<td valign="top">';
             FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
             echo '</td></tr></table>';
         }
         echo '</td>';
     }
     echo '</tr></table>';
     if ($sosa && $family->canShow()) {
         foreach ($family->getFacts(WT_EVENTS_MARR) as $fact) {
             echo '<a href="', $family->getHtmlUrl(), '" class="details1">';
             echo str_repeat('&nbsp;', 10);
             echo $fact->summary();
             echo '</a>';
         }
     } else {
         echo '<br>';
     }
     /**
      * wife side
      */
     echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr><td rowspan=\"2\">";
     echo "<table><tr>";
     if ($parid) {
         if ($wife->getXref() == $parid) {
             self::printSosaNumber($label);
         } else {
             self::printSosaNumber($label, "", "blank");
         }
     } elseif ($sosa) {
         self::printSosaNumber($sosa * 2 + 1);
     }
     if ($wife->isPendingAddtion()) {
         echo '<td valign="top" class="facts_value new">';
     } elseif ($wife->isPendingDeletion()) {
         echo '<td valign="top" class="facts_value old">';
     } else {
         echo '<td valign="top">';
     }
     FunctionsPrint::printPedigreePerson($wife, $show_full);
     echo "</td></tr></table>";
     echo "</td>";
     // wife’s parents
     $hfam = $wife->getPrimaryChildFamily();
     if ($hfam) {
         echo "<td rowspan=\"2\"><img src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\"></td><td rowspan=\"2\"><img src=\"" . Theme::theme()->parameter('image-vline') . "\" width=\"3\" height=\"" . ($pbheight + 9) . "\" alt=\"\"></td>";
         echo "<td><img class=\"line5\" src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\"></td><td>";
         // wife’s father
         if ($hfam && $hfam->getHusband()) {
             echo "<table><tr>";
             if ($sosa > 0) {
                 self::printSosaNumber($sosa * 4 + 2, $hfam->getHusband()->getXref(), "down");
             }
             if (!empty($gparid) && $hfam->getHusband()->getXref() == $gparid) {
                 self::printSosaNumber(trim(substr($label, 0, -3), ".") . ".");
             }
             echo "<td valign=\"top\">";
             FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
             echo "</td></tr></table>";
         } elseif ($hfam && !$hfam->getHusband()) {
             // Empty box for grandfather
             echo "<table border='0'><tr>";
             echo '<td valign="top">';
             FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
             echo '</td></tr></table>';
         }
         echo "</td>";
     }
     if ($hfam && $sosa != -1) {
         echo '<td valign="middle" rowspan="2">';
         self::printUrlArrow($sosa == 0 ? '?famid=' . $hfam->getXref() . '&amp;ged=' . $hfam->getTree()->getNameUrl() : '#' . $hfam->getXref(), $hfam->getXref(), 1);
         echo '</td>';
     }
     if ($hfam) {
         // wife’s mother
         echo "</tr><tr><td><img src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\"></td><td>";
         if ($hfam && $hfam->getWife()) {
             echo "<table><tr>";
             if ($sosa > 0) {
                 self::printSosaNumber($sosa * 4 + 3, $hfam->getWife()->getXref(), "down");
             }
             if (!empty($gparid) && $hfam->getWife()->getXref() == $gparid) {
                 self::printSosaNumber(trim(substr($label, 0, -3), ".") . ".");
             }
             echo "<td valign=\"top\">";
             FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
             echo "</td></tr></table>";
         } elseif ($hfam && !$hfam->getWife()) {
             // Empty box for grandmother
             echo "<table border='0'><tr>";
             echo '<td valign="top">';
             FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
             echo '</td></tr></table>';
         }
         echo '</td>';
     }
     echo "</tr></table>";
 }
 /**
  * Get the events of associates.
  *
  * @param Individual $person
  *
  * @return Fact[]
  */
 private static function associateFacts(Individual $person)
 {
     $facts = array();
     $associates = array_merge($person->linkedIndividuals('ASSO'), $person->linkedIndividuals('_ASSO'), $person->linkedFamilies('ASSO'), $person->linkedFamilies('_ASSO'));
     foreach ($associates as $associate) {
         foreach ($associate->getFacts() as $fact) {
             $arec = $fact->getAttribute('_ASSO');
             if (!$arec) {
                 $arec = $fact->getAttribute('ASSO');
             }
             if ($arec && trim($arec, '@') === $person->getXref()) {
                 // Extract the important details from the fact
                 $factrec = '1 ' . $fact->getTag();
                 if (preg_match('/\\n2 DATE .*/', $fact->getGedcom(), $match)) {
                     $factrec .= $match[0];
                 }
                 if (preg_match('/\\n2 PLAC .*/', $fact->getGedcom(), $match)) {
                     $factrec .= $match[0];
                 }
                 if ($associate instanceof Family) {
                     foreach ($associate->getSpouses() as $spouse) {
                         $factrec .= "\n2 _ASSO @" . $spouse->getXref() . '@';
                     }
                 } else {
                     $factrec .= "\n2 _ASSO @" . $associate->getXref() . '@';
                 }
                 $facts[] = new Fact($factrec, $associate, 'asso');
             }
         }
     }
     return $facts;
 }
Ejemplo n.º 13
0
 /**
  * Display an individual in a box - for charts, etc.
  *
  * @param Individual $individual
  *
  * @return string
  */
 public function individualBoxSmall(Individual $individual)
 {
     $personBoxClass = array_search($individual->getSex(), array('person_box' => 'M', 'person_boxF' => 'F', 'person_boxNN' => 'U'));
     if ($individual->getTree()->getPreference('SHOW_HIGHLIGHT_IMAGES')) {
         $thumbnail = $individual->displayImage();
     } else {
         $thumbnail = '';
     }
     return '<div data-pid="' . $individual->getXref() . '" class="person_box_template ' . $personBoxClass . ' iconz box-style0" style="width: ' . $this->parameter('compact-chart-box-x') . 'px; min-height: ' . $this->parameter('compact-chart-box-y') . 'px">' . '<div class="compact_view">' . $thumbnail . '<a href="' . $individual->getHtmlUrl() . '">' . '<span class="namedef name0">' . $individual->getFullName() . '</span>' . '</a>' . '<div class="inout2 details0">' . $individual->getLifeSpan() . '</div>' . '</div>' . '<div class="inout"></div>' . '</div>';
 }
Ejemplo n.º 14
0
 /**
  * Return HTML Code to display individual in non structured list (e.g. Patronymic Lineages)
  *
  * @param \Fisharebest\Webtrees\Individual $individual Individual to print
  * @param bool $isStrong Bolden the name ?
  * @return string HTML Code for individual item
  */
 public static function htmlIndividualForList(\Fisharebest\Webtrees\Individual $individual, $isStrong = true)
 {
     $html = '';
     $tag = 'em';
     if ($isStrong) {
         $tag = 'strong';
     }
     if ($individual && $individual->canShow()) {
         $dindi = new Individual($individual);
         $html = $individual->getSexImage();
         $html .= '<a class="list_item" href="' . $individual->getHtmlUrl() . '" title="' . I18N::translate('Informations for individual %s', $individual->getXref()) . '">';
         $html .= '<' . $tag . '>' . $individual->getFullName() . '</' . $tag . '>&nbsp;(' . $individual->getXref() . ')&nbsp;';
         $html .= FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 1, 'small');
         $html .= '&nbsp;<span><small><em>' . $dindi->formatFirstMajorFact(WT_EVENTS_BIRT, 10) . '</em></small></span>';
         $html .= '&nbsp;<span><small><em>' . $dindi->formatFirstMajorFact(WT_EVENTS_DEAT, 10) . '</em></small></span>';
         $html .= '</a>';
     } else {
         $html .= '<span class=\\"list_item\\"><' . $tag . '>' . I18N::translate('Private') . '</' . $tag . '></span>';
     }
     return $html;
 }
Ejemplo n.º 15
0
 /**
  * Generate a menu item for the timeline chart (timeline.php).
  *
  * @param Individual $individual
  *
  * @return Menu
  */
 protected function menuChartTimeline(Individual $individual)
 {
     return new Menu(I18N::translate('Timeline'), 'timeline.php?pids%5B%5D=' . $individual->getXref() . '&amp;' . $this->tree_url, 'menu-chart-timeline', array('rel' => 'nofollow'));
 }
Ejemplo n.º 16
0
 /**
  * Returns the list of Sosa numbers to which an individual is related.
  * Format: key = sosa number, value = generation for the Sosa number
  * 
  * @param Individual $indi
  * @return array Array of sosa numbers
  */
 public function getSosaNumbers(Individual $indi)
 {
     if (!$this->is_setup) {
         return array();
     }
     return Database::prepare('SELECT majs_sosa, majs_gen FROM `##maj_sosa`' . ' WHERE majs_i_id=:indi_id AND majs_gedcom_id=:tree_id AND majs_user_id=:user_id')->execute(array('indi_id' => $indi->getXref(), 'tree_id' => $this->tree->getTreeId(), 'user_id' => $this->user->getUserId()))->fetchAssoc();
 }
Ejemplo n.º 17
0
/**
 * Print a form to add an individual or edit an individual’s name
 *
 * @param string     $nextaction
 * @param Individual $person
 * @param Family     $family
 * @param Fact       $name_fact
 * @param string     $famtag
 * @param string     $gender
 */
function print_indi_form($nextaction, Individual $person = null, Family $family = null, Fact $name_fact = null, $famtag = 'CHIL', $gender = 'U')
{
    global $WT_TREE, $bdm, $controller;
    if ($person) {
        $xref = $person->getXref();
    } elseif ($family) {
        $xref = $family->getXref();
    } else {
        $xref = 'new';
    }
    // Different cultures do surnames differently
    $surname_tradition = SurnameTradition::create($WT_TREE->getPreference('SURNAME_TRADITION'));
    $name_fields = array();
    if ($name_fact) {
        // Editing an existing name
        $name_fact_id = $name_fact->getFactId();
        $name_type = $name_fact->getAttribute('TYPE');
        $namerec = $name_fact->getGedcom();
        foreach (Config::standardNameFacts() as $tag) {
            if ($tag === 'NAME') {
                $name_fields[$tag] = $name_fact->getValue();
            } else {
                $name_fields[$tag] = $name_fact->getAttribute($tag);
            }
        }
        // Populate any missing 2 XXXX fields from the 1 NAME field
        $npfx_accept = implode('|', Config::namePrefixes());
        if (preg_match('/(((' . $npfx_accept . ')\\.? +)*)([^\\n\\/"]*)("(.*)")? *\\/(([a-z]{2,3} +)*)(.*)\\/ *(.*)/i', $name_fields['NAME'], $name_bits)) {
            if (empty($name_fields['NPFX'])) {
                $name_fields['NPFX'] = $name_bits[1];
            }
            if (empty($name_fields['SPFX']) && empty($name_fields['SURN'])) {
                $name_fields['SPFX'] = trim($name_bits[7]);
                // For names with two surnames, there will be four slashes.
                // Turn them into a list
                $name_fields['SURN'] = preg_replace('~/[^/]*/~', ',', $name_bits[9]);
            }
            if (empty($name_fields['GIVN'])) {
                $name_fields['GIVN'] = $name_bits[4];
            }
            if (empty($name_fields['NICK']) && !empty($name_bits[6]) && !preg_match('/^2 NICK/m', $namerec)) {
                $name_fields['NICK'] = $name_bits[6];
            }
        }
    } else {
        // Creating a new name
        $name_fact_id = null;
        $name_type = null;
        $namerec = null;
        // Populate the standard NAME field and subfields
        foreach (Config::standardNameFacts() as $tag) {
            $name_fields[$tag] = '';
        }
        // Inherit surname from parents, spouse or child
        if ($family) {
            $father = $family->getHusband();
            if ($father && $father->getFirstFact('NAME')) {
                $father_name = $father->getFirstFact('NAME')->getValue();
            } else {
                $father_name = '';
            }
            $mother = $family->getWife();
            if ($mother && $mother->getFirstFact('NAME')) {
                $mother_name = $mother->getFirstFact('NAME')->getValue();
            } else {
                $mother_name = '';
            }
        } else {
            $father = null;
            $mother = null;
            $father_name = '';
            $mother_name = '';
        }
        if ($person && $person->getFirstFact('NAME')) {
            $indi_name = $person->getFirstFact('NAME')->getValue();
        } else {
            $indi_name = '';
        }
        switch ($nextaction) {
            case 'add_child_to_family_action':
                $name_fields = $surname_tradition->newChildNames($father_name, $mother_name, $gender) + $name_fields;
                break;
            case 'add_child_to_individual_action':
                if ($person->getSex() === 'F') {
                    $name_fields = $surname_tradition->newChildNames('', $indi_name, $gender) + $name_fields;
                } else {
                    $name_fields = $surname_tradition->newChildNames($indi_name, '', $gender) + $name_fields;
                }
                break;
            case 'add_parent_to_individual_action':
                $name_fields = $surname_tradition->newParentNames($indi_name, $gender) + $name_fields;
                break;
            case 'add_spouse_to_family_action':
                if ($father) {
                    $name_fields = $surname_tradition->newSpouseNames($father_name, $gender) + $name_fields;
                } else {
                    $name_fields = $surname_tradition->newSpouseNames($mother_name, $gender) + $name_fields;
                }
                break;
            case 'add_spouse_to_individual_action':
                $name_fields = $surname_tradition->newSpouseNames($indi_name, $gender) + $name_fields;
                break;
            case 'add_unlinked_indi_action':
            case 'update':
                if ($surname_tradition->hasSurnames()) {
                    $name_fields['NAME'] = '//';
                }
                break;
        }
    }
    $bdm = '';
    // used to copy '1 SOUR' to '2 SOUR' for BIRT DEAT MARR
    echo '<div id="edit_interface-page">';
    echo '<h4>', $controller->getPageTitle(), '</h4>';
    FunctionsPrint::initializeCalendarPopup();
    echo '<form method="post" name="addchildform" onsubmit="return checkform();">';
    echo '<input type="hidden" name="ged" value="', $WT_TREE->getNameHtml(), '">';
    echo '<input type="hidden" name="action" value="', $nextaction, '">';
    echo '<input type="hidden" name="fact_id" value="', $name_fact_id, '">';
    echo '<input type="hidden" name="xref" value="', $xref, '">';
    echo '<input type="hidden" name="famtag" value="', $famtag, '">';
    echo '<input type="hidden" name="gender" value="', $gender, '">';
    echo '<input type="hidden" name="goto" value="">';
    // set by javascript
    echo Filter::getCsrf();
    echo '<table class="facts_table">';
    switch ($nextaction) {
        case 'add_child_to_family_action':
        case 'add_child_to_individual_action':
            // When adding a new child, specify the pedigree
            FunctionsEdit::addSimpleTag('0 PEDI');
            break;
        case 'update':
            // When adding/editing a name, specify the type
            FunctionsEdit::addSimpleTag('0 TYPE ' . $name_type, '', '', null, $person);
            break;
    }
    // First - new/existing standard name fields
    foreach ($name_fields as $tag => $value) {
        if (substr_compare($tag, '_', 0, 1) !== 0) {
            FunctionsEdit::addSimpleTag('0 ' . $tag . ' ' . $value);
        }
    }
    // Second - new/existing advanced name fields
    if ($surname_tradition->hasMarriedNames() || preg_match('/\\n2 _MARNM /', $namerec)) {
        $adv_name_fields = array('_MARNM' => '');
    } else {
        $adv_name_fields = array();
    }
    if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('ADVANCED_NAME_FACTS'), $match)) {
        foreach ($match[1] as $tag) {
            $adv_name_fields[$tag] = '';
        }
    }
    foreach (array_keys($adv_name_fields) as $tag) {
        // Edit existing tags, grouped together
        if (preg_match_all('/2 ' . $tag . ' (.+)/', $namerec, $match)) {
            foreach ($match[1] as $value) {
                FunctionsEdit::addSimpleTag('2 ' . $tag . ' ' . $value, '', GedcomTag::getLabel('NAME:' . $tag, $person));
                if ($tag === '_MARNM') {
                    preg_match_all('/\\/([^\\/]*)\\//', $value, $matches);
                    FunctionsEdit::addSimpleTag('2 _MARNM_SURN ' . implode(',', $matches[1]));
                }
            }
        }
        // Allow a new tag to be entered
        if (!array_key_exists($tag, $name_fields)) {
            FunctionsEdit::addSimpleTag('0 ' . $tag, '', GedcomTag::getLabel('NAME:' . $tag, $person));
            if ($tag === '_MARNM') {
                FunctionsEdit::addSimpleTag('0 _MARNM_SURN');
            }
        }
    }
    // Third - new/existing custom name fields
    foreach ($name_fields as $tag => $value) {
        if (substr_compare($tag, '_', 0, 1) === 0) {
            FunctionsEdit::addSimpleTag('0 ' . $tag . ' ' . $value);
            if ($tag === '_MARNM') {
                preg_match_all('/\\/([^\\/]*)\\//', $value, $matches);
                FunctionsEdit::addSimpleTag('2 _MARNM_SURN ' . implode(',', $matches[1]));
            }
        }
    }
    // Fourth - SOUR, NOTE, _CUSTOM, etc.
    if ($namerec) {
        $gedlines = explode("\n", $namerec);
        // -- find the number of lines in the record
        $fields = explode(' ', $gedlines[0]);
        $glevel = $fields[0];
        $level = $glevel;
        $type = trim($fields[1]);
        $tags = array();
        $i = 0;
        do {
            if ($type !== 'TYPE' && !array_key_exists($type, $name_fields) && !array_key_exists($type, $adv_name_fields)) {
                $text = '';
                for ($j = 2; $j < count($fields); $j++) {
                    if ($j > 2) {
                        $text .= ' ';
                    }
                    $text .= $fields[$j];
                }
                while ($i + 1 < count($gedlines) && preg_match('/' . ($level + 1) . ' CONT ?(.*)/', $gedlines[$i + 1], $cmatch) > 0) {
                    $text .= "\n" . $cmatch[2];
                    $i++;
                }
                FunctionsEdit::addSimpleTag($level . ' ' . $type . ' ' . $text);
            }
            $tags[] = $type;
            $i++;
            if (isset($gedlines[$i])) {
                $fields = explode(' ', $gedlines[$i]);
                $level = $fields[0];
                if (isset($fields[1])) {
                    $type = $fields[1];
                }
            }
        } while ($level > $glevel && $i < count($gedlines));
    }
    // If we are adding a new individual, add the basic details
    if ($nextaction !== 'update') {
        echo '</table><br><table class="facts_table">';
        // 1 SEX
        if ($famtag === 'HUSB' || $gender === 'M') {
            FunctionsEdit::addSimpleTag("0 SEX M");
        } elseif ($famtag === 'WIFE' || $gender === 'F') {
            FunctionsEdit::addSimpleTag('0 SEX F');
        } else {
            FunctionsEdit::addSimpleTag('0 SEX');
        }
        $bdm = 'BD';
        if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
            foreach ($matches[1] as $match) {
                if (!in_array($match, explode('|', WT_EVENTS_DEAT))) {
                    FunctionsEdit::addSimpleTags($match);
                }
            }
        }
        //-- if adding a spouse add the option to add a marriage fact to the new family
        if ($nextaction === 'add_spouse_to_individual_action' || $nextaction === 'add_spouse_to_family_action') {
            $bdm .= 'M';
            if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FAMFACTS'), $matches)) {
                foreach ($matches[1] as $match) {
                    FunctionsEdit::addSimpleTags($match);
                }
            }
        }
        if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
            foreach ($matches[1] as $match) {
                if (in_array($match, explode('|', WT_EVENTS_DEAT))) {
                    FunctionsEdit::addSimpleTags($match);
                }
            }
        }
    }
    echo keep_chan($person);
    echo '</table>';
    if ($nextaction === 'update') {
        // GEDCOM 5.5.1 spec says NAME doesn’t get a OBJE
        FunctionsEdit::printAddLayer('SOUR');
        FunctionsEdit::printAddLayer('NOTE');
        FunctionsEdit::printAddLayer('SHARED_NOTE');
        FunctionsEdit::printAddLayer('RESN');
    } else {
        FunctionsEdit::printAddLayer('SOUR', 1);
        FunctionsEdit::printAddLayer('NOTE', 1);
        FunctionsEdit::printAddLayer('SHARED_NOTE', 1);
        FunctionsEdit::printAddLayer('RESN', 1);
    }
    // If we are editing an existing name, allow raw GEDCOM editing
    if ($name_fact && (Auth::isAdmin() || $WT_TREE->getPreference('SHOW_GEDCOM_RECORD'))) {
        echo '<br><br><a href="edit_interface.php?action=editrawfact&amp;xref=', $xref, '&amp;fact_id=', $name_fact->getFactId(), '&amp;ged=', $WT_TREE->getNameUrl(), '">', I18N::translate('Edit raw GEDCOM'), '</a>';
    }
    echo '<p id="save-cancel">';
    echo '<input type="submit" class="save" value="', I18N::translate('save'), '">';
    if (preg_match('/^add_(child|spouse|parent|unlinked_indi)/', $nextaction)) {
        echo '<input type="submit" class="save" value="', I18N::translate('go to new individual'), '" onclick="document.addchildform.goto.value=\'new\';">';
    }
    echo '<input type="button" class="cancel" value="', I18N::translate('close'), '" onclick="window.close();">';
    echo '</p>';
    echo '</form>';
    $controller->addInlineJavascript('
	SURNAME_TRADITION="' . $WT_TREE->getPreference('SURNAME_TRADITION') . '";
	gender="' . $gender . '";
	famtag="' . $famtag . '";
	function trim(str) {
		str=str.replace(/\\s\\s+/g, " ");
		return str.replace(/(^\\s+)|(\\s+$)/g, "");
	}

	function lang_class(str) {
		if (str.match(/[\\u0370-\\u03FF]/)) return "greek";
		if (str.match(/[\\u0400-\\u04FF]/)) return "cyrillic";
		if (str.match(/[\\u0590-\\u05FF]/)) return "hebrew";
		if (str.match(/[\\u0600-\\u06FF]/)) return "arabic";
		return "latin"; // No matched text implies latin :-)
	}

	// Generate a full name from the name components
	function generate_name() {
		var npfx = jQuery("#NPFX").val();
		var givn = jQuery("#GIVN").val();
		var spfx = jQuery("#SPFX").val();
		var surn = jQuery("#SURN").val();
		var nsfx = jQuery("#NSFX").val();
		if (SURNAME_TRADITION === "polish" && (gender === "F" || famtag === "WIFE")) {
			surn = surn.replace(/ski$/, "ska");
			surn = surn.replace(/cki$/, "cka");
			surn = surn.replace(/dzki$/, "dzka");
			surn = surn.replace(/żki$/, "żka");
		}
		// Commas are used in the GIVN and SURN field to separate lists of surnames.
		// For example, to differentiate the two Spanish surnames from an English
		// double-barred name.
		// Commas *may* be used in other fields, and will form part of the NAME.
		if (WT_LOCALE=="vi" || WT_LOCALE=="hu") {
			// Default format: /SURN/ GIVN
			return trim(npfx+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/ "+givn.replace(/ *, */g, " ")+" "+nsfx);
		} else if (WT_LOCALE=="zh") {
			// Default format: /SURN/GIVN
			return trim(npfx+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/"+givn.replace(/ *, */g, " ")+" "+nsfx);
		} else {
			// Default format: GIVN /SURN/
			return trim(npfx+" "+givn.replace(/ *, */g, " ")+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/ "+nsfx);
		}
	}

	// Update the NAME and _MARNM fields from the name components
	// and also display the value in read-only "gedcom" format.
	function updatewholename() {
		// Don’t update the name if the user manually changed it
		if (manualChange) {
			return;
		}
		var npfx = jQuery("#NPFX").val();
		var givn = jQuery("#GIVN").val();
		var spfx = jQuery("#SPFX").val();
		var surn = jQuery("#SURN").val();
		var nsfx = jQuery("#NSFX").val();
		var name = generate_name();
		jQuery("#NAME").val(name);
		jQuery("#NAME_display").text(name);
		// Married names inherit some NSFX values, but not these
		nsfx = nsfx.replace(/^(I|II|III|IV|V|VI|Junior|Jr\\.?|Senior|Sr\\.?)$/i, "");
		// Update _MARNM field from _MARNM_SURN field and display it
		// Be careful of mixing latin/hebrew/etc. character sets.
		var ip = document.getElementsByTagName("input");
		var marnm_id = "";
		var romn = "";
		var heb = "";
		for (var i = 0; i < ip.length; i++) {
			var val = trim(ip[i].value);
			if (ip[i].id.indexOf("_HEB") === 0)
				heb = val;
			if (ip[i].id.indexOf("ROMN") === 0)
				romn = val;
			if (ip[i].id.indexOf("_MARNM") === 0) {
				if (ip[i].id.indexOf("_MARNM_SURN") === 0) {
					var msurn = "";
					if (val !== "") {
						var lc = lang_class(document.getElementById(ip[i].id).value);
						if (lang_class(name) === lc)
							msurn = trim(npfx + " " + givn + " /" + val + "/ " + nsfx);
						else if (lc === "hebrew")
							msurn = heb.replace(/\\/.*\\//, "/" + val + "/");
						else if (lang_class(romn) === lc)
							msurn = romn.replace(/\\/.*\\//, "/" + val + "/");
					}
					document.getElementById(marnm_id).value = msurn;
					document.getElementById(marnm_id+"_display").innerHTML = msurn;
				} else {
					marnm_id = ip[i].id;
				}
			}
		}
	}

	// Toggle the name editor fields between
	// <input type="hidden"> <span style="display:inline">
	// <input type="text">   <span style="display:hidden">
	var oldName = "";

	// Calls to generate_name() trigger an update - hence need to
	// set the manual change to true first.  We are probably
	// listening to the wrong events on the input fields...
	var manualChange = true;
	manualChange = generate_name() !== jQuery("#NAME").val();

	function convertHidden(eid) {
		var input1 = jQuery("#" + eid);
		var input2 = jQuery("#" + eid + "_display");
		// Note that IE does not allow us to change the type of an input, so we must create a new one.
		if (input1.attr("type")=="hidden") {
			input1.replaceWith(input1.clone().attr("type", "text"));
			input2.hide();
		} else {
			input1.replaceWith(input1.clone().attr("type", "hidden"));
			input2.show();
		}
	}

	/**
	 * if the user manually changed the NAME field, then update the textual
	 * HTML representation of it
	 * If the value changed set manualChange to true so that changing
	 * the other fields doesn’t change the NAME line
	 */
	function updateTextName(eid) {
		var element = document.getElementById(eid);
		if (element) {
			if (element.value!=oldName) manualChange = true;
			var delement = document.getElementById(eid+"_display");
			if (delement) {
				delement.innerHTML = element.value;
			}
		}
	}

	function checkform() {
		var ip=document.getElementsByTagName("input");
		for (var i=0; i<ip.length; i++) {
			// ADD slashes to _HEB and _AKA names
			if (ip[i].id.indexOf("_AKA")==0 || ip[i].id.indexOf("_HEB")==0 || ip[i].id.indexOf("ROMN")==0)
				if (ip[i].value.indexOf("/")<0 && ip[i].value!="")
					ip[i].value=ip[i].value.replace(/([^\\s]+)\\s*$/, "/$1/");
			// Blank out temporary _MARNM_SURN
			if (ip[i].id.indexOf("_MARNM_SURN")==0)
					ip[i].value="";
			// Convert "xxx yyy" and "xxx y yyy" surnames to "xxx,yyy"
			if ((SURNAME_TRADITION=="spanish" || "SURNAME_TRADITION"=="portuguese") && ip[i].id.indexOf("SURN")==0) {
				ip[i].value=document.forms[0].SURN.value.replace(/^\\s*([^\\s,]{2,})\\s+([iIyY] +)?([^\\s,]{2,})\\s*$/, "$1,$3");
			}
		}
		return true;
	}

	// If the name isn’t initially formed from the components in a standard way,
	// then don’t automatically update it.
	if (document.getElementById("NAME").value!=generate_name() && document.getElementById("NAME").value!="//") {
		convertHidden("NAME");
	}
	');
    echo '</div>';
}
Ejemplo n.º 18
0
 /**
  * Recursive method to add individual to the Sosa table, and flush it regularly
  * @param Individual $indi Individual to add
  * @param int $sosa Individual's sosa
  */
 protected function addNode(Individual $indi, $sosa)
 {
     $birth_year = $indi->getEstimatedBirthDate()->gregorianYear();
     $death_year = $indi->getEstimatedDeathDate()->gregorianYear();
     $this->tmp_sosa_table[] = array('indi' => $indi->getXref(), 'sosa' => $sosa, 'birth_year' => $birth_year, 'death_year' => $death_year);
     $this->flushTmpSosaTable();
     if ($fam = $indi->getPrimaryChildFamily()) {
         if ($husb = $fam->getHusband()) {
             $this->addNode($husb, 2 * $sosa);
         }
         if ($wife = $fam->getWife()) {
             $this->addNode($wife, 2 * $sosa + 1);
         }
     }
 }
Ejemplo n.º 19
0
 /**
  * Return a menu item for this chart.
  *
  * @return Menu|null
  */
 public function getChartMenu(Individual $individual)
 {
     return new Menu($this->getTitle(), 'module.php?mod=tree&amp;mod_action=treeview&amp;rootid=' . $individual->getXref() . '&amp;ged=' . $individual->getTree()->getNameUrl(), 'menu-chart-tree', array('rel' => 'nofollow'));
 }
Ejemplo n.º 20
0
    /**
     * Build a map for an individual.
     *
     * @param Individual $indi
     */
    private function buildIndividualMap(Individual $indi)
    {
        $GM_MAX_ZOOM = $this->getSetting('GM_MAX_ZOOM');
        $facts = $indi->getFacts();
        foreach ($indi->getSpouseFamilies() as $family) {
            $facts = array_merge($facts, $family->getFacts());
            // Add birth of children from this family to the facts array
            foreach ($family->getChildren() as $child) {
                $facts[] = $child->getFirstFact('BIRT');
            }
        }
        $facts = array_values(array_filter($facts, function ($item) {
            // remove null facts (child without birth event) and
            // facts without places
            return !is_null($item) && !$item->getPlace()->isEmpty();
        }));
        Functions::sortFacts($facts);
        // At this point we have an array of valid sorted facts
        // so now build the data structures needed for the map display
        $events = array();
        $unique_places = array();
        foreach ($facts as $fact) {
            $place_data = $this->getPlaceData($fact);
            if (!empty($place_data)) {
                $index = $place_data['index'];
                if ($place_data['mapdata']['pl_zoom']) {
                    $GM_MAX_ZOOM = min($GM_MAX_ZOOM, $place_data['mapdata']['pl_zoom']);
                }
                // Produce the html for the sidebar
                $parent = $fact->getParent();
                if ($parent instanceof Individual && $parent->getXref() !== $indi->getXref()) {
                    // Childs birth
                    $name = '<a href="' . $parent->getHtmlUrl() . '">' . $parent->getFullName() . '</a>';
                    $label = strtr($parent->getSex(), array('F' => I18N::translate('Birth of a daughter'), 'M' => I18N::translate('Birth of a son'), 'U' => I18N::translate('Birth of a child')));
                    $class = 'person_box' . strtr($parent->getSex(), array('F' => 'F', 'M' => '', 'U' => 'NN'));
                    $evtStr = '<div class="gm-event">' . $label . '<div><strong>' . $name . '</strong></div>' . $fact->getDate()->display(true) . '</div>';
                } else {
                    $spouse = $parent instanceof Family ? $parent->getSpouse($indi) : null;
                    $name = $spouse ? '<a href="' . $spouse->getHtmlUrl() . '">' . $spouse->getFullName() . '</a>' : '';
                    $label = $fact->getLabel();
                    $class = 'optionbox';
                    if ($fact->getValue() && $spouse) {
                        $evtStr = '<div class="gm-event">' . $label . '<div>' . $fact->getValue() . '</div><strong>' . $name . '</strong>' . $fact->getDate()->display(true) . '</div>';
                    } elseif ($spouse) {
                        $evtStr = '<div class="gm-event">' . $label . '<div><strong>' . $name . '</strong></div>' . $fact->getDate()->display(true) . '</div>';
                    } elseif ($fact->getValue()) {
                        $evtStr = '<div class="gm-event">' . $label . '<div> ' . $fact->getValue() . '</div>' . $fact->getDate()->display(true) . '</div>';
                    } else {
                        $evtStr = '<div class="gm-event">' . $label . '<div>' . $fact->getDate()->display(true) . '</div></div>';
                    }
                }
                if (empty($unique_places[$index])) {
                    $unique_places[$index] = $place_data['mapdata'];
                }
                $unique_places[$index]['events'] .= $evtStr;
                $events[] = array('class' => $class, 'fact_label' => $label, 'date' => $fact->getDate()->display(true), 'info' => $fact->getValue(), 'name' => $name, 'place' => '<a href="' . $fact->getPlace()->getURL() . '">' . $fact->getPlace()->getFullName() . '</a>', 'placeid' => $index);
            }
        }
        if (!empty($events)) {
            $places = array_keys($unique_places);
            ob_start();
            // Create the normal googlemap sidebar of events and children
            echo '<div class="gm-events"><table class="facts_table">';
            foreach ($events as $event) {
                $index = array_search($event['placeid'], $places);
                echo '<tr>';
                echo '<td class="facts_label">';
                echo '<a href="#" onclick="return openInfowindow(\'', $index, '\')">', $event['fact_label'], '</a></td>';
                echo '<td class="', $event['class'], '">';
                if ($event['info']) {
                    echo '<div><span class="field">', Filter::escapeHtml($event['info']), '</span></div>';
                }
                if ($event['name']) {
                    echo '<div>', $event['name'], '</div>';
                }
                echo '<div>', $event['place'], '</div>';
                if ($event['date']) {
                    echo '<div>', $event['date'], '</div>';
                }
                echo '</td>';
                echo '</tr>';
            }
            echo '</table></div>';
            // *** ENABLE STREETVIEW ***
            $STREETVIEW = (bool) $this->getSetting('GM_USE_STREETVIEW');
            ?>

			<script>
				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"] = {
					url:    "https://maps.google.com/mapfiles/marker.png",
					size:   google.maps.Size(20, 34),
					origin: google.maps.Point(0, 0),
					anchor: google.maps.Point(9, 34)
				};

				var iconImage = {
					url:    "https://maps.google.com/mapfiles/marker.png",
					size:   new google.maps.Size(20, 34),
					origin: new google.maps.Point(0, 0),
					anchor: 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] = {
							url:    '//maps.google.com/mapfiles/marker' + iconColor + '.png',
							size:   new google.maps.Size(20, 34),
							origin: new google.maps.Point(0, 0),
							anchor: 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) {
					// Use flag icon (if defined) instead of regular marker icon
					if (marker_icon) {
						var icon_image = {
							url:    WT_STATIC_URL + WT_MODULES_DIR + 'googlemap/' + marker_icon,
							size:   new google.maps.Size(25, 15),
							origin: new google.maps.Point(0, 0),
							anchor: new google.maps.Point(12, 15)
						};
					} else {
						var icon_image = getMarkerImage('red');
					}

					// 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,
						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(html);
						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
							}
						};

						// Tabs within the info-windows.
						<?php 
            if ($STREETVIEW) {
                ?>
						google.maps.event.addListener(infowindow, 'domready', function() {
							jQuery('#gm-tab-events').click(function () {
								document.getElementById("gm-tab-events").classList.add('gm-tab-active');
								document.getElementById("gm-tab-streetview").classList.remove('gm-tab-active');
								document.getElementById("gm-pane-events").style.display = 'block';
								document.getElementById("gm-pane-streetview").style.display = 'none';

								return false;
							});
							jQuery('#gm-tab-streetview').click(function () {
								document.getElementById("gm-tab-events").classList.remove('gm-tab-active');
								document.getElementById("gm-tab-streetview").classList.add('gm-tab-active');
								document.getElementById("gm-pane-events").style.display = 'none';
								document.getElementById("gm-pane-streetview").style.display = 'block';
								var panorama = new google.maps.StreetViewPanorama(document.querySelector(".gm-streetview"), panoramaOptions);

								return false;
							});
						});
						<?php 
            }
            ?>
					});
				}

				// Opens Marker infowindow when corresponding Sidebar item is clicked
				function openInfowindow(i) {
					infowindow.close();
					google.maps.event.trigger(gmarkers[i], 'click');
					return false;
				}

				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:        true,
						scrollwheel:              true
					};
					map = new google.maps.Map(document.querySelector('.gm-map'), mapOptions);

					// Close any infowindow when map is clicked
					google.maps.event.addListener(map, 'click', function() {
						infowindow.close();
					});

					// Add the markers to the map

					// Group the markers by location
					var locations = <?php 
            echo json_encode($unique_places);
            ?>
;

					// Set the Marker bounds
					var bounds = new google.maps.LatLngBounds();
					var zoomLevel = <?php 
            echo $GM_MAX_ZOOM;
            ?>
;

					jQuery.each(locations, function(index, location) {
						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 html      =
					    '<div class="gm-info-window">' +
					    '<div class="gm-info-window-header">' + location.place + '</div>' +
					    '<ul class="gm-tabs">' +
					    '<li class="gm-tab gm-tab-active" id="gm-tab-events"><a href="#"><?php 
            echo I18N::translate('Events');
            ?>
</a></li>' +
					    <?php 
            if ($STREETVIEW) {
                ?>
					    '<li class="gm-tab" id="gm-tab-streetview"><a href="#"><?php 
                echo I18N::translate('Google Street View™');
                ?>
</a></li>' +
					    <?php 
            }
            ?>
					    '</ul>' +
						  '<div class="gm-panes">' +
					    '<div class="gm-pane" id="gm-pane-events">' + location.events + '</div>' +
					    <?php 
            if ($STREETVIEW) {
                ?>
					    '<div class="gm-pane" id="gm-pane-streetview" hidden><div class="gm-streetview"></div></div>' +
					    <?php 
            }
            ?>
					    '</div>' +
					    '</div>';

						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;
						}
						bounds.extend(myLatLng);
					}); // end loop through location markers

					map.setCenter(bounds.getCenter());
					map.fitBounds(bounds);
					google.maps.event.addListenerOnce(map, "bounds_changed", function(event) {
						if (this.getZoom() > zoomLevel) {
							this.setZoom(zoomLevel);
						}
					});
				} // end loadMap()

			</script>
			<?php 
            $html = ob_get_clean();
        } else {
            $html = '';
        }
        return $html;
    }
Ejemplo n.º 21
0
 /**
  * Get relationship between two individuals in the gedcom
  *
  * @param Individual $person1 The person to compute the relationship from
  * @param Individual $person2 The person to compute the relatiohip to
  * @param int $maxlength The maximum length of path
  *
  * @return array|bool An array of nodes on the relationship path, or false if no path found
  */
 public static function getRelationship(Individual $person1, Individual $person2, $maxlength = 4)
 {
     if ($person1 === $person2) {
         return false;
     }
     $spouse_codes = array('M' => 'hus', 'F' => 'wif', 'U' => 'spo');
     $parent_codes = array('M' => 'fat', 'F' => 'mot', 'U' => 'par');
     $child_codes = array('M' => 'son', 'F' => 'dau', 'U' => 'chi');
     $sibling_codes = array('M' => 'bro', 'F' => 'sis', 'U' => 'sib');
     //-- current path nodes
     $p1nodes = array();
     //-- ids visited
     $visited = array();
     //-- set up first node for person1
     $node1 = array('path' => array($person1), 'length' => 0, 'indi' => $person1, 'relations' => array('self'));
     $p1nodes[] = $node1;
     $visited[$person1->getXref()] = true;
     $found = false;
     while (!$found) {
         //-- search the node list for the shortest path length
         $shortest = -1;
         foreach ($p1nodes as $index => $node) {
             if ($shortest == -1) {
                 $shortest = $index;
             } else {
                 $node1 = $p1nodes[$shortest];
                 if ($node1['length'] > $node['length']) {
                     $shortest = $index;
                 }
             }
         }
         if ($shortest === -1) {
             return false;
         }
         $node = $p1nodes[$shortest];
         if ($maxlength == 0 || count($node['path']) <= $maxlength) {
             $indi = $node['indi'];
             //-- check all parents and siblings of this node
             foreach ($indi->getChildFamilies(Auth::PRIV_HIDE) as $family) {
                 $visited[$family->getXref()] = true;
                 foreach ($family->getSpouses(Auth::PRIV_HIDE) as $spouse) {
                     if (!isset($visited[$spouse->getXref()])) {
                         $node1 = $node;
                         $node1['length']++;
                         $node1['path'][] = $spouse;
                         $node1['indi'] = $spouse;
                         $node1['relations'][] = $parent_codes[$spouse->getSex()];
                         $p1nodes[] = $node1;
                         if ($spouse === $person2) {
                             $found = true;
                             $resnode = $node1;
                         } else {
                             $visited[$spouse->getXref()] = true;
                         }
                     }
                 }
                 foreach ($family->getChildren(Auth::PRIV_HIDE) as $child) {
                     if (!isset($visited[$child->getXref()])) {
                         $node1 = $node;
                         $node1['length']++;
                         $node1['path'][] = $child;
                         $node1['indi'] = $child;
                         $node1['relations'][] = $sibling_codes[$child->getSex()];
                         $p1nodes[] = $node1;
                         if ($child === $person2) {
                             $found = true;
                             $resnode = $node1;
                         } else {
                             $visited[$child->getXref()] = true;
                         }
                     }
                 }
             }
             //-- check all spouses and children of this node
             foreach ($indi->getSpouseFamilies(Auth::PRIV_HIDE) as $family) {
                 $visited[$family->getXref()] = true;
                 foreach ($family->getSpouses(Auth::PRIV_HIDE) as $spouse) {
                     if (!in_array($spouse->getXref(), $node1) || !isset($visited[$spouse->getXref()])) {
                         $node1 = $node;
                         $node1['length']++;
                         $node1['path'][] = $spouse;
                         $node1['indi'] = $spouse;
                         $node1['relations'][] = $spouse_codes[$spouse->getSex()];
                         $p1nodes[] = $node1;
                         if ($spouse === $person2) {
                             $found = true;
                             $resnode = $node1;
                         } else {
                             $visited[$spouse->getXref()] = true;
                         }
                     }
                 }
                 foreach ($family->getChildren(Auth::PRIV_HIDE) as $child) {
                     if (!isset($visited[$child->getXref()])) {
                         $node1 = $node;
                         $node1['length']++;
                         $node1['path'][] = $child;
                         $node1['indi'] = $child;
                         $node1['relations'][] = $child_codes[$child->getSex()];
                         $p1nodes[] = $node1;
                         if ($child === $person2) {
                             $found = true;
                             $resnode = $node1;
                         } else {
                             $visited[$child->getXref()] = true;
                         }
                     }
                 }
             }
         }
         unset($p1nodes[$shortest]);
     }
     return $resnode;
 }
Ejemplo n.º 22
0
 /**
  * Does an individual (or their spouse-families) have any facts with places?
  *
  * @param Individual $individual
  *
  * @return bool
  */
 private function checkMapData(Individual $individual)
 {
     $statement = Database::prepare("SELECT COUNT(*) FROM `##placelinks` WHERE pl_gid = :xref AND pl_file = :tree_id");
     $args = array('xref' => $individual->getXref(), 'tree_id' => $individual->getTree()->getTreeId());
     if ($statement->execute($args)->fetchOne()) {
         return true;
     }
     foreach ($individual->getSpouseFamilies() as $family) {
         $args['xref'] = $family->getXref();
         if ($statement->execute($args)->fetchOne()) {
             return true;
         }
     }
     return false;
 }
Ejemplo n.º 23
0
 /**
  * Find all the individuals that are descended from an individual.
  *
  * @param Individual   $person
  * @param int          $n
  * @param Individual[] $array
  *
  * @return Individual[]
  */
 public function individualDescendancy(Individual $person, $n, $array)
 {
     if ($n < 1) {
         return $array;
     }
     $array[$person->getXref()] = $person;
     foreach ($person->getSpouseFamilies() as $family) {
         $spouse = $family->getSpouse($person);
         if ($spouse) {
             $array[$spouse->getXref()] = $spouse;
         }
         foreach ($family->getChildren() as $child) {
             $array = $this->individualDescendancy($child, $n - 1, $array);
         }
     }
     return $array;
 }
Ejemplo n.º 24
0
 /**
  * Generate an HTML row of data for the census
  *
  * @param CensusInterface $census
  * @param Individual      $individual
  * @param Individual|null $head
  *
  * @return string
  */
 public static function censusTableRow(CensusInterface $census, Individual $individual, Individual $head = null)
 {
     $html = '<td>' . $individual->getXref() . '</td>';
     foreach ($census->columns() as $column) {
         $html .= '<td><input type="text" value="' . $column->generate($individual, $head) . '"></td>';
     }
     return '<tr>' . $html . '</tr>';
 }
Ejemplo n.º 25
0
 /**
  * Return a menu item for this chart.
  *
  * @return Menu|null
  */
 public function getChartMenu(Individual $individual)
 {
     return new Menu($this->getTitle(), 'timeline.php?pids%5B%5D=' . $individual->getXref() . '&amp;ged=' . $individual->getTree()->getNameUrl(), 'menu-chart-timeline', array('rel' => 'nofollow'));
 }