コード例 #1
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 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;
 }
コード例 #2
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     $xref = Filter::get('famid', WT_REGEX_XREF);
     $this->record = Family::getInstance($xref, $WT_TREE);
     parent::__construct();
 }
コード例 #3
0
ファイル: Family.php プロジェクト: jon48/webtrees-lib
 /**
  * Extend \Fisharebest\Webtrees\Family getInstance, in order to retrieve directly a \MyArtJaub\Webtrees\Family object 
  *
  * @param string $xref
  * @param Tree $tree
  * @param string $gedcom
  * @return NULL|\MyArtJaub\Webtrees\Family
  */
 public static function getIntance($xref, Tree $tree, $gedcom = null)
 {
     $dfam = null;
     $fam = fw\Family::getInstance($xref, $tree, $gedcom);
     if ($fam) {
         $dfam = new Family($fam);
     }
     return $dfam;
 }
コード例 #4
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;
 }
コード例 #5
0
 /**
  * Autocomplete search for families.
  *
  * @param Tree   $tree  Search this tree
  * @param string $query Search for this text
  *
  * @return string
  */
 private function search(Tree $tree, $query)
 {
     if (strlen($query) < 2) {
         return '';
     }
     $rows = Database::prepare("SELECT i_id AS xref" . " FROM `##individuals`, `##name`" . " WHERE (i_id LIKE CONCAT('%', :query_1, '%') OR n_sort LIKE CONCAT('%', :query_2, '%'))" . " AND i_id = n_id AND i_file = n_file AND i_file = :tree_id" . " ORDER BY n_sort COLLATE :collation" . " LIMIT 50")->execute(array('query_1' => $query, 'query_2' => $query, 'tree_id' => $tree->getTreeId(), 'collation' => I18N::collation()))->fetchAll();
     $ids = array();
     foreach ($rows as $row) {
         $ids[] = $row->xref;
     }
     $vars = array();
     if (empty($ids)) {
         //-- no match : search for FAM id
         $where = "f_id LIKE CONCAT('%', ?, '%')";
         $vars[] = $query;
     } else {
         //-- search for spouses
         $qs = implode(',', array_fill(0, count($ids), '?'));
         $where = "(f_husb IN ({$qs}) OR f_wife IN ({$qs}))";
         $vars = array_merge($vars, $ids, $ids);
     }
     $vars[] = $tree->getTreeId();
     $rows = Database::prepare("SELECT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom FROM `##families` WHERE {$where} AND f_file=?")->execute($vars)->fetchAll();
     $out = '<ul>';
     foreach ($rows as $row) {
         $family = Family::getInstance($row->xref, $tree, $row->gedcom);
         if ($family->canShowName()) {
             $out .= '<li><a href="' . $family->getHtmlUrl() . '">' . $family->getFullName() . ' ';
             if ($family->canShow()) {
                 $marriage_year = $family->getMarriageYear();
                 if ($marriage_year) {
                     $out .= ' (' . $marriage_year . ')';
                 }
             }
             $out .= '</a></li>';
         }
     }
     $out .= '</ul>';
     return $out;
 }
コード例 #6
0
 /**
  * add a new tag input field
  *
  * called for each fact to be edited on a form.
  * Fact level=0 means a new empty form : data are POSTed by name
  * else data are POSTed using arrays :
  * glevels[] : tag level
  *  islink[] : tag is a link
  *     tag[] : tag name
  *    text[] : tag value
  *
  * @param string $tag fact record to edit (eg 2 DATE xxxxx)
  * @param string $upperlevel optional upper level tag (eg BIRT)
  * @param string $label An optional label to echo instead of the default
  * @param string $extra optional text to display after the input field
  * @param Individual $person For male/female translations
  *
  * @return string
  */
 public static function addSimpleTag($tag, $upperlevel = '', $label = '', $extra = null, Individual $person = null)
 {
     global $tags, $main_fact, $xref, $bdm, $action, $WT_TREE;
     // Keep track of SOUR fields, so we can reference them in subsequent PAGE fields.
     static $source_element_id;
     $subnamefacts = array('NPFX', 'GIVN', 'SPFX', 'SURN', 'NSFX', '_MARNM_SURN');
     preg_match('/^(?:(\\d+) (' . WT_REGEX_TAG . ') ?(.*))/', $tag, $match);
     list(, $level, $fact, $value) = $match;
     $level = (int) $level;
     // element name : used to POST data
     if ($level === 0) {
         if ($upperlevel) {
             $element_name = $upperlevel . '_' . $fact;
         } else {
             $element_name = $fact;
         }
     } else {
         $element_name = 'text[]';
     }
     if ($level === 1) {
         $main_fact = $fact;
     }
     // element id : used by javascript functions
     if ($level === 0) {
         $element_id = $fact;
     } else {
         $element_id = $fact . Uuid::uuid4();
     }
     if ($upperlevel) {
         $element_id = $upperlevel . '_' . $fact . Uuid::uuid4();
     }
     // field value
     $islink = substr($value, 0, 1) === '@' && substr($value, 0, 2) !== '@#';
     if ($islink) {
         $value = trim(substr($tag, strlen($fact) + 3), ' @\\r');
     } else {
         $value = (string) substr($tag, strlen($fact) + 3);
     }
     if ($fact === 'REPO' || $fact === 'SOUR' || $fact === 'OBJE' || $fact === 'FAMC') {
         $islink = true;
     }
     if ($fact === 'SHARED_NOTE_EDIT' || $fact === 'SHARED_NOTE') {
         $islink = true;
         $fact = 'NOTE';
     }
     // label
     echo '<tr id="', $element_id, '_tr"';
     if ($fact === 'MAP' || ($fact === 'LATI' || $fact === 'LONG') && $value === '') {
         echo ' style="display:none;"';
     }
     echo '>';
     if (in_array($fact, $subnamefacts) || $fact === 'LATI' || $fact === 'LONG') {
         echo '<td class="optionbox wrap width25">';
     } else {
         echo '<td class="descriptionbox wrap width25">';
     }
     // tag name
     if ($label) {
         echo $label;
     } elseif ($upperlevel) {
         echo GedcomTag::getLabel($upperlevel . ':' . $fact);
     } else {
         echo GedcomTag::getLabel($fact);
     }
     // If using GEDFact-assistant window
     if ($action === 'addnewnote_assisted') {
         // Do not print on GEDFact Assistant window
     } else {
         // Not all facts have help text.
         switch ($fact) {
             case 'NAME':
                 if ($upperlevel !== 'REPO' && $upperlevel !== 'UNKNOWN') {
                     echo FunctionsPrint::helpLink($fact);
                 }
                 break;
             case 'DATE':
             case 'PLAC':
             case 'RESN':
             case 'ROMN':
             case 'SURN':
             case '_HEB':
                 echo FunctionsPrint::helpLink($fact);
                 break;
         }
     }
     // tag level
     if ($level > 0) {
         if ($fact === 'TEXT' && $level > 1) {
             echo '<input type="hidden" name="glevels[]" value="', $level - 1, '">';
             echo '<input type="hidden" name="islink[]" value="0">';
             echo '<input type="hidden" name="tag[]" value="DATA">';
             // leave data text[] value empty because the following TEXT line will cause the DATA to be added
             echo '<input type="hidden" name="text[]" value="">';
         }
         echo '<input type="hidden" name="glevels[]" value="', $level, '">';
         echo '<input type="hidden" name="islink[]" value="', $islink, '">';
         echo '<input type="hidden" name="tag[]" value="', $fact, '">';
     }
     echo '</td>';
     // value
     echo '<td class="optionbox wrap">';
     // retrieve linked NOTE
     if ($fact === 'NOTE' && $islink) {
         $note1 = Note::getInstance($value, $WT_TREE);
         if ($note1) {
             $noterec = $note1->getGedcom();
             preg_match('/' . $value . '/i', $noterec, $notematch);
             $value = $notematch[0];
         }
     }
     // Show names for spouses in MARR/HUSB/AGE and MARR/WIFE/AGE
     if ($fact === 'HUSB' || $fact === 'WIFE') {
         $family = Family::getInstance($xref, $WT_TREE);
         if ($family) {
             $spouse_link = $family->getFirstFact($fact);
             if ($spouse_link) {
                 $spouse = $spouse_link->getTarget();
                 if ($spouse) {
                     echo $spouse->getFullName();
                 }
             }
         }
     }
     if (in_array($fact, Config::emptyFacts()) && ($value === '' || $value === 'Y' || $value === 'y')) {
         echo '<input type="hidden" id="', $element_id, '" name="', $element_name, '" value="', $value, '">';
         if ($level <= 1) {
             echo '<input type="checkbox" ';
             if ($value) {
                 echo 'checked';
             }
             echo ' onclick="document.getElementById(\'' . $element_id . '\').value = (this.checked) ? \'Y\' : \'\';">';
             echo I18N::translate('yes');
         }
         if ($fact === 'CENS' && $value === 'Y') {
             echo self::censusDateSelector(WT_LOCALE, $xref);
             if (Module::getModuleByName('GEDFact_assistant') && GedcomRecord::getInstance($xref, $WT_TREE) instanceof Individual) {
                 echo '<div></div><a href="#" style="display: none;" id="assistant-link" onclick="return activateCensusAssistant();">' . I18N::translate('Create a new shared note using assistant') . '</a></div>';
             }
         }
     } elseif ($fact === 'TEMP') {
         echo self::selectEditControl($element_name, GedcomCodeTemp::templeNames(), I18N::translate('No temple - living ordinance'), $value);
     } elseif ($fact === 'ADOP') {
         echo self::editFieldAdoption($element_name, $value, '', $person);
     } elseif ($fact === 'PEDI') {
         echo self::editFieldPedigree($element_name, $value, '', $person);
     } elseif ($fact === 'STAT') {
         echo self::selectEditControl($element_name, GedcomCodeStat::statusNames($upperlevel), '', $value);
     } elseif ($fact === 'RELA') {
         echo self::editFieldRelationship($element_name, strtolower($value));
     } elseif ($fact === 'QUAY') {
         echo self::selectEditControl($element_name, GedcomCodeQuay::getValues(), '', $value);
     } elseif ($fact === '_WT_USER') {
         echo self::editFieldUsername($element_name, $value);
     } elseif ($fact === 'RESN') {
         echo self::editFieldRestriction($element_name, $value);
     } elseif ($fact === '_PRIM') {
         echo '<select id="', $element_id, '" name="', $element_name, '" >';
         echo '<option value=""></option>';
         echo '<option value="Y" ';
         if ($value === 'Y') {
             echo ' selected';
         }
         echo '>', I18N::translate('always'), '</option>';
         echo '<option value="N" ';
         if ($value === 'N') {
             echo 'selected';
         }
         echo '>', I18N::translate('never'), '</option>';
         echo '</select>';
         echo '<p class="small text-muted">', I18N::translate('Use this image for charts and on the individual’s page.'), '</p>';
     } elseif ($fact === 'SEX') {
         echo '<select id="', $element_id, '" name="', $element_name, '"><option value="M" ';
         if ($value === 'M') {
             echo 'selected';
         }
         echo '>', I18N::translate('Male'), '</option><option value="F" ';
         if ($value === 'F') {
             echo 'selected';
         }
         echo '>', I18N::translate('Female'), '</option><option value="U" ';
         if ($value === 'U' || empty($value)) {
             echo 'selected';
         }
         echo '>', I18N::translateContext('unknown gender', 'Unknown'), '</option></select>';
     } elseif ($fact === 'TYPE' && $level === 3) {
         //-- Build the selector for the Media 'TYPE' Fact
         echo '<select name="text[]"><option selected value="" ></option>';
         $selectedValue = strtolower($value);
         if (!array_key_exists($selectedValue, GedcomTag::getFileFormTypes())) {
             echo '<option selected value="', Filter::escapeHtml($value), '" >', Filter::escapeHtml($value), '</option>';
         }
         foreach (GedcomTag::getFileFormTypes() as $typeName => $typeValue) {
             echo '<option value="', $typeName, '" ';
             if ($selectedValue === $typeName) {
                 echo 'selected';
             }
             echo '>', $typeValue, '</option>';
         }
         echo '</select>';
     } elseif ($fact === 'NAME' && $upperlevel !== 'REPO' && $upperlevel !== 'UNKNOWN' || $fact === '_MARNM') {
         // Populated in javascript from sub-tags
         echo '<input type="hidden" id="', $element_id, '" name="', $element_name, '" onchange="updateTextName(\'', $element_id, '\');" value="', Filter::escapeHtml($value), '" class="', $fact, '">';
         echo '<span id="', $element_id, '_display" dir="auto">', Filter::escapeHtml($value), '</span>';
         echo ' <a href="#edit_name" onclick="convertHidden(\'', $element_id, '\'); return false;" class="icon-edit_indi" title="' . I18N::translate('Edit name') . '"></a>';
     } else {
         // textarea
         if ($fact === 'TEXT' || $fact === 'ADDR' || $fact === 'NOTE' && !$islink) {
             echo '<textarea id="', $element_id, '" name="', $element_name, '" dir="auto">', Filter::escapeHtml($value), '</textarea><br>';
         } else {
             // text
             // If using GEDFact-assistant window
             if ($action === 'addnewnote_assisted') {
                 echo '<input type="text" id="', $element_id, '" name="', $element_name, '" value="', Filter::escapeHtml($value), '" style="width:4.1em;" dir="ltr"';
             } else {
                 echo '<input type="text" id="', $element_id, '" name="', $element_name, '" value="', Filter::escapeHtml($value), '" dir="ltr"';
             }
             echo ' class="', $fact, '"';
             if (in_array($fact, $subnamefacts)) {
                 echo ' onblur="updatewholename();" onkeyup="updatewholename();"';
             }
             // Extra markup for specific fact types
             switch ($fact) {
                 case 'ALIA':
                 case 'ASSO':
                 case '_ASSO':
                     echo ' data-autocomplete-type="ASSO" data-autocomplete-extra="input.DATE"';
                     break;
                 case 'DATE':
                     echo ' onblur="valid_date(this);" onmouseout="valid_date(this);"';
                     break;
                 case 'GIVN':
                     echo ' autofocus data-autocomplete-type="GIVN"';
                     break;
                 case 'LATI':
                     echo ' onblur="valid_lati_long(this, \'N\', \'S\');" onmouseout="valid_lati_long(this, \'N\', \'S\');"';
                     break;
                 case 'LONG':
                     echo ' onblur="valid_lati_long(this, \'E\', \'W\');" onmouseout="valid_lati_long(this, \'E\', \'W\');"';
                     break;
                 case 'NOTE':
                     // Shared notes. Inline notes are handled elsewhere.
                     echo ' data-autocomplete-type="NOTE"';
                     break;
                 case 'OBJE':
                     echo ' data-autocomplete-type="OBJE"';
                     break;
                 case 'PAGE':
                     echo ' data-autocomplete-type="PAGE" data-autocomplete-extra="#' . $source_element_id . '"';
                     break;
                 case 'PLAC':
                     echo ' data-autocomplete-type="PLAC"';
                     break;
                 case 'REPO':
                     echo ' data-autocomplete-type="REPO"';
                     break;
                 case 'SOUR':
                     $source_element_id = $element_id;
                     echo ' data-autocomplete-type="SOUR"';
                     break;
                 case 'SURN':
                 case '_MARNM_SURN':
                     echo ' data-autocomplete-type="SURN"';
                     break;
                 case 'TIME':
                     echo ' pattern="([0-1][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?" dir="ltr" placeholder="' . I18N::translate('hh:mm or hh:mm:ss') . '"';
                     break;
             }
             echo '>';
         }
         $tmp_array = array('TYPE', 'TIME', 'NOTE', 'SOUR', 'REPO', 'OBJE', 'ASSO', '_ASSO', 'AGE');
         // split PLAC
         if ($fact === 'PLAC') {
             echo '<div id="', $element_id, '_pop" style="display: inline;">';
             echo FunctionsPrint::printSpecialCharacterLink($element_id), ' ', FunctionsPrint::printFindPlaceLink($element_id);
             echo '<span  onclick="jQuery(\'tr[id^=', $upperlevel, '_LATI],tr[id^=', $upperlevel, '_LONG],tr[id^=LATI],tr[id^=LONG]\').toggle(\'fast\'); return false;" class="icon-target" title="', GedcomTag::getLabel('LATI'), ' / ', GedcomTag::getLabel('LONG'), '"></span>';
             echo '</div>';
             if (Module::getModuleByName('places_assistant')) {
                 \PlacesAssistantModule::setup_place_subfields($element_id);
                 \PlacesAssistantModule::print_place_subfields($element_id);
             }
         } elseif (!in_array($fact, $tmp_array)) {
             echo FunctionsPrint::printSpecialCharacterLink($element_id);
         }
     }
     // MARRiage TYPE : hide text field and show a selection list
     if ($fact === 'TYPE' && $level === 2 && $tags[0] === 'MARR') {
         echo '<script>';
         echo 'document.getElementById(\'', $element_id, '\').style.display=\'none\'';
         echo '</script>';
         echo '<select id="', $element_id, '_sel" onchange="document.getElementById(\'', $element_id, '\').value=this.value;" >';
         foreach (array('Unknown', 'Civil', 'Religious', 'Partners') as $key) {
             if ($key === 'Unknown') {
                 echo '<option value="" ';
             } else {
                 echo '<option value="', $key, '" ';
             }
             $a = strtolower($key);
             $b = strtolower($value);
             if ($b !== '' && strpos($a, $b) !== false || strpos($b, $a) !== false) {
                 echo 'selected';
             }
             echo '>', GedcomTag::getLabel('MARR_' . strtoupper($key)), '</option>';
         }
         echo '</select>';
     } elseif ($fact === 'TYPE' && $level === 0) {
         // NAME TYPE : hide text field and show a selection list
         $onchange = 'onchange="document.getElementById(\'' . $element_id . '\').value=this.value;"';
         echo self::editFieldNameType($element_name, $value, $onchange, $person);
         echo '<script>document.getElementById("', $element_id, '").style.display="none";</script>';
     }
     // popup links
     switch ($fact) {
         case 'DATE':
             echo self::printCalendarPopup($element_id);
             break;
         case 'FAMC':
         case 'FAMS':
             echo FunctionsPrint::printFindFamilyLink($element_id);
             break;
         case 'ALIA':
         case 'ASSO':
         case '_ASSO':
             echo FunctionsPrint::printFindIndividualLink($element_id, $element_id . '_description');
             break;
         case 'FILE':
             FunctionsPrint::printFindMediaLink($element_id, '0file');
             break;
         case 'SOUR':
             echo FunctionsPrint::printFindSourceLink($element_id, $element_id . '_description'), ' ', self::printAddNewSourceLink($element_id);
             //-- checkboxes to apply '1 SOUR' to BIRT/MARR/DEAT as '2 SOUR'
             if ($level === 1) {
                 echo '<br>';
                 switch ($WT_TREE->getPreference('PREFER_LEVEL2_SOURCES')) {
                     case '2':
                         // records
                         $level1_checked = 'checked';
                         $level2_checked = '';
                         break;
                     case '1':
                         // facts
                         $level1_checked = '';
                         $level2_checked = 'checked';
                         break;
                     case '0':
                         // none
                     // none
                     default:
                         $level1_checked = '';
                         $level2_checked = '';
                         break;
                 }
                 if (strpos($bdm, 'B') !== false) {
                     echo ' <label><input type="checkbox" name="SOUR_INDI" ', $level1_checked, ' value="1">', I18N::translate('Individual'), '</label>';
                     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))) {
                                 echo ' <label><input type="checkbox" name="SOUR_', $match, '" ', $level2_checked, ' value="1">', GedcomTag::getLabel($match), '</label>';
                             }
                         }
                     }
                 }
                 if (strpos($bdm, 'D') !== false) {
                     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))) {
                                 echo ' <label><input type="checkbox" name="SOUR_', $match, '"', $level2_checked, ' value="1">', GedcomTag::getLabel($match), '</label>';
                             }
                         }
                     }
                 }
                 if (strpos($bdm, 'M') !== false) {
                     echo ' <label><input type="checkbox" name="SOUR_FAM" ', $level1_checked, ' value="1">', I18N::translate('Family'), '</label>';
                     if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FAMFACTS'), $matches)) {
                         foreach ($matches[1] as $match) {
                             echo ' <label><input type="checkbox" name="SOUR_', $match, '"', $level2_checked, ' value="1">', GedcomTag::getLabel($match), '</label>';
                         }
                     }
                 }
             }
             break;
         case 'REPO':
             echo FunctionsPrint::printFindRepositoryLink($element_id), ' ', self::printAddNewRepositoryLink($element_id);
             break;
         case 'NOTE':
             // Shared Notes Icons ========================================
             if ($islink) {
                 // Print regular Shared Note icons ---------------------------
                 echo ' ', FunctionsPrint::printFindNoteLink($element_id, $element_id . '_description'), ' ', self::printAddNewNoteLink($element_id);
                 if ($value) {
                     echo ' ', self::printEditNoteLink($value);
                 }
             }
             break;
         case 'OBJE':
             echo FunctionsPrint::printFindMediaLink($element_id, '1media');
             if (!$value) {
                 echo ' ', self::printAddNewMediaLink($element_id);
                 $value = 'new';
             }
             break;
     }
     echo '<div id="' . $element_id . '_description">';
     // current value
     if ($fact === 'DATE') {
         $date = new Date($value);
         echo $date->display();
     }
     if (($fact === 'ASSO' || $fact === '_ASSO') && $value === '') {
         if ($level === 1) {
             echo '<p class="small text-muted">' . I18N::translate('An associate is another individual who was involved with this individual, such as a friend or an employer.') . '</p>';
         } else {
             echo '<p class="small text-muted">' . I18N::translate('An associate is another individual who was involved with this fact or event, such as a witness or a priest.') . '</p>';
         }
     }
     if ($value && $value !== 'new' && $islink) {
         switch ($fact) {
             case 'ALIA':
             case 'ASSO':
             case '_ASSO':
                 $tmp = Individual::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'SOUR':
                 $tmp = Source::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'NOTE':
                 $tmp = Note::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'OBJE':
                 $tmp = Media::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'REPO':
                 $tmp = Repository::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
         }
     }
     // pastable values
     if ($fact === 'FORM' && $upperlevel === 'OBJE') {
         FunctionsPrint::printAutoPasteLink($element_id, Config::fileFormats());
     }
     echo '</div>', $extra, '</td></tr>';
     return $element_id;
 }
コード例 #7
0
 /**
  * print cousins list
  *
  * @param string $famid family ID
  * @param int $show_full large or small box
  */
 public static function printCousins($famid, $show_full = 1)
 {
     global $WT_TREE;
     if ($show_full) {
         $bheight = Theme::theme()->parameter('chart-box-y');
     } else {
         $bheight = Theme::theme()->parameter('compact-chart-box-y');
     }
     $family = Family::getInstance($famid, $WT_TREE);
     $fchildren = $family->getChildren();
     $kids = count($fchildren);
     echo '<td valign="middle" height="100%">';
     if ($kids) {
         echo '<table cellspacing="0" cellpadding="0" border="0" ><tr valign="middle">';
         if ($kids > 1) {
             echo '<td rowspan="', $kids, '" valign="middle" align="right"><img width="3px" height="', ($bheight + 9) * ($kids - 1), 'px" src="', Theme::theme()->parameter('image-vline'), '" alt=""></td>';
         }
         $ctkids = count($fchildren);
         $i = 1;
         foreach ($fchildren as $fchil) {
             if ($i == 1) {
                 echo '<td><img width="10px" height="3px" align="top"';
             } else {
                 echo '<td><img width="10px" height="3px"';
             }
             if (I18N::direction() === 'ltr') {
                 echo ' style="padding-right: 2px;"';
             } else {
                 echo ' style="padding-left: 2px;"';
             }
             echo ' src="', Theme::theme()->parameter('image-hline'), '" alt=""></td><td>';
             FunctionsPrint::printPedigreePerson($fchil, $show_full);
             echo '</td></tr>';
             if ($i < $ctkids) {
                 echo '<tr>';
                 $i++;
             }
         }
         echo '</table>';
     } else {
         // If there is known that there are no children (as opposed to no known children)
         if (preg_match('/\\n1 NCHI (\\d+)/', $family->getGedcom(), $match) && $match[1] == 0) {
             echo ' <i class="icon-childless" title="', I18N::translate('This family remained childless'), '"></i>';
         }
     }
     echo '</td>';
 }
コード例 #8
0
ファイル: family.php プロジェクト: AlexSnet/webtrees
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
namespace Fisharebest\Webtrees;

/**
 * Defined in session.php
 *
 * @global Tree $WT_TREE
 */
global $WT_TREE;
use Fisharebest\Webtrees\Controller\FamilyController;
use Fisharebest\Webtrees\Functions\FunctionsCharts;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
define('WT_SCRIPT_NAME', 'family.php');
require './includes/session.php';
$record = Family::getInstance(Filter::get('famid', WT_REGEX_XREF), $WT_TREE);
$controller = new FamilyController($record);
if ($controller->record && $controller->record->canShow()) {
    $controller->pageHeader();
    if ($controller->record->isPendingDeletion()) {
        if (Auth::isModerator($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been deleted.  You should review the deletion and then %1$s or %2$s it.', '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        } elseif (Auth::isEditor($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been deleted.  The deletion will need to be reviewed by a moderator.'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        }
    } elseif ($controller->record->isPendingAddtion()) {
        if (Auth::isModerator($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been edited.  You should review the changes and then %1$s or %2$s them.', '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        } elseif (Auth::isEditor($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been edited.  The changes need to be reviewed by a moderator.'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        }
コード例 #9
0
ファイル: edit_interface.php プロジェクト: jflash/webtrees
/**
 * 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>';
}
コード例 #10
0
    /**
     * Render the Ajax response for the sortable table of Sosa family
     * @param AjaxController $controller
     */
    protected function renderFamSosaListIndi(AjaxController $controller)
    {
        global $WT_TREE;
        $listFamSosa = $this->sosa_provider->getFamilySosaListAtGeneration($this->generation);
        $this->view_bag->set('has_sosa', false);
        if (count($listFamSosa) > 0) {
            $this->view_bag->set('has_sosa', true);
            $table_id = 'table-sosa-fam-' . Uuid::uuid4();
            $this->view_bag->set('table_id', $table_id);
            $controller->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)->addInlineJavascript('
                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_id . '").dataTable( {
					dom: \'<"H"<"filtersH_' . $table_id . '"><"dt-clear">pf<"dt-clear">irl>t<"F"pl<"dt-clear"><"filtersF_' . $table_id . '">>\',
                    ' . I18N::datatablesI18N(array(16, 32, 64, 128, -1)) . ',
					jQueryUI: true,
					autoWidth: false,
					processing: true,
					retrieve: true,
					columns: [
						/* 0-Sosa */  	   { dataSort: 1, class: "center"},
		                /* 1-SOSA */ 	   { type: "num", visible: false },
						/* 2-Husb Givn */  { dataSort: 4},
						/* 3-Husb Surn */  { dataSort: 5},
						/* 4-GIVN,SURN */  { type: "unicode", visible: false},
						/* 5-SURN,GIVN */  { type: "unicode", visible: false},
						/* 6-Husb Age  */  { dataSort: 7, class: "center"},
						/* 7-AGE       */  { type: "num", visible: false},
						/* 8-Wife Givn */  { dataSort: 10},
						/* 9-Wife Surn */  { dataSort: 11},
						/* 10-GIVN,SURN */ { type: "unicode", visible: false},
						/* 11-SURN,GIVN */ { type: "unicode", visible: false},
						/* 12-Wife Age  */ { dataSort: 13, class: "center"},
						/* 13-AGE       */ { type: "num", visible: false},
						/* 14-Marr Date */ { dataSort: 15, class: "center"},
						/* 15-MARR:DATE */ { visible: false},
						/* 16-Marr Plac */ { type: "unicode", class: "center"},
						/* 17-Marr Sour */ { dataSort : 18, class: "center", visible: ' . (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME) ? 'true' : 'false') . ' },
						/* 18-Sort Sour */ { visible: false},
						/* 19-Children  */ { dataSort: 20, class: "center"},
						/* 20-NCHI      */ { type: "num", visible: false},
						/* 21-MARR      */ { visible: false},
						/* 22-DEAT      */ { visible: false},
						/* 23-TREE      */ { visible: false}
					],
					sorting: [[0, "asc"]],
					displayLength: 16,
					pagingType: "full_numbers"
			   });
					
				jQuery("#' . $table_id . '")
				/* Hide/show parents */
				.on("click", ".btn-toggle-parents", function() {
					jQuery(this).toggleClass("ui-state-active");
					jQuery(".parents", jQuery(this).closest("table").DataTable().rows().nodes()).slideToggle();
				})
				/* Hide/show statistics */
				.on("click",  ".btn-toggle-statistics", function() {
					jQuery(this).toggleClass("ui-state-active");
					jQuery("#fam_list_table-charts_' . $table_id . '").slideToggle();
				})
				/* Filter buttons in table header */
				.on("click", "button[data-filter-column]", function() {
					var btn = $(this);
					// De-activate the other buttons in this button group
					btn.siblings().removeClass("ui-state-active");
					// Apply (or clear) this filter
					var col = jQuery("#' . $table_id . '").DataTable().column(btn.data("filter-column"));
					if (btn.hasClass("ui-state-active")) {
						btn.removeClass("ui-state-active");
						col.search("").draw();
					} else {
						btn.addClass("ui-state-active");
						col.search(btn.data("filter-value")).draw();
					}
				});					
				
				jQuery("#sosa-fam-list").css("visibility", "visible");
				
				jQuery("#btn-toggle-statistics-' . $table_id . '").click();
           ');
            $stats = new Stats($WT_TREE);
            $max_age = max($stats->oldestMarriageMaleAge(), $stats->oldestMarriageFemaleAge()) + 1;
            //-- init chart data
            $marr_by_age = array();
            for ($age = 0; $age <= $max_age; $age++) {
                $marr_by_age[$age] = '';
            }
            $birt_by_decade = array();
            $marr_by_decade = array();
            for ($year = 1550; $year < 2030; $year += 10) {
                $birt_by_decade[$year] = '';
                $marr_by_decade[$year] = '';
            }
            foreach ($listFamSosa as $sosa => $fid) {
                $sfamily = Family::getInstance($fid, $WT_TREE);
                if (!$sfamily || !$sfamily->canShow()) {
                    unset($sfamily[$sosa]);
                    continue;
                }
                $mdate = $sfamily->getMarriageDate();
                if (($husb = $sfamily->getHusband()) && ($hdate = $husb->getBirthDate()) && $hdate->isOK() && $mdate->isOK()) {
                    if (FunctionsPrint::isDateWithinChartsRange($hdate)) {
                        $birt_by_decade[(int) ($hdate->gregorianYear() / 10) * 10] .= $husb->getSex();
                    }
                    $hage = Date::getAge($hdate, $mdate, 0);
                    if ($hage >= 0 && $hage <= $max_age) {
                        $marr_by_age[$hage] .= $husb->getSex();
                    }
                }
                if (($wife = $sfamily->getWife()) && ($wdate = $wife->getBirthDate()) && $wdate->isOK() && $mdate->isOK()) {
                    if (FunctionsPrint::isDateWithinChartsRange($wdate)) {
                        $birt_by_decade[(int) ($wdate->gregorianYear() / 10) * 10] .= $wife->getSex();
                    }
                    $wage = Date::getAge($wdate, $mdate, 0);
                    if ($wage >= 0 && $wage <= $max_age) {
                        $marr_by_age[$wage] .= $wife->getSex();
                    }
                }
                if ($mdate->isOK() && FunctionsPrint::isDateWithinChartsRange($mdate) && $husb && $wife) {
                    $marr_by_decade[(int) ($mdate->gregorianYear() / 10) * 10] .= $husb->getSex() . $wife->getSex();
                }
                $listFamSosa[$sosa] = $sfamily;
            }
            $this->view_bag->set('sosa_list', $listFamSosa);
            $this->view_bag->set('chart_births', FunctionsPrintLists::chartByDecade($birt_by_decade, I18N::translate('Decade of birth')));
            $this->view_bag->set('chart_marriages', FunctionsPrintLists::chartByDecade($marr_by_decade, I18N::translate('Decade of marriage')));
            $this->view_bag->set('chart_ages', FunctionsPrintLists::chartByAge($marr_by_age, I18N::translate('Age in year of marriage')));
        }
        ViewFactory::make('SosaListFam', $this, $controller, $this->view_bag)->render();
    }
コード例 #11
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     parent::__construct();
     $this->setPageTitle(I18N::translate('Lifespans'));
     $this->facts = explode('|', WT_EVENTS_BIRT . '|' . WT_EVENTS_DEAT . '|' . WT_EVENTS_MARR . '|' . WT_EVENTS_DIV);
     $tmp = explode('\\', get_class(I18N::defaultCalendar()));
     $cal = strtolower(array_pop($tmp));
     $this->defaultCalendar = str_replace('calendar', '', $cal);
     $filterPids = false;
     // Request parameters
     $clear = Filter::getBool('clear');
     $newpid = Filter::get('newpid', WT_REGEX_XREF);
     $addfam = Filter::getBool('addFamily');
     $this->place = Filter::get('place');
     $this->beginYear = Filter::getInteger('beginYear', 0, PHP_INT_MAX, null);
     $this->endYear = Filter::getInteger('endYear', 0, PHP_INT_MAX, null);
     $this->calendar = Filter::get('calendar', null, $this->defaultCalendar);
     $this->strictDate = Filter::getBool('strictDate');
     // Set up base color parameters
     $this->colors['M'] = new ColorGenerator(240, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE * -1);
     $this->colors['F'] = new ColorGenerator(00, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE);
     // Build a list of people based on the input parameters
     if ($clear) {
         // Empty list & reset form
         $xrefs = array();
         $this->place = null;
         $this->beginYear = null;
         $this->endYear = null;
         $this->calendar = $this->defaultCalendar;
     } elseif ($this->place) {
         // Get all individual & family records found for a place
         $this->place_obj = new Place($this->place, $WT_TREE);
         $xrefs = Database::prepare("SELECT DISTINCT `i_id` FROM `##placelinks`" . " JOIN `##individuals` ON `pl_gid`=`i_id` AND `pl_file`=`i_file`" . " WHERE `i_file`=:tree_id" . " AND `pl_p_id`=:place_id" . " UNION" . " SELECT DISTINCT `f_id` FROM `##placelinks`" . " JOIN `##families` ON `pl_gid`=`f_id` AND `pl_file`=`f_file`" . " WHERE `f_file`=:tree_id" . " AND `pl_p_id`=:place_id")->execute(array('tree_id' => $WT_TREE->getTreeId(), 'place_id' => $this->place_obj->getPlaceId()))->fetchOneColumn();
     } else {
         // Modify an existing list of records
         $xrefs = Session::get(self::SESSION_DATA, array());
         if ($newpid) {
             $xrefs = array_merge($xrefs, $this->addFamily(Individual::getInstance($newpid, $WT_TREE), $addfam));
             $xrefs = array_unique($xrefs);
         } elseif (!$xrefs) {
             $xrefs = $this->addFamily($this->getSignificantIndividual(), false);
         }
     }
     $tmp = $this->getCalendarDate(unixtojd());
     $this->currentYear = $tmp->today()->y;
     $tmp = strtoupper(strtr($this->calendar, array('jewish' => 'hebrew', 'french' => 'french r')));
     $this->calendarEscape = sprintf('@#D%s@', $tmp);
     if ($xrefs) {
         // ensure date ranges are valid in preparation for filtering list
         if ($this->beginYear || $this->endYear) {
             $filterPids = true;
             if (!$this->beginYear) {
                 $tmp = new Date($this->calendarEscape . ' 1');
                 $this->beginYear = $tmp->minimumDate()->y;
             }
             if (!$this->endYear) {
                 $this->endYear = $this->currentYear;
             }
             $this->startDate = new Date($this->calendarEscape . $this->beginYear);
             $this->endDate = new Date($this->calendarEscape . $this->endYear);
         }
         // Test each xref to see if the search criteria are met
         foreach ($xrefs as $key => $xref) {
             $valid = false;
             $person = Individual::getInstance($xref, $WT_TREE);
             if ($person) {
                 if ($person->canShow()) {
                     foreach ($person->getFacts() as $fact) {
                         if ($this->checkFact($fact)) {
                             $this->people[] = $person;
                             $valid = true;
                             break;
                         }
                     }
                 }
             } else {
                 $family = Family::getInstance($xref, $WT_TREE);
                 if ($family && $family->canShow() && $this->checkFact($family->getMarriage())) {
                     $valid = true;
                     $this->people[] = $family->getHusband();
                     $this->people[] = $family->getWife();
                 }
             }
             if (!$valid) {
                 unset($xrefs[$key]);
                 // no point in storing a xref if we can't use it
             }
         }
         Session::put(self::SESSION_DATA, $xrefs);
     } else {
         Session::forget(self::SESSION_DATA);
     }
     $this->people = array_filter(array_unique($this->people));
     $count = count($this->people);
     if ($count) {
         // Build the subtitle
         if ($this->place && $filterPids) {
             $this->subtitle = I18N::plural('%s individual with events in %s between %s and %s', '%s individuals with events in %s between %s and %s', $count, I18N::number($count), $this->place, $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y'));
         } elseif ($this->place) {
             $this->subtitle = I18N::plural('%s individual with events in %s', '%s individuals with events in %s', $count, I18N::number($count), $this->place);
         } elseif ($filterPids) {
             $this->subtitle = I18N::plural('%s individual with events between %s and %s', '%s individuals with events between %s and %s', $count, I18N::number($count), $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y'));
         } else {
             $this->subtitle = I18N::plural('%s individual', '%s individuals', $count, I18N::number($count));
         }
         // Sort the array in order of birth year
         usort($this->people, function (Individual $a, Individual $b) {
             return Date::compare($a->getEstimatedBirthDate(), $b->getEstimatedBirthDate());
         });
         //Find the mimimum birth year and maximum death year from the individuals in the array.
         $bdate = $this->getCalendarDate($this->people[0]->getEstimatedBirthDate()->minimumJulianDay());
         $minyear = $bdate->y;
         $that = $this;
         // PHP5.3 cannot access $this inside a closure
         $maxyear = array_reduce($this->people, function ($carry, Individual $item) use($that) {
             $date = $that->getCalendarDate($item->getEstimatedDeathDate()->maximumJulianDay());
             return max($carry, $date->y);
         }, 0);
     } elseif ($filterPids) {
         $minyear = $this->endYear;
         $maxyear = $this->endYear;
     } else {
         $minyear = $this->currentYear;
         $maxyear = $this->currentYear;
     }
     $maxyear = min($maxyear, $this->currentYear);
     // Limit maximum year to current year as we can't forecast the future
     $minyear = min($minyear, $maxyear - $WT_TREE->getPreference('MAX_ALIVE_AGE'));
     // Set default minimum chart length
     $this->timelineMinYear = (int) floor($minyear / 10) * 10;
     // round down to start of the decade
     $this->timelineMaxYear = (int) ceil($maxyear / 10) * 10;
     // round up to start of next decade
 }
コード例 #12
0
ファイル: Fact.php プロジェクト: tunandras/webtrees
 /**
  * Get the record to which this fact links
  *
  * @return Individual|Family|Source|Repository|Media|Note|null
  */
 public function getTarget()
 {
     $xref = trim($this->getValue(), '@');
     switch ($this->tag) {
         case 'FAMC':
         case 'FAMS':
             return Family::getInstance($xref, $this->getParent()->getTree());
         case 'HUSB':
         case 'WIFE':
         case 'CHIL':
             return Individual::getInstance($xref, $this->getParent()->getTree());
         case 'SOUR':
             return Source::getInstance($xref, $this->getParent()->getTree());
         case 'OBJE':
             return Media::getInstance($xref, $this->getParent()->getTree());
         case 'REPO':
             return Repository::getInstance($xref, $this->getParent()->getTree());
         case 'NOTE':
             return Note::getInstance($xref, $this->getParent()->getTree());
         default:
             return GedcomRecord::getInstance($xref, $this->getParent()->getTree());
     }
 }
コード例 #13
0
ファイル: Individual.php プロジェクト: bmhm/webtrees
 /**
  * Create a label for a step family
  *
  * @param Family $step_family
  *
  * @return string
  */
 public function getStepFamilyLabel(Family $step_family)
 {
     foreach ($this->getChildFamilies() as $family) {
         if ($family !== $step_family) {
             // Must be a step-family
             foreach ($family->getSpouses() as $parent) {
                 foreach ($step_family->getSpouses() as $step_parent) {
                     if ($parent === $step_parent) {
                         // One common parent - must be a step family
                         if ($parent->getSex() == 'M') {
                             // Father’s family with someone else
                             if ($step_family->getSpouse($step_parent)) {
                                 return I18N::translate('Father’s family with %s', $step_family->getSpouse($step_parent)->getFullName());
                             } else {
                                 return I18N::translate('Father’s family with an unknown individual');
                             }
                         } else {
                             // Mother’s family with someone else
                             if ($step_family->getSpouse($step_parent)) {
                                 return I18N::translate('Mother’s family with %s', $step_family->getSpouse($step_parent)->getFullName());
                             } else {
                                 return I18N::translate('Mother’s family with an unknown individual');
                             }
                         }
                     }
                 }
             }
         }
     }
     // Perahps same parents - but a different family record?
     return I18N::translate('Family with parents');
 }
コード例 #14
0
ファイル: reportengine.php プロジェクト: jflash/webtrees
//-- setup the arrays
$newvars = array();
foreach ($vars as $name => $var) {
    $newvars[$name]['id'] = $var;
    if (!empty($type[$name])) {
        switch ($type[$name]) {
            case 'INDI':
                $record = Individual::getInstance($var, $WT_TREE);
                if ($record && $record->canShowName()) {
                    $newvars[$name]['gedcom'] = $record->privatizeGedcom(Auth::accessLevel($WT_TREE));
                } else {
                    $action = 'setup';
                }
                break;
            case 'FAM':
                $record = Family::getInstance($var, $WT_TREE);
                if ($record && $record->canShowName()) {
                    $newvars[$name]['gedcom'] = $record->privatizeGedcom(Auth::accessLevel($WT_TREE));
                } else {
                    $action = 'setup';
                }
                break;
            case 'SOUR':
                $record = Source::getInstance($var, $WT_TREE);
                if ($record && $record->canShowName()) {
                    $newvars[$name]['gedcom'] = $record->privatizeGedcom(Auth::accessLevel($WT_TREE));
                } else {
                    $action = 'setup';
                }
                break;
            default:
コード例 #15
0
ファイル: inverselink.php プロジェクト: pal-saugstad/webtrees
     if ($linktoid == "") {
         echo '<input class="pedigree_form" type="text" name="linktoid" id="linktopid" size="3" value="', $linktoid, '"> ';
         echo FunctionsPrint::printFindIndividualLink('linktopid');
     } else {
         $record = Individual::getInstance($linktoid, $WT_TREE);
         echo $record->formatList('span', false, $record->getFullName());
     }
 }
 if ($linkto == "family") {
     echo I18N::translate('Family'), '</td>';
     echo '<td class="optionbox wrap">';
     if ($linktoid == "") {
         echo '<input class="pedigree_form" type="text" name="linktoid" id="linktofamid" size="3" value="', $linktoid, '"> ';
         echo FunctionsPrint::printFindFamilyLink('linktofamid');
     } else {
         $record = Family::getInstance($linktoid, $WT_TREE);
         echo $record->formatList('span', false, $record->getFullName());
     }
 }
 if ($linkto == "source") {
     echo I18N::translate('Source'), "</td>";
     echo '<td  class="optionbox wrap">';
     if ($linktoid == "") {
         echo '<input class="pedigree_form" type="text" name="linktoid" id="linktosid" size="3" value="', $linktoid, '"> ';
         echo FunctionsPrint::printFindSourceLink('linktosid');
     } else {
         $record = Source::getInstance($linktoid, $WT_TREE);
         echo $record->formatList('span', false, $record->getFullName());
     }
 }
 if ($linkto == "repository") {
コード例 #16
0
 /**
  * XML <List>
  *
  * @param array $attrs an array of key value pairs for the attributes
  */
 private function listStartHandler($attrs)
 {
     global $WT_TREE;
     $this->process_repeats++;
     if ($this->process_repeats > 1) {
         return;
     }
     $match = array();
     if (isset($attrs['sortby'])) {
         $sortby = $attrs['sortby'];
         if (preg_match("/\\\$(\\w+)/", $sortby, $match)) {
             $sortby = $this->vars[$match[1]]['id'];
             $sortby = trim($sortby);
         }
     } else {
         $sortby = "NAME";
     }
     if (isset($attrs['list'])) {
         $listname = $attrs['list'];
     } else {
         $listname = "individual";
     }
     // Some filters/sorts can be applied using SQL, while others require PHP
     switch ($listname) {
         case "pending":
             $rows = Database::prepare("SELECT xref, CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom" . " FROM `##change`" . " WHERE (xref, change_id) IN (" . "  SELECT xref, MAX(change_id)" . "  FROM `##change`" . "  WHERE status = 'pending' AND gedcom_id = :tree_id" . "  GROUP BY xref" . " )")->execute(array('tree_id' => $WT_TREE->getTreeId()))->fetchAll();
             $this->list = array();
             foreach ($rows as $row) {
                 $this->list[] = GedcomRecord::getInstance($row->xref, $WT_TREE, $row->gedcom);
             }
             break;
         case 'individual':
             $sql_select = "SELECT i_id AS xref, i_gedcom AS gedcom FROM `##individuals` ";
             $sql_join = "";
             $sql_where = " WHERE i_file = :tree_id";
             $sql_order_by = "";
             $sql_params = array('tree_id' => $WT_TREE->getTreeId());
             foreach ($attrs as $attr => $value) {
                 if (strpos($attr, 'filter') === 0 && $value) {
                     $value = $this->substituteVars($value, false);
                     // Convert the various filters into SQL
                     if (preg_match('/^(\\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) {
                         $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=i_file AND {$attr}.d_gid=i_id)";
                         $sql_where .= " AND {$attr}.d_fact = :{$attr}fact";
                         $sql_params[$attr . 'fact'] = $match[1];
                         $date = new Date($match[3]);
                         if ($match[2] == "LTE") {
                             $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date";
                             $sql_params[$attr . 'date'] = $date->maximumJulianDay();
                         } else {
                             $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date";
                             $sql_params[$attr . 'date'] = $date->minimumJulianDay();
                         }
                         if ($sortby == $match[1]) {
                             $sortby = "";
                             $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.d_julianday1";
                         }
                         unset($attrs[$attr]);
                         // This filter has been fully processed
                     } elseif (preg_match('/^NAME CONTAINS (.*)$/', $value, $match)) {
                         // Do nothing, unless you have to
                         if ($match[1] != '' || $sortby == 'NAME') {
                             $sql_join .= " JOIN `##name` AS {$attr} ON (n_file=i_file AND n_id=i_id)";
                             // Search the DB only if there is any name supplied
                             if ($match[1] != "") {
                                 $names = explode(" ", $match[1]);
                                 foreach ($names as $n => $name) {
                                     $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')";
                                     $sql_params[$attr . 'name' . $n] = $name;
                                 }
                             }
                             // Let the DB do the name sorting even when no name was entered
                             if ($sortby == "NAME") {
                                 $sortby = "";
                                 $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.n_sort";
                             }
                         }
                         unset($attrs[$attr]);
                         // This filter has been fully processed
                     } elseif (preg_match('/^REGEXP \\/(.+)\\//', $value, $match)) {
                         $sql_where .= " AND i_gedcom REGEXP :{$attr}gedcom";
                         // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT"
                         $sql_params[$attr . 'gedcom'] = str_replace('\\n', "\n", $match[1]);
                         unset($attrs[$attr]);
                         // This filter has been fully processed
                     } elseif (preg_match('/^(?:\\w+):PLAC CONTAINS (.+)$/', $value, $match)) {
                         $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file = i_file)";
                         $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file = {$attr}b.pl_file AND {$attr}b.pl_p_id = {$attr}a.p_id AND {$attr}b.pl_gid = i_id)";
                         $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')";
                         $sql_params[$attr . 'place'] = $match[1];
                         // Don't unset this filter. This is just initial filtering
                     } elseif (preg_match('/^(\\w*):*(\\w*) CONTAINS (.+)$/', $value, $match)) {
                         $sql_where .= " AND i_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')";
                         $sql_params[$attr . 'contains1'] = $match[1];
                         $sql_params[$attr . 'contains2'] = $match[2];
                         $sql_params[$attr . 'contains3'] = $match[3];
                         // Don't unset this filter. This is just initial filtering
                     }
                 }
             }
             $this->list = array();
             $rows = Database::prepare($sql_select . $sql_join . $sql_where . $sql_order_by)->execute($sql_params)->fetchAll();
             foreach ($rows as $row) {
                 $this->list[$row->xref] = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
             }
             break;
         case 'family':
             $sql_select = "SELECT f_id AS xref, f_gedcom AS gedcom FROM `##families`";
             $sql_join = "";
             $sql_where = " WHERE f_file = :tree_id";
             $sql_order_by = "";
             $sql_params = array('tree_id' => $WT_TREE->getTreeId());
             foreach ($attrs as $attr => $value) {
                 if (strpos($attr, 'filter') === 0 && $value) {
                     $value = $this->substituteVars($value, false);
                     // Convert the various filters into SQL
                     if (preg_match('/^(\\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) {
                         $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=f_file AND {$attr}.d_gid=f_id)";
                         $sql_where .= " AND {$attr}.d_fact = :{$attr}fact";
                         $sql_params[$attr . 'fact'] = $match[1];
                         $date = new Date($match[3]);
                         if ($match[2] == "LTE") {
                             $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date";
                             $sql_params[$attr . 'date'] = $date->maximumJulianDay();
                         } else {
                             $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date";
                             $sql_params[$attr . 'date'] = $date->minimumJulianDay();
                         }
                         if ($sortby == $match[1]) {
                             $sortby = "";
                             $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.d_julianday1";
                         }
                         unset($attrs[$attr]);
                         // This filter has been fully processed
                     } elseif (preg_match('/^REGEXP \\/(.+)\\//', $value, $match)) {
                         $sql_where .= " AND f_gedcom REGEXP :{$attr}gedcom";
                         // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT"
                         $sql_params[$attr . 'gedcom'] = str_replace('\\n', "\n", $match[1]);
                         unset($attrs[$attr]);
                         // This filter has been fully processed
                     } elseif (preg_match('/^NAME CONTAINS (.+)$/', $value, $match)) {
                         // Do nothing, unless you have to
                         if ($match[1] != '' || $sortby == 'NAME') {
                             $sql_join .= " JOIN `##name` AS {$attr} ON n_file = f_file AND n_id IN (f_husb, f_wife)";
                             // Search the DB only if there is any name supplied
                             if ($match[1] != "") {
                                 $names = explode(" ", $match[1]);
                                 foreach ($names as $n => $name) {
                                     $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')";
                                     $sql_params[$attr . 'name' . $n] = $name;
                                 }
                             }
                             // Let the DB do the name sorting even when no name was entered
                             if ($sortby == "NAME") {
                                 $sortby = "";
                                 $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.n_sort";
                             }
                         }
                         unset($attrs[$attr]);
                         // This filter has been fully processed
                     } elseif (preg_match('/^(?:\\w+):PLAC CONTAINS (.+)$/', $value, $match)) {
                         $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file=f_file)";
                         $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file={$attr}b.pl_file AND {$attr}b.pl_p_id={$attr}a.p_id AND {$attr}b.pl_gid=f_id)";
                         $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')";
                         $sql_params[$attr . 'place'] = $match[1];
                         // Don't unset this filter. This is just initial filtering
                     } elseif (preg_match('/^(\\w*):*(\\w*) CONTAINS (.+)$/', $value, $match)) {
                         $sql_where .= " AND f_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')";
                         $sql_params[$attr . 'contains1'] = $match[1];
                         $sql_params[$attr . 'contains2'] = $match[2];
                         $sql_params[$attr . 'contains3'] = $match[3];
                         // Don't unset this filter. This is just initial filtering
                     }
                 }
             }
             $this->list = array();
             $rows = Database::prepare($sql_select . $sql_join . $sql_where . $sql_order_by)->execute($sql_params)->fetchAll();
             foreach ($rows as $row) {
                 $this->list[$row->xref] = Family::getInstance($row->xref, $WT_TREE, $row->gedcom);
             }
             break;
         default:
             throw new \DomainException('Invalid list name: ' . $listname);
     }
     $filters = array();
     $filters2 = array();
     if (isset($attrs['filter1']) && count($this->list) > 0) {
         foreach ($attrs as $key => $value) {
             if (preg_match("/filter(\\d)/", $key)) {
                 $condition = $value;
                 if (preg_match("/@(\\w+)/", $condition, $match)) {
                     $id = $match[1];
                     $value = "''";
                     if ($id == "ID") {
                         if (preg_match("/0 @(.+)@/", $this->gedrec, $match)) {
                             $value = "'" . $match[1] . "'";
                         }
                     } elseif ($id == "fact") {
                         $value = "'" . $this->fact . "'";
                     } elseif ($id == "desc") {
                         $value = "'" . $this->desc . "'";
                     } else {
                         if (preg_match("/\\d {$id} (.+)/", $this->gedrec, $match)) {
                             $value = "'" . str_replace("@", "", trim($match[1])) . "'";
                         }
                     }
                     $condition = preg_replace("/@{$id}/", $value, $condition);
                 }
                 //-- handle regular expressions
                 if (preg_match("/([A-Z:]+)\\s*([^\\s]+)\\s*(.+)/", $condition, $match)) {
                     $tag = trim($match[1]);
                     $expr = trim($match[2]);
                     $val = trim($match[3]);
                     if (preg_match("/\\\$(\\w+)/", $val, $match)) {
                         $val = $this->vars[$match[1]]['id'];
                         $val = trim($val);
                     }
                     if ($val) {
                         $searchstr = "";
                         $tags = explode(":", $tag);
                         //-- only limit to a level number if we are specifically looking at a level
                         if (count($tags) > 1) {
                             $level = 1;
                             foreach ($tags as $t) {
                                 if (!empty($searchstr)) {
                                     $searchstr .= "[^\n]*(\n[2-9][^\n]*)*\n";
                                 }
                                 //-- search for both EMAIL and _EMAIL... silly double gedcom standard
                                 if ($t == "EMAIL" || $t == "_EMAIL") {
                                     $t = "_?EMAIL";
                                 }
                                 $searchstr .= $level . " " . $t;
                                 $level++;
                             }
                         } else {
                             if ($tag == "EMAIL" || $tag == "_EMAIL") {
                                 $tag = "_?EMAIL";
                             }
                             $t = $tag;
                             $searchstr = "1 " . $tag;
                         }
                         switch ($expr) {
                             case "CONTAINS":
                                 if ($t == "PLAC") {
                                     $searchstr .= "[^\n]*[, ]*" . $val;
                                 } else {
                                     $searchstr .= "[^\n]*" . $val;
                                 }
                                 $filters[] = $searchstr;
                                 break;
                             default:
                                 $filters2[] = array("tag" => $tag, "expr" => $expr, "val" => $val);
                                 break;
                         }
                     }
                 }
             }
         }
     }
     //-- apply other filters to the list that could not be added to the search string
     if ($filters) {
         foreach ($this->list as $key => $record) {
             foreach ($filters as $filter) {
                 if (!preg_match("/" . $filter . "/i", $record->privatizeGedcom(Auth::accessLevel($WT_TREE)))) {
                     unset($this->list[$key]);
                     break;
                 }
             }
         }
     }
     if ($filters2) {
         $mylist = array();
         foreach ($this->list as $indi) {
             $key = $indi->getXref();
             $grec = $indi->privatizeGedcom(Auth::accessLevel($WT_TREE));
             $keep = true;
             foreach ($filters2 as $filter) {
                 if ($keep) {
                     $tag = $filter['tag'];
                     $expr = $filter['expr'];
                     $val = $filter['val'];
                     if ($val == "''") {
                         $val = "";
                     }
                     $tags = explode(":", $tag);
                     $t = end($tags);
                     $v = $this->getGedcomValue($tag, 1, $grec);
                     //-- check for EMAIL and _EMAIL (silly double gedcom standard :P)
                     if ($t == "EMAIL" && empty($v)) {
                         $tag = str_replace("EMAIL", "_EMAIL", $tag);
                         $tags = explode(":", $tag);
                         $t = end($tags);
                         $v = Functions::getSubRecord(1, $tag, $grec);
                     }
                     switch ($expr) {
                         case "GTE":
                             if ($t == "DATE") {
                                 $date1 = new Date($v);
                                 $date2 = new Date($val);
                                 $keep = Date::compare($date1, $date2) >= 0;
                             } elseif ($val >= $v) {
                                 $keep = true;
                             }
                             break;
                         case "LTE":
                             if ($t == "DATE") {
                                 $date1 = new Date($v);
                                 $date2 = new Date($val);
                                 $keep = Date::compare($date1, $date2) <= 0;
                             } elseif ($val >= $v) {
                                 $keep = true;
                             }
                             break;
                         default:
                             if ($v == $val) {
                                 $keep = true;
                             } else {
                                 $keep = false;
                             }
                             break;
                     }
                 }
             }
             if ($keep) {
                 $mylist[$key] = $indi;
             }
         }
         $this->list = $mylist;
     }
     switch ($sortby) {
         case 'NAME':
             uasort($this->list, '\\Fisharebest\\Webtrees\\GedcomRecord::compare');
             break;
         case 'CHAN':
             uasort($this->list, function (GedcomRecord $x, GedcomRecord $y) {
                 return $y->lastChangeTimestamp(true) - $x->lastChangeTimestamp(true);
             });
             break;
         case 'BIRT:DATE':
             uasort($this->list, '\\Fisharebest\\Webtrees\\Individual::compareBirthDate');
             break;
         case 'DEAT:DATE':
             uasort($this->list, '\\Fisharebest\\Webtrees\\Individual::compareDeathDate');
             break;
         case 'MARR:DATE':
             uasort($this->list, '\\Fisharebest\\Webtrees\\Family::compareMarrDate');
             break;
         default:
             // unsorted or already sorted by SQL
             break;
     }
     array_push($this->repeats_stack, array($this->repeats, $this->repeat_bytes));
     $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1;
 }
コード例 #17
0
    /**
     * Format a family.
     *
     * @param Family $family
     * @param string $title
     */
    private function drawFamily(Family $family, $title)
    {
        global $controller;
        ?>
		<tr>
			<td class="center" colspan="2">
				<a class="famnav_title" href="<?php 
        echo $family->getHtmlUrl();
        ?>
">
					<?php 
        echo $title;
        ?>
				</a>
			</td>
		</tr>
		<?php 
        foreach ($family->getSpouses() as $spouse) {
            $menu = new Menu(Functions::getCloseRelationshipName($controller->record, $spouse));
            $menu->addClass('', 'submenu flyout');
            $menu->addSubmenu(new Menu($this->getParents($spouse)));
            ?>
			<tr>
				<td class="facts_label">
					<?php 
            echo $menu->getMenu();
            ?>
				</td>
				<td class="center <?php 
            echo $controller->getPersonStyle($spouse);
            ?>
 nam">
					<a class="famnav_link" href="<?php 
            echo $spouse->getHtmlUrl();
            ?>
">
						<?php 
            echo $spouse->getFullName();
            ?>
					</a>
					<div class="font9">
						<?php 
            echo $spouse->getLifeSpan();
            ?>
					</div>
				</td>
			</tr>
		<?php 
        }
        foreach ($family->getChildren() as $child) {
            $menu = new Menu(Functions::getCloseRelationshipName($controller->record, $child));
            $menu->addClass('', 'submenu flyout');
            $menu->addSubmenu(new Menu($this->getFamily($child)));
            ?>
			<tr>
				<td class="facts_label">
					<?php 
            echo $menu->getMenu();
            ?>
				</td>
				<td class="center <?php 
            echo $controller->getPersonStyle($child);
            ?>
 nam">
					<a class="famnav_link" href="<?php 
            echo $child->getHtmlUrl();
            ?>
">
						<?php 
            echo $child->getFullName();
            ?>
					</a>
					<div class="font9">
						<?php 
            echo $child->getLifeSpan();
            ?>
					</div>
				</td>
			</tr>
		<?php 
        }
    }
コード例 #18
0
    /**
     * Print a family group.
     *
     * @param Family $family
     * @param string $type
     * @param string $label
     */
    private function printFamily(Family $family, $type, $label)
    {
        global $controller;
        if ($family->getTree()->getPreference('SHOW_PRIVATE_RELATIONSHIPS')) {
            $access_level = Auth::PRIV_HIDE;
        } else {
            $access_level = Auth::accessLevel($family->getTree());
        }
        ?>
		<table>
			<tr>
				<td>
					<i class="icon-cfamily"></i>
				</td>
				<td>
					<span class="subheaders"> <?php 
        echo $label;
        ?>
</span>
					<a class="noprint" href="<?php 
        echo $family->getHtmlUrl();
        ?>
"> - <?php 
        echo I18N::translate('View this family');
        ?>
</a>
				</td>
			</tr>
		</table>
		<table class="facts_table">
		<?php 
        ///// HUSB /////
        $found = false;
        foreach ($family->getFacts('HUSB', false, $access_level) as $fact) {
            $found |= !$fact->isPendingDeletion();
            $person = $fact->getTarget();
            if ($person instanceof Individual) {
                if ($fact->isPendingAddition()) {
                    $class = 'facts_label new';
                } elseif ($fact->isPendingDeletion()) {
                    $class = 'facts_label old';
                } else {
                    $class = 'facts_label';
                }
                ?>
					<tr>
					<td class="<?php 
                echo $class;
                ?>
">
						<?php 
                echo Functions::getCloseRelationshipName($controller->record, $person);
                ?>
					</td>
					<td class="<?php 
                echo $controller->getPersonStyle($person);
                ?>
">
						<?php 
                echo Theme::theme()->individualBoxLarge($person);
                ?>
					</td>
					</tr>
				<?php 
            }
        }
        if (!$found && $family->canEdit()) {
            ?>
			<tr>
				<td class="facts_label"></td>
				<td class="facts_value"><a href="#" onclick="return add_spouse_to_family('<?php 
            echo $family->getXref();
            ?>
', 'HUSB');"><?php 
            echo I18N::translate('Add a husband to this family');
            ?>
</a></td>
			</tr>
			<?php 
        }
        ///// WIFE /////
        $found = false;
        foreach ($family->getFacts('WIFE', false, $access_level) as $fact) {
            $person = $fact->getTarget();
            if ($person instanceof Individual) {
                $found |= !$fact->isPendingDeletion();
                if ($fact->isPendingAddition()) {
                    $class = 'facts_label new';
                } elseif ($fact->isPendingDeletion()) {
                    $class = 'facts_label old';
                } else {
                    $class = 'facts_label';
                }
                ?>
				<tr>
					<td class="<?php 
                echo $class;
                ?>
">
						<?php 
                echo Functions::getCloseRelationshipName($controller->record, $person);
                ?>
					</td>
					<td class="<?php 
                echo $controller->getPersonStyle($person);
                ?>
">
						<?php 
                echo Theme::theme()->individualBoxLarge($person);
                ?>
					</td>
				</tr>
				<?php 
            }
        }
        if (!$found && $family->canEdit()) {
            ?>
			<tr>
				<td class="facts_label"></td>
				<td class="facts_value"><a href="#" onclick="return add_spouse_to_family('<?php 
            echo $family->getXref();
            ?>
', 'WIFE');"><?php 
            echo I18N::translate('Add a wife to this family');
            ?>
</a></td>
			</tr>
			<?php 
        }
        ///// MARR /////
        $found = false;
        $prev = new Date('');
        foreach ($family->getFacts(WT_EVENTS_MARR . '|' . WT_EVENTS_DIV, true) as $fact) {
            $found |= !$fact->isPendingDeletion();
            if ($fact->isPendingAddition()) {
                $class = ' new';
            } elseif ($fact->isPendingDeletion()) {
                $class = ' old';
            } else {
                $class = '';
            }
            ?>
			<tr>
				<td class="facts_label">
				</td>
				<td class="facts_value<?php 
            echo $class;
            ?>
">
					<?php 
            echo GedcomTag::getLabelValue($fact->getTag(), $fact->getDate()->display() . ' — ' . $fact->getPlace()->getFullName());
            ?>
				</td>
			</tr>
			<?php 
            if (!$prev->isOK() && $fact->getDate()->isOK()) {
                $prev = $fact->getDate();
            }
        }
        if (!$found && $family->canShow() && $family->canEdit()) {
            // Add a new marriage
            ?>
			<tr>
				<td class="facts_label">
				</td>
				<td class="facts_value">
					<a href="#" onclick="return add_new_record('<?php 
            echo $family->getXref();
            ?>
', 'MARR');">
						<?php 
            echo I18N::translate('Add marriage details');
            ?>
					</a>
				</td>
			</tr>
			<?php 
        }
        ///// CHIL /////
        $child_number = 0;
        foreach ($family->getFacts('CHIL', false, $access_level) as $fact) {
            $person = $fact->getTarget();
            if ($person instanceof Individual) {
                if ($fact->isPendingAddition()) {
                    $child_number++;
                    $class = 'facts_label new';
                } elseif ($fact->isPendingDeletion()) {
                    $class = 'facts_label old';
                } else {
                    $child_number++;
                    $class = 'facts_label';
                }
                $next = new Date('');
                foreach ($person->getFacts(WT_EVENTS_BIRT, true) as $bfact) {
                    if ($bfact->getDate()->isOK()) {
                        $next = $bfact->getDate();
                        break;
                    }
                }
                ?>
				<tr>
					<td class="<?php 
                echo $class;
                ?>
">
						<?php 
                echo self::ageDifference($prev, $next, $child_number);
                ?>
						<?php 
                echo Functions::getCloseRelationshipName($controller->record, $person);
                ?>
					</td>
					<td class="<?php 
                echo $controller->getPersonStyle($person);
                ?>
">
						<?php 
                echo Theme::theme()->individualBoxLarge($person);
                ?>
					</td>
				</tr>
				<?php 
                $prev = $next;
            }
        }
        // Re-order children / add a new child
        if ($family->canEdit()) {
            if ($type == 'FAMS') {
                $add_child_text = I18N::translate('Add a son or daughter');
            } else {
                $add_child_text = I18N::translate('Add a brother or sister');
            }
            ?>
			<tr class="noprint">
				<td class="facts_label">
					<?php 
            if (count($family->getChildren()) > 1) {
                ?>
					<a href="#" onclick="reorder_children('<?php 
                echo $family->getXref();
                ?>
');tabswitch(5);"><i class="icon-media-shuffle"></i> <?php 
                echo I18N::translate('Re-order children');
                ?>
</a>
					<?php 
            }
            ?>
				</td>
				<td class="facts_value">
					<a href="#" onclick="return add_child_to_family('<?php 
            echo $family->getXref();
            ?>
');"><?php 
            echo $add_child_text;
            ?>
</a>
					<span style='white-space:nowrap;'>
						<a href="#" class="icon-sex_m_15x15" onclick="return add_child_to_family('<?php 
            echo $family->getXref();
            ?>
','M');"></a>
						<a href="#" class="icon-sex_f_15x15" onclick="return add_child_to_family('<?php 
            echo $family->getXref();
            ?>
','F');"></a>
					</span>
				</td>
			</tr>
			<?php 
        }
        echo '</table>';
        return;
    }
コード例 #19
0
    /**
     * Create a family on the census navigator.
     *
     * @param CensusInterface $census
     * @param Family          $family
     * @param Individual      $head
     *
     * @return string
     */
    public static function censusNavigatorFamily(CensusInterface $census, Family $family, Individual $head)
    {
        $headImg2 = '<i class="icon-button_head" title="' . I18N::translate('Head of household') . '"></i>';
        foreach ($family->getSpouses() as $spouse) {
            $menu = new Menu(Functions::getCloseRelationshipName($head, $spouse));
            foreach ($spouse->getChildFamilies() as $grandparents) {
                foreach ($grandparents->getSpouses() as $grandparent) {
                    $submenu = new Menu(Functions::getCloseRelationshipName($head, $grandparent) . ' - ' . $grandparent->getFullName(), '#', '', array('onclick' => 'return appendCensusRow("' . Filter::escapeJs(self::censusTableRow($census, $grandparent, $head)) . '");'));
                    $submenu->addClass('submenuitem', '');
                    $menu->addSubmenu($submenu);
                    $menu->addClass('', 'submenu');
                }
            }
            ?>
			<tr>
				<td class="optionbox">
					<?php 
            echo $menu->getMenu();
            ?>
				</td>
				<td class="facts_value nowrap">
					<a href="#" onclick="return appendCensusRow('<?php 
            echo Filter::escapeJs(self::censusTableRow($census, $spouse, $head));
            ?>
');">
						<?php 
            echo $spouse->getFullName();
            ?>
					</a>
				</td>
				<td class="facts_value">
					<?php 
            if ($head !== $spouse) {
                ?>
						<a href="edit_interface.php?action=addnewnote_assisted&amp;noteid=newnote&amp;xref=<?php 
                echo $spouse->getXref();
                ?>
&amp;gedcom=<?php 
                echo $spouse->getTree()->getNameUrl();
                ?>
&amp;census=<?php 
                echo get_class($census);
                ?>
">
							<?php 
                echo $headImg2;
                ?>
						</a>
					<?php 
            }
            ?>
				</td>
			</tr>
			<?php 
        }
        foreach ($family->getChildren() as $child) {
            $menu = new Menu(Functions::getCloseRelationshipName($head, $child));
            foreach ($child->getSpouseFamilies() as $spouse_family) {
                foreach ($spouse_family->getSpouses() as $spouse_family_spouse) {
                    if ($spouse_family_spouse != $child) {
                        $submenu = new Menu(Functions::getCloseRelationshipName($head, $spouse_family_spouse) . ' - ' . $spouse_family_spouse->getFullName(), '#', '', array('onclick' => 'return appendCensusRow("' . Filter::escapeJs(self::censusTableRow($census, $spouse_family_spouse, $head)) . '");'));
                        $submenu->addClass('submenuitem', '');
                        $menu->addSubmenu($submenu);
                        $menu->addClass('', 'submenu');
                    }
                }
                foreach ($spouse_family->getChildren() as $spouse_family_child) {
                    $submenu = new Menu(Functions::getCloseRelationshipName($head, $spouse_family_child) . ' - ' . $spouse_family_child->getFullName(), '#', '', array('onclick' => 'return appendCensusRow("' . Filter::escapeJs(self::censusTableRow($census, $spouse_family_child, $head)) . '");'));
                    $submenu->addClass('submenuitem', '');
                    $menu->addSubmenu($submenu);
                    $menu->addClass('', 'submenu');
                }
            }
            ?>
			<tr>
				<td class="optionbox">
					<?php 
            echo $menu->getMenu();
            ?>
				</td>
				<td class="facts_value">
					<a href="#" onclick="return appendCensusRow('<?php 
            echo Filter::escapeJs(self::censusTableRow($census, $child, $head));
            ?>
');">
						<?php 
            echo $child->getFullName();
            ?>
					</a>
				</td>
				<td class="facts_value">
					<?php 
            if ($head !== $child) {
                ?>
						<a href="edit_interface.php?action=addnewnote_assisted&amp;noteid=newnote&amp;xref=<?php 
                echo $child->getXref();
                ?>
&amp;gedcom=<?php 
                echo $child->getTree()->getNameUrl();
                ?>
&amp;census=<?php 
                echo get_class($census);
                ?>
">
							<?php 
                echo $headImg2;
                ?>
						</a>
					<?php 
            }
            ?>
				</td>
			</tr>
			<?php 
        }
        echo '<tr><td><br></td></tr>';
    }
コード例 #20
0
ファイル: TreeView.php プロジェクト: tunandras/webtrees
 /**
  * Draw a person in the tree
  *
  * @param Individual $person The Person object to draw the box for
  * @param int        $gen    The number of generations up or down to print
  * @param int        $state  Whether we are going up or down the tree, -1 for descendents +1 for ancestors
  * @param Family     $pfamily
  * @param string     $order  first (1), last(2), unique(0), or empty. Required for drawing lines between boxes
  * @param bool       $isRoot
  *
  * @return string
  *
  * Notes : "spouse" means explicitely married partners. Thus, the word "partner"
  * (for "life partner") here fits much better than "spouse" or "mate"
  * to translate properly the modern french meaning of "conjoint"
  */
 private function drawPerson(Individual $person, $gen, $state, Family $pfamily = null, $order = null, $isRoot = false)
 {
     if ($gen < 0) {
         return '';
     }
     if (!empty($pfamily)) {
         $partner = $pfamily->getSpouse($person);
     } else {
         $partner = $person->getCurrentSpouse();
     }
     if ($isRoot) {
         $html = '<table id="tvTreeBorder" class="tv_tree"><tbody><tr><td id="tv_tree_topleft"></td><td id="tv_tree_top"></td><td id="tv_tree_topright"></td></tr><tr><td id="tv_tree_left"></td><td>';
     } else {
         $html = '';
     }
     /* height 1% : this hack enable the div auto-dimensioning in td for FF & Chrome */
     $html .= '<table class="tv_tree"' . ($isRoot ? ' id="tv_tree"' : '') . ' style="height: 1%"><tbody><tr>';
     if ($state <= 0) {
         // draw children
         $html .= $this->drawChildren($person->getSpouseFamilies(), $gen);
     } else {
         // draw the parent’s lines
         $html .= $this->drawVerticalLine($order) . $this->drawHorizontalLine();
     }
     /* draw the person. Do NOT add person or family id as an id, since a same person could appear more than once in the tree !!! */
     // Fixing the width for td to the box initial width when the person is the root person fix a rare bug that happen when a person without child and without known parents is the root person : an unwanted white rectangle appear at the right of the person’s boxes, otherwise.
     $html .= '<td' . ($isRoot ? ' style="width:1px"' : '') . '><div class="tv_box' . ($isRoot ? ' rootPerson' : '') . '" dir="' . I18N::direction() . '" style="text-align: ' . (I18N::direction() === 'rtl' ? 'right' : 'left') . '; direction: ' . I18N::direction() . '" abbr="' . $person->getXref() . '" onclick="' . $this->name . 'Handler.expandBox(this, event);">';
     $html .= $this->drawPersonName($person);
     $fop = array();
     // $fop is fathers of partners
     if (!is_null($partner)) {
         $dashed = '';
         foreach ($person->getSpouseFamilies() as $family) {
             $spouse = $family->getSpouse($person);
             if ($spouse) {
                 if ($spouse === $partner || $this->all_partners === 'true') {
                     $spouse_parents = $spouse->getPrimaryChildFamily();
                     if ($spouse_parents && $spouse_parents->getHusband()) {
                         $fop[] = array($spouse_parents->getHusband(), $spouse_parents);
                     } elseif ($spouse_parents && $spouse_parents->getWife()) {
                         $fop[] = array($spouse_parents->getWife(), $spouse_parents);
                     }
                     $html .= $this->drawPersonName($spouse, $dashed);
                     if ($this->all_partners !== 'true') {
                         break;
                         // we can stop here the foreach loop
                     }
                     $dashed = 'dashed';
                 }
             }
         }
     }
     $html .= '</div></td>';
     $primaryChildFamily = $person->getPrimaryChildFamily();
     if (!empty($primaryChildFamily)) {
         $parent = $primaryChildFamily->getHusband();
         if (empty($parent)) {
             $parent = $primaryChildFamily->getWife();
         }
     }
     if (!empty($parent) || count($fop) || $state < 0) {
         $html .= $this->drawHorizontalLine();
     }
     /* draw the parents */
     if ($state >= 0 && (!empty($parent) || count($fop))) {
         $unique = empty($parent) || count($fop) == 0;
         $html .= '<td align="left"><table class="tv_tree"><tbody>';
         if (!empty($parent)) {
             $u = $unique ? 'c' : 't';
             $html .= '<tr><td ' . ($gen == 0 ? ' abbr="p' . $primaryChildFamily->getXref() . '@' . $u . '"' : '') . '>';
             $html .= $this->drawPerson($parent, $gen - 1, 1, $primaryChildFamily, $u);
             $html .= '</td></tr>';
         }
         if (count($fop)) {
             $n = 0;
             $nb = count($fop);
             foreach ($fop as $p) {
                 $n++;
                 $u = $unique ? 'c' : ($n == $nb || empty($p[1]) ? 'b' : 'h');
                 $html .= '<tr><td ' . ($gen == 0 ? ' abbr="p' . $p[1]->getXref() . '@' . $u . '"' : '') . '>' . $this->drawPerson($p[0], $gen - 1, 1, $p[1], $u) . '</td></tr>';
             }
         }
         $html .= '</tbody></table></td>';
     }
     if ($state < 0) {
         $html .= $this->drawVerticalLine($order);
     }
     $html .= '</tr></tbody></table>';
     if ($isRoot) {
         $html .= '</td><td id="tv_tree_right"></td></tr><tr><td id="tv_tree_bottomleft"></td><td id="tv_tree_bottom"></td><td id="tv_tree_bottomright"></td></tr></tbody></table>';
     }
     return $html;
 }
コード例 #21
0
 /**
  * Print the links to media objects
  *
  * @param string $factrec
  * @param int $level
  */
 public static function printMediaLinks($factrec, $level)
 {
     global $WT_TREE;
     $nlevel = $level + 1;
     if (preg_match_all("/{$level} OBJE @(.*)@/", $factrec, $omatch, PREG_SET_ORDER) == 0) {
         return;
     }
     $objectNum = 0;
     while ($objectNum < count($omatch)) {
         $media_id = $omatch[$objectNum][1];
         $media = Media::getInstance($media_id, $WT_TREE);
         if ($media) {
             if ($media->canShow()) {
                 if ($objectNum > 0) {
                     echo '<br class="media-separator" style="clear:both;">';
                 }
                 echo '<div class="media-display"><div class="media-display-image">';
                 echo $media->displayImage();
                 echo '</div>';
                 echo '<div class="media-display-title">';
                 echo '<a href="', $media->getHtmlUrl(), '">', $media->getFullName(), '</a>';
                 // NOTE: echo the notes of the media
                 echo '<p>';
                 echo FunctionsPrint::printFactNotes($media->getGedcom(), 1);
                 $ttype = preg_match("/" . ($nlevel + 1) . " TYPE (.*)/", $media->getGedcom(), $match);
                 if ($ttype > 0) {
                     $mediaType = GedcomTag::getFileFormTypeValue($match[1]);
                     echo '<p class="label">', I18N::translate('Type'), ': </span> <span class="field">', $mediaType, '</p>';
                 }
                 echo '</p>';
                 //-- print spouse name for marriage events
                 $ct = preg_match("/WT_SPOUSE: (.*)/", $factrec, $match);
                 if ($ct > 0) {
                     $spouse = Individual::getInstance($match[1], $media->getTree());
                     if ($spouse) {
                         echo '<a href="', $spouse->getHtmlUrl(), '">';
                         echo $spouse->getFullName();
                         echo '</a>';
                     }
                     $ct = preg_match("/WT_FAMILY_ID: (.*)/", $factrec, $match);
                     if ($ct > 0) {
                         $famid = trim($match[1]);
                         $family = Family::getInstance($famid, $spouse->getTree());
                         if ($family) {
                             if ($spouse) {
                                 echo " - ";
                             }
                             echo '<a href="', $family->getHtmlUrl(), '">', I18N::translate('View family'), '</a>';
                         }
                     }
                 }
                 echo FunctionsPrint::printFactNotes($media->getGedcom(), $nlevel);
                 echo self::printFactSources($media->getGedcom(), $nlevel);
                 echo '</div>';
                 //close div "media-display-title"
                 echo '</div>';
                 //close div "media-display"
             }
         } elseif (!$WT_TREE->getPreference('HIDE_GEDCOM_ERRORS')) {
             echo '<p class="ui-state-error">', $media_id, '</p>';
         }
         $objectNum++;
     }
 }
コード例 #22
0
ファイル: GedcomRecord.php プロジェクト: AlexSnet/webtrees
 /**
  * Find families linked to this record.
  *
  * @param string $link
  *
  * @return Family[]
  */
 public function linkedFamilies($link)
 {
     $rows = Database::prepare("SELECT f_id AS xref, f_gedcom AS gedcom" . " FROM `##families`" . " JOIN `##link` ON f_file = l_file AND f_id = l_from" . " LEFT JOIN `##name` ON f_file = n_file AND f_id = n_id AND n_num = 0" . " WHERE f_file = :tree_id AND l_type = :link AND l_to = :xref")->execute(array('tree_id' => $this->tree->getTreeId(), 'link' => $link, 'xref' => $this->xref))->fetchAll();
     $list = array();
     foreach ($rows as $row) {
         $record = Family::getInstance($row->xref, $this->tree, $row->gedcom);
         if ($record->canShowName()) {
             $list[] = $record;
         }
     }
     return $list;
 }
コード例 #23
0
ファイル: MEDIA_ctrl.php プロジェクト: jflash/webtrees
/**
 * Display family members with clickable links
 *
 * @param Family     $family
 * @param Individual $individual
 */
function print_navigator_family(Family $family, Individual $individual)
{
    foreach ($family->getSpouses() as $spouse) {
        ?>
		<tr class="fact_value">
			<td class="facts_value">
				<a href="edit_interface.php?action=addmedia_links&amp;noteid=newnote&amp;pid=<?php 
        echo $spouse->getXref();
        ?>
&amp;gedcom=<?php 
        echo $spouse->getTree()->getNameUrl();
        ?>
">
					<i class="headimg vmiddle icon-button_head"></i>
				</a>
			</td>
			<td class="facts_value" >
				<a href="#" onclick="opener.insertRowToTable('<?php 
        echo $spouse->getXref();
        ?>
', '<?php 
        echo Filter::escapeJs($spouse->getFullName());
        ?>
', '', '', '', '', '', '', '', '');">
					<?php 
        echo $spouse === $individual ? '<b>' : '';
        ?>
					<?php 
        echo $spouse->getFullName();
        ?>
 <?php 
        echo $spouse->getLifeSpan();
        ?>
					<?php 
        echo $spouse === $individual ? '</b>' : '';
        ?>
				</a>
			</td>
		<tr>
	<?php 
    }
    foreach ($family->getChildren() as $child) {
        ?>
		<tr>
			<td class="facts_value" >
				<a href="edit_interface.php?action=addmedia_links&amp;noteid=newnote&amp;pid=<?php 
        echo $child->getXref();
        ?>
&amp;gedcom=<?php 
        echo $child->getTree()->getNameUrl();
        ?>
">
					<i class="headimg vmiddle icon-button_head"></i>
				</a>
			</td>
			<td class="facts_value">
				<a href="#" onclick="opener.insertRowToTable('<?php 
        echo $child->getXref();
        ?>
', '<?php 
        echo Filter::escapeJs($child->getFullName());
        ?>
', '', '', '', '', '', '', '', '');">
					<?php 
        echo $child === $individual ? '<b>' : '';
        ?>
					<?php 
        echo $child->getFullName();
        ?>
 <?php 
        echo $child->getLifeSpan();
        ?>
				<?php 
        echo $child === $individual ? '</b>' : '';
        ?>
				</a>
			</td>
		</tr>
	<?php 
    }
}
コード例 #24
0
        $record = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
        foreach ($record->getFacts() as $fact) {
            $old_place = $fact->getAttribute('PLAC');
            if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
                $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
                $changes[$old_place] = $new_place;
                if ($confirm == 'update') {
                    $gedcom = preg_replace('/(\\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom());
                    $record->updateFact($fact->getFactId(), $gedcom, false);
                }
            }
        }
    }
    $rows = Database::prepare("SELECT f_id AS xref, f_gedcom AS gedcom" . " FROM `##families`" . " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" . " WHERE f_file = ?" . " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|\$)')")->execute(array($WT_TREE->getTreeId(), preg_quote($search)))->fetchAll();
    foreach ($rows as $row) {
        $record = Family::getInstance($row->xref, $WT_TREE, $row->gedcom);
        foreach ($record->getFacts() as $fact) {
            $old_place = $fact->getAttribute('PLAC');
            if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
                $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
                $changes[$old_place] = $new_place;
                if ($confirm == 'update') {
                    $gedcom = preg_replace('/(\\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom());
                    $record->updateFact($fact->getFactId(), $gedcom, false);
                }
            }
        }
    }
}
$controller = new PageController();
$controller->restrictAccess(Auth::isManager($WT_TREE))->setPageTitle(I18N::translate('Update all the place names in a family tree') . ' — ' . $WT_TREE->getTitleHtml())->addInlineJavascript('autocomplete();')->pageHeader();
コード例 #25
0
 /**
  * Export the database in GEDCOM format
  *
  * @param Tree $tree Which tree to export
  * @param resource $gedout Handle to a writable stream
  * @param string[] $exportOptions Export options are as follows:
  *                                'privatize':    which Privacy rules apply? (none, visitor, user, manager)
  *                                'toANSI':       should the output be produced in ISO-8859-1 instead of UTF-8? (yes, no)
  *                                'path':         what constant should prefix all media file paths? (eg: media/  or c:\my pictures\my family
  *                                'slashes':      what folder separators apply to media file paths? (forward, backward)
  */
 public static function exportGedcom(Tree $tree, $gedout, $exportOptions)
 {
     switch ($exportOptions['privatize']) {
         case 'gedadmin':
             $access_level = Auth::PRIV_NONE;
             break;
         case 'user':
             $access_level = Auth::PRIV_USER;
             break;
         case 'visitor':
             $access_level = Auth::PRIV_PRIVATE;
             break;
         case 'none':
             $access_level = Auth::PRIV_HIDE;
             break;
     }
     $head = self::gedcomHeader($tree);
     if ($exportOptions['toANSI'] == 'yes') {
         $head = str_replace('UTF-8', 'ANSI', $head);
         $head = utf8_decode($head);
     }
     $head = self::reformatRecord($head);
     fwrite($gedout, $head);
     // Buffer the output. Lots of small fwrite() calls can be very slow when writing large gedcoms.
     $buffer = '';
     // Generate the OBJE/SOUR/REPO/NOTE records first, as their privacy calcualations involve
     // database queries, and we wish to avoid large gaps between queries due to MySQL connection timeouts.
     $tmp_gedcom = '';
     $rows = Database::prepare("SELECT m_id AS xref, m_gedcom AS gedcom" . " FROM `##media` WHERE m_file = :tree_id ORDER BY m_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Media::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         $rec = self::convertMediaPath($rec, $exportOptions['path']);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $tmp_gedcom .= self::reformatRecord($rec);
     }
     $rows = Database::prepare("SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom" . " FROM `##sources` WHERE s_file = :tree_id ORDER BY s_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Source::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $tmp_gedcom .= self::reformatRecord($rec);
     }
     $rows = Database::prepare("SELECT o_type AS type, o_id AS xref, o_gedcom AS gedcom" . " FROM `##other` WHERE o_file = :tree_id AND o_type NOT IN ('HEAD', 'TRLR') ORDER BY o_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         switch ($row->type) {
             case 'NOTE':
                 $record = Note::getInstance($row->xref, $tree, $row->gedcom);
                 break;
             case 'REPO':
                 $record = Repository::getInstance($row->xref, $tree, $row->gedcom);
                 break;
             default:
                 $record = GedcomRecord::getInstance($row->xref, $tree, $row->gedcom);
                 break;
         }
         $rec = $record->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $tmp_gedcom .= self::reformatRecord($rec);
     }
     $rows = Database::prepare("SELECT i_id AS xref, i_gedcom AS gedcom" . " FROM `##individuals` WHERE i_file = :tree_id ORDER BY i_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Individual::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $buffer .= self::reformatRecord($rec);
         if (strlen($buffer) > 65536) {
             fwrite($gedout, $buffer);
             $buffer = '';
         }
     }
     $rows = Database::prepare("SELECT f_id AS xref, f_gedcom AS gedcom" . " FROM `##families` WHERE f_file = :tree_id ORDER BY f_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Family::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $buffer .= self::reformatRecord($rec);
         if (strlen($buffer) > 65536) {
             fwrite($gedout, $buffer);
             $buffer = '';
         }
     }
     fwrite($gedout, $buffer);
     fwrite($gedout, $tmp_gedcom);
     fwrite($gedout, '0 TRLR' . WT_EOL);
 }
コード例 #26
0
    return array_map(function ($y) use($WT_TREE) {
        return Source::getInstance($y, $WT_TREE);
    }, $tmp);
}, $sources);
$individuals = Database::prepare("SELECT DISTINCT GROUP_CONCAT(d_gid ORDER BY d_gid) AS xrefs" . " FROM `##dates` AS d" . " JOIN `##name` ON d_file = n_file AND d_gid = n_id" . " WHERE d_file = :tree_id AND d_fact IN ('BIRT', 'CHR', 'BAPM', 'DEAT', 'BURI')" . " GROUP BY d_day, d_month, d_year, d_type, d_fact, n_type, n_full" . " HAVING COUNT(DISTINCT d_gid) > 1")->execute(array('tree_id' => $WT_TREE->getTreeId()))->fetchAll();
$individuals = array_map(function (\stdClass $x) use($WT_TREE) {
    $tmp = explode(',', $x->xrefs);
    return array_map(function ($y) use($WT_TREE) {
        return Individual::getInstance($y, $WT_TREE);
    }, $tmp);
}, $individuals);
$families = Database::prepare("SELECT GROUP_CONCAT(f_id) AS xrefs " . " FROM `##families`" . " WHERE f_file = :tree_id" . " GROUP BY LEAST(f_husb, f_wife), GREATEST(f_husb, f_wife)" . " HAVING COUNT(f_id) > 1")->execute(array('tree_id' => $WT_TREE->getTreeId()))->fetchAll();
$families = array_map(function (\stdClass $x) use($WT_TREE) {
    $tmp = explode(',', $x->xrefs);
    return array_map(function ($y) use($WT_TREE) {
        return Family::getInstance($y, $WT_TREE);
    }, $tmp);
}, $families);
$media = Database::prepare("SELECT GROUP_CONCAT(m_id) AS xrefs " . " FROM `##media`" . " WHERE m_file = :tree_id" . " GROUP BY m_titl" . " HAVING COUNT(m_id) > 1")->execute(array('tree_id' => $WT_TREE->getTreeId()))->fetchAll();
$media = array_map(function (\stdClass $x) use($WT_TREE) {
    $tmp = explode(',', $x->xrefs);
    return array_map(function ($y) use($WT_TREE) {
        return Media::getInstance($y, $WT_TREE);
    }, $tmp);
}, $media);
$all_duplicates = array(I18N::translate('Repositories') => $repositories, I18N::translate('Sources') => $sources, I18N::translate('Individuals') => $individuals, I18N::translate('Families') => $families, I18N::translate('Media objects') => $media);
?>
<ol class="breadcrumb small">
	<li><a href="admin.php"><?php 
echo I18N::translate('Control panel');
?>
コード例 #27
0
ファイル: Stats.php プロジェクト: AlexSnet/webtrees
 /**
  * Find the couple with the most grandchildren.
  *
  * @param string   $type
  * @param string[] $params
  *
  * @return string
  */
 private function topTenGrandFamilyQuery($type = 'list', $params = array())
 {
     if (isset($params[0])) {
         $total = (int) $params[0];
     } else {
         $total = 10;
     }
     $rows = $this->runSql("SELECT SQL_CACHE COUNT(*) AS tot, f_id AS id" . " FROM `##families`" . " JOIN `##link` AS children ON children.l_file = {$this->tree->getTreeId()}" . " JOIN `##link` AS mchildren ON mchildren.l_file = {$this->tree->getTreeId()}" . " JOIN `##link` AS gchildren ON gchildren.l_file = {$this->tree->getTreeId()}" . " WHERE" . " f_file={$this->tree->getTreeId()} AND" . " children.l_from=f_id AND" . " children.l_type='CHIL' AND" . " children.l_to=mchildren.l_from AND" . " mchildren.l_type='FAMS' AND" . " mchildren.l_to=gchildren.l_from AND" . " gchildren.l_type='CHIL'" . " GROUP BY id" . " ORDER BY tot DESC" . " LIMIT " . $total);
     if (!isset($rows[0])) {
         return '';
     }
     $top10 = array();
     foreach ($rows as $row) {
         $family = Family::getInstance($row['id'], $this->tree);
         if ($family->canShow()) {
             if ($type === 'list') {
                 $top10[] = '<li><a href="' . $family->getHtmlUrl() . '">' . $family->getFullName() . '</a> - ' . I18N::plural('%s grandchild', '%s grandchildren', $row['tot'], I18N::number($row['tot']));
             } else {
                 $top10[] = '<a href="' . $family->getHtmlUrl() . '">' . $family->getFullName() . '</a> - ' . I18N::plural('%s grandchild', '%s grandchildren', $row['tot'], I18N::number($row['tot']));
             }
         }
     }
     if ($type === 'list') {
         $top10 = implode('', $top10);
     } else {
         $top10 = implode(';&nbsp; ', $top10);
     }
     if (I18N::direction() === 'rtl') {
         $top10 = str_replace(array('[', ']', '(', ')', '+'), array('&rlm;[', '&rlm;]', '&rlm;(', '&rlm;)', '&rlm;+'), $top10);
     }
     if ($type === 'list') {
         return '<ul>' . $top10 . '</ul>';
     }
     return $top10;
 }
コード例 #28
0
 /**
  * Get the current view of a record, allowing for pending changes
  *
  * @param string $xref
  * @param string $type
  *
  * @return string
  */
 public static function getLatestRecord($xref, $type)
 {
     global $WT_TREE;
     switch ($type) {
         case 'INDI':
             return Individual::getInstance($xref, $WT_TREE)->getGedcom();
         case 'FAM':
             return Family::getInstance($xref, $WT_TREE)->getGedcom();
         case 'SOUR':
             return Source::getInstance($xref, $WT_TREE)->getGedcom();
         case 'REPO':
             return Repository::getInstance($xref, $WT_TREE)->getGedcom();
         case 'OBJE':
             return Media::getInstance($xref, $WT_TREE)->getGedcom();
         case 'NOTE':
             return Note::getInstance($xref, $WT_TREE)->getGedcom();
         default:
             return GedcomRecord::getInstance($xref, $WT_TREE)->getGedcom();
     }
 }
コード例 #29
0
 /**
  * Get the description for the family.
  *
  * For example, "XXX's family with new wife".
  *
  * @param Family     $family
  * @param Individual $individual
  *
  * @return string
  */
 public function getSpouseFamilyLabel(Family $family, Individual $individual)
 {
     $spouse = $family->getSpouse($individual);
     if ($spouse) {
         return I18N::translate('Family with %s', $spouse->getFullName());
     } else {
         return $family->getFullName();
     }
 }
コード例 #30
0
 /**
  * Get the events of children and grandchildren.
  *
  * @param Individual $person
  * @param Family     $family
  * @param string     $option
  * @param string     $relation
  *
  * @return Fact[]
  */
 private static function childFacts(Individual $person, Family $family, $option, $relation)
 {
     global $controller;
     $SHOW_RELATIVES_EVENTS = $person->getTree()->getPreference('SHOW_RELATIVES_EVENTS');
     $facts = array();
     // Only include events between birth and death
     $birt_date = $controller->record->getEstimatedBirthDate();
     $deat_date = $controller->record->getEstimatedDeathDate();
     // Deal with recursion.
     switch ($option) {
         case '_CHIL':
             // Add grandchildren
             foreach ($family->getChildren() as $child) {
                 foreach ($child->getSpouseFamilies() as $cfamily) {
                     switch ($child->getSex()) {
                         case 'M':
                             foreach (self::childFacts($person, $cfamily, '_GCHI', 'son') as $fact) {
                                 $facts[] = $fact;
                             }
                             break;
                         case 'F':
                             foreach (self::childFacts($person, $cfamily, '_GCHI', 'dau') as $fact) {
                                 $facts[] = $fact;
                             }
                             break;
                         default:
                             foreach (self::childFacts($person, $cfamily, '_GCHI', 'chi') as $fact) {
                                 $facts[] = $fact;
                             }
                             break;
                     }
                 }
             }
             break;
     }
     // For each child in the family
     foreach ($family->getChildren() as $child) {
         if ($child->getXref() == $person->getXref()) {
             // We are not our own sibling!
             continue;
         }
         // add child’s birth
         if (strpos($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option)) !== false) {
             foreach ($child->getFacts(WT_EVENTS_BIRT) as $fact) {
                 $sgdate = $fact->getDate();
                 // Always show _BIRT_CHIL, even if the dates are not known
                 if ($option == '_CHIL' || $sgdate->isOK() && Date::compare($birt_date, $sgdate) <= 0 && Date::compare($sgdate, $deat_date) <= 0) {
                     if ($option == '_GCHI' && $relation == 'dau') {
                         // Convert the event to a close relatives event.
                         $rela_fact = clone $fact;
                         $rela_fact->setTag('_' . $fact->getTag() . '_GCH1');
                         $facts[] = $rela_fact;
                     } elseif ($option == '_GCHI' && $relation == 'son') {
                         // Convert the event to a close relatives event.
                         $rela_fact = clone $fact;
                         $rela_fact->setTag('_' . $fact->getTag() . '_GCH2');
                         $facts[] = $rela_fact;
                     } else {
                         // Convert the event to a close relatives event.
                         $rela_fact = clone $fact;
                         $rela_fact->setTag('_' . $fact->getTag() . $option);
                         $facts[] = $rela_fact;
                     }
                 }
             }
         }
         // add child’s death
         if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option)) !== false) {
             foreach ($child->getFacts(WT_EVENTS_DEAT) as $fact) {
                 $sgdate = $fact->getDate();
                 if ($sgdate->isOK() && Date::compare($birt_date, $sgdate) <= 0 && Date::compare($sgdate, $deat_date) <= 0) {
                     if ($option == '_GCHI' && $relation == 'dau') {
                         // Convert the event to a close relatives event.
                         $rela_fact = clone $fact;
                         $rela_fact->setTag('_' . $fact->getTag() . '_GCH1');
                         $facts[] = $rela_fact;
                     } elseif ($option == '_GCHI' && $relation == 'son') {
                         // Convert the event to a close relatives event.
                         $rela_fact = clone $fact;
                         $rela_fact->setTag('_' . $fact->getTag() . '_GCH2');
                         $facts[] = $rela_fact;
                     } else {
                         // Convert the event to a close relatives event.
                         $rela_fact = clone $fact;
                         $rela_fact->setTag('_' . $fact->getTag() . $option);
                         $facts[] = $rela_fact;
                     }
                 }
             }
         }
         // add child’s marriage
         if (strstr($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option))) {
             foreach ($child->getSpouseFamilies() as $sfamily) {
                 foreach ($sfamily->getFacts(WT_EVENTS_MARR) as $fact) {
                     $sgdate = $fact->getDate();
                     if ($sgdate->isOK() && Date::compare($birt_date, $sgdate) <= 0 && Date::compare($sgdate, $deat_date) <= 0) {
                         if ($option == '_GCHI' && $relation == 'dau') {
                             // Convert the event to a close relatives event.
                             $rela_fact = clone $fact;
                             $rela_fact->setTag('_' . $fact->getTag() . '_GCH1');
                             $facts[] = $rela_fact;
                         } elseif ($option == '_GCHI' && $relation == 'son') {
                             // Convert the event to a close relatives event.
                             $rela_fact = clone $fact;
                             $rela_fact->setTag('_' . $fact->getTag() . '_GCH2');
                             $facts[] = $rela_fact;
                         } else {
                             // Convert the event to a close relatives event.
                             $rela_fact = clone $fact;
                             $rela_fact->setTag('_' . $fact->getTag() . $option);
                             $facts[] = $rela_fact;
                         }
                     }
                 }
             }
         }
     }
     return $facts;
 }