diff options
183 files changed, 6574 insertions, 7929 deletions
diff --git a/action.php b/action.php index 5e3611b82c..084685aacb 100644 --- a/action.php +++ b/action.php @@ -20,7 +20,7 @@ // the correct response for both success/error. // // webtrees: Web based Family History software -// Copyright (C) 2011 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -48,9 +48,9 @@ case 'accept-changes': // Accept all the pending changes for a record require WT_ROOT.'includes/functions/functions_edit.php'; $record=WT_GedcomRecord::getInstance(safe_POST_xref('xref')); - if ($record && WT_USER_CAN_ACCEPT && $record->canDisplayDetails() && $record->canEdit()) { + if ($record && WT_USER_CAN_ACCEPT && $record->canShow() && $record->canEdit()) { WT_FlashMessages::addMessage(/* I18N: %s is the name of an individual, source or other record */ WT_I18N::translate('The changes to “%s” have been accepted.', $record->getFullName())); - accept_all_changes($record->getXref(), $record->getGedId()); + accept_all_changes($record->getXref(), $record->getGedcomId()); } else { header('HTTP/1.0 406 Not Acceptable'); } @@ -58,30 +58,61 @@ case 'accept-changes': case 'copy-fact': // Copy a fact to the clipboard - // The calling page may want to reload, to refresh its "paste" buffer require WT_ROOT.'includes/functions/functions_edit.php'; - $fact=new WT_Event(rawurldecode(safe_POST('factgedcom', WT_REGEX_UNSAFE)), null, 0); - // Where can we paste this? - if (preg_match('/^(NOTE|SOUR|OBJE)$/', $fact->getTag())) { - // Some facts can be pasted to any record - $type='all'; - } else { - // Other facts can only be pasted records of the same type - $type=safe_POST('type', array('INDI','FAM','SOUR','REPO','OBJE','NOTE')); - } - if (!is_array($WT_SESSION->clipboard)) { - $WT_SESSION->clipboard=array(); + $xref = safe_POST_xref('xref'); + $fact_id = safe_POST('fact_id'); + + $record = WT_GedcomRecord::getInstance($xref); + + if ($record && $record->canEdit()) { + foreach ($record->getFacts() as $fact) { + if ($fact->getfactId() == $fact_id) { + switch ($fact->getTag()) { + case 'NOTE': + case 'SOUR': + case 'OBJE': + $type = 'all'; // paste this anywhere + break; + default: + $type = $record::RECORD_TYPE; // paste only to the same record type + break; + } + if (!is_array($WT_SESSION->clipboard)) { + $WT_SESSION->clipboard=array(); + } + $WT_SESSION->clipboard[]=array( + 'type' =>$type, + 'factrec'=>$fact->getGedcom(), + 'fact' =>$fact->getTag() + ); + // The clipboard only holds 10 facts + while (count($WT_SESSION->clipboard)>10) { + array_pop($WT_SESSION->clipboard); + } + WT_FlashMessages::addMessage(WT_I18N::translate('Record copied to clipboard')); + break 2; + } + } } - $WT_SESSION->clipboard[]=array( - 'type' =>$type, - 'factrec'=>$fact->getGedcomRecord(), - 'fact' =>$fact->getTag() - ); - // The clipboard only holds 10 facts - while (count($WT_SESSION->clipboard)>10) { - array_pop($WT_SESSION->clipboard); + break; + +case 'delete-fact': + require WT_ROOT.'includes/functions/functions_edit.php'; + $xref = safe_POST_xref('xref'); + $fact_id = safe_POST('fact_id'); + + $record = WT_GedcomRecord::getInstance($xref); + if ($record && $record->canEdit()) { + foreach ($record->getFacts() as $fact) { + if ($fact->getfactId() == $fact_id && $fact->canShow() && $fact->canEdit()) { + $record->updateFact($fact_id, '', true); + break 2; + } + } } - WT_FlashMessages::addMessage(WT_I18N::translate('Record copied to clipboard')); + + // Can’t find the record/fact, or don’t have permission to delete it. + header('HTTP/1.0 406 Not Acceptable'); break; case 'delete-family': @@ -92,34 +123,34 @@ case 'delete-repository': case 'delete-source': require WT_ROOT.'includes/functions/functions_edit.php'; $record=WT_GedcomRecord::getInstance(safe_POST_xref('xref')); - if ($record && WT_USER_CAN_EDIT && $record->canDisplayDetails() && $record->canEdit()) { + if ($record && WT_USER_CAN_EDIT && $record->canShow() && $record->canEdit()) { // Delete links to this record - foreach (fetch_all_links($record->getXref(), $record->getGedId()) as $xref) { + foreach (fetch_all_links($record->getXref(), $record->getGedcomId()) as $xref) { $linker = WT_GedcomRecord::getInstance($xref); - $gedrec = find_gedcom_record($xref, $record->getGedId(), true); + $gedrec = find_gedcom_record($xref, $record->getGedcomId(), true); $gedrec = remove_links($gedrec, $record->getXref()); // If we have removed a link from a family to an individual, and it has only one member if (preg_match('/^0 @'.WT_REGEX_XREF.'@ FAM/', $gedrec) && preg_match_all('/\n1 (HUSB|WIFE|CHIL) @(' . WT_REGEX_XREF . ')@/', $gedrec, $match)<2) { // Delete the family $family = WT_GedcomRecord::getInstance($xref); WT_FlashMessages::addMessage(/* I18N: %s is the name of a family group, e.g. “Husband name + Wife name” */ WT_I18N::translate('The family “%s” has been deleted, as it only has one member.', $family->getFullName())); - delete_gedrec($family->getXref(), $family->getGedId()); + $family->deleteRecord(); // Delete any remaining link to this family if ($match) { $relict = WT_GedcomRecord::getInstance($match[2][0]); - $gedrec = find_gedcom_record($relict->getXref(), $relict->getGedId(), true); + $gedrec = find_gedcom_record($relict->getXref(), $relict->getGedcomId(), true); $gedrec = remove_links($gedrec, $linker->getXref()); - replace_gedrec($relict->getXref(), $relict->getGedId(), $gedrec, false); + replace_gedrec($relict->getXref(), $relict->getGedcomId(), $gedrec, false); WT_FlashMessages::addMessage(/* I18N: %s are names of records, such as sources, repositories or individuals */ WT_I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $relict->getFullName(), $family->getFullName())); } } else { // Remove links from $linker to $record WT_FlashMessages::addMessage(/* I18N: %s are names of records, such as sources, repositories or individuals */ WT_I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $linker->getFullName(), $record->getFullName())); - replace_gedrec($linker->getXref(), $linker->getGedId(), $gedrec, false); + replace_gedrec($linker->getXref(), $linker->getGedcomId(), $gedrec, false); } } // Delete the record itself - delete_gedrec($record->getXref(), $record->getGedId()); + $record->deleteRecord(); } else { header('HTTP/1.0 406 Not Acceptable'); } @@ -129,9 +160,9 @@ case 'reject-changes': // Reject all the pending changes for a record require WT_ROOT.'includes/functions/functions_edit.php'; $record=WT_GedcomRecord::getInstance(safe_POST_xref('xref')); - if ($record && WT_USER_CAN_ACCEPT && $record->canDisplayDetails() && $record->canEdit()) { + if ($record && WT_USER_CAN_ACCEPT && $record->canShow() && $record->canEdit()) { WT_FlashMessages::addMessage(/* I18N: %s is the name of an individual, source or other record */ WT_I18N::translate('The changes to “%s” have been rejected.', $record->getFullName())); - reject_all_changes($record->getXref(), $record->getGedId()); + reject_all_changes($record->getXref(), $record->getGedcomId()); } else { header('HTTP/1.0 406 Not Acceptable'); } diff --git a/addmedia.php b/addmedia.php index f0e89f095d..874e0ca227 100644 --- a/addmedia.php +++ b/addmedia.php @@ -68,12 +68,12 @@ $controller $disp = true; $media = WT_Media::getInstance($pid); if ($media) { - $disp = $media->canDisplayDetails(); + $disp = $media->canShow(); } if ($action=='update' || $action=='create') { if (!isset($linktoid) || $linktoid=='new') $linktoid=''; if (!empty($linktoid)) { - $disp = WT_GedcomRecord::getInstance($linktoid)->canDisplayDetails(); + $disp = WT_GedcomRecord::getInstance($linktoid)->canShow(); } } @@ -226,29 +226,25 @@ case 'create': // Save the information from the “showcreateform” action $controller->pageHeader(); // Build the gedcom record - $media_id = get_new_xref('OBJE'); - if ($media_id) { - $newged = '0 @' . $media_id . "@ OBJE\n"; - if ($tag[0]=='FILE') { - // The admin has an edit field to change the file name - $text[0] = $folderName . $fileName; - } else { - // Users keep the original filename - $newged .= '1 FILE ' . $folderName . $fileName; - } + $newged = "0 @new@ OBJE\n"; + if ($tag[0]=='FILE') { + // The admin has an edit field to change the file name + $text[0] = $folderName . $fileName; + } else { + // Users keep the original filename + $newged .= '1 FILE ' . $folderName . $fileName; + } - $newged = handle_updates($newged); + $newged = handle_updates($newged); - if (append_gedrec($newged, WT_GED_ID)) { - if ($linktoid) { - linkMedia($media_id, $linktoid, 1); - AddToLog('Media ID '.$media_id." successfully added to $linktoid.", 'edit'); - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } else { - AddToLog('Media ID '.$media_id.' successfully added.', 'edit'); - $controller->addInlineJavascript('openerpasteid("' . $media_id . '");'); - } - } + $media = WT_GedcomRecord::createRecord($newged, WT_GED_ID); + if ($linktoid) { + linkMedia($media->getXref(), $linktoid, 1); + AddToLog('Media ID '.$media->getXref()." successfully added to $linktoid.", 'edit'); + $controller->addInlineJavascript('closePopupAndReloadParent();'); + } else { + AddToLog('Media ID '.$media->getXref().' successfully added.', 'edit'); + $controller->addInlineJavascript('openerpasteid("' . $media->getXref() . '");'); } echo '<button onclick="closePopupAndReloadParent();">', WT_I18N::translate('close'), '</button>'; exit; @@ -731,8 +727,8 @@ if (WT_USER_IS_ADMIN) { echo "<input type=\"checkbox\" name=\"preserve_last_changed\">"; } echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'), '<br>'; - $event = new WT_Event(get_sub_record(1, '1 CHAN', $gedrec), null, 0); - echo format_fact_date($event, new WT_Person(''), false, true); + //$event = new WT_Fact(get_sub_record(1, '1 CHAN', $gedrec), null, 0); + //echo format_fact_date($event, new WT_Individual(''), false, true); echo '</td></tr>'; } echo '</table>'; @@ -747,3 +743,18 @@ echo '</table>'; </p> </form> </div> + +<?php + + +// Legacy/depracted function. TODO: refactor this away.... +function get_first_tag($level, $tag, $gedrec, $num=1) { + $temp = get_sub_record($level, $level." ".$tag, $gedrec, $num)."\n"; + $length = strpos($temp, "\n"); + if ($length===false) { + $length = strlen($temp); + } + return substr($temp, 2, $length-2); +} + + @@ -1261,10 +1261,6 @@ function old_paths() { WT_ROOT.'modules_v3/googlemap/pedigree_map.php', WT_ROOT.'modules_v3/lightbox/admin_config.php', WT_ROOT.'modules_v3/lightbox/album.php', - WT_ROOT.'modules_v3/lightbox/functions/lb_call_js.php', - WT_ROOT.'modules_v3/lightbox/functions/lb_head.php', - WT_ROOT.'modules_v3/lightbox/functions/lb_link.php', - WT_ROOT.'modules_v3/lightbox/functions/lightbox_print_media_row.php', WT_ROOT.'modules_v3/tree/css/vline.jpg', WT_ROOT.'themes/_administration/images/darrow2.png', WT_ROOT.'themes/_administration/images/darrow.png', @@ -1433,6 +1429,10 @@ function old_paths() { WT_ROOT.'themes/minimal/jquery-ui-1.10.0', WT_ROOT.'themes/webtrees/jquery-ui-1.10.0', WT_ROOT.'themes/xenea/jquery-ui-1.10.0', + // Removed in 1.5.0 + WT_ROOT.'library/WT/Person.php', + WT_ROOT.'library/WT/Event.php', + WT_ROOT.'modules_v3/lightbox/functions', ); } diff --git a/admin_media.php b/admin_media.php index d304ebdb81..15b7b400f2 100644 --- a/admin_media.php +++ b/admin_media.php @@ -91,7 +91,7 @@ case 'load_json': case 'local': // Filtered rows $SELECT1 = - "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS TRIM(LEADING ? FROM m_filename) AS media_path, 'OBJE' AS type, m_titl, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_filename" . + "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS TRIM(LEADING ? FROM m_filename) AS media_path, m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom" . " FROM `##media`" . " JOIN `##gedcom_setting` ON (m_file = gedcom_id AND setting_name = 'MEDIA_DIRECTORY')" . " JOIN `##gedcom` USING (gedcom_id)" . @@ -147,16 +147,16 @@ case 'load_json': $ORDER_BY="1 ASC"; } - $rows = WT_DB::prepare($SELECT1.$ORDER_BY.$LIMIT)->execute($ARGS1)->fetchAll(PDO::FETCH_ASSOC); + $rows = WT_DB::prepare($SELECT1.$ORDER_BY.$LIMIT)->execute($ARGS1)->fetchAll(); // Total filtered/unfiltered rows $iTotalDisplayRecords = WT_DB::prepare("SELECT FOUND_ROWS()")->fetchColumn(); $iTotalRecords = WT_DB::prepare($SELECT2)->execute($ARGS2)->fetchColumn(); $aaData = array(); foreach ($rows as $row) { - $media = WT_Media::getInstance($row); + $media = WT_Media::getInstance($row->xref, $row->gedcom_id); $aaData[] = array( - media_file_info($media_folder, $media_path, $row['media_path']), + media_file_info($media_folder, $media_path, $row->media_path), $media->displayImage(), media_object_info($media), ); @@ -166,7 +166,7 @@ case 'load_json': case 'external': // Filtered rows $SELECT1 = - "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS m_filename AS media_path, 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename" . + "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom, m_filename" . " FROM `##media`" . " WHERE (m_filename LIKE 'http://%' OR m_filename LIKE 'https://%')" . " AND (m_filename LIKE CONCAT('%', ?, '%') OR m_titl LIKE CONCAT('%', ?, '%'))"; @@ -205,7 +205,7 @@ case 'load_json': $ORDER_BY="1 ASC"; } - $rows = WT_DB::prepare($SELECT1.$ORDER_BY.$LIMIT)->execute($ARGS1)->fetchAll(PDO::FETCH_ASSOC); + $rows = WT_DB::prepare($SELECT1.$ORDER_BY.$LIMIT)->execute($ARGS1)->fetchAll(); // Total filtered/unfiltered rows $iTotalDisplayRecords = WT_DB::prepare("SELECT FOUND_ROWS()")->fetchColumn(); @@ -213,9 +213,9 @@ case 'load_json': $aaData = array(); foreach ($rows as $row) { - $media = WT_Media::getInstance($row); + $media = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); $aaData[] = array( - WT_Gedcom_Tag::getLabelValue('URL', $row['m_filename']), + WT_Gedcom_Tag::getLabelValue('URL', $row->m_filename), $media->displayImage(), media_object_info($media), ); @@ -420,7 +420,7 @@ function media_file_info($media_folder, $media_path, $file) { function media_object_info(WT_Media $media) { $xref = $media->getXref(); - $gedcom = WT_Tree::getNameFromId($media->getGedId()); + $gedcom = WT_Tree::getNameFromId($media->getGedcomId()); $name = $media->getFullName(); $conf = WT_I18N::translate('Are you sure you want to delete “%s”?', strip_tags($name)); diff --git a/admin_site_merge.php b/admin_site_merge.php index f9a0b4e9e2..fd3b5d09ad 100644 --- a/admin_site_merge.php +++ b/admin_site_merge.php @@ -60,8 +60,8 @@ if ($action!='choose') { $gedrec2 = find_gedcom_record($gid2, get_id_from_gedcom($ged2), true); // Fetch the original XREF - may differ in case from the supplied value - $tmp=new WT_Person($gedrec1); $gid1=$tmp->getXref(); - $tmp=new WT_Person($gedrec2); $gid2=$tmp->getXref(); + $tmp=new WT_Individual($gedrec1); $gid1=$tmp->getXref(); + $tmp=new WT_Individual($gedrec2); $gid2=$tmp->getXref(); if (empty($gedrec1)) { echo '<span class="error">', WT_I18N::translate('Unable to find record with ID'), ':</span> ', $gid1, ', ', $ged; @@ -155,8 +155,7 @@ if ($action!='choose') { foreach ($facts2 as $j=>$fact2) { if (($fact2['fact']!='CHAN')&&(!in_array($j, $skip2))) { echo '<tr><td><input type="checkbox" name="keep2[]" value="', $j, '" checked="checked"></td>'; - // PHP5.3 echo '<td>', nl2br($fact2['subrec'], false), '</td></tr>'; - echo '<td>', nl2br($fact2['subrec']), '</td></tr>'; + echo '<td>', nl2br($fact2['subrec'], false), '</td></tr>'; } } echo '</table>'; @@ -168,7 +167,7 @@ if ($action!='choose') { $manual_save = true; echo '<div id="merge3"><h3>', WT_I18N::translate('Merge records'), '</h3>'; if ($GEDCOM==$ged2) { - $success = delete_gedrec($gid2, WT_GED_ID); + WT_GedcomRecord::getInstance($gid2)->deleteRecord(); echo WT_I18N::translate('GEDCOM record successfully deleted.'), '<br>'; //-- replace all the records that linked to gid2 $ids=fetch_all_links($gid2, WT_GED_ID); diff --git a/admin_trees_config.php b/admin_trees_config.php index 56712e6d09..73ec55bc53 100644 --- a/admin_trees_config.php +++ b/admin_trees_config.php @@ -236,7 +236,7 @@ if (count(WT_Tree::getAll())==1) { //Removed because it doesn't work here for mu <input type="text" name="NEW_PEDIGREE_ROOT_ID" id="NEW_PEDIGREE_ROOT_ID" value="<?php echo get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID'); ?>" size="5" maxlength="20"> <?php echo print_findindi_link('NEW_PEDIGREE_ROOT_ID'); - $person=WT_Person::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); + $person=WT_Individual::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); if ($person) { echo ' <span class="list_item">', $person->getFullName(), ' ', $person->format_first_major_fact(WT_EVENTS_BIRT, 1), '</span>'; } else { diff --git a/ancestry.php b/ancestry.php index f008485143..9f830747a7 100644 --- a/ancestry.php +++ b/ancestry.php @@ -160,7 +160,7 @@ case 1: $treeid=ancestry_array($controller->root->getXref(), $PEDIGREE_GENERATIONS-1); foreach ($treeid as $i=>$pid) { if ($pid) { - $person=WT_Person::getInstance($pid); + $person=WT_Individual::getInstance($pid); if ($person) { foreach ($person->getChildFamilies() as $family) { print_sosa_family($family->getXref(), $pid, $i); @@ -182,7 +182,7 @@ case 3: $treeid=ancestry_array($controller->root->getXref(), $PEDIGREE_GENERATIONS-1); $famlist=array(); foreach ($treeid as $pid) { - $person=WT_Person::getInstance($pid); + $person=WT_Individual::getInstance($pid); if (is_null($person)) { continue; } diff --git a/autocomplete.php b/autocomplete.php index 31c7e35afd..ecdd9d67f8 100644 --- a/autocomplete.php +++ b/autocomplete.php @@ -53,7 +53,7 @@ case 'ASSO': // Associates of an individuals, whose name contains the search ter $event_jd=$tmp->JD(); // INDI $indi_birth_jd = 0; - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $indi_birth_jd=$record->getEstimatedBirthDate()->minJD(); } // HUSB & WIFE @@ -70,8 +70,8 @@ case 'ASSO': // Associates of an individuals, whose name contains the search ter } } foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if ($person->canDisplayName()) { + $person=WT_Individual::getInstance($row); + if ($person->canShowName()) { // filter ASSOciate if ($event_jd) { // no self-ASSOciate @@ -129,17 +129,17 @@ case 'CEME': // Cemetery fields, that contain the search term // Fetch all data, regardless of privacy $rows= WT_DB::prepare( - "SELECT SQL_CACHE 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT SQL_CACHE i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`". " WHERE i_gedcom LIKE '%\n2 CEME %' AND i_file=?". " ORDER BY SUBSTRING_INDEX(i_gedcom, '\n2 CEME ', -1) COLLATE '".WT_I18N::$collation."'" ) ->execute(array(WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); // Filter for privacy foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if (preg_match('/\n2 CEME (.*'.preg_quote($term, '/').'.*)/i', $person->getGedcomRecord(), $match)) { + $person=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if (preg_match('/\n2 CEME (.*'.preg_quote($term, '/').'.*)/i', $person->getGedcom(), $match)) { if (!in_array($match[1], $data)) { $data[]=$match[1]; } @@ -155,7 +155,7 @@ case 'FAM': // Families, whose name contains the search terms // Filter for privacy foreach ($rows as $row) { $family=WT_Family::getInstance($row); - if ($family->canDisplayName()) { + if ($family->canShowName()) { $marriage_year=$family->getMarriageYear(); if ($marriage_year) { $data[]=array('value'=>$family->getXref(), 'label'=>$family->getFullName().', <i>'.$marriage_year.'</i>'); @@ -186,18 +186,18 @@ case 'INDI': // Individuals, whose name contains the search terms // Fetch all data, regardless of privacy $rows= WT_DB::prepare( - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec, n_full". + "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, n_full". " FROM `##individuals`". " JOIN `##name` ON (i_id=n_id AND i_file=n_file)". " WHERE (n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') OR n_surn LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%')) AND i_file=? ORDER BY n_full COLLATE '".WT_I18N::$collation."'" ) ->execute(array($term, $term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); // Filter for privacy foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if ($person->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row['n_full']).', <i>'.$person->getLifeSpan().'</i>'); + $person=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($person->canShowName()) { + $data[]=array('value'=>$row->xref, 'label'=>str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row->n_full).', <i>'.$person->getLifeSpan().'</i>'); } } echo json_encode($data); @@ -209,9 +209,9 @@ case 'NOTE': // Notes which contain the search terms $rows=get_NOTE_rows($term); // Filter for privacy foreach ($rows as $row) { - $note=WT_Note::getInstance($row); - if ($note->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>$note->getFullName()); + $note=WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($note->canShowName()) { + $data[]=array('value'=>$note->getXref(), 'label'=>$note->getFullName()); } } echo json_encode($data); @@ -223,9 +223,9 @@ case 'OBJE': $rows=get_OBJE_rows($term); // Filter for privacy foreach ($rows as $row) { - $media=WT_Media::getInstance($row); - if ($media->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>'<img src="'.$media->getHtmlUrlDirect().'" width="25"> '.$media->getFullName()); + $media=WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($media->canShowName()) { + $data[]=array('value'=>$row->xref, 'label'=>'<img src="'.$media->getHtmlUrlDirect().'" width="25"> '.$media->getFullName()); } } echo json_encode($data); @@ -290,8 +290,8 @@ case 'REPO': // Repositories, that include the search terms $rows=get_REPO_rows($term); // Filter for privacy foreach ($rows as $row) { - $repository=WT_Repository::getInstance($row); - if ($repository->canDisplayName()) { + $repository=WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($repository->canShowName()) { $data[]=array('value'=>$row['xref'], 'label'=>$row['n_full']); } } @@ -304,8 +304,8 @@ case 'REPO_NAME': // Repository names, that include the search terms $rows=get_REPO_rows($term); // Filter for privacy foreach ($rows as $row) { - $repository=WT_Repository::getInstance($row); - if ($repository->canDisplayName()) { + $repository=WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($repository->canShowName()) { $data[]=$row['n_full']; } } @@ -318,9 +318,9 @@ case 'SOUR': // Sources, that include the search terms $rows=get_SOUR_rows($term); // Filter for privacy foreach ($rows as $row) { - $source=WT_Source::getInstance($row); - if ($source->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>$row['n_full']); + $source=WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($source->canShowName()) { + $data[]=array('value'=>$row->xref, 'label'=>$row->n_full); } } echo json_encode($data); @@ -332,38 +332,38 @@ case 'SOUR_PAGE': // Citation details, for a given source, that contain the sear // Fetch all data, regardless of privacy $rows= WT_DB::prepare( - "SELECT SQL_CACHE 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT SQL_CACHE i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`". " WHERE i_gedcom LIKE CONCAT('%\n_ SOUR @', ?, '@%', REPLACE(?, ' ', '%'), '%') AND i_file=?" ) ->execute(array($sid, $term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); // Filter for privacy foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if (preg_match('/\n1 SOUR @'.$sid.'@(?:\n[2-9].*)*\n2 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $person->getGedcomRecord(), $match)) { + $person=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if (preg_match('/\n1 SOUR @'.$sid.'@(?:\n[2-9].*)*\n2 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $person->getGedcom(), $match)) { $data[]=$match[1]; } - if (preg_match('/\n2 SOUR @'.$sid.'@(?:\n[3-9].*)*\n3 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $person->getGedcomRecord(), $match)) { + if (preg_match('/\n2 SOUR @'.$sid.'@(?:\n[3-9].*)*\n3 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $person->getGedcom(), $match)) { $data[]=$match[1]; } } // Fetch all data, regardless of privacy $rows= WT_DB::prepare( - "SELECT SQL_CACHE 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec". + "SELECT SQL_CACHE f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom". " FROM `##families`". " WHERE f_gedcom LIKE CONCAT('%\n_ SOUR @', ?, '@%', REPLACE(?, ' ', '%'), '%') AND f_file=?" ) ->execute(array($sid, $term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); // Filter for privacy foreach ($rows as $row) { - $family=WT_Family::getInstance($row); - if (preg_match('/\n1 SOUR @'.$sid.'@(?:\n[2-9].*)*\n2 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $family->getGedcomRecord(), $match)) { + $family=WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if (preg_match('/\n1 SOUR @'.$sid.'@(?:\n[2-9].*)*\n2 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $family->getGedcom(), $match)) { $data[]=$match[1]; } - if (preg_match('/\n2 SOUR @'.$sid.'@(?:\n[3-9].*)*\n3 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $family->getGedcomRecord(), $match)) { + if (preg_match('/\n2 SOUR @'.$sid.'@(?:\n[3-9].*)*\n3 PAGE (.*'.str_replace(' ', '.+', preg_quote($term, '/')).'.*)/i', $family->getGedcom(), $match)) { $data[]=$match[1]; } } @@ -379,17 +379,17 @@ case 'SOUR_TITL': // Source titles, that include the search terms // Fetch all data, regardless of privacy $rows= WT_DB::prepare( - "SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec, s_name". + "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom, s_name". " FROM `##sources`". " WHERE s_name LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND s_file=? ORDER BY s_name COLLATE '".WT_I18N::$collation."'" ) ->execute(array($term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); // Filter for privacy foreach ($rows as $row) { - $source=WT_Source::getInstance($row); - if ($source->canDisplayName()) { - $data[]=$row['s_name']; + $source=WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($source->canShowName()) { + $data[]=$row->s_name; } } echo json_encode($data); @@ -415,36 +415,36 @@ case 'IFSRO': $rows=get_INDI_rows($term); // Filter for privacy foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if ($person->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row['n_full']).', <i>'.$person->getLifeSpan().'</i>'); + $person=WT_Individual::getInstance($row); + if ($person->canShowName()) { + $data[]=array('value'=>$person->getXref(), 'label'=>str_replace(array('@N.N.', '@P.N.'), array($UNKNOWN_NN, $UNKNOWN_PN), $row['n_full']).', <i>'.$person->getLifeSpan().'</i>'); } } // Fetch all data, regardless of privacy $rows=get_SOUR_rows($term); // Filter for privacy foreach ($rows as $row) { - $source=WT_Source::getInstance($row); - if ($source->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>$row['n_full']); + $source=WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($source->canShowName()) { + $data[]=array('value'=>$source->getXref(), 'label'=>$source->getFullName()); } } // Fetch all data, regardless of privacy $rows=get_REPO_rows($term); // Filter for privacy foreach ($rows as $row) { - $repository=WT_Repository::getInstance($row); - if ($repository->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>$row['n_full']); + $repository=WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($repository->canShowName()) { + $data[]=array('value'=>$repository->getXref(), 'label'=>$repository->getFullName()); } } // Fetch all data, regardless of privacy $rows=get_OBJE_rows($term); // Filter for privacy foreach ($rows as $row) { - $media=WT_Media::getInstance($row); - if ($media->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>'<img src="'.$media->getHtmlUrlDirect().'" width="25"> '.$media->getFullName()); + $media=WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($media->canShowName()) { + $data[]=array('value'=>$media->getXref(), 'label'=>'<img src="'.$media->getHtmlUrlDirect().'" width="25"> '.$media->getFullName()); } } // Fetch all data, regardless of privacy @@ -452,7 +452,7 @@ case 'IFSRO': // Filter for privacy foreach ($rows as $row) { $family=WT_Family::getInstance($row); - if ($family->canDisplayName()) { + if ($family->canShowName()) { $marriage_year=$family->getMarriageYear(); if ($marriage_year) { $data[]=array('value'=>$family->getXref(), 'label'=>$family->getFullName().', <i>'.$marriage_year.'</i>'); @@ -465,9 +465,9 @@ case 'IFSRO': $rows=get_NOTE_rows($term); // Filter for privacy foreach ($rows as $row) { - $note=WT_Note::getInstance($row); - if ($note->canDisplayName()) { - $data[]=array('value'=>$row['xref'], 'label'=>$note->getFullName()); + $note=WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($note->canShowName()) { + $data[]=array('value'=>$note->getXref(), 'label'=>$note->getFullName()); } } echo json_encode($data); @@ -493,7 +493,7 @@ function get_FAM_rows($term) { function get_INDI_rows($term) { return WT_DB::prepare( - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec, n_full". + "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". " FROM `##individuals`". " JOIN `##name` ON (i_id=n_id AND i_file=n_file)". " WHERE n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND i_file=? ORDER BY n_full COLLATE '".WT_I18N::$collation."'" @@ -505,20 +505,20 @@ function get_INDI_rows($term) { function get_NOTE_rows($term) { return WT_DB::prepare( - "SELECT o_type AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec, n_full". + "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". " FROM `##other`". " JOIN `##name` ON (o_id=n_id AND o_file=n_file)". " WHERE o_gedcom LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND o_file=? AND o_type='NOTE'". " ORDER BY n_full COLLATE '".WT_I18N::$collation."'" ) ->execute(array($term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); } function get_OBJE_rows($term) { return WT_DB::prepare( - "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename". + "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec". " FROM `##media`". " WHERE (m_titl LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') OR m_id LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%')) AND m_file=?" ) @@ -529,23 +529,23 @@ function get_OBJE_rows($term) { function get_REPO_rows($term) { return WT_DB::prepare( - "SELECT o_type AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec, n_full". + "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". " FROM `##other`". " JOIN `##name` ON (o_id=n_id AND o_file=n_file)". " WHERE n_full LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND o_file=? AND o_type='REPO'". " ORDER BY n_full COLLATE '".WT_I18N::$collation."'" ) ->execute(array($term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); } function get_SOUR_rows($term) { return WT_DB::prepare( - "SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec, s_name AS n_full". + "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom". " FROM `##sources`". " WHERE s_name LIKE CONCAT('%', REPLACE(?, ' ', '%'), '%') AND s_file=? ORDER BY s_name COLLATE '".WT_I18N::$collation."'" ) ->execute(array($term, WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); } diff --git a/branches.php b/branches.php index 832da51f1c..72cc44add7 100644 --- a/branches.php +++ b/branches.php @@ -37,7 +37,7 @@ if (empty($ged)) { $user_ancestors=array(); if (WT_USER_GEDCOM_ID) { - load_ancestors_array(WT_Person::getInstance(WT_USER_GEDCOM_ID), 1); + load_ancestors_array(WT_Individual::getInstance(WT_USER_GEDCOM_ID), 1); } $controller=new WT_Controller_Page(); @@ -77,7 +77,7 @@ $controller if ($surn) { echo '<fieldset><legend><i class="icon-patriarch"></i> ', $surn, '</legend>'; $indis = indis_array($surn, $soundex_std, $soundex_dm); - usort($indis, array('WT_Person', 'CompareBirtDate')); + usort($indis, array('WT_Individual', 'CompareBirtDate')); echo '<ol>'; foreach ($indis as $person) { $famc = $person->getPrimaryChildFamily(); @@ -138,7 +138,7 @@ function print_fams($person, $famid=null) { $person->getLifeSpan().' '.$sosa; if ($famid && $person->getChildFamilyPedigree($famid)) { $sex = $person->getSex(); - $famcrec = get_sub_record(1, '1 FAMC @'.$famid.'@', $person->getGedcomRecord()); + $famcrec = get_sub_record(1, '1 FAMC @'.$famid.'@', $person->getGedcom()); $pedi = get_gedcom_value('PEDI', 2, $famcrec); if ($pedi) { $label = WT_Gedcom_Code_Pedi::getValue($pedi, $person); @@ -196,7 +196,7 @@ function load_ancestors_array($person, $sosa=1) { function indis_array($surn, $soundex_std, $soundex_dm) { $sql= - "SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT DISTINCT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`". " JOIN `##name` ON (i_id=n_id AND i_file=n_file)". " WHERE n_file=?". @@ -219,10 +219,10 @@ function indis_array($surn, $soundex_std, $soundex_dm) { $rows= WT_DB::prepare($sql) ->execute($args) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); $data=array(); foreach ($rows as $row) { - $data[]=WT_Person::getInstance($row); + $data[]=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $data; } diff --git a/calendar.php b/calendar.php index c8d640912a..7c86b7ca69 100644 --- a/calendar.php +++ b/calendar.php @@ -544,7 +544,7 @@ function apply_filter($facts, $filterof, $filtersx) { if ($filterof=='recent' && $fact['date']->MaxJD()<$hundred_years) continue; // Finally, check for privacy rules before adding fact. - if ($tmp->canDisplayDetails()) + if ($tmp->canShow()) $filtered[]=$fact; } return $filtered; @@ -572,7 +572,7 @@ function calendar_list_text($list, $tag1, $tag2, $show_sex_symbols) { foreach ($list as $id=>$facts) { $tmp=WT_GedcomRecord::GetInstance($id); echo $tag1, '<a href="', $tmp->getHtmlUrl(), '">', $tmp->getFullName(), '</a> '; - if ($show_sex_symbols && $tmp instanceof WT_Person) + if ($show_sex_symbols && $tmp instanceof WT_Individual) switch ($tmp->getSex()) { case 'M': echo '<i class="icon-sex_m_9x9" title="', WT_I18N::translate('Male'), '"></i>'; diff --git a/edit_changes.php b/edit_changes.php index 76f98e12ab..8c02dd94b5 100644 --- a/edit_changes.php +++ b/edit_changes.php @@ -2,7 +2,7 @@ // Interface to moderate pending changes. // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2103 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -158,12 +158,10 @@ if ($changed_gedcoms) { // This prevents us from displaying it... // This generates a record of some sorts from the last-but-one // version of the record. - $record=new WT_GedcomRecord($change->gedcom); + $record=new WT_GedcomRecord($change->xref, $change->gedcom, null, $change->gedcom_id); } $output.='<b>'.$record->getFullName().'</b><br>'; $output.='<a href="#" onclick="return show_diff(\''.$record->getHtmlUrl().'\');">'.WT_I18N::translate('View the changes').'</a> | '; - $output.="<a href=\"#\" onclick=\"show_gedcom_record('".$change->xref."');\">".WT_I18N::translate('View GEDCOM Record')."</a> | "; - $output.="<a href=\"#\" onclick=\"return edit_raw('".$change->xref."');\">".WT_I18N::translate('Edit raw GEDCOM record').'</a><br>'; $output.='<div class="indent">'; $output.=WT_I18N::translate('The following changes were made to this record:').'<br>'; $output.='<table class="list_table"><tr>'; diff --git a/edit_interface.php b/edit_interface.php index f5692096f0..04da100da8 100644 --- a/edit_interface.php +++ b/edit_interface.php @@ -27,57 +27,23 @@ define('WT_SCRIPT_NAME', 'edit_interface.php'); require './includes/session.php'; require WT_ROOT.'includes/functions/functions_edit.php'; +$action = safe_REQUEST($_REQUEST, 'action'); + $controller=new WT_Controller_Simple(); $controller - ->requireMemberLogin() - ->addExternalJavascript(WT_STATIC_URL.'js/autocomplete.js'); - -// TODO work out whether to use GET/POST for these -// TODO decide what (if any) validation is required on these parameters -$action =safe_REQUEST($_REQUEST, 'action', WT_REGEX_UNSAFE); -$linenum=safe_REQUEST($_REQUEST, 'linenum', WT_REGEX_UNSAFE); -$pid =safe_REQUEST($_REQUEST, 'pid', WT_REGEX_XREF); -$famid =safe_REQUEST($_REQUEST, 'famid', WT_REGEX_XREF); -$text =safe_REQUEST($_REQUEST, 'text', WT_REGEX_UNSAFE); -$tag =safe_REQUEST($_REQUEST, 'tag', WT_REGEX_UNSAFE); -$famtag =safe_REQUEST($_REQUEST, 'famtag', WT_REGEX_UNSAFE); -$glevels=safe_REQUEST($_REQUEST, 'glevels', WT_REGEX_UNSAFE); -$islink =safe_REQUEST($_REQUEST, 'islink', WT_REGEX_UNSAFE); -$type =safe_REQUEST($_REQUEST, 'type', WT_REGEX_UNSAFE); -$fact =safe_REQUEST($_REQUEST, 'fact', WT_REGEX_UNSAFE); -$option =safe_REQUEST($_REQUEST, 'option', WT_REGEX_UNSAFE); - -$assist =safe_REQUEST($_REQUEST, 'assist', WT_REGEX_UNSAFE); -$noteid =safe_REQUEST($_REQUEST, 'noteid', WT_REGEX_UNSAFE); - -$pid_array =safe_REQUEST($_REQUEST, 'pid_array', WT_REGEX_XREF); -$pids_array_add =safe_REQUEST($_REQUEST, 'pids_array_add', WT_REGEX_XREF); -$pids_array_edit=safe_REQUEST($_REQUEST, 'pids_array_edit', WT_REGEX_XREF); - -$update_CHAN=!safe_POST_bool('preserve_last_changed'); - -$uploaded_files = array(); - -$controller->addInlineJavascript(' + ->requireEditorLogin() + ->addExternalJavascript(WT_STATIC_URL.'js/autocomplete.js') + ->addInlineJavascript(' var locale_date_format="' . preg_replace('/[^DMY]/', '', str_replace(array('J', 'F'), array('D', 'M'), strtoupper($DATE_FORMAT))). '"; -'); - -$controller->addInlineJavascript(' function openerpasteid(id) { if (window.opener.paste_id) { window.opener.paste_id(id); } window.close(); } -'); - -$controller->addInlineJavascript(' function paste_id(value) { pastefield.value = value; } -'); - -$controller->addInlineJavascript(' function paste_char(value) { if (document.selection) { // IE @@ -102,84 +68,29 @@ $controller->addInlineJavascript(' } '); -//-- check if user has access to the gedcom record -$edit = false; - -if (!empty($pid)) { - if (($pid!="newsour") && ($pid!="newrepo") && ($noteid!="newnote")) { - $gedrec = find_gedcom_record($pid, WT_GED_ID, true); - $ct = preg_match("/^0 @$pid@ (.*)/i", $gedrec, $match); - if ($ct>0) { - $type = trim($match[1]); - $tmp = WT_GedcomRecord::getInstance($pid); - $edit = $tmp->canDisplayDetails() && $tmp->canEdit(); - } - // Don't allow edits if the record has changed since the edit-link was created - checkChangeTime($pid, $gedrec, safe_GET('accesstime', WT_REGEX_INTEGER)); - } else { - $edit = true; - } -} elseif (!empty($famid)) { - if ($famid != "new") { - $gedrec = find_gedcom_record($famid, WT_GED_ID, true); - $ct = preg_match("/^0 @$famid@ (.*)/i", $gedrec, $match); - if ($ct>0) { - $type = trim($match[1]); - $tmp = WT_GedcomRecord::getInstance($famid); - $edit = $tmp->canDisplayDetails() && $tmp->canEdit(); - } - // Don't allow edits if the record has changed since the edit-link was created - checkChangeTime($famid, $gedrec, safe_GET('accesstime', WT_REGEX_INTEGER)); - } -} else { - $edit = true; -} - -if (!WT_USER_CAN_EDIT || !$edit) { - $controller - ->pageHeader() - ->addInlineJavascript('closePopupAndReloadParent();'); - exit; -} - -$level0type = $type; - switch ($action) { //////////////////////////////////////////////////////////////////////////////// -case 'delete': - $controller - ->setPageTitle(WT_I18N::translate('Delete')) - ->pageHeader(); - - // Retrieve the private data - $record = new WT_GedcomRecord($gedrec); - list($gedcom, $private_gedrec)=$record->privatizeGedcom(WT_USER_ACCESS_LEVEL); - - // When deleting a media link, $linenum comes is an OBJE and the $mediaid to delete should be set - if ($linenum=='OBJE') { - $newged = remove_media_subrecord($gedrec, $_REQUEST['mediaid']); - } else { - $newged = remove_subline($gedrec, $linenum); - } - $success = replace_gedrec($pid, WT_GED_ID, $newged.$private_gedrec, $update_CHAN); - - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } - break; - -//////////////////////////////////////////////////////////////////////////////// case 'editraw': - $pid = safe_GET('pid', WT_REGEX_XREF); // print_indi_form() uses this - $record = WT_GedcomRecord::getInstance($pid); + $xref = safe_GET('xref', WT_REGEX_XREF); + $fact_id = safe_GET('fact_id'); - // Hide the private data - list($gedrec)=$record->privatizeGedcom(WT_USER_ACCESS_LEVEL); + $record = WT_GedcomRecord::getInstance($xref); + check_record_access($record); - // Remove the first line of the gedrec - things go wrong when users change either the TYPE or XREF - // Notes are special - they may contain data on the first line - $gedrec=preg_replace('/^(0 @'.WT_REGEX_XREF.'@ NOTE) (.+)/', "$1\n1 CONC $2", $gedrec); - list($gedrec1, $gedrec2)=explode("\n", $gedrec, 2); + // Find the fact to edit + $edit_fact = null; + foreach ($record->getFacts() as $fact) { + if ($fact->getFactId() == $fact_id && $fact->canShow() && $fact->canEdit()) { + $edit_fact = $fact; + break; + } + } + if (!$edit_fact) { + $controller + ->pageHeader() + ->addInlineJavascript('closePopupAndReloadParent();'); + exit; + } $controller ->setPageTitle($record->getFullName() . ' - ' . WT_I18N::translate('Edit raw GEDCOM record')) @@ -190,16 +101,15 @@ case 'editraw': <h4> <?php echo $controller->getPageTitle(); ?> <?php echo help_link('edit_edit_raw'); ?> - <?php print_specialchar_link('newgedrec2'); ?> + <?php print_specialchar_link('gedcom'); ?> </h4> <form method="post" action="edit_interface.php"> <input type="hidden" name="action" value="updateraw"> - <input type="hidden" name="pid" value="<?php echo $pid; ?>"> - <textarea name="newgedrec1" id="newgedrec1" dir="ltr" readonly="readonly"><?php echo htmlspecialchars($gedrec1); ?></textarea> - <br> - <textarea name="newgedrec2" id="newgedrec2" dir="ltr"><?php echo htmlspecialchars($gedrec2); ?></textarea> + <input type="hidden" name="xref" value="<?php echo $xref; ?>"> + <input type="hidden" name="fact_id" value="<?php echo $fact_id; ?>"> + <textarea name="gedcom" id="gedcom" dir="ltr"><?php echo htmlspecialchars($edit_fact->getGedcom()); ?></textarea> <br> - <?php echo no_update_chan($record); ?> + <?php echo keep_chan($record); ?> <p id="save-cancel"> <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> @@ -210,43 +120,84 @@ case 'editraw': break; //////////////////////////////////////////////////////////////////////////////// +case 'updateraw': + $xref = safe_POST('xref', WT_REGEX_XREF); + $fact_id = safe_POST('fact_id'); + $gedcom = safe_POST('gedcom', WT_REGEX_UNSAFE); + $keep_chan = safe_POST_bool('keep_chan'); + + $record = WT_GedcomRecord::getInstance($xref); + check_record_access($record); + + // Find the fact to edit + $edit_fact = null; + foreach ($record->getFacts() as $fact) { + if ($fact->getFactId() == $fact_id && $fact->canShow() && $fact->canEdit()) { + $edit_fact = $fact; + break; + } + } + if (!$edit_fact) { + $controller + ->pageHeader() + ->addInlineJavascript('closePopupAndReloadParent();'); + exit; + } + + $controller + ->setPageTitle($record->getFullName() . ' - ' . WT_I18N::translate('Edit raw GEDCOM record')) + ->pageHeader(); + + // Cleanup the client’s bad editing? + $gedcom = preg_replace('/\n\n+/', "\n", $gedcom); // Empty lines + $gedcom = trim($gedcom); // Leading/trailing spaces + + $record->updateRecord($gedcom, !$keep_chan); + + $controller->addInlineJavascript('closePopupAndReloadParent();'); + break; + +//////////////////////////////////////////////////////////////////////////////// case 'edit': - $pid = safe_GET('pid', WT_REGEX_XREF); - $record = WT_GedcomRecord::getInstance($pid); + $xref = safe_GET('xref', WT_REGEX_XREF); + $fact_id = safe_GET('fact_id'); + + $record = WT_GedcomRecord::getInstance($xref); + check_record_access($record); + + // Find the fact to edit + $edit_fact = null; + foreach ($record->getFacts() as $fact) { + if ($fact->getFactId() == $fact_id && $fact->canShow() && $fact->canEdit()) { + $edit_fact = $fact; + break; + } + } + if (!$edit_fact) { + $controller + ->pageHeader() + ->addInlineJavascript('closePopupAndReloadParent();'); + exit; + } $controller ->setPageTitle($record->getFullName() . ' - ' . WT_I18N::translate('Edit')) ->pageHeader(); - // Hide the private data - list($gedrec)=$record->privatizeGedcom(WT_USER_ACCESS_LEVEL); - echo '<div id="edit_interface-page">'; echo '<h4>', $controller->getPageTitle(), '</h4>'; init_calendar_popup(); echo '<form name="editform" method="post" action="edit_interface.php" enctype="multipart/form-data">'; echo '<input type="hidden" name="action" value="update">'; - echo '<input type="hidden" name="linenum" value="', $linenum, '">'; - echo '<input type="hidden" name="pid" value="', $pid, '">'; - echo '<input type="hidden" id="pids_array_edit" name="pids_array_edit" value="no_array">'; - + echo '<input type="hidden" name="fact_id" value="', $fact_id, '">'; + echo '<input type="hidden" name="xref" value="', $xref, '">'; echo '<table class="facts_table">'; - $level1type = create_edit_form($gedrec, $linenum, $level0type); - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $record->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $record->LastChangeUser()); - echo '</td></tr>'; - } + create_edit_form($edit_fact); + echo keep_chan($record); echo '</table>'; - switch ($level0type) { + + $level1type = $edit_fact->getTag(); + switch ($record::RECORD_TYPE) { case 'OBJE': case 'NOTE': // OBJE and NOTE "facts" are all special, and none can take lower-level links @@ -287,6 +238,12 @@ case 'edit': } break; } + if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { + echo + '<br><br><a href="edit_interface.php?action=editraw&xref=', $xref, '&fact_id=', $fact_id, '&ged=', WT_GEDURL, '">', + WT_I18N::translate('Edit raw GEDCOM record'), + '</a>'; + } ?> <p id="save-cancel"> <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> @@ -299,40 +256,30 @@ case 'edit': //////////////////////////////////////////////////////////////////////////////// case 'add': - $pid = safe_GET('pid', WT_REGEX_XREF); - $fact = safe_GET('fact', WT_REGEX_TAG); - $record = WT_GedcomRecord::getInstance($pid); + $xref = safe_GET('xref', WT_REGEX_XREF); + $fact = safe_GET('fact', WT_REGEX_TAG); + + $record = WT_GedcomRecord::getInstance($xref); + check_record_access($record); $controller ->setPageTitle($record->getFullName() . ' - ' . WT_Gedcom_Tag::getLabel($fact, $record)) ->pageHeader(); + $level0type = $record::RECORD_TYPE; + echo '<div id="edit_interface-page">'; echo '<h4>', $controller->getPageTitle(), '</h4>'; init_calendar_popup(); echo '<form name="addform" method="post" action="edit_interface.php" enctype="multipart/form-data">'; echo '<input type="hidden" name="action" value="update">'; - echo '<input type="hidden" name="linenum" value="new">'; - echo '<input type="hidden" name="pid" value="', $pid, '">'; - echo '<input type="hidden" id="pids_array_add" name="pids_array_add" value="no_array">'; + echo '<input type="hidden" name="xref" value="', $xref, '">'; echo '<table class="facts_table">'; create_add_form($fact); - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $record->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $record->LastChangeUser()); - echo '</td></tr>'; - } + echo keep_chan($record); echo '</table>'; // Genealogical facts (e.g. for INDI and FAM records) can have 2 SOUR/NOTE/OBJE/ASSO/RESN ... @@ -365,31 +312,118 @@ case 'add': break; //////////////////////////////////////////////////////////////////////////////// +case 'update': + // Update a fact + $xref = safe_POST('xref', WT_REGEX_XREF); + $fact_id = safe_POST('fact_id'); + + $record = WT_GedcomRecord::getInstance($xref); + check_record_access($record); + + // Arrays for each GEDCOM line + $glevels = safe_POST('glevels'); + $tag = safe_POST('tag', WT_REGEX_TAG); + $text = safe_POST('text', WT_REGEX_UNSAFE); + $islink = safe_POST('islink'); + + $controller + ->setPageTitle(WT_I18N::translate('Edit')) + ->pageHeader(); + + // If the fact has a DATE or PLAC, then delete any value of Y + if ($text[0]=='Y') { + for ($n=1; $n<count($tag); ++$n) { + if ($glevels[$n]==2 && ($tag[$n]=='DATE' || $tag[$n]=='PLAC') && $text[$n]) { + $text[0]=''; + break; + } + } + } + + //-- check for photo update + if (count($_FILES)>0) { + if (isset($_REQUEST['folder'])) $folder = $_REQUEST['folder']; + $uploaded_files = array(); + if (substr($folder, 0, 1) == "/") $folder = substr($folder, 1); + if (substr($folder, -1, 1) != "/") $folder .= "/"; + foreach ($_FILES as $upload) { + if (!empty($upload['tmp_name'])) { + if (!move_uploaded_file($upload['tmp_name'], $MEDIA_DIRECTORY.$folder.basename($upload['name']))) { + $error .= "<br>".WT_I18N::translate('There was an error uploading your file.')."<br>".file_upload_error_text($upload['error']); + $uploaded_files[] = ""; + } else { + $filename = $MEDIA_DIRECTORY.$folder.basename($upload['name']); + $uploaded_files[] = $MEDIA_DIRECTORY.$folder.basename($upload['name']); + if (!is_dir($MEDIA_DIRECTORY."thumbs/".$folder)) mkdir($MEDIA_DIRECTORY."thumbs/".$folder); + $thumbnail = $MEDIA_DIRECTORY."thumbs/".$folder.basename($upload['name']); + generate_thumbnail($filename, $thumbnail); + if (!empty($error)) { + echo "<span class=\"error\">", $error, "</span>"; + } + } + } else { + $uploaded_files[] = ""; + } + } + } + + $newged = ""; + if (!empty($_POST['NAME'])) $newged .= "\n1 NAME " . $_POST['NAME']; + if (!empty($_POST['TYPE'])) $newged .= "\n2 TYPE " . $_POST['TYPE']; + if (!empty($_POST['NPFX'])) $newged .= "\n2 NPFX " . $_POST['NPFX']; + if (!empty($_POST['GIVN'])) $newged .= "\n2 GIVN " . $_POST['GIVN']; + if (!empty($_POST['NICK'])) $newged .= "\n2 NICK " . $_POST['NICK']; + if (!empty($_POST['SPFX'])) $newged .= "\n2 SPFX " . $_POST['SPFX']; + if (!empty($_POST['SURN'])) $newged .= "\n2 SURN " . $_POST['SURN']; + if (!empty($_POST['NSFX'])) $newged .= "\n2 NSFX " . $_POST['NSFX']; + if (!empty($_POST['ROMN'])) $newged .= "\n2 ROMN " . $_POST['ROMN']; + if (!empty($_POST['FONE'])) $newged .= "\n2 FONE " . $_POST['FONE']; + if (!empty($_POST['_HEB'])) $newged .= "\n2 _HEB " . $_POST['_HEB']; + if (!empty($_POST['_AKA'])) $newged .= "\n2 _AKA " . $_POST['_AKA']; + if (!empty($_POST['_MARNM'])) $newged .= "\n2 _MARNM " . $_POST['_MARNM']; + + if (isset($_POST['NOTE'])) $NOTE = $_POST['NOTE']; + if (!empty($NOTE)) { + $tempnote = preg_split('/\r?\n/', trim($NOTE) . "\n"); // make sure only one line ending on the end + $title[] = "0 @$xref@ NOTE " . array_shift($tempnote); + foreach($tempnote as &$line) { + $line = trim("1 CONT " . $line,' '); + } + } + + $newged = handle_updates($newged); + $newged = substr($newged, 1); // Remove leading newline + $record->updateFact($fact_id, $newged, $update_CHAN); + + $controller->addInlineJavascript('closePopupAndReloadParent();'); + break; + +//////////////////////////////////////////////////////////////////////////////// case 'addchild': $gender = safe_GET('gender', '[MF]', 'U'); $famid = safe_GET('famid', WT_REGEX_XREF); - $pid = safe_GET('pid', WT_REGEX_XREF); // print_indi_form() uses this + $family = WT_Family::getInstance($famid); if ($family) { + check_record_access($family); $controller->setPageTitle($family->getFullName() . ' - ' . WT_I18N::translate('Add a new child')); } else { $controller->setPageTitle(WT_I18N::translate('Add an unlinked person')); } $controller->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - print_indi_form('addchildaction', $famid, '', '', 'CHIL', $gender); - - echo '</div><!-- id="edit_interface-page" -->'; + print_indi_form('addchildaction', null, $family, null, 'CHIL', $gender); break; //////////////////////////////////////////////////////////////////////////////// case 'addspouse': $famtag = safe_GET('famtag', '(HUSB|WIFE)'); - $famid = safe_GET('famid', WT_REGEX_XREF); + $xref = safe_GET('xref', WT_REGEX_XREF); + + $person = WT_Individual::getInstance($xref); + + check_record_access($person); if ($famtag=='WIFE') { $controller->setPageTitle(WT_I18N::translate('Add a new wife')); @@ -398,20 +432,21 @@ case 'addspouse': } $controller->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - print_indi_form('addspouseaction', $famid, '', '', $famtag); - - echo '</div><!-- id="edit_interface-page" -->'; + print_indi_form('addspouseaction', $person, null, null, $famtag); break; //////////////////////////////////////////////////////////////////////////////// case 'addnewparent': + $xref = safe_GET('xref', WT_REGEX_XREF); $famtag = safe_GET('famtag', '(HUSB|WIFE)'); $famid = safe_GET('famid', WT_REGEX_XREF); - $pid = safe_GET('pid', WT_REGEX_XREF); // print_indi_form() uses this - $person = WT_Person::getInstance($pid); + + $person = WT_Individual::getInstance($xref); + $family = WT_Family::getInstance($famid); + check_record_access($person); + if ($family) { + check_record_access($family); + } if ($person) { // Adding a parent to an individual @@ -428,81 +463,50 @@ case 'addnewparent': } $controller->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - print_indi_form('addnewparentaction', $famid, '', '', $famtag); - - echo '</div><!-- id="edit_interface-page" -->'; + print_indi_form('addnewparentaction', $person, $family, null, $famtag, $person->getSex()); break; //////////////////////////////////////////////////////////////////////////////// case 'addopfchild': - $pid = safe_GET('pid', WT_REGEX_XREF); - $famid = safe_GET('famid', WT_REGEX_XREF); - $person = WT_Person::getInstance($pid); + $pid = safe_GET('pid', WT_REGEX_XREF); + + $person = WT_Individual::getInstance($pid); + check_record_access($person); $controller ->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Add a child to create a one-parent family')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - print_indi_form('addopfchildaction', $famid, '', '', 'CHIL'); - - echo '</div><!-- id="edit_interface-page" -->'; + print_indi_form('addopfchildaction', $person, null, null, 'CHIL', $person->getSex()); break; //////////////////////////////////////////////////////////////////////////////// case 'addfamlink': - $person=WT_Person::getInstance($pid); - - if ($famtag=='CHIL') { - $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a child')); - } elseif ($person->getSex()=='F') { - $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a wife')); - } else { - $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a husband')); - } + $xref = safe_GET('xref', WT_REGEX_XREF); - $controller->pageHeader(); + $person = WT_Individual::getInstance($xref); + check_record_access($person); + + $controller + ->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a child')) + ->pageHeader(); echo '<div id="edit_interface-page">'; echo '<h4>', $controller->getPageTitle(), '</h4>'; echo '<form method="post" name="addchildform" action="edit_interface.php">'; echo '<input type="hidden" name="action" value="linkfamaction">'; - echo '<input type="hidden" name="pid" value="', $pid, '">'; - echo '<input type="hidden" name="famtag" value="', $famtag, '">'; + echo '<input type="hidden" name="xref" value="', $person->getXref(), '">'; echo '<table class="facts_table">'; echo '<tr><td class="facts_label">', WT_I18N::translate('Family'), '</td>'; echo '<td class="facts_value"><input type="text" id="famid" name="famid" size="8"> '; echo print_findfamily_link('famid'); echo '</td></tr>'; - if ($famtag=='CHIL') { - echo '<tr><td class="facts_label">', WT_Gedcom_Tag::getLabel('PEDI'), '</td><td class="facts_value">'; - switch ($person->getSex()) { - case 'M': echo edit_field_pedi_m('PEDI'); break; - case 'F': echo edit_field_pedi_f('PEDI'); break; - case 'U': echo edit_field_pedi_u('PEDI'); break; - } - echo help_link('PEDI'); - echo '</td></tr>'; - } - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $person->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $person->LastChangeUser()); - echo '</td></tr>'; - } + echo '<tr><td class="facts_label">', WT_Gedcom_Tag::getLabel('PEDI'), '</td><td class="facts_value">'; + echo edit_field_pedi('PEDI', '', '', $person); + echo help_link('PEDI'); + echo '</td></tr>'; + echo keep_chan($person); echo '</table>'; ?> <p id="save-cancel"> @@ -516,7 +520,11 @@ case 'addfamlink': //////////////////////////////////////////////////////////////////////////////// case 'linkspouse': - $person=WT_Person::getInstance($pid); + $famtag = safe_GET('famtag', '(HUSB|WIFE)'); + $pid = safe_GET('pid', WT_REGEX_XREF); + + $person = WT_Individual::getInstance($pid); + check_record_access($person); if ($person->getSex()=='F') { $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Add a husband using an existing person')); @@ -528,12 +536,10 @@ case 'linkspouse': echo '<div id="edit_interface-page">'; echo '<h4>', $controller->getPageTitle(), '</h4>'; - init_calendar_popup(); echo '<form method="post" name="addchildform" action="edit_interface.php">'; echo '<input type="hidden" name="action" value="linkspouseaction">'; - echo '<input type="hidden" name="pid" value="', $pid, '">'; - echo '<input type="hidden" name="famid" value="new">'; + echo '<input type="hidden" name="xref" value="', $person->getXref(), '">'; echo '<input type="hidden" name="famtag" value="', $famtag, '">'; echo '<table class="facts_table">'; echo '<tr><td class="facts_label">'; @@ -549,19 +555,7 @@ case 'linkspouse': add_simple_tag("0 MARR Y"); add_simple_tag("0 DATE", "MARR"); add_simple_tag("0 PLAC", "MARR"); - if (WT_USER_IS_ADMIN) { - echo "<tr><td class=\"descriptionbox wrap width25\">"; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $person->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $person->LastChangeUser()); - echo '</td></tr>'; - } + echo keep_chan($person); echo '</table>'; print_add_layer("SOUR"); print_add_layer("OBJE"); @@ -583,83 +577,44 @@ case 'linkspouse': //////////////////////////////////////////////////////////////////////////////// case 'linkfamaction': - $person=WT_Person::getInstance($pid); - - if ($famtag=='CHIL') { - $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a child')); - } elseif ($person->getSex()=='F') { - $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a wife')); - } else { - $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a husband')); - } + $xref = safe_POST('xref', WT_REGEX_XREF); + $famid = safe_POST('famid', WT_REGEX_XREF); + $PEDI = safe_POST('PEDI'); - $controller->pageHeader(); - - // Make sure we have the right ID (f123 vs. F123) - $famid=WT_Family::getInstance($famid)->getXref(); - $famrec = find_gedcom_record($famid, WT_GED_ID, true); - $success=false; - if (!empty($famrec)) { - $itag = "FAMC"; - if ($famtag=="HUSB" || $famtag=="WIFE") $itag="FAMS"; + $person = WT_Individual::getInstance($xref); + $family = WT_Family::getInstance($famid); + check_record_access($person); + check_record_access($family); + + $controller + ->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Link this person to an existing family as a child')) + ->pageHeader(); - //-- update the individual record for the person - if (strpos($gedrec, "1 $itag @$famid@")===false) { - switch ($itag) { - case 'FAMC': - if (isset($_REQUEST['PEDI'])) { - $PEDI = $_REQUEST['PEDI']; - } else { - $PEDI=''; - } - $gedrec.="\n".WT_Gedcom_Code_Pedi::createNewFamcPedi($PEDI, $famid); - break; - case 'FAMS': - $gedrec.="\n1 FAMS @$famid@"; - break; - } - $success=replace_gedrec($pid, WT_GED_ID, $gedrec, $update_CHAN); + // Replace any existing child->family link (we may be changing the PEDI); + $fact_id = null; + foreach ($person->getFacts('FAMC') as $fact) { + if ($family->equals($fact->getTarget())) { + $fact_id = $fact->getFactId(); + break; } + } - //-- if it is adding a new child to a family - if ($famtag=="CHIL") { - if (strpos($famrec, "1 $famtag @$pid@")===false) { - $famrec .= "\n1 $famtag @$pid@"; - $success=replace_gedrec($famid, WT_GED_ID, $famrec, $update_CHAN); - } - } else { - //-- if it is adding a husband or wife - //-- check if the family already has a HUSB or WIFE - $ct = preg_match("/1 $famtag @(.*)@/", $famrec, $match); - if ($ct>0) { - //-- get the old ID - $spid = trim($match[1]); - //-- only continue if the old husb/wife is not the same as the current one - if ($spid!=$pid) { - //-- change a of the old ids to the new id - $famrec = str_replace("\n1 $famtag @$spid@", "\n1 $famtag @$pid@", $famrec); - $success=replace_gedrec($famid, WT_GED_ID, $famrec, $update_CHAN); - //-- remove the FAMS reference from the old husb/wife - if (!empty($spid)) { - $srec = find_gedcom_record($spid, WT_GED_ID, true); - if ($srec) { - $srec = str_replace("\n1 $itag @$famid@", "", $srec); - $success=replace_gedrec($spid, WT_GED_ID, $srec, $update_CHAN); - } - } - } - } else { - $famrec .= "\n1 $famtag @$pid@"; - $success=replace_gedrec($famid, WT_GED_ID, $famrec, $update_CHAN); - } + $gedcom = WT_Gedcom_Code_Pedi::createNewFamcPedi($PEDI, $famid); + $person->updateFact($fact_id, $gedcom, true); + + // Only set the family->child link if it does not already exist + $edit_fact = null; + foreach ($family->getFacts('CHIL') as $fact) { + if ($person->equals($fact->getTarget())) { + $edit_fact = $fact; + break; } - } else { - echo "Family record not found"; } - - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); + if (!$edit_fact) { + $family->updateFact(null, '1 CHIL @' . $person->getXref() . '@', true); } + + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// @@ -668,11 +623,8 @@ case 'addnewsource': ->setPageTitle(WT_I18N::translate('Create a new source')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - echo '<script>'; ?> + <script> function check_form(frm) { if (frm.TITL.value=="") { alert('<?php echo WT_I18N::translate('You must provide a source title'); ?>'); @@ -681,80 +633,68 @@ case 'addnewsource': } return true; } - <?php - echo '</script>'; - ?> - <form method="post" action="edit_interface.php" onsubmit="return check_form(this);"> - <input type="hidden" name="action" value="addsourceaction"> - <input type="hidden" name="pid" value="newsour"> - <table class="facts_table"> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('TITL'); ?></td> - <td class="optionbox wrap"><input type="text" name="TITL" id="TITL" value="" size="60"> <?php echo print_specialchar_link('TITL'); ?></td></tr> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('ABBR'); ?></td> - <td class="optionbox wrap"><input type="text" name="ABBR" id="ABBR" value="" size="40" maxlength="255"> <?php echo print_specialchar_link('ABBR'); ?></td></tr> - <?php if (strstr($ADVANCED_NAME_FACTS, "_HEB")!==false) { ?> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('_HEB'), help_link('_HEB'); ?></td> - <td class="optionbox wrap"><input type="text" name="_HEB" id="_HEB" value="" size="60"> <?php echo print_specialchar_link('_HEB'); ?></td></tr> - <?php } ?> - <?php if (strstr($ADVANCED_NAME_FACTS, "ROMN")!==false) { ?> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('ROMN'), help_link('ROMN'); ?></td> - <td class="optionbox wrap"><input type="text" name="ROMN" id="ROMN" value="" size="60"> <?php echo print_specialchar_link('ROMN'); ?></td></tr> - <?php } ?> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('AUTH'); ?></td> - <td class="optionbox wrap"><input type="text" name="AUTH" id="AUTH" value="" size="40" maxlength="255"> <?php echo print_specialchar_link('AUTH'); ?></td></tr> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('PUBL'); ?></td> - <td class="optionbox wrap"><textarea name="PUBL" id="PUBL" rows="5" cols="60"></textarea><br><?php echo print_specialchar_link('PUBL'); ?></td></tr> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('REPO'); ?></td> - <td class="optionbox wrap"><input type="text" name="REPO" id="REPO" value="" size="10"> <?php echo print_findrepository_link('REPO'), ' ', print_addnewrepository_link('REPO'); ?></td></tr> - <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('CALN'); ?></td> - <td class="optionbox wrap"><input type="text" name="CALN" id="CALN" value=""></td></tr> - <?php - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo '</td></tr>'; - } - ?> - </table> - <a href="#" onclick="return expand_layer('events');"><i id="events_img" class="icon-plus"></i> - <?php echo WT_I18N::translate('Associate events with this source'); ?></a><?php echo help_link('edit_SOUR_EVEN'); ?> - <div id="events" style="display: none;"> + </script> + <div id="edit_interface-page"> + <h4><?php echo $controller->getPageTitle(); ?></h4> + <form method="post" action="edit_interface.php" onsubmit="return check_form(this);"> + <input type="hidden" name="action" value="addsourceaction"> + <input type="hidden" name="xref" value="newsour"> <table class="facts_table"> - <tr> - <td class="descriptionbox wrap width25"><?php echo WT_I18N::translate('Select Events'), help_link('edit_SOUR_EVEN'); ?></td> - <td class="optionbox wrap"><select name="EVEN[]" multiple="multiple" size="5"> - <?php - $parts = explode(',', get_gedcom_setting(WT_GED_ID, 'INDI_FACTS_ADD')); - foreach ($parts as $key) { - ?><option value="<?php echo $key; ?>"><?php echo WT_Gedcom_Tag::getLabel($key); ?></option> - <?php - } - $parts = explode(',', get_gedcom_setting(WT_GED_ID, 'FAM_FACTS_ADD')); - foreach ($parts as $key) { - ?><option value="<?php echo $key; ?>"><?php echo WT_Gedcom_Tag::getLabel($key); ?></option> - <?php - } - ?> - </select></td> - </tr> - <?php - add_simple_tag('0 DATE', 'EVEN'); - add_simple_tag('0 PLAC', 'EVEN'); - add_simple_tag('0 AGNC'); - ?> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('TITL'); ?></td> + <td class="optionbox wrap"><input type="text" name="TITL" id="TITL" value="" size="60"> <?php echo print_specialchar_link('TITL'); ?></td></tr> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('ABBR'); ?></td> + <td class="optionbox wrap"><input type="text" name="ABBR" id="ABBR" value="" size="40" maxlength="255"> <?php echo print_specialchar_link('ABBR'); ?></td></tr> + <?php if (strstr($ADVANCED_NAME_FACTS, "_HEB")!==false) { ?> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('_HEB'), help_link('_HEB'); ?></td> + <td class="optionbox wrap"><input type="text" name="_HEB" id="_HEB" value="" size="60"> <?php echo print_specialchar_link('_HEB'); ?></td></tr> + <?php } ?> + <?php if (strstr($ADVANCED_NAME_FACTS, "ROMN")!==false) { ?> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('ROMN'), help_link('ROMN'); ?></td> + <td class="optionbox wrap"><input type="text" name="ROMN" id="ROMN" value="" size="60"> <?php echo print_specialchar_link('ROMN'); ?></td></tr> + <?php } ?> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('AUTH'); ?></td> + <td class="optionbox wrap"><input type="text" name="AUTH" id="AUTH" value="" size="40" maxlength="255"> <?php echo print_specialchar_link('AUTH'); ?></td></tr> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('PUBL'); ?></td> + <td class="optionbox wrap"><textarea name="PUBL" id="PUBL" rows="5" cols="60"></textarea><br><?php echo print_specialchar_link('PUBL'); ?></td></tr> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('REPO'); ?></td> + <td class="optionbox wrap"><input type="text" name="REPO" id="REPO" value="" size="10"> <?php echo print_findrepository_link('REPO'), ' ', print_addnewrepository_link('REPO'); ?></td></tr> + <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('CALN'); ?></td> + <td class="optionbox wrap"><input type="text" name="CALN" id="CALN" value=""></td></tr> + <?php echo $keep_chan(); ?> </table> - </div> - <p id="save-cancel"> - <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> - </p> - </form> + <a href="#" onclick="return expand_layer('events');"><i id="events_img" class="icon-plus"></i> + <?php echo WT_I18N::translate('Associate events with this source'); ?></a><?php echo help_link('edit_SOUR_EVEN'); ?> + <div id="events" style="display: none;"> + <table class="facts_table"> + <tr> + <td class="descriptionbox wrap width25"><?php echo WT_I18N::translate('Select Events'), help_link('edit_SOUR_EVEN'); ?></td> + <td class="optionbox wrap"><select name="EVEN[]" multiple="multiple" size="5"> + <?php + $parts = explode(',', get_gedcom_setting(WT_GED_ID, 'INDI_FACTS_ADD')); + foreach ($parts as $key) { + ?><option value="<?php echo $key; ?>"><?php echo WT_Gedcom_Tag::getLabel($key); ?></option> + <?php + } + $parts = explode(',', get_gedcom_setting(WT_GED_ID, 'FAM_FACTS_ADD')); + foreach ($parts as $key) { + ?><option value="<?php echo $key; ?>"><?php echo WT_Gedcom_Tag::getLabel($key); ?></option> + <?php + } + ?> + </select></td> + </tr> + <?php + add_simple_tag('0 DATE', 'EVEN'); + add_simple_tag('0 PLAC', 'EVEN'); + add_simple_tag('0 AGNC'); + ?> + </table> + </div> + <p id="save-cancel"> + <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> + <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> + </p> + </form> </div><!-- id="edit_interface-page" --> <?php break; @@ -802,10 +742,8 @@ case 'addsourceaction': $newgedrec .= "\n1 REPO @$REPO@"; if (!empty($CALN)) $newgedrec .= "\n2 CALN $CALN"; } - $xref = append_gedrec($newgedrec, WT_GED_ID); - if ($xref) { - $controller->addInlineJavascript('openerpasteid("' . $xref . '");'); - } + $record = WT_GedcomRecord::createRecord($newgedrec, WT_GED_ID); + $controller->addInlineJavascript('openerpasteid("' . $record->getXref() . '");'); break; //////////////////////////////////////////////////////////////////////////////// @@ -814,42 +752,30 @@ case 'addnewnote': ->setPageTitle(WT_I18N::translate('Create a new Shared Note')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - ?> - <form method="post" action="edit_interface.php" onsubmit="return check_form(this);"> - <input type="hidden" name="action" value="addnoteaction"> - <input type="hidden" name="noteid" value="newnote"> - <!-- <input type="hidden" name="pid" value="$pid"> --> - <?php + <div id="edit_interface-page"> + <h4><?php echo $controller->getPageTitle(); ?></h4> + + <form method="post" action="edit_interface.php" onsubmit="return check_form(this);"> + <input type="hidden" name="action" value="addnoteaction"> + <input type="hidden" name="noteid" value="newnote"> + <?php echo '<table class="facts_table">'; - echo '<tr>'; - echo '<td class="descriptionbox nowrap">'; - echo WT_I18N::translate('Shared note'), help_link('SHARED_NOTE'); - echo '</td>'; - echo '<td class="optionbox wrap" ><textarea name="NOTE" id="NOTE" rows="15" cols="87"></textarea>'; - echo print_specialchar_link('NOTE'); - echo '</td>'; - echo '</tr>'; - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo "</td></tr>"; - } - ?> - </table> - <p id="save-cancel"> - <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> - </p> - </form> + echo '<tr>'; + echo '<td class="descriptionbox nowrap">'; + echo WT_I18N::translate('Shared note'), help_link('SHARED_NOTE'); + echo '</td>'; + echo '<td class="optionbox wrap" ><textarea name="NOTE" id="NOTE" rows="15" cols="87"></textarea>'; + echo print_specialchar_link('NOTE'); + echo '</td>'; + echo '</tr>'; + echo keep_chan(); + ?> + <p id="save-cancel"> + <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> + <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> + </p> + </form> </div><!-- id="edit_interface-page" --> <?php break; @@ -874,10 +800,8 @@ case 'addnoteaction': } } - $xref = append_gedrec($newgedrec, WT_GED_ID); - if ($xref) { - $controller->addInlineJavascript('openerpasteid("' . $xref . '");'); - } + $record = WT_GedcomRecord::createRecord($newgedrec, WT_GED_ID); + $controller->addInlineJavascript('openerpasteid("' . $record->getXref() . '");'); break; //////////////////////////////////////////////////////////////////////////////// @@ -911,7 +835,7 @@ case 'addnewnote_assisted': <input type="hidden" name="action" value="addnoteaction_assisted"> <input type="hidden" name="noteid" value="newnote"> <input id="pid_array" type="hidden" name="pid_array" value="none"> - <input id="pid" type="hidden" name="pid" value=<?php echo $pid; ?>> + <input id="xref" type="hidden" name="xref" value=<?php echo $pid; ?>> <?php require WT_ROOT.WT_MODULES_DIR.'GEDFact_assistant/CENS_ctrl.php'; ?> @@ -956,12 +880,11 @@ case 'addmedia_links': //////////////////////////////////////////////////////////////////////////////// case 'editsource': - $pid = safe_GET('pid', WT_REGEX_XREF); - $source = WT_Source::getInstance($pid); + $xref = safe_GET('xref', WT_REGEX_XREF); + + $source = WT_Source::getInstance($xref); + check_record_access($source); - // Hide the private data - list($gedrec)=$source->privatizeGedcom(WT_USER_ACCESS_LEVEL); - $controller ->setPageTitle($source->getFullName()) ->pageHeader(); @@ -971,7 +894,7 @@ case 'editsource': init_calendar_popup(); echo '<form method="post" action="edit_interface.php" enctype="multipart/form-data">'; echo '<input type="hidden" name="action" value="update">'; - echo '<input type="hidden" name="pid" value="', $pid, '">'; + echo '<input type="hidden" name="xref" value="', $xref, '">'; echo '<table class="facts_table">'; $gedlines = explode("\n", $gedrec); // -- find the number of lines in the record $uniquefacts = preg_split("/[, ;:]+/", get_gedcom_setting(WT_GED_ID, 'SOUR_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); @@ -986,7 +909,7 @@ case 'editsource': for ($i=$linenum; $i<$lines; $i++) { $fields = explode(' ', $gedlines[$i]); if ((substr($gedlines[$i], 0, 1)<2) && $fields[1]!="CHAN") { - $level1type = create_edit_form($gedrec, $i, $level0type); + $level1type = create_edit_form($gedrec, $i, 'SOUR'); echo '<input type="hidden" name="linenum[]" value="', $i, '">'; $usedfacts[]=$fields[1]; foreach ($uniquefacts as $key=>$fact) { @@ -996,23 +919,11 @@ case 'editsource': } foreach ($uniquefacts as $key=>$fact) { $gedrec.="\n1 ".$fact; - $level1type = create_edit_form($gedrec, $lines++, $level0type); + $level1type = create_edit_form($gedrec, $lines++, 'SOUR'); echo '<input type="hidden" name="linenum[]" value="', $i, '">'; } - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $source->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $source->LastChangeUser()); - echo '</td></tr>'; - } + echo keep_chan($source); echo '</table>'; print_add_layer("OBJE"); print_add_layer("NOTE"); @@ -1030,68 +941,37 @@ case 'editsource': //////////////////////////////////////////////////////////////////////////////// case 'editnote': - $pid = safe_GET('pid', WT_REGEX_XREF); - $note = WT_Note::getInstance($pid); + $xref = safe_GET('xref', WT_REGEX_XREF); + + $note = WT_Note::getInstance($xref); + check_record_access($note); $controller ->setPageTitle(WT_I18N::translate('Edit Shared Note')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - // Hide the private data - list($gedrec)=$note->privatizeGedcom(WT_USER_ACCESS_LEVEL); - ?> - <form method="post" action="edit_interface.php" > - <input type="hidden" name="action" value="update"> - <input type="hidden" name="pid" value="<?php echo $pid; ?>"> - - <?php - if (preg_match("/^0 @$pid@ NOTE ?(.*)/", $gedrec, $n1match)) { - $note_content=$n1match[1].get_cont(1, $gedrec, false); - - $num_note_lines=0; - foreach (preg_split("/\r?\n/", $note_content, -1 ) as $j=>$line) { - $num_note_lines++; - } - - } else { - $note_content=''; - } - ?> - <table class="facts_table"> - <tr> - <td class="descriptionbox wrap width25"><?php echo WT_I18N::translate('Shared note'), help_link('SHARED_NOTE'); ?></td> - <td class="optionbox wrap"> - <textarea name="NOTE" id="NOTE" rows="15" cols="90"><?php - echo htmlspecialchars($note_content); - ?></textarea><br><?php echo print_specialchar_link('NOTE'); ?> - </td> - </tr> - <?php - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $note->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $note->LastChangeUser()); - echo '</td></tr>'; - } - ?> - </table> - <input type="hidden" name="num_note_lines" value="<?php echo $num_note_lines; ?>"> - <p id="save-cancel"> - <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> - </p> - </form> + <div id="edit_interface-page"> + <h4><?php echo $controller->getPageTitle(); ?></h4> + <form method="post" action="edit_interface.php" > + <input type="hidden" name="action" value="update"> + <input type="hidden" name="xref" value="<?php echo $xref; ?>"> + <table class="facts_table"> + <tr> + <td class="descriptionbox wrap width25"><?php echo WT_I18N::translate('Shared note'), help_link('SHARED_NOTE'); ?></td> + <td class="optionbox wrap"> + <textarea name="NOTE" id="NOTE" rows="15" cols="90"><?php echo htmlspecialchars($note->getNote()); ?></textarea> + <br> + <?php echo print_specialchar_link('NOTE'); ?> + </td> + </tr> + <?php echo keep_chan($note); ?> + </table> + <p id="save-cancel"> + <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> + <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> + </p> + </form> </div><!-- id="edit_interface-page" --> <?php break; @@ -1120,7 +1000,7 @@ case 'addnewrepository': ?> <form method="post" action="edit_interface.php" onsubmit="return check_form(this);"> <input type="hidden" name="action" value="addrepoaction"> - <input type="hidden" name="pid" value="newrepo"> + <input type="hidden" name="xref" value="newrepo"> <table class="facts_table"> <tr><td class="descriptionbox wrap width25"><?php echo WT_I18N::translate('Repository name'); ?></td> <td class="optionbox wrap"><input type="text" name="REPO_NAME" id="REPO_NAME" value="" size="40" maxlength="255"> <?php echo print_specialchar_link('REPO_NAME'); ?></td></tr> @@ -1142,19 +1022,7 @@ case 'addnewrepository': <td class="optionbox wrap"><input type="text" name="EMAIL" id="EMAIL" value="" size="40" maxlength="255"></td></tr> <tr><td class="descriptionbox wrap width25"><?php echo WT_Gedcom_Tag::getLabel('WWW'), help_link('URL'); ?></td> <td class="optionbox wrap"><input type="text" name="WWW" id="WWW" value="" size="40" maxlength="255"> </td></tr> - <?php - if (WT_USER_IS_ADMIN) { - echo '<tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo '</td></tr>'; - } - ?> + <?php echo keep_chan(); ?> </table> <p id="save-cancel"> <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> @@ -1200,267 +1068,23 @@ case 'addrepoaction': if (!empty($EMAIL)) $newgedrec .= "\n1 EMAIL $EMAIL"; if (!empty($WWW)) $newgedrec .= "\n1 WWW $WWW"; - $xref = append_gedrec($newgedrec, WT_GED_ID); - if ($xref) { - $controller->addInlineJavascript('openerpasteid("' . $xref . '");'); - } - break; - -//////////////////////////////////////////////////////////////////////////////// -case 'updateraw': - $controller - ->setPageTitle(WT_I18N::translate('Edit raw GEDCOM record')) - ->pageHeader(); - - $pid = safe_POST('pid', WT_REGEX_XREF); - $record = WT_GedcomRecord::getInstance($pid); - - // Retrieve the private data - list(, $private_gedrec)=$record->privatizeGedcom(WT_USER_ACCESS_LEVEL); - - $newgedrec = $_POST['newgedrec1'] . "\n" . $_POST['newgedrec2'] . $private_gedrec; - $success = replace_gedrec($pid, WT_GED_ID, $newgedrec, !safe_POST_bool('preserve_last_changed')); - - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $record = WT_GedcomRecord::createRecord($newgedrec, WT_GED_ID); + $controller->addInlineJavascript('openerpasteid("' . $record->getXref() . '");'); break; //////////////////////////////////////////////////////////////////////////////// -case 'update': - $controller - ->setPageTitle(WT_I18N::translate('Edit')) - ->pageHeader(); - - /* ----------------------------------------------------------------------------- - * $pids_array is a text file passed via js from the CENS GEDFact Assistant - * to the hidden field id=\"pids_array\" in the case 'add'. - * The subsequent array ($cens_pids), after exploding this text file, - * is an array of indi id's within the Census Transcription - * If $cens_pids is set, then this allows the array to "copy" the new CENS event - * using the foreach loop to these id's - * If $cens_pids is not set, then the array created is just the current $pid. - * ----------------------------------------------------------------------------- - */ - if (isset($_REQUEST['pids_array_add'])) $pids_array = $_REQUEST['pids_array_add']; - if (isset($_REQUEST['pids_array_edit'])) $pids_array = $_REQUEST['pids_array_edit']; - if (isset($_REQUEST['num_note_lines'])) $num_note_lines = $_REQUEST['num_note_lines']; - - if (isset($pids_array) && $pids_array!="no_array") { - $cens_pids=explode(', ', $pids_array); - } - - if (!isset($cens_pids)) { - $cens_pids = array($pid); - $idnums=""; - } else { - $cens_pids = $cens_pids; - $idnums="multi"; - } - - // Cycle through each individual concerned defined by $cens_pids array. - $success = true; - foreach ($cens_pids as $pid) { - if (isset($pid)) { - $gedrec = find_gedcom_record($pid, WT_GED_ID, true); - } elseif (isset($famid)) { - $gedrec = find_gedcom_record($famid, WT_GED_ID, true); - } - - // Retrieve the private data - $tmp=new WT_GedcomRecord($gedrec); - list($gedrec, $private_gedrec)=$tmp->privatizeGedcom(WT_USER_ACCESS_LEVEL); - - // If the fact has a DATE or PLAC, then delete any value of Y - if ($text[0]=='Y') { - for ($n=1; $n<count($tag); ++$n) { - if ($glevels[$n]==2 && ($tag[$n]=='DATE' || $tag[$n]=='PLAC') && $text[$n]) { - $text[0]=''; - break; - } - } - } - - //-- check for photo update - if (count($_FILES)>0) { - if (isset($_REQUEST['folder'])) $folder = $_REQUEST['folder']; - $uploaded_files = array(); - if (substr($folder, 0, 1) == "/") $folder = substr($folder, 1); - if (substr($folder, -1, 1) != "/") $folder .= "/"; - foreach ($_FILES as $upload) { - if (!empty($upload['tmp_name'])) { - if (!move_uploaded_file($upload['tmp_name'], $MEDIA_DIRECTORY.$folder.basename($upload['name']))) { - $error .= "<br>".WT_I18N::translate('There was an error uploading your file.')."<br>".file_upload_error_text($upload['error']); - $uploaded_files[] = ""; - } else { - $filename = $MEDIA_DIRECTORY.$folder.basename($upload['name']); - $uploaded_files[] = $MEDIA_DIRECTORY.$folder.basename($upload['name']); - if (!is_dir($MEDIA_DIRECTORY."thumbs/".$folder)) mkdir($MEDIA_DIRECTORY."thumbs/".$folder); - $thumbnail = $MEDIA_DIRECTORY."thumbs/".$folder.basename($upload['name']); - generate_thumbnail($filename, $thumbnail); - if (!empty($error)) { - echo "<span class=\"error\">", $error, "</span>"; - } - } - } else { - $uploaded_files[] = ""; - } - } - } - - $gedlines = explode("\n", trim($gedrec)); - //-- for new facts set linenum to number of lines - if (!is_array($linenum)) { - if ($linenum=="new" || $idnums=="multi") { - $linenum = count($gedlines); - } - $newged = ""; - for ($i=0; $i<$linenum; $i++) { - $newged .= $gedlines[$i]."\n"; - } - //-- for edits get the level from the line - if (isset($gedlines[$linenum])) { - $fields = explode(' ', $gedlines[$linenum]); - $glevel = $fields[0]; - $i++; - while (($i<count($gedlines))&&($gedlines[$i]{0}>$glevel)) { - $i++; - } - } - - if (!isset($glevels)) $glevels = array(); - if (isset($_REQUEST['NAME'])) $NAME = $_REQUEST['NAME']; - if (isset($_REQUEST['TYPE'])) $TYPE = $_REQUEST['TYPE']; - if (isset($_REQUEST['NPFX'])) $NPFX = $_REQUEST['NPFX']; - if (isset($_REQUEST['GIVN'])) $GIVN = $_REQUEST['GIVN']; - if (isset($_REQUEST['NICK'])) $NICK = $_REQUEST['NICK']; - if (isset($_REQUEST['SPFX'])) $SPFX = $_REQUEST['SPFX']; - if (isset($_REQUEST['SURN'])) $SURN = $_REQUEST['SURN']; - if (isset($_REQUEST['NSFX'])) $NSFX = $_REQUEST['NSFX']; - if (isset($_REQUEST['ROMN'])) $ROMN = $_REQUEST['ROMN']; - if (isset($_REQUEST['FONE'])) $FONE = $_REQUEST['FONE']; - if (isset($_REQUEST['_HEB'])) $_HEB = $_REQUEST['_HEB']; - if (isset($_REQUEST['_AKA'])) $_AKA = $_REQUEST['_AKA']; - if (isset($_REQUEST['_MARNM'])) $_MARNM = $_REQUEST['_MARNM']; - if (isset($_REQUEST['NOTE'])) $NOTE = $_REQUEST['NOTE']; - - if (!empty($NAME)) $newged .= "\n1 NAME $NAME"; - if (!empty($TYPE)) $newged .= "\n2 TYPE $TYPE"; - if (!empty($NPFX)) $newged .= "\n2 NPFX $NPFX"; - if (!empty($GIVN)) $newged .= "\n2 GIVN $GIVN"; - if (!empty($NICK)) $newged .= "\n2 NICK $NICK"; - if (!empty($SPFX)) $newged .= "\n2 SPFX $SPFX"; - if (!empty($SURN)) $newged .= "\n2 SURN $SURN"; - if (!empty($NSFX)) $newged .= "\n2 NSFX $NSFX"; - - if (!empty($NOTE)) { - $cmpfunc = create_function('$e', 'return strpos($e,"0 @N") !==0 && strpos($e,"1 CONT") !==0;'); - $gedlines = array_filter($gedlines, $cmpfunc); - $tempnote = preg_split('/\r?\n/', trim($NOTE) . "\n"); // make sure only one line ending on the end - $title[] = "0 @$pid@ NOTE " . array_shift($tempnote); - foreach($tempnote as &$line) { - $line = trim("1 CONT " . $line,' '); - } - $gedlines = array_merge($title,$tempnote,$gedlines); - } - - //-- Refer to Bug [ 1329644 ] Add Married Name - Wrong Sequence - //-- _HEB/ROMN/FONE have to be before _AKA, even if _AKA exists in input and the others are now added - if (!empty($ROMN)) $newged .= "\n2 ROMN $ROMN"; - if (!empty($FONE)) $newged .= "\n2 FONE $FONE"; - if (!empty($_HEB)) $newged .= "\n2 _HEB $_HEB"; - - $newged = handle_updates($newged); - - if (!empty($_AKA)) $newged .= "\n2 _AKA $_AKA"; - if (!empty($_MARNM)) $newged .= "\n2 _MARNM $_MARNM"; - - while ($i<count($gedlines)) { - $newged .= "\n".$gedlines[$i]; - $i++; - } - } else { - $newged = ""; - $current = 0; - foreach ($linenum as $editline) { - for ($i=$current; $i<$editline; $i++) { - $newged .= "\n".$gedlines[$i]; - } - //-- for edits get the level from the line - if (isset($gedlines[$editline])) { - $fields = explode(' ', $gedlines[$editline]); - $glevel = $fields[0]; - $i++; - while (($i<count($gedlines))&&($gedlines[$i]{0}>$glevel)) $i++; - } - - if (!isset($glevels)) $glevels = array(); - if (isset($_REQUEST['NAME'])) $NAME = $_REQUEST['NAME']; - if (isset($_REQUEST['TYPE'])) $TYPE = $_REQUEST['TYPE']; - if (isset($_REQUEST['NPFX'])) $NPFX = $_REQUEST['NPFX']; - if (isset($_REQUEST['GIVN'])) $GIVN = $_REQUEST['GIVN']; - if (isset($_REQUEST['NICK'])) $NICK = $_REQUEST['NICK']; - if (isset($_REQUEST['SPFX'])) $SPFX = $_REQUEST['SPFX']; - if (isset($_REQUEST['SURN'])) $SURN = $_REQUEST['SURN']; - if (isset($_REQUEST['NSFX'])) $NSFX = $_REQUEST['NSFX']; - if (isset($_REQUEST['ROMN'])) $ROMN = $_REQUEST['ROMN']; - if (isset($_REQUEST['FONE'])) $FONE = $_REQUEST['FONE']; - if (isset($_REQUEST['_HEB'])) $_HEB = $_REQUEST['_HEB']; - if (isset($_REQUEST['_AKA'])) $_AKA = $_REQUEST['_AKA']; - if (isset($_REQUEST['_MARNM'])) $_MARNM = $_REQUEST['_MARNM']; - if (isset($_REQUEST['NOTE'])) $NOTE = $_REQUEST['NOTE']; - - if (!empty($NAME)) $newged .= "\n1 NAME $NAME"; - if (!empty($TYPE)) $newged .= "\n2 TYPE $TYPE"; - if (!empty($NPFX)) $newged .= "\n2 NPFX $NPFX"; - if (!empty($GIVN)) $newged .= "\n2 GIVN $GIVN"; - if (!empty($NICK)) $newged .= "\n2 NICK $NICK"; - if (!empty($SPFX)) $newged .= "\n2 SPFX $SPFX"; - if (!empty($SURN)) $newged .= "\n2 SURN $SURN"; - if (!empty($NSFX)) $newged .= "\n2 NSFX $NSFX"; - - if (!empty($NOTE)) { - $cmpfunc = create_function('$e', 'return strpos($e,"0 @N") !==0 && strpos($e,"1 CONT") !==0;'); - $gedlines = array_filter($gedlines, $cmpfunc); - $tempnote = preg_split('/\r?\n/', trim($NOTE) . "\n"); // make sure only one line ending on the end - $title[] = "0 @$pid@ NOTE " . array_shift($tempnote); - foreach($tempnote as &$line) { - $line = trim("1 CONT " . $line,' '); - } - $gedlines = array_merge($title,$tempnote,$gedlines); - } - - //-- Refer to Bug [ 1329644 ] Add Married Name - Wrong Sequence - //-- _HEB/ROMN/FONE have to be before _AKA, even if _AKA exists in input and the others are now added - if (!empty($ROMN)) $newged .= "\n2 ROMN $ROMN"; - if (!empty($FONE)) $newged .= "\n2 FONE $FONE"; - if (!empty($_HEB)) $newged .= "\n2 _HEB $_HEB"; - - if (!empty($_AKA)) $newged .= "\n2 _AKA $_AKA"; - if (!empty($_MARNM)) $newged .= "\n2 _MARNM $_MARNM"; - - $newged = handle_updates($newged); - $current = $editline; - break; - } - - } - $success = $success && replace_gedrec($pid, WT_GED_ID, $newged.$private_gedrec, $update_CHAN); - } // end foreach $cens_pids ------------- +case 'addchildaction': + $famid = safe_POST('famid', WT_REGEX_XREF); // Add a child to this family + $keep_chan = safe_POST_bool('keep_chan'); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } - break; + $family = WT_Family::getInstance($famid); + check_record_access($family); -//////////////////////////////////////////////////////////////////////////////// -case 'addchildaction': $controller ->setPageTitle(WT_I18N::translate('Add child')) ->pageHeader(); - splitSOUR(); // separate SOUR record from the rest - + splitSOUR(); $gedrec ="0 @REF@ INDI"; $gedrec.=addNewName(); $gedrec.=addNewSex (); @@ -1469,225 +1093,179 @@ case 'addchildaction': $gedrec.=addNewFact($match); } } - - if (!empty($famid)) { + if ($family) { + // $family is not set when creating unlinked individuals if (isset($_REQUEST['PEDI'])) { $PEDI = $_REQUEST['PEDI']; } else { - $PEDI=''; + $PEDI = ''; } - $gedrec.="\n".WT_Gedcom_Code_Pedi::createNewFamcPedi($PEDI, $famid); + $gedrec .= "\n".WT_Gedcom_Code_Pedi::createNewFamcPedi($PEDI, $famid); } - if (safe_POST_bool('SOUR_INDI')) { $gedrec = handle_updates($gedrec); } else { $gedrec = updateRest($gedrec); } - $xref = append_gedrec($gedrec, WT_GED_ID); - $gedrec = ""; - if ($xref) { - if (empty($famid)) { - $success=true; - } else { - // Insert new child at the right place [ 1686246 ] - $newchild = WT_Person::getInstance($xref); - $gedrec=find_gedcom_record($famid, WT_GED_ID, true); - $family=new WT_Family($gedrec); - $done = false; - foreach ($family->getChildren() as $key=>$child) { - if (WT_Date::Compare($newchild->getEstimatedBirthDate(), $child->getEstimatedBirthDate())<0) { - // new child is older : insert before - $gedrec = str_replace("1 CHIL @".$child->getXref()."@", - "1 CHIL @$xref@\n1 CHIL @".$child->getXref()."@", - $gedrec); - $done = true; - break; - } - } - // new child is the only one - if (count($family->getChildren())<1) { - $gedrec .= "\n1 CHIL @$xref@"; - } elseif (!$done) { - // new child is the youngest or undated : insert after - $gedrec = str_replace("\n1 CHIL @".$child->getXref()."@", - "\n1 CHIL @".$child->getXref()."@\n1 CHIL @$xref@", - $gedrec); + // Create the new child + $new_child = WT_GedcomRecord::createRecord($gedrec, WT_GED_ID); + + if ($family) { + // Insert new child at the right place + foreach ($family->getFacts('CHIL') as $fact) { + $old_child = $fact->getTarget(); + if ($old_child && WT_Date::Compare($newchild->getEstimatedBirthDate(), $child->getEstimatedBirthDate())<0) { + // Insert before this child + $family->updateFact($fact->fact_id, "1 CHIL @" . $new_child->getXref()."@\n" . $fact->getGedcom(), !$keep_chan); + $done = true; + break; } - $success=replace_gedrec($famid, WT_GED_ID, $gedrec, $update_CHAN); } - } else { - $success=false; + if (!$done) { + // Append to end + $family->updateFact(null, "1 CHIL @" . $new_child->getXref()."@\n", !$keep_chan); + } } - if ($success && !WT_DEBUG) { - if (safe_POST('goto')=='new') { - $record = WT_Person::getInstance($xref); - $controller->addInlineJavascript('closePopupAndReloadParent("' . $record->getRawUrl() . '");'); - } else { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + if (safe_POST('goto')=='new') { + $controller->addInlineJavascript('closePopupAndReloadParent("' . $new_child->getRawUrl() . '");'); + } else { + $controller->addInlineJavascript('closePopupAndReloadParent();'); } break; //////////////////////////////////////////////////////////////////////////////// case 'addspouseaction': + $xref = safe_POST('xref', WT_REGEX_XREF); // Add a spouse to this person + $sex = safe_POST('SEX', '[MFU]'); + + $person = WT_Individual::getInstance($xref); + check_record_access($person); + $controller ->setPageTitle(WT_I18N::translate('Add a new spouse')) ->pageHeader(); - splitSOUR(); // separate SOUR record from the rest - - $gedrec ="0 @REF@ INDI"; - $gedrec.=addNewName(); - $gedrec.=addNewSex (); + splitSOUR(); + $indi_gedcom = '0 @REF@ INDI'; + $indi_gedcom.= addNewName(); + $indi_gedcom.= addNewSex (); if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FACTS, $matches)) { foreach ($matches[1] as $match) { - $gedrec.=addNewFact($match); + $indi_gedcom.=addNewFact($match); } } - if (safe_POST_bool('SOUR_INDI')) { - $gedrec = handle_updates($gedrec); + $indi_gedcom = handle_updates($indi_gedcom); } else { - $gedrec = updateRest($gedrec); + $indi_gedcom = updateRest($indi_gedcom); } - $xref = append_gedrec($gedrec, WT_GED_ID); - $success = true; - if ($famid=="new") { - $famrec = "0 @new@ FAM"; - $SEX=safe_POST('SEX', '[MF]', 'U'); - if ($SEX=="M") $famtag = "HUSB"; - if ($SEX=="F") $famtag = "WIFE"; - if ($famtag=="HUSB") { - $famrec .= "\n1 HUSB @$xref@"; - $famrec .= "\n1 WIFE @$pid@"; - } else { - $famrec .= "\n1 WIFE @$xref@"; - $famrec .= "\n1 HUSB @$pid@"; - } - - if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FAMFACTS, $matches)) { - foreach ($matches[1] as $match) { - $famrec.=addNewFact($match); - } + $fam_gedcom = ''; + if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FAMFACTS, $matches)) { + foreach ($matches[1] as $match) { + $fam_gedcom.=addNewFact($match); } + } + if (safe_POST_bool('SOUR_FAM')) { + $fam_gedcom = handle_updates($fam_gedcom); + } else { + $fam_gedcom = updateRest($fam_gedcom); + } - if (safe_POST_bool('SOUR_FAM')) { - $famrec = handle_updates($famrec); + if ($family) { + // Append to an existing family + $indi_gedcom .= "\n1 FAMS @" . $family->getXref() . '@'; + // Create the new spouse + $spouse = WT_GedcomRecord::createRecord($indi_gedcom, WT_GED_ID); + // Link the family + if ($sex=='F') { + $family::updateFact(null, '1 WIFE @' . $spouse->getXref() . '@' . $fam_gedcom, true); } else { - $famrec = updateRest($famrec); + $family::updateFact(null, '1 HUSB @' . $spouse->getXref() . '@' . $fam_gedcom, true); } - - $famid = append_gedrec($famrec, WT_GED_ID); - } elseif (!empty($famid)) { - $famrec = find_gedcom_record($famid, WT_GED_ID, true); - if (!empty($famrec)) { - $famrec .= "\n1 $famtag @$xref@"; - - if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FAMFACTS, $matches)) { - foreach ($matches[1] as $match) { - $famrec.=addNewFact($match); - } - } - - if (safe_POST_bool('SOUR_FAM')) { - $famrec = handle_updates($famrec); - } else { - $famrec = updateRest($famrec); - } - - $success = $success && replace_gedrec($famid, WT_GED_ID, $famrec, $update_CHAN); - } - } - if ((!empty($famid))&&($famid!="new")) { - $gedrec = find_gedcom_record($xref, WT_GED_ID, true) . "\n1 FAMS @$famid@"; - $success = $success && replace_gedrec($xref, WT_GED_ID, $gedrec, $update_CHAN); - } - if (!empty($pid)) { - $indirec = find_gedcom_record($pid, WT_GED_ID, true); - if ($indirec) { - $indirec .= "\n1 FAMS @$famid@"; - $success = $success && replace_gedrec($pid, WT_GED_ID, $indirec, $update_CHAN); + } else { + // Create the new spouse + $spouse = WT_GedcomRecord::createRecord($indi_gedcom, WT_GED_ID); + // Create a new family + if ($sex == 'F') { + $family = WT_GedcomRecord::createRecord("0 @NEW@ FAM\n1 WIFE @" . $spouse->getXref() . "@\n1 HUSB @" . $person->getXref() . "@" . $fam_gedcom, WT_GED_ID); + } else { + $family = WT_GedcomRecord::createRecord("0 @NEW@ FAM\n1 HUSB @" . $spouse->getXref() . "@\n1 WIFE @" . $person->getXref() . "@" . $fam_gedcom, WT_GED_ID); } + // Link the spouses to the family + $spouse->updateFact(null, '1 FAMS @' . $family->getXref() . '@', true); + $person->updateFact(null, '1 FAMS @' . $family->getXref() . '@', true); } - if ($success && !WT_DEBUG) { - if (safe_POST('goto')=='new') { - $record = WT_Person::getInstance($xref); - $controller->addInlineJavascript('closePopupAndReloadParent("' . $record->getRawUrl() . '");'); - } else { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + if (safe_POST('goto')=='new') { + $controller->addInlineJavascript('closePopupAndReloadParent("' . $new_spouse->getRawUrl() . '");'); + } else { + $controller->addInlineJavascript('closePopupAndReloadParent();'); } break; //////////////////////////////////////////////////////////////////////////////// case 'linkspouseaction': - $controller - ->setPageTitle(WT_I18N::translate('Add child')) - ->pageHeader(); + $pid = safe_POST('pid', WT_REGEX_XREF); + $spid = safe_POST('spid', WT_REGEX_XREF); + $famtag = safe_POST('famtag', '(HUSB|WIFE)'); - splitSOUR(); // separate SOUR record from the rest + $person = WT_Individual::getInstance($pid); + $spouse = WT_Individual::getInstance($spid); + check_record_access($person); + check_record_access($spouse); - if (isset($_REQUEST['spid'])) $spid = $_REQUEST['spid']; - $success=false; - if (!empty($spid)) { - $gedrec = find_gedcom_record($spid, WT_GED_ID, true); - if ($gedrec) { - if ($famid=="new") { - $famrec = "0 @new@ FAM"; - $SEX = get_gedcom_value("SEX", 1, $gedrec); - if ($SEX=="M") $famtag = "HUSB"; - if ($SEX=="F") $famtag = "WIFE"; - if ($famtag=="HUSB") { - $famrec .= "\n1 HUSB @$spid@"; - $famrec .= "\n1 WIFE @$pid@"; - } else { - $famrec .= "\n1 WIFE @$spid@"; - $famrec .= "\n1 HUSB @$pid@"; - } - $famrec.=addNewFact('MARR'); + if ($person->getSex()=='F') { + $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Add a husband using an existing person')); + } else { + $controller->setPageTitle($person->getFullName() . ' - ' . WT_I18N::translate('Add a wife using an existing person')); + } + $controller->pageHeader(); - if (safe_POST_bool('SOUR_FAM') || count($tagSOUR)>0) { - // before adding 2 SOUR it needs to add 1 MARR Y first - if (addNewFact('MARR')=='') { - $famrec .= "\n1 MARR Y"; - } - $famrec = handle_updates($famrec); - } else { - // before adding level 2 facts it needs to add 1 MARR Y first - if (addNewFact('MARR')=='') { - $famrec .= "\n1 MARR Y"; - } - $famrec = updateRest($famrec); - } + if ($person->getSex()=='M') { + $gedcom = "0 @new@ FAM\n1 HUSB @" . $person->getXref() . "@\n1 WIFE @" . $spouse->getXref() . "@"; + } else { + $gedcom = "0 @new@ FAM\n1 HUSB @" . $spouse->getXref() . "@\n1 WIFE @" . $person->getXref() . "@"; + } + splitSOUR(); + $gedcom .= addNewFact('MARR'); - $famid = append_gedrec($famrec, WT_GED_ID); - } - if ((!empty($famid))&&($famid!="new")) { - $gedrec .= "\n1 FAMS @$famid@"; - $success=replace_gedrec($spid, WT_GED_ID, $gedrec, $update_CHAN); - } - if (!empty($pid)) { - $indirec = find_gedcom_record($pid, WT_GED_ID, true); - if (!empty($indirec)) { - $indirec = trim($indirec) . "\n1 FAMS @$famid@"; - $success=replace_gedrec($pid, WT_GED_ID, $indirec, $update_CHAN); - } - } + if (safe_POST_bool('SOUR_FAM') || count($tagSOUR)>0) { + // before adding 2 SOUR it needs to add 1 MARR Y first + if (addNewFact('MARR') == '') { + $gedcom .= "\n1 MARR Y"; + } + $gedcom = handle_updates($gedcom); + } else { + // before adding level 2 facts it needs to add 1 MARR Y first + if (addNewFact('MARR')=='') { + $gedcom .= "\n1 MARR Y"; } + $gedcom = updateRest($gedcom); } - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $family = WT_GedcomRecord::createRecord($gedcom, WT_GED_ID); + $person->updateFact(null, '1 FAMS @' . $family->getXref() .'@', true); + $spouse->updateFact(null, '1 FAMS @' . $family->getXref() .'@', true); + + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// case 'addnewparentaction': + $xref = safe_POST('xref', WT_REGEX_XREF); + $famid = safe_POST('famid', WT_REGEX_XREF); + $famtag = safe_POST('famtag', '(HUSB|WIFE)'); + + $person = WT_Individual::getInstance($xref); + $family = WT_Family::getInstance($famid); + check_record_access($person); + if ($family) { + check_record_access($family); + } + $controller ->setPageTitle(WT_I18N::translate('Add a new father')) ->pageHeader(); @@ -1709,357 +1287,365 @@ case 'addnewparentaction': $gedrec = updateRest($gedrec); } - $xref = append_gedrec($gedrec, WT_GED_ID); - $success = true; - if ($famid=="new") { - $famrec = "0 @new@ FAM"; - if ($famtag=="HUSB") { - $famrec .= "\n1 HUSB @$xref@"; - $famrec .= "\n1 CHIL @$pid@"; - } else { - $famrec .= "\n1 WIFE @$xref@"; - $famrec .= "\n1 CHIL @$pid@"; - } - + $parent = WT_GedcomRecord::createRecord($gedrec, WT_GED_ID); + if ($family) { + // Link to an existing family + $famrec = '1 ' . $famtag .' @' . $parent . '@'; if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FAMFACTS, $matches)) { foreach ($matches[1] as $match) { $famrec.=addNewFact($match); } } - if (safe_POST_bool('SOUR_FAM')) { $famrec = handle_updates($famrec); } else { $famrec = updateRest($famrec); } + $family->updateFact(null, $famrec, true); + $parent->updateFact(null, '1 FAMS @' . $family->getXref() . '@', true); + } else { + // Create a new family + $famrec = '0 @new@ FAM'; + if ($famtag == 'HUSB') { + $famrec .= "\n1 HUSB @" . $parent->getXref() . '@'; + $famrec .= "\n1 CHIL @" . $person->getXref() . '@'; + } else { + $famrec .= "\n1 WIFE @" . $parent->getXref() . '@'; + $famrec .= "\n1 CHIL @" . $person->getXref() . '@'; + } - $famid = append_gedrec($famrec, WT_GED_ID); - } elseif (!empty($famid)) { - $famrec = find_gedcom_record($famid, WT_GED_ID, true); - if (!empty($famrec)) { - $famrec .= "\n1 $famtag @$xref@"; - if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FAMFACTS, $matches)) { - foreach ($matches[1] as $match) { - $famrec.=addNewFact($match); - } - } - if (safe_POST_bool('SOUR_FAM')) { - $famrec = handle_updates($famrec); - } else { - $famrec = updateRest($famrec); + if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FAMFACTS, $matches)) { + foreach ($matches[1] as $match) { + $famrec.=addNewFact($match); } - $success = $success && replace_gedrec($famid, WT_GED_ID, $famrec, $update_CHAN); } - } - if (!empty($famid) && $famid!="new") { - $gedrec = find_gedcom_record($xref, WT_GED_ID, true); - $gedrec.= "\n1 FAMS @$famid@"; - $success = $success && replace_gedrec($xref, WT_GED_ID, $gedrec, $update_CHAN); - } - if (!empty($pid)) { - $indirec = find_gedcom_record($pid, WT_GED_ID, true); - if ($indirec) { - if (strpos($indirec, "1 FAMC @$famid@")===false) { - $indirec .= "\n1 FAMC @$famid@"; - $success = $success && replace_gedrec($pid, WT_GED_ID, $indirec, $update_CHAN); - } + if (safe_POST_bool('SOUR_FAM')) { + $famrec = handle_updates($famrec); + } else { + $famrec = updateRest($famrec); } + + $family = WT_GedcomRecord::createRecord($famrec, WT_GED_ID); + $person->updateFact(null, '1 FAMC @' . $family->getXref() . '@', true); + $parent->updateFact(null, '1 FAMS @' . $family->getXref() . '@', true); } - if ($success && !WT_DEBUG) { - if (safe_POST('goto')=='new') { - $record = WT_Person::getInstance($xref); - $controller->addInlineJavascript('closePopupAndReloadParent("' . $record->getRawUrl() . '");'); - } else { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + if (safe_POST('goto')=='new') { + $controller->addInlineJavascript('closePopupAndReloadParent("' . $parent->getRawUrl() . '");'); + } else { + $controller->addInlineJavascript('closePopupAndReloadParent();'); } break; //////////////////////////////////////////////////////////////////////////////// case 'addopfchildaction': + $pid = safe_POST('pid', WT_REGEX_XREF); + $PEDI = safe_POST('PEDI'); + + $person = WT_Individual::getInstance($pid); + check_record_access($person); + $controller ->setPageTitle(WT_I18N::translate('Add child')) ->pageHeader(); splitSOUR(); // separate SOUR record from the rest - $newindixref=get_new_xref('INDI'); - $newfamxref=get_new_xref('FAM'); - - $gedrec ="0 @{$newindixref}@ INDI".addNewName().addNewSex (); + $gedcom = "0 @{$newindixref}@ INDI"; + $gedcom .= addNewName(); + $gedcom .= addNewSex (); + $gedcom .= "\n".WT_Gedcom_Code_Pedi::createNewFamcPedi($PEDI, $newfamxref); if (preg_match_all('/([A-Z0-9_]+)/', $QUICK_REQUIRED_FACTS, $matches)) { foreach ($matches[1] as $match) { - $gedrec.=addNewFact($match); + $gedcom.=addNewFact($match); } } - - if (isset($_REQUEST['PEDI'])) { - $PEDI = $_REQUEST['PEDI']; - } else { - $PEDI=''; - } - $gedrec.="\n".WT_Gedcom_Code_Pedi::createNewFamcPedi($PEDI, $newfamxref); - if (safe_POST_bool('SOUR_INDI')) { - $gedrec=handle_updates($gedrec); + $gedcom=handle_updates($gedcom); } else { - $gedrec=updateRest($gedrec); + $gedcom=updateRest($gedcom); } - $famrec="0 @$newfamxref@ FAM\n1 CHIL @{$newindixref}@"; - $person=WT_Person::getInstance($pid); - if ($person->getSex()=='F') { - $famrec.="\n1 WIFE @{$pid}@"; - } else { - $famrec.="\n1 HUSB @{$pid}@"; - } + $child = WT_GedcomRecord::createRecord($gedcom, WT_GED_ID); - $indirec=find_gedcom_record($pid, WT_GED_ID, true); - if ($indirec) { - $indirec.="\n1 FAMS @{$newfamxref}@"; - $success = - replace_gedrec($pid, WT_GED_ID, $indirec, $update_CHAN) && - append_gedrec($gedrec, WT_GED_ID) && - append_gedrec($famrec, WT_GED_ID); + $gedcom="0 @NEW@ FAM\n1 CHIL @" . $child->getXref() . "@"; + if ($person->getSex()=='F') { + $gedcom.="\n1 WIFE @{$pid}@"; } else { - $success = false; + $gedcom.="\n1 HUSB @{$pid}@"; } + $family = WT_GedcomRecord::createRecord($gedcom, WT_GED_ID); + $person->replaceFact(null, "1 FAMS @" . $family->getXref() . "@", true); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// case 'editname': - $pid = safe_GET('pid', WT_REGEX_XREF); // print_indi_form() needs this global - $person = WT_Person::getInstance($pid); + $pid = safe_GET('pid', WT_REGEX_XREF); + $fact_id = safe_GET('fact_id'); + + $person = WT_Individual::getInstance($pid); + check_record_access($person); + + // Find the fact to edit + $name_fact = null; + foreach ($person->getFacts() as $fact) { + if ($fact->getFactId() == $fact_id && $fact->canShow() && $fact->canEdit()) { + $name_fact = $fact; + } + } + if (!$name_fact) { + $controller + ->pageHeader() + ->addInlineJavascript('closePopupAndReloadParent();'); + exit; + } $controller ->setPageTitle(WT_I18N::translate('Edit name')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - // Hide the private data - list($gedrec)=$person->privatizeGedcom(WT_USER_ACCESS_LEVEL); - $gedlines = explode("\n", trim($gedrec)); - $fields = explode(' ', $gedlines[$linenum]); - $glevel = $fields[0]; - $i = $linenum+1; - $namerec = $gedlines[$linenum]; - while (($i<count($gedlines))&&($gedlines[$i]{0}>$glevel)) { - $namerec.="\n".$gedlines[$i]; - $i++; - } - print_indi_form('update', '', $linenum, $namerec, '', $person->getSex()); - echo '</div><!-- id="edit_interface-page" -->'; + print_indi_form('update', $person, null, $name_fact, '', $person->getSex()); break; //////////////////////////////////////////////////////////////////////////////// case 'addname': + $pid = safe_GET('pid', WT_REGEX_XREF); + + $person = WT_Individuual::getInstance($pid); + check_record_access($person); + $controller ->setPageTitle(WT_I18N::translate('Add new Name')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - - $person=WT_Person::getInstance($pid); - print_indi_form('update', '', 'new', 'NEW', '', $person->getSex()); - echo '</div><!-- id="edit_interface-page" -->'; + print_indi_form('update', $person, null, null, '', $person->getSex()); break; //////////////////////////////////////////////////////////////////////////////// case 'paste': + $xref = safe_REQUEST($_REQUEST, 'pid', WT_REGEX_XREF); + $fact = safe_REQUEST($_REQUEST, 'fact', WT_REGEX_UNSAFE); + + $record = WT_GedcomRecord::getInstance($xref); + check_record_access($record); + $controller ->setPageTitle(WT_I18N::translate('Add from clipboard')) ->pageHeader(); - $gedrec .= "\n".$WT_SESSION->clipboard[$fact]['factrec']; - $success=replace_gedrec($pid, WT_GED_ID, $gedrec, $NO_UPDATE_CHAN); - - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $record->updateFact(null, $WT_SESSION->clipboard[$fact]['factrec']); + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// case 'reorder_media': // Sort page using Popup - $controller - ->setPageTitle(WT_I18N::translate('Re-order media')) - ->pageHeader(); + $xref = safe_REQUEST($_REQUEST, 'pid', WT_REGEX_XREF); - echo '<div id="edit_interface-page">'; - require_once WT_ROOT.'includes/media_reorder.php'; - echo '</div><!-- id="edit_interface-page" -->'; - break; + $person = WT_Individual::getInstance($xref); + check_record_access($person); -//////////////////////////////////////////////////////////////////////////////// -case 'reorder_media_update': // Update sort using popup $controller ->setPageTitle(WT_I18N::translate('Re-order media')) - ->pageHeader(); + ->pageHeader() + ->addInlineJavascript(' + jQuery("#reorder_media_list").sortable({forceHelperSize: true, forcePlaceholderSize: true, opacity: 0.7, cursor: "move", axis: "y"}); + + //-- update the order numbers after drag-n-drop sorting is complete + jQuery("#reorder_media_list").bind("sortupdate", function(event, ui) { + jQuery("#"+jQuery(this).attr("id")+" input").each( + function (index, value) { + value.value = index+1; + } + ); + }); + '); - if (isset($_REQUEST['order1'])) $order1 = $_REQUEST['order1']; - $lines = explode("\n", $gedrec); - $newgedrec = ""; - foreach ($lines as $line) { - if (strpos($line, '1 _WT_OBJE_SORT')===false) { - $newgedrec .= $line."\n"; + // Get the current sort order + $sort_obje = array(); + foreach ($person->getFacts('_WT_OBJE_SORT') as $fact) { + $media = $fact->getTarget(); + if ($media && $media->canShow()) { + $sort_obje[] = $media; } } - foreach ($order1 as $m_media=>$num) { - $newgedrec .= "\n1 _WT_OBJE_SORT @".$m_media."@"; - } - $success=replace_gedrec($pid, WT_GED_ID, $newgedrec, $update_CHAN); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); + // Add other media objects from the individual and any spouse-families + $record_list = array($person); + foreach ($person->getSpouseFamilies() as $family) { + $record_list[] = $family; } - break; - -//////////////////////////////////////////////////////////////////////////////// -case 'al_reset_media_update': // Reset sort using Album Page - $controller - ->setPageTitle(WT_I18N::translate('Re-order media')) - ->pageHeader(); - - $lines = explode("\n", $gedrec); - $newgedrec = ""; - foreach ($lines as $line) { - if (strpos($line, "1 _WT_OBJE_SORT")===false) { - $newgedrec .= $line."\n"; + foreach ($record_list as $record) { + if ($record->canShow()) { + foreach ($record->getFacts() as $fact) { + if ($fact->canShow() && !$fact->isOld()) { + preg_match_all('/(?:^1|\n\d) OBJE @(' . WT_REGEX_XREF . ')@/', $fact->getGedcom(), $matches); + foreach ($matches[1] as $match) { + $media = WT_Media::getInstance($match); + if (!in_array($media, $sort_obje)) { + $sort_obje[] = $media; + } + } + } + } } } - $success=replace_gedrec($pid, WT_GED_ID, $newgedrec, $update_CHAN); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + ?> + <div id="edit_interface-page"> + <h4><?php echo WT_I18N::translate('Click a row, then drag-and-drop to re-order media '); ?></h4> + <form name="reorder_form" method="post" action="edit_interface.php"> + <input type="hidden" name="action" value="reorder_media_update"> + <input type="hidden" name="xref" value="<?php echo $xref; ?>"> + <ul id="reorder_media_list"> + <?php foreach ($sort_obje as $n=>$obje) { ?> + <li class="facts_value" style="list-style:none;cursor:move;margin-bottom:2px;" id="li_<?php echo $obje->getXref(); ?>"> + <table class="pic"> + <tr> + <td width="80" valign="top" align="center"> + <?php echo $obje->displayImage(); ?> + </td> + <td> + <?php echo $obje->getFullName(); ?> + </td> + </tr> + </table> + <input type="hidden" name="order1[<?php echo $obje->getXref(); ?>]" value="<?php echo $n; ?>"> + </li> + <?php } ?> + </ul> + <table> + <?php echo keep_chan($person); ?> + </table> + <p id="save-cancel"> + <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> + <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> + </p> + </form> + </div> + <?php break; //////////////////////////////////////////////////////////////////////////////// -case 'al_reorder_media_update': // Update sort using Album Page +case 'reorder_media_update': // Update sort using popup + $xref = safe_POST('xref', WT_REGEX_XREF); + $order1 = safe_POST('order1'); + $keep_chan = safe_POST_bool('keep_chan'); + + $person = WT_Individual::getInstance($xref); + check_record_access($person); + $controller ->setPageTitle(WT_I18N::translate('Re-order media')) ->pageHeader(); - if (isset($_REQUEST['order1'])) $order1 = $_REQUEST['order1']; - function SwapArray($Array) { - $Values = array(); - while (list($Key, $Val) = each($Array)) - $Values[$Val] = $Key; - return $Values; - } - if (isset($_REQUEST['order2'])) $order2 = $_REQUEST['order2']; - $order2 = SwapArray(explode(",", substr($order2, 0, -1))); - - $lines = explode("\n", $gedrec); - $newgedrec = ""; - foreach ($lines as $line) { - if (strpos($line, "1 _WT_OBJE_SORT")===false) { - $newgedrec .= $line."\n"; + // Delete any existing _WT_OBJE_SORT records + $facts = array('0 @' . $person->getXref() . '@ INDI'); + foreach ($person->getFacts() as $fact) { + if ($fact->getTag() != '_WT_OBJE_SORT') { + $facts[] = $fact->getGedcom(); } } - foreach ($order2 as $m_media=>$num) { - $newgedrec .= "\n1 _WT_OBJE_SORT @".$m_media."@"; + if (is_array($order1)) { + // Add new _WT_OBJE_SORT records + foreach ($order1 as $xref=>$n) { + $facts[] = '1 _WT_OBJE_SORT @' . $xref . '@'; + } } - $success=replace_gedrec($pid, WT_GED_ID, $newgedrec, $update_CHAN); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $person->updateRecord(implode("\n", $facts), !$keep_chan); + + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// case 'reorder_children': + $xref = safe_GET('xref', WT_REGEX_XREF); + $option = safe_GET('option'); + + $family = WT_Family::getInstance($xref); + check_record_access($family); + $controller ->addInlineJavascript('jQuery("#reorder_list").sortable({forceHelperSize: true, forcePlaceholderSize: true, opacity: 0.7, cursor: "move", axis: "y"});') - //-- update the order numbers after drag-n-drop sorting is complete ->addInlineJavascript('jQuery("#reorder_list").bind("sortupdate", function(event, ui) { jQuery("#"+jQuery(this).attr("id")+" input").each( function (index, value) { value.value = index+1; }); });') ->setPageTitle(WT_I18N::translate('Re-order children')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; - ?> - <form name="reorder_form" method="post" action="edit_interface.php"> - <input type="hidden" name="action" value="reorder_update"> - <input type="hidden" name="pid" value="<?php echo $pid; ?>"> - <input type="hidden" name="option" value="bybirth"> - <ul id="reorder_list"> - <?php - // reorder children in modified families - $family = WT_Family::getInstance($pid); - $ids = array(); - foreach ($family->getChildren() as $child) { - $ids[]=$child->getXref(); - } - if ($family->getUpdatedFamily()) $family = $family->getUpdatedFamily(); - $children = array(); - foreach ($family->getChildren() as $k=>$child) { - $bdate = $child->getEstimatedBirthDate(); - if ($bdate->isOK()) { - $sortkey = $bdate->JD(); - } else { - $sortkey = 1e8; // birth date missing => sort last + <div id="edit_interface-page"> + <h4><?php echo $controller->getPageTitle(); ?></h4> + <form name="reorder_form" method="post" action="edit_interface.php"> + <input type="hidden" name="action" value="reorder_update"> + <input type="hidden" name="xref" value="<?php echo $xref; ?>"> + <input type="hidden" name="option" value="bybirth"> + <ul id="reorder_list"> + <?php + // reorder children in modified families + $ids = array(); + foreach ($family->getChildren() as $child) { + $ids[]=$child->getXref(); } - $children[$child->getXref()] = $sortkey; - } - if ((!empty($option))&&($option=="bybirth")) { - asort($children); - } - $i=0; - $show_full = 1; // Force details to show for each child - foreach ($children as $id=>$child) { - echo '<li style="cursor:move; margin-bottom:2px; position:relative;"'; - if (!in_array($id, $ids)) echo ' class="facts_valueblue"'; - echo ' id="li_',$id,'" >'; - print_pedigree_person(WT_Person::getInstance($id), 2); - echo '<input type="hidden" name="order[',$id,']" value="',$i,'">'; - echo '</li>'; - $i++; - } - echo '</ul>'; - if (WT_USER_IS_ADMIN) { - echo "<table width=93%><tr><td class=\"descriptionbox wrap width25\">"; - echo WT_Gedcom_Tag::getLabel('CHAN'), "</td><td class=\"optionbox wrap\">"; - echo '<input type="checkbox" name="preserve_last_changed"'; - if ($NO_UPDATE_CHAN) { - echo ' checked="checked"'; - } - echo '>'; - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'); - echo WT_Gedcom_Tag::getLabelValue('DATE', $family->LastChangeTimestamp()); - echo WT_Gedcom_Tag::getLabelValue('_WT_USER', $family->LastChangeUser()); - echo '</td></tr></table>'; - } - ?> - <p id="save-cancel"> - <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <button type="submit" class="save" onclick="document.reorder_form.action.value='reorder_children'; document.reorder_form.submit();"><?php echo WT_I18N::translate('sort by date of birth'); ?></button> - <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> - </p> - </form> + $children = array(); + foreach ($family->getChildren() as $k=>$child) { + $bdate = $child->getEstimatedBirthDate(); + if ($bdate->isOK()) { + $sortkey = $bdate->JD(); + } else { + $sortkey = 1e8; // birth date missing => sort last + } + $children[$child->getXref()] = $sortkey; + } + if ($option=='bybirth') { + asort($children); + } + $i=0; + $show_full = 1; // Force details to show for each child + foreach ($children as $id=>$child) { + echo '<li style="cursor:move; margin-bottom:2px; position:relative;"'; + if (!in_array($id, $ids)) echo ' class="facts_value new"'; + echo ' id="li_',$id,'" >'; + print_pedigree_person(WT_Individual::getInstance($id), 2); + echo '<input type="hidden" name="order[',$id,']" value="',$i,'">'; + echo '</li>'; + $i++; + } + echo '</ul>'; + ?> + <table> + <?php echo keep_chan($family); ?> + </table> + <p id="save-cancel"> + <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> + <input type="submit" class="save" onclick="document.reorder_form.action.value='reorder_children'; document.reorder_form.submit();" value="<?php echo WT_I18N::translate('sort by date of birth'); ?>"> + <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> + </p> + </form> </div><!-- id="edit_interface-page" --> <?php break; //////////////////////////////////////////////////////////////////////////////// case 'changefamily': - $famid = safe_GET('famid', WT_REGEX_XREF); - $family = WT_Family::getInstance($famid); + $xref = safe_GET('xref', WT_REGEX_XREF); + + $family = WT_Family::getInstance($xref); + check_record_access($family); $controller ->setPageTitle(WT_I18N::translate('Change Family Members')) - ->pageHeader(); - - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; + ->pageHeader() + ->addInlineJavascript(' + function pastename(name) { + if (nameElement) { + nameElement.innerHTML = name; + } + if (remElement) { + remElement.style.display = "block"; + } + } + '); $father = $family->getHusband(); $mother = $family->getWife(); @@ -2111,95 +1697,134 @@ case 'changefamily': } } ?> - <script> - function pastename(name) { - if (nameElement) { - nameElement.innerHTML = name; - } - if (remElement) { - remElement.style.display = 'block'; - } - } - </script> - <div id="changefam"> - <p> - <?php echo WT_I18N::translate('Use this page to change or remove family members.<br /><br />For each member in the family, you can use the Change link to choose a different person to fill that role in the family. You can also use the Remove link to remove that person from the family.<br /><br />When you have finished changing the family members, click the Save button to save the changes.'); ?> - </p> - <form name="changefamform" method="post" action="edit_interface.php"> - <input type="hidden" name="action" value="changefamily_update"> - <input type="hidden" name="famid" value="<?php echo $famid; ?>"> - <table> - <tr> - <?php if ($father) { ?> - <td class="descriptionbox"><b><?php echo $father->getLabel(); ?></b><input type="hidden" name="HUSB" value="<?php echo $father->getXref(); ?>"></td> - <td id="HUSBName" class="optionbox"><?php echo $father->getFullName(); ?></td> - <?php } else { ?> - <td class="descriptionbox"><b><?php echo WT_I18N::translate('spouse'); ?></b><input type="hidden" name="HUSB" value=""></td> - <td id="HUSBName" class="optionbox"></td> - <?php } ?> - <td class="optionbox"> - <a href="#" id="husbrem" style="display: <?php echo is_null($father) ? 'none':'block'; ?>;" onclick="document.changefamform.HUSB.value=''; document.getElementById('HUSBName').innerHTML=''; this.style.display='none'; return false;"><?php echo WT_I18N::translate('Remove'); ?></a> - </td> - <td class="optionbox"> - <a href="#" onclick="return findIndi(document.changefamform.HUSB, document.getElementById('HUSBName'));"><?php echo WT_I18N::translate('Change'); ?></a> - </td> - </tr> - <tr> - <?php if ($mother) { ?> - <td class="descriptionbox"><b><?php echo $mother->getLabel(); ?></b><input type="hidden" name="WIFE" value="<?php echo $mother->getXref(); ?>"></td> - <td id="WIFEName" class="optionbox"><?php echo $mother->getFullName(); ?></td> - <?php } else { ?> - <td class="descriptionbox"><b><?php echo WT_I18N::translate('spouse'); ?></b><input type="hidden" name="WIFE" value=""></td> - <td id="WIFEName" class="optionbox"></td> - <?php } ?> - <td class="optionbox"> - <a href="#" id="wiferem" style="display: <?php echo is_null($mother) ? 'none':'block'; ?>;" onclick="document.changefamform.WIFE.value=''; document.getElementById('WIFEName').innerHTML=''; this.style.display='none'; return false;"><?php echo WT_I18N::translate('Remove'); ?></a> - </td> - <td class="optionbox"> - <a href="#" onclick="return findIndi(document.changefamform.WIFEdocument.getElementById('WIFEName'));"><?php echo WT_I18N::translate('Change'); ?></a> - </td> - </tr> - <?php $i=0; foreach ($children as $child) { ?> - <tr> - <td class="descriptionbox"><b><?php echo $child->getLabel(); ?></b><input type="hidden" name="CHIL<?php echo $i; ?>" value="<?php echo $child->getXref(); ?>"></td> - <td id="CHILName<?php echo $i; ?>" class="optionbox"><?php echo $child->getFullName(); ?></td> - <td class="optionbox"> - <a href="#" id="childrem<?php echo $i; ?>" style="display: block;" onclick="document.changefamform.CHIL<?php echo $i; ?>.value=''; document.getElementById('CHILName<?php echo $i; ?>').innerHTML=''; this.style.display='none'; return false;"><?php echo WT_I18N::translate('Remove'); ?></a> - </td> - <td class="optionbox"> - <a href="#" onclick="return findIndi(document.changefamform.CHIL<?php echo $i; ?>, document.getElementById('CHILName<?php echo $i; ?>'));"><?php echo WT_I18N::translate('Change'); ?></a> - </td> - </tr> - <?php $i++; } ?> - <tr> - <td class="descriptionbox"><b><?php echo WT_I18N::translate('child'); ?></b><input type="hidden" name="CHIL<?php echo $i; ?>" value=""></td> - <td id="CHILName<?php echo $i; ?>" class="optionbox"></td> - <td colspan="2" class="optionbox child"> - <a href="#" id="childrem<?php echo $i; ?>" style="display: none;" onclick="document.changefamform.CHIL<?php echo $i; ?>.value=''; document.getElementById('CHILName<?php echo $i; ?>').innerHTML=''; this.style.display='none'; return false;"><?php echo WT_I18N::translate('Remove'); ?></a> - <a href="#" onclick="remElement = document.getElementById('childrem<?php echo $i; ?>'); return findIndi(document.changefamform.CHIL<?php echo $i; ?>, document.getElementById('CHILName<?php echo $i; ?>'));"><?php echo WT_I18N::translate('Add'); ?></a> - </td> - </tr> - </table> - <p id="save-cancel"> - <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> - </p> - </form> + <div id="edit_interface-page"> + <h4><?php echo $controller->getPageTitle(); ?></h4> + <div id="changefam"> + <p> + <?php echo WT_I18N::translate('Use this page to change or remove family members.<br /><br />For each member in the family, you can use the Change link to choose a different person to fill that role in the family. You can also use the Remove link to remove that person from the family.<br /><br />When you have finished changing the family members, click the Save button to save the changes.'); ?> + </p> + <form name="changefamform" method="post" action="edit_interface.php"> + <input type="hidden" name="action" value="changefamily_update"> + <input type="hidden" name="xref" value="<?php echo $xref; ?>"> + <table> + <tr> + <?php if ($father) { ?> + <td class="descriptionbox"> + <b><?php echo $father->getLabel(); ?></b> + <input type="hidden" name="HUSB" value="<?php echo $father->getXref(); ?>"> + </td> + <td id="HUSBName" class="optionbox"><?php echo $father->getFullName(); ?> + </td> + <?php } else { ?> + <td class="descriptionbox"> + <b><?php echo WT_I18N::translate('spouse'); ?></b> + <input type="hidden" name="HUSB" value=""> + </td> + <td id="HUSBName" class="optionbox"> + </td> + <?php } ?> + <td class="optionbox"> + <a href="#" id="husbrem" style="display: <?php echo is_null($father) ? 'none':'block'; ?>;" onclick="document.changefamform.HUSB.value=''; document.getElementById('HUSBName').innerHTML=''; this.style.display='none'; return false;"> + <?php echo WT_I18N::translate('Remove'); ?> + </a> + </td> + <td class="optionbox"> + <a href="#" onclick="return findIndi(document.changefamform.HUSB, document.getElementById('HUSBName'));"> + <?php echo WT_I18N::translate('Change'); ?> + </a> + </td> + </tr> + <tr> + <?php if ($mother) { ?> + <td class="descriptionbox"> + <b><?php echo $mother->getLabel(); ?></b> + <input type="hidden" name="WIFE" value="<?php echo $mother->getXref(); ?>"> + </td> + <td id="WIFEName" class="optionbox"> + <?php echo $mother->getFullName(); ?> + </td> + <?php } else { ?> + <td class="descriptionbox"> + <b><?php echo WT_I18N::translate('spouse'); ?></b> + <input type="hidden" name="WIFE" value=""> + </td> + <td id="WIFEName" class="optionbox"> + </td> + <?php } ?> + <td class="optionbox"> + <a href="#" id="wiferem" style="display: <?php echo is_null($mother) ? 'none':'block'; ?>;" onclick="document.changefamform.WIFE.value=''; document.getElementById('WIFEName').innerHTML=''; this.style.display='none'; return false;"> + <?php echo WT_I18N::translate('Remove'); ?> + </a> + </td> + <td class="optionbox"> + <a href="#" onclick="return findIndi(document.changefamform.WIFEdocument.getElementById('WIFEName'));"> + <?php echo WT_I18N::translate('Change'); ?> + </a> + </td> + </tr> + <?php $i=0; foreach ($children as $child) { ?> + <tr> + <td class="descriptionbox"> + <b><?php echo $child->getLabel(); ?></b> + <input type="hidden" name="CHIL<?php echo $i; ?>" value="<?php echo $child->getXref(); ?>"> + </td> + <td id="CHILName<?php echo $i; ?>" class="optionbox"><?php echo $child->getFullName(); ?> + </td> + <td class="optionbox"> + <a href="#" id="childrem<?php echo $i; ?>" style="display: block;" onclick="document.changefamform.CHIL<?php echo $i; ?>.value=''; document.getElementById('CHILName<?php echo $i; ?>').innerHTML=''; this.style.display='none'; return false;"> + <?php echo WT_I18N::translate('Remove'); ?> + </a> + </td> + <td class="optionbox"> + <a href="#" onclick="return findIndi(document.changefamform.CHIL<?php echo $i; ?>, document.getElementById('CHILName<?php echo $i; ?>'));"> + <?php echo WT_I18N::translate('Change'); ?> + </a> + </td> + </tr> + <?php $i++; } ?> + <tr> + <td class="descriptionbox"> + <b><?php echo WT_I18N::translate('child'); ?></b> + <input type="hidden" name="CHIL<?php echo $i; ?>" value=""> + </td> + <td id="CHILName<?php echo $i; ?>" class="optionbox"> + </td> + <td colspan="2" class="optionbox child"> + <a href="#" id="childrem<?php echo $i; ?>" style="display: none;" onclick="document.changefamform.CHIL<?php echo $i; ?>.value=''; document.getElementById('CHILName<?php echo $i; ?>').innerHTML=''; this.style.display='none'; return false;"> + <?php echo WT_I18N::translate('Remove'); ?> + </a> + <a href="#" onclick="remElement = document.getElementById('childrem<?php echo $i; ?>'); return findIndi(document.changefamform.CHIL<?php echo $i; ?>, document.getElementById('CHILName<?php echo $i; ?>'));"> + <?php echo WT_I18N::translate('Add'); ?> + </a> + </td> + </tr> + </table> + <p id="save-cancel"> + <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> + <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> + </p> + </form> + </div><!-- id="changefam" --> </div><!-- id="edit_interface-page" --> - </div><!-- id="changefam" --> <?php break; //////////////////////////////////////////////////////////////////////////////// case 'changefamily_update': + $xref = safe_POST('xref', WT_REGEX_XREF); + + $family = WT_Family::getInstance($xref); + check_record_access($family); + $controller ->setPageTitle(WT_I18N::translate('Change Family Members')) ->pageHeader(); - $family = new WT_Family($gedrec); - $father = $family->getHusband(); - $mother = $family->getWife(); + $father = $family->getHusband(); + $mother = $family->getWife(); $children = $family->getChildren(); + + $gedrec = $family->getGedcom(); $updated = false; //-- add the new father link if (isset($_REQUEST['HUSB'])) $HUSB = $_REQUEST['HUSB']; @@ -2209,10 +1834,10 @@ case 'changefamily_update': } else { $gedrec .= "\n1 HUSB @$HUSB@"; } - $indirec = find_gedcom_record($HUSB, WT_GED_ID, true); - if (!empty($indirec) && (strpos($indirec, "1 FAMS @$famid@")===false)) { - $indirec .= "\n1 FAMS @$famid@"; - replace_gedrec($HUSB, WT_GED_ID, $indirec, $update_CHAN); + $indirec = $father->getGedcom(); + if (!empty($indirec) && (strpos($indirec, "1 FAMS @$xref@")===false)) { + $indirec .= "\n1 FAMS @$xref@"; + $father->updateRecord($indirec, $update_CHAN); } $updated = true; } @@ -2233,7 +1858,7 @@ case 'changefamily_update': //-- remove the FAMS link from the old father if (!is_null($father) && $father->getXref()!=$HUSB) { $indirec = find_gedcom_record($father->getXref(), WT_GED_ID, true); - $pos1 = strpos($indirec, "1 FAMS @$famid@"); + $pos1 = strpos($indirec, "1 FAMS @$xref@"); if ($pos1!==false) { $pos2 = strpos($indirec, "\n1", $pos1+5); if ($pos2===false) { @@ -2242,7 +1867,7 @@ case 'changefamily_update': $pos2++; } $indirec = substr($indirec, 0, $pos1) . substr($indirec, $pos2); - replace_gedrec($father->getXref(), WT_GED_ID, $indirec, $update_CHAN); + $father->updateRecord($indirec, $update_CHAN); } } //-- add the new mother link @@ -2254,9 +1879,10 @@ case 'changefamily_update': $gedrec .= "\n1 WIFE @$WIFE@"; } $indirec = find_gedcom_record($WIFE, WT_GED_ID, true); - if (!empty($indirec) && (strpos($indirec, "1 FAMS @$famid@")===false)) { - $indirec .= "\n1 FAMS @$famid@"; - replace_gedrec($WIFE, WT_GED_ID, $indirec, $update_CHAN); + if (!empty($indirec) && (strpos($indirec, "1 FAMS @$xref@")===false)) { + $indirec .= "\n1 FAMS @$xref@"; + $record = WT_GedcomRecord::getInstance($WI); + $record->updateRecord($indirec, $update_CHAN); } $updated = true; } @@ -2277,7 +1903,7 @@ case 'changefamily_update': //-- remove the FAMS link from the old father if (!is_null($mother) && $mother->getXref()!=$WIFE) { $indirec = find_gedcom_record($mother->getXref(), WT_GED_ID, true); - $pos1 = strpos($indirec, "1 FAMS @$famid@"); + $pos1 = strpos($indirec, "1 FAMS @$xref@"); if ($pos1!==false) { $pos2 = strpos($indirec, "\n1", $pos1+5); if ($pos2===false) { @@ -2286,7 +1912,7 @@ case 'changefamily_update': $pos2++; } $indirec = substr($indirec, 0, $pos1) . substr($indirec, $pos2); - replace_gedrec($mother->getXref(), WT_GED_ID, $indirec, $update_CHAN); + $mother->updateRecord($indirec, $update_CHAN); } } @@ -2302,9 +1928,10 @@ case 'changefamily_update': $gedrec .= "\n1 CHIL @$CHIL@"; $updated = true; $indirec = find_gedcom_record($CHIL, WT_GED_ID, true); - if (!empty($indirec) && (strpos($indirec, "1 FAMC @$famid@")===false)) { - $indirec .= "\n1 FAMC @$famid@"; - replace_gedrec($CHIL, WT_GED_ID, $indirec, $update_CHAN); + if (!empty($indirec) && (strpos($indirec, "1 FAMC @$xref@")===false)) { + $indirec .= "\n1 FAMC @$xref@"; + $record = WT_GedcomRecord::getInstance($CHIL); + $record->updateRecord($indirec, $update_CHAN); } } } @@ -2330,7 +1957,7 @@ case 'changefamily_update': } //-- remove the FAMC link from the child record $indirec = find_gedcom_record($child->getXref(), WT_GED_ID, true); - $pos1 = strpos($indirec, "1 FAMC @$famid@"); + $pos1 = strpos($indirec, "1 FAMC @$xref@"); if ($pos1!==false) { $pos2 = strpos($indirec, "\n1", $pos1+5); if ($pos2===false) { @@ -2339,49 +1966,65 @@ case 'changefamily_update': $pos2++; } $indirec = substr($indirec, 0, $pos1) . substr($indirec, $pos2); - replace_gedrec($child->getXref(), WT_GED_ID, $indirec, $update_CHAN); + $child->updateRecord($indirec, $update_CHAN); } } } } if ($updated) { - $success = replace_gedrec($famid, WT_GED_ID, $gedrec, $update_CHAN); - } else { - $success = false; + $record = WT_Family::getInstance($xref); + $record->updateRecord($gedrec, $update_CHAN); } - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// case 'reorder_update': + $xref = safe_POST('xref', WT_REGEX_XREF); + $order = safe_POST('order'); + $keep_chan = safe_POST_bool('keep_chan'); + + $family = WT_Family::getInstance($xref); + check_record_access($family); + $controller ->setPageTitle(WT_I18N::translate('Re-order children')) ->pageHeader(); - if (isset($_REQUEST['order'])) $order = $_REQUEST['order']; - asort($order); - reset($order); - $newgedrec = $gedrec; - foreach ($order as $child=>$num) { - // move each child subrecord to the bottom, in the order specified - $subrec = get_sub_record(1, '1 CHIL @'.$child.'@', $gedrec); - $subrec = trim($subrec, "\n"); - $newgedrec = str_replace($subrec, '', $newgedrec); - $newgedrec .= "\n".$subrec."\n"; - } - $success = replace_gedrec($pid, WT_GED_ID, $newgedrec, $update_CHAN); + if (is_array($order)) { + $gedcom = array('0 @' . $family->getXref() . '@ FAM'); + $facts = $family->getFacts(); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); + // Move children to the end of the record + foreach ($order as $child=>$num) { + foreach ($facts as $n=>$fact) { + if ($fact->getValue() == '@'.$child.'@') { + $facts[]=$fact; + unset($facts[$n]); + break; + } + } + } + foreach ($facts as $fact) { + $gedcom[] = $fact->getGedcom(); + } + + $family->updateRecord(implode("\n", $gedcom), !$keep_chan); } + + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; //////////////////////////////////////////////////////////////////////////////// case 'reorder_fams': + $xref = safe_GET('xref', WT_REGEX_XREF); + $option = safe_GET('option'); + + $person = WT_Individual::getInstance($xref); + check_record_access($person); + $controller ->addInlineJavascript('jQuery("#reorder_list").sortable({forceHelperSize: true, forcePlaceholderSize: true, opacity: 0.7, cursor: "move", axis: "y"});') //-- update the order numbers after drag-n-drop sorting is complete @@ -2389,35 +2032,30 @@ case 'reorder_fams': ->setPageTitle(WT_I18N::translate('Re-order families')) ->pageHeader(); - echo '<div id="edit_interface-page">'; - echo '<h4>', $controller->getPageTitle(), '</h4>'; + $fams = $person->getSpouseFamilies(); + if ($option=='bymarriage') { + usort($fams, array('WT_Family', 'CompareMarrDate')); + } ?> + <div id="edit_interface-page"> + <h4><?php echo $controller->getPageTitle(); ?></h4> <form name="reorder_form" method="post" action="edit_interface.php"> <input type="hidden" name="action" value="reorder_fams_update"> - <input type="hidden" name="pid" value="<?php echo $pid; ?>"> + <input type="hidden" name="xref" value="<?php echo $xref; ?>"> <input type="hidden" name="option" value="bymarriage"> <ul id="reorder_list"> - <?php - $person = WT_Person::getInstance($pid); - $fams = $person->getSpouseFamilies(); - if ((!empty($option))&&($option=="bymarriage")) { - usort($fams, array('WT_Family', 'CompareMarrDate')); - } - $i=0; - foreach ($fams as $family) { - echo '<li class="facts_value" style="cursor:move;margin-bottom:2px;" id="li_', $family->getXref(), '" >'; - echo '<span class="name2">', $family->getFullName(), '</span><br>'; - echo $family->format_first_major_fact(WT_EVENTS_MARR, 2); - echo '<input type="hidden" name="order[', $family->getXref(), ']" value="', $i, '">'; - echo '</li>'; - $i++; - } - ?> + <?php foreach ($fams as $n=>$family) { ?> + <li class="facts_value" style="cursor:move;margin-bottom:2px;" id="li_<?php echo $family->getXref(); ?>" > + <div class="name2"><?php echo $family->getFullName(); ?></div> + <?php echo $family->format_first_major_fact(WT_EVENTS_MARR, 2); ?> + <input type="hidden" name="order[<?php echo $family->getXref(); ?>]" value="<?php echo $n; ?>"> + </li> + <?php } ?> </ul> <p id="save-cancel"> <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <button type="submit" class="save" onclick="document.reorder_form.action.value='reorder_fams'; document.reorder_form.submit();"><?php echo WT_I18N::translate('sort by date of marriage'); ?></button> + <input type="submit" class="save" onclick="document.reorder_form.action.value='reorder_fams'; document.reorder_form.submit();" value="<?php echo WT_I18N::translate('sort by date of marriage'); ?>"> <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> </p> </form> @@ -2427,51 +2065,709 @@ case 'reorder_fams': //////////////////////////////////////////////////////////////////////////////// case 'reorder_fams_update': + $xref = safe_POST('xref', WT_REGEX_XREF); + $order = safe_POST('order'); + $keep_chan = safe_POST_bool('keep_chan'); + + $person = WT_Individual::getInstance($xref); + check_record_access($person); + $controller ->setPageTitle(WT_I18N::translate('Re-order families')) ->pageHeader(); - if (isset($_REQUEST['order'])) $order = $_REQUEST['order']; - asort($order); - reset($order); - $lines = explode("\n", $gedrec); - $newgedrec = ""; - foreach ($lines as $line) { - if (strpos($line, "1 FAMS")===false) { - $newgedrec .= $line."\n"; + if (is_array($order)) { + $gedcom = array('0 @' . $person->getXref() . '@ INDI'); + $facts = $person->getFacts(); + + // Move families to the end of the record + foreach ($order as $family=>$num) { + foreach ($facts as $n=>$fact) { + if ($fact->getValue() == '@'.$family.'@') { + $facts[]=$fact; + unset($facts[$n]); + break; + } + } } + foreach ($facts as $fact) { + $gedcom[] = $fact->getGedcom(); + } + + $person->updateRecord(implode("\n", $gedcom), !$keep_chan); } - foreach ($order as $famid=>$num) { - $newgedrec .= "\n1 FAMS @".$famid."@"; - } - $success = replace_gedrec($pid, WT_GED_ID, $newgedrec, $update_CHAN); - if ($success && !WT_DEBUG) { - $controller->addInlineJavascript('closePopupAndReloadParent();'); - } + $controller->addInlineJavascript('closePopupAndReloadParent();'); break; } // Keep the existing CHAN record when editing -function no_update_chan(WT_GedcomRecord $record) { +function keep_chan(WT_GedcomRecord $record=null) { global $NO_UPDATE_CHAN; - $checked = $NO_UPDATE_CHAN ? ' checked="checked"' : ''; - if (WT_USER_IS_ADMIN) { + $checked = $NO_UPDATE_CHAN ? ' checked="checked"' : ''; + + if ($record) { + $details = + WT_Gedcom_Tag::getLabelValue('DATE', $record->LastChangeTimestamp()) . + WT_Gedcom_Tag::getLabelValue('_WT_USER', $record->LastChangeUser()); + } else { + $details = ''; + } + return '<table class="facts_table">' . '<tr><td class="descriptionbox wrap width25">' . WT_Gedcom_Tag::getLabel('CHAN') . '</td><td class="optionbox wrap">' . - '<input type="checkbox" name="preserve_last_changed"' . $checked . '>' . + '<input type="checkbox" name="keep_chan"' . $checked . '>' . WT_I18N::translate('Do not update the “last change” record') . help_link('no_update_CHAN') . - WT_Gedcom_Tag::getLabelValue('DATE', $record->LastChangeTimestamp()) . - WT_Gedcom_Tag::getLabelValue('_WT_USER', $record->LastChangeUser()) . + $details; '</td></tr>' . '</table>'; } else { return ''; } } + +// prints a form to add an individual or edit an individual's name +function print_indi_form($nextaction, WT_Individual $person=null, WT_Family $family=null, WT_Fact $name_fact=null, $famtag='CHIL', $sextag='U') { + global $WORD_WRAPPED_NOTES; + global $NPFX_accept, $SPFX_accept, $NSFX_accept, $FILE_FORM_accept; + global $bdm, $STANDARD_NAME_FACTS, $REVERSED_NAME_FACTS, $ADVANCED_NAME_FACTS, $ADVANCED_PLAC_FACTS; + global $QUICK_REQUIRED_FACTS, $QUICK_REQUIRED_FAMFACTS, $NO_UPDATE_CHAN, $controller; + + $SURNAME_TRADITION=get_gedcom_setting(WT_GED_ID, 'SURNAME_TRADITION'); + + if ($person) { + $xref = $person->getXref(); + } else { + $xref = null; + } + if ($family) { + $famid = $family->getXref(); + } else { + $famid = null; + } + if ($name_fact) { + $name_fact_id = $name_fact->getFactId(); + $name_type = $name_fact->getAttribute('TYPE'); + $namerec = $name_fact->getGedcom(); + // Populate the standard NAME field and subfields + foreach ($STANDARD_NAME_FACTS as $tag) { + $name_fields[$tag] = $name_fact->getAttribute($tag); + } + } else { + $name_fact_id = null; + $name_type = null; + $name_fields = array(); + $namerec = null; + // Populate the standard NAME field and subfields + foreach ($STANDARD_NAME_FACTS as $tag) { + $name_fields[$tag] = ''; + } + } + + $bdm = ''; // used to copy '1 SOUR' to '2 SOUR' for BIRT DEAT MARR + + echo '<div id="edit_interface-page">'; + echo '<h4>', $controller->getPageTitle(), '</h4>'; + init_calendar_popup(); + echo "<form method=\"post\" name=\"addchildform\" onsubmit=\"return checkform();\">"; + echo "<input type=\"hidden\" name=\"action\" value=\"$nextaction\">"; + echo "<input type=\"hidden\" name=\"fact_id\" value=\"$name_fact_id\">"; + echo "<input type=\"hidden\" name=\"famid\" value=\"$famid\">"; + echo "<input type=\"hidden\" name=\"xref\" value=\"$xref\">"; + echo "<input type=\"hidden\" name=\"famtag\" value=\"$famtag\">"; + echo "<input type=\"hidden\" name=\"goto\" value=\"\">"; // set by javascript + echo "<table class=\"facts_table\">"; + + switch ($nextaction) { + case 'addchildaction': + case 'addopfchildaction': + // When adding a new child, specify the pedigree + add_simple_tag('0 PEDI'); + break; + case 'update': + // When adding/editing a name, specify the type + add_simple_tag('0 TYPE '.$name_type); + break; + } + + $new_marnm=''; + // Inherit surname from parents, spouse or child + if (!$namerec) { + // We'll need the parent's name to set the child's surname + $family=WT_Family::getInstance($famid); + if ($family && $family->getHusband()) { + $father_name=get_gedcom_value('NAME', 0, $family->getHusband()->getGedcom()); + } else { + $father_name=''; + } + if ($family && $family->getWife()) { + $mother_name=get_gedcom_value('NAME', 0, $family->getWife()->getGedcom()); + } else { + $mother_name=''; + } + // We'll need the spouse/child's name to set the spouse/parent's surname + $prec=find_gedcom_record($xref, WT_GED_ID, true); + $indi_name=get_gedcom_value('NAME', 0, $prec); + // Different cultures do surnames differently + switch ($SURNAME_TRADITION) { + case 'spanish': + //Mother: Maria /AAAA BBBB/ + //Father: Jose /CCCC DDDD/ + //Child: Pablo /CCCC AAAA/ + switch ($nextaction) { + case 'addchildaction': + if (preg_match('/\/(\S+)\s+\S+\//', $mother_name, $matchm) && + preg_match('/\/(\S+)\s+\S+\//', $father_name, $matchf)) { + $name_fields['SURN']=$matchf[1].' '.$matchm[1]; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + break; + case 'addnewparentaction': + if ($famtag=='HUSB' && preg_match('/\/(\S+)\s+\S+\//', $indi_name, $match)) { + $name_fields['SURN']=$match[1].' '; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + if ($famtag=='WIFE' && preg_match('/\/\S+\s+(\S+)\//', $indi_name, $match)) { + $name_fields['SURN']=$match[1].' '; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + break; + } + break; + case 'portuguese': + //Mother: Maria /AAAA BBBB/ + //Father: Jose /CCCC DDDD/ + //Child: Pablo /BBBB DDDD/ + switch ($nextaction) { + case 'addchildaction': + if (preg_match('/\/\S+\s+(\S+)\//', $mother_name, $matchm) && + preg_match('/\/\S+\s+(\S+)\//', $father_name, $matchf)) { + $name_fields['SURN']=$matchf[1].' '.$matchm[1]; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + break; + case 'addnewparentaction': + if ($famtag=='HUSB' && preg_match('/\/\S+\s+(\S+)\//', $indi_name, $match)) { + $name_fields['SURN']=' '.$match[1]; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + if ($famtag=='WIFE' && preg_match('/\/(\S+)\s+\S+\//', $indi_name, $match)) { + $name_fields['SURN']=' '.$match[1]; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + break; + } + break; + case 'icelandic': + // Sons get their father's given name plus "sson" + // Daughters get their father's given name plus "sdottir" + switch ($nextaction) { + case 'addchildaction': + if ($sextag=='M' && preg_match('/(\S+)\s+\/.*\//', $father_name, $match)) { + $name_fields['SURN']=preg_replace('/s$/', '', $match[1]).'sson'; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + if ($sextag=='F' && preg_match('/(\S+)\s+\/.*\//', $father_name, $match)) { + $name_fields['SURN']=preg_replace('/s$/', '', $match[1]).'sdottir'; + $name_fields['NAME']='/'.$name_fields['SURN'].'/'; + } + break; + case 'addnewparentaction': + if ($famtag=='HUSB' && preg_match('/(\S+)sson\s+\/.*\//i', $indi_name, $match)) { + $name_fields['GIVN']=$match[1]; + $name_fields['NAME']=$name_fields['GIVN'].' //'; + } + if ($famtag=='WIFE' && preg_match('/(\S+)sdottir\s+\/.*\//i', $indi_name, $match)) { + $name_fields['GIVN']=$match[1]; + $name_fields['NAME']=$name_fields['GIVN'].' //'; + } + break; + } + break; + case 'patrilineal': + // Father gives his surname to his children + switch ($nextaction) { + case 'addchildaction': + if (preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $father_name, $match)) { + $name_fields['SURN']=$match[2]; + $name_fields['SPFX']=trim($match[1]); + $name_fields['NAME']="/{$match[1]}{$match[2]}/"; + } + break; + case 'addnewparentaction': + if ($famtag=='HUSB' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { + $name_fields['SURN']=$match[2]; + $name_fields['SPFX']=trim($match[1]); + $name_fields['NAME']="/{$match[1]}{$match[2]}/"; + } + break; + } + break; + case 'matrilineal': + // Mother gives her surname to her children + switch ($nextaction) { + case 'addchildaction': + if (preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $mother, $match)) { + $name_fields['SURN']=$match[2]; + $name_fields['SPFX']=trim($match[1]); + $name_fields['NAME']="/{$match[1]}{$match[2]}/"; + } + break; + case 'addnewparentaction': + if ($famtag=='WIFE' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { + $name_fields['SURN']=$match[2]; + $name_fields['SPFX']=trim($match[1]); + $name_fields['NAME']="/{$match[1]}{$match[2]}/"; + } + break; + } + break; + case 'paternal': + case 'polish': + case 'lithuanian': + // Father gives his surname to his wife and children + switch ($nextaction) { + case 'addspouseaction': + if ($famtag=='WIFE' && preg_match('/\/(.*)\//', $indi_name, $match)) { + if ($SURNAME_TRADITION=='polish') { + $match[1]=preg_replace(array('/ski$/', '/cki$/', '/dzki$/', '/żki$/'), array('ska', 'cka', 'dzka', 'żka'), $match[1]); + } else if ($SURNAME_TRADITION=='lithuanian') { + $match[1]=preg_replace(array('/as$/', '/is$/', '/ys$/', '/us$/'), array('ienė', 'ienė', 'ienė', 'ienė'), $match[1]); + } + $new_marnm=$match[1]; + } + break; + case 'addchildaction': + if (preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $father_name, $match)) { + $name_fields['SURN']=$match[2]; + if ($SURNAME_TRADITION=='polish' && $sextag=='F') { + $match[2]=preg_replace(array('/ski$/', '/cki$/', '/dzki$/', '/żki$/'), array('ska', 'cka', 'dzka', 'żka'), $match[2]); + } else if ($SURNAME_TRADITION=='lithuanian' && $sextag=='F') { + $match[2]=preg_replace(array('/as$/', '/a$/', '/is$/', '/ys$/', '/ius$/', '/us$/'), array('aitė', 'aitė', 'ytė', 'ytė', 'iūtė', 'utė'), $match[2]); + } + $name_fields['SPFX']=trim($match[1]); + $name_fields['NAME']="/{$match[1]}{$match[2]}/"; + } + break; + case 'addnewparentaction': + if ($famtag=='HUSB' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { + if ($SURNAME_TRADITION=='polish' && $sextag=='M') { + $match[2]=preg_replace(array('/ska$/', '/cka$/', '/dzka$/', '/żka$/'), array('ski', 'cki', 'dzki', 'żki'), $match[2]); + } else if ($SURNAME_TRADITION=='lithuanian') { + // not a complete list as the rules are somewhat complicated but will do 95% correctly + $match[2]=preg_replace(array('/aitė$/', '/ytė$/', '/iūtė$/', '/utė$/'), array('as', 'is', 'ius', 'us'), $match[2]); + } + $name_fields['SPFX']=trim($match[1]); + $name_fields['SURN']=$match[2]; + $name_fields['NAME']="/{$match[1]}{$match[2]}/"; + } + if ($famtag=='WIFE' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { + if ($SURNAME_TRADITION=='lithuanian') { + $match[2]=preg_replace(array('/as$/', '/is$/', '/ys$/', '/us$/'), array('ienė', 'ienė', 'ienė', 'ienė'), $match[2]); + $match[2]=preg_replace(array('/aitė$/', '/ytė$/', '/iūtė$/', '/utė$/'), array('ienė', 'ienė', 'ienė', 'ienė'), $match[2]); + $new_marnm=$match[2]; + } + } + break; + } + break; + } + } + + // Make sure there are two slashes in the name + if (!preg_match('/\//', $name_fields['NAME'])) + $name_fields['NAME'].=' /'; + if (!preg_match('/\/.*\//', $name_fields['NAME'])) + $name_fields['NAME'].='/'; + + // Populate any missing 2 XXXX fields from the 1 NAME field + $npfx_accept=implode('|', $NPFX_accept); + 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]; + } + // Don't automatically create an empty NICK - it is an "advanced" field. + if (empty($name_fields['NICK']) && !empty($name_bits[6]) && !preg_match('/^2 NICK/m', $namerec)) { + $name_fields['NICK']=$name_bits[6]; + } + } + + // Edit the standard name fields + foreach ($name_fields as $tag=>$value) { + add_simple_tag("0 $tag $value"); + } + + // Get the advanced name fields + $adv_name_fields=array(); + if (preg_match_all('/('.WT_REGEX_TAG.')/', $ADVANCED_NAME_FACTS, $match)) + foreach ($match[1] as $tag) + $adv_name_fields[$tag]=''; + // This is a custom tag, but webtrees uses it extensively. + if ($SURNAME_TRADITION=='paternal' || $SURNAME_TRADITION=='polish' || $SURNAME_TRADITION=='lithuanian' || (strpos($namerec, '2 _MARNM')!==false)) { + $adv_name_fields['_MARNM']=''; + } + $person = WT_Individual::getInstance($xref); + if (isset($adv_name_fields['TYPE'])) { + unset($adv_name_fields['TYPE']); + } + foreach ($adv_name_fields as $tag=>$dummy) { + // Edit existing tags + if (preg_match_all("/2 $tag (.+)/", $namerec, $match)) + foreach ($match[1] as $value) { + if ($tag=='_MARNM') { + $mnsct = preg_match('/\/(.+)\//', $value, $match2); + $marnm_surn = ''; + if ($mnsct>0) $marnm_surn = $match2[1]; + add_simple_tag("2 _MARNM ".$value); + add_simple_tag("2 _MARNM_SURN ".$marnm_surn); + } else { + add_simple_tag("2 $tag $value", '', WT_Gedcom_Tag::getLabel("NAME:{$tag}", $person)); + } + } + // Allow a new row to be entered if there was no row provided + if (count($match[1])==0 && empty($name_fields[$tag]) || $tag!='_HEB' && $tag!='NICK') + if ($tag=='_MARNM') { + if (strstr($ADVANCED_NAME_FACTS, '_MARNM')==false) { + add_simple_tag("0 _MARNM"); + add_simple_tag("0 _MARNM_SURN $new_marnm"); + } + } else { + add_simple_tag("0 $tag", '', WT_Gedcom_Tag::getLabel("NAME:{$tag}", $person)); + } + } + + // Handle any other NAME subfields that aren't included above (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]); + $level1type = $type; + $tags=array(); + $i = 0; + do { + if ($type!='TYPE' && !isset($name_fields[$type]) && !isset($adv_name_fields[$type])) { + $text = ''; + for ($j=2; $j<count($fields); $j++) { + if ($j>2) $text .= ' '; + $text .= $fields[$j]; + } + $iscont = false; + while (($i+1<count($gedlines))&&(preg_match("/".($level+1)." (CON[CT]) ?(.*)/", $gedlines[$i+1], $cmatch)>0)) { + $iscont=true; + if ($cmatch[1]=="CONT") $text.="\n"; + if ($WORD_WRAPPED_NOTES) $text .= ' '; + $text .= $cmatch[2]; + $i++; + } + add_simple_tag($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" || $sextag=="M") { + add_simple_tag("0 SEX M"); + } elseif ($famtag=="WIFE" || $sextag=="F") { + add_simple_tag("0 SEX F"); + } else { + add_simple_tag("0 SEX"); + } + $bdm = "BD"; + if (preg_match_all('/('.WT_REGEX_TAG.')/', $QUICK_REQUIRED_FACTS, $matches)) { + foreach ($matches[1] as $match) { + if (!in_array($match, explode('|', WT_EVENTS_DEAT))) { + addSimpleTags($match); + } + } + } + //-- if adding a spouse add the option to add a marriage fact to the new family + if ($nextaction=='addspouseaction' || ($nextaction=='addnewparentaction' && $famid!='new')) { + $bdm .= "M"; + if (preg_match_all('/('.WT_REGEX_TAG.')/', $QUICK_REQUIRED_FAMFACTS, $matches)) { + foreach ($matches[1] as $match) { + addSimpleTags($match); + } + } + } + if (preg_match_all('/('.WT_REGEX_TAG.')/', $QUICK_REQUIRED_FACTS, $matches)) { + foreach ($matches[1] as $match) { + if (in_array($match, explode('|', WT_EVENTS_DEAT))) { + addSimpleTags($match); + } + } + } + } + if (WT_USER_IS_ADMIN) { + echo "<tr><td class=\"descriptionbox wrap width25\">"; + echo WT_Gedcom_Tag::getLabel('CHAN'), "</td><td class=\"optionbox wrap\">"; + if ($NO_UPDATE_CHAN) { + echo "<input type=\"checkbox\" checked=\"checked\" name=\"preserve_last_changed\">"; + } else { + echo "<input type=\"checkbox\" name=\"preserve_last_changed\">"; + } + echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'), "<br>"; + if (isset($famrec)) { + $event = new WT_Fact(get_sub_record(1, "1 CHAN", $famrec), null, 0); + echo format_fact_date($event, new WT_Individual(''), false, true); + } + echo "</td></tr>"; + } + echo "</table>"; + if ($nextaction=='update') { // GEDCOM 5.5.1 spec says NAME doesn't get a OBJE + print_add_layer('SOUR'); + print_add_layer('NOTE'); + print_add_layer('SHARED_NOTE'); + } else { + print_add_layer('SOUR', 1); + print_add_layer('OBJE', 1); + print_add_layer('NOTE', 1); + print_add_layer('SHARED_NOTE', 1); + } + echo '<p id="save-cancel">'; + echo '<input type="submit" class="save" value="', /* I18N: button label */ WT_I18N::translate('save'), '">'; + if (preg_match('/^add(child|spouse|newparent)/', $nextaction)) { + echo '<input type="submit" class="save" value="', /* I18N: button label */ WT_I18N::translate('go to new individual'), '" onclick="document.addchildform.goto.value=\'new\';">'; + } + echo '<input type="button" class="cancel" value="', /* I18N: button label */ WT_I18N::translate('close'), '" onclick="window.close();">'; + echo '</p>'; + echo '</form>'; + $controller->addInlineJavascript(' + SURNAME_TRADITION="'.$SURNAME_TRADITION.'"; + sextag="'.$sextag.'"; + 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 frm =document.forms[0]; + var npfx=frm.NPFX.value; + var givn=frm.GIVN.value; + var spfx=frm.SPFX.value; + var surn=frm.SURN.value; + var nsfx=frm.NSFX.value; + if (SURNAME_TRADITION=="polish" && (sextag=="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; + // Update NAME field from components and display it + var frm =document.forms[0]; + var npfx=frm.NPFX.value; + var givn=frm.GIVN.value; + var spfx=frm.SPFX.value; + var surn=frm.SURN.value; + var nsfx=frm.NSFX.value; + document.getElementById("NAME").value=generate_name(); + document.getElementById("NAME_display").innerHTML=frm.NAME.value; + // 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=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(frm.NAME.value)==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; + } + } + } + } + + /** + * convert a hidden field to a text box + */ + var oldName = ""; + var manualChange = false; + function convertHidden(eid) { + var element = document.getElementById(eid); + if (element) { + if (element.type=="hidden") { + // IE doesn’t allow changing the "type" of an input field so we’ll cludge it ( silly :P) + if (IE) { + var newInput = document.createElement("input"); + newInput.setAttribute("type", "text"); + newInput.setAttribute("name", element.Name); + newInput.setAttribute("id", element.id); + newInput.setAttribute("value", element.value); + newInput.setAttribute("onchange", element.onchange); + var parent = element.parentNode; + parent.replaceChild(newInput, element); + element = newInput; + } + else { + element.type="text"; + } + element.size="40"; + oldName = element.value; + manualChange = true; + var delement = document.getElementById(eid+"_display"); + if (delement) { + delement.style.display="none"; + // force FF ui to update the display + if (delement.innerHTML != oldName) { + oldName = delement.innerHTML; + element.value = oldName; + } + } + } + else { + manualChange = false; + // IE doesn’t allow changing the "type" of an input field so we’ll cludge it ( silly :P) + if (IE) { + var newInput = document.createElement("input"); + newInput.setAttribute("type", "hidden"); + newInput.setAttribute("name", element.Name); + newInput.setAttribute("id", element.id); + newInput.setAttribute("value", element.value); + newInput.setAttribute("onchange", element.onchange); + var parent = element.parentNode; + parent.replaceChild(newInput, element); + element = newInput; + } + else { + element.type="hidden"; + } + var delement = document.getElementById(eid+"_display"); + if (delement) { + delement.style.display="inline"; + } + } + } + } + + /** + * 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><!-- id="edit_interface-page" -->'; +} + +// Can we edit a WT_GedcomRecord object +function check_record_access(WT_GedcomRecord $object=null) { + global $controller; + + if (!$object || !$object->canShow() || !$object->canEdit()) { + $controller + ->pageHeader() + ->addInlineJavascript('closePopupAndReloadParent();'); + exit; + } +} diff --git a/edituser.php b/edituser.php index 5c540a2477..159fabd57d 100644 --- a/edituser.php +++ b/edituser.php @@ -140,12 +140,12 @@ echo '<div id="edituser-page"> <div class="value"><input type="text" name="form_username" value="', WT_USER_NAME, '" autofocus></div> <div class="label">', WT_I18N::translate('Real name'), help_link('real_name'), '</div> <div class="value"><input type="text" name="form_realname" value="', getUserFullName(WT_USER_ID), '"></div>'; - $person=WT_Person::getInstance(WT_USER_GEDCOM_ID); + $person=WT_Individual::getInstance(WT_USER_GEDCOM_ID); if ($person) { echo '<div class="label">', WT_I18N::translate('Individual record'), help_link('edituser_gedcomid'), '</div> <div class="value">', $person->format_list('span'), '</div>'; } - $person=WT_Person::getInstance(WT_USER_ROOT_ID); + $person=WT_Individual::getInstance(WT_USER_ROOT_ID); echo '<div class="label">', WT_I18N::translate('Default individual'), help_link('default_individual'), '</div> <div class="value"><input type="text" name="form_rootid" id="rootid" value="', WT_USER_ROOT_ID, '">'; echo print_findindi_link('rootid'), '<br>'; diff --git a/expand_view.php b/expand_view.php index e7a796d96e..d5ca426583 100644 --- a/expand_view.php +++ b/expand_view.php @@ -2,7 +2,7 @@ // Used by AJAX to load the expanded view inside person boxes // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2008 PGV Development Team. All rights reserved. @@ -29,16 +29,20 @@ require './includes/session.php'; Zend_Session::writeClose(); header('Content-Type: text/html; charset=UTF-8'); -$person = WT_Person::getInstance(safe_GET_xref('pid')); -if (!$person || !$person->canDisplayDetails()) { +$person = WT_Individual::getInstance(safe_GET_xref('pid')); +if (!$person || !$person->canShow()) { return WT_I18N::translate('Private'); } -$person->add_family_facts(false); -$events=$person->getIndiFacts(); -sort_facts($events); +$facts = $person->getFacts(); +foreach ($person->getSpouseFamilies() as $family) { + foreach ($family->getFacts() as $fact) { + $facts[] = $fact; + } +} +sort_facts($facts); -foreach ($events as $event) { +foreach ($facts as $event) { if ($event->canShow()) { switch ($event->getTag()) { case 'SEX': @@ -78,18 +82,18 @@ foreach ($events as $event) { // Simple version of print_fact() echo '<div>'; echo '<span class="details_label">', $event->getLabel(), '</span> '; - $details=$event->getDetail(); + $details=$event->getValue(); if ($details!='Y' && $details!='N') { echo '<span dir="auto">', $details, '</span>'; } echo format_fact_date($event, $person, false, false); // Show spouse/family for family events - $spouse=$event->getSpouse(); - if ($spouse) { - echo ' <a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> - '; - } - if ($event->getParentObject() instanceof WT_Family) { - echo '<a href="', $event->getParentObject()->getHtmlUrl(), '">', WT_I18N::translate('View Family'), ' - </a>'; + if ($event->getParent() instanceof WT_Family) { + $spouse = $event->getParent()->getSpouse($person); + if ($spouse) { + echo ' <a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> - '; + } + echo '<a href="', $event->getParent()->getHtmlUrl(), '">', WT_I18N::translate('View Family'), ' - </a>'; } echo ' ',format_fact_place($event, true, true); echo '</div>'; diff --git a/family.php b/family.php index a311baa4fb..6790ce2af0 100644 --- a/family.php +++ b/family.php @@ -4,7 +4,7 @@ // You must supply a $famid value with the identifier for the family. // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -30,9 +30,9 @@ require './includes/session.php'; $controller=new WT_Controller_Family(); -if ($controller->record && $controller->record->canDisplayDetails()) { +if ($controller->record && $controller->record->canShow()) { $controller->pageHeader(); - if ($controller->record->isMarkedDeleted()) { + if ($controller->record->isOld()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -50,7 +50,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { ' ', help_link('pending_changes'), '</p>'; } - } elseif (find_updated_record($controller->record->getXref(), WT_GED_ID)!==null) { + } elseif ($controller->record->isNew()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -101,7 +101,7 @@ echo '</script>'; <table id="family-table" align="center" width="95%"> <tr valign="top"> <td valign="top" style="width: <?php echo $pbwidth+30; ?>px;"><!--//List of children//--> - <?php print_family_children($controller->record->getXref()); ?> + <?php print_family_children($controller->record); ?> </td> <td> <!--//parents pedigree chart and Family Details//--> <table width="100%"> @@ -111,36 +111,26 @@ echo '</script>'; </tr> <tr> <td colspan="2"> - <table><tr><td> <!--//parents pedigree chart //--> <?php - echo print_family_parents($controller->record->getXref()); + echo print_family_parents($controller->record); if (WT_USER_CAN_EDIT) { - if ($controller->diff_record) { - $husb=$controller->diff_record->getHusband(); - } else { - $husb=$controller->record->getHusband(); - } + $husb=$controller->record->getHusband(); if (!$husb) { echo '<a href="#" onclick="return addnewparentfamily(\'\', \'HUSB\', \'', $controller->record->getXref(), '\');">', WT_I18N::translate('Add a new father'), '</a><br>'; } - if ($controller->diff_record) { - $wife=$controller->diff_record->getWife(); - } else { - $wife=$controller->record->getWife(); - } + $wife=$controller->record->getWife(); if (!$wife) { echo '<a href="#" onclick="return addnewparentfamily(\'\', \'WIFE\', \'', $controller->record->getXref(), '\');">', WT_I18N::translate('Add a new mother'), '</a><br>'; } } ?> - </td></tr></table> </td> </tr> <tr> <td colspan="2"> <span class="subheaders"><?php echo WT_I18N::translate('Family Group Information'); ?></span> <?php - if ($controller->record->canDisplayDetails()) { + if ($controller->record->canShow()) { echo '<table class="facts_table">'; $controller->printFamilyFacts(); echo '</table>'; @@ -184,7 +184,7 @@ if ($type == "indi") { <span>', WT_I18N::translate('Name contains:'), ' </span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '"> + echo '" autofocus> <input type="submit" value="', WT_I18N::translate('Filter'), '"> </form></div>'; } @@ -199,7 +199,7 @@ if ($type == "fam") { <span>', WT_I18N::translate('Name contains:'), ' </span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '"> + echo '" autofocus> <input type="submit" value="', WT_I18N::translate('Filter'), '"> </form></div>'; } @@ -216,7 +216,7 @@ if ($type == 'media') { <span>', WT_I18N::translate('Media contains:'), '</span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '">', + echo '" autofocus>', help_link('simple_filter'), '<p><input type="submit" name="search" value="', WT_I18N::translate('Filter'), '" onclick="this.form.subclick.value=this.name"> <input type="submit" name="all" value="', WT_I18N::translate('Display all'), '" onclick=\"this.form.subclick.value=this.name\"> @@ -234,7 +234,7 @@ if ($type == "place") { <span>', WT_I18N::translate('Place contains:'), '</span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '"> + echo '" autofocus> <p><input type="submit" name="search" value="', WT_I18N::translate('Filter'), '" onclick="this.form.subclick.value=this.name"> <input type="submit" name="all" value="', WT_I18N::translate('Display all'), '" onclick="this.form.subclick.value=this.name"> </p></form></div>'; @@ -251,7 +251,7 @@ if ($type == "repo") { <span>', WT_I18N::translate('Repository contains:'), '</span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '"> + echo '" autofocus> <p><input type="submit" name="search" value="', WT_I18N::translate('Filter'), '" onclick="this.form.subclick.value=this.name"> <input type="submit" name="all" value="', WT_I18N::translate('Display all'), '" onclick="this.form.subclick.value=this.name"> </td></tr></table> @@ -269,7 +269,7 @@ if ($type == "note") { <span>', WT_I18N::translate('Shared Note contains:'), '</span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '"> + echo '" autofocus> <p><input type="submit" name="search" value="', WT_I18N::translate('Filter'), '" onclick="this.form.subclick.value=this.name"> <input type="submit" name="all" value="', WT_I18N::translate('Display all'), '" onclick="this.form.subclick.value=this.name"> </p></form></div>'; @@ -286,7 +286,7 @@ if ($type == "source") { <span>', WT_I18N::translate('Source contains:'), '</span> <input type="text" name="filter" value="'; if ($filter) echo $filter; - echo '"> + echo '" autofocus> <p><input type="submit" name="search" value="', WT_I18N::translate('Filter'), '" onclick="this.form.subclick.value=this.name"> <input type="submit" name="all" value="', WT_I18N::translate('Display all'), '" onclick="this.form.subclick.value=this.name"> </p></form></div>'; diff --git a/gedrecord.php b/gedrecord.php index 074ece77e4..f5d9db788b 100644 --- a/gedrecord.php +++ b/gedrecord.php @@ -29,7 +29,7 @@ $controller=new WT_Controller_Page(); $obj=WT_GedcomRecord::getInstance(safe_GET_xref('pid')); if ( - $obj instanceof WT_Person || + $obj instanceof WT_Individual || $obj instanceof WT_Family || $obj instanceof WT_Source || $obj instanceof WT_Repository || @@ -38,7 +38,7 @@ if ( ) { header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$obj->getRawUrl()); exit; -} elseif (!$obj || !$obj->canDisplayDetails()) { +} elseif (!$obj || !$obj->canShow()) { $controller->pageHeader(); print_privacy_error(); } else { @@ -47,7 +47,7 @@ if ( '<pre style="white-space:pre-wrap; word-wrap:break-word;">', preg_replace( '/@('.WT_REGEX_XREF.')@/', '@<a href="gedrecord.php?pid=$1">$1</a>@', - htmlspecialchars($obj->getGedcomRecord()) + htmlspecialchars($obj->getGedcom()) ), '</pre>'; } diff --git a/hourglass.php b/hourglass.php index a57ab1373e..b0eabb9042 100644 --- a/hourglass.php +++ b/hourglass.php @@ -4,7 +4,7 @@ // Set the root person using the $pid variable // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -117,12 +117,12 @@ $gencount=0; <!-- // descendancy --> <td valign="middle"> <?php - $controller->print_descendency(WT_Person::getInstance($controller->pid), 1); ?> + $controller->print_descendency(WT_Individual::getInstance($controller->pid), 1); ?> </td> <!-- // pedigree --> <td valign="middle"> <?php - $controller->print_person_pedigree(WT_Person::getInstance($controller->pid), 1); ?> + $controller->print_person_pedigree(WT_Individual::getInstance($controller->pid), 1); ?> </td> </tr></table> </div><!-- close #hourglass_chart --> diff --git a/hourglass_ajax.php b/hourglass_ajax.php index e73242755e..ae1c87ae9f 100644 --- a/hourglass_ajax.php +++ b/hourglass_ajax.php @@ -42,6 +42,6 @@ Zend_Session::writeClose(); // -- print html header information if (isset($_REQUEST['type']) && $_REQUEST['type']=='desc') - $controller->print_descendency(WT_Person::getInstance($controller->pid), 1, false); + $controller->print_descendency(WT_Individual::getInstance($controller->pid), 1, false); else - $controller->print_person_pedigree(WT_Person::getInstance($controller->pid), 0); + $controller->print_person_pedigree(WT_Individual::getInstance($controller->pid), 0); diff --git a/includes/functions/functions.php b/includes/functions/functions.php index aed4c67883..3236c00c19 100644 --- a/includes/functions/functions.php +++ b/includes/functions/functions.php @@ -357,22 +357,6 @@ function wt_error_handler($errno, $errstr, $errfile, $errline) { // ************************************************* START OF GEDCOM FUNCTIONS ********************************* // /** - * Get first tag in GEDCOM sub-record - * - * This routine uses function get_sub_record to retrieve the specified sub-record - * and then returns the first tag. - * - */ -function get_first_tag($level, $tag, $gedrec, $num=1) { - $temp = get_sub_record($level, $level." ".$tag, $gedrec, $num)."\n"; - $length = strpos($temp, "\n"); - if ($length===false) { - $length = strlen($temp); - } - return substr($temp, 2, $length-2); -} - -/** * get a gedcom subrecord * * searches a gedcom record and returns a subrecord of it. A subrecord is defined starting at a @@ -517,38 +501,6 @@ function get_gedcom_value($tag, $level, $gedrec, $truncate='') { } /** - * create CONT lines - * - * Break input GEDCOM subrecord into pieces not more than 255 chars long, - * with CONC and CONT lines as needed. Routine also pays attention to the - * word wrapped Notes option. Routine also avoids splitting UTF-8 encoded - * characters between lines. - * - * @param string $newline Input GEDCOM subrecord to be worked on - * @return string $newged Output string with all necessary CONC and CONT lines - */ -function breakConts($newline) { - global $WORD_WRAPPED_NOTES; - - // Determine level number of CONC and CONT lines - $level = substr($newline, 0, 1); - $tag = substr($newline, 1, 6); - if ($tag!=" CONC " && $tag!=" CONT ") { - $level ++; - } - - $newged = ""; - $newlines = preg_split("/\n/", rtrim($newline)); - for ($k=0; $k<count($newlines); $k++) { - if ($k>0) { - $newlines[$k] = "{$level} CONT ".$newlines[$k]; - } - $newged .= trim($newlines[$k])."\n"; - } - return $newged; -} - -/** * get CONT lines * * get the N+1 CONT or CONC lines of a gedcom subrecord @@ -761,13 +713,16 @@ function sort_facts(&$arr) { foreach ($arr as $event) { $event->sortOrder = $order; $order++; - if ($event->getValue("DATE")==NULL || !$event->getDate()->isOk()) $nondated[] = $event; - else $dated[] = $event; + if ($event->getDate()->isOk()) { + $dated[] = $event; + } else { + $nondated[] = $event; + } } //-- sort each type of array - usort($dated, array("WT_Event", "CompareDate")); - usort($nondated, array("WT_Event", "CompareType")); + usort($dated, array("WT_Fact", "CompareDate")); + usort($nondated, array("WT_Fact", "CompareType")); //-- merge the arrays back together comparing by Facts $dc = count($dated); @@ -778,7 +733,7 @@ function sort_facts(&$arr) { // while there is anything in the dated array continue merging while ($i<$dc) { // compare each fact by type to merge them in order - if ($j<$nc && WT_Event::CompareType($dated[$i], $nondated[$j])>0) { + if ($j<$nc && WT_Fact::CompareType($dated[$i], $nondated[$j])>0) { $arr[$k] = $nondated[$j]; $j++; } @@ -807,7 +762,7 @@ function sort_facts(&$arr) { * @param int $maxlength - the maximum length of path * @param int $path_to_find - which path in the relationship to find, 0 is the shortest path, 1 is the next shortest path, etc */ -function get_relationship(WT_Person $person1, WT_Person $person2, $followspouse=true, $maxlength=0, $path_to_find=0) { +function get_relationship(WT_Individual $person1, WT_Individual $person2, $followspouse=true, $maxlength=0, $path_to_find=0) { if (!$person1 || !$person2 || $person1->equals($person2)) { return false; } @@ -1110,7 +1065,7 @@ function cousin_name2($n, $sex, $relation) { } -function get_relationship_name_from_path($path, WT_Person $person1=null, WT_Person $person2=null) { +function get_relationship_name_from_path($path, WT_Individual $person1=null, WT_Individual $person2=null) { if (!preg_match('/^(mot|fat|par|hus|wif|spo|son|dau|chi|bro|sis|sib)*$/', $path)) { // TODO: Update all the “3 RELA ” values in class_person return '<span class="error">'.$path.'</span>'; @@ -2214,12 +2169,12 @@ function add_ancestors(&$list, $pid, $children=false, $generations=-1, $show_emp while (count($genlist)>0) { $id = array_shift($genlist); if (strpos($id, "empty")===0) continue; // id can be something like “empty7” - $person = WT_Person::getInstance($id); + $person = WT_Individual::getInstance($id); $famids = $person->getChildFamilies(); if (count($famids)>0) { if ($show_empty) { for ($i=0;$i<$num_skipped;$i++) { - $list["empty" . $total_num_skipped] = new WT_Person(''); + $list["empty" . $total_num_skipped] = new WT_Individual(''); $list["empty" . $total_num_skipped]->generation = $list[$id]->generation+1; array_push($genlist, "empty" . $total_num_skipped); $total_num_skipped++; @@ -2233,14 +2188,14 @@ function add_ancestors(&$list, $pid, $children=false, $generations=-1, $show_emp $list[$husband->getXref()] = $husband; $list[$husband->getXref()]->generation = $list[$id]->generation+1; } elseif ($show_empty) { - $list["empty" . $total_num_skipped] = new WT_Person(''); + $list["empty" . $total_num_skipped] = new WT_Individual(''); $list["empty" . $total_num_skipped]->generation = $list[$id]->generation+1; } if ($wife) { $list[$wife->getXref()] = $wife; $list[$wife->getXref()]->generation = $list[$id]->generation+1; } elseif ($show_empty) { - $list["empty" . $total_num_skipped] = new WT_Person(''); + $list["empty" . $total_num_skipped] = new WT_Individual(''); $list["empty" . $total_num_skipped]->generation = $list[$id]->generation+1; } if ($generations == -1 || $list[$id]->generation+1 < $generations) { @@ -2271,10 +2226,10 @@ function add_ancestors(&$list, $pid, $children=false, $generations=-1, $show_emp } else if ($show_empty) { if ($skipped_gen > $list[$id]->generation) { - $list["empty" . $total_num_skipped] = new WT_Person(''); + $list["empty" . $total_num_skipped] = new WT_Individual(''); $list["empty" . $total_num_skipped]->generation = $list[$id]->generation+1; $total_num_skipped++; - $list["empty" . $total_num_skipped] = new WT_Person(''); + $list["empty" . $total_num_skipped] = new WT_Individual(''); $list["empty" . $total_num_skipped]->generation = $list[$id]->generation+1; array_push($genlist, "empty" . ($total_num_skipped - 1)); array_push($genlist, "empty" . $total_num_skipped); @@ -2288,7 +2243,7 @@ function add_ancestors(&$list, $pid, $children=false, $generations=-1, $show_emp //--- copied from class_reportpdf.php function add_descendancy(&$list, $pid, $parents=false, $generations=-1) { - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); if ($person==null) return; if (!isset($list[$pid])) { $list[$pid] = $person; diff --git a/includes/functions/functions_charts.php b/includes/functions/functions_charts.php index 172c25326f..9487b431eb 100644 --- a/includes/functions/functions_charts.php +++ b/includes/functions/functions_charts.php @@ -2,7 +2,7 @@ // Functions used for charts // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -75,34 +75,25 @@ function print_sosa_number($sosa, $pid = "", $arrowDirection = "up") { * @param string $parid optional parent ID (descendancy booklet) * @param string $gparid optional gd-parent ID (descendancy booklet) */ -function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', $personcount=1) { - global $pbwidth, $pbheight, $WT_IMAGES, $GEDCOM; - $ged_id=get_id_from_gedcom($GEDCOM); - - $family = WT_Family::getInstance($famid); - if (is_null($family)) return; +function print_family_parents(WT_Family $family, $sosa=0, $label='', $parid='', $gparid='', $personcount=1) { + global $pbwidth, $pbheight, $WT_IMAGES; $husb = $family->getHusband(); - if (is_null($husb)) $husb = new WT_Person(''); - $wife = $family->getWife(); - if (is_null($wife)) $wife = new WT_Person(''); - - if (!is_null($husb)) { - $tempID = $husb->getXref(); - if (!empty($tempID)) echo "<a name=\"{$tempID}\"></a>"; + if ($husb) { + echo '<a name="', $husb->getXref(), '"></a>'; + } else { + $husb = new WT_Individual('M', "0 @M@ INDI\n1 SEX M", null, WT_GED_ID); } - if (!is_null($wife)) { - $tempID = $wife->getXref(); - if (!empty($tempID)) echo "<a name=\"{$tempID}\"></a>"; + $wife = $family->getWife(); + echo '<a name="', $wife->getXref(), '"></a>'; + if ($wife) { + } else { + $wife = new WT_Individual('F', "0 @F@ INDI\n1 SEX F", null, WT_GED_ID); } - if ($sosa != 0) { + + if ($sosa) { echo '<p class="name_head">', $family->getFullName(), '</p>'; } - // -- get the new record and parents if in editing show changes mode - if (find_gedcom_record($famid, $ged_id) != find_gedcom_record($famid, $ged_id, WT_USER_CAN_EDIT)) { - $newrec = find_gedcom_record($famid, $ged_id, true); - $newparents = find_parents_in_record($newrec); - } /** * husband side @@ -110,17 +101,22 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr><td rowspan=\"2\">"; echo "<table style=\"width: " . ($pbwidth) . "px; height: " . $pbheight . "px;\" border=\"0\"><tr>"; if ($parid) { - if ($husb->getXref()==$parid) print_sosa_number($label); - else print_sosa_number($label, "", "blank"); + if ($husb->getXref()==$parid) { + print_sosa_number($label); + } else { + print_sosa_number($label, "", "blank"); + } + } elseif ($sosa) { + print_sosa_number($sosa * 2); } - else if ($sosa > 0) print_sosa_number($sosa * 2); - if (isset($newparents) && $husb->getXref() != $newparents["HUSB"]) { - echo "<td valign=\"top\" class=\"facts_valueblue\">"; - print_pedigree_person(WT_Person::getInstance($newparents['HUSB']), 1, 2, $personcount); + if ($husb->isNew()) { + echo '<td valign="top" class="facts_value new">'; + } elseif ($husb->isOld()) { + echo '<td valign="top" class="facts_value old">'; } else { - echo "<td valign=\"top\">"; - print_pedigree_person($husb, 1, 2, $personcount); + echo '<td valign="top">'; } + print_pedigree_person($husb, 1, 2, $personcount); echo "</td></tr></table>"; echo "</td>"; // husband's parents @@ -133,7 +129,7 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', echo "<td><img class=\"line5\" src=\"".$WT_IMAGES["hline"]."\" alt=\"\"></td><td>"; $hparents = false; foreach ($hfams as $hfamily) { - $hparents = find_parents_in_record($hfamily->getGedcomRecord()); + $hparents = find_parents_in_record($hfamily->getGedcom()); $upfamid = $hfamily->getXref(); break; } @@ -143,7 +139,7 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', if ($sosa > 0) print_sosa_number($sosa * 4, $hparents['HUSB'], "down"); if (!empty($gparid) && $hparents['HUSB']==$gparid) print_sosa_number(trim(substr($label,0,-3),".")."."); echo "<td valign=\"top\">"; - print_pedigree_person(WT_Person::getInstance($hparents['HUSB']), 1, 4, $personcount); + print_pedigree_person(WT_Individual::getInstance($hparents['HUSB']), 1, 4, $personcount); echo "</td></tr></table>"; } echo "</td>"; @@ -160,7 +156,7 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', if ($sosa > 0) print_sosa_number($sosa * 4 + 1, $hparents['WIFE'], "down"); if (!empty($gparid) && $hparents['WIFE']==$gparid) print_sosa_number(trim(substr($label,0,-3),".")."."); echo "<td valign=\"top\">"; - print_pedigree_person(WT_Person::getInstance($hparents['WIFE']), 1, 5, $personcount); + print_pedigree_person(WT_Individual::getInstance($hparents['WIFE']), 1, 5, $personcount); echo "</td></tr></table>"; echo "</td>"; } @@ -182,17 +178,22 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr><td rowspan=\"2\">"; echo "<table style=\"width: " . ($pbwidth) . "px; height: " . $pbheight . "px;\"><tr>"; if ($parid) { - if ($wife->getXref()==$parid) print_sosa_number($label); - else print_sosa_number($label, "", "blank"); + if ($wife->getXref()==$parid) { + print_sosa_number($label); + } else { + print_sosa_number($label, "", "blank"); + } + } elseif ($sosa) { + print_sosa_number($sosa * 2 + 1); } - else if ($sosa > 0) print_sosa_number($sosa * 2 + 1); - if (isset($newparents) && $wife->getXref() != $newparents["WIFE"]) { - echo "<td valign=\"top\" class=\"facts_valueblue\">"; - print_pedigree_person(WT_Person::getInstance($newparents['WIFE']), 1, 3, $personcount); + if ($wife->isNew()) { + echo '<td valign="top" class="facts_value new">'; + } elseif ($wife->isOld()) { + echo '<td valign="top" class="facts_value old">'; } else { - echo "<td valign=\"top\">"; - print_pedigree_person($wife, 1, 3, $personcount); + echo '<td valign="top">'; } + print_pedigree_person($wife, 1, 3, $personcount); echo "</td></tr></table>"; echo "</td>"; // wife's parents @@ -205,7 +206,7 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', echo "<td><img class=\"line5\" src=\"".$WT_IMAGES["hline"]."\" alt=\"\"></td><td>"; $j = 0; foreach ($hfams as $hfamily) { - $hparents = find_parents_in_record($hfamily->getGedcomRecord()); + $hparents = find_parents_in_record($hfamily->getGedcom()); $upfamid = $hfamily->getXref(); break; } @@ -215,7 +216,7 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', if ($sosa > 0) print_sosa_number($sosa * 4 + 2, $hparents['HUSB'], "down"); if (!empty($gparid) && $hparents['HUSB']==$gparid) print_sosa_number(trim(substr($label,0,-3),".")."."); echo "<td valign=\"top\">"; - print_pedigree_person(WT_Person::getInstance($hparents['HUSB']), 1, 6, $personcount); + print_pedigree_person(WT_Individual::getInstance($hparents['HUSB']), 1, 6, $personcount); echo "</td></tr></table>"; } echo "</td>"; @@ -232,7 +233,7 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', if ($sosa > 0) print_sosa_number($sosa * 4 + 3, $hparents['WIFE'], "down"); if (!empty($gparid) && $hparents['WIFE']==$gparid) print_sosa_number(trim(substr($label,0,-3),".")."."); echo "<td valign=\"top\">"; - print_pedigree_person(WT_Person::getInstance($hparents['WIFE']), 1, 7, $personcount); + print_pedigree_person(WT_Individual::getInstance($hparents['WIFE']), 1, 7, $personcount); echo "</td></tr></table>"; echo "</td>"; } @@ -247,15 +248,12 @@ function print_family_parents($famid, $sosa=0, $label='', $parid='', $gparid='', * @param int $sosa optional child sosa number * @param string $label optional indi label (descendancy booklet) */ -function print_family_children($famid, $childid = "", $sosa = 0, $label="", $personcount="1") { - global $bwidth, $bheight, $pbwidth, $pbheight, $cbheight, $cbwidth, $show_cousins, $WT_IMAGES, $GEDCOM, $TEXT_DIRECTION; +function print_family_children(WT_Family $family, $childid = "", $sosa = 0, $label="", $personcount="1") { + global $bwidth, $bheight, $pbwidth, $pbheight, $cbheight, $cbwidth, $show_cousins, $WT_IMAGES, $TEXT_DIRECTION; - $family=WT_Family::getInstance($famid); - $children=array(); - foreach ($family->getChildren() as $child) { - $children[]=$child->getXref(); - } + $children = $family->getFacts('CHIL'); $numchil=$family->getNumberOfChildren(); + echo "<table border=\"0\" cellpadding=\"0\" cellspacing=\"2\"><tr>"; if ($sosa>0) echo "<td></td>"; echo "<td><span class=\"subheaders\">"; @@ -269,9 +267,9 @@ function print_family_children($famid, $childid = "", $sosa = 0, $label="", $per if ($sosa==0 && WT_USER_CAN_EDIT) { echo '<br>'; echo '<span class="nowrap font12">'; - echo "<a href=\"#\" onclick=\"return addnewchild('$famid','');\">" . WT_I18N::translate('Add a child to this family') . "</a>"; - echo ' <a class="icon-sex_m_15x15" href="#" onclick="return addnewchild(\'', $famid, '\',\'M\');" title="',WT_I18N::translate('son'), '"></a>'; - echo ' <a class="icon-sex_f_15x15" href="#" onclick="return addnewchild(\'', $famid, '\',\'F\');" title="',WT_I18N::translate('daughter'), '"></a>'; + echo "<a href=\"#\" onclick=\"return addnewchild('", $family->getXref(), "','');\">" . WT_I18N::translate('Add a child to this family') . "</a>"; + echo ' <a class="icon-sex_m_15x15" href="#" onclick="return addnewchild(\'', $family->getXref(), '\',\'M\');" title="',WT_I18N::translate('son'), '"></a>'; + echo ' <a class="icon-sex_f_15x15" href="#" onclick="return addnewchild(\'', $family->getXref(), '\',\'F\');" title="',WT_I18N::translate('daughter'), '"></a>'; echo '</span>'; echo '<br><br>'; } @@ -281,151 +279,119 @@ function print_family_children($famid, $childid = "", $sosa = 0, $label="", $per } echo '</tr>'; - $newchildren = array(); - $oldchildren = array(); - if (WT_USER_CAN_EDIT || WT_USER_CAN_ACCEPT) { - $newrec = find_gedcom_record($famid, WT_GED_ID, true); - $ct = preg_match_all("/1 CHIL @(.*)@/", $newrec, $match, PREG_SET_ORDER); - if ($ct > 0) { - $oldchil = array(); - for ($i = 0; $i < $ct; $i++) { - if (!in_array($match[$i][1], $children)) $newchildren[] = $match[$i][1]; - else $oldchil[] = $match[$i][1]; - } - foreach ($children as $indexval => $chil) { - if (!in_array($chil, $oldchil)) $oldchildren[] = $chil; - } - //-- if there are no old or new children then the children were reordered - if ((count($newchildren)==0) && (count($oldchildren)==0)) { - $children = array(); - for ($i = 0; $i < $ct; $i++) { - $children[] = $match[$i][1]; - } - } - } - } $nchi=1; - if ((count($children) > 0) || (count($newchildren) > 0) || (count($oldchildren) > 0)) { - foreach ($children as $indexval => $chil) { - if (!in_array($chil, $oldchildren)) { - echo "<tr>"; - if ($sosa != 0) { - if ($chil == $childid) { - print_sosa_number($sosa, $childid); - } elseif (empty($label)) { - print_sosa_number(""); - } else { - print_sosa_number($label.($nchi++)."."); - } + if ($children) { + foreach ($children as $chil) { + $child = $chil->getTarget(); + echo '<tr>'; + if ($sosa != 0) { + if ($child->getXref() == $childid) { + print_sosa_number($sosa, $childid); + } elseif (empty($label)) { + print_sosa_number(""); + } else { + print_sosa_number($label.($nchi++)."."); } - echo "<td valign=\"middle\" >"; - print_pedigree_person(WT_Person::getInstance($chil), 1, 8, $personcount); - $personcount++; - echo "</td>"; - if ($sosa != 0) { - // loop for all families where current child is a spouse - $famids = WT_Person::getInstance($chil)->getSpouseFamilies(); - - - $maxfam = count($famids)-1; - for ($f=0; $f<=$maxfam; $f++) { - $famid_child = $famids[$f]->getXref(); - $parents = find_parents($famid_child); - if ($parents["HUSB"] == $chil) $spouse = $parents["WIFE"]; - else $spouse = $parents["HUSB"]; - // multiple marriages - if ($f>0) { - echo "</tr><tr><td> </td>"; - echo "<td valign=\"top\""; - if ($TEXT_DIRECTION == "rtl") echo " align=\"left\">"; - else echo " align=\"right\">"; - //if ($f==$maxfam) echo "<img height=\"50%\""; - //else echo "<img height=\"100%\""; - - //find out how many cousins there are to establish vertical line on second families - $family=WT_Family::getInstance($famid_child); - $fchildren=$family->getChildren(); - $kids = count($fchildren); - $PBheight = $bheight; - $Pheader = ($cbheight*$kids)-$bheight; - $PBadj = 6; // default - if ($show_cousins>0) { - if (($cbheight * $kids) > $bheight) { - $PBadj = ($Pheader/2+$kids*4.5); - } - } - - if ($PBadj<0) $PBadj=0; - if ($f==$maxfam) echo "<img height=\"".( (($bheight/2))+$PBadj)."px\""; - else echo "<img height=\"".$pbheight."px\""; - echo " width=\"3\" src=\"".$WT_IMAGES["vline"]."\" alt=\"\">"; - echo "</td>"; - } - echo "<td class=\"details1\" valign=\"middle\" align=\"center\">"; - $famrec = find_family_record($famid_child, WT_GED_ID); - $marrec = get_sub_record(1, "1 MARR", $famrec); - $divrec = get_sub_record(1, "1 DIV", $famrec); - if (canDisplayFact($famid_child, WT_GED_ID, $marrec)) { - // marriage date - $ct = preg_match("/2 DATE.*(\d\d\d\d)/", $marrec, $match); - if ($ct>0) echo "<span class=\"date\">".trim($match[1])."</span>"; - // divorce date - $ct = preg_match("/2 DATE.*(\d\d\d\d)/", $divrec, $match); - if ($ct>0) echo "-<span class=\"date\">".trim($match[1])."</span>"; - } - echo "<br><img width=\"100%\" class=\"line5\" height=\"3\" src=\"".$WT_IMAGES["hline"]."\" alt=\"\">"; - // family link - if ($famid_child) { - $family_child = WT_Family::getInstance($famid_child); - if ($family_child) { - echo "<br>"; - echo '<a class="details1" href="', $family_child->getHtmlUrl(), '">'; - // TODO: shouldn't there be something inside this <a></a> - echo "</a>"; - } + } + if ($chil->isNew()) { + echo '<td valign="middle" class="new">'; + } elseif ($chil->isOld()) { + echo '<td valign="middle" class="old">'; + } else { + echo '<td valign="middle">'; + } + print_pedigree_person($child, 1, 8, $personcount); + $personcount++; + echo "</td>"; + if ($sosa != 0) { + // loop for all families where current child is a spouse + $famids = $child->getSpouseFamilies(); + + + $maxfam = count($famids)-1; + for ($f=0; $f<=$maxfam; $f++) { + $famid_child = $famids[$f]->getXref(); + $parents = find_parents($famid_child); + if ($parents["HUSB"] == $child->getXref()) $spouse = $parents["WIFE"]; + else $spouse = $parents["HUSB"]; + // multiple marriages + if ($f>0) { + echo "</tr><tr><td> </td>"; + echo "<td valign=\"top\""; + if ($TEXT_DIRECTION == "rtl") echo " align=\"left\">"; + else echo " align=\"right\">"; + //if ($f==$maxfam) echo "<img height=\"50%\""; + //else echo "<img height=\"100%\""; + + //find out how many cousins there are to establish vertical line on second families + $family=WT_Family::getInstance($famid_child); + $fchildren=$family->getChildren(); + $kids = count($fchildren); + $PBheight = $bheight; + $Pheader = ($cbheight*$kids)-$bheight; + $PBadj = 6; // default + if ($show_cousins>0) { + if (($cbheight * $kids) > $bheight) { + $PBadj = ($Pheader/2+$kids*4.5); + } } + + if ($PBadj<0) $PBadj=0; + if ($f==$maxfam) echo "<img height=\"".( (($bheight/2))+$PBadj)."px\""; + else echo "<img height=\"".$pbheight."px\""; + echo " width=\"3\" src=\"".$WT_IMAGES["vline"]."\" alt=\"\">"; echo "</td>"; - // spouse information - echo "<td style=\"vertical-align: center;"; - if (!empty($divrec)) echo " filter:alpha(opacity=40);opacity:0.4;\">"; - else echo "\">"; - print_pedigree_person(WT_Person::getInstance($spouse), 1, 9, $personcount); - $personcount++; - echo "</td>"; - // cousins - if ($show_cousins) { - print_cousins($famid_child, $personcount); - $personcount++; + } + echo "<td class=\"details1\" valign=\"middle\" align=\"center\">"; + $famrec = find_family_record($famid_child, WT_GED_ID); + $marrec = get_sub_record(1, "1 MARR", $famrec); + $divrec = get_sub_record(1, "1 DIV", $famrec); + if (canDisplayFact($famid_child, WT_GED_ID, $marrec)) { + // marriage date + $ct = preg_match("/2 DATE.*(\d\d\d\d)/", $marrec, $match); + if ($ct>0) echo "<span class=\"date\">".trim($match[1])."</span>"; + // divorce date + $ct = preg_match("/2 DATE.*(\d\d\d\d)/", $divrec, $match); + if ($ct>0) echo "-<span class=\"date\">".trim($match[1])."</span>"; + } + echo "<br><img width=\"100%\" class=\"line5\" height=\"3\" src=\"".$WT_IMAGES["hline"]."\" alt=\"\">"; + // family link + if ($famid_child) { + $family_child = WT_Family::getInstance($famid_child); + if ($family_child) { + echo "<br>"; + echo '<a class="details1" href="', $family_child->getHtmlUrl(), '">'; + // TODO: shouldn't there be something inside this <a></a> + echo "</a>"; } } + echo "</td>"; + // spouse information + echo "<td style=\"vertical-align: center;"; + if (!empty($divrec)) echo " filter:alpha(opacity=40);opacity:0.4;\">"; + else echo "\">"; + print_pedigree_person(WT_Individual::getInstance($spouse), 1, 9, $personcount); + $personcount++; + echo "</td>"; + // cousins + if ($show_cousins) { + print_cousins($famid_child, $personcount); + $personcount++; + } } - echo "</tr>"; } + echo "</tr>"; } - foreach ($newchildren as $indexval => $chil) { - echo "<tr >"; - echo "<td valign=\"top\" class=\"facts_valueblue\" style=\"width: " . ($pbwidth) . "px; height: " . $pbheight . "px;\">"; - print_pedigree_person(WT_Person::getInstance($chil), 1, 0, $personcount); - $personcount++; - echo "</td></tr>"; - } - foreach ($oldchildren as $indexval => $chil) { - echo "<tr >"; - echo "<td valign=\"top\" class=\"facts_valuered\" style=\"width: " . ($pbwidth) . "px; height: " . $pbheight . "px;\">"; - print_pedigree_person(WT_Person::getInstance($chil), 1, 0, $personcount); - $personcount++; - echo "</td></tr>"; - } - // message 'no children' except for sosa } elseif ($sosa<1) { - if (preg_match('/\n1 NCHI (\d+)/', $family->getGedcomRecord(), $match) && $match[1]==0) { + // message 'no children' except for sosa + if (preg_match('/\n1 NCHI (\d+)/', $family->getGedcom(), $match) && $match[1]==0) { echo '<tr><td><i class="icon-childless"></i> '.WT_I18N::translate('This family remained childless').'</td></tr>'; } } else { echo "<tr>"; - print_sosa_number($sosa, WT_Person::getInstance($chil)); + print_sosa_number($sosa, $child); echo "<td valign=\"top\">"; - print_pedigree_person(WT_Person::getInstance($childid), 1, 0, $personcount); + print_pedigree_person(WT_Individual::getInstance($childid), 1, 0, $personcount); $personcount++; echo "</td></tr>"; } @@ -482,7 +448,7 @@ function ancestry_array($rootid, $maxgen=0) { $treeid[($i * 2)] = false; // -- father $treeid[($i * 2) + 1] = false; // -- mother if (!empty($treeid[$i])) { - $person = WT_Person::getInstance($treeid[$i]); + $person = WT_Individual::getInstance($treeid[$i]); $family = $person->getPrimaryChildFamily(); if ($family) { if ($family->getHusband()) { @@ -549,9 +515,8 @@ function get_sosa_name($sosa) { * @param string $famid family ID */ function print_cousins($famid, $personcount=1) { - global $show_full, $bheight, $bwidth, $cbheight, $cbwidth, $WT_IMAGES, $TEXT_DIRECTION, $GEDCOM; + global $show_full, $bheight, $bwidth, $cbheight, $cbwidth, $WT_IMAGES, $TEXT_DIRECTION; - $ged_id=get_id_from_gedcom($GEDCOM); $family=WT_Family::getInstance($famid); $fchildren=$family->getChildren(); @@ -591,7 +556,7 @@ function print_cousins($famid, $personcount=1) { 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->getGedcomRecord(), $match) && $match[1]==0) { + if (preg_match('/\n1 NCHI (\d+)/', $family->getGedcom(), $match) && $match[1]==0) { echo ' <i class="icon-childless" title="', WT_I18N::translate('This family remained childless'), '"></i>'; } } diff --git a/includes/functions/functions_db.php b/includes/functions/functions_db.php index 9eb06f476c..b6d9baec15 100644 --- a/includes/functions/functions_db.php +++ b/includes/functions/functions_db.php @@ -33,95 +33,94 @@ if (!defined('WT_WEBTREES')) { //////////////////////////////////////////////////////////////////////////////// function fetch_linked_indi($xref, $link, $ged_id) { $rows=WT_DB::prepare( - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`". " JOIN `##link` ON (i_file=l_file AND i_id=l_from)". " LEFT JOIN `##name` ON (i_file=n_file AND i_id=n_id AND n_num=0)". " WHERE i_file=? AND l_type=? AND l_to=?". " ORDER BY n_sort COLLATE '".WT_I18N::$collation."'" - )->execute(array($ged_id, $link, $xref))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id, $link, $xref))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Person::getInstance($row); + $list[]=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } function fetch_linked_fam($xref, $link, $ged_id) { $rows=WT_DB::prepare( - "SELECT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec". + "SELECT f_id AS xref, f_file AS gedcom_id, 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=? AND l_type=? AND l_to=?". - " ORDER BY n_sort" // n_sort is not used for families. Sorting here has no effect??? - )->execute(array($ged_id, $link, $xref))->fetchAll(PDO::FETCH_ASSOC); + " WHERE f_file=? AND l_type=? AND l_to=?" + )->execute(array($ged_id, $link, $xref))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Family::getInstance($row); + $list[]=WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } function fetch_linked_note($xref, $link, $ged_id) { $rows=WT_DB::prepare( - "SELECT 'NOTE' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec". + "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". " FROM `##other`". " JOIN `##link` ON (o_file=l_file AND o_id=l_from)". " LEFT JOIN `##name` ON (o_file=n_file AND o_id=n_id AND n_num=0)". " WHERE o_file=? AND o_type='NOTE' AND l_type=? AND l_to=?". " ORDER BY n_sort COLLATE '".WT_I18N::$collation."'" - )->execute(array($ged_id, $link, $xref))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id, $link, $xref))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Note::getInstance($row); + $list[]=WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } function fetch_linked_sour($xref, $link, $ged_id) { $rows=WT_DB::prepare( - "SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec". + "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom". " FROM `##sources`". " JOIN `##link` ON (s_file=l_file AND s_id=l_from)". " WHERE s_file=? AND l_type=? AND l_to=?". " ORDER BY s_name COLLATE '".WT_I18N::$collation."'" - )->execute(array($ged_id, $link, $xref))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id, $link, $xref))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Source::getInstance($row); + $list[]=WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } function fetch_linked_repo($xref, $link, $ged_id) { $rows=WT_DB::prepare( - "SELECT 'REPO' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec". + "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". " FROM `##other`". " JOIN `##link` ON (o_file=l_file AND o_id=l_from)". " LEFT JOIN `##name` ON (o_file=n_file AND o_id=n_id AND n_num=0)". " WHERE o_file=? AND o_type='REPO' AND l_type=? AND l_to=?". " ORDER BY n_sort COLLATE '".WT_I18N::$collation."'" - )->execute(array($ged_id, $link, $xref))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id, $link, $xref))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Note::getInstance($row); + $list[]=WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } function fetch_linked_obje($xref, $link, $ged_id) { $rows=WT_DB::prepare( - "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename". + "SELECT m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom". " FROM `##media`". " JOIN `##link` ON (m_file=l_file AND m_id=l_from)". " WHERE m_file=? AND l_type=? AND l_to=?". " ORDER BY m_titl COLLATE '".WT_I18N::$collation."'" - )->execute(array($ged_id, $link, $xref))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id, $link, $xref))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Media::getInstance($row); + $list[]=WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } @@ -264,13 +263,13 @@ function exists_pending_change($user_id=WT_USER_ID, $ged_id=WT_GED_ID) { // get a list of all the sources function get_source_list($ged_id) { $rows= - WT_DB::prepare("SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec FROM `##sources` s WHERE s_file=?") + WT_DB::prepare("SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom FROM `##sources` WHERE s_file=?") ->execute(array($ged_id)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Source::getInstance($row); + $list[]=WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } usort($list, array('WT_GedcomRecord', 'Compare')); return $list; @@ -280,13 +279,13 @@ function get_source_list($ged_id) { // $ged_id - the gedcom to search function get_repo_list($ged_id) { $rows= - WT_DB::prepare("SELECT 'REPO' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec FROM `##other` WHERE o_type='REPO' AND o_file=?") + WT_DB::prepare("SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom FROM `##other` WHERE o_type='REPO' AND o_file=?") ->execute(array($ged_id)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Repository::getInstance($row); + $list[]=WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } usort($list, array('WT_GedcomRecord', 'Compare')); return $list; @@ -295,13 +294,13 @@ function get_repo_list($ged_id) { //-- get the shared note list from the datastore function get_note_list($ged_id) { $rows= - WT_DB::prepare("SELECT 'NOTE' AS type, o_id AS xref, {$ged_id} AS ged_id, o_gedcom AS gedrec FROM `##other` WHERE o_type=? AND o_file=?") - ->execute(array('NOTE', $ged_id)) - ->fetchAll(PDO::FETCH_ASSOC); + WT_DB::prepare("SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom FROM `##other` WHERE o_type='NOTE' AND o_file=?") + ->execute(array($ged_id)) + ->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Note::getInstance($row); + $list[]=WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } usort($list, array('WT_GedcomRecord', 'Compare')); return $list; @@ -310,22 +309,22 @@ function get_note_list($ged_id) { // Search for INDIs using custom SQL generated by the report engine function search_indis_custom($join, $where, $order) { - $sql="SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec FROM `##individuals` ".implode(' ', $join).' WHERE '.implode(' AND ', $where); + $sql="SELECT DISTINCT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom FROM `##individuals` ".implode(' ', $join).' WHERE '.implode(' AND ', $where); if ($order) { $sql.=' ORDER BY '.implode(' ', $order); } $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } - $list[]=WT_Person::getInstance($row); + $list[]=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } // Switch privacy file if necessary if ($GED_ID!=WT_GED_ID) { @@ -337,22 +336,22 @@ function search_indis_custom($join, $where, $order) { // Search for FAMs using custom SQL generated by the report engine function search_fams_custom($join, $where, $order) { - $sql="SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec FROM `##families` ".implode(' ', $join).' WHERE '.implode(' AND ', $where); + $sql="SELECT DISTINCT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom FROM `##families` ".implode(' ', $join).' WHERE '.implode(' AND ', $where); if ($order) { $sql.=' ORDER BY '.implode(' ', $order); } $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } - $list[]=WT_Family::getInstance($row); + $list[]=WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } // Switch privacy file if necessary if ($GED_ID!=WT_GED_ID) { @@ -384,25 +383,25 @@ function search_indis($query, $geds, $match) { $querysql[]="i_gedcom LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."'"; } - $sql="SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec FROM `##individuals` WHERE (".implode(" {$match} ", $querysql).') AND i_file IN ('.implode(',', $geds).')'; + $sql="SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom FROM `##individuals` WHERE (".implode(" {$match} ", $querysql).') AND i_file IN ('.implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } // SQL may have matched on private data or gedcom tags, so check again against privatized data. - $record=WT_Person::getInstance($row); + $record=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // Ignore non-genealogical data - $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcomRecord()); + $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcom()); // Ignore links and tags $gedrec=preg_replace('/\n\d '.WT_REGEX_TAG.'( @'.WT_REGEX_XREF.'@)?/', '', $gedrec); // Re-apply the filtering @@ -439,24 +438,24 @@ function search_indis_names($query, $geds, $match) { foreach ($query as $q) { $querysql[]="n_full LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."'"; } - $sql="SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec, n_num FROM `##individuals` JOIN `##name` ON i_id=n_id AND i_file=n_file WHERE (".implode(" {$match} ", $querysql).') AND i_file IN ('.implode(',', $geds).')'; + $sql="SELECT DISTINCT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, n_num FROM `##individuals` JOIN `##name` ON i_id=n_id AND i_file=n_file WHERE (".implode(" {$match} ", $querysql).') AND i_file IN ('.implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } - $indi=WT_Person::getInstance($row); - if ($indi->canDisplayName()) { - $indi->setPrimaryName($row['n_num']); + $indi=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($indi->canShowName()) { + $indi->setPrimaryName($row->n_num); // We need to clone $indi, as we may have multiple references to the // same person in this list, and the "primary name" would otherwise // be shared amongst all of them. This has some performance/memory @@ -478,7 +477,7 @@ function search_indis_names($query, $geds, $match) { // $lastname, $firstname, $place - search terms // $geds - array of gedcoms to search function search_indis_soundex($soundex, $lastname, $firstname, $place, $geds) { - $sql="SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec FROM `##individuals`"; + $sql="SELECT DISTINCT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom FROM `##individuals`"; if ($place) { $sql.=" JOIN `##placelinks` ON (pl_file=i_file AND pl_gid=i_id)"; $sql.=" JOIN `##places` ON (p_file=pl_file AND pl_p_id=p_id)"; @@ -522,20 +521,20 @@ function search_indis_soundex($soundex, $lastname, $firstname, $place, $geds) { } // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } - $indi=WT_Person::getInstance($row); - if ($indi->canDisplayName()) { + $indi=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($indi->canShowName()) { $list[]=$indi; } } @@ -566,7 +565,7 @@ function get_recent_changes($jd=0, $allgeds=false) { // Seach for individuals with events on a given day function search_indis_dates($day, $month, $year, $facts) { - $sql="SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec FROM `##individuals` JOIN `##dates` ON i_id=d_gid AND i_file=d_file WHERE i_file=?"; + $sql="SELECT DISTINCT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom FROM `##individuals` JOIN `##dates` ON i_id=d_gid AND i_file=d_file WHERE i_file=?"; $vars=array(WT_GED_ID); if ($day) { $sql.=" AND d_day=?"; @@ -595,9 +594,9 @@ function search_indis_dates($day, $month, $year, $facts) { } $list=array(); - $rows=WT_DB::prepare($sql)->execute($vars)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->execute($vars)->fetchAll(); foreach ($rows as $row) { - $list[]=WT_Person::getInstance($row); + $list[]=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } @@ -624,25 +623,25 @@ function search_fams($query, $geds, $match) { $querysql[]="f_gedcom LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."'"; } - $sql="SELECT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec FROM `##families` WHERE (".implode(" {$match} ", $querysql).') AND f_file IN ('.implode(',', $geds).')'; + $sql="SELECT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom FROM `##families` WHERE (".implode(" {$match} ", $querysql).') AND f_file IN ('.implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } // SQL may have matched on private data or gedcom tags, so check again against privatized data. - $record=WT_Person::getInstance($row); + $record=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // Ignore non-genealogical data - $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcomRecord()); + $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcom()); // Ignore links and tags $gedrec=preg_replace('/\n\d '.WT_REGEX_TAG.'( @'.WT_REGEX_XREF.'@)?/', '', $gedrec); // Ignore tags @@ -682,23 +681,23 @@ function search_fams_names($query, $geds, $match) { $querysql[]="(husb.n_full LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."' OR wife.n_full LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."')"; } - $sql="SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec FROM `##families` LEFT OUTER JOIN `##name` husb ON f_husb=husb.n_id AND f_file=husb.n_file LEFT OUTER JOIN `##name` wife ON f_wife=wife.n_id AND f_file=wife.n_file WHERE (".implode(" {$match} ", $querysql).') AND f_file IN ('.implode(',', $geds).')'; + $sql="SELECT DISTINCT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom FROM `##families` LEFT OUTER JOIN `##name` husb ON f_husb=husb.n_id AND f_file=husb.n_file LEFT OUTER JOIN `##name` wife ON f_wife=wife.n_id AND f_file=wife.n_file WHERE (".implode(" {$match} ", $querysql).') AND f_file IN ('.implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } - $indi=WT_Family::getInstance($row); - if ($indi->canDisplayName()) { + $indi=WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($indi->canShowName()) { $list[]=$indi; } } @@ -732,25 +731,25 @@ function search_sources($query, $geds, $match) { $querysql[]="s_gedcom LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."'"; } - $sql="SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec FROM `##sources` WHERE (".implode(" {$match} ", $querysql).') AND s_file IN ('.implode(',', $geds).')'; + $sql="SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom FROM `##sources` WHERE (".implode(" {$match} ", $querysql).') AND s_file IN ('.implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } // SQL may have matched on private data or gedcom tags, so check again against privatized data. - $record=WT_Person::getInstance($row); + $record=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // Ignore non-genealogical data - $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcomRecord()); + $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcom()); // Ignore links and tags $gedrec=preg_replace('/\n\d '.WT_REGEX_TAG.'( @'.WT_REGEX_XREF.'@)?/', '', $gedrec); // Ignore tags @@ -794,25 +793,25 @@ function search_notes($query, $geds, $match) { $querysql[]="o_gedcom LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."'"; } - $sql="SELECT 'NOTE' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec FROM `##other` WHERE (".implode(" {$match} ", $querysql).") AND o_type='NOTE' AND o_file IN (".implode(',', $geds).')'; + $sql="SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom FROM `##other` WHERE (".implode(" {$match} ", $querysql).") AND o_type='NOTE' AND o_file IN (".implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } // SQL may have matched on private data or gedcom tags, so check again against privatized data. - $record=WT_Person::getInstance($row); + $record=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // Ignore non-genealogical data - $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcomRecord()); + $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcom()); // Ignore links and tags $gedrec=preg_replace('/\n\d '.WT_REGEX_TAG.'( @'.WT_REGEX_XREF.'@)?/', '', $gedrec); // Ignore tags @@ -857,25 +856,25 @@ function search_repos($query, $geds, $match) { $querysql[]="o_gedcom LIKE ".WT_DB::quote("%{$q}%")." COLLATE '".WT_I18N::$collation."'"; } - $sql="SELECT 'REPO' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec FROM `##other` WHERE (".implode(" {$match} ", $querysql).") AND o_type='REPO' AND o_file IN (".implode(',', $geds).')'; + $sql="SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom FROM `##other` WHERE (".implode(" {$match} ", $querysql).") AND o_type='REPO' AND o_file IN (".implode(',', $geds).')'; // Group results by gedcom, to minimise switching between privacy files - $sql.=' ORDER BY ged_id'; + $sql.=' ORDER BY gedcom_id'; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); $GED_ID=WT_GED_ID; foreach ($rows as $row) { // Switch privacy file if necessary - if ($row['ged_id']!=$GED_ID) { - $GEDCOM=get_gedcom_from_id($row['ged_id']); - load_gedcom_settings($row['ged_id']); - $GED_ID=$row['ged_id']; + if ($row->gedcom_id!=$GED_ID) { + $GEDCOM=get_gedcom_from_id($row->gedcom_id); + load_gedcom_settings($row->gedcom_id); + $GED_ID=$row->gedcom_id; } // SQL may have matched on private data or gedcom tags, so check again against privatized data. - $record=WT_Person::getInstance($row); + $record=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // Ignore non-genealogical data - $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcomRecord()); + $gedrec=preg_replace('/\n\d (_UID|_WT_USER|FILE|FORM|TYPE|CHAN|REFN|RESN) .*/', '', $record->getGedcom()); // Ignore links and tags $gedrec=preg_replace('/\n\d '.WT_REGEX_TAG.'( @'.WT_REGEX_XREF.'@)?/', '', $gedrec); // Ignore tags @@ -1100,47 +1099,47 @@ function get_anniversary_events($jd, $facts='', $ged_id=WT_GED_ID) { $where.=" AND d_file=".$ged_id; // Now fetch these anniversaries - $ind_sql="SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec, d_type, d_day, d_month, d_year, d_fact FROM `##dates`, `##individuals` {$where} AND d_gid=i_id AND d_file=i_file ORDER BY d_day ASC, d_year DESC"; - $fam_sql="SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec, d_type, d_day, d_month, d_year, d_fact FROM `##dates`, `##families` {$where} AND d_gid=f_id AND d_file=f_file ORDER BY d_day ASC, d_year DESC"; + $ind_sql="SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, d_type, d_day, d_month, d_year, d_fact FROM `##dates`, `##individuals` {$where} AND d_gid=i_id AND d_file=i_file ORDER BY d_day ASC, d_year DESC"; + $fam_sql="SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom, d_type, d_day, d_month, d_year, d_fact FROM `##dates`, `##families` {$where} AND d_gid=f_id AND d_file=f_file ORDER BY d_day ASC, d_year DESC"; foreach (array($ind_sql, $fam_sql) as $sql) { - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); foreach ($rows as $row) { - if ($row['type']=='INDI') { - $record=WT_Person::getInstance($row); + if ($row->type=='INDI') { + $record=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } else { - $record=WT_Family::getInstance($row); + $record=WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } - if ($record->canDisplayDetails()) { + if ($record->canShow()) { // Generate a regex to match the retrieved date - so we can find it in the original gedcom record. // TODO having to go back to the original gedcom is lame. This is why it is so slow. // We should store the level1 fact here (or in a "facts" table) - if ($row['d_type']=='@#DJULIAN@') { - if ($row['d_year']<0) { - $year_regex=$row['d_year'].' ?[Bb]\.? ?[Cc]\.\ ?'; + if ($row->d_type == '@#DJULIAN@') { + if ($row->d_year < 0) { + $year_regex=$row->d_year . ' ?[Bb]\.? ?[Cc]\.\ ?'; } else { - $year_regex="({$row['d_year']}|".($row['d_year']-1)."\/".($row['d_year']%100).")"; + $year_regex='(' . $row->d_year .'|' . ($row->d_year - 1) . '\/' . ($row->d_year % 100) . ')'; } } else - $year_regex="0*".$row['d_year']; - $ged_date_regex="/2 DATE.*(".($row['d_day']>0 ? "0?{$row['d_day']}\s*" : "").$row['d_month']."\s*".($row['d_year']!=0 ? $year_regex : "").")/i"; - preg_match_all('/\n(1 ('.WT_REGEX_TAG.').*(\n[2-9] .*)*)/', $row['gedrec'], $matches); + $year_regex='0*' . $row->d_year; + $ged_date_regex='/2 DATE.*(' . ($row->d_day > 0 ? '0?' . $row->d_day .'\s*' : '') . $row->d_month . '\s*' . ($row->d_year != 0 ? $year_regex : '') . ')/i'; + preg_match_all('/\n(1 ('.WT_REGEX_TAG.').*(\n[2-9] .*)*)/', $row->gedcom, $matches); foreach ($matches[1] as $factrec) { - if (preg_match('/^1 '.$row['d_fact'].'[ \n]/', $factrec) && preg_match($ged_date_regex, $factrec, $match)) { + if (preg_match('/^1 ' . $row->d_fact . '[ \n]/', $factrec) && preg_match($ged_date_regex, $factrec, $match)) { $date=new WT_Date($match[1]); if (preg_match('/2 PLAC (.+)/', $factrec, $match)) { $plac=$match[1]; } else { $plac=''; } - if (canDisplayFact($row['xref'], $ged_id, $factrec)) { + if (canDisplayFact($row->xref, $ged_id, $factrec)) { $found_facts[]=array( 'record'=>$record, - 'id'=>$row['xref'], - 'objtype'=>$row['type'], - 'fact'=>$row['d_fact'], + 'id'=>$row->xref, + 'objtype'=>$row->type, + 'fact'=>$row->d_fact, 'factrec'=>$factrec, 'jd'=>$jd, - 'anniv'=>($row['d_year']==0?0:$anniv->y-$row['d_year']), + 'anniv'=>($row->d_year == 0 ? 0 : $anniv->y - $row->d_year), 'date'=>$date, 'plac'=>$plac ); diff --git a/includes/functions/functions_edit.php b/includes/functions/functions_edit.php index 323d53cf62..2353cf21ae 100644 --- a/includes/functions/functions_edit.php +++ b/includes/functions/functions_edit.php @@ -268,48 +268,18 @@ function edit_field_username($name, $selected='', $extra='') { } // Print an edit control for a ADOP field -function edit_field_adop_u($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Adop::getValues(), null, $selected, $extra); -} - -// Print an edit control for a ADOP female field -function edit_field_adop_f($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Adop::getValues(new WT_Person("0 @XXX@ INDI\n1 SEX F")), null, $selected, $extra); -} - -// Print an edit control for a ADOP male field -function edit_field_adop_m($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Adop::getValues(new WT_Person("0 @XXX@ INDI\n1 SEX M")), null, $selected, $extra); +function edit_field_adop($name, $selected='', $extra='', WT_Individual $individual=null) { + return select_edit_control($name, WT_Gedcom_Code_Adop::getValues($individual), null, $selected, $extra); } // Print an edit control for a PEDI field -function edit_field_pedi_u($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Pedi::getValues(), '', $selected, $extra); -} - -// Print an edit control for a PEDI female field -function edit_field_pedi_f($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Pedi::getValues(new WT_Person("0 @XXX@ INDI\n1 SEX F")), '', $selected, $extra); -} - -// Print an edit control for a PEDI male field -function edit_field_pedi_m($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Pedi::getValues(new WT_Person("0 @XXX@ INDI\n1 SEX M")), '', $selected, $extra); +function edit_field_pedi($name, $selected='', $extra='', WT_Individual $individual=null) { + return select_edit_control($name, WT_Gedcom_Code_Pedi::getValues($individual), '', $selected, $extra); } // Print an edit control for a NAME TYPE field -function edit_field_name_type_u($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Name::getValues(), '', $selected, $extra); -} - -// Print an edit control for a female NAME TYPE field -function edit_field_name_type_f($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Name::getValues(new WT_Person("0 @XXX@ INDI\n1 SEX F")), '', $selected, $extra); -} - -// Print an edit control for a male NAME TYPE field -function edit_field_name_type_m($name, $selected='', $extra='') { - return select_edit_control($name, WT_Gedcom_Code_Name::getValues(new WT_Person("0 @XXX@ INDI\n1 SEX M")), '', $selected, $extra); +function edit_field_name_type($name, $selected='', $extra='', WT_Individual $individual=null) { + return select_edit_control($name, WT_Gedcom_Code_Name::getValues($individual), '', $selected, $extra); } // Print an edit control for a RELA field @@ -322,171 +292,6 @@ function edit_field_rela($name, $selected='', $extra='') { return select_edit_control($name, $rela_codes, '', $selected, $extra); } -/** -* Check if the given gedcom record has changed since the last session access -* This is used to check if the gedcom record changed between the time the user -* loaded the individual page and the time they clicked on a link to edit -* the data. -* -* @param string $pid The gedcom id of the record to check -*/ -function checkChangeTime($pid, $gedrec, $last_time) { - $change=WT_DB::prepare( - "SELECT UNIX_TIMESTAMP(change_time) AS change_time, user_name". - " FROM `##change`". - " JOIN `##user` USING (user_id)". - " WHERE status<>'rejected' AND gedcom_id=? AND xref=? AND change_time>?". - " ORDER BY change_id DESC". - " LIMIT 1" - )->execute(array(WT_GED_ID, $pid, $last_time))->fetchOneRow(); - - if ($change) { - $changeTime=$change->change_time; - $changeUser=$change->user_name; - } else { - $changeTime = 0; - $changeUser = ''; - } - if (isset($_REQUEST['linenum']) && $changeTime!=0 && $last_time && $changeTime > $last_time) { - global $controller; - $controller->pageHeader(); - echo '<p class="error">', WT_I18N::translate('The record with id %s was changed by another user since you last accessed it.', $pid), '</p>'; - if (!empty($changeUser)) { - echo '<p>', /* I18N: %s placeholders are a user-ID and a timestamp */ WT_I18N::translate('This record was last changed by <i>%s</i> at %s', $changeUser, date("d M Y H:i:s", $changeTime)), '</p>'; - } - echo '<p>', WT_I18N::translate('Please reload the previous page to make sure you are working with the most recent record.'), "</p>"; - exit; - } -} - -// Replace an updated record with a newer version -// $xref/$ged_id - the record to update -// $gedrec - the new gedcom record -// $chan - whether or not to update the CHAN record -function replace_gedrec($xref, $ged_id, $gedrec, $chan=true) { - if (($gedrec = check_gedcom($gedrec, $chan))!==false) { - $old_gedrec=find_gedcom_record($xref, $ged_id, true); - if ($old_gedrec!=$gedrec) { - WT_DB::prepare( - "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, ?, ?, ?)" - )->execute(array( - $ged_id, - $xref, - $old_gedrec, - $gedrec, - WT_USER_ID - )); - } - - if (get_user_setting(WT_USER_ID, 'auto_accept')) { - accept_all_changes($xref, $ged_id); - } - return true; - } - return false; -} - -//-- this function will append a new gedcom record at -//-- the end of the gedcom file. -function append_gedrec($gedrec, $ged_id) { - if (($gedrec = check_gedcom($gedrec, true))!==false && preg_match("/0 @(".WT_REGEX_XREF.")@ (".WT_REGEX_TAG.")/", $gedrec, $match)) { - $gid = $match[1]; - $type = $match[2]; - - if (preg_match("/\d/", $gid)==0) { - $xref = get_new_xref($type); - } else { - $xref = $gid; - } - $gedrec=preg_replace("/^0 @(.*)@/", "0 @$xref@", $gedrec); - - WT_DB::prepare( - "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, ?, ?, ?)" - )->execute(array( - $ged_id, - $xref, - '', - $gedrec, - WT_USER_ID - )); - - AddToLog("Appending new $type record $xref", 'edit'); - - if (get_user_setting(WT_USER_ID, 'auto_accept')) { - accept_all_changes($xref, WT_GED_ID); - } - return $xref; - } - return false; -} - -//-- this function will delete the gedcom record with -//-- the given $xref -function delete_gedrec($xref, $ged_id) { - WT_DB::prepare( - "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, ?, ?, ?)" - )->execute(array( - $ged_id, - $xref, - find_gedcom_record($xref, $ged_id, true), - '', - WT_USER_ID - )); - - AddToLog("Deleting gedcom record $xref", 'edit'); - - if (get_user_setting(WT_USER_ID, 'auto_accept')) { - accept_all_changes($xref, WT_GED_ID); - } -} - -//-- this function will check a GEDCOM record for valid gedcom format -function check_gedcom($gedrec, $chan=true) { - $ct = preg_match("/0 @(.*)@ (.*)/", $gedrec, $match); - if ($ct==0) { - echo "ERROR 20: Invalid GEDCOM format"; - AddToLog("ERROR 20: Invalid GEDCOM format:\n".$gedrec, 'edit'); - if (WT_DEBUG) { - echo "<pre>$gedrec</pre>"; - echo debug_print_backtrace(); - } - return false; - } - $gedrec = trim($gedrec); - if ($chan) { - $pos1 = strpos($gedrec, "1 CHAN"); - if ($pos1!==false) { - $pos2 = strpos($gedrec, "\n1", $pos1+4); - if ($pos2===false) $pos2 = strlen($gedrec); - $newgedrec = substr($gedrec, 0, $pos1); - $newgedrec .= "1 CHAN\n2 DATE ".strtoupper(date("d M Y"))."\n"; - $newgedrec .= "3 TIME ".date("H:i:s")."\n"; - $newgedrec .= "2 _WT_USER ".WT_USER_NAME."\n"; - $newgedrec .= substr($gedrec, $pos2); - $gedrec = $newgedrec; - } - else { - $newgedrec = "\n1 CHAN\n2 DATE ".strtoupper(date("d M Y"))."\n"; - $newgedrec .= "3 TIME ".date("H:i:s")."\n"; - $newgedrec .= "2 _WT_USER ".WT_USER_NAME; - $gedrec .= $newgedrec; - } - } - $gedrec = preg_replace('/\\\+/', "\\", $gedrec); - - //-- remove any empty lines - $lines = explode("\n", $gedrec); - $newrec = ''; - foreach ($lines as $ind=>$line) { - //-- remove any whitespace - $line = trim($line); - if (!empty($line)) $newrec .= $line."\n"; - } - - $newrec = html_entity_decode($newrec, ENT_COMPAT, 'UTF-8'); - return $newrec; -} - // Remove all links from $gedrec to $xref, and any sub-tags. function remove_links($gedrec, $xref) { $gedrec = preg_replace('/\n1 '.WT_REGEX_TAG.' @'.$xref.'@(\n[2-9].*)*/', '', $gedrec); @@ -551,611 +356,6 @@ function remove_subline($oldrecord, $linenum) { return $newrec; } -/** -* prints a form to add an individual or edit an individual's name -* -* @param string $nextaction the next action the edit_interface.php file should take after the form is submitted -* @param string $famid the family that the new person should be added to -* @param string $namerec the name subrecord when editing a name -* @param string $famtag how the new person is added to the family -*/ -function print_indi_form($nextaction, $famid, $linenum='', $namerec='', $famtag="CHIL", $sextag='') { - global $pid, $WORD_WRAPPED_NOTES; - global $NPFX_accept, $SPFX_accept, $NSFX_accept, $FILE_FORM_accept; - global $bdm, $STANDARD_NAME_FACTS, $REVERSED_NAME_FACTS, $ADVANCED_NAME_FACTS, $ADVANCED_PLAC_FACTS; - global $QUICK_REQUIRED_FACTS, $QUICK_REQUIRED_FAMFACTS, $NO_UPDATE_CHAN, $controller; - - $SURNAME_TRADITION=get_gedcom_setting(WT_GED_ID, 'SURNAME_TRADITION'); - - $bdm = ''; // used to copy '1 SOUR' to '2 SOUR' for BIRT DEAT MARR - init_calendar_popup(); - echo "<form method=\"post\" name=\"addchildform\" onsubmit=\"return checkform();\">"; - echo "<input type=\"hidden\" name=\"action\" value=\"$nextaction\">"; - echo "<input type=\"hidden\" name=\"linenum\" value=\"$linenum\">"; - echo "<input type=\"hidden\" name=\"famid\" value=\"$famid\">"; - echo "<input type=\"hidden\" name=\"pid\" value=\"$pid\">"; - echo "<input type=\"hidden\" name=\"famtag\" value=\"$famtag\">"; - echo "<input type=\"hidden\" name=\"goto\" value=\"\">"; - echo "<table class=\"facts_table\">"; - - // When adding a new child, specify the pedigree - if ($nextaction=='addchildaction' || $nextaction=='addopfchildaction') { - add_simple_tag('0 PEDI'); - } - - if ($nextaction=='update') { - $name_type=get_gedcom_value('TYPE', 2, $namerec); - add_simple_tag('0 TYPE '.$name_type); - } - // Populate the standard NAME field and subfields - $name_fields=array(); - foreach ($STANDARD_NAME_FACTS as $tag) { - $name_fields[$tag]=get_gedcom_value($tag, 0, $namerec); - } - - $new_marnm=''; - // Inherit surname from parents, spouse or child - if (empty($namerec)) { - // We'll need the parent's name to set the child's surname - $family=WT_Family::getInstance($famid); - if ($family && $family->getHusband()) { - $father_name=get_gedcom_value('NAME', 0, $family->getHusband()->getGedcomRecord()); - } else { - $father_name=''; - } - if ($family && $family->getWife()) { - $mother_name=get_gedcom_value('NAME', 0, $family->getWife()->getGedcomRecord()); - } else { - $mother_name=''; - } - // We'll need the spouse/child's name to set the spouse/parent's surname - $prec=find_gedcom_record($pid, WT_GED_ID, true); - $indi_name=get_gedcom_value('NAME', 0, $prec); - // Different cultures do surnames differently - switch ($SURNAME_TRADITION) { - case 'spanish': - //Mother: Maria /AAAA BBBB/ - //Father: Jose /CCCC DDDD/ - //Child: Pablo /CCCC AAAA/ - switch ($nextaction) { - case 'addchildaction': - if (preg_match('/\/(\S+)\s+\S+\//', $mother_name, $matchm) && - preg_match('/\/(\S+)\s+\S+\//', $father_name, $matchf)) { - $name_fields['SURN']=$matchf[1].' '.$matchm[1]; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - break; - case 'addnewparentaction': - if ($famtag=='HUSB' && preg_match('/\/(\S+)\s+\S+\//', $indi_name, $match)) { - $name_fields['SURN']=$match[1].' '; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - if ($famtag=='WIFE' && preg_match('/\/\S+\s+(\S+)\//', $indi_name, $match)) { - $name_fields['SURN']=$match[1].' '; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - break; - } - break; - case 'portuguese': - //Mother: Maria /AAAA BBBB/ - //Father: Jose /CCCC DDDD/ - //Child: Pablo /BBBB DDDD/ - switch ($nextaction) { - case 'addchildaction': - if (preg_match('/\/\S+\s+(\S+)\//', $mother_name, $matchm) && - preg_match('/\/\S+\s+(\S+)\//', $father_name, $matchf)) { - $name_fields['SURN']=$matchf[1].' '.$matchm[1]; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - break; - case 'addnewparentaction': - if ($famtag=='HUSB' && preg_match('/\/\S+\s+(\S+)\//', $indi_name, $match)) { - $name_fields['SURN']=' '.$match[1]; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - if ($famtag=='WIFE' && preg_match('/\/(\S+)\s+\S+\//', $indi_name, $match)) { - $name_fields['SURN']=' '.$match[1]; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - break; - } - break; - case 'icelandic': - // Sons get their father's given name plus "sson" - // Daughters get their father's given name plus "sdottir" - switch ($nextaction) { - case 'addchildaction': - if ($sextag=='M' && preg_match('/(\S+)\s+\/.*\//', $father_name, $match)) { - $name_fields['SURN']=preg_replace('/s$/', '', $match[1]).'sson'; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - if ($sextag=='F' && preg_match('/(\S+)\s+\/.*\//', $father_name, $match)) { - $name_fields['SURN']=preg_replace('/s$/', '', $match[1]).'sdottir'; - $name_fields['NAME']='/'.$name_fields['SURN'].'/'; - } - break; - case 'addnewparentaction': - if ($famtag=='HUSB' && preg_match('/(\S+)sson\s+\/.*\//i', $indi_name, $match)) { - $name_fields['GIVN']=$match[1]; - $name_fields['NAME']=$name_fields['GIVN'].' //'; - } - if ($famtag=='WIFE' && preg_match('/(\S+)sdottir\s+\/.*\//i', $indi_name, $match)) { - $name_fields['GIVN']=$match[1]; - $name_fields['NAME']=$name_fields['GIVN'].' //'; - } - break; - } - break; - case 'patrilineal': - // Father gives his surname to his children - switch ($nextaction) { - case 'addchildaction': - if (preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $father_name, $match)) { - $name_fields['SURN']=$match[2]; - $name_fields['SPFX']=trim($match[1]); - $name_fields['NAME']="/{$match[1]}{$match[2]}/"; - } - break; - case 'addnewparentaction': - if ($famtag=='HUSB' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { - $name_fields['SURN']=$match[2]; - $name_fields['SPFX']=trim($match[1]); - $name_fields['NAME']="/{$match[1]}{$match[2]}/"; - } - break; - } - break; - case 'matrilineal': - // Mother gives her surname to her children - switch ($nextaction) { - case 'addchildaction': - if (preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $mother, $match)) { - $name_fields['SURN']=$match[2]; - $name_fields['SPFX']=trim($match[1]); - $name_fields['NAME']="/{$match[1]}{$match[2]}/"; - } - break; - case 'addnewparentaction': - if ($famtag=='WIFE' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { - $name_fields['SURN']=$match[2]; - $name_fields['SPFX']=trim($match[1]); - $name_fields['NAME']="/{$match[1]}{$match[2]}/"; - } - break; - } - break; - case 'paternal': - case 'polish': - case 'lithuanian': - // Father gives his surname to his wife and children - switch ($nextaction) { - case 'addspouseaction': - if ($famtag=='WIFE' && preg_match('/\/(.*)\//', $indi_name, $match)) { - if ($SURNAME_TRADITION=='polish') { - $match[1]=preg_replace(array('/ski$/', '/cki$/', '/dzki$/', '/żki$/'), array('ska', 'cka', 'dzka', 'żka'), $match[1]); - } else if ($SURNAME_TRADITION=='lithuanian') { - $match[1]=preg_replace(array('/as$/', '/is$/', '/ys$/', '/us$/'), array('ienė', 'ienė', 'ienė', 'ienė'), $match[1]); - } - $new_marnm=$match[1]; - } - break; - case 'addchildaction': - if (preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $father_name, $match)) { - $name_fields['SURN']=$match[2]; - if ($SURNAME_TRADITION=='polish' && $sextag=='F') { - $match[2]=preg_replace(array('/ski$/', '/cki$/', '/dzki$/', '/żki$/'), array('ska', 'cka', 'dzka', 'żka'), $match[2]); - } else if ($SURNAME_TRADITION=='lithuanian' && $sextag=='F') { - $match[2]=preg_replace(array('/as$/', '/a$/', '/is$/', '/ys$/', '/ius$/', '/us$/'), array('aitė', 'aitė', 'ytė', 'ytė', 'iūtė', 'utė'), $match[2]); - } - $name_fields['SPFX']=trim($match[1]); - $name_fields['NAME']="/{$match[1]}{$match[2]}/"; - } - break; - case 'addnewparentaction': - if ($famtag=='HUSB' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { - if ($SURNAME_TRADITION=='polish' && $sextag=='M') { - $match[2]=preg_replace(array('/ska$/', '/cka$/', '/dzka$/', '/żka$/'), array('ski', 'cki', 'dzki', 'żki'), $match[2]); - } else if ($SURNAME_TRADITION=='lithuanian') { - // not a complete list as the rules are somewhat complicated but will do 95% correctly - $match[2]=preg_replace(array('/aitė$/', '/ytė$/', '/iūtė$/', '/utė$/'), array('as', 'is', 'ius', 'us'), $match[2]); - } - $name_fields['SPFX']=trim($match[1]); - $name_fields['SURN']=$match[2]; - $name_fields['NAME']="/{$match[1]}{$match[2]}/"; - } - if ($famtag=='WIFE' && preg_match('/\/((?:[a-z]{2,3} )*)(.*)\//i', $indi_name, $match)) { - if ($SURNAME_TRADITION=='lithuanian') { - $match[2]=preg_replace(array('/as$/', '/is$/', '/ys$/', '/us$/'), array('ienė', 'ienė', 'ienė', 'ienė'), $match[2]); - $match[2]=preg_replace(array('/aitė$/', '/ytė$/', '/iūtė$/', '/utė$/'), array('ienė', 'ienė', 'ienė', 'ienė'), $match[2]); - $new_marnm=$match[2]; - } - } - break; - } - break; - } - } - - // Make sure there are two slashes in the name - if (!preg_match('/\//', $name_fields['NAME'])) - $name_fields['NAME'].=' /'; - if (!preg_match('/\/.*\//', $name_fields['NAME'])) - $name_fields['NAME'].='/'; - - // Populate any missing 2 XXXX fields from the 1 NAME field - $npfx_accept=implode('|', $NPFX_accept); - 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]; - } - // Don't automatically create an empty NICK - it is an "advanced" field. - if (empty($name_fields['NICK']) && !empty($name_bits[6]) && !preg_match('/^2 NICK/m', $namerec)) { - $name_fields['NICK']=$name_bits[6]; - } - } - - // Edit the standard name fields - foreach ($name_fields as $tag=>$value) { - add_simple_tag("0 $tag $value"); - } - - // Get the advanced name fields - $adv_name_fields=array(); - if (preg_match_all('/('.WT_REGEX_TAG.')/', $ADVANCED_NAME_FACTS, $match)) - foreach ($match[1] as $tag) - $adv_name_fields[$tag]=''; - // This is a custom tag, but webtrees uses it extensively. - if ($SURNAME_TRADITION=='paternal' || $SURNAME_TRADITION=='polish' || $SURNAME_TRADITION=='lithuanian' || (strpos($namerec, '2 _MARNM')!==false)) { - $adv_name_fields['_MARNM']=''; - } - $person = WT_Person::getInstance($pid); - if (isset($adv_name_fields['TYPE'])) { - unset($adv_name_fields['TYPE']); - } - foreach ($adv_name_fields as $tag=>$dummy) { - // Edit existing tags - if (preg_match_all("/2 $tag (.+)/", $namerec, $match)) - foreach ($match[1] as $value) { - if ($tag=='_MARNM') { - $mnsct = preg_match('/\/(.+)\//', $value, $match2); - $marnm_surn = ''; - if ($mnsct>0) $marnm_surn = $match2[1]; - add_simple_tag("2 _MARNM ".$value); - add_simple_tag("2 _MARNM_SURN ".$marnm_surn); - } else { - add_simple_tag("2 $tag $value", '', WT_Gedcom_Tag::getLabel("NAME:{$tag}", $person)); - } - } - // Allow a new row to be entered if there was no row provided - if (count($match[1])==0 && empty($name_fields[$tag]) || $tag!='_HEB' && $tag!='NICK') - if ($tag=='_MARNM') { - if (strstr($ADVANCED_NAME_FACTS, '_MARNM')==false) { - add_simple_tag("0 _MARNM"); - add_simple_tag("0 _MARNM_SURN $new_marnm"); - } - } else { - add_simple_tag("0 $tag", '', WT_Gedcom_Tag::getLabel("NAME:{$tag}", $person)); - } - } - - // Handle any other NAME subfields that aren't included above (SOUR, NOTE, _CUSTOM, etc) - if ($namerec!='' && $namerec!="NEW") { - $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]); - $level1type = $type; - $tags=array(); - $i = 0; - do { - if ($type!='TYPE' && !isset($name_fields[$type]) && !isset($adv_name_fields[$type])) { - $text = ''; - for ($j=2; $j<count($fields); $j++) { - if ($j>2) $text .= ' '; - $text .= $fields[$j]; - } - $iscont = false; - while (($i+1<count($gedlines))&&(preg_match("/".($level+1)." (CON[CT]) ?(.*)/", $gedlines[$i+1], $cmatch)>0)) { - $iscont=true; - if ($cmatch[1]=="CONT") $text.="\n"; - if ($WORD_WRAPPED_NOTES) $text .= ' '; - $text .= $cmatch[2]; - $i++; - } - add_simple_tag($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" || $sextag=="M") { - add_simple_tag("0 SEX M"); - } elseif ($famtag=="WIFE" || $sextag=="F") { - add_simple_tag("0 SEX F"); - } else { - add_simple_tag("0 SEX"); - } - $bdm = "BD"; - if (preg_match_all('/('.WT_REGEX_TAG.')/', $QUICK_REQUIRED_FACTS, $matches)) { - foreach ($matches[1] as $match) { - if (!in_array($match, explode('|', WT_EVENTS_DEAT))) { - addSimpleTags($match); - } - } - } - //-- if adding a spouse add the option to add a marriage fact to the new family - if ($nextaction=='addspouseaction' || ($nextaction=='addnewparentaction' && $famid!='new')) { - $bdm .= "M"; - if (preg_match_all('/('.WT_REGEX_TAG.')/', $QUICK_REQUIRED_FAMFACTS, $matches)) { - foreach ($matches[1] as $match) { - addSimpleTags($match); - } - } - } - if (preg_match_all('/('.WT_REGEX_TAG.')/', $QUICK_REQUIRED_FACTS, $matches)) { - foreach ($matches[1] as $match) { - if (in_array($match, explode('|', WT_EVENTS_DEAT))) { - addSimpleTags($match); - } - } - } - } - if (WT_USER_IS_ADMIN) { - echo "<tr><td class=\"descriptionbox wrap width25\">"; - echo WT_Gedcom_Tag::getLabel('CHAN'), "</td><td class=\"optionbox wrap\">"; - if ($NO_UPDATE_CHAN) { - echo "<input type=\"checkbox\" checked=\"checked\" name=\"preserve_last_changed\">"; - } else { - echo "<input type=\"checkbox\" name=\"preserve_last_changed\">"; - } - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'), "<br>"; - if (isset($famrec)) { - $event = new WT_Event(get_sub_record(1, "1 CHAN", $famrec), null, 0); - echo format_fact_date($event, new WT_Person(''), false, true); - } - echo "</td></tr>"; - } - echo "</table>"; - if ($nextaction=='update') { // GEDCOM 5.5.1 spec says NAME doesn't get a OBJE - print_add_layer('SOUR'); - print_add_layer('NOTE'); - print_add_layer('SHARED_NOTE'); - } else { - print_add_layer('SOUR', 1); - print_add_layer('OBJE', 1); - print_add_layer('NOTE', 1); - print_add_layer('SHARED_NOTE', 1); - } - echo '<p id="save-cancel">'; - echo '<input type="submit" class="save" value="', /* I18N: button label */ WT_I18N::translate('save'), '">'; - if (preg_match('/^add(child|spouse|newparent)/', $nextaction)) { - echo '<input type="submit" class="save" value="', /* I18N: button label */ WT_I18N::translate('go to new individual'), '" onclick="document.addchildform.goto.value=\'new\';">'; - } - echo '<input type="button" class="cancel" value="', /* I18N: button label */ WT_I18N::translate('close'), '" onclick="window.close();">'; - echo '</p>'; - echo '</form>'; - $controller->addInlineJavascript(' - SURNAME_TRADITION="'.$SURNAME_TRADITION.'"; - sextag="'.$sextag.'"; - 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 frm =document.forms[0]; - var npfx=frm.NPFX.value; - var givn=frm.GIVN.value; - var spfx=frm.SPFX.value; - var surn=frm.SURN.value; - var nsfx=frm.NSFX.value; - if (SURNAME_TRADITION=="polish" && (sextag=="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; - // Update NAME field from components and display it - var frm =document.forms[0]; - var npfx=frm.NPFX.value; - var givn=frm.GIVN.value; - var spfx=frm.SPFX.value; - var surn=frm.SURN.value; - var nsfx=frm.NSFX.value; - document.getElementById("NAME").value=generate_name(); - document.getElementById("NAME_display").innerHTML=frm.NAME.value; - // 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=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(frm.NAME.value)==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; - } - } - } - } - - /** - * convert a hidden field to a text box - */ - var oldName = ""; - var manualChange = false; - function convertHidden(eid) { - var element = document.getElementById(eid); - if (element) { - if (element.type=="hidden") { - // IE doesn’t allow changing the "type" of an input field so we’ll cludge it ( silly :P) - if (IE) { - var newInput = document.createElement("input"); - newInput.setAttribute("type", "text"); - newInput.setAttribute("name", element.Name); - newInput.setAttribute("id", element.id); - newInput.setAttribute("value", element.value); - newInput.setAttribute("onchange", element.onchange); - var parent = element.parentNode; - parent.replaceChild(newInput, element); - element = newInput; - } - else { - element.type="text"; - } - element.size="40"; - oldName = element.value; - manualChange = true; - var delement = document.getElementById(eid+"_display"); - if (delement) { - delement.style.display="none"; - // force FF ui to update the display - if (delement.innerHTML != oldName) { - oldName = delement.innerHTML; - element.value = oldName; - } - } - } - else { - manualChange = false; - // IE doesn’t allow changing the "type" of an input field so we’ll cludge it ( silly :P) - if (IE) { - var newInput = document.createElement("input"); - newInput.setAttribute("type", "hidden"); - newInput.setAttribute("name", element.Name); - newInput.setAttribute("id", element.id); - newInput.setAttribute("value", element.value); - newInput.setAttribute("onchange", element.onchange); - var parent = element.parentNode; - parent.replaceChild(newInput, element); - element = newInput; - } - else { - element.type="hidden"; - } - var delement = document.getElementById(eid+"_display"); - if (delement) { - delement.style.display="inline"; - } - } - } - } - - /** - * 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"); - } - '); -} - // generates javascript code for calendar popup in user's language function print_calendar_popup($id) { return @@ -1181,7 +381,7 @@ function print_addnewnote_assisted_link($element_id, $pid) { } function print_editnote_link($note_id) { - return '<a href="#" onclick="var win02=window.open(\'edit_interface.php?action=editnote&pid='.$note_id.'\', \'win02\', edit_window_specs);" class="icon-button_note" title="'.WT_I18N::translate('Edit Shared Note').'"></a>'; + return '<a href="#" onclick="var win02=window.open(\'edit_interface.php?action=editnote&xref='.$note_id.'\', \'win02\', edit_window_specs);" class="icon-button_note" title="'.WT_I18N::translate('Edit Shared Note').'"></a>'; } function print_addnewsource_link($element_id) { @@ -1210,7 +410,7 @@ function print_addnewsource_link($element_id) { function add_simple_tag($tag, $upperlevel='', $label='', $readOnly='', $noClose='', $rowDisplay=true) { global $MEDIA_DIRECTORY, $tags, $emptyfacts, $main_fact, $TEXT_DIRECTION; global $NPFX_accept, $SPFX_accept, $NSFX_accept, $FILE_FORM_accept, $upload_count; - global $pid, $gender, $linkToID, $bdm, $action, $event_add, $CensDate; + global $pid, $linkToID, $bdm, $action, $event_add, $CensDate; global $QUICK_REQUIRED_FACTS, $QUICK_REQUIRED_FAMFACTS, $PREFER_LEVEL2_SOURCES; if (substr($tag, 0, strpos($tag, "CENS"))) { @@ -1400,7 +600,7 @@ function add_simple_tag($tag, $upperlevel='', $label='', $readOnly='', $noClose= if ($fact=="NOTE" && $islink) { $note1=WT_Note::getInstance($value); if ($note1) { - $noterec=$note1->getGedcomRecord(); + $noterec=$note1->getGedcom(); preg_match("/$value/i", $noterec, $notematch); $value=$notematch[0]; } @@ -1420,17 +620,9 @@ function add_simple_tag($tag, $upperlevel='', $label='', $readOnly='', $noClose= } else if ($fact=="TEMP") { echo select_edit_control($element_name, WT_Gedcom_Code_Temp::templeNames(), WT_I18N::translate('No Temple - Living Ordinance'), $value); } else if ($fact=="ADOP") { - switch ($gender) { - case 'M': echo edit_field_adop_m($element_name, $value); break; - case 'F': echo edit_field_adop_f($element_name, $value); break; - default: echo edit_field_adop_u($element_name, $value); break; - } + echo edit_field_adop($element_name, $value, '', WT_Individual::getInstance($pid)); } else if ($fact=="PEDI") { - switch ($gender) { - case 'M': echo edit_field_pedi_m($element_name, $value); break; - case 'F': echo edit_field_pedi_f($element_name, $value); break; - default: echo edit_field_pedi_u($element_name, $value); break; - } + echo edit_field_pedi($element_name, $value, '', WT_Individual::getInstance($pid)); } else if ($fact=='STAT') { echo select_edit_control($element_name, WT_Gedcom_Code_Stat::statusNames($upperlevel), '', $value); } else if ($fact=='RELA') { @@ -1546,11 +738,7 @@ function add_simple_tag($tag, $upperlevel='', $label='', $readOnly='', $noClose= // NAME TYPE : hide text field and show a selection list else if ($fact=='TYPE' && $level==0) { $extra = 'onchange="document.getElementById(\''.$element_id.'\').value=this.value;"'; - switch (WT_Person::getInstance($pid)->getSex()) { - case 'M': echo edit_field_name_type_m($element_name, $value, $extra); break; - case 'F': echo edit_field_name_type_f($element_name, $value, $extra); break; - default: echo edit_field_name_type_u($element_name, $value, $extra); break; - } + echo edit_field_name_type($element_name, $value, $extra, WT_Individual::getInstance($pid)); echo '<script>'; echo "document.getElementById('", $element_id, "').style.display='none';"; echo '</script>'; @@ -1647,7 +835,7 @@ function add_simple_tag($tag, $upperlevel='', $label='', $readOnly='', $noClose= // Check if a CENS event --------------------------- if ($event_add=='census_add') { $type_pid=WT_GedcomRecord::getInstance($pid); - if ($type_pid instanceof WT_Person) { + if ($type_pid instanceof WT_Individual) { echo '<br>', print_addnewnote_assisted_link($element_id, $pid); } } @@ -2138,7 +1326,7 @@ function handle_updates($newged, $levelOverride="no") { if ($islink[$j]) $newline .= " @".$text[$j]."@"; else $newline .= ' '.$text[$j]; } - $newged .= "\n".breakConts($newline); + $newged .= "\n".str_replace("\n", "\n" . (1 + substr($newline, 0, 1)) . ' CONT ', $newline); } } @@ -2146,36 +1334,6 @@ function handle_updates($newged, $levelOverride="no") { } /** -* Link Media ID to Indi, Family, or Source ID -* -* Code was removed from inverselink.php to become a callable function -* -* @param string $mediaid Media ID to be linked -* @param string $linktoid Indi, Family, or Source ID that the Media ID should link to -* @param int $level Level where the Media Object reference should be created -* @param boolean $chan Whether or not to update/add the CHAN record -* @return bool success or failure -*/ -function linkMedia($mediaid, $linktoid, $level=1, $chan=true) { - if (empty($level)) $level = 1; - if ($level!=1) return false; // Level 2 items get linked elsewhere - // find Indi, Family, or Source record to link to - $gedrec = find_gedcom_record($linktoid, WT_GED_ID, true); - - //-- check if we are re-editing an unaccepted link that is not already in the DB - if (strpos($gedrec, "1 OBJE @$mediaid@")!==false) return false; - - if ($gedrec) { - $newrec = $gedrec."\n1 OBJE @".$mediaid."@"; - replace_gedrec($linktoid, WT_GED_ID, $newrec, $chan); - return true; - } else { - // Record not found? Maybe deleted since we started this action? - return false; - } -} - -/** * builds the form for adding new facts * @param string $fact the new fact we are adding */ @@ -2223,36 +1381,22 @@ function create_add_form($fact) { } } -/** -* creates the form for editing the fact within the given gedcom record at the -* given line number -* @param string $gedrec the level 0 gedcom record -* @param int $linenum the line number of the fact to edit within $gedrec -* @param string $level0type the type of the level 0 gedcom record -*/ -function create_edit_form($gedrec, $linenum, $level0type) { - global $WORD_WRAPPED_NOTES; - global $pid, $tags, $ADVANCED_PLAC_FACTS, $date_and_time; - global $FULL_SOURCES; +// Create a form to edit a WT_Fact object +function create_edit_form($fact) { + global $WORD_WRAPPED_NOTES, $ADVANCED_PLAC_FACTS, $date_and_time, $FULL_SOURCES; + global $pid, $tags; $tags=array(); - $gedlines = explode("\n", $gedrec); // -- find the number of lines in the record - if (!isset($gedlines[$linenum])) { - echo "<span class=\"error\">", WT_I18N::translate('An error occurred while creating the Edit form. Another user may have changed this record since you previously viewed it.'), "<br><br>"; - echo WT_I18N::translate('Please reload the previous page to make sure you are working with the most recent record.'), "</span>"; - return; - } + $gedlines = explode("\n", $fact->getGedcom()); + + $linenum = 0; $fields = explode(' ', $gedlines[$linenum]); $glevel = $fields[0]; $level = $glevel; - if ($level!=1 && preg_match("~/@.*/@~i", trim($fields[1]))) { - echo "<span class=\"error\">", WT_I18N::translate('An error occurred while creating the Edit form. Another user may have changed this record since you previously viewed it.'), "<br><br>"; - echo WT_I18N::translate('Please reload the previous page to make sure you are working with the most recent record.'), "</span>"; - return; - } - - $type = trim($fields[1]); + $type = $fact->getTag(); + $parent = $fact->getParent(); + $level0type = $parent::RECORD_TYPE; $level1type = $type; // GEDFact_assistant ================================================ @@ -2318,7 +1462,7 @@ function create_edit_form($gedrec, $linenum, $level0type) { if ($type!="DATA" && $type!="CONT") { $tags[]=$type; - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); $subrecord = $level.' '.$type.' '.$text; if ($inSource && $type=="DATE") { add_simple_tag($subrecord, '', WT_Gedcom_Tag::getLabel($label, $person)); diff --git a/includes/functions/functions_export.php b/includes/functions/functions_export.php index cf9598766c..eaef1ed0c3 100644 --- a/includes/functions/functions_export.php +++ b/includes/functions/functions_export.php @@ -206,11 +206,11 @@ function export_gedcom($gedcom, $gedout, $exportOptions) { $buffer=reformat_record_export($head); $rows=WT_DB::prepare( - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". " FROM `##individuals` WHERE i_file=? ORDER BY i_id" - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(C); foreach ($rows as $row) { - list($rec)=WT_Person::getInstance($row)->privatizeGedcom($access_level); + $rec = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); if ($exportOptions['toANSI']=="yes") { $rec=utf8_decode($rec); } @@ -222,11 +222,11 @@ function export_gedcom($gedcom, $gedout, $exportOptions) { } $rows=WT_DB::prepare( - "SELECT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec". + "SELECT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom". " FROM `##families` WHERE f_file=? ORDER BY f_id" - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - list($rec)=WT_Family::getInstance($row)->privatizeGedcom($access_level); + $rec = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); if ($exportOptions['toANSI']=="yes") { $rec=utf8_decode($rec); } @@ -238,11 +238,11 @@ function export_gedcom($gedcom, $gedout, $exportOptions) { } $rows=WT_DB::prepare( - "SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec". + "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom". " FROM `##sources` WHERE s_file=? ORDER BY s_id" - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - list($rec)=WT_Source::getInstance($row)->privatizeGedcom($access_level); + $rec = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); if ($exportOptions['toANSI']=="yes") { $rec=utf8_decode($rec); } @@ -254,11 +254,22 @@ function export_gedcom($gedcom, $gedout, $exportOptions) { } $rows=WT_DB::prepare( - "SELECT o_type AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec". - " FROM `##other` WHERE o_file=? AND o_type!=? AND o_type!=? ORDER BY o_id" - )->execute(array($ged_id, 'HEAD', 'TRLR'))->fetchAll(PDO::FETCH_ASSOC); + "SELECT o_type AS type, o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". + " FROM `##other` WHERE o_file=? AND o_type!='HEAD' AND o_type!='TRLR' ORDER BY o_id" + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - list($rec)=WT_GedcomRecord::getInstance($row)->privatizeGedcom($access_level); + switch ($row->type) { + case 'NOTE': + $rec = WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); + break; + case 'REPO': + $rec = WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); + break; + default: + $rec = WT_GedcomRecord::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); + break; + } + if ($exportOptions['toANSI']=="yes") { $rec=utf8_decode($rec); } @@ -272,9 +283,9 @@ function export_gedcom($gedcom, $gedout, $exportOptions) { $rows=WT_DB::prepare( "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename". " FROM `##media` WHERE m_file=? ORDER BY m_id" - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - list($rec)=WT_Media::getInstance($row)->privatizeGedcom($access_level); + $rec = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level); $rec = convert_media_path($rec, $exportOptions['path']); if ($exportOptions['toANSI']=="yes") { $rec=utf8_decode($rec); diff --git a/includes/functions/functions_import.php b/includes/functions/functions_import.php index b1f5d7648d..1de2a011f1 100644 --- a/includes/functions/functions_import.php +++ b/includes/functions/functions_import.php @@ -39,10 +39,8 @@ function reformat_record_import($rec) { // Strip out UTF8 formatting characters $rec=str_replace(array(WT_UTF8_BOM, WT_UTF8_LRM, WT_UTF8_RLM), '', $rec); - // Strip out control characters and mac/msdos line endings - static $control1="\r\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F"; - static $control2="\n?????????????????????????????"; - $rec=strtr($rec, $control1, $control2); + // Strip out mac/msdos line endings + $rec=preg_replace("/[\r\n]+/", "\n", $rec); // Extract lines from the record; lines consist of: level + optional xref + tag + optional data $num_matches=preg_match_all('/^[ \t]*(\d+)[ \t]*(@[^@]*@)?[ \t]*(\w+)[ \t]?(.*)$/m', $rec, $matches, PREG_SET_ORDER); @@ -664,7 +662,7 @@ function import_record($gedrec, $ged_id, $update) { switch ($type) { case 'INDI': - $record=new WT_Person($gedrec); + $record=new WT_Individual($xref, $gedrec, null, $ged_id); if ($USE_RIN && preg_match('/\n1 RIN (.+)/', $gedrec, $match)) { $rin=$match[1]; } else { @@ -678,7 +676,7 @@ function import_record($gedrec, $ged_id, $update) { update_names ($xref, $ged_id, $record); break; case 'FAM': - $record=new WT_Family($gedrec); + $record=new WT_Family($xref, $gedrec, null, $ged_id); if (preg_match('/\n1 HUSB @('.WT_REGEX_XREF.')@/', $gedrec, $match)) { $husb=$match[1]; } else { @@ -705,7 +703,7 @@ function import_record($gedrec, $ged_id, $update) { //update_names ($xref, $ged_id, $record); We do not store family names in wt_names break; case 'SOUR': - $record=new WT_Source($gedrec); + $record=new WT_Source($xref, $gedrec, null, $ged_id); if (preg_match('/\n1 TITL (.+)/', $gedrec, $match)) { $name=$match[1]; } elseif (preg_match('/\n1 ABBR (.+)/', $gedrec, $match)) { @@ -719,14 +717,14 @@ function import_record($gedrec, $ged_id, $update) { update_names ($xref, $ged_id, $record); break; case 'REPO': - $record=new WT_Repository($gedrec); + $record=new WT_Repository($xref, $gedrec, null, $ged_id); $sql_insert_other->execute(array($xref, $ged_id, $type, $gedrec)); // Update the cross-reference/index tables. update_links ($xref, $ged_id, $gedrec); update_names ($xref, $ged_id, $record); break; case 'OBJE': - $record=new WT_Media($gedrec); + $record=new WT_Media($xref, $gedrec, null, $ged_id); $sql_insert_media->execute(array($xref, $record->extension(), $record->getMediaType(), $record->title, $record->file, $ged_id, $gedrec)); // Update the cross-reference/index tables. update_links ($xref, $ged_id, $gedrec); @@ -736,7 +734,7 @@ function import_record($gedrec, $ged_id, $update) { // Custom records beginning with frequently do not contain unique // identifiers - so we cannot load them. if (substr($type, 0, 1)!='_') { - $record=new WT_GedcomRecord($gedrec); + $record=new WT_GedcomRecord($xref, $gedrec, null, $ged_id); if ($type=='HEAD' && !strpos($gedrec, "\n1 DATE ")) { $gedrec.="\n1 DATE ".date('j M Y'); } @@ -897,7 +895,7 @@ function update_names($xref, $ged_id, $record) { } foreach ($record->getAllNames() as $n=>$name) { - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { if ($name['givn']=='@P.N.') { $soundex_givn_std=null; $soundex_givn_dm=null; @@ -1037,21 +1035,6 @@ function reject_all_changes($xref, $ged_id) { )->execute(array($xref, $ged_id)); } -// Find a string in a file, preceded by a any form of line-ending. -// Although webtrees always writes them as WT_EOL, it is possible that the file was -// edited externally by an editor that uses different endings. -function find_newline_string($haystack, $needle, $offset=0) { - if ($pos=strpos($haystack, "\r\n{$needle}", $offset)) { - return $pos+2; - } elseif ($pos=strpos($haystack, "\n{$needle}", $offset)) { - return $pos+1; - } elseif ($pos=strpos($haystack, "\r{$needle}", $offset)) { - return $pos+1; - } else { - return false; - } -} - /** * update a record in the database * @param string $gedrec diff --git a/includes/functions/functions_print.php b/includes/functions/functions_print.php index 7528ab266a..b7b5d79325 100644 --- a/includes/functions/functions_print.php +++ b/includes/functions/functions_print.php @@ -79,11 +79,11 @@ function print_pedigree_person($person, $style=1, $count=0, $personcount="1") { $iconsStyleAdd = 'float:right;'; if ($TEXT_DIRECTION=='rtl') $iconsStyleAdd='float:left;'; - $disp=$person->canDisplayDetails(); + $disp=$person->canShow(); $uniqueID = (int)(microtime() * 1000000); $boxID = $pid.'.'.$personcount.'.'.$count.'.'.$uniqueID; $mouseAction4 = " onclick=\"expandbox('".$boxID."', $style); return false;\""; - if ($person->canDisplayName()) { + if ($person->canShowName()) { if (empty($SEARCH_SPIDER)) { //-- draw a box for the family popup // NOTE: Start div I.$pid.$personcount.$count.links @@ -169,7 +169,7 @@ function print_pedigree_person($person, $style=1, $count=0, $personcount="1") { $addname=$person->getAddName(); // add optional CSS style for each fact - $indirec = $person->getGedcomRecord(); + $indirec = $person->getGedcom(); $cssfacts = array("BIRT", "CHR", "DEAT", "BURI", "CREM", "ADOP", "BAPM", "BARM", "BASM", "BLES", "CHRA", "CONF", "FCOM", "ORDN", "NATU", "EMIG", "IMMI", "CENS", "PROB", "WILL", "GRAD", "RETI", "CAST", "DSCR", "EDUC", "IDNO", "NATI", "NCHI", "NMR", "OCCU", "PROP", "RELI", "RESI", "SSN", "TITL", "BAPL", "CONL", "ENDL", "SLGC", "_MILI"); foreach ($cssfacts as $indexval => $fact) { @@ -216,7 +216,7 @@ function print_pedigree_person($person, $style=1, $count=0, $personcount="1") { if ($show_full) { foreach (explode('|', WT_EVENTS_DEAT) as $deattag) { $event = $person->getFactByType($deattag); - if (!is_null($event) && ($event->getDate()->isOK() || $event->getPlace() || $event->getDetail()=='Y') && $event->canShow()) { + if (!is_null($event) && ($event->getDate()->isOK() || $event->getPlace() || $event->getValue()=='Y') && $event->canShow()) { $BirthDeath .= $event->print_simple_fact(true); if (in_array($deattag, $opt_tags)) { unset ($opt_tags[array_search($deattag, $opt_tags)]); @@ -277,15 +277,14 @@ function header_links($META_DESCRIPTION, $META_ROBOTS, $META_GENERATOR, $LINK_CA * prints out the execution time and the databse queries */ function execution_stats() { - global $start_time, $PRIVACY_CHECKS; + global $start_time; return '<div class="execution_stats">'. WT_I18N::translate( - 'Execution time: %1$s seconds. Database queries: %2$s. Privacy checks: %3$s. Memory usage: %4$s KB.', - WT_I18N::number(microtime(true)-$start_time, 3), + 'Execution time: %1$s seconds. Database queries: %2$s. Memory usage: %3$s KB.', + WT_I18N::number(microtime(true) - $start_time, 3), WT_I18N::number(WT_DB::getQueryCount()), - WT_I18N::number($PRIVACY_CHECKS), WT_I18N::number(memory_get_peak_usage(true)/1024) ). '</div>'; @@ -541,8 +540,8 @@ function print_fact_notes($factrec, $level, $textOnly=false, $return=false) { } else { $note=WT_Note::getInstance($nmatch[1]); if ($note) { - if ($note->canDisplayDetails()) { - $noterec = $note->getGedcomRecord(); + if ($note->canShow()) { + $noterec = $note->getGedcom(); //-- print linked note records $nt = preg_match("/0 @$nmatch[1]@ NOTE (.*)/", $noterec, $n1match); $closeSpan = print_note_record(($nt>0)?$n1match[1]:"", 1, $noterec, $textOnly, true); @@ -623,11 +622,11 @@ function highlight_search_hits($string) { } // Print the associations from the associated individuals in $event to the individuals in $record -function print_asso_rela_record(WT_Event $event, WT_GedcomRecord $record) { +function print_asso_rela_record(WT_Fact $event, WT_GedcomRecord $record) { global $SEARCH_SPIDER; // To whom is this record an assocate? - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { // On an individual page, we just show links to the person $associates=array($record); } elseif ($record instanceof WT_Family) { @@ -638,15 +637,15 @@ function print_asso_rela_record(WT_Event $event, WT_GedcomRecord $record) { return; } - preg_match_all('/^1 ASSO @('.WT_REGEX_XREF.')@((\n[2-9].*)*)/', $event->getGedcomRecord(), $amatches1, PREG_SET_ORDER); - preg_match_all('/\n2 _?ASSO @('.WT_REGEX_XREF.')@((\n[3-9].*)*)/', $event->getGedcomRecord(), $amatches2, PREG_SET_ORDER); + preg_match_all('/^1 ASSO @('.WT_REGEX_XREF.')@((\n[2-9].*)*)/', $event->getGedcom(), $amatches1, PREG_SET_ORDER); + preg_match_all('/\n2 _?ASSO @('.WT_REGEX_XREF.')@((\n[3-9].*)*)/', $event->getGedcom(), $amatches2, PREG_SET_ORDER); // For each ASSO record foreach (array_merge($amatches1, $amatches2) as $amatch) { - $person=WT_Person::getInstance($amatch[1]); + $person=WT_Individual::getInstance($amatch[1]); if (!$person) { // If the target of the ASSO does not exist, create a dummy person, so // the user can see that something is present. - $person=new WT_Person(''); + $person=new WT_Individual(''); } if (preg_match('/\n[23] RELA (.+)/', $amatch[2], $rmatch)) { $rela=$rmatch[1]; @@ -700,7 +699,7 @@ function format_parents_age($pid, $birth_date=null) { $html=''; if ($SHOW_PARENTS_AGE) { - $person=WT_Person::getInstance($pid); + $person=WT_Individual::getInstance($pid); $families=$person->getChildFamilies(); // Where an indi has multiple birth records, we need to know the // date of it. For person boxes, etc., use the default birth date. @@ -752,12 +751,12 @@ function format_parents_age($pid, $birth_date=null) { // $record - the person (or couple) whose ages should be printed // $anchor option to print a link to calendar // $time option to print TIME value -function format_fact_date(WT_Event $event, WT_GedcomRecord $record, $anchor=false, $time=false) { +function format_fact_date(WT_Fact $event, WT_GedcomRecord $record, $anchor=false, $time=false) { global $pid, $SEARCH_SPIDER; global $GEDCOM; $ged_id=get_id_from_gedcom($GEDCOM); - $factrec = $event->getGedcomRecord(); + $factrec = $event->getGedcom(); $html=''; // Recorded age $fact_age=get_gedcom_value('AGE', 2, $factrec); @@ -781,7 +780,7 @@ function format_fact_date(WT_Event $event, WT_GedcomRecord $record, $anchor=fals } } $fact = $event->getTag(); - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { // age of parents at child birth if ($fact=='BIRT') { $html .= format_parents_age($record->getXref(), $date); @@ -825,7 +824,7 @@ function format_fact_date(WT_Event $event, WT_GedcomRecord $record, $anchor=fals } else { $ageText = '('.$age.' '.WT_I18N::translate('after death').')'; // Family events which occur after death are probably errors - if ($event->getParentObject() instanceof WT_Family) { + if ($event->getParent() instanceof WT_Family) { $ageText.='<i class="icon-warning"></i>'; } } @@ -834,26 +833,27 @@ function format_fact_date(WT_Event $event, WT_GedcomRecord $record, $anchor=fals if ($ageText) $html .= ' <span class="age">'.$ageText.'</span>'; } } elseif ($record instanceof WT_Family) { - $indirec=find_person_record($pid, $ged_id); - $indi=new WT_Person($indirec); - $birth_date=$indi->getBirthDate(); - $death_date=$indi->getDeathDate(); - $ageText = ''; - if (WT_Date::Compare($date, $death_date)<=0) { - $age=WT_Date::GetAgeGedcom($birth_date, $date); - // Only show calculated age if it differs from recorded age - if ($age!='' && $age>0) { - if ( - $fact_age!='' && $fact_age!=$age || - $fact_age=='' && $husb_age=='' && $wife_age=='' || - $husb_age!='' && $indi->getSex()=='M' && $husb_age!= $age || - $wife_age!='' && $indi->getSex()=='F' && $wife_age!=$age - ) { - $ageText = '('.WT_I18N::translate('Age').' '.get_age_at_event($age, false).')'; + $indi = WT_Individual::getInstance($pid); + if ($indi) { + $birth_date=$indi->getBirthDate(); + $death_date=$indi->getDeathDate(); + $ageText = ''; + if (WT_Date::Compare($date, $death_date)<=0) { + $age=WT_Date::GetAgeGedcom($birth_date, $date); + // Only show calculated age if it differs from recorded age + if ($age!='' && $age>0) { + if ( + $fact_age!='' && $fact_age!=$age || + $fact_age=='' && $husb_age=='' && $wife_age=='' || + $husb_age!='' && $indi->getSex()=='M' && $husb_age!= $age || + $wife_age!='' && $indi->getSex()=='F' && $wife_age!=$age + ) { + $ageText = '('.WT_I18N::translate('Age').' '.get_age_at_event($age, false).')'; + } } } + if ($ageText) $html .= ' <span class="age">'.$ageText.'</span>'; } - if ($ageText) $html .= ' <span class="age">'.$ageText.'</span>'; } } else { // 1 DEAT Y with no DATE => print YES @@ -881,10 +881,10 @@ function format_fact_date(WT_Event $event, WT_GedcomRecord $record, $anchor=fals * @param boolean $sub option to print place subrecords * @param boolean $lds option to print LDS TEMPle and STATus */ -function format_fact_place(WT_Event $event, $anchor=false, $sub=false, $lds=false) { +function format_fact_place(WT_Fact $event, $anchor=false, $sub=false, $lds=false) { global $SHOW_PEDIGREE_PLACES, $SHOW_PEDIGREE_PLACES_SUFFIX, $SEARCH_SPIDER; - $factrec = $event->getGedcomRecord(); + $factrec = $event->getGedcom(); $wt_place=new WT_Place($event->getPlace(), WT_GED_ID); diff --git a/includes/functions/functions_print_facts.php b/includes/functions/functions_print_facts.php index 65a87e6c53..cff5c19cf6 100644 --- a/includes/functions/functions_print_facts.php +++ b/includes/functions/functions_print_facts.php @@ -32,12 +32,12 @@ if (!defined('WT_WEBTREES')) { // Print a fact record, for the individual/family/source/repository/etc. pages. // -// Although a WT_Event has a parent object, we also need to know +// Although a WT_Fact has a parent object, we also need to know // the WT_GedcomRecord for which we are printing it. For example, // we can show the death of X on the page of Y, or the marriage // of X+Y on the page of Z. We need to know both records to // calculate ages, relationships, etc. -function print_fact(WT_Event $fact, WT_GedcomRecord $record) { +function print_fact(WT_Fact $fact, WT_GedcomRecord $record) { global $HIDE_GEDCOM_ERRORS, $SHOW_FACT_ICONS; static $n_chil=0, $n_gchi=0; @@ -45,13 +45,7 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { return; } - $parent = $fact->getParentObject(); - - if ($parent) { - $pid = $parent->getXref(); - } else { - $pid = ''; - } + $parent = $fact->getParent(); // Some facts don't get printed here ... switch ($fact->getTag()) { @@ -62,10 +56,7 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { print_main_sources($fact, 1); return; case 'OBJE': - // These are printed separately, after all other facts - return; - case 'BLOB': - // A deprecated tag, that cannot be displayed ?? + print_main_media($fact, 1); return; case 'FAMC': case 'FAMS': @@ -86,12 +77,9 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { } // Who is this fact about? Need it to translate fact label correctly - if ($fact->getSpouse()) { + if ($fact->getParent() instanceof WT_Family && $fact->getParent()->getSpouse($record)) { // Event of close relative - $label_person = $fact->getSpouse(); - } else if (preg_match('/2 _WTS @('.WT_REGEX_XREF.')@/', $fact->getGedcomRecord(), $match)) { - // Event of close relative - $label_person=WT_Person::getInstance($match[1]); + $label_person = $fact->getParent()->getSpouse($record); } else if ($parent instanceof WT_Family) { // Family event $husb = $parent->getHusband(); @@ -104,21 +92,32 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { $label_person=$parent; } - $styleadd=""; - if ($fact->getIsNew()) $styleadd="change_new"; - if ($fact->getIsOld()) $styleadd="change_old"; + // New or deleted facts need different styling + $styleadd=''; + if ($fact->isNew()) { + $styleadd = 'new'; + } + if ($fact->isOld()) { + $styleadd = 'old'; + } - if ($fact->getLineNumber()<1) $styleadd='rela'; // not editable - if ($fact->getLineNumber()==-1) $styleadd='histo'; // historical facts + // Event of close relative + if (preg_match('/^_[A-Z_]{4,5}_[A-Z0-9]{4}$/', $fact->getTag())) { + $styleadd='rela'; + } - if ($styleadd=='') { - $rowID = 'row_'.(int)(microtime()*1000000); - } else { - $rowID = 'row_'.$styleadd; + // Event of close associates + if ($fact->getFactId()=='asso') { + $styleadd='rela'; + } + + // historical facts + if ($fact->getFactId()=='histo') { + $styleadd='histo'; } // Does this fact have a type? - if (preg_match('/\n2 TYPE (.+)/', $fact->getGedcomRecord(), $match)) { + if (preg_match('/\n2 TYPE (.+)/', $fact->getGedcom(), $match)) { $type=$match[1]; } else { $type=''; @@ -156,21 +155,47 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { break; } - echo '<tr class="', $rowID, '">'; - echo '<td class="descriptionbox ', $styleadd, ' width20">'; + echo '<tr class="', $styleadd, '">'; + echo '<td class="descriptionbox width20">'; if ($SHOW_FACT_ICONS) { echo $fact->Icon(), ' '; } - if (WT_USER_CAN_EDIT && $styleadd!='change_old' && $fact->getLineNumber()>0 && $fact->canEdit()) { - echo - '<a onclick="return edit_record(\'', $pid, '\', ', $fact->getLineNumber(), ');" href="#" title="', WT_I18N::translate('Edit'), '">', $label, '</a>', - '<div class="editfacts">', - '<div class="editlink"><a class="editicon" onclick="return edit_record(\'', $pid, '\', ', $fact->getLineNumber(), ');" href="#" title="', WT_I18N::translate('Edit'), '"><span class="link_text">', WT_I18N::translate('Edit'), '</span></a></div>', - '<div class="copylink"><a class="copyicon" href="#" onclick="jQuery.post(\'action.php\',{action:\'copy-fact\', type:\''.$parent::RECORD_TYPE.'\',factgedcom:\''.rawurlencode($fact->getGedcomRecord()).'\'},function(){location.reload();})" title="', WT_I18N::translate('Copy'), '"><span class="link_text">', WT_I18N::translate('Copy'), '</span></a></div>', - '<div class="deletelink"><a class="deleteicon" onclick="return delete_fact(\'', $pid, '\', ', $fact->getLineNumber(), ', \'\', \' ', WT_I18N::translate('Are you sure you want to delete this fact?'), '\');" href="#" title="', WT_I18N::translate('Delete'), '"><span class="link_text">', WT_I18N::translate('Delete'), '</span></a></div>', - '</div>'; + if ($fact->canEdit()) { + ?> + <a + href="#" + title="<?php echo WT_I18N::translate('Edit'); ?>" + onclick="return edit_record('<?php echo $parent->getXref(); ?>', '<?php echo $fact->getFactId(); ?>');" + ><?php echo $label; ?></a> + <div class="editfacts"> + <div class="editlink"> + <a + href="#" + title="<?php echo WT_I18N::translate('Edit'); ?>" + class="editicon" + onclick="return edit_record('<?php echo $parent->getXref(); ?>', '<?php echo $fact->getFactId(); ?>');" + ><span class="link_text"><?php echo WT_I18N::translate('Edit'); ?></span></a> + </div> + <div class="copylink"> + <a + href="#" + title="<?php echo WT_I18N::translate('Copy'); ?>" + class="copyicon" + onclick="return copy_fact('<?php echo $parent->getXref(); ?>', '<?php echo $fact->getFactId(); ?>');" + ><span class="link_text">', WT_I18N::translate('Copy'), '</span></a> + </div> + <div class="deletelink"> + <a + href="#" + title="<?php echo WT_I18N::translate('Delete'); ?>" + class="deleteicon" + onclick="return delete_fact('<?php echo WT_I18N::translate('Are you sure you want to delete this fact?'); ?>', '<?php echo $parent->getXref(); ?>', '<?php echo $fact->getFactId(); ?>');" + ><span class="link_text">', WT_I18N::translate('Delete'), '</span></a> + </div> + </div> + <?php } else { echo $label; } @@ -189,11 +214,12 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { echo '</td><td class="optionbox ', $styleadd, ' wrap">'; // Print the spouse and family of this fact/event - if ($fact->getSpouse()) { - // The significant spouse is set on family events of close relatives - echo '<a href="', $fact->getSpouse()->getHtmlUrl(), '">', $fact->getSpouse()->getFullName(), '</a> - '; - } - if ($parent instanceof WT_Family && $record instanceof WT_Person) { + if ($parent instanceof WT_Family && $record instanceof WT_Individual) { + foreach ($parent->getSpouses() as $spouse) { + if (!$record->equals($spouse)) { + echo '<a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> - '; + } + } // Family events on an individual page echo '<a href="', $parent->getHtmlUrl(), '">', WT_I18N::translate('View Family'), '</a><br>'; } @@ -201,10 +227,10 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { // Print the value of this fact/event switch ($fact->getTag()) { case 'ADDR': - print_address_structure($fact->getGedcomRecord(), 1); + print_address_structure($fact->getGedcom(), 1); break; case 'AFN': - echo '<div class="field"><a href="https://familysearch.org/search/tree/results#count=20&query=afn:', rawurlencode($fact->getDetail()), '" target="new">', htmlspecialchars($fact->getDetail()), '</a></div>'; + echo '<div class="field"><a href="https://familysearch.org/search/tree/results#count=20&query=afn:', rawurlencode($fact->getValue()), '" target="new">', htmlspecialchars($fact->getValue()), '</a></div>'; break; case 'ASSO': // we handle this later, in print_asso_rela_record() @@ -212,16 +238,16 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { case 'EMAIL': case 'EMAI': case '_EMAIL': - echo '<div class="field"><a href="mailto:', htmlspecialchars($fact->getDetail()), '">', htmlspecialchars($fact->getDetail()), '</a></div>'; + echo '<div class="field"><a href="mailto:', htmlspecialchars($fact->getValue()), '">', htmlspecialchars($fact->getValue()), '</a></div>'; break; case 'FILE': if (WT_USER_CAN_EDIT || WT_USER_CAN_ACCEPT) { - echo '<div class="field">', htmlspecialchars($fact->getDetail()), '</div>'; + echo '<div class="field">', htmlspecialchars($fact->getValue()), '</div>'; } break; case 'RESN': echo '<div class="field">'; - switch ($fact->getDetail()) { + switch ($fact->getValue()) { case 'none': // Note: "1 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private record to public". @@ -237,32 +263,31 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { echo '<i class="icon-locked-none"></i> ', WT_I18N::translate('Only managers can edit'); break; default: - echo htmlspecialchars($fact->getDetail()); + echo htmlspecialchars($fact->getValue()); break; } echo '</div>'; break; case 'PUBL': // Publication details might contain URLs. - echo '<div class="field">', expand_urls(htmlspecialchars($fact->getDetail())), '</div>'; + echo '<div class="field">', expand_urls(htmlspecialchars($fact->getValue())), '</div>'; break; case 'REPO': - if (preg_match('/^@('.WT_REGEX_XREF.')@$/', $fact->getDetail(), $match)) { + if (preg_match('/^@('.WT_REGEX_XREF.')@$/', $fact->getValue(), $match)) { print_repository_record($match[1]); } else { - echo '<div class="error">', htmlspecialchars($fact->getDetail()), '</div>'; + echo '<div class="error">', htmlspecialchars($fact->getValue()), '</div>'; } break; case 'URL': case 'WWW': - echo '<div class="field"><a href="', htmlspecialchars($fact->getDetail()), '">', htmlspecialchars($fact->getDetail()), '</a></div>'; + echo '<div class="field"><a href="', htmlspecialchars($fact->getValue()), '">', htmlspecialchars($fact->getValue()), '</a></div>'; break; case 'TEXT': // 0 SOUR / 1 TEXT - // PHP5.3 echo '<div class="field">', nl2br(htmlspecialchars($fact->getDetail()), false), '</div>'; - echo '<div class="field">', nl2br(htmlspecialchars($fact->getDetail())), '</div>'; + echo '<div class="field">', nl2br(htmlspecialchars($fact->getValue()), false), '</div>'; break; default: // Display the value for all other facts/events - switch ($fact->getDetail()) { + switch ($fact->getValue()) { case '': // Nothing to display break; @@ -274,15 +299,15 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { // Do not display "Yes". break; default: - if (preg_match('/^@('.WT_REGEX_XREF.')@$/', $fact->getDetail(), $match)) { + if (preg_match('/^@('.WT_REGEX_XREF.')@$/', $fact->getValue(), $match)) { $target=WT_GedcomRecord::getInstance($match[1]); if ($target) { echo '<div><a href="', $target->getHtmlUrl(), '">', $target->getFullName(), '</a></div>'; } else { - echo '<div class="error">', htmlspecialchars($fact->getDetail()), '</div>'; + echo '<div class="error">', htmlspecialchars($fact->getValue()), '</div>'; } } else { - echo '<div class="field"><span dir="auto">', htmlspecialchars($fact->getDetail()), '</span></div>'; + echo '<div class="field"><span dir="auto">', htmlspecialchars($fact->getValue()), '</span></div>'; } break; } @@ -302,13 +327,13 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { echo '<div class="place">', format_fact_place($fact, true, true, true), '</div>'; // A blank line between the primary attributes (value, date, place) and the secondary ones echo '<br>'; - print_address_structure($fact->getGedcomRecord(), 2); + print_address_structure($fact->getGedcom(), 2); // Print the associates of this fact/event print_asso_rela_record($fact, $record); // Print any other "2 XXXX" attributes, in the order in which they appear. - preg_match_all('/\n2 ('.WT_REGEX_TAG.') (.+)/', $fact->getGedcomRecord(), $matches, PREG_SET_ORDER); + preg_match_all('/\n2 ('.WT_REGEX_TAG.') (.+)/', $fact->getGedcom(), $matches, PREG_SET_ORDER); foreach ($matches as $match) { switch ($match[1]) { case 'DATE': @@ -325,8 +350,6 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { case 'TEMP': case 'TYPE': case 'FAMS': - case '_WTS': - case '_WTFS': case 'CONT': // These were already shown at the beginning break; @@ -342,11 +365,11 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { } if (count($events)==1) echo WT_Gedcom_Tag::getLabelValue('EVEN', $event); else echo WT_Gedcom_Tag::getLabelValue('EVEN', implode(WT_I18N::$list_separator, $events)); - if (preg_match('/\n3 DATE (.+)/', $fact->getGedcomRecord(), $date_match)) { + if (preg_match('/\n3 DATE (.+)/', $fact->getGedcom(), $date_match)) { $date=new WT_Date($date_match[1]); echo WT_Gedcom_Tag::getLabelValue('DATE', $date->Display()); } - if (preg_match('/\n3 PLAC (.+)/', $fact->getGedcomRecord(), $plac_match)) { + if (preg_match('/\n3 PLAC (.+)/', $fact->getGedcom(), $plac_match)) { echo WT_Gedcom_Tag::getLabelValue('PLAC', $plac_match[1]); } break; @@ -354,7 +377,7 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { $family=WT_Family::getInstance(str_replace('@', '', $match[2])); if ($family) { // May be a pointer to a non-existant record echo WT_Gedcom_Tag::getLabelValue('FAM', '<a href="'.$family->getHtmlUrl().'">'.$family->getFullName().'</a>'); - if (preg_match('/\n3 ADOP (HUSB|WIFE|BOTH)/', $fact->getGedcomRecord(), $match)) { + if (preg_match('/\n3 ADOP (HUSB|WIFE|BOTH)/', $fact->getGedcom(), $match)) { echo WT_Gedcom_Tag::getLabelValue('ADOP', WT_Gedcom_Code_Adop::getValue($match[1], $label_person)); } } else { @@ -395,7 +418,7 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { break; case 'FORM': // 0 OBJE / 1 FILE / 2 FORM / 3 TYPE echo WT_Gedcom_Tag::getLabelValue('FORM', $match[2]); - if (preg_match('/\n3 TYPE (.+)/', $fact->getGedcomRecord(), $type_match)) { + if (preg_match('/\n3 TYPE (.+)/', $fact->getGedcom(), $type_match)) { echo WT_Gedcom_Tag::getLabelValue('TYPE', WT_Gedcom_Tag::getFileFormTypeValue($type_match[1])); } break; @@ -419,11 +442,11 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { } } // -- find source for each fact - print_fact_sources($fact->getGedcomRecord(), 2); + print_fact_sources($fact->getGedcom(), 2); // -- find notes for each fact - print_fact_notes($fact->getGedcomRecord(), 2); + print_fact_notes($fact->getGedcom(), 2); //-- find media objects - print_media_links($fact->getGedcomRecord(), 2, $pid); + print_media_links($fact->getGedcom(), 2, $parent->getXref()); echo '</td></tr>'; } //------------------- end print fact function @@ -436,11 +459,11 @@ function print_fact(WT_Event $fact, WT_GedcomRecord $record) { */ function print_repository_record($xref) { $repository=WT_Repository::getInstance($xref); - if ($repository && $repository->canDisplayDetails()) { + if ($repository && $repository->canShow()) { echo '<a class="field" href="', $repository->getHtmlUrl(), '">', $repository->getFullName(), '</a><br>'; - print_address_structure($repository->getGedcomRecord(), 1); + print_address_structure($repository->getGedcom(), 1); echo '<br>'; - print_fact_notes($repository->getGedcomRecord(), 1); + print_fact_notes($repository->getGedcom(), 1); } } @@ -476,7 +499,7 @@ function print_fact_sources($factrec, $level, $return=false) { $sid = $match[$j][1]; $source=WT_Source::getInstance($sid); if ($source) { - if ($source->canDisplayDetails()) { + if ($source->canShow()) { $spos1 = strpos($factrec, "$level SOUR @".$sid."@", $spos2); $spos2 = strpos($factrec, "\n$level", $spos1); if (!$spos2) { @@ -505,7 +528,7 @@ function print_fact_sources($factrec, $level, $return=false) { } $data .= ' class="source_citations">'; // PUBL - $text = get_gedcom_value('PUBL', '1', $source->getGedcomRecord()); + $text = get_gedcom_value('PUBL', '1', $source->getGedcom()); if (!empty($text)) { $data .= '<span class="label">'.WT_Gedcom_Tag::getLabel('PUBL').': </span>'; $data .= $text; @@ -553,7 +576,7 @@ function print_media_links($factrec, $level, $pid='') { $media_id = $omatch[$objectNum][1]; $media=WT_Media::getInstance($media_id); if ($media) { - if ($media->canDisplayDetails()) { + 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(); @@ -566,13 +589,13 @@ function print_media_links($factrec, $level, $pid='') { } // NOTE: echo the notes of the media echo '<p>'; - echo print_fact_notes($media->getGedcomRecord(), 1); - if (preg_match('/2 DATE (.+)/', get_sub_record('FILE', 1, $media->getGedcomRecord()), $match)) { + echo print_fact_notes($media->getGedcom(), 1); + if (preg_match('/2 DATE (.+)/', get_sub_record('FILE', 1, $media->getGedcom()), $match)) { $media_date=new WT_Date($match[1]); $md = $media_date->Display(true); echo '<p class="label">', WT_Gedcom_Tag::getLabel('DATE'), ': </p> ', $md; } - $ttype = preg_match("/".($nlevel+1)." TYPE (.*)/", $media->getGedcomRecord(), $match); + $ttype = preg_match("/".($nlevel+1)." TYPE (.*)/", $media->getGedcom(), $match); if ($ttype>0) { $mediaType = WT_Gedcom_Tag::getFileFormTypeValue($match[1]); echo '<p class="label">', WT_I18N::translate('Type'), ': </span> <span class="field">', $mediaType, '</p>'; @@ -581,7 +604,7 @@ function print_media_links($factrec, $level, $pid='') { //-- print spouse name for marriage events $ct = preg_match("/WT_SPOUSE: (.*)/", $factrec, $match); if ($ct>0) { - $spouse=WT_Person::getInstance($match[1]); + $spouse=WT_Individual::getInstance($match[1]); if ($spouse) { echo '<a href="', $spouse->getHtmlUrl(), '">'; echo $spouse->getFullName(); @@ -599,8 +622,8 @@ function print_media_links($factrec, $level, $pid='') { } } } - print_fact_notes($media->getGedcomRecord(), $nlevel); - print_fact_sources($media->getGedcomRecord(), $nlevel); + print_fact_notes($media->getGedcom(), $nlevel); + print_fact_sources($media->getGedcom(), $nlevel); echo '</div>';//close div "media-display-title" echo '</div>';//close div "media-display" } @@ -630,20 +653,20 @@ function print_address_structure($factrec, $level) { } // Print a row for the sources tab on the individual page -function print_main_sources(WT_Event $fact, $level) { +function print_main_sources(WT_Fact $fact, $level) { global $SHOW_FACT_ICONS; - $factrec = $fact->getGedcomRecord(); - $linenum = $fact->getLineNumber(); - $parent = $fact->getParentObject(); + $factrec = $fact->getGedcom(); + $fact_id = $fact->getFactId(); + $parent = $fact->getParent(); $pid = $parent->getXref(); $nlevel = $level+1; - if ($fact->getIsNew()) { - $styleadd = 'change_new'; + if ($fact->isNew()) { + $styleadd = 'new'; $can_edit = $level==1 && $fact->canEdit(); - } elseif ($fact->getIsOld()) { - $styleadd='change_old'; + } elseif ($fact->isOld()) { + $styleadd='old'; $can_edit = false; } else { $styleadd=''; @@ -661,11 +684,11 @@ function print_main_sources(WT_Event $fact, $level) { $srec = substr($factrec, $spos1, $spos2-$spos1); $source=WT_Source::getInstance($sid); // Allow access to "1 SOUR @non_existent_source@", so it can be corrected/deleted - if (!$source || $source->canDisplayDetails()) { - if ($level==2) echo '<tr class="row_sour2">'; + if (!$source || $source->canShow()) { + if ($level>1) echo '<tr class="row_sour2">'; else echo '<tr>'; echo '<td class="descriptionbox'; - if ($level==2) echo ' rela'; + if ($level>1) echo ' rela'; echo ' ', $styleadd, ' width20">'; $temp = preg_match("/^\d (\w*)/", $factrec, $factname); $factlines = explode("\n", $factrec); // 1 BIRT Y\n2 SOUR ... @@ -682,26 +705,25 @@ function print_main_sources(WT_Event $fact, $level) { } } else if ($can_edit) { - echo "<a onclick=\"return edit_record('$pid', $linenum);\" href=\"#\" title=\"", WT_I18N::translate('Edit'), '">'; + echo "<a onclick=\"return edit_record('$pid', '$fact_id');\" href=\"#\" title=\"", WT_I18N::translate('Edit'), '">'; if ($SHOW_FACT_ICONS) { if ($level==1) echo '<i class="icon-source"></i> '; } echo WT_Gedcom_Tag::getLabel($factname, $parent), '</a>'; echo '<div class="editfacts">'; - echo "<div class=\"editlink\"><a class=\"editicon\" onclick=\"return edit_record('$pid', $linenum);\" href=\"#\" title=\"".WT_I18N::translate('Edit')."\"><span class=\"link_text\">".WT_I18N::translate('Edit')."</span></a></div>"; + echo "<div class=\"editlink\"><a class=\"editicon\" onclick=\"return edit_record('$pid', '$fact_id');\" href=\"#\" title=\"".WT_I18N::translate('Edit')."\"><span class=\"link_text\">".WT_I18N::translate('Edit')."</span></a></div>"; echo '<div class="copylink"><a class="copyicon" href="#" onclick="jQuery.post(\'action.php\',{action:\'copy-fact\', type:\'\', factgedcom:\''.rawurlencode($factrec).'\'},function(){location.reload();})" title="'.WT_I18N::translate('Copy').'"><span class="link_text">'.WT_I18N::translate('Copy').'</span></a></div>'; - echo "<div class=\"deletelink\"><a class=\"deleteicon\" onclick=\"return delete_fact('$pid', $linenum, '', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');\" href=\"#\" title=\"".WT_I18N::translate('Delete')."\"><span class=\"link_text\">".WT_I18N::translate('Delete')."</span></a></div>"; + echo "<div class=\"deletelink\"><a class=\"deleteicon\" onclick=\"return delete_fact('$pid', '$fact_id', '', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');\" href=\"#\" title=\"".WT_I18N::translate('Delete')."\"><span class=\"link_text\">".WT_I18N::translate('Delete')."</span></a></div>"; echo '</div>'; } else { echo WT_Gedcom_Tag::getLabel($factname, $parent); } echo '</td>'; echo '<td class="optionbox ', $styleadd, ' wrap">'; - //echo "<td class=\"facts_value$styleadd\">"; if ($source) { echo '<a href="', $source->getHtmlUrl(), '">', $source->getFullName(), '</a>'; // PUBL - $text = get_gedcom_value('PUBL', '1', $source->getGedcomRecord()); + $text = get_gedcom_value('PUBL', '1', $source->getGedcom()); if (!empty($text)) { echo '<br><span class="label">', WT_Gedcom_Tag::getLabel('PUBL'), ': </span>'; echo $text; @@ -742,11 +764,11 @@ function print_main_sources(WT_Event $fact, $level) { echo '<div class="indent">'; print_media_links($srec, $nlevel); if ($nlevel==2) { - print_media_links($source->getGedcomRecord(), 1); + print_media_links($source->getGedcom(), 1); } print_fact_notes($srec, $nlevel); if ($nlevel==2) { - print_fact_notes($source->getGedcomRecord(), 1); + print_fact_notes($source->getGedcom(), 1); } echo '</div>'; } else { @@ -846,19 +868,19 @@ function getSourceStructure($srec) { } // Print a row for the notes tab on the individual page -function print_main_notes(WT_Event $fact, $level) { +function print_main_notes(WT_Fact $fact, $level) { global $GEDCOM, $SHOW_FACT_ICONS, $TEXT_DIRECTION; - $factrec = $fact->getGedcomRecord(); - $linenum = $fact->getLineNumber(); - $parent = $fact->getParentObject(); + $factrec = $fact->getGedcom(); + $fact_id = $fact->getFactId(); + $parent = $fact->getParent(); $pid = $parent->getXref(); - if ($fact->getIsNew()) { - $styleadd = ' change_new'; + if ($fact->isNew()) { + $styleadd = ' new'; $can_edit = $level==1 && $fact->canEdit(); - } elseif ($fact->getIsOld()) { - $styleadd=' change_old'; + } elseif ($fact->isOld()) { + $styleadd=' old'; $can_edit = false; } else { $styleadd=''; @@ -873,7 +895,7 @@ function print_main_notes(WT_Event $fact, $level) { if ($level>=2) echo ' rela'; echo ' ', $styleadd, ' width20">'; if ($can_edit) { - echo '<a onclick="return edit_record(\'', $pid, '\', ', $linenum, ');" href="#" title="', WT_I18N::translate('Edit'), '">'; + echo '<a onclick="return edit_record(\'', $pid, '\', \'', $fact_id, '\');" href="#" title="', WT_I18N::translate('Edit'), '">'; if ($level<2) { if ($SHOW_FACT_ICONS) { echo '<i class="icon-note"></i> '; @@ -885,9 +907,9 @@ function print_main_notes(WT_Event $fact, $level) { } echo '</a>'; echo '<div class="editfacts">'; - echo "<div class=\"editlink\"><a class=\"editicon\" onclick=\"return edit_record('$pid', $linenum);\" href=\"#\" title=\"".WT_I18N::translate('Edit')."\"><span class=\"link_text\">".WT_I18N::translate('Edit')."</span></a></div>"; + echo "<div class=\"editlink\"><a class=\"editicon\" onclick=\"return edit_record('$pid', '$fact_id');\" href=\"#\" title=\"".WT_I18N::translate('Edit')."\"><span class=\"link_text\">".WT_I18N::translate('Edit')."</span></a></div>"; echo '<div class="copylink"><a class="copyicon" href="#" onclick="jQuery.post(\'action.php\',{action:\'copy-fact\', type:\'\', factgedcom:\''.rawurlencode($factrec).'\'},function(){location.reload();})" title="'.WT_I18N::translate('Copy').'"><span class="link_text">'.WT_I18N::translate('Copy').'</span></a></div>'; - echo "<div class=\"deletelink\"><a class=\"deleteicon\" onclick=\"return delete_fact('$pid', $linenum, '', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');\" href=\"#\" title=\"".WT_I18N::translate('Delete')."\"><span class=\"link_text\">".WT_I18N::translate('Delete')."</span></a></div>"; + echo "<div class=\"deletelink\"><a class=\"deleteicon\" onclick=\"return delete_fact('".WT_I18N::translate('Are you sure you want to delete this fact?')."', '$pid', '$fact_id');\" href=\"#\" title=\"".WT_I18N::translate('Delete')."\"><span class=\"link_text\">".WT_I18N::translate('Delete')."</span></a></div>"; echo '</div>'; } } else { @@ -926,10 +948,7 @@ function print_main_notes(WT_Event $fact, $level) { $nid = $nmatch[1]; $note=WT_Note::getInstance($nid); if ($note) { - $noterec=$note->getGedcomRecord(); - $nt = preg_match("/^0 @[^@]+@ NOTE (.*)/", $noterec, $n1match); - $line1 = $n1match[1]; - $text = get_cont(1, $noterec); + $text = $note->getNote(); // If Census assistant installed, if ($fact->getTag()=='CENS' && array_key_exists('GEDFact_assistant', WT_Module::getActiveModules())) { $centitl = str_replace('~~', '', $line1); @@ -937,7 +956,7 @@ function print_main_notes(WT_Event $fact, $level) { $centitl = "<a href=\"note.php?nid=$nid\">" . $centitl . '</a>'; require WT_ROOT.WT_MODULES_DIR.'GEDFact_assistant/_CENS/census_note_decode.php'; } else { - $text = expand_urls($line1 . $text); + $text = expand_urls($text); } } else { $text = '<span class="error">' . htmlspecialchars($nid) . '</span>'; @@ -949,7 +968,7 @@ function print_main_notes(WT_Event $fact, $level) { } echo '<td class="optionbox', $styleadd, ' wrap" align="', $TEXT_DIRECTION== "rtl"?"right": "left" , '">'; - echo $text; + echo '<div style="white-space:pre-wrap;">', $text, '</div>'; if (!empty($noterec)) print_fact_sources($noterec, 1); @@ -985,255 +1004,110 @@ function print_main_notes(WT_Event $fact, $level) { } } -/** - * Print the links to media objects - * @param string $pid The the xref id of the object to find media records related to - * @param int $level The level of media object to find - * @param boolean $related Whether or not to grab media from related records - */ -function print_main_media($pid, $level=1, $related=false) { - global $GEDCOM; - $ged_id=get_id_from_gedcom($GEDCOM); - $person = WT_GedcomRecord::getInstance($pid); - - //-- find all of the related ids - $ids = array($person->getXref()); - if ($related) { - foreach ($person->getSpouseFamilies() as $family) { - $ids[] = $family->getXref(); - } - } - - //-- If they exist, get a list of the sorted current objects in the indi gedcom record - (1 _WT_OBJE_SORT @xxx@ .... etc) ---------- - $sort_current_objes = array(); - $sort_ct = preg_match_all('/\n1 _WT_OBJE_SORT @(.*)@/', $person->getGedcomRecord(), $sort_match, PREG_SET_ORDER); - for ($i=0; $i<$sort_ct; $i++) { - if (!isset($sort_current_objes[$sort_match[$i][1]])) { - $sort_current_objes[$sort_match[$i][1]] = 1; - } else { - $sort_current_objes[$sort_match[$i][1]]++; - } - $sort_obje_links[$sort_match[$i][1]][] = $sort_match[$i][0]; - } - - // create ORDER BY list from Gedcom sorted records list --------------------------- - $orderbylist = 'ORDER BY '; // initialize - foreach ($sort_match as $id) { - $orderbylist .= "m_id='$id[1]' DESC, "; - } - $orderbylist = rtrim($orderbylist, ', '); - - //-- get a list of the current objects in the record - $current_objes = array(); - if ($level>0) { - $regexp = '/\n' . $level . ' OBJE @(.*)@/'; +// Print a row for the media tab on the individual page +function print_main_media(WT_Fact $fact, $level) { + $factrec = $fact->getGedcom(); + $fact_id = $fact->getFactId(); + $parent = $fact->getParent(); + + if ($fact->isNew()) { + $styleadd = 'new'; + $can_edit = $level==1 && $fact->canEdit(); + } elseif ($fact->isOld()) { + $styleadd='old'; + $can_edit = false; } else { - $regexp = '/\n\d OBJE @(.*)@/'; - } - $ct = preg_match_all($regexp, $person->getGedcomRecord(), $match, PREG_SET_ORDER); - for ($i=0; $i<$ct; $i++) { - if (!isset($current_objes[$match[$i][1]])) { - $current_objes[$match[$i][1]] = 1; - } else { - $current_objes[$match[$i][1]]++; - } - $obje_links[$match[$i][1]][] = $match[$i][0]; - } - - $media_found = false; - - // Get the related media items - $sqlmm = - "SELECT DISTINCT m_id, m_ext, m_filename, m_titl, m_file, m_gedcom, l_from AS pid" . - " FROM `##media`" . - " JOIN `##link` ON (m_id=l_to AND m_file=l_file AND l_type='OBJE')" . - " WHERE m_file=? AND l_from IN ("; - $i=0; - $vars=array(WT_GED_ID); - foreach ($ids as $media_id) { - if ($i>0) $sqlmm .= ", "; - $sqlmm .= "?"; - $vars[]=$media_id; - $i++; - } - $sqlmm .= ')'; - - if ($sort_ct>0) { - $sqlmm .= $orderbylist; + $styleadd=''; + $can_edit = $level==1 && $fact->canEdit(); } - $rows=WT_DB::prepare($sqlmm)->execute($vars)->fetchAll(PDO::FETCH_ASSOC); - - $foundObjs = array(); - foreach ($rows as $rowm) { - //-- for family, repository, note and source page only show level 1 obje references - $tmp=WT_GedcomRecord::getInstance($rowm['pid']); - if ($level && !preg_match('/\n'.$level.' OBJE @'.$rowm['m_id'].'@/', $tmp->getGedcomRecord())) { - continue; - } - if (isset($foundObjs[$rowm['m_id']])) { - if (isset($current_objes[$rowm['m_id']])) { - $current_objes[$rowm['m_id']]--; + // -- find source for each fact + preg_match_all('/(?:^|\n)' . $level . ' OBJE @(.*)@/', $factrec, $matches); + foreach ($matches[1] as $xref) { + $media=WT_Media::getInstance($xref); + // Allow access to "1 OBJE @non_existent_source@", so it can be corrected/deleted + if (!$media || $media->canShow()) { + if ($level>1) { + echo '<tr class="row_obje2">'; + } else { + echo '<tr>'; } - continue; - } - $rows=array(); - - //-- if there is a change to this media item then get the - //-- updated media item and show it - if ($newrec=find_updated_record($rowm["m_id"], $ged_id)) { - $row = array(); - $row['m_id'] = $rowm["m_id"]; - $row['m_file']=$rowm["m_file"]; - $row['m_filename'] = get_gedcom_value("FILE", 1, $newrec); - $row['m_titl'] = get_gedcom_value("TITL", 1, $newrec); - if (empty($row['m_titl'])) $row['m_titl'] = get_gedcom_value("FILE:TITL", 1, $newrec); - $row['m_gedcom'] = $newrec; - $et = preg_match("/(\.\w+)$/", $row['m_file'], $ematch); - $ext = ""; - if ($et>0) $ext = substr(trim($ematch[1]), 1); - $row['m_ext'] = $ext; - $row['pid'] = $pid; - $rows['new'] = $row; - $rows['old'] = $rowm; - if (isset($current_objes[$rowm['m_id']])) { - $current_objes[$rowm['m_id']]--; + echo '<td class="descriptionbox'; + if ($level>1) { + echo ' rela'; } - } else { - if (!isset($current_objes[$rowm['m_id']]) && ($rowm['pid']==$pid)) { - $rows['old'] = $rowm; - } else { - $rows['normal'] = $rowm; - if (isset($current_objes[$rowm['m_id']])) { - $current_objes[$rowm['m_id']]--; + echo ' ', $styleadd, ' width20">'; + $temp = preg_match("/^\d (\w*)/", $factrec, $factname); + $factlines = explode("\n", $factrec); // 1 BIRT Y\n2 SOUR ... + $factwords = explode(" ", $factlines[0]); // 1 BIRT Y + $factname = $factwords[1]; // BIRT + if ($factname == 'EVEN' || $factname=='FACT') { + // Add ' EVEN' to provide sensible output for an event with an empty TYPE record + $ct = preg_match("/2 TYPE (.*)/", $factrec, $ematch); + if ($ct>0) { + $factname = $ematch[1]; + echo $factname; + } else { + echo WT_Gedcom_Tag::getLabel($factname, $parent); } + } else + if ($can_edit) { + echo '<a onclick="window.open(\'addmedia.php?action=editmedia&pid=', $media->getXref(), '\', \'_blank\', edit_window_specs); return false;" href="#" title="', WT_I18N::translate('Edit'), '">'; + echo WT_Gedcom_Tag::getLabel($factname, $parent), '</a>'; + echo '<div class="editfacts">'; + echo '<div class="editlink"><a class="editicon" onclick="window.open(\'addmedia.php?action=editmedia&pid=', $media->getXref(), '\', \'_blank\', edit_window_specs); return false;" href="#" title="', WT_I18N::translate('Edit'), '"><span class="link_text">', WT_I18N::translate('Edit'), '</span></a></div>'; + echo '<div class="copylink"><a class="copyicon" href="#" onclick="jQuery.post(\'action.php\',{action:\'copy-fact\', type:\'\', factgedcom:\''.rawurlencode($factrec).'\'},function(){location.reload();})" title="'.WT_I18N::translate('Copy').'"><span class="link_text">'.WT_I18N::translate('Copy').'</span></a></div>'; + echo '<div class="deletelink"><a class="deleteicon" onclick="return delete_fact(\'', WT_I18N::translate('Are you sure you want to delete this fact?'), '\', \'', $parent->getXref(), '\', \'', $fact->getFactId(), '\');" href="#" title="', WT_I18N::translate('Delete'), '"><span class="link_text">', WT_I18N::translate('Delete'), '</span></a></div>'; + echo '</div>'; + } else { + echo WT_Gedcom_Tag::getLabel($factname, $parent); } - } - foreach ($rows as $rtype => $rowm) { - $res = print_main_media_row($rtype, $rowm, $pid); - $media_found = $media_found || $res; - $foundObjs[$rowm['m_id']]=true; - } - } - - //-- objects are removed from the $current_objes list as they are printed - //-- any objects left in the list are new objects recently added to the gedcom - //-- but not yet accepted into the database. We will print them too. - foreach ($current_objes as $media_id=>$value) { - while ($value>0) { - $objSubrec = array_pop($obje_links[$media_id]); - $row = array(); - $newrec = find_gedcom_record($media_id, $ged_id, true); - $row['m_id'] = $media_id; - $row['m_file']=$ged_id; - $row['m_filename'] = get_gedcom_value("FILE", 1, $newrec); - $row['m_titl'] = get_gedcom_value("TITL", 1, $newrec); - if (empty($row['m_titl'])) $row['m_titl'] = get_gedcom_value("FILE:TITL", 1, $newrec); - $row['m_gedcom'] = $newrec; - $et = preg_match("/(\.\w+)$/", $row['m_file'], $ematch); - $ext = ""; - if ($et>0) $ext = substr(trim($ematch[1]), 1); - $row['m_ext'] = $ext; - $row['pid'] = $pid; - $res = print_main_media_row('new', $row, $pid); - $media_found = $media_found || $res; - $value--; - } - } - return $media_found; -} - -/** - * print a media row in a table - * @param string $rtype whether this is a 'new', 'old', or 'normal' media row... this is used to determine if the rows should be printed with an outline color - * @param array $rowm An array with the details about this media item - * @param string $pid The record id this media item was attached to - */ -function print_main_media_row($rtype, $rowm, $pid) { - global $SHOW_FACT_ICONS, $SEARCH_SPIDER; - $mediaobject = new WT_Media($rowm['m_gedcom']); - if (!$mediaobject || !$mediaobject->canDisplayDetails()) { - return false; - } - - if ($rtype=='new') { - $styleadd = ' change_new'; - } elseif ($rtype=='old') { - $styleadd = ' change_old'; - } else { - $styleadd = ''; - } - - $linenum = 0; - echo '<tr><td class="descriptionbox width20', $styleadd, '">'; - if ($SHOW_FACT_ICONS) { - echo '<i class="icon-media"></i> '; - } - echo WT_Gedcom_Tag::getLabel('OBJE'), '</a>'; - echo '<div class="editfacts">'; - if ($mediaobject->canEdit()) { - echo '<a onclick="return window.open(\'addmedia.php?action=editmedia&pid=', $mediaobject->getXref(), '\', \'_blank\', edit_window_specs);" href="#" title="', WT_I18N::translate('Edit'), '">'; - echo "<div class=\"editlink\"><a class=\"editicon\" onclick=\"return window.open('addmedia.php?action=editmedia&pid=".$mediaobject->getXref()."', '_blank', edit_window_specs);\" href=\"#\" title=\"".WT_I18N::translate('Edit')."\"><span class=\"link_text\">".WT_I18N::translate('Edit')."</span></a></div>"; - echo '<div class="copylink"><a class="copyicon" href="#" onclick="jQuery.post(\'action.php\',{action:\'copy-fact\', type:\'\', factgedcom:\'1 OBJE @'.$mediaobject->getXref().'@\'},function(){location.reload();})" title="'.WT_I18N::translate('Copy').'"><span class="link_text">'.WT_I18N::translate('Copy').'</span></a></div>'; - echo "<div class=\"deletelink\"><a class=\"deleteicon\" onclick=\"return delete_fact('", $rowm['pid'], "', 'OBJE', '".$mediaobject->getXref()."', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');\" href=\"#\" title=\"".WT_I18N::translate('Delete')."\"><span class=\"link_text\">".WT_I18N::translate('Delete')."</span></a></div>"; - } - echo '</div>'; - echo '</td>'; - - // NOTE Print the title of the media - echo '<td class="optionbox wrap', $styleadd, '"><span class="field">'; - echo $mediaobject->displayImage(); - if (empty($SEARCH_SPIDER)) { - echo '<a href="'.$mediaobject->getHtmlUrl().'">'; - } - echo '<em>'; - foreach ($mediaobject->getAllNames() as $name) { - if ($name['type']!='TITL') echo '<br>'; - echo $name['full']; - } - echo '</em>'; - if (empty($SEARCH_SPIDER)) { - echo '</a>'; - } - - echo WT_Gedcom_Tag::getLabelValue('FORM', $mediaobject->mimeType()); - $imgsize = $mediaobject->getImageAttributes('main'); - if (!empty($imgsize['WxH'])) { - echo WT_Gedcom_Tag::getLabelValue('__IMAGE_SIZE__', $imgsize['WxH']); - } - if ($mediaobject->getFilesizeraw()>0) { - echo WT_Gedcom_Tag::getLabelValue('__FILE_SIZE__', $mediaobject->getFilesize()); - } - $mediatype=$mediaobject->getMediaType(); - if ($mediatype) { - echo WT_Gedcom_Tag::getLabelValue('TYPE', WT_Gedcom_Tag::getFileFormTypeValue($mediatype)); - } - echo '</span>'; - //-- print spouse name for marriage events - if ($rowm['pid']!=$pid) { - $person=WT_Person::getInstance($pid); - $family=WT_Family::getInstance($rowm['pid']); - if ($family) { - $spouse=$family->getSpouse($person); - if ($spouse) { - echo '<a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> - '; + echo '</td>'; + echo '<td class="optionbox ', $styleadd, ' wrap">'; + if ($media) { + echo '<span class="field">'; + echo $media->displayImage(); + if (empty($SEARCH_SPIDER)) { + echo '<a href="'.$media->getHtmlUrl().'">'; + } + echo '<em>'; + foreach ($media->getAllNames() as $name) { + if ($name['type']!='TITL') echo '<br>'; + echo $name['full']; + } + echo '</em>'; + if (empty($SEARCH_SPIDER)) { + echo '</a>'; + } + + echo WT_Gedcom_Tag::getLabelValue('FORM', $media->mimeType()); + $imgsize = $media->getImageAttributes('main'); + if (!empty($imgsize['WxH'])) { + echo WT_Gedcom_Tag::getLabelValue('__IMAGE_SIZE__', $imgsize['WxH']); + } + if ($media->getFilesizeraw()>0) { + echo WT_Gedcom_Tag::getLabelValue('__FILE_SIZE__', $media->getFilesize()); + } + $mediatype=$media->getMediaType(); + if ($mediatype) { + echo WT_Gedcom_Tag::getLabelValue('TYPE', WT_Gedcom_Tag::getFileFormTypeValue($mediatype)); + } + echo '</span>'; + + switch ($media->isPrimary()) { + case 'Y': + echo WT_Gedcom_Tag::getLabelValue('_PRIM', WT_I18N::translate('yes')); + break; + case 'N': + echo WT_Gedcom_Tag::getLabelValue('_PRIM', WT_I18N::translate('no')); + break; + } + print_fact_notes($media->getGedcom(), 1); + print_fact_sources($media->getGedcom(), 1); + } else { + echo $xref; } - echo '<a href="', $family->getHtmlUrl(), '">', WT_I18N::translate('View Family'), '</a><br>'; + echo '</td></tr>'; } - } - - switch ($mediaobject->isPrimary()) { - case 'Y': - echo WT_Gedcom_Tag::getLabelValue('_PRIM', WT_I18N::translate('yes')); - break; - case 'N': - echo WT_Gedcom_Tag::getLabelValue('_PRIM', WT_I18N::translate('no')); - break; - } - print_fact_notes($mediaobject->getGedcomRecord(), 1); - print_fact_sources($mediaobject->getGedcomRecord(), 1); - - echo '</td></tr>'; - - return true; + } } diff --git a/includes/functions/functions_print_lists.php b/includes/functions/functions_print_lists.php index 191cbb196e..8a11ae2eca 100644 --- a/includes/functions/functions_print_lists.php +++ b/includes/functions/functions_print_lists.php @@ -85,9 +85,9 @@ function format_indi_table($datalist, $option='') { }); jQuery("div.filtersH_'.$table_id.'").html("'.addslashes( - '<button type="button" id="SEX_M_'. $table_id.'" class="ui-state-default SEX_M" title="'. WT_I18N::translate('Show only males.').'"> '.WT_Person::sexImage('M', 'small').' </button>'. - '<button type="button" id="SEX_F_'. $table_id.'" class="ui-state-default SEX_F" title="'. WT_I18N::translate('Show only females.').'"> '.WT_Person::sexImage('F', 'small').' </button>'. - '<button type="button" id="SEX_U_'. $table_id.'" class="ui-state-default SEX_U" title="'. WT_I18N::translate('Show only persons of whom the gender is not known.').'"> '.WT_Person::sexImage('U', 'small').' </button>'. + '<button type="button" id="SEX_M_'. $table_id.'" class="ui-state-default SEX_M" title="'. WT_I18N::translate('Show only males.').'"> '.WT_Individual::sexImage('M', 'small').' </button>'. + '<button type="button" id="SEX_F_'. $table_id.'" class="ui-state-default SEX_F" title="'. WT_I18N::translate('Show only females.').'"> '.WT_Individual::sexImage('F', 'small').' </button>'. + '<button type="button" id="SEX_U_'. $table_id.'" class="ui-state-default SEX_U" title="'. WT_I18N::translate('Show only persons of whom the gender is not known.').'"> '.WT_Individual::sexImage('U', 'small').' </button>'. '<button type="button" id="DEAT_N_'. $table_id.'" class="ui-state-default DEAT_N" title="'. WT_I18N::translate('Show people who are alive or couples where both partners are alive.').'">'.WT_I18N::translate('Alive').'</button>'. '<button type="button" id="DEAT_Y_'. $table_id.'" class="ui-state-default DEAT_Y" title="'. WT_I18N::translate('Show people who are dead or couples where both partners are deceased.').'">'.WT_I18N::translate('Dead').'</button>'. '<button type="button" id="DEAT_YES_'. $table_id.'" class="ui-state-default DEAT_YES" title="'. WT_I18N::translate('Show people who died more than 100 years ago.').'">'.WT_Gedcom_Tag::getLabel('DEAT').'>100</button>'. @@ -236,15 +236,15 @@ function format_indi_table($datalist, $option='') { if (is_object($value)) { // Array of objects $person=$value; } elseif (!is_array($value)) { // Array of IDs - $person = WT_Person::getInstance($value); + $person = WT_Individual::getInstance($value); } else { // Array of search results $gid = $key; if (isset($value['gid'])) $gid = $value['gid']; // from indilist if (isset($value[4])) $gid = $value[4]; // from indilist ALL - $person = WT_Person::getInstance($gid); + $person = WT_Individual::getInstance($gid); } if (is_null($person)) continue; - if (!$person->canDisplayName()) { + if (!$person->canShowName()) { continue; } //-- place filtering @@ -400,7 +400,7 @@ function format_indi_table($datalist, $option='') { $html .= '</td>'; //-- Filtering by birth date $html .= '<td>'; - if (!$person->canDisplayDetails() || WT_Date::Compare($birth_date, $d100y)>0) { + if (!$person->canShow() || WT_Date::Compare($birth_date, $d100y)>0) { $html .= 'Y100'; } else { $html .= 'YES'; @@ -659,10 +659,10 @@ function format_fam_table($datalist, $option='') { if (is_null($family)) continue; //-- Retrieve husband and wife $husb = $family->getHusband(); - if (is_null($husb)) $husb = new WT_Person(''); + if (is_null($husb)) $husb = new WT_Individual(''); $wife = $family->getWife(); - if (is_null($wife)) $wife = new WT_Person(''); - if (!$family->canDisplayDetails()) { + if (is_null($wife)) $wife = new WT_Individual(''); + if (!$family->canShow()) { continue; } //-- place filtering @@ -771,13 +771,13 @@ function format_fam_table($datalist, $option='') { if ($marriage_dates[0]->gregorianYear()>=1550 && $marriage_dates[0]->gregorianYear()<2030) { $marr_by_decade[(int)($marriage_dates[0]->gregorianYear()/10)*10] .= $husb->getSex().$wife->getSex(); } - } else if (get_sub_record(1, '1 _NMR', $family->getGedcomRecord())) { + } else if (get_sub_record(1, '1 _NMR', $family->getGedcom())) { $hus = $family->getHusband(); $wif = $family->getWife(); if (empty($wif) && !empty($hus)) $html .= WT_Gedcom_Tag::getLabel('_NMR', $hus); else if (empty($hus) && !empty($wif)) $html .= WT_Gedcom_Tag::getLabel('_NMR', $wif); else $html .= WT_Gedcom_Tag::getLabel('_NMR'); - } else if (get_sub_record(1, '1 _NMAR', $family->getGedcomRecord())) { + } else if (get_sub_record(1, '1 _NMAR', $family->getGedcom())) { $hus = $family->getHusband(); $wif = $family->getWife(); if (empty($wif) && !empty($hus)) $html .= WT_Gedcom_Tag::getLabel('_NMAR', $hus); @@ -840,7 +840,7 @@ function format_fam_table($datalist, $option='') { } //-- Sorting by marriage date $html .= '<td>'; - if (!$family->canDisplayDetails() || !$mdate->isOK()) { + if (!$family->canShow() || !$mdate->isOK()) { $html .= 'U'; } else { if (WT_Date::Compare($mdate, $d100y)>0) { @@ -976,7 +976,7 @@ function format_sour_table($datalist) { $source=WT_Source::getInstance($gid); } } - if (!$source || !$source->canDisplayDetails()) { + if (!$source || !$source->canShow()) { continue; } $html .= '<tr>'; @@ -1092,7 +1092,7 @@ function format_note_table($datalist) { //-- table body $html .= '<tbody>'; foreach ($datalist as $note) { - if (!$note->canDisplayDetails()) { + if (!$note->canShow()) { continue; } $html .= '<tr>'; @@ -1182,7 +1182,7 @@ function format_repo_table($repos) { $html .= '<tbody>'; $n=0; foreach ($repos as $repo) { - if (!$repo->canDisplayDetails()) { + if (!$repo->canShow()) { continue; } $html .= '<tr>'; @@ -1289,7 +1289,7 @@ function format_media_table($datalist) { if (is_null($media)) $media = WT_Media::getInstance($key); if (is_null($media)) continue; } - if ($media->canDisplayDetails()) { + if ($media->canShow()) { $name = $media->getFullName(); $html .= "<tr>"; //-- Object thumbnail @@ -1538,7 +1538,7 @@ function print_changes_list($change_ids, $sort) { $arr=array(); foreach ($change_ids as $change_id) { $record = WT_GedcomRecord::getInstance($change_id); - if (!$record || !$record->canDisplayDetails()) { + if (!$record || !$record->canShow()) { continue; } // setup sorting parameters @@ -1563,7 +1563,7 @@ function print_changes_list($change_ids, $sort) { foreach ($arr as $value) { $html .= '<a href="' . $value['record']->getHtmlUrl() . '" class="list_item name2">' . $value['record']->getFullName() . '</a>'; $html .= '<div class="indent" style="margin-bottom:5px">'; - if ($value['record'] instanceof WT_Person) { + if ($value['record'] instanceof WT_Individual) { if ($value['record']->getAddName()) { $html .= '<a href="' . $value['record']->getHtmlUrl() . '" class="list_item">' . $value['record']->getAddName() . '</a>'; } @@ -1632,7 +1632,7 @@ function print_changes_table($change_ids, $sort) { //-- table body foreach ($change_ids as $change_id) { $record = WT_GedcomRecord::getInstance($change_id); - if (!$record || !$record->canDisplayDetails()) { + if (!$record || !$record->canShow()) { continue; } $html .= '<tr><td>'; @@ -1666,7 +1666,7 @@ function print_changes_table($change_ids, $sort) { $name = $record->getFullName(); $html .= '<td class="wrap">'; $html .= '<a href="'. $record->getHtmlUrl() .'">'. $name . '</a>'; - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $addname = $record->getAddName(); if ($addname) { $html .= '<div class="indent"><a href="'. $record->getHtmlUrl() .'">'. $addname . '</a></div>'; @@ -1727,7 +1727,7 @@ function print_events_table($startjd, $endjd, $events='BIRT MARR DEAT', $only_li $record=$value['record']; //-- only living people ? if ($only_living) { - if ($record instanceof WT_Person && $record->isDead()) { + if ($record instanceof WT_Individual && $record->isDead()) { $filter ++; continue; } @@ -1746,7 +1746,7 @@ function print_events_table($startjd, $endjd, $events='BIRT MARR DEAT', $only_li } // Privacy - if (!$record->canDisplayDetails() || !canDisplayFact($record->getXref(), $record->getGedId(), $value['factrec'])) { + if (!$record->canShow() || !canDisplayFact($record->getXref(), $record->getGedcomId(), $value['factrec'])) { continue; } //-- Counter @@ -1768,7 +1768,7 @@ function print_events_table($startjd, $endjd, $events='BIRT MARR DEAT', $only_li $value['name'] = $record->getFullName(); $value['url'] = $record->getHtmlUrl(); - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $value['sex'] = $record->getSexImage(); } else { $value['sex'] = ''; @@ -1782,7 +1782,7 @@ function print_events_table($startjd, $endjd, $events='BIRT MARR DEAT', $only_li $name = $value['name']; $html .= '<td class="wrap">'; $html .= '<a href="'.$value['url'].'">'.$name.'</a>'; - if ($value['record'] instanceof WT_Person) { + if ($value['record'] instanceof WT_Individual) { $html .= $value['sex']; } $html .= '</td>'; @@ -1866,7 +1866,7 @@ function print_events_list($startjd, $endjd, $events='BIRT MARR DEAT', $only_liv $record = WT_GedcomRecord::getInstance($value['id']); //-- only living people ? if ($only_living) { - if ($record instanceof WT_Person && $record->isDead()) { + if ($record instanceof WT_Individual && $record->isDead()) { $filter ++; continue; } @@ -1885,14 +1885,14 @@ function print_events_list($startjd, $endjd, $events='BIRT MARR DEAT', $only_liv } // Privacy - if (!$record->canDisplayDetails() || !canDisplayFact($record->getXref(), $record->getGedId(), $value['factrec'])) { + if (!$record->canShow() || !canDisplayFact($record->getXref(), $record->getGedcomId(), $value['factrec'])) { continue; } $output ++; $value['name'] = $record->getFullName(); $value['url'] = $record->getHtmlUrl(); - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $value['sex'] = $record->getSexImage(); } else { $value['sex'] = ''; diff --git a/includes/functions/functions_rtl.php b/includes/functions/functions_rtl.php index 0d9f3f426c..18639e856c 100644 --- a/includes/functions/functions_rtl.php +++ b/includes/functions/functions_rtl.php @@ -1041,21 +1041,6 @@ function finishCurrentSpan(&$result, $theEnd=false) { return; } -/** - * convert HTML entities to to their original characters - * - * original found at http://www.php.net/manual/en/function.get-html-translation-table.php - * @see http://www.php.net/manual/en/function.get-html-translation-table.php - * @param string $string the string to remove the entities from - * @return string the string with entities converted - */ -function unhtmlentities($string) { - $trans_tbl=array_flip(get_html_translation_table (HTML_ENTITIES)); - $trans_tbl['‎']=WT_UTF8_LRM; - $trans_tbl['‏']=WT_UTF8_RLM; - return preg_replace('/&#(\d+);/e', "chr(\\1)", strtr($string, $trans_tbl)); -} - /* * Function to reverse RTL text for proper appearance on charts. * diff --git a/includes/media_reorder.php b/includes/media_reorder.php deleted file mode 100644 index 147b82364e..0000000000 --- a/includes/media_reorder.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -// Reorder media Items using drag and drop -// -// webtrees: Web based Family History software -// Copyright (C) 2013 webtrees development team. -// -// Derived from PhpGedView -// Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// $Id$ - -if (!defined('WT_WEBTREES')) { - header('HTTP/1.0 403 Forbidden'); - exit; -} - -require_once WT_ROOT.'includes/functions/functions_print_facts.php'; - -function media_reorder_row($rowm) { - $media = WT_Media::getInstance($rowm['m_id']); - - if (!$media->canDisplayDetails()) { - return false; - } - - echo "<li class=\"facts_value\" style=\"list-style:none;cursor:move;margin-bottom:2px;\" id=\"li_" . $media->getXref() . "\" >"; - echo "<table class=\"pic\"><tr>"; - echo "<td width=\"80\" valign=\"top\" align=\"center\" >"; - echo $media->displayImage(); - echo "</td><td>"; - echo $media->getFullName(); - echo "</td>"; - echo "</tr>"; - echo "</table>"; - echo "<input type=\"hidden\" name=\"order1[",$media->getXref(), "]\" value=\"0\">"; - echo "</li>"; - return true; -} - -$controller->addInlineJavascript(' - jQuery("#reorder_media_list").sortable({forceHelperSize: true, forcePlaceholderSize: true, opacity: 0.7, cursor: "move", axis: "y"}); - - //-- update the order numbers after drag-n-drop sorting is complete - jQuery("#reorder_media_list").bind("sortupdate", function(event, ui) { - jQuery("#"+jQuery(this).attr("id")+" input").each( - function (index, value) { - value.value = index+1; - } - ); - }); - '); - -echo '<br><b>', WT_I18N::translate('Re-order media'), '</b>'; -echo '  --- ' . WT_I18N::translate('Click a row, then drag-and-drop to re-order media '); - -?> -<form name="reorder_form" method="post" action="edit_interface.php"> - <input type="hidden" name="action" value="reorder_media_update"> - <input type="hidden" name="pid" value="<?php echo $pid; ?>"> - - <ul id="reorder_media_list"> - <?php - $person = WT_Person::getInstance($pid); - - //-- find all of the related ids - $ids = array($person->getXref()); - foreach ($person->getSpouseFamilies() as $family) { - $ids[] = $family->getXref(); - } - - //-- If they exist, get a list of the sorted current objects in the indi gedcom record - (1 _WT_OBJE_SORT @xxx@ .... etc) ---------- - $sort_current_objes = array(); - $sort_ct = preg_match_all('/\n1 _WT_OBJE_SORT @(.*)@/', $person->getGedcomRecord(), $sort_match, PREG_SET_ORDER); - for ($i=0; $i<$sort_ct; $i++) { - if (!isset($sort_current_objes[$sort_match[$i][1]])) { - $sort_current_objes[$sort_match[$i][1]] = 1; - } else { - $sort_current_objes[$sort_match[$i][1]]++; - } - $sort_obje_links[$sort_match[$i][1]][] = $sort_match[$i][0]; - } - - // create ORDER BY list from Gedcom sorted records list --------------------------- - $orderbylist = 'ORDER BY '; // initialize - foreach ($sort_match as $id) { - $orderbylist .= "m_id='$id[1]' DESC, "; - } - $orderbylist = rtrim($orderbylist, ', '); - - //-- get a list of the current objects in the record - $current_objes = array(); - $regexp = '/\n\d OBJE @(.*)@/'; - $ct = preg_match_all($regexp, $person->getGedcomRecord(), $match, PREG_SET_ORDER); - for ($i=0; $i<$ct; $i++) { - if (!isset($current_objes[$match[$i][1]])) { - $current_objes[$match[$i][1]] = 1; - } else { - $current_objes[$match[$i][1]]++; - } - $obje_links[$match[$i][1]][] = $match[$i][0]; - } - - $media_found = false; - - // Get the related media items - $sqlmm = - "SELECT DISTINCT m_id, m_ext, m_filename, m_titl, m_file, m_gedcom" . - " FROM `##media`" . - " JOIN `##link` ON (m_id=l_to AND m_file=l_file AND l_type='OBJE')" . - " WHERE m_file=? AND l_from IN ("; - $i=0; - $vars=array(WT_GED_ID); - foreach ($ids as $media_id) { - if ($i>0) $sqlmm .= ","; - $sqlmm .= "?"; - $vars[]=$media_id; - $i++; - } - $sqlmm .= ')'; - - if ($sort_ct>0) { - $sqlmm .= $orderbylist; - } - - $rows=WT_DB::prepare($sqlmm)->execute($vars)->fetchAll(PDO::FETCH_ASSOC); - - $foundObjs = array(); - foreach ($rows as $rowm) { - if (isset($foundObjs[$rowm['m_id']])) { - if (isset($current_objes[$rowm['m_id']])) { - $current_objes[$rowm['m_id']]--; - } - continue; - } - $rows = array(); - $rows['normal'] = $rowm; - if (isset($current_objes[$rowm['m_id']])) $current_objes[$rowm['m_id']]--; - foreach ($rows as $rowm) { - $res = media_reorder_row($rowm); - $media_found = $media_found || $res; - $foundObjs[$rowm['m_id']] = true; - } - } - ?> - </ul> - <?php - if (WT_USER_IS_ADMIN) { - echo '<table width=97%><tr><td class="descriptionbox wrap width25">'; - echo WT_Gedcom_Tag::getLabel('CHAN'), '</td><td class="optionbox wrap">'; - if ($NO_UPDATE_CHAN) { - echo '<input type="checkbox" checked="checked" name="preserve_last_changed">'; - } else { - echo '<input type="checkbox" name="preserve_last_changed">'; - } - echo WT_I18N::translate('Do not update the “last change” record'), help_link('no_update_CHAN'), '<br>'; - $event = $person->getChangeEvent(); - if ($event) { - echo format_fact_date($event, $person, false, true); - } - echo '</td></tr></table>'; - } - ?> - <p id="save-cancel"> - <input type="submit" class="save" value="<?php echo WT_I18N::translate('save'); ?>"> - <input type="button" class="cancel" value="<?php echo WT_I18N::translate('close'); ?>" onclick="window.close();"> - </p> -</form> diff --git a/includes/old_messages.php b/includes/old_messages.php index 7534671a4b..3d0794a9de 100644 --- a/includes/old_messages.php +++ b/includes/old_messages.php @@ -31,4 +31,12 @@ exit; -// /* I18N: This message is deleted in webtrees-1.x.x */ WT_I18N::translate(''); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('An error occurred while creating the Edit form. Another user may have changed this record since you previously viewed it.'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('Execution time: %1$s seconds. Database queries: %2$s. Privacy checks: %3$s. Memory usage: %4$s KB.'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('Link this person to an existing family as a husband'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('Link this person to an existing family as a wife'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('Please reload the previous page to make sure you are working with the most recent record.'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('The record with id %s was changed by another user since you last accessed it.'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('This record was last changed by <i>%s</i> at %s'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('UK census images have been obtained from The National Archives, the custodian of the original records, and appear here with their approval on the condition that no commercial use is made of them without permission. Requests for commercial publication of these or other UK census images appearing on this website should be directed to: Image Library, The National Archives, Kew, Surrey, TW9 4DU, United Kingdom.'); +/* I18N: This message is deleted in webtrees-1.5.0 */ WT_I18N::translate('View GEDCOM Record'); diff --git a/includes/session.php b/includes/session.php index fba8f32a24..2f491bca17 100644 --- a/includes/session.php +++ b/includes/session.php @@ -59,7 +59,7 @@ define('WT_JQUERY_DATATABLES_URL', WT_STATIC_URL.'js/jquery.datatables-1.9.4.js' define('WT_JQUERY_JEDITABLE_URL', WT_STATIC_URL.'js/jquery.jeditable-1.7.1.js'); define('WT_JQUERY_WHEELZOOM_URL', WT_STATIC_URL.'js/jquery.wheelzoom-1.1.2.js'); define('WT_MODERNIZR_URL', WT_STATIC_URL.'js/modernizr.custom-2.6.2.js'); -define('WT_WEBTREES_JS_URL', WT_STATIC_URL.'js/webtrees-1.4.2.js'); +define('WT_WEBTREES_JS_URL', WT_STATIC_URL.'js/webtrees-1.5.0.js'); // Location of our modules and themes. These are used as URLs and folder paths. define('WT_MODULES_DIR', 'modules_v3/'); // Update setup.php and build/Makefile when this changes @@ -130,7 +130,6 @@ define ('WT_ROOT', realpath(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR); // Keep track of time statistics, for the summary in the footer $start_time=microtime(true); -$PRIVACY_CHECKS=0; // We want to know about all PHP errors error_reporting(E_ALL | E_STRICT); diff --git a/individual.php b/individual.php index 200e4662be..08340bec54 100644 --- a/individual.php +++ b/individual.php @@ -34,7 +34,7 @@ $controller ->addExternalJavascript(WT_JQUERY_COOKIE_URL) // We use this to record the sidebar state ->addInlineJavascript('var catch_and_ignore; function paste_id(value) {catch_and_ignore = value;}'); // For the "find" links -if ($controller->record && $controller->record->canDisplayDetails()) { +if ($controller->record && $controller->record->canShow()) { if (safe_GET('action')=='ajax') { $controller->ajaxRequest(); exit; @@ -44,7 +44,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { $sidebar_html=$controller->getSideBarContent(); $controller->pageHeader(); - if ($controller->record->isMarkedDeleted()) { + if ($controller->record->isOld()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -62,7 +62,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { ' ', help_link('pending_changes'), '</p>'; } - } elseif (find_updated_record($controller->record->getXref(), WT_GED_ID)!==null) { + } elseif ($controller->record->isNew()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -81,7 +81,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { '</p>'; } } -} elseif ($controller->record && $controller->record->canDisplayName()) { +} elseif ($controller->record && $controller->record->canShowName()) { // Just show the name. $controller->pageHeader(); echo '<h2>', $controller->record->getFullName(), '</h2>'; @@ -174,10 +174,9 @@ echo '<div id="main" class="use-sidebar sidebar-at-right" style="visibility:hidden;">', //overall page container '<div id="indi_left">', '<div id="indi_header">'; -if ($controller->record->canDisplayDetails()) { +if ($controller->record->canShow()) { // Highlight image or silhouette echo '<div id="indi_mainimage">', $controller->record->displayImage(), '</div>'; - $globalfacts=$controller->getGlobalFacts(); echo '<div id="header_accordion1">'; // contain accordions for names echo '<h3 class="name_one ', $controller->getPersonStyle($controller->record), '"><span>', $controller->record->getFullName(), '</span>'; // First name accordion header $bdate=$controller->record->getBirthDate(); @@ -193,17 +192,22 @@ if ($controller->record->canDisplayDetails()) { echo '</span>'; // Display summary birth/death info. echo '<span id="dates">', $controller->record->getLifeSpan(), '</span>'; - //Display gender icon - foreach ($globalfacts as $key=>$value) { - $fact = $value->getTag(); - if ($fact=="SEX") $controller->print_sex_record($value); + + // Display gender icon + foreach ($controller->record->getFacts() as $fact) { + if ($fact->getTag() == 'SEX') { + $controller->print_sex_record($fact); + } } echo '</h3>'; // close first name accordion header - //Display name details - foreach ($globalfacts as $key=>$value) { - $fact = $value->getTag(); - if ($fact=="NAME") $controller->print_name_record($value); + + // Display name details + foreach ($controller->record->getFacts() as $fact) { + if ($fact->getTag() == 'NAME' && $fact->canShow()) { + $controller->print_name_record($fact); + } } + echo '</div>'; // close header_accordion1 } echo '</div>';// close #indi_header diff --git a/inverselink.php b/inverselink.php index 0bc9f637f7..cc5ede6415 100644 --- a/inverselink.php +++ b/inverselink.php @@ -49,7 +49,7 @@ if ($linkto=='manage' && array_key_exists('GEDFact_assistant', WT_Module::getAct //-- check for admin $paramok = true; - if (!empty($linktoid)) $paramok = WT_GedcomRecord::getInstance($linktoid)->canDisplayDetails(); + if (!empty($linktoid)) $paramok = WT_GedcomRecord::getInstance($linktoid)->canShow(); if ($action == "choose" && $paramok) { ?> @@ -113,7 +113,7 @@ if ($linkto=='manage' && array_key_exists('GEDFact_assistant', WT_Module::getAct echo '<input class="pedigree_form" type="text" name="linktoid" id="linktopid" size="3" value="', $linktoid, '"> '; echo print_findindi_link('linktopid'); } else { - $record=WT_Person::getInstance($linktoid); + $record=WT_Individual::getInstance($linktoid); echo $record->format_list('span', false, $record->getFullName()); } } diff --git a/js/webtrees-1.4.2.js b/js/webtrees-1.5.0.js index 2b4f3cde83..c9feaa3215 100644 --- a/js/webtrees-1.4.2.js +++ b/js/webtrees-1.5.0.js @@ -306,79 +306,69 @@ function getMouseXY(e) { return true; } -/** - * @param params - * Object containing URL parameters. - * @param {optional} windowspecs - * Window features to use. Defaults to edit_window_specs. - * @param {optional} pastefield - * Field to paste a result into. - */ +// Open the "edit interface" popup window function edit_interface(params, windowspecs, pastefield) { var features = windowspecs || edit_window_specs; - var url = 'edit_interface.php?' + jQuery.param(params) + '&accesstime=' + accesstime + '&ged=' + WT_GEDCOM; + var url = 'edit_interface.php?' + jQuery.param(params) + '&ged=' + WT_GEDCOM; window.open(url, '_blank', features); } -function edit_record(pid, linenum) { +function edit_record(xref, fact_id) { edit_interface({ - "action": "edit", - "pid": pid, - "linenum": linenum + "action": "edit", + "xref": xref, + "fact_id": fact_id }); return false; } -function edit_raw(pid) { +function edit_raw(xref) { edit_interface({ "action": "editraw", - "pid": pid + "xref": xref }); return false; } -function edit_note(pid) { +function edit_note(xref) { edit_interface({ "action": "editnote", - "pid": pid, - "linenum": 1 + "xref": xref }); return false; } -function edit_source(pid) { +function edit_source(xref) { edit_interface({ "action": "editsource", - "pid": pid, - "linenum": 1 + "xref": xref, }); return false; } -function add_record(pid, fact) { - var factfield = document.getElementById(fact); - if (factfield) { - var factvalue = factfield.options[factfield.selectedIndex].value; - if (factvalue == "OBJE") { - window.open('addmedia.php?action=showmediaform&linkid='+pid+'&ged='+WT_GEDCOM, '_blank', edit_window_specs); +function add_record(xref, fact_field) { + var fact = jQuery('#' + fact_field).val(); + if (fact) { + if (fact == "OBJE") { + window.open('addmedia.php?action=showmediaform&linkid=' + xref + '&ged=' + WT_GEDCOM, '_blank', edit_window_specs); } else { edit_interface({ "action": "add", - "pid": pid, - "fact": factvalue + "xref": xref, + "fact": fact }); } } return false; } -function addClipboardRecord(pid, fact) { +function addClipboardRecord(xref, fact) { var factfield = document.getElementById(fact); if (factfield) { var factvalue = factfield.options[factfield.selectedIndex].value; edit_interface({ "action": "paste", - "pid": pid, + "xref": xref, "fact": factvalue.substr(10) }); } @@ -388,16 +378,16 @@ function addClipboardRecord(pid, fact) { function reorder_media(xref) { edit_interface({ "action": "reorder_media", - "pid": xref + "xref": xref }, mord_window_specs); return false; } -function add_new_record(pid, fact) { +function add_new_record(xref, fact) { edit_interface({ "action": "add", - "pid": pid, - "fact": fact + "xref": xref, + "fact": fact }); return false; } @@ -420,114 +410,121 @@ function addnewspouse(famid, famtag) { return false; } -function addopfchild(pid, gender) { +function addopfchild(xref, gender) { edit_interface({ "action": "addopfchild", - "pid": pid, + "xref": xref, "gender": gender }); return false; } -function addspouse(pid, famtag) { +function addspouse(xref, famtag) { edit_interface({ "action": "addspouse", - "pid": pid, + "xref": xref, "famtag": famtag, "famid": "new" }); return false; } -function linkspouse(pid, famtag) { +function linkspouse(xref, famtag) { edit_interface({ "action": "linkspouse", - "pid": pid, + "xref": xref, "famtag": famtag, "famid": "new" }); return false; } -function add_famc(pid) { - edit_interface({ - "action": "addfamlink", - "pid": pid, - "famtag": "CHIL" - }); - return false; -} - -function add_fams(pid, famtag) { +function add_famc(xref) { edit_interface({ "action": "addfamlink", - "pid": pid, - "famtag": famtag + "xref": xref, }); return false; } -function edit_name(pid, linenum) { +function edit_name(xref, fact_id) { edit_interface({ "action": "editname", - "pid": pid, - "linenum": linenum + "xref": xref, + "fact_id": fact_id }); return false; } -function add_name(pid) { +function add_name(xref) { edit_interface({ "action": "addname", - "pid": pid + "xref": xref }); return false; } -function addnewparent(pid, famtag) { +function addnewparent(xref, famtag) { edit_interface({ "action": "addnewparent", - "pid": pid, - "famtag": famtag, - "famid": "new" + "xref": xref, + "famtag": famtag }); return false; } -function addnewparentfamily(pid, famtag, famid) { +function addnewparentfamily(xref, famtag, famid) { edit_interface({ "action": "addnewparent", - "pid": pid, + "xref": xref, "famtag": famtag, - "famid": famid + "famid": famid }); return false; } -function delete_fact(pid, linenum, mediaid, message) { +// Delete a fact - and reload the page +function delete_fact(message, xref, fact_id) { if (confirm(message)) { - edit_interface({ - "action": "delete", - "pid": pid, - "linenum": linenum, - "mediaid": mediaid - }); + jQuery.post('action.php', { + action: 'delete-fact', + xref: xref, + fact_id: fact_id, + ged: WT_GEDCOM + }, + function(){ + location.reload(); + }); } return false; } -function reorder_children(famid) { +// Copy a fact to the clipboard +function copy_fact(xref, fact_id) { + jQuery.post('action.php', { + action: 'copy-fact', + xref: xref, + fact_id: fact_id, + ged: WT_GEDCOM + }, + function(){ + location.reload(); + }); + return false; +} + +function reorder_children(xref) { edit_interface({ "action": "reorder_children", - "pid": famid + "xref": xref }); return false; } -function reorder_families(pid) { +function reorder_families(xref) { edit_interface({ "action": "reorder_fams", - "pid": pid + "xref": xref }); return false; } @@ -542,10 +539,10 @@ function delete_message(id) { return false; } -function change_family_members(famid) { +function change_family_members(xref) { edit_interface({ "action": "changefamily", - "famid": famid + "xref": xref }); return false; } @@ -554,7 +551,7 @@ function addnewsource(field) { pastefield=field; edit_interface({ "action": "addnewsource", - "pid": "newsour" + "xref": "newsour" }, null, field); return false; } @@ -563,7 +560,7 @@ function addnewrepository(field) { pastefield=field; edit_interface({ "action": "addnewrepository", - "pid": "newrepo" + "xref": "newrepo" }, null, field); return false; } @@ -577,12 +574,12 @@ function addnewnote(field) { return false; } -function addnewnote_assisted(field, iid) { +function addnewnote_assisted(field, xref) { pastefield=field; edit_interface({ "action": "addnewnote_assisted", "noteid": "newnote", - "pid": iid + "xref": xref }, assist_window_specs, field); return false; } @@ -1400,7 +1397,7 @@ function activate_colorbox(config) { next: textDirection=='ltr' ? '▶' : '◀', slideshowStart: '○', slideshowStop: '●', - close: '×', + close: '×' }); if (config) { jQuery.extend(jQuery.colorbox.settings, config); diff --git a/library/WT/Controller/AdvancedSearch.php b/library/WT/Controller/AdvancedSearch.php index cba844cd74..586db82939 100644 --- a/library/WT/Controller/AdvancedSearch.php +++ b/library/WT/Controller/AdvancedSearch.php @@ -2,7 +2,7 @@ // Controller for the advanced search page // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -202,7 +202,7 @@ class WT_Controller_AdvancedSearch extends WT_Controller_Search { } // Dynamic SQL query, plus bind variables - $sql="SELECT DISTINCT 'INDI' AS type, ind.i_id AS xref, ind.i_file AS ged_id, ind.i_gedcom AS gedrec FROM `##individuals` ind"; + $sql="SELECT DISTINCT ind.i_id AS xref, ind.i_file AS gedcom_id, ind.i_gedcom AS gedcom FROM `##individuals` ind"; $bind=array(); // Join the following tables @@ -486,13 +486,13 @@ class WT_Controller_AdvancedSearch extends WT_Controller_Search { $bind[]=$value; } } - $rows=WT_DB::prepare($sql)->execute($bind)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->execute($bind)->fetchAll(); foreach ($rows as $row) { - $person=WT_Person::getInstance($row); + $person=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // Check for XXXX:PLAC fields, which were only partially matched by SQL foreach ($this->fields as $n=>$field) { if ($this->values[$n] && preg_match('/^('.WT_REGEX_TAG.'):PLAC$/', $field, $match)) { - if (!preg_match('/\n1 '.$match[1].'(\n[2-9].*)*\n2 PLAC .*'.preg_quote($this->values[$n], '/').'/i', $person->getGedcomRecord())) { + if (!preg_match('/\n1 '.$match[1].'(\n[2-9].*)*\n2 PLAC .*'.preg_quote($this->values[$n], '/').'/i', $person->getGedcom())) { continue 2; } } diff --git a/library/WT/Controller/Ancestry.php b/library/WT/Controller/Ancestry.php index 6228418cdc..23bafdd5b5 100644 --- a/library/WT/Controller/Ancestry.php +++ b/library/WT/Controller/Ancestry.php @@ -2,7 +2,7 @@ // Controller for the ancestry chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -74,7 +74,7 @@ class WT_Controller_Ancestry extends WT_Controller_Chart { $pbwidth = $bwidth+12; $pbheight = $bheight+14; - if ($this->root && $this->root->canDisplayName()) { + if ($this->root && $this->root->canShowName()) { $this->setPageTitle( /* I18N: %s is an individual’s name */ WT_I18N::translate('Ancestors of %s', $this->root->getFullName()) diff --git a/library/WT/Controller/Chart.php b/library/WT/Controller/Chart.php index 6e54c135d7..ce9f1d9726 100644 --- a/library/WT/Controller/Chart.php +++ b/library/WT/Controller/Chart.php @@ -35,14 +35,14 @@ class WT_Controller_Chart extends WT_Controller_Page { $this->rootid = safe_GET_xref('rootid'); if ($this->rootid) { - $this->root = WT_Person::getInstance($this->rootid); + $this->root = WT_Individual::getInstance($this->rootid); } else { // Missing rootid parameter? Do something. $this->root = $this->getSignificantIndividual(); $this->rootid = $this->root->getXref(); } - if (!$this->root || !$this->root->canDisplayName()) { + if (!$this->root || !$this->root->canShowName()) { header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden'); $this->error_message=WT_I18N::translate('This individual does not exist or you do not have permission to view it.'); $this->rootid=null; diff --git a/library/WT/Controller/Compact.php b/library/WT/Controller/Compact.php index d8b051e248..5bda1695b1 100644 --- a/library/WT/Controller/Compact.php +++ b/library/WT/Controller/Compact.php @@ -2,7 +2,7 @@ // Controller for the compact chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -41,7 +41,7 @@ class WT_Controller_Compact extends WT_Controller_Chart { // Extract the request parameters $this->show_thumbs=safe_GET_bool('show_thumbs'); - if ($this->root && $this->root->canDisplayName()) { + if ($this->root && $this->root->canShowName()) { $this->setPageTitle( /* I18N: %s is an individual’s name */ WT_I18N::translate('Compact tree of %s', $this->root->getFullName()) @@ -55,9 +55,9 @@ class WT_Controller_Compact extends WT_Controller_Chart { function sosa_person($n) { global $SHOW_HIGHLIGHT_IMAGES; - $indi=WT_Person::getInstance($this->treeid[$n]); + $indi=WT_Individual::getInstance($this->treeid[$n]); - if ($indi && $indi->canDisplayName()) { + if ($indi && $indi->canShowName()) { $name=$indi->getFullName(); $addname=$indi->getAddName(); @@ -72,7 +72,7 @@ class WT_Controller_Compact extends WT_Controller_Chart { if ($addname) $html .= '<br>' . $addname; $html .= '</a>'; $html .= '<br>'; - if ($indi->canDisplayDetails()) { + if ($indi->canShow()) { $html.='<div class="details1">'.$indi->getLifeSpan().'</div>'; } } else { @@ -115,7 +115,7 @@ class WT_Controller_Compact extends WT_Controller_Chart { } if ($pid) { - $indi=WT_Person::getInstance($pid); + $indi=WT_Individual::getInstance($pid); $title=WT_I18N::translate('Compact tree of %s', $indi->getFullName()); $text = '<a class="icon-'.$arrow_dir.'arrow" title="'.strip_tags($title).'" href="?rootid='.$pid; if ($this->show_thumbs) $text .= "&show_thumbs=".$this->show_thumbs; diff --git a/library/WT/Controller/Descendancy.php b/library/WT/Controller/Descendancy.php index f9d07c6977..9ee2c3d733 100644 --- a/library/WT/Controller/Descendancy.php +++ b/library/WT/Controller/Descendancy.php @@ -2,7 +2,7 @@ // Controller for the descendancy chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -92,7 +92,7 @@ class WT_Controller_Descendancy extends WT_Controller_Chart { $this->cellwidth=(strlen($this->name)*14); } - if ($this->root && $this->root->canDisplayName()) { + if ($this->root && $this->root->canShowName()) { $this->setPageTitle( /* I18N: %s is an individual’s name */ WT_I18N::translate('Descendants of %s', $this->root->getFullName()) @@ -199,7 +199,7 @@ class WT_Controller_Descendancy extends WT_Controller_Chart { $spouse=$family->getSpouse($person); if (!$spouse) { // One parent families have no spouse - $spouse=new WT_Person(''); + $spouse=new WT_Individual(''); } // print marriage info @@ -244,7 +244,7 @@ class WT_Controller_Descendancy extends WT_Controller_Chart { } else { // Distinguish between no children (NCHI 0) and no recorded // children (no CHIL records) - if (strpos($family->getGedcomRecord(), '\n1 NCHI 0')) { + if (strpos($family->getGedcom(), '\n1 NCHI 0')) { echo WT_Gedcom_Tag::getLabel('NCHI').': '.count($children); } else { echo WT_I18N::translate('No children'); diff --git a/library/WT/Controller/Family.php b/library/WT/Controller/Family.php index 68151a0d35..686627562b 100644 --- a/library/WT/Controller/Family.php +++ b/library/WT/Controller/Family.php @@ -2,7 +2,7 @@ // Controller for the family page // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -32,46 +32,14 @@ require_once WT_ROOT.'includes/functions/functions_print_facts.php'; require_once WT_ROOT.'includes/functions/functions_import.php'; class WT_Controller_Family extends WT_Controller_GedcomRecord { - var $diff_record; - var $record = null; - var $user = null; - var $display = false; - var $famrec = ''; - var $title = ''; - public function __construct() { global $Dbwidth, $bwidth, $pbwidth, $pbheight, $bheight; - $bwidth = $Dbwidth; - $pbwidth = $bwidth + 12; + $bwidth = $Dbwidth; + $pbwidth = $bwidth + 12; $pbheight = $bheight + 14; - $xref = safe_GET_xref('famid'); - - $gedrec = find_family_record($xref, WT_GED_ID); - - if (empty($gedrec)) { - $gedrec = "0 @".$xref."@ FAM\n"; - } - - if (find_family_record($xref, WT_GED_ID) || find_updated_record($xref, WT_GED_ID)!==null) { - $this->record = new WT_Family($gedrec); - $this->record->ged_id=WT_GED_ID; // This record is from a file - } else if (!$this->record) { - parent::__construct(); - return; - } - - $xref=$this->record->getXref(); // Correct upper/lower case mismatch - - //-- if the user can edit and there are changes then get the new changes - if (WT_USER_CAN_EDIT) { - $newrec = find_updated_record($xref, WT_GED_ID); - if (!empty($newrec)) { - $this->diff_record = new WT_Family($newrec); - $this->diff_record->setChanged(true); - $this->record->diffMerge($this->diff_record); - } - } + $xref = safe_GET_xref('famid'); + $this->record = WT_Family::getInstance($xref); parent::__construct(); } @@ -98,7 +66,7 @@ class WT_Controller_Family extends WT_Controller_GedcomRecord { // $tags is an array of HUSB/WIFE/CHIL function getTimelineIndis($tags) { - preg_match_all('/\n1 (?:'.implode('|', $tags).') @('.WT_REGEX_XREF.')@/', $this->record->getGedcomRecord(), $matches); + preg_match_all('/\n1 (?:'.implode('|', $tags).') @('.WT_REGEX_XREF.')@/', $this->record->getGedcom(), $matches); foreach ($matches[1] as &$match) { $match='pids[]='.$match; } @@ -111,7 +79,7 @@ class WT_Controller_Family extends WT_Controller_GedcomRecord { function getEditMenu() { $SHOW_GEDCOM_RECORD=get_gedcom_setting(WT_GED_ID, 'SHOW_GEDCOM_RECORD'); - if (!$this->record || $this->record->isMarkedDeleted()) { + if (!$this->record || $this->record->isOld()) { return null; } @@ -138,21 +106,6 @@ class WT_Controller_Family extends WT_Controller_GedcomRecord { } } - // edit/view raw gedcom - if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('Edit raw GEDCOM record'), '#', 'menu-fam-editraw'); - $submenu->addOnclick("return edit_raw('".$this->record->getXref()."');"); - $menu->addSubmenu($submenu); - } elseif ($SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('View GEDCOM Record'), '#', 'menu-fam-viewraw'); - if (WT_USER_CAN_EDIT) { - $submenu->addOnclick("return show_gedcom_record('new');"); - } else { - $submenu->addOnclick("return show_gedcom_record();"); - } - $menu->addSubmenu($submenu); - } - // delete if (WT_USER_CAN_EDIT) { $submenu = new WT_Menu(WT_I18N::translate('Delete'), '#', 'menu-fam-del'); @@ -202,7 +155,6 @@ class WT_Controller_Family extends WT_Controller_GedcomRecord { foreach ($indifacts as $fact) { print_fact($fact, $this->record); } - print_main_media($this->record->getXref()); } else { echo '<tr><td class="messagebox" colspan="2">', WT_I18N::translate('No facts for this family.'), '</td></tr>'; } diff --git a/library/WT/Controller/Familybook.php b/library/WT/Controller/Familybook.php index e75a46b6a6..c509a10af4 100644 --- a/library/WT/Controller/Familybook.php +++ b/library/WT/Controller/Familybook.php @@ -2,7 +2,7 @@ // Controller for the familybook chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -64,7 +64,7 @@ class WT_Controller_Familybook extends WT_Controller_Chart { // Validate parameters if (!empty($rootid)) $this->pid = $rootid; $rootid=$this->rootid; - $this->hourPerson = WT_Person::getInstance($this->pid); + $this->hourPerson = WT_Individual::getInstance($this->pid); if (!$this->hourPerson) { $this->hourPerson=$this->getSignificantIndividual(); $this->pid=$this->hourPerson->getXref(); @@ -75,7 +75,7 @@ class WT_Controller_Familybook extends WT_Controller_Chart { $bheight = $cbheight; } $bhalfheight = $bheight / 2; - if ($this->root && $this->root->canDisplayName()) { + if ($this->root && $this->root->canShowName()) { $this->setPageTitle( /* I18N: %s is an individual’s name */ WT_I18N::translate('Family book of %s', $this->root->getFullName()) @@ -334,7 +334,7 @@ class WT_Controller_Familybook extends WT_Controller_Chart { */ function max_descendency_generations($pid, $depth) { if ($depth > $this->generations) return $depth; - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); if (is_null($person)) return $depth; $maxdc = $depth; foreach ($person->getSpouseFamilies() as $family) { @@ -360,7 +360,7 @@ class WT_Controller_Familybook extends WT_Controller_Chart { } function print_family_book($person, $descent) { global $firstrun; - if ($descent==0 || !$person->canDisplayName()) { + if ($descent==0 || !$person->canShowName()) { return; } $families=$person->getSpouseFamilies(); diff --git a/library/WT/Controller/Fanchart.php b/library/WT/Controller/Fanchart.php index 2b86dab1d6..ea6edf7c12 100644 --- a/library/WT/Controller/Fanchart.php +++ b/library/WT/Controller/Fanchart.php @@ -2,7 +2,7 @@ // Controller for the fan chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -46,7 +46,7 @@ class WT_Controller_Fanchart extends WT_Controller_Chart { $this->fan_width =safe_GET_integer('fan_width', 50, 300, 100); $this->generations=safe_GET_integer('generations', 2, 9, $default_generations); - if ($this->root && $this->root->canDisplayName()) { + if ($this->root && $this->root->canShowName()) { $this->setPageTitle( /* I18N: http://en.wikipedia.org/wiki/Family_tree#Fan_chart - %s is an individual’s name */ WT_I18N::translate('Fan chart of %s', $this->root->getFullName()) @@ -211,7 +211,7 @@ class WT_Controller_Fanchart extends WT_Controller_Chart { while ($sosa >= $p2) { $pid=$treeid[$sosa]; if ($pid) { - $person =WT_Person::getInstance($pid); + $person =WT_Individual::getInstance($pid); $name =$person->getFullName(); $addname=$person->getAddName(); @@ -234,8 +234,8 @@ class WT_Controller_Fanchart extends WT_Controller_Chart { $text .= $person->getLifeSpan(); - $text = unhtmlentities($text); $text = strip_tags($text); + $text = htmlspecialchars_decode($text); // split and center text by lines $wmax = (int)($angle*7/$fanChart['size']*$scale); diff --git a/library/WT/Controller/GedcomRecord.php b/library/WT/Controller/GedcomRecord.php index 18c64bd9fa..233c7fbaac 100644 --- a/library/WT/Controller/GedcomRecord.php +++ b/library/WT/Controller/GedcomRecord.php @@ -29,6 +29,22 @@ class WT_Controller_GedcomRecord extends WT_Controller_Page { public $record; // individual, source, repository, etc. public function __construct() { + // Automatically fix broken links + if ($this->record && $this->record->canEdit()) { + $broken_links=0; + foreach ($this->record->getFacts('HUSB|WIFE|CHIL|FAMS|FAMC|SOUR|REPO|OBJE') as $fact) { // Not NOTE! + if (!$fact->isOld() && $fact->getTarget() === null) { + $this->record->updateFact($fact->getFactId(), null, false); + WT_FlashMessages::addMessage(/* I18N: %s are names of records, such as sources, repositories or individuals */ WT_I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $this->record->getFullName(), $fact->getValue())); + $broken_links = true; + } + } + if ($broken_links) { + // Reload the updated family + $this->record = WT_GedcomRecord::getInstance($this->record->getXref()); + } + } + parent::__construct(); // We want robots to index this page @@ -37,7 +53,7 @@ class WT_Controller_GedcomRecord extends WT_Controller_Page { // Set a page title if ($this->record) { $this->setCanonicalUrl($this->record->getHtmlUrl()); - if ($this->record->canDisplayName()) { + if ($this->record->canShowName()) { // e.g. "John Doe" or "1881 Census of Wales" $this->setPageTitle($this->record->getFullName()); } else { diff --git a/library/WT/Controller/Hourglass.php b/library/WT/Controller/Hourglass.php index 7dee4869e3..01285b296b 100644 --- a/library/WT/Controller/Hourglass.php +++ b/library/WT/Controller/Hourglass.php @@ -2,7 +2,7 @@ // Controller for the hourglass chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -90,7 +90,7 @@ class WT_Controller_Hourglass extends WT_Controller_Chart { $bhalfheight = (int)($bheight / 2); // Validate parameters - $this->hourPerson = WT_Person::getInstance($this->pid); + $this->hourPerson = WT_Individual::getInstance($this->pid); if (!$this->hourPerson) { $this->hourPerson=$this->getSignificantIndividual(); $this->pid=$this->hourPerson->getXref(); @@ -347,7 +347,7 @@ class WT_Controller_Hourglass extends WT_Controller_Chart { // For the root person, print a down arrow that allows changing the root of tree if ($showNav && $count==1) { // NOTE: If statement OK - if ($person->canDisplayName()) { + if ($person->canShowName()) { // -- print left arrow for decendants so that we can move down the tree $famids = $person->getSpouseFamilies(); //-- make sure there is more than 1 child in the family with parents @@ -435,7 +435,7 @@ class WT_Controller_Hourglass extends WT_Controller_Chart { */ function max_descendency_generations($pid, $depth) { if ($depth > $this->generations) return $depth; - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); if (is_null($person)) return $depth; $maxdc = $depth; foreach ($person->getSpouseFamilies() as $family) { diff --git a/library/WT/Controller/Individual.php b/library/WT/Controller/Individual.php index 26cf33b4ec..c09304fa32 100644 --- a/library/WT/Controller/Individual.php +++ b/library/WT/Controller/Individual.php @@ -32,58 +32,29 @@ require_once WT_ROOT.'includes/functions/functions_print_facts.php'; require_once WT_ROOT.'includes/functions/functions_import.php'; class WT_Controller_Individual extends WT_Controller_GedcomRecord { - var $name_count = 0; - var $total_names = 0; - var $SEX_COUNT = 0; - var $Fam_Navigator = 'YES'; - var $NAME_LINENUM = null; - var $SEX_LINENUM = null; - var $globalfacts = null; + public $name_count = 0; + public $total_names = 0; + public $tabs; function __construct() { - global $USE_RIN, $MAX_ALIVE_AGE, $SEARCH_SPIDER; - global $DEFAULT_PIN_STATE, $DEFAULT_SB_CLOSED_STATE; - global $Fam_Navigator; - - $xref = safe_GET_xref('pid'); - - $gedrec = find_person_record($xref, WT_GED_ID); - - if ($USE_RIN && $gedrec==false) { - $xref = find_rin_id($xref); - $gedrec = find_person_record($xref, WT_GED_ID); - } - if (empty($gedrec)) { - $gedrec = "0 @".$xref."@ INDI\n"; - } + global $USE_RIN; - if (find_person_record($xref, WT_GED_ID) || find_updated_record($xref, WT_GED_ID)!==null) { - $this->record = new WT_Person($gedrec); - $this->record->ged_id=WT_GED_ID; // This record is from a file - } else if (!$this->record) { - parent::__construct(); - return; - } + $xref = safe_GET_xref('pid'); + $this->record = WT_Individual::getInstance($xref); - //-- if the user can edit and there are changes then get the new changes - if (WT_USER_CAN_EDIT || WT_USER_CAN_ACCEPT) { - $newrec = find_updated_record($xref, WT_GED_ID); - if (!empty($newrec)) { - $diff_record = new WT_Person($newrec); - $diff_record->setChanged(true); - $this->record->diffMerge($diff_record); - } + if (!$this->record && $USE_RIN) { + $rin = find_rin_id($xref); + $this->record = WT_Individual::getInstance($rin); } - $this->tabs=WT_Module::getActiveTabs(); - - // Our parent needs $this->record parent::__construct(); + $this->tabs = WT_Module::getActiveTabs(); + // If we can display the details, add them to the page header - if ($this->record && $this->record->canDisplayDetails()) { - $this->setPageTitle($this->record->getFullName().' '.$this->record->getLifespan()); + if ($this->record && $this->record->canShow()) { + $this->setPageTitle($this->record->getFullName() . ' ' . $this->record->getLifespan()); } } @@ -147,29 +118,33 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { * @see individual.php * @param Event $event the event object */ - function print_name_record(WT_Event $event) { + function print_name_record(WT_Fact $event) { if (!$event->canShow()) { return false; } - $factrec = $event->getGedComRecord(); - $linenum = $event->getLineNumber(); + $factrec = $event->getGedcom(); // Create a dummy record, so we can extract the formatted NAME value from the event. - $dummy=new WT_Person('0 @'.$event->getParentObject()->getXref()."@ INDI\n1 DEAT Y\n".$factrec); + $dummy=new WT_Individual( + 'xref', + "0 @xref@ INDI\n1 DEAT Y\n".$factrec, + null, + WT_GED_ID + ); $all_names=$dummy->getAllNames(); $primary_name=$all_names[0]; $this->name_count++; if ($this->name_count >1) { echo '<h3 class="name_two">',$dummy->getFullName(), '</h3>'; } //Other names accordion element - echo '<div class="indi_name_details"'; - if ($event->getIsOld()) { - echo " class=\"namered\""; + echo '<div class="indi_name_details'; + if ($event->isOld()) { + echo ' old'; } - if ($event->getIsNew()) { - echo " class=\"nameblue\""; + if ($event->isNew()) { + echo ' new'; } - echo ">"; + echo '">'; echo '<div class="name1">'; echo '<dl><dt class="label">', WT_I18N::translate('Name'), '</dt>'; @@ -184,9 +159,9 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { } } } - if ($this->record->canEdit() && !$event->getIsOld()) { - echo "<div class=\"deletelink\"><a class=\"font9 deleteicon\" href=\"#\" onclick=\"return delete_fact('".$this->record->getXref()."', ".$linenum.", '', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');\" title=\"".WT_I18N::translate('Delete name')."\"><span class=\"link_text\">".WT_I18N::translate('Delete name')."</span></a></div>"; - echo "<div class=\"editlink\"><a href=\"#\" class=\"font9 editicon\" onclick=\"edit_name('".$this->record->getXref()."', ".$linenum."); return false;\" title=\"".WT_I18N::translate('Edit name')."\"><span class=\"link_text\">".WT_I18N::translate('Edit name')."</span></a></div>"; + if ($this->record->canEdit() && !$event->isOld()) { + echo "<div class=\"deletelink\"><a class=\"font9 deleteicon\" href=\"#\" onclick=\"return delete_fact('".WT_I18N::translate('Are you sure you want to delete this fact?')."', '".$this->record->getXref()."', '".$event->getFactId()."');\" title=\"".WT_I18N::translate('Delete name')."\"><span class=\"link_text\">".WT_I18N::translate('Delete name')."</span></a></div>"; + echo "<div class=\"editlink\"><a href=\"#\" class=\"font9 editicon\" onclick=\"edit_name('".$this->record->getXref()."', '".$event->getFactId()."'); return false;\" title=\"".WT_I18N::translate('Edit name')."\"><span class=\"link_text\">".WT_I18N::translate('Edit name')."</span></a></div>"; } echo '</dd>'; echo '</dl>'; @@ -243,50 +218,45 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { * @see individual.php * @param Event $event the Event object */ - function print_sex_record(WT_Event $event) { - global $sex; - - if (!$event->canShow()) return false; - $factrec = $event->getGedComRecord(); - $sex = $event->getDetail(); + function print_sex_record(WT_Fact $event) { + $sex = $event->getValue(); if (empty($sex)) $sex = 'U'; - echo '<span id="sex"'; - echo ' class="'; - if ($event->getIsOld()) { - echo 'namered '; - } - if ($event->getIsNew()) { - echo 'nameblue '; - } - switch ($sex) { - case 'M': - echo 'male_gender"'; - if ($this->record->canEdit() && !$event->getIsOld()) { - echo ' title="', WT_I18N::translate('Male'), ' - ', WT_I18N::translate('Edit'), '"'; - echo ' onclick="edit_record(\''.$this->record->getXref().'\', '.$event->getLineNumber().'); return false;"> '; - } else { - echo ' title="', WT_I18N::translate('Male'), '"> '; - } - break; - case 'F': - echo 'female_gender"'; - if ($this->record->canEdit() && !$event->getIsOld()) { - echo ' title="', WT_I18N::translate('Female'), ' - ', WT_I18N::translate('Edit'), '"'; - echo ' onclick="edit_record(\''.$this->record->getXref().'\', '.$event->getLineNumber().'); return false;"> '; - } else { - echo ' title="', WT_I18N::translate('Female'), '"> '; - } - break; - case 'U': - echo 'unknown_gender"'; - if ($this->record->canEdit() && !$event->getIsOld()) { - echo ' title="', WT_I18N::translate_c('unknown gender', 'Unknown'), ' - ', WT_I18N::translate('Edit'), '"'; - echo ' onclick="edit_record(\''.$this->record->getXref().'\', '.$event->getLineNumber().'); return false;"> '; - } else { - echo ' title="', WT_I18N::translate_c('unknown gender', 'Unknown'), '"> '; - } - break; - } + echo '<span id="sex" class="'; + if ($event->isOld()) { + echo 'old'; + } + if ($event->isNew()) { + echo 'new'; + } + switch ($sex) { + case 'M': + echo ' male_gender"'; + if ($event->canEdit()) { + echo ' title="', WT_I18N::translate('Male'), ' - ', WT_I18N::translate('Edit'), '"'; + echo ' onclick="edit_record(\''.$this->record->getXref().'\', \''.$event->getFactId().'\'); return false;">'; + } else { + echo ' title="', WT_I18N::translate('Male'), '">'; + } + break; + case 'F': + echo ' female_gender"'; + if ($event->canEdit()) { + echo ' title="', WT_I18N::translate('Female'), ' - ', WT_I18N::translate('Edit'), '"'; + echo ' onclick="edit_record(\''.$this->record->getXref().'\', \''.$event->getFactId().'\'); return false;">'; + } else { + echo ' title="', WT_I18N::translate('Female'), '">'; + } + break; + case 'U': + echo ' unknown_gender"'; + if ($event->canEdit()) { + echo ' title="', WT_I18N::translate_c('unknown gender', 'Unknown'), ' - ', WT_I18N::translate('Edit'), '"'; + echo ' onclick="edit_record(\''.$this->record->getXref().'\', \''.$event->getFactId().'\'); return false;">'; + } else { + echo ' title="', WT_I18N::translate_c('unknown gender', 'Unknown'), '">'; + } + break; + } echo '</span>'; } /** @@ -295,39 +265,41 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { function getEditMenu() { $SHOW_GEDCOM_RECORD=get_gedcom_setting(WT_GED_ID, 'SHOW_GEDCOM_RECORD'); - if (!$this->record || $this->record->isMarkedDeleted()) { + if (!$this->record || $this->record->isOld()) { return null; } // edit menu $menu = new WT_Menu(WT_I18N::translate('Edit'), '#', 'menu-indi'); $menu->addLabel($menu->label, 'down'); - $this->getGlobalFacts(); // sets NAME_LINENUM and SEX_LINENUM. individual.php doesn't do it early enough for us.... - // What behaviour shall we give the main menu? If we leave it blank, the framework // will copy the first submenu - which may be edit-raw or delete. // As a temporary solution, make it edit the name - if (WT_USER_CAN_EDIT && $this->NAME_LINENUM) { - $menu->addOnclick("return edit_name('".$this->record->getXref()."', ".$this->NAME_LINENUM.");"); - } else { - $menu->addOnclick("return false;"); - } - + $menu->addOnclick("return false;"); if (WT_USER_CAN_EDIT) { - //--make sure the totals are correct + foreach ($this->record->getFacts() as $fact) { + if ($fact->getTag()=='NAME' && $fact->canShow() && $fact->canEdit()) + $menu->addOnclick("return edit_name('".$this->record->getXref() . "', '" . $fact->getFactId() . "');"); + break; + } + $submenu = new WT_Menu(WT_I18N::translate('Add new Name'), '#', 'menu-indi-addname'); $submenu->addOnclick("return add_name('".$this->record->getXref()."');"); $menu->addSubmenu($submenu); - if ($this->SEX_COUNT<2) { - $submenu = new WT_Menu(WT_I18N::translate('Edit gender'), '#', 'menu-indi-editsex'); - if ($this->SEX_LINENUM=="new") { - $submenu->addOnclick("return add_new_record('".$this->record->getXref()."', 'SEX');"); - } else { - $submenu->addOnclick("return edit_record('".$this->record->getXref()."', ".$this->SEX_LINENUM.");"); + $has_sex_record = false; + $submenu = new WT_Menu(WT_I18N::translate('Edit gender'), '#', 'menu-indi-editsex'); + foreach ($this->record->getFacts() as $fact) { + if ($fact->getTag()=='SEX' && $fact->canShow() && $fact->canEdit()) { + $submenu->addOnclick("return edit_record('" . $this->record->getXref() . "', '" . $fact->getFactId() . "');"); + $has_sex_record = true; + break; } - $menu->addSubmenu($submenu); } + if (!$has_sex_record) { + $submenu->addOnclick("return add_new_record('" . $this->record->getXref() . "', 'SEX');"); + } + $menu->addSubmenu($submenu); if (count($this->record->getSpouseFamilies())>1) { $submenu = new WT_Menu(WT_I18N::translate('Re-order families'), '#', 'menu-indi-orderfam'); @@ -336,21 +308,6 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { } } - // edit/view raw gedcom - if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('Edit raw GEDCOM record'), '#', 'menu-indi-editraw'); - $submenu->addOnclick("return edit_raw('".$this->record->getXref()."');"); - $menu->addSubmenu($submenu); - } elseif ($SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('View GEDCOM Record'), '#', 'menu-indi-viewraw'); - if (WT_USER_CAN_EDIT) { - $submenu->addOnclick("return show_gedcom_record('new');"); - } else { - $submenu->addOnclick("return show_gedcom_record();"); - } - $menu->addSubmenu($submenu); - } - // delete if (WT_USER_CAN_EDIT) { $submenu = new WT_Menu(WT_I18N::translate('Delete'), '#', 'menu-indi-del'); @@ -372,48 +329,7 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { return $menu; } - /** - * get global facts - * global facts are NAME and SEX - * @return array return the array of global facts - */ - function getGlobalFacts() { - if ($this->globalfacts==null) { - $this->globalfacts = $this->record->getGlobalFacts(); - foreach ($this->globalfacts as $key => $value) { - $fact = $value->getTag(); - if ($fact=="SEX") { - $this->SEX_COUNT++; - $this->SEX_LINENUM = $value->getLineNumber(); - } - if ($fact=="NAME") { - $this->total_names++; - if ($this->NAME_LINENUM==null && !$value->getIsOld()) { - // This is the "primary" name and is edited from the menu - // Subsequent names get their own edit links - $this->NAME_LINENUM = $value->getLineNumber(); - } - } - } - } - return $this->globalfacts; - } - /** - * get the individual facts shown on tab 1 - * @return array - */ - function getIndiFacts() { - $indifacts = $this->record->getIndiFacts(); - sort_facts($indifacts); - return $indifacts; - } - /** - * get the other facts shown on tab 2 - * @return array - */ - function getOtherFacts() { - $otherfacts = $this->record->getOtherFacts(); - return $otherfacts; + function add_asso_facts() { } /** @@ -514,22 +430,10 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { $newwife = null; $newchildren = array(); $delchildren = array(); - $children = array(); - $husb = null; - $wife = null; - if (!$family->getChanged()) { - $husb = $family->getHusband(); - $wife = $family->getWife(); - $children = $family->getChildren(); - } - //-- step families : set the label for the common parent - if ($type=="step-parents") { - $fams = $this->record->getChildFamilies(); - foreach ($fams as $key=>$fam) { - if ($fam->hasParent($husb)) $labels["father"] = get_relationship_name_from_path('fat', null, null); - if ($fam->hasParent($wife)) $labels["mother"] = get_relationship_name_from_path('mot', null, null); - } - } + $husb = $family->getHusband(); + $wife = $family->getWife(); + $children = $family->getChildren(); + //-- set the label for the husband if (!is_null($husb)) { $label = $labels["parent"]; @@ -560,80 +464,6 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { } $wife->setLabel($label); } - if (WT_USER_CAN_EDIT || WT_USER_CAN_ACCEPT) { - $newfamily = $family->getUpdatedFamily(); - if (!is_null($newfamily)) { - $newhusb = $newfamily->getHusband(); - //-- check if the husband in the family has changed - if (!is_null($newhusb) && !$newhusb->equals($husb)) { - $label = $labels["parent"]; - $sex = $newhusb->getSex(); - if ($sex=="F") { - $label = $labels["mother"]; - } - if ($sex=="M") { - $label = $labels["father"]; - } - if ($newhusb->getXref()==$this->record->getXref()) { - $label = '<i class="icon-selected"></i>'; - } - $newhusb->setLabel($label); - } - else $newhusb = null; - $newwife = $newfamily->getWife(); - //-- check if the wife in the family has changed - if (!is_null($newwife) && !$newwife->equals($wife)) { - $label = $labels["parent"]; - $sex = $newwife->getSex(); - if ($sex=="F") { - $label = $labels["mother"]; - } - if ($sex=="M") { - $label = $labels["father"]; - } - if ($newwife->getXref()==$this->record->getXref()) { - $label = '<i class="icon-selected"></i>'; - } - $newwife->setLabel($label); - } - else $newwife = null; - //-- check for any new children - $merged_children = array(); - $new_children = $newfamily->getChildren(); - $num = count($children); - for ($i=0; $i<$num; $i++) { - $child = $children[$i]; - if (!is_null($child)) { - $found = false; - foreach ($new_children as $key=>$newchild) { - if (!is_null($newchild)) { - if ($child->equals($newchild)) { - $found = true; - break; - } - } - } - if (!$found) $delchildren[] = $child; - else $merged_children[] = $child; - } - } - foreach ($new_children as $key=>$newchild) { - if (!is_null($newchild)) { - $found = false; - foreach ($children as $key1=>$child) { - if (!is_null($child)) { - if ($child->equals($newchild)) { - $found = true; - break; - } - } - } - if (!$found) $newchildren[] = $newchild; - } - } - $children = $merged_children; - } - } //-- set the labels for the children $num = count($children); for ($i=0; $i<$num; $i++) { @@ -650,7 +480,7 @@ class WT_Controller_Individual extends WT_Controller_GedcomRecord { $label = '<i class="icon-selected"></i>'; } if ($include_pedi==true) { - $famcrec = get_sub_record(1, "1 FAMC @".$family->getXref()."@", $children[$i]->getGedcomRecord()); + $famcrec = get_sub_record(1, "1 FAMC @".$family->getXref()."@", $children[$i]->getGedcom()); $pedi = get_gedcom_value("PEDI", 2, $famcrec); if ($pedi) { $label.='<br>('.WT_Gedcom_Code_Pedi::getValue($pedi, $children[$i]).')'; diff --git a/library/WT/Controller/Lifespan.php b/library/WT/Controller/Lifespan.php index 60c6664289..4c4f325d30 100644 --- a/library/WT/Controller/Lifespan.php +++ b/library/WT/Controller/Lifespan.php @@ -122,7 +122,7 @@ class WT_Controller_Lifespan extends WT_Controller_Page { } } } elseif ($newpid) { - $person=WT_Person::getInstance($newpid); + $person=WT_Individual::getInstance($newpid); $this->addFamily($person, $addfam); } elseif (!$this->pids) { $this->addFamily($this->getSignificantIndividual(), false); @@ -138,13 +138,13 @@ class WT_Controller_Lifespan extends WT_Controller_Page { foreach ($this->pids as $key => $value) { if ($value != $remove) { $this->pids[$key] = $value; - $person = WT_Person::getInstance($value); + $person = WT_Individual::getInstance($value); // list of linked records includes families as well as individuals. if ($person) { $bdate = $person->getEstimatedBirthDate(); $ddate = $person->getEstimatedDeathDate(); //--Checks to see if the details of that person can be viewed - if ($bdate->isOK() && $person->canDisplayDetails()) { + if ($bdate->isOK() && $person->canShow()) { $this->people[] = $person; } } @@ -169,7 +169,7 @@ class WT_Controller_Lifespan extends WT_Controller_Page { $bdate = $person->getEstimatedBirthDate(); $ddate = $person->getEstimatedDeathDate(); //--Checks to see if the details of that person can be viewed - if ($bdate->isOK() && $person->canDisplayDetails()) { + if ($bdate->isOK() && $person->canShow()) { $this->people[] = $person; } } @@ -424,7 +424,7 @@ class WT_Controller_Lifespan extends WT_Controller_Page { $evntwdth = $eventwidth."%"; //-- if the fact is a generic EVENt then get the qualifying TYPE if ($fact=="EVEN") { - $fact = $val->getType(); + $fact = $val->getAttribute('TYPE'); } $place = $val->getPlace(); $trans = WT_Gedcom_Tag::getLabel($fact); @@ -532,18 +532,18 @@ class WT_Controller_Lifespan extends WT_Controller_Page { $endjd =WT_Date_Gregorian::YMDtoJD($endyear+1, 1, 1)-1; $sql= - "SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT DISTINCT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`". " JOIN `##dates` ON i_id=d_gid AND i_file=d_file". " WHERE i_file=? AND d_julianday1 BETWEEN ? AND ?"; $rows=WT_DB::prepare($sql) ->execute(array(WT_GED_ID, $startjd, $endjd)) - ->fetchAll(PDO::FETCH_ASSOC); + ->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=WT_Person::getInstance($row); + $list[]=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } return $list; } diff --git a/library/WT/Controller/Media.php b/library/WT/Controller/Media.php index 562bf8aabe..c9fbf39547 100644 --- a/library/WT/Controller/Media.php +++ b/library/WT/Controller/Media.php @@ -2,7 +2,7 @@ // Controller for the media page // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -34,35 +34,8 @@ require_once WT_ROOT.'includes/functions/functions_import.php'; class WT_Controller_Media extends WT_Controller_GedcomRecord { public function __construct() { - $xref = safe_GET_xref('mid'); - - $gedrec=find_media_record($xref, WT_GED_ID); - if (WT_USER_CAN_EDIT) { - $newrec=find_updated_record($xref, WT_GED_ID); - } else { - $newrec=null; - } - - if ($gedrec===null) { - if ($newrec===null) { - // Nothing to see here. - parent::__construct(); - return; - } else { - // Create a dummy record from the first line of the new record. - // We need it for diffMerge(), getXref(), etc. - list($gedrec)=explode("\n", $newrec); - } - } - - $this->record = new WT_Media($gedrec); - - // If there are pending changes, merge them in. - if ($newrec!==null) { - $diff_record=new WT_Media($newrec); - $diff_record->setChanged(true); - $this->record->diffMerge($diff_record); - } + $xref = safe_GET_xref('mid'); + $this->record = WT_Media::getInstance($xref); parent::__construct(); } @@ -73,7 +46,7 @@ class WT_Controller_Media extends WT_Controller_GedcomRecord { function getEditMenu() { $SHOW_GEDCOM_RECORD=get_gedcom_setting(WT_GED_ID, 'SHOW_GEDCOM_RECORD'); - if (!$this->record || $this->record->isMarkedDeleted()) { + if (!$this->record || $this->record->isOld()) { return null; } @@ -107,21 +80,6 @@ class WT_Controller_Media extends WT_Controller_GedcomRecord { $menu->addSubmenu($submenu); } - // edit/view raw gedcom - if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('Edit raw GEDCOM record'), '#', 'menu-obje-editraw'); - $submenu->addOnclick("return edit_raw('".$this->record->getXref()."');"); - $menu->addSubmenu($submenu); - } elseif ($SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('View GEDCOM Record'), '#', 'menu-obje-viewraw'); - if (WT_USER_CAN_EDIT || WT_USER_CAN_ACCEPT) { - $submenu->addOnclick("return show_gedcom_record('new');"); - } else { - $submenu->addOnclick("return show_gedcom_record();"); - } - $menu->addSubmenu($submenu); - } - // delete if (WT_USER_CAN_EDIT) { $submenu = new WT_Menu(WT_I18N::translate('Delete'), '#', 'menu-obje-del'); @@ -153,17 +111,17 @@ class WT_Controller_Media extends WT_Controller_GedcomRecord { * @return array */ function getFacts($includeFileName=true) { - $facts = $this->record->getFacts(array()); + $facts = $this->record->getFacts(); // Add some dummy facts to show additional information if ($this->record->fileExists()) { // get height and width of image, when available $imgsize = $this->record->getImageAttributes(); if (!empty($imgsize['WxH'])) { - $facts[] = new WT_Event('1 __IMAGE_SIZE__ '.$imgsize['WxH'], $this->record, 0); + $facts[] = new WT_Fact('1 __IMAGE_SIZE__ '.$imgsize['WxH'], $this->record, 0); } //Prints the file size - $facts[] = new WT_Event('1 __FILE_SIZE__ '.$this->record->getFilesize(), $this->record, 0); + $facts[] = new WT_Fact('1 __FILE_SIZE__ '.$this->record->getFilesize(), $this->record, 0); } sort_facts($facts); diff --git a/library/WT/Controller/Note.php b/library/WT/Controller/Note.php index 01fad484c8..003fd45acd 100644 --- a/library/WT/Controller/Note.php +++ b/library/WT/Controller/Note.php @@ -2,7 +2,7 @@ // Controller for the shared note page // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2009 PGV Development Team. All rights reserved. @@ -33,35 +33,8 @@ require_once WT_ROOT.'includes/functions/functions_import.php'; class WT_Controller_Note extends WT_Controller_GedcomRecord { public function __construct() { - $xref=safe_GET_xref('nid'); - - $gedrec=find_other_record($xref, WT_GED_ID); - if (WT_USER_CAN_EDIT) { - $newrec=find_updated_record($xref, WT_GED_ID); - } else { - $newrec=null; - } - - if ($gedrec===null) { - if ($newrec===null) { - // Nothing to see here. - parent::__construct(); - return; - } else { - // Create a dummy record from the first line of the new record. - // We need it for diffMerge(), getXref(), etc. - list($gedrec)=explode("\n", $newrec); - } - } - - $this->record = new WT_Note($gedrec); - - // If there are pending changes, merge them in. - if ($newrec!==null) { - $diff_record=new WT_Note($newrec); - $diff_record->setChanged(true); - $this->record->diffMerge($diff_record); - } + $xref = safe_GET_xref('nid'); + $this->record = WT_Note::getInstance($xref); parent::__construct(); } @@ -72,7 +45,7 @@ class WT_Controller_Note extends WT_Controller_GedcomRecord { function getEditMenu() { $SHOW_GEDCOM_RECORD=get_gedcom_setting(WT_GED_ID, 'SHOW_GEDCOM_RECORD'); - if (!$this->record || $this->record->isMarkedDeleted()) { + if (!$this->record || $this->record->isOld()) { return null; } @@ -85,21 +58,6 @@ class WT_Controller_Note extends WT_Controller_GedcomRecord { $menu->addSubmenu($submenu); } - // edit/view raw gedcom - if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('Edit raw GEDCOM record'), '#', 'menu-note-editraw'); - $submenu->addOnclick("return edit_raw('".$this->record->getXref()."');"); - $menu->addSubmenu($submenu); - } elseif ($SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('View GEDCOM Record'), '#', 'menu-note-viewraw'); - if (WT_USER_CAN_EDIT) { - $submenu->addOnclick("return show_gedcom_record('new');"); - } else { - $submenu->addOnclick("return show_gedcom_record();"); - } - $menu->addSubmenu($submenu); - } - // delete if (WT_USER_CAN_EDIT) { $submenu = new WT_Menu(WT_I18N::translate('Delete'), '#', 'menu-note-del'); diff --git a/library/WT/Controller/Page.php b/library/WT/Controller/Page.php index 55a6b55cdc..d2fe6031db 100644 --- a/library/WT/Controller/Page.php +++ b/library/WT/Controller/Page.php @@ -163,7 +163,6 @@ class WT_Controller_Page extends WT_Controller_Base { var browserType = "'.$BROWSERTYPE.'"; var WT_SCRIPT_NAME = "'.WT_SCRIPT_NAME.'"; var WT_LOCALE = "'.WT_LOCALE.'"; - var accesstime = '.WT_TIMESTAMP.'; ', self::JS_PRIORITY_HIGH); // Temporary fix for access to main menu hover elements on android/blackberry touch devices @@ -220,16 +219,16 @@ class WT_Controller_Page extends WT_Controller_Base { static $individual; // Only query the DB once. if (!$individual && WT_USER_ROOT_ID) { - $individual=WT_Person::getInstance(WT_USER_ROOT_ID); + $individual=WT_Individual::getInstance(WT_USER_ROOT_ID); } if (!$individual && WT_USER_GEDCOM_ID) { - $individual=WT_Person::getInstance(WT_USER_GEDCOM_ID); + $individual=WT_Individual::getInstance(WT_USER_GEDCOM_ID); } if (!$individual) { - $individual=WT_Person::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); + $individual=WT_Individual::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); } if (!$individual) { - $individual=WT_Person::getInstance( + $individual=WT_Individual::getInstance( WT_DB::prepare( "SELECT MIN(i_id) FROM `##individuals` WHERE i_file=?" )->execute(array(WT_GED_ID))->fetchOne() @@ -237,7 +236,7 @@ class WT_Controller_Page extends WT_Controller_Base { } if (!$individual) { // always return a record - $individual=new WT_Person('0 @I@ INDI'); + $individual=new WT_Individual('I', '0 @I@ INDI', null, WT_GED_ID); } return $individual; } @@ -252,7 +251,7 @@ class WT_Controller_Page extends WT_Controller_Base { } } // always return a record - return new WT_Family('0 @F@ FAM'); + return new WT_Family('F', '0 @F@ FAM', null, WT_GED_ID); } public function getSignificantSurname() { return ''; diff --git a/library/WT/Controller/Pedigree.php b/library/WT/Controller/Pedigree.php index 65bb3174f0..5133aea959 100644 --- a/library/WT/Controller/Pedigree.php +++ b/library/WT/Controller/Pedigree.php @@ -2,7 +2,7 @@ // Controller for the pedigree chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -85,7 +85,7 @@ class WT_Controller_Pedigree extends WT_Controller_Chart { $show_full = $this->show_full; $talloffset = $this->talloffset; - if ($this->root && $this->root->canDisplayName()) { + if ($this->root && $this->root->canShowName()) { $this->setPageTitle( /* I18N: %s is an individual’s name */ WT_I18N::translate('Pedigree tree of %s', $this->root->getFullName()) diff --git a/library/WT/Controller/Repository.php b/library/WT/Controller/Repository.php index 7af4c8c139..2c409a6110 100644 --- a/library/WT/Controller/Repository.php +++ b/library/WT/Controller/Repository.php @@ -2,7 +2,7 @@ // Controller for the repository page // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -33,35 +33,8 @@ require_once WT_ROOT.'includes/functions/functions_import.php'; class WT_Controller_Repository extends WT_Controller_GedcomRecord { public function __construct() { - $xref = safe_GET_xref('rid'); - - $gedrec=find_other_record($xref, WT_GED_ID); - if (WT_USER_CAN_EDIT) { - $newrec=find_updated_record($xref, WT_GED_ID); - } else { - $newrec=null; - } - - if ($gedrec===null) { - if ($newrec===null) { - // Nothing to see here. - parent::__construct(); - return; - } else { - // Create a dummy record from the first line of the new record. - // We need it for diffMerge(), getXref(), etc. - list($gedrec)=explode("\n", $newrec); - } - } - - $this->record = new WT_Repository($gedrec); - - // If there are pending changes, merge them in. - if ($newrec!==null) { - $diff_record=new WT_Repository($newrec); - $diff_record->setChanged(true); - $this->record->diffMerge($diff_record); - } + $xref = safe_GET_xref('rid'); + $this->record = WT_Repository::getInstance($xref); parent::__construct(); } @@ -72,7 +45,7 @@ class WT_Controller_Repository extends WT_Controller_GedcomRecord { function getEditMenu() { $SHOW_GEDCOM_RECORD=get_gedcom_setting(WT_GED_ID, 'SHOW_GEDCOM_RECORD'); - if (!$this->record || $this->record->isMarkedDeleted()) { + if (!$this->record || $this->record->isOld()) { return null; } @@ -85,21 +58,6 @@ class WT_Controller_Repository extends WT_Controller_GedcomRecord { $menu->addSubmenu($submenu); } - // edit/view raw gedcom - if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('Edit raw GEDCOM record'), '#', 'menu-repo-editraw'); - $submenu->addOnclick("return edit_raw('".$this->record->getXref()."');"); - $menu->addSubmenu($submenu); - } elseif ($SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('View GEDCOM Record'), '#', 'menu-repo-viewraw'); - if (WT_USER_CAN_EDIT) { - $submenu->addOnclick("return show_gedcom_record('new');"); - } else { - $submenu->addOnclick("return show_gedcom_record();"); - } - $menu->addSubmenu($submenu); - } - // delete if (WT_USER_CAN_EDIT) { $submenu = new WT_Menu(WT_I18N::translate('Delete'), '#', 'menu-repo-del'); diff --git a/library/WT/Controller/Search.php b/library/WT/Controller/Search.php index 90a83891a1..ac67d6a0c7 100644 --- a/library/WT/Controller/Search.php +++ b/library/WT/Controller/Search.php @@ -285,7 +285,7 @@ class WT_Controller_Search extends WT_Controller_Page { // Then see if an ID is typed in. If so, we might want to jump there. if (isset ($this->query)) { $record=WT_GedcomRecord::getInstance($this->query); - if ($record && $record->canDisplayDetails()) { + if ($record && $record->canShow()) { header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$record->getRawUrl()); exit; } @@ -357,7 +357,7 @@ class WT_Controller_Search extends WT_Controller_Page { // If ID cannot be displayed, continue to the search page. if (count($this->myindilist)==1 && !$this->myfamlist && !$this->mysourcelist && !$this->mynotelist) { $indi=$this->myindilist[0]; - if ($indi->canDisplayName()) { + if ($indi->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$indi->getRawUrl()); exit; @@ -365,7 +365,7 @@ class WT_Controller_Search extends WT_Controller_Page { } if (!$this->myindilist && count($this->myfamlist)==1 && !$this->mysourcelist && !$this->mynotelist) { $fam=$this->myfamlist[0]; - if ($fam->canDisplayName()) { + if ($fam->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$fam->getRawUrl()); exit; @@ -373,7 +373,7 @@ class WT_Controller_Search extends WT_Controller_Page { } if (!$this->myindilist && !$this->myfamlist && count($this->mysourcelist)==1 && !$this->mynotelist) { $sour=$this->mysourcelist[0]; - if ($sour->canDisplayName()) { + if ($sour->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$sour->getRawUrl()); exit; @@ -381,7 +381,7 @@ class WT_Controller_Search extends WT_Controller_Page { } if (!$this->myindilist && !$this->myfamlist && !$this->mysourcelist && count($this->mynotelist)==1) { $note=$this->mynotelist[0]; - if ($note->canDisplayName()) { + if ($note->canShowName()) { Zend_Session::writeClose(); header('Location: '.WT_SERVER_NAME.WT_SCRIPT_PATH.$note->getRawUrl()); exit; @@ -443,7 +443,7 @@ class WT_Controller_Search extends WT_Controller_Page { } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { - replace_gedrec($individual->getXref(), WT_GED_ID, $newRecord); + $individual->updateRecord($newRecord, true); } else { unset($this->myindilist[$id]); } @@ -465,7 +465,7 @@ class WT_Controller_Search extends WT_Controller_Page { } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { - replace_gedrec($family->getXref(), WT_GED_ID, $newRecord); + $family->updateRecord($newRecord, true); } else { unset($this->myfamlist[$id]); } @@ -490,7 +490,7 @@ class WT_Controller_Search extends WT_Controller_Page { } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { - replace_gedrec($source->getXref(), WT_GED_ID, $newRecord); + $source->updateRecord($newRecord, true); } else { unset($this->mysourcelist[$id]); } @@ -506,7 +506,7 @@ class WT_Controller_Search extends WT_Controller_Page { } //-- if the record changed replace the record otherwise remove it from the search results if ($newRecord != $oldRecord) { - replace_gedrec($note->getXref(), WT_GED_ID, $newRecord); + $noteource->updateRecord($newRecord, true); } else { unset($this->mynotelist[$id]); } @@ -557,10 +557,10 @@ class WT_Controller_Search extends WT_Controller_Page { if ($this->showasso == "on") { foreach ($this->myindilist as $indi) { - foreach (fetch_linked_indi($indi->getXref(), 'ASSO', $indi->getGedId()) as $asso) { + foreach (fetch_linked_indi($indi->getXref(), 'ASSO', $indi->getGedcomId()) as $asso) { $this->myindilist[]=$asso; } - foreach (fetch_linked_fam($indi->getXref(), 'ASSO', $indi->getGedId()) as $asso) { + foreach (fetch_linked_fam($indi->getXref(), 'ASSO', $indi->getGedcomId()) as $asso) { $this->myfamlist[]=$asso; } } @@ -603,7 +603,7 @@ class WT_Controller_Search extends WT_Controller_Page { foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->myindilist as $individual) { - if ($individual->getGedId()==$ged_id) { + if ($individual->getGedcomId()==$ged_id) { $datalist[]=$individual; } } @@ -627,7 +627,7 @@ class WT_Controller_Search extends WT_Controller_Page { foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->myfamlist as $family) { - if ($family->getGedId()==$ged_id) { + if ($family->getGedcomId()==$ged_id) { $datalist[]=$family; } } @@ -651,7 +651,7 @@ class WT_Controller_Search extends WT_Controller_Page { foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->mysourcelist as $source) { - if ($source->getGedId()==$ged_id) { + if ($source->getGedcomId()==$ged_id) { $datalist[]=$source; } } @@ -675,7 +675,7 @@ class WT_Controller_Search extends WT_Controller_Page { foreach ($this->sgeds as $ged_id=>$gedcom) { $datalist = array(); foreach ($this->mynotelist as $note) { - if ($note->getGedId()==$ged_id) { + if ($note->getGedcomId()==$ged_id) { $datalist[]=$note; } } diff --git a/library/WT/Controller/Source.php b/library/WT/Controller/Source.php index f2825493d4..dff23a7558 100644 --- a/library/WT/Controller/Source.php +++ b/library/WT/Controller/Source.php @@ -2,7 +2,7 @@ // Controller for the source page // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -33,35 +33,8 @@ require_once WT_ROOT.'includes/functions/functions_import.php'; class WT_Controller_Source extends WT_Controller_GedcomRecord { public function __construct() { - $xref=safe_GET_xref('sid'); - - $gedrec=find_source_record($xref, WT_GED_ID); - if (WT_USER_CAN_EDIT) { - $newrec=find_updated_record($xref, WT_GED_ID); - } else { - $newrec=null; - } - - if ($gedrec===null) { - if ($newrec===null) { - // Nothing to see here. - parent::__construct(); - return; - } else { - // Create a dummy record from the first line of the new record. - // We need it for diffMerge(), getXref(), etc. - list($gedrec)=explode("\n", $newrec); - } - } - - $this->record = new WT_Source($gedrec); - - // If there are pending changes, merge them in. - if ($newrec!==null) { - $diff_record=new WT_Source($newrec); - $diff_record->setChanged(true); - $this->record->diffMerge($diff_record); - } + $xref = safe_GET_xref('sid'); + $this->record = WT_Source::getInstance($xref); parent::__construct(); } @@ -72,7 +45,7 @@ class WT_Controller_Source extends WT_Controller_GedcomRecord { function getEditMenu() { $SHOW_GEDCOM_RECORD=get_gedcom_setting(WT_GED_ID, 'SHOW_GEDCOM_RECORD'); - if (!$this->record || $this->record->isMarkedDeleted()) { + if (!$this->record || $this->record->isOld()) { return null; } @@ -85,21 +58,6 @@ class WT_Controller_Source extends WT_Controller_GedcomRecord { $menu->addSubmenu($submenu); } - // edit/view raw gedcom - if (WT_USER_IS_ADMIN || $SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('Edit raw GEDCOM record'), '#', 'menu-sour-editraw'); - $submenu->addOnclick("return edit_raw('".$this->record->getXref()."');"); - $menu->addSubmenu($submenu); - } elseif ($SHOW_GEDCOM_RECORD) { - $submenu = new WT_Menu(WT_I18N::translate('View GEDCOM Record'), '#', 'menu-sour-viewraw'); - if (WT_USER_CAN_EDIT) { - $submenu->addOnclick("return show_gedcom_record('new');"); - } else { - $submenu->addOnclick("return show_gedcom_record();"); - } - $menu->addSubmenu($submenu); - } - // delete if (WT_USER_CAN_EDIT) { $submenu = new WT_Menu(WT_I18N::translate('Delete'), '#', 'menu-sour-del'); diff --git a/library/WT/Controller/Timeline.php b/library/WT/Controller/Timeline.php index 85f82ea2f7..349a843561 100644 --- a/library/WT/Controller/Timeline.php +++ b/library/WT/Controller/Timeline.php @@ -71,7 +71,7 @@ class WT_Controller_Timeline extends WT_Controller_Page { foreach ($this->pids as $value) { if ($value!=$remove) { $newpids[] = $value; - $person = WT_Person::getInstance($value); + $person = WT_Individual::getInstance($value); if ($person) { $this->people[] = $person; } @@ -81,7 +81,7 @@ class WT_Controller_Timeline extends WT_Controller_Page { $this->pidlinks = ""; /* @var $indi Person */ foreach ($this->people as $p=>$indi) { - if (!is_null($indi) && $indi->canDisplayDetails()) { + if (!is_null($indi) && $indi->canShow()) { //-- setup string of valid pids for links $this->pidlinks .= "pids%5B%5D=".$indi->getXref()."&"; $bdate = $indi->getBirthDate(); @@ -95,8 +95,14 @@ class WT_Controller_Timeline extends WT_Controller_Page { } } // find all the fact information - $indi->add_family_facts(false); - foreach ($indi->getIndiFacts() as $event) { + $facts = $indi->getFacts(); + foreach ($indi->getSpouseFamilies() as $family) { + foreach ($family->getFacts() as $fact) { + $fact->spouse = $family->getSpouse($indi); + $facts[] = $fact; + } + } + foreach ($facts as $event) { //-- get the fact type $fact = $event->getTag(); if (!in_array($fact, $this->nonfacts)) { @@ -137,8 +143,8 @@ class WT_Controller_Timeline extends WT_Controller_Page { $printed = false; for ($i=0; $i<count($this->people); $i++) { if (!is_null($this->people[$i])) { - if (!$this->people[$i]->canDisplayDetails()) { - if ($this->people[$i]->canDisplayName()) { + if (!$this->people[$i]->canShow()) { + if ($this->people[$i]->canShowName()) { echo " <a href=\"".$this->people[$i]->getHtmlUrl()."\">".$this->people[$i]->getFullName()."</a>"; print_privacy_error(); echo "<br>"; @@ -153,15 +159,15 @@ class WT_Controller_Timeline extends WT_Controller_Page { } } - function print_time_fact(WT_Event $event) { + function print_time_fact(WT_Fact $event) { global $basexoffset, $baseyoffset, $factcount, $TEXT_DIRECTION, $WT_IMAGES, $SHOW_PEDIGREE_PLACES, $placements; /* @var $event Event */ - $factrec = $event->getGedComRecord(); + $factrec = $event->getGedcom(); $fact = $event->getTag(); - $desc = $event->getDetail(); + $desc = $event->getValue(); if ($fact=="EVEN" || $fact=="FACT") { - $fact = $event->getType(); + $fact = $event->getAttribute('TYPE'); } //-- check if this is a family fact $gdate=$event->getDate(); @@ -201,11 +207,11 @@ class WT_Controller_Timeline extends WT_Controller_Page { echo ": 3px;\">"; $col = $event->temp % 6; echo "</td><td valign=\"top\" class=\"person".$col."\">"; - if (count($this->pids) > 6) echo $event->getParentObject()->getFullName()." - "; - $record=$event->getParentObject(); + if (count($this->pids) > 6) echo $event->getParent()->getFullName()." - "; + $record=$event->getParent(); echo $event->getLabel(); echo " -- "; - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { echo format_fact_date($event, $record, false, false); } elseif ($record instanceof WT_Family) { echo $gdate->Display(false); @@ -242,7 +248,11 @@ class WT_Controller_Timeline extends WT_Controller_Page { } } //-- print spouse name for marriage events - $spouse = $event->getSpouse(); + if (isset($event->spouse)) { + $spouse = $event->spouse; + } else { + $spouse = null; + } if ($spouse) { for ($p=0; $p<count($this->pids); $p++) { if ($this->pids[$p]==$spouse->getXref()) break; @@ -252,7 +262,7 @@ class WT_Controller_Timeline extends WT_Controller_Page { if ($spouse->getXref()!=$this->pids[$p]) { echo ' <a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a>'; } else { - echo ' <a href="', $event->getParentObject()->getHtmlUrl(), '">', $event->getParentObject()->getFullName(), '</a>'; + echo ' <a href="', $event->getParent()->getHtmlUrl(), '">', $event->getParent()->getFullName(), '</a>'; } } echo "</td></tr></table>"; @@ -284,7 +294,7 @@ class WT_Controller_Timeline extends WT_Controller_Page { public function getSignificantIndividual() { if ($this->pids) { - return WT_Person::getInstance($this->pids[0]); + return WT_Individual::getInstance($this->pids[0]); } else { return parent::getSignificantIndividual(); } diff --git a/library/WT/Event.php b/library/WT/Fact.php index da786f8d86..8655c76fef 100644 --- a/library/WT/Event.php +++ b/library/WT/Fact.php @@ -2,7 +2,7 @@ // Class that defines an event details object // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2008 PGV Development Team. All rights reserved. @@ -28,109 +28,83 @@ if (!defined('WT_WEBTREES')) { exit; } -class WT_Event { -// These objects need further refinement in their implementations and parsing -// var $address = null; -// var $notes = array(); //[0..*]: string -// var $sourceCitations = array(); //[0..*]: SourceCitation -// var $multimediaLinks = array(); //[0..*]: MultimediaLink +class WT_Fact { + private $fact_id = null; // Unique identifier for this fact + private $parent = null; // The GEDCOM record from which this fact is taken. + private $gedcom = null; // The raw GEDCOM data for this fact + private $tag = null; // The GEDCOM tag for this record - var $lineNumber = null; - var $canShow = null; - var $state = ""; - var $type = NULL; - var $tag = NULL; - var $date = NULL; - var $place = null; - var $gedcomRecord = null; - var $resn = null; - var $dest = false; - var $label = null; - var $parentObject = null; - var $detail = NULL; - var $values = NULL; - var $sortOrder = 0; - var $sortDate = NULL; - //-- temporary state variable that can be used by other scripts - var $temp = NULL; + private $is_old = false; // Is this a pending record? + private $is_new = false; // Is this a pending record? - // Is this an old/new pending record? - private $is_old = false; - private $is_new = false; + private $date = null; // The WT_Date object for the "2 DATE ..." attribute + private $place = null; // The WT_Place object for the "2 PLAC ..." attribute - // For family facts on individual pages - who is the significant spouse. - private $spouse; + // Temporary(!) variables that are used by other scripts + public $temp = null; // Timeline controller + public $sortOrder = 0; // sort_facts() - /** - * Get the value for the first given GEDCOM tag - * - * @param string $code - * @return string - */ - function getValue($code) { - if (is_null($this->values)) { - $this->values=array(); - preg_match_all('/\n2 ('.WT_REGEX_TAG.') (.+)/', $this->gedcomRecord, $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - // If this is a link, remove the "@" - if (preg_match('/^@'.WT_REGEX_XREF.'@$/', $match[2])) { - $this->values[$match[1]]=trim($match[2], "@"); - } else { - $this->values[$match[1]]=$match[2]; - } - } - } - if (array_key_exists($code, $this->values)) { - return $this->values[$code]; + // Create an event objects from a gedcom fragment. + // We need the parent object (to check privacy) and a (pseudo) fact ID to + // identify the fact within the record. + function __construct($gedcom, WT_GedcomRecord $parent, $fact_id) { + if (preg_match('/^1 ('.WT_REGEX_TAG.')/', $gedcom, $match)) { + $this->gedcom = $gedcom; + $this->parent = $parent; + $this->fact_id = $fact_id; + $this->tag = $match[1]; + } else { + // TODO need to rewrite code that passes dummy data to this function + //throw new Exception('Invalid GEDCOM data passed to WT_Fact::_construct('.$gedcom.')'); } - return null; } - // Create an event objects from a gedcom fragment. - // We also need to know the parent (to check privacy, etc.) and - // the line number (from the original, privacy-filtered) gedcom - // record, to allow editing - function __construct($subrecord, $parent, $lineNumber) { - if (preg_match('/^1 ('.WT_REGEX_TAG.') ?(.*)((\n2 CONT.*)*)/', $subrecord, $match)) { - $this->tag =$match[1]; - $this->detail=$match[2]; - // Some detail records contain multiple lines - if ($match[3]) { - $this->detail.=str_replace(array("\n2 CONT ", "\n2 CONT"), "\n", $match[3]); - } + // Get the value of level 1 data in the fact + // Allow for multi-line values + function getValue() { + if (preg_match('/^1 (?:' . $this->tag . ') ?(.*(?:(?:\n2 CONT .*)*))/', $this->gedcom, $match)) { + return str_replace("\n2 CONT ", "\n", $match[1]); } else { - // We are not ready for this yet. - // throw new Exception('Invalid GEDCOM data passed to WT_Event::_construct('.$subrecord.')'); + return null; } - $this->gedcomRecord=$subrecord; - $this->parentObject=$parent; - $this->lineNumber =$lineNumber; } - function setState($s) { - $this->state = $s; + // Get the record to which this fact links + function getTarget() { + $xref = trim($this->getValue(), '@'); + switch ($this->tag) { + case 'FAMC': + case 'FAMS': + return WT_Family::getInstance($xref); + case 'HUSB': + case 'WIFE': + case 'CHIL': + return WT_Individual::getInstance($xref); + case 'SOUR': + return WT_Source::getInstance($xref); + case 'OBJE': + return WT_Media::getInstance($xref); + case 'REPO': + return WT_Repository::getInstance($xref); + case 'NOTE': + return WT_Note::getInstance($xref); + default: + return WT_GedcomRecord::getInstance($xref); + } } - function getState() { - return $this->state; + // Get the value of level 2 data in the fact + function getAttribute($tag) { + if (preg_match('/\n2 (?:' . $tag . ') ?(.*(?:(?:\n3 CONT .*)*)*)/', $this->gedcom, $match)) { + return str_replace("\n2 CONT ", "\n", $match[1]); + } else { + return null; + } } - /** - * Check whether or not this event can be shown - * - * @return boolean - */ + // Do the privacy rules allow us to display this fact to the current user function canShow() { - if (is_null($this->canShow)) { - if (empty($this->gedcomRecord)) { - $this->canShow = false; - } elseif (!is_null($this->parentObject)) { - $this->canShow = canDisplayFact($this->parentObject->getXref(), $this->parentObject->getGedId(), $this->gedcomRecord); - } else { - $this->canShow = true; - } - } - return $this->canShow; + return canDisplayFact($this->parent->getXref(), $this->parent->getGedcomId(), $this->gedcom); } // Check whether this fact is protected against edit @@ -138,92 +112,52 @@ class WT_Event { // Managers can edit anything // Members cannot edit RESN, CHAN and locked records return - $this->parentObject && $this->parentObject->canEdit() && ( + $this->parent->canEdit() && !$this->isOld() && ( WT_USER_GEDCOM_ADMIN || - WT_USER_CAN_EDIT && strpos($this->gedcomRecord, "\n2 RESN locked")===false && $this->getTag()!='RESN' && $this->getTag()!='CHAN' + WT_USER_CAN_EDIT && strpos($this->gedcom, "\n2 RESN locked")===false && $this->getTag()!='RESN' && $this->getTag()!='CHAN' ); } - /** - * The 4 character event type specified by GEDCom. - * - * @return string - */ - function getType() { - if (is_null($this->type)) - $this->type=$this->getValue('TYPE'); - return $this->type; - } - - /** - * The place where the event occured. - * - * @return string - */ + // The place where the event occured. function getPlace() { - if (is_null($this->place)) { - $this->place=$this->getValue('PLAC'); + if ($this->place === null) { + $this->place = $this->getAttribute('PLAC'); } return $this->place; } - // For family facts on individual pages, we need to know the spouse - public function setSpouse(WT_Person $spouse=null) { - $this->spouse=$spouse; - } - public function getSpouse() { - return $this->spouse; - } - // We can call this function many times, especially when sorting, // so keep a copy of the date. function getDate() { - if ($this->date===null) { - $this->date=new WT_Date($this->getValue('DATE')); + if ($this->date === null) { + $this->date = new WT_Date($this->getAttribute('DATE')); } - return $this->date; } - /** - * The remaining unparsed GEDCom record - * - * @return string - */ - function getGedcomRecord() { - return $this->gedcomRecord; + // The raw GEDCOM data for this fact + function getGedcom() { + return $this->gedcom; } - /** - * The line number, or line of occurrence in the GEDCom record. - * - * @return unknown - */ - function getLineNumber() { - return $this->lineNumber; + // Unique identifier for the fact + function getFactId() { + return $this->fact_id; } - /** - * - */ + // What sort of fact is this? function getTag() { return $this->tag; } - /** - * The Person/Family record where this WT_Event came from - * - * @return GedcomRecord - */ - function getParentObject() { - return $this->parentObject; + // Used to convert a real fact (e.g. BIRT) into a close-relative’s fact (e.g. _BIRT_CHIL) + function setTag($tag) { + $this->tag = $tag; } - /** - * - */ - function getDetail() { - return $this->detail; + // The Person/Family record where this WT_Fact came from + function getParent() { + return $this->parent; } function getLabel($abbreviate=false) { @@ -239,42 +173,39 @@ class WT_Event { } // no break - drop into next case default: - return WT_Gedcom_Tag::getLabel($this->tag, $this->parentObject); + return WT_Gedcom_Tag::getLabel($this->tag, $this->parent); } } } + // Is this a pending edit? public function setIsOld() { - $this->is_old=true; - $this->is_new=false; + $this->is_old = true; + $this->is_new = false; } - public function getIsOld() { + public function isOld() { return $this->is_old; } public function setIsNew() { - $this->is_new=true; - $this->is_old=false; + $this->is_new = true; + $this->is_old = false; } - public function getIsNew() { + public function isNew() { return $this->is_new; } - /** - * Print a simple fact version of this event - * - * @param boolean $return whether to print or return - * @param boolean $anchor whether to add anchor to date and place - */ + // Print a simple fact version of this event function print_simple_fact($return=false, $anchor=false) { - global $SHOW_PEDIGREE_PLACES, $ABBREVIATE_CHART_LABELS; + global $ABBREVIATE_CHART_LABELS; + + $value = $this->getValue(); - if (!$this->canShow()) return ""; $data = '<span class="details_label">'.$this->getLabel($ABBREVIATE_CHART_LABELS).'</span>'; // Don't display "yes", because format_fact_date() does this for us. (Should it?) - if ($this->detail && $this->detail!='Y') { - $data .= ' <span dir="auto">'.htmlspecialchars($this->detail).'</span>'; + if ($value && $value != 'Y') { + $data .= ' <span dir="auto">' . htmlspecialchars($value) . '</span>'; } - $data .= ' '.format_fact_date($this, $this->getParentObject(), $anchor, false); + $data .= ' '.format_fact_date($this, $this->getParent(), $anchor, false); $data .= ' '.format_fact_place($this, $anchor, false, false); $data .= '<br>'; if ($return) { @@ -300,13 +231,7 @@ class WT_Event { } } - /** - * Static Helper functions to sort events - * - * @param WT_Event $a - * @param WT_Event $b - * @return int - */ + // Static Helper functions to sort events static function CompareDate($a, $b) { if ($a->getDate()->isOK() && $b->getDate()->isOK()) { // If both events have dates, compare by date @@ -326,13 +251,7 @@ class WT_Event { } } - /** - * Static method to Compare two events by their type - * - * @param WT_Event $a - * @param WT_Event $b - * @return int - */ + // Static method to Compare two events by their type static function CompareType($a, $b) { global $factsort; @@ -398,7 +317,7 @@ class WT_Event { // Facts from same families stay grouped together // Keep MARR and DIV from the same families from mixing with events from other FAMs // Use the original order in which the facts were added - if ($a->parentObject instanceof WT_Family && $b->parentObject instanceof WT_Family && !$a->parentObject->equals($b->parentObject)) { + if ($a->parent instanceof WT_Family && $b->parent instanceof WT_Family && !$a->parent->equals($b->parent)) { return $a->sortOrder - $b->sortOrder; } @@ -423,13 +342,13 @@ class WT_Event { //-- don't let dated after DEAT/BURI facts sort non-dated facts before DEAT/BURI //-- treat dated after BURI facts as BURI instead - if ($a->getValue('DATE')!=NULL && $factsort[$atag]>$factsort['BURI'] && $factsort[$atag]<$factsort['CHAN']) $atag='BURI'; - if ($b->getValue('DATE')!=NULL && $factsort[$btag]>$factsort['BURI'] && $factsort[$btag]<$factsort['CHAN']) $btag='BURI'; + if ($a->getAttribute('DATE')!=NULL && $factsort[$atag]>$factsort['BURI'] && $factsort[$atag]<$factsort['CHAN']) $atag='BURI'; + if ($b->getAttribute('DATE')!=NULL && $factsort[$btag]>$factsort['BURI'] && $factsort[$btag]<$factsort['CHAN']) $btag='BURI'; $ret = $factsort[$atag]-$factsort[$btag]; //-- if facts are the same then put dated facts before non-dated facts if ($ret==0) { - if ($a->getValue('DATE')!=NULL && $b->getValue('DATE')==NULL) return -1; - if ($b->getValue('DATE')!=NULL && $a->getValue('DATE')==NULL) return 1; + if ($a->getAttribute('DATE')!=NULL && $b->getAttribute('DATE')==NULL) return -1; + if ($b->getAttribute('DATE')!=NULL && $a->getAttribute('DATE')==NULL) return 1; //-- if no sorting preference, then keep original ordering $ret = $a->sortOrder - $b->sortOrder; } diff --git a/library/WT/Family.php b/library/WT/Family.php index cc7876451c..16193de7fa 100644 --- a/library/WT/Family.php +++ b/library/WT/Family.php @@ -30,6 +30,7 @@ if (!defined('WT_WEBTREES')) { class WT_Family extends WT_GedcomRecord { const RECORD_TYPE = 'FAM'; + const SQL_FETCH = "SELECT f_gedcom FROM `##families` WHERE f_id=? AND f_file=?"; const URL_PREFIX = 'family.php?famid='; private $husb = null; @@ -37,23 +38,15 @@ class WT_Family extends WT_GedcomRecord { private $marriage = null; // Create a Family object from either raw GEDCOM data or a database row - function __construct($data) { - if (is_array($data)) { - // Construct from a row from the database - if (preg_match('/^1 HUSB @(.+)@/m', $data['gedrec'], $match)) { - $this->husb=WT_Person::getInstance($match[1]); - } - if (preg_match('/^1 WIFE @(.+)@/m', $data['gedrec'], $match)) { - $this->wife=WT_Person::getInstance($match[1]); - } - } else { - // Construct from raw GEDCOM data - if (preg_match('/^1 HUSB @(.+)@/m', $data, $match)) { - $this->husb=WT_Person::getInstance($match[1]); - } - if (preg_match('/^1 WIFE @(.+)@/m', $data, $match)) { - $this->wife=WT_Person::getInstance($match[1]); - } + function __construct($xref, $gedcom, $pending, $gedcom_id) { + parent::__construct($xref, $gedcom, $pending, $gedcom_id); + + // TODO: fetch these from WT_Fact objects + if (preg_match('/^1 HUSB @(.+)@/m', $gedcom.$pending, $match)) { + $this->husb = WT_Individual::getInstance($match[1]); + } + if (preg_match('/^1 WIFE @(.+)@/m', $gedcom.$pending, $match)) { + $this->wife = WT_Individual::getInstance($match[1]); } // Make sure husb/wife are the right way round. @@ -61,7 +54,6 @@ class WT_Family extends WT_GedcomRecord { list($this->husb, $this->wife)=array($this->wife, $this->husb); } - parent::__construct($data); } // Generate a private version of this record @@ -70,10 +62,10 @@ class WT_Family extends WT_GedcomRecord { $rec='0 @'.$this->xref.'@ FAM'; // Just show the 1 CHIL/HUSB/WIFE tag, not any subtags, which may contain private data - preg_match_all('/\n1 (?:CHIL|HUSB|WIFE) @('.WT_REGEX_XREF.')@/', $this->_gedrec, $matches, PREG_SET_ORDER); + preg_match_all('/\n1 (?:CHIL|HUSB|WIFE) @('.WT_REGEX_XREF.')@/', $this->gedcom, $matches, PREG_SET_ORDER); foreach ($matches as $match) { - $rela=WT_Person::getInstance($match[1]); - if ($rela && ($SHOW_PRIVATE_RELATIONSHIPS || $rela->canDisplayDetails($access_level))) { + $rela=WT_Individual::getInstance($match[1]); + if ($rela && ($SHOW_PRIVATE_RELATIONSHIPS || $rela->canShow($access_level))) { $rec.=$match[0]; } } @@ -81,16 +73,14 @@ class WT_Family extends WT_GedcomRecord { } // Fetch the record from the database - protected static function fetchGedcomRecord($xref, $ged_id) { + protected static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; if ($statement===null) { - $statement=WT_DB::prepare( - "SELECT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec ". - "FROM `##families` WHERE f_id=? AND f_file=?" - ); + $statement=WT_DB::prepare("SELECT f_gedcom FROM `##families` WHERE f_id=? AND f_file=?"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } /** @@ -109,12 +99,12 @@ class WT_Family extends WT_GedcomRecord { } // Implement family-specific privacy logic - protected function _canDisplayDetailsByType($access_level) { + protected function _canShowByType($access_level) { // Hide a family if any member is private - preg_match_all('/\n1 (?:CHIL|HUSB|WIFE) @('.WT_REGEX_XREF.')@/', $this->_gedrec, $matches); + preg_match_all('/\n1 (?:CHIL|HUSB|WIFE) @('.WT_REGEX_XREF.')@/', $this->gedcom, $matches); foreach ($matches[1] as $match) { - $person=WT_Person::getInstance($match); - if ($person && !$person->canDisplayDetails($access_level)) { + $person=WT_Individual::getInstance($match); + if ($person && !$person->canShow($access_level)) { return false; } } @@ -122,7 +112,7 @@ class WT_Family extends WT_GedcomRecord { } // Can the name of this record be shown? - public function canDisplayName($access_level=WT_USER_ACCESS_LEVEL) { + public function canShowName($access_level=WT_USER_ACCESS_LEVEL) { // We can always see the name (Husband-name + Wife-name), however, // the name will often be "private + private" return true; @@ -137,10 +127,10 @@ class WT_Family extends WT_GedcomRecord { if (is_null($this->wife) || is_null($this->husb)) { return null; } - if ($this->wife->equals($person) && $this->husb->canDisplayDetails($access_level)) { + if ($this->wife->equals($person) && $this->husb->canShow($access_level)) { return $this->husb; } - if ($this->husb->equals($person) && $this->wife->canDisplayDetails($access_level)) { + if ($this->husb->equals($person) && $this->wife->canShow($access_level)) { return $this->wife; } return null; @@ -148,10 +138,10 @@ class WT_Family extends WT_GedcomRecord { function getSpouses($access_level=WT_USER_ACCESS_LEVEL) { $spouses=array(); - if ($this->husb && $this->husb->canDisplayDetails($access_level)) { + if ($this->husb && $this->husb->canShow($access_level)) { $spouses[]=$this->husb; } - if ($this->wife && $this->wife->canDisplayDetails($access_level)) { + if ($this->wife && $this->wife->canShow($access_level)) { $spouses[]=$this->wife; } return $spouses; @@ -165,10 +155,10 @@ class WT_Family extends WT_GedcomRecord { global $SHOW_PRIVATE_RELATIONSHIPS; $children=array(); - preg_match_all('/\n1 CHIL @('.WT_REGEX_XREF.')@/', $this->_gedrec, $match); + preg_match_all('/\n1 CHIL @('.WT_REGEX_XREF.')@/', $this->gedcom, $match); foreach ($match[1] as $pid) { - $child=WT_Person::getInstance($pid); - if ($child && ($SHOW_PRIVATE_RELATIONSHIPS || $child->canDisplayDetails($access_level))) { + $child=WT_Individual::getInstance($pid); + if ($child && ($SHOW_PRIVATE_RELATIONSHIPS || $child->canShow($access_level))) { $children[]=$child; } } @@ -186,69 +176,23 @@ class WT_Family extends WT_GedcomRecord { */ function getNumberOfChildren() { - $nchi1=(int)get_gedcom_value('NCHI', 1, $this->getGedcomRecord()); - $nchi2=(int)get_gedcom_value('NCHI', 2, $this->getGedcomRecord()); + $nchi1=(int)get_gedcom_value('NCHI', 1, $this->getGedcom()); + $nchi2=(int)get_gedcom_value('NCHI', 2, $this->getGedcom()); $nchi3=count($this->getChildren()); return max($nchi1, $nchi2, $nchi3); } /** - * get updated Family - * If there is an updated family record in the gedcom file - * return a new family object for it - */ - function getUpdatedFamily() { - if ($this->getChanged()) { - return $this; - } - if (WT_USER_CAN_EDIT && $this->canDisplayDetails()) { - $newrec = find_updated_record($this->xref, $this->ged_id); - if (!is_null($newrec)) { - $newfamily = new WT_Family($newrec); - $newfamily->setChanged(true); - return $newfamily; - } - } - return null; - } - /** - * check if this family has the given person - * as a parent in the family - * @param Person $person - */ - function hasParent($person) { - if (is_null($person)) return false; - if ($person->equals($this->husb)) return true; - if ($person->equals($this->wife)) return true; - return false; - } - /** - * check if this family has the given person - * as a child in the family - * @param Person $person - */ - function hasChild($person) { - if ($person) { - foreach ($this->getChildren() as $child) { - if ($person->equals($child)) { - return true; - } - } - } - return false; - } - - /** * parse marriage record */ function _parseMarriageRecord() { - $this->marriage = new WT_Event(get_sub_record(1, '1 MARR', $this->getGedcomRecord()), $this, 0); + $this->marriage = new WT_Fact(get_sub_record(1, '1 MARR', $this->getGedcom()), $this, 0); } /** * get the marriage event * - * @return WT_Event + * @return WT_Fact */ function getMarriage() { if (is_null($this->marriage)) $this->_parseMarriageRecord(); @@ -261,17 +205,17 @@ class WT_Family extends WT_GedcomRecord { */ function getMarriageRecord() { if (is_null($this->marriage)) $this->_parseMarriageRecord(); - return $this->marriage->getGedcomRecord(); + return $this->marriage->getGedcom(); } // Return whether or not this family ended in a divorce or was never married. // Note that this is calculated using unprivatized data, so we can // always distinguish spouses from ex-spouses. function isDivorced() { - return (bool)preg_match('/\n1 ('.WT_EVENTS_DIV.')( Y|\n)/', $this->_gedrec); + return (bool)preg_match('/\n1 ('.WT_EVENTS_DIV.')( Y|\n)/', $this->gedcom); } function isNotMarried() { - return (bool)preg_match('/\n1 _NMR( Y|\n)/', $this->_gedrec); + return (bool)preg_match('/\n1 _NMR( Y|\n)/', $this->gedcom); } /** @@ -279,7 +223,7 @@ class WT_Family extends WT_GedcomRecord { * @return string */ function getMarriageDate() { - if (!$this->canDisplayDetails()) { + if (!$this->canShow()) { return new WT_Date(''); } if (is_null($this->marriage)) { @@ -299,7 +243,7 @@ class WT_Family extends WT_GedcomRecord { */ function getMarriageType() { if (is_null($this->marriage)) $this->_parseMarriageRecord(); - return $this->marriage->getType(); + return $this->marriage->getAttribute('TYPE'); } /** @@ -313,7 +257,7 @@ class WT_Family extends WT_GedcomRecord { // Get all the dates/places for marriages - for the FAM lists function getAllMarriageDates() { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach (explode('|', WT_EVENTS_MARR) as $event) { if ($array=$this->getAllEventDates($event)) { return $array; @@ -323,7 +267,7 @@ class WT_Family extends WT_GedcomRecord { return array(); } function getAllMarriagePlaces() { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach (explode('|', WT_EVENTS_MARR) as $event) { if ($array=$this->getAllEventPlaces($event)) { return $array; @@ -336,8 +280,8 @@ class WT_Family extends WT_GedcomRecord { // Get an array of structures containing all the names in the record public function getAllNames() { if (is_null($this->_getAllNames)) { - $husb=$this->husb ? $this->husb : new WT_Person('1 SEX M'); - $wife=$this->wife ? $this->wife : new WT_Person('1 SEX F'); + $husb=$this->husb ? $this->husb : new WT_Individual('M', '1 SEX M', null, $this->gedcom_id); + $wife=$this->wife ? $this->wife : new WT_Individual('F', '1 SEX F', null, $this->gedcom_id); // Check the script used by each name, so we can match cyrillic with cyrillic, greek with greek, etc. $husb_names=$husb->getAllNames(); foreach ($husb_names as $n=>$husb_name) { diff --git a/library/WT/Gedcom/Code/Adop.php b/library/WT/Gedcom/Code/Adop.php index 5a1d9edd79..4b10b4dbcb 100644 --- a/library/WT/Gedcom/Code/Adop.php +++ b/library/WT/Gedcom/Code/Adop.php @@ -2,7 +2,7 @@ // Functions and logic for GEDCOM "PEDI" codes // // webtrees: Web based Family History software -// Copyright (C) 2011 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ class WT_Gedcom_Code_Adop { // Translate a code, for an (optional) record public static function getValue($type, $record=null) { - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $sex=$record->getSex(); } else { $sex='U'; diff --git a/library/WT/Gedcom/Code/Name.php b/library/WT/Gedcom/Code/Name.php index a5ad95f06f..20470b12ed 100644 --- a/library/WT/Gedcom/Code/Name.php +++ b/library/WT/Gedcom/Code/Name.php @@ -2,7 +2,7 @@ // Functions and logic for GEDCOM "NAME" codes // // webtrees: Web based Family History software -// Copyright (C) 2011 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ class WT_Gedcom_Code_Name { // Translate a code, for an (optional) record public static function getValue($type, $record=null) { - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $sex=$record->getSex(); } else { $sex='U'; diff --git a/library/WT/Gedcom/Code/Pedi.php b/library/WT/Gedcom/Code/Pedi.php index 9b8a835ce1..783c59b4f1 100644 --- a/library/WT/Gedcom/Code/Pedi.php +++ b/library/WT/Gedcom/Code/Pedi.php @@ -2,7 +2,7 @@ // Functions and logic for GEDCOM "PEDI" codes // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ class WT_Gedcom_Code_Pedi { // Translate a code, for an optional record public static function getValue($type, $record=null) { - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $sex=$record->getSex(); } else { $sex='U'; diff --git a/library/WT/Gedcom/Code/Rela.php b/library/WT/Gedcom/Code/Rela.php index d4faa8f49c..0f53c835b8 100644 --- a/library/WT/Gedcom/Code/Rela.php +++ b/library/WT/Gedcom/Code/Rela.php @@ -2,7 +2,7 @@ // Functions and logic for GEDCOM "RELA" codes // // webtrees: Web based Family History software -// Copyright (C) 2011 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ class WT_Gedcom_Code_Rela { // Translate a code, for an (optional) record public static function getValue($type, $record=null) { - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $sex=$record->getSex(); } else { $sex='U'; diff --git a/library/WT/Gedcom/Tag.php b/library/WT/Gedcom/Tag.php index 83a62af317..d79b92b753 100644 --- a/library/WT/Gedcom/Tag.php +++ b/library/WT/Gedcom/Tag.php @@ -2,7 +2,7 @@ // Static GEDCOM data for Tags // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -102,7 +102,7 @@ class WT_Gedcom_Tag { // Translate a tag, for an (optional) record public static function getLabel($tag, $record=null) { - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { $sex=$record->getSex(); } else { $sex='U'; @@ -879,12 +879,6 @@ class WT_Gedcom_Tag { return $facts; } - // Get a list of reference facts that will be displayed in the "Extra information" sidebar module, and at the same time excluded from the personal_facts module - public static function getReferenceFacts() { - return array('CHAN', 'IDNO', 'RFN', 'AFN', 'REFN', 'RIN', '_UID', 'SSN'); - } - - ////////////////////////////////////////////////////////////////////////////// // Definitions for Object, File, Format, Types ////////////////////////////////////////////////////////////////////////////// diff --git a/library/WT/GedcomRecord.php b/library/WT/GedcomRecord.php index 2b67f6caa4..67fbca8730 100644 --- a/library/WT/GedcomRecord.php +++ b/library/WT/GedcomRecord.php @@ -30,305 +30,265 @@ if (!defined('WT_WEBTREES')) { class WT_GedcomRecord { const RECORD_TYPE = 'UNKNOWN'; + const SQL_FETCH = "SELECT o_gedcom FROM `##other` WHERE o_id=? AND o_file=?"; const URL_PREFIX = 'gedrecord.php?pid='; - protected $xref =null; // The record identifier - public $ged_id =null; // The gedcom file, only set if this record comes from the database - protected $_gedrec =null; // Raw gedcom text (unprivatised) - private $gedrec =null; // Raw gedcom text (privatised) - protected $facts =null; - protected $changeEvent=null; - private $disp_public=null; // Can we display details of this record to WT_PRIV_PUBLIC - private $disp_user =null; // Can we display details of this record to WT_PRIV_USER - private $disp_none =null; // Can we display details of this record to WT_PRIV_NONE - private $changed =false; // Is this a new record, pending approval + protected $xref = null; // The record identifier + protected $gedcom_id = null; // The gedcom file + protected $gedcom = null; // GEDCOM data (before any pending edits) + protected $pending = null; // GEDCOM data (after any pending edits) - // Cached results from various functions. - protected $_getAllNames =null; - protected $_getPrimaryName =null; - protected $_getSecondaryName=null; + protected $facts = null; // Array of WT_Fact objects (from $gedcom/$pending) - // Create a GedcomRecord object from either raw GEDCOM data or a database row - public function __construct($data) { - if (is_array($data)) { - // Construct from a row from the database - $this->xref =$data['xref']; - $this->ged_id =$data['ged_id']; - $this->_gedrec=$data['gedrec']; - } else { - // Construct from raw GEDCOM data - $this->_gedrec=$data; - if (preg_match('/^0 (?:@('.WT_REGEX_XREF.')@ )?('.WT_REGEX_TAG.')/', $data, $match)) { - $this->xref=$match[1]; - $this->ged_id=WT_GED_ID; - } - } - } + private $disp_public = null; // Can we display details of this record to WT_PRIV_PUBLIC + private $disp_user = null; // Can we display details of this record to WT_PRIV_USER + private $disp_none = null; // Can we display details of this record to WT_PRIV_NONE - // Get an instance of a GedcomRecord. We either specify - // an XREF (in the current gedcom), or we can provide a row - // from the database (if we anticipate the record hasn't - // been fetched previously). - static public function getInstance($data) { - global $gedcom_record_cache, $GEDCOM; - static $pending_record_cache; + // Cached results from various functions. + protected $_getAllNames = null; + protected $_getPrimaryName = null; + protected $_getSecondaryName = null; + + // Allow getInstance() to return references to existing objects + private static $gedcom_record_cache; + // Fetch all pending edits in one database query + private static $pending_record_cache; - $is_pending=false; // Did this record come from a pending edit + // Create a GedcomRecord object from raw GEDCOM data. + // $gedcom is an empty string for new/pending records + // $pending is null for a record with no pending edits + // $pending is an empty string for records with pending deletions + public function __construct($xref, $gedcom, $pending, $gedcom_id) { + $this->xref = $xref; + $this->gedcom = $gedcom; + $this->pending = $pending; + $this->gedcom_id = $gedcom_id; - if (is_array($data)) { - $ged_id=$data['ged_id']; - $pid =$data['xref']; + // Split the record into facts + if ($gedcom) { + $gedcom_facts = preg_split('/\n(?=1)/s', $gedcom); + array_shift($gedcom_facts); + } else { + $gedcom_facts = array(); + } + if ($pending) { + $pending_facts = preg_split('/\n(?=1)/s', $pending); + array_shift($pending_facts); } else { - $ged_id=get_id_from_gedcom($GEDCOM); - $pid =$data; + $pending_facts = array(); } - // Check the cache first - if (isset($gedcom_record_cache[$pid][$ged_id])) { - return $gedcom_record_cache[$pid][$ged_id]; + $this->facts = array(); + + foreach ($gedcom_facts as $gedcom_fact) { + $fact = new WT_Fact($gedcom_fact, $this, md5($gedcom_fact)); + if ($pending !== null && !in_array($gedcom_fact, $pending_facts)) { + $fact->setIsOld(); + } + $this->facts[] = $fact; + } + foreach ($pending_facts as $pending_fact) { + if (!in_array($pending_fact, $gedcom_facts)) { + $fact = new WT_Fact($pending_fact, $this, md5($pending_fact)); + $fact->setIsNew(); + $this->facts[] = $fact; + } } + } - // Look for the record in the database - if (!is_array($data)) { - $data=static::fetchGedcomRecord($pid, $ged_id); + // Get an instance of a GedcomRecord object. For single records, + // we just receive the XREF. For bulk records (such as lists + // and search results) we can receive the GEDCOM data as well. + static public function getInstance($xref, $gedcom_id=WT_GED_ID, $gedcom=null) { + // Is this record already in the cache? + if (isset(self::$gedcom_record_cache[$xref][$gedcom_id])) { + return self::$gedcom_record_cache[$xref][$gedcom_id]; + } - // If we can edit, then we also need to be able to see pending records. - // Otherwise relationship privacy rules will not allow us to see - // newly added records. - if (WT_USER_CAN_EDIT) { - if (!isset($pending_record_cache[$ged_id])) { - // Fetch all pending records in one database query - $pending_record_cache[$ged_id]=array(); - $rows = WT_DB::prepare( - "SELECT xref, new_gedcom FROM `##change` WHERE status='pending' AND gedcom_id=?" - )->execute(array($ged_id))->fetchAll(); - foreach ($rows as $row) { - $pending_record_cache[$ged_id][$row->xref] = $row->new_gedcom; - } - } + // Do we need to fetch the record from the database? + if ($gedcom === null) { + $gedcom = static::fetchGedcomRecord($xref, $gedcom_id); + } - if (isset($pending_record_cache[$ged_id][$pid])) { - // A pending edit exists for this record - $tmp = $pending_record_cache[$ged_id][$pid]; - // $tmp can be an empty string, indicating the record has - // a pending deletion. Ignore this, as we handle pending - // deletions separately. - if ($tmp) { - $is_pending=true; - $data=$tmp; - } + // If we can edit, then we also need to be able to see pending records. + if (WT_USER_CAN_EDIT) { + if (!isset(self::$pending_record_cache[$gedcom_id])) { + // Fetch all pending records in one database query + self::$pending_record_cache[$gedcom_id]=array(); + $rows = WT_DB::prepare( + "SELECT xref, new_gedcom FROM `##change` WHERE status='pending' AND gedcom_id=?" + )->execute(array($gedcom_id))->fetchAll(); + foreach ($rows as $row) { + self::$pending_record_cache[$gedcom_id][$row->xref] = $row->new_gedcom; } } - // If we still didn't find it, it doesn't exist - if (!$data) { - return null; + if (isset(self::$pending_record_cache[$gedcom_id][$xref])) { + // A pending edit exists for this record + $pending = self::$pending_record_cache[$gedcom_id][$xref]; + } else { + $pending = null; } + } else { + // There are no pending changes for this record + $pending = null; + } + + // No such record exists + if ($gedcom === null && $pending === null) { + return null; } // Create the object - if (is_array($data)) { - $type=$data['type']; - } elseif (preg_match('/^0 @'.WT_REGEX_XREF.'@ ('.WT_REGEX_TAG.')/', $data, $match)) { - $type=$match[1]; + if (preg_match('/^0 @' . WT_REGEX_XREF . '@ (' . WT_REGEX_TAG . ')/', $gedcom.$pending, $match)) { + $type = $match[1]; } else { - $type=''; + throw new Exception('Unrecognised GEDCOM record: ' . $gedcom); } + switch($type) { case 'INDI': - $object=new WT_Person($data); + $record = new WT_Individual($xref, $gedcom, $pending, $gedcom_id); break; case 'FAM': - $object=new WT_Family($data); + $record = new WT_Family($xref, $gedcom, $pending, $gedcom_id); break; case 'SOUR': - $object=new WT_Source($data); + $record = new WT_Source($xref, $gedcom, $pending, $gedcom_id); break; case 'OBJE': - $object=new WT_Media($data); + $record = new WT_Media($xref, $gedcom, $pending, $gedcom_id); break; case 'REPO': - $object=new WT_Repository($data); + $record = new WT_Repository($xref, $gedcom, $pending, $gedcom_id); break; case 'NOTE': - $object=new WT_Note($data); + $record = new WT_Note($xref, $gedcom, $pending, $gedcom_id); break; default: - $object=new WT_GedcomRecord($data); - break; - } - - // This is an object from the database, so indicate which gedcom it comes from. - $object->ged_id=$ged_id; - - if ($is_pending) { - $object->setChanged(true); + throw new Exception('No support for GEDCOM record type: ' . $type); } // Store it in the cache - $gedcom_record_cache[$object->xref][$object->ged_id]=&$object; - return $object; + self::$gedcom_record_cache[$xref][$gedcom_id] = $record; + + return $record; } - private static function fetchGedcomRecord($xref, $ged_id) { + private static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; // We don't know what type of object this is. Try each one in turn. - $row=WT_Person::fetchGedcomRecord($xref, $ged_id); - if ($row) { - return $row; + $data = WT_Individual::fetchGedcomRecord($xref, $gedcom_id); + if ($data) { + return $data; } - $row=WT_Family::fetchGedcomRecord($xref, $ged_id); - if ($row) { - return $row; + $data = WT_Family::fetchGedcomRecord($xref, $gedcom_id); + if ($data) { + return $data; } - $row=WT_Source::fetchGedcomRecord($xref, $ged_id); - if ($row) { - return $row; + $data = WT_Source::fetchGedcomRecord($xref, $gedcom_id); + if ($data) { + return $data; } - $row=WT_Repository::fetchGedcomRecord($xref, $ged_id); - if ($row) { - return $row; + $data = WT_Repository::fetchGedcomRecord($xref, $gedcom_id); + if ($data) { + return $data; } - $row=WT_Media::fetchGedcomRecord($xref, $ged_id); - if ($row) { - return $row; + $data = WT_Media::fetchGedcomRecord($xref, $gedcom_id); + if ($data) { + return $data; } - $row=WT_Note::fetchGedcomRecord($xref, $ged_id); - if ($row) { - return $row; + $data = WT_Note::fetchGedcomRecord($xref, $gedcom_id); + if ($data) { + return $data; } // Some other type of record... if (is_null($statement)) { - $statement=WT_DB::prepare( - "SELECT o_type AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec ". - "FROM `##other` WHERE o_id=? AND o_file=? AND o_type NOT IN ('REPO', 'NOTE')" - ); + $statement=WT_DB::prepare("SELECT o_gedcom FROM `##other` WHERE o_id=? AND o_file=?"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } - /** - * get the xref - * @return string returns the person ID - */ + // XREF public function getXref() { return $this->xref; } - /** - * get the gedcom file - * @return string returns the person ID - */ - public function getGedId() { - return $this->ged_id; + + // GEDCOM ID + public function getGedcomId() { + return $this->gedcom_id; } - /** - * get gedcom record - */ - public function getGedcomRecord() { - if ($this->gedrec===null) { - list($this->gedrec)=$this->privatizeGedcom(WT_USER_ACCESS_LEVEL); + // Application code should access data via WT_Fact objects + public function getGedcom() { + if ($this->pending === null) { + return $this->gedcom; + } else { + return $this->pending; } - return $this->gedrec; - } - /** - * set gedcom record - */ - public function setGedcomRecord($gcRec) { - $this->gedrec = $gcRec; } - /** - * set if this is a changed record from the gedcom file - * @param boolean $changed - */ - public function setChanged($changed) { - $this->changed = $changed; + + // Does this record have a pending change? + public function isNew() { + return $this->pending !== null; } - /** - * get if this is a changed record from the gedcom file - * @return boolean - */ - public function getChanged() { - return $this->changed; + + // Does this record have a pending deletion? + public function isOld() { + return $this->pending === ''; } - /** - * check if this object is equal to the given object - * @param GedcomRecord $obj - */ + // Are two records the same? public function equals($obj) { - return !is_null($obj) && $this->xref==$obj->getXref(); + return $obj && $this->xref==$obj->getXref(); } - // Generate a URL to this record, suitable for use in HTML + // Generate a URL to this record, suitable for use in HTML, etc. public function getHtmlUrl() { - return self::_getLinkUrl(static::URL_PREFIX, '&'); + return $this->_getLinkUrl(static::URL_PREFIX, '&'); } // Generate a URL to this record, suitable for use in javascript, HTTP headers, etc. public function getRawUrl() { - return self::_getLinkUrl(static::URL_PREFIX, '&'); + return $this->_getLinkUrl(static::URL_PREFIX, '&'); } - private function _getLinkUrl($link, $separator) { - if ($this->ged_id) { - // If the record was created from the database, we know the gedcom - return $link.$this->getXref().$separator.'ged='.rawurlencode(get_gedcom_from_id($this->ged_id)); - } else { - // If the record was created from a text string, assume the current gedcom - return $link.$this->getXref().$separator.'ged='.WT_GEDURL; - } - } - - /** - * return an absolute url for linking to this record from another site - * - */ + // Generate an absolute URL for this record, suitable for sitemap.xml, RSS feeds, etc. public function getAbsoluteLinkUrl() { - return WT_SERVER_NAME.WT_SCRIPT_PATH.$this->getHtmlUrl(); + return WT_SERVER_NAME . WT_SCRIPT_PATH . $this->getHtmlUrl(); } - /** - * check if this record has been marked for deletion - * @return boolean - */ - public function isMarkedDeleted() { - $tmp=WT_DB::prepare( - "SELECT new_gedcom". - " FROM `##change`". - " WHERE status='pending' AND gedcom_id=? AND xref=?". - " ORDER BY change_id desc". - " LIMIT 1" - )->execute(array($this->ged_id, $this->xref))->fetchOne(); - - return $tmp===''; + private function _getLinkUrl($link, $separator) { + if ($this->gedcom_id == WT_GED_ID) { + return $link . $this->getXref() . $separator . 'ged=' . WT_GEDURL; + } else { + return $link . $this->getXref() . $separator . 'ged=' . rawurlencode(get_gedcom_from_id($this->gedcom_id)); + } } // Work out whether this record can be shown to a user with a given access level - private function _canDisplayDetails($access_level) { - global $person_privacy, $HIDE_LIVE_PEOPLE, $PRIVACY_CHECKS; + private function _canShow($access_level) { + global $person_privacy, $HIDE_LIVE_PEOPLE; - //-- keep a count of how many times we have checked for privacy - ++$PRIVACY_CHECKS; // This setting would better be called "$ENABLE_PRIVACY" if (!$HIDE_LIVE_PEOPLE) { return true; } // We should always be able to see our own record (unless an admin is applying download restrictions) - if ($this->getXref()==WT_USER_GEDCOM_ID && $this->getGedId()==WT_GED_ID && $access_level==WT_USER_ACCESS_LEVEL) { + if ($this->getXref()==WT_USER_GEDCOM_ID && $this->getGedcomId()==WT_GED_ID && $access_level==WT_USER_ACCESS_LEVEL) { return true; } // Does this record have a RESN? - if (strpos($this->_gedrec, "\n1 RESN confidential")) { + if (strpos($this->gedcom, "\n1 RESN confidential")) { return WT_PRIV_NONE>=$access_level; } - if (strpos($this->_gedrec, "\n1 RESN privacy")) { + if (strpos($this->gedcom, "\n1 RESN privacy")) { return WT_PRIV_USER>=$access_level; } - if (strpos($this->_gedrec, "\n1 RESN none")) { + if (strpos($this->gedcom, "\n1 RESN none")) { return true; } @@ -343,11 +303,11 @@ class WT_GedcomRecord { } // Different types of record have different privacy rules - return $this->_canDisplayDetailsByType($access_level); + return $this->_canShowByType($access_level); } // Each object type may have its own special rules, and re-implement this function. - protected function _canDisplayDetailsByType($access_level) { + protected function _canShowByType($access_level) { global $global_facts; if (isset($global_facts[static::RECORD_TYPE])) { @@ -360,23 +320,23 @@ class WT_GedcomRecord { } // Can the details of this record be shown? - public function canDisplayDetails($access_level=WT_USER_ACCESS_LEVEL) { + public function canShow($access_level=WT_USER_ACCESS_LEVEL) { // CACHING: this function can take three different parameters, // and therefore needs three different caches for the result. switch ($access_level) { case WT_PRIV_PUBLIC: // visitor if ($this->disp_public===null) { - $this->disp_public=$this->_canDisplayDetails(WT_PRIV_PUBLIC); + $this->disp_public=$this->_canShow(WT_PRIV_PUBLIC); } return $this->disp_public; case WT_PRIV_USER: // member if ($this->disp_user===null) { - $this->disp_user=$this->_canDisplayDetails(WT_PRIV_USER); + $this->disp_user=$this->_canShow(WT_PRIV_USER); } return $this->disp_user; case WT_PRIV_NONE: // admin if ($this->disp_none===null) { - $this->disp_none=$this->_canDisplayDetails(WT_PRIV_NONE); + $this->disp_none=$this->_canShow(WT_PRIV_NONE); } return $this->disp_none; case WT_PRIV_HIDE: // hidden from admins @@ -390,15 +350,13 @@ class WT_GedcomRecord { } // Can the name of this record be shown? - public function canDisplayName($access_level=WT_USER_ACCESS_LEVEL) { - return $this->canDisplayDetails($access_level); + public function canShowName($access_level=WT_USER_ACCESS_LEVEL) { + return $this->canShow($access_level); } // Can we edit this record? - // We use the unprivatized _gedrec as we must take account - // of the RESN tag, even if we are not permitted to see it. public function canEdit() { - return WT_USER_GEDCOM_ADMIN || WT_USER_CAN_EDIT && strpos($this->_gedrec, "\n1 RESN locked")===false; + return WT_USER_GEDCOM_ADMIN || WT_USER_CAN_EDIT && strpos($this->gedcom, "\n1 RESN locked")===false; } // Remove private data from the raw gedcom record. @@ -408,28 +366,25 @@ class WT_GedcomRecord { if ($access_level==WT_PRIV_HIDE) { // We may need the original record, for example when downloading a GEDCOM or clippings cart - return array($this->_gedrec, ''); - } elseif ($this->canDisplayDetails($access_level)) { + return array($this->gedcom, ''); + } elseif ($this->canShow($access_level)) { // The record is not private, but the individual facts may be. // Include the entire first line (for NOTE records) - list($gedrec)=explode("\n", $this->_gedrec, 2); + list($gedrec)=explode("\n", $this->gedcom, 2); - $private_gedrec=''; // Check each of the sub facts for access - preg_match_all('/\n1 .*(?:\n[2-9].*)*/', $this->_gedrec, $matches); + preg_match_all('/\n1 .*(?:\n[2-9].*)*/', $this->gedcom, $matches); foreach ($matches[0] as $match) { - if (canDisplayFact($this->xref, $this->ged_id, $match, $access_level)) { + if (canDisplayFact($this->xref, $this->gedcom_id, $match, $access_level)) { $gedrec.=$match; - } else { - $private_gedrec.=$match; } } - return array($gedrec, $private_gedrec); + return $gedrec; } else { // We cannot display the details, but we may be able to display // limited data, such as links to other records. - return array($this->createPrivateGedcomRecord($access_level), ''); + return $this->createPrivateGedcomRecord($access_level); } } @@ -440,10 +395,10 @@ class WT_GedcomRecord { // Convert a name record into sortable and full/display versions. This default // should be OK for simple record types. INDI/FAM records will need to redefine it. - protected function _addName($type, $value, $gedrec) { + protected function _addName($type, $value, $gedcom) { $this->_getAllNames[]=array( 'type'=>$type, - 'sort'=>preg_replace('/([0-9]+)/e', 'substr("000000000\\1", -10)', $value), + 'sort'=>preg_replace_callback('/([0-9]+)/', function($matches) { return str_pad($matches[0], 10, '0', STR_PAD_LEFT); }, $value), 'full'=>'<span dir="auto">'.htmlspecialchars($value).'</span>', // This is used for display 'fullNN'=>$value, // This goes into the database ); @@ -462,10 +417,10 @@ class WT_GedcomRecord { if (is_null($this->_getAllNames)) { $this->_getAllNames=array(); - if ($this->canDisplayName()) { + if ($this->canShowName()) { $sublevel=$level+1; $subsublevel=$sublevel+1; - if (preg_match_all("/^{$level} ({$fact}) (.+)((\n[{$sublevel}-9].+)*)/m", $this->getGedcomRecord(), $matches, PREG_SET_ORDER)) { + if (preg_match_all("/^{$level} ({$fact}) (.+)((\n[{$sublevel}-9].+)*)/m", $this->getGedcom(), $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { // Treat 1 NAME / 2 TYPE married the same as _MARNM if ($match[1]=='NAME' && strpos($match[3], "\n2 TYPE married")!==false) { @@ -581,20 +536,20 @@ class WT_GedcomRecord { // Allow native PHP functions such as array_intersect() to work with objects public function __toString() { - return $this->xref.'@'.$this->ged_id; + return $this->xref.'@'.$this->gedcom_id; } // Static helper function to sort an array of objects by name // Records whose names cannot be displayed are sorted at the end. static function Compare($x, $y) { - if ($x->canDisplayName()) { - if ($y->canDisplayName()) { + if ($x->canShowName()) { + if ($y->canShowName()) { return utf8_strcasecmp($x->getSortName(), $y->getSortName()); } else { return -1; // only $y is private } } else { - if ($y->canDisplayName()) { + if ($y->canShowName()) { return 1; // only $x is private } else { return 0; // both $x and $y private @@ -611,8 +566,8 @@ class WT_GedcomRecord { return $tmp; } else { if ( - preg_match('/^\d\d:\d\d:\d\d/', get_gedcom_value('DATE:TIME', 2, $chan_x->getGedcomRecord()).':00', $match_x) && - preg_match('/^\d\d:\d\d:\d\d/', get_gedcom_value('DATE:TIME', 2, $chan_y->getGedcomRecord()).':00', $match_y) + preg_match('/^\d\d:\d\d:\d\d/', get_gedcom_value('DATE:TIME', 2, $chan_x->getGedcom()).':00', $match_x) && + preg_match('/^\d\d:\d\d:\d\d/', get_gedcom_value('DATE:TIME', 2, $chan_y->getGedcom()).':00', $match_y) ) { return strcmp($match_x[0], $match_y[0]); } else { @@ -623,22 +578,22 @@ class WT_GedcomRecord { // Get variants of the name public function getFullName() { - if ($this->canDisplayName()) { - $tmp=$this->getAllNames(); + if ($this->canShowName()) { + $tmp = $this->getAllNames(); return $tmp[$this->getPrimaryName()]['full']; } else { return WT_I18N::translate('Private'); } } public function getSortName() { - // The sortable name is never displayed, no need to call canDisplayName() - $tmp=$this->getAllNames(); + // The sortable name is never displayed, no need to call canShowName() + $tmp = $this->getAllNames(); return $tmp[$this->getPrimaryName()]['sort']; } // Get the fullname in an alternative character set public function getAddName() { - if ($this->canDisplayName() && $this->getPrimaryName()!=$this->getSecondaryName()) { - $all_names=$this->getAllNames(); + if ($this->canShowName() && $this->getPrimaryName()!=$this->getSecondaryName()) { + $all_names = $this->getAllNames(); return $all_names[$this->getSecondaryName()]['full']; } else { return null; @@ -672,7 +627,7 @@ class WT_GedcomRecord { // Extract/format the first fact from a list of facts. public function format_first_major_fact($facts, $style) { - foreach ($this->getAllFactsByType(explode('|', $facts)) as $event) { + foreach ($this->getFacts($facts) as $event) { // Only display if it has a date or place (or both) if (($event->getDate()->isOK() || $event->getPlace()) && $event->canShow()) { switch ($style) { @@ -688,22 +643,22 @@ class WT_GedcomRecord { // Fetch the records that link to this one public function fetchLinkedIndividuals() { - return fetch_linked_indi($this->getXref(), static::RECORD_TYPE, $this->ged_id); + return fetch_linked_indi($this->getXref(), static::RECORD_TYPE, $this->gedcom_id); } public function fetchLinkedFamilies() { - return fetch_linked_fam($this->getXref(), static::RECORD_TYPE, $this->ged_id); + return fetch_linked_fam($this->getXref(), static::RECORD_TYPE, $this->gedcom_id); } public function fetchLinkedNotes() { - return fetch_linked_note($this->getXref(), static::RECORD_TYPE, $this->ged_id); + return fetch_linked_note($this->getXref(), static::RECORD_TYPE, $this->gedcom_id); } public function fetchLinkedSources() { - return fetch_linked_sour($this->getXref(), static::RECORD_TYPE, $this->ged_id); + return fetch_linked_sour($this->getXref(), static::RECORD_TYPE, $this->gedcom_id); } public function fetchLinkedRepositories() { - return fetch_linked_repo($this->getXref(), static::RECORD_TYPE, $this->ged_id); + return fetch_linked_repo($this->getXref(), static::RECORD_TYPE, $this->gedcom_id); } public function fetchLinkedMedia() { - return fetch_linked_obje($this->getXref(), static::RECORD_TYPE, $this->ged_id); + return fetch_linked_obje($this->getXref(), static::RECORD_TYPE, $this->gedcom_id); } // Get all attributes (e.g. DATE or PLAC) from an event (e.g. BIRT or MARR). @@ -712,154 +667,48 @@ class WT_GedcomRecord { // calendars, place-names in both latin and hebrew character sets, etc. // It also allows us to combine dates/places from different events in the summaries. public function getAllEventDates($event) { - $dates=array(); - foreach ($this->getAllFactsByType($event) as $event) { + $dates = array(); + foreach ($this->getFacts($event) as $event) { if ($event->getDate()->isOK()) { - $dates[]=$event->getDate(); + $dates[] = $event->getDate(); } } return $dates; } public function getAllEventPlaces($event) { - $places=array(); - foreach ($this->getAllFactsByType($event) as $event) { - if (preg_match_all('/\n(?:2 PLAC|3 (?:ROMN|FONE|_HEB)) +(.+)/', $event->getGedcomRecord(), $ged_places)) { + $places = array(); + foreach ($this->getFacts($event) as $event) { + if (preg_match_all('/\n(?:2 PLAC|3 (?:ROMN|FONE|_HEB)) +(.+)/', $event->getGedcom(), $ged_places)) { foreach ($ged_places[1] as $ged_place) { - $places[]=$ged_place; + $places[] = $ged_place; } } } return $places; } - // Get the first WT_Event for the given fact type + // Get the first WT_Fact for the given fact type public function getFactByType($tag) { foreach ($this->getFacts() as $fact) { - if ($fact->getTag()==$tag) { + if ($fact->getTag() == $tag) { return $fact; } } return null; } - // Return an array of events that match the given types - public function getAllFactsByType($tags) { - if (is_string($tags)) { - $tags = array($tags); - } - $facts = array(); - foreach ($tags as $tag) { - foreach ($this->getFacts() as $fact) { - if ($fact->getTag()==$tag) { - $facts[]=$fact; - } - } - } - return $facts; - } - - /** - * returns an array of all of the facts - * @return Array - */ - public function getFacts() { - $this->parseFacts(); - return $this->facts; - } - - /** - * Get the CHAN event for this record - * - * @return WT_Event - */ - public function getChangeEvent() { - if (is_null($this->changeEvent)) { - $this->changeEvent = $this->getFactByType('CHAN'); - } - return $this->changeEvent; - } - - /** - * Parse the facts from the record - */ - public function parseFacts() { - //-- only run this function once - if (!is_null($this->facts) && is_array($this->facts)) { - return; - } - $this->facts=array(); - //-- don't run this function if privacy does not allow viewing of details - if (!$this->canDisplayDetails()) { - return; - } - //-- find all the fact information - $indilines = explode("\n", $this->getGedcomRecord()); // -- find the number of lines in the individuals record - $lct = count($indilines); - $factrec = ''; // -- complete fact record - $line = ''; // -- temporary line buffer - $linenum=1; - for ($i=1; $i<=$lct; $i++) { - if ($i<$lct) { - $line = $indilines[$i]; - } else { - $line=' '; - } - if (empty($line)) { - $line=' '; - } - if ($i==$lct||$line{0}==1) { - if ($i>1) { - $this->facts[] = new WT_Event($factrec, $this, $linenum); - } - $factrec = $line; - $linenum = $i; - } - else $factrec .= "\n".$line; - } - } - - /** - * Merge the facts from another GedcomRecord object into this object - * for generating a diff view - * @param GedcomRecord $diff the record to compare facts with - */ - public function diffMerge($diff) { - if (is_null($diff)) { - return; - } - $this->parseFacts(); - $diff->parseFacts(); - - //-- update old facts - foreach ($this->facts as $key=>$event) { - $found = false; - foreach ($diff->facts as $indexval => $newevent) { - $newfact = $newevent->getGedcomRecord(); - $newfact=preg_replace("/\\\/", '/', $newfact); - if (trim($newfact)==trim($event->getGedcomRecord())) { - $found = true; - break; - } - } - if (!$found) { - $this->facts[$key]->setIsOld(); - } - } - //-- look for new facts - foreach ($diff->facts as $key=>$newevent) { - $found = false; - foreach ($this->facts as $indexval => $event) { - $newfact = $newevent->getGedcomRecord(); - $newfact=preg_replace("/\\\/", '/', $newfact); - if (trim($newfact)==trim($event->getGedcomRecord())) { - $found = true; - break; + // The facts and events for this record + public function getFacts($filter=null) { + if ($filter === null) { + return $this->facts; + } else { + $facts=array(); + foreach ($this->facts as $fact) { + if (preg_match('/^' . $filter . '$/', $fact->getTag())) { + $facts[] = $fact; } } - if (!$found) { - $newevent->setIsNew(); - $this->facts[]=$newevent; - } + return $facts; } } @@ -871,26 +720,18 @@ class WT_GedcomRecord { $srec = $srec[0]; return get_gedcom_value('DATE', 2, $srec); } - public function getEventSource($event) { - $srec = $this->getAllEvents($event); - if (!$srec) { - return ''; - } - $srec = $srec[0]; - return get_sub_record('SOUR', 2, $srec); - } ////////////////////////////////////////////////////////////////////////////// // Get the last-change timestamp for this record, either as a formatted string // (for display) or as a unix timestamp (for sorting) ////////////////////////////////////////////////////////////////////////////// public function LastChangeTimestamp($sorting=false) { - $chan = $this->getChangeEvent(); + $chan = $this->getFactByType('CHAN'); if ($chan) { // The record does have a CHAN event $d = $chan->getDate()->MinDate(); - if (preg_match('/^(\d\d):(\d\d):(\d\d)/', get_gedcom_value('DATE:TIME', 2, $chan->getGedcomRecord()).':00', $match)) { + if (preg_match('/^(\d\d):(\d\d):(\d\d)/', get_gedcom_value('DATE:TIME', 2, $chan->getGedcom()).':00', $match)) { $t=mktime((int)$match[1], (int)$match[2], (int)$match[3], (int)$d->Format('%n'), (int)$d->Format('%j'), (int)$d->Format('%Y')); } else { $t=mktime(0, 0, 0, (int)$d->Format('%n'), (int)$d->Format('%j'), (int)$d->Format('%Y')); @@ -914,16 +755,192 @@ class WT_GedcomRecord { // Get the last-change user for this record ////////////////////////////////////////////////////////////////////////////// public function LastChangeUser() { - $chan = $this->getChangeEvent(); + $chan = $this->getFactByType('CHAN'); if (is_null($chan)) { return ' '; } - $chan_user = $chan->getValue('_WT_USER'); + $chan_user = $chan->getAttribute('_WT_USER'); if (empty($chan_user)) { return ' '; } return $chan_user; } + + ////////////////////////////////////////////////////////////////////////////// + // CRUD operations + ////////////////////////////////////////////////////////////////////////////// + + // Replace a (possibly empty) fact with a new (possibly empty) fact. + // This allows create/update/delete of individual facts + public function updateFact($fact_id, $gedcom, $update_chan) { + if (strpos("\r", $gedcom)!==false) { + // MSDOS line endings will break things in horrible ways + throw new Exception('Evil line endings found in WT_GedcomRecord::updateRecord(' . $gedcom . ')'); + } + if ($this->pending==='') { + throw new Exception('Cannot edit a deleted record'); + } + if ($gedcom && !preg_match('/^1 ' . WT_REGEX_TAG . '/', $gedcom)) { + throw new Exception('Invalid GEDCOM data passed to WT_GedcomRecord::updateFact()'); + } + + if ($this->pending) { + $old_gedcom = $this->pending; + } else { + $old_gedcom = $this->gedcom; + } + + $new_gedcom = '0 @' . $this->getXref() . '@ ' . static::RECORD_TYPE; + $old_chan = $this->getFactByType('CHAN'); + // Replacing (or deleting) an existing fact + foreach ($this->getFacts() as $fact) { + if ($fact->getFactId() == $fact_id) { + if ($gedcom) { + $new_gedcom .= "\n" . $gedcom; + } + } elseif ($fact->getTag()!='CHAN' || !$update_chan) { + $new_gedcom .= "\n" . $fact->getGedcom(); + } + } + if ($update_chan) { + $new_gedcom .= "\n1 CHAN\n2 DATE " . date('d M Y') . "\n3 TIME " . date('H:i:s') . "\n2 _WT_USER " . WT_USER_NAME; + } + + // Adding a new fact + if (!$fact_id) { + $new_gedcom .= "\n" . $gedcom; + } + + if ($new_gedcom != $old_gedcom) { + // Save the changes + WT_DB::prepare( + "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, ?, ?, ?)" + )->execute(array( + $this->gedcom_id, + $this->xref, + $old_gedcom, + $new_gedcom, + WT_USER_ID + )); + + // Clear the cache + self::$gedcom_record_cache = null; + self::$pending_record_cache = null; + + if (get_user_setting(WT_USER_ID, 'auto_accept')) { + accept_all_changes($xref, $ged_id); + } + } + } + + static public function createRecord($gedcom, $gedcom_id) { + if (preg_match('/^0 @(' . WT_REGEX_XREF . ')@ (' . WT_REGEX_TAG . ')/', $gedcom, $match)) { + $xref = $match[1]; + $type = $match[2]; + } else { + throw new Exception('Invalid argument to WT_GedcomRecord::createRecord(' . $gedcom . ')'); + } + if (strpos("\r", $gedcom)!==false) { + // MSDOS line endings will break things in horrible ways + throw new Exception('Evil line endings found in WT_GedcomRecord::createRecord(' . $gedcom . ')'); + } + + // webtrees creates XREFs containing digits. Anything else (e.g. “new”) is just a placeholder. + if (!preg_match('/\d/', $xref)) { + $xref = get_new_xref($type); + $gedcom = preg_replace('/^0 @(' . WT_REGEX_XREF . ')@/', '0 @' . $xref . '@', $gedcom); + } + + // Create a change record, if not already present + if (!preg_match('/\n1 CHAN/', $gedcom)) { + $gedcom .= "\n1 CHAN\n2 DATE " . date('d M Y') . "\n3 TIME " . date('H:i:s') . "\n2 _WT_USER " . WT_USER_NAME; + } + + // Create a pending change + WT_DB::prepare( + "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, '', ?, ?)" + )->execute(array( + $gedcom_id, + $xref, + $gedcom, + $gedcom_id + )); + + // Accept this pending change + if (get_user_setting(WT_USER_ID, 'auto_accept')) { + accept_all_changes($this->xref, $this->gedcom_id); + } + + // Clear this record from the cache + self::$pending_record_cache = null; + + AddToLog('Create: ' . $type . ' ' . $xref, 'edit'); + + // Return the newly created record + return WT_GedcomRecord::getInstance($xref); + } + + private static function readRecord($xref, $gedcom_id) { + return WT_DB::prepare(static::SQL_FETCH)->execute(array($xref, $gedcom_id))->fetchOne(); + } + + public function updateRecord($gedcom, $update_chan) { + if (strpos("\r", $gedcom)!==false) { + // MSDOS line endings will break things in horrible ways + throw new Exception('Evil line endings found in WT_GedcomRecord::updateRecord(' . $gedcom . ')'); + } + + // Update the CHAN record + if ($update_chan) { + $gedcom = preg_replace('/\n1 CHAN(\n[2-9].*)*/', '', $gedcom); + $gedcom .= "\n1 CHAN\n2 DATE " . date('d M Y') . "\n3 TIME " . date('H:i:s') . "\n2 _WT_USER " . WT_USER_NAME; + } + + // Create a pending change + WT_DB::prepare( + "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, ?, ?, ?)" + )->execute(array( + $this->gedcom_id, + $this->xref, + $this->getGedcom(), + $gedcom, + WT_USER_ID + )); + + // Accept this pending change + if (get_user_setting(WT_USER_ID, 'auto_accept')) { + accept_all_changes($this->xref, $this->gedcom_id); + } + + // Clear the cache + self::$gedcom_record_cache = null; + self::$pending_record_cache = null; + + AddToLog('Update: ' . self::RECORD_TYPE . ' ' . $this->xref, 'edit'); + } + + public function deleteRecord() { + // Create a pending change + WT_DB::prepare( + "INSERT INTO `##change` (gedcom_id, xref, old_gedcom, new_gedcom, user_id) VALUES (?, ?, ?, '', ?)" + )->execute(array( + $this->gedcom_id, + $this->xref, + $this->getGedcom(), + WT_USER_ID + )); + + // Accept this pending change + if (get_user_setting(WT_USER_ID, 'auto_accept')) { + accept_all_changes($this->xref, $this->gedcom_id); + } + + // Clear the cache + self::$gedcom_record_cache = null; + self::$pending_record_cache = null; + + AddToLog('Delete: ' . self::RECORD_TYPE . ' ' . $this->xref, 'edit'); + } } diff --git a/library/WT/Person.php b/library/WT/Individual.php index a2ab1229af..babefa9fbe 100644 --- a/library/WT/Person.php +++ b/library/WT/Individual.php @@ -1,5 +1,5 @@ <?php -// Class file for a person +// Class file for an individual // // webtrees: Web based Family History software // Copyright (C) 2013 webtrees development team. @@ -28,15 +28,11 @@ if (!defined('WT_WEBTREES')) { exit; } -class WT_Person extends WT_GedcomRecord { +class WT_Individual extends WT_GedcomRecord { const RECORD_TYPE = 'INDI'; + const SQL_FETCH = "SELECT i_gedcom FROM `##individuals` WHERE i_id=? AND i_file=?"; const URL_PREFIX = 'individual.php?pid='; - var $indifacts = array(); - var $otherfacts = array(); - var $globalfacts = array(); - var $mediafacts = array(); - var $facts_parsed = false; var $label = ''; var $highlightedimage = null; var $file = ''; @@ -59,21 +55,21 @@ class WT_Person extends WT_GedcomRecord { private $_getEstimatedDeathDate=null; // Can the name of this record be shown? - public function canDisplayName($access_level=WT_USER_ACCESS_LEVEL) { + public function canShowName($access_level=WT_USER_ACCESS_LEVEL) { global $SHOW_LIVING_NAMES; - return $SHOW_LIVING_NAMES>=$access_level || $this->canDisplayDetails($access_level); + return $SHOW_LIVING_NAMES>=$access_level || $this->canShow($access_level); } // Implement person-specific privacy logic - protected function _canDisplayDetailsByType($access_level) { + protected function _canShowByType($access_level) { global $SHOW_DEAD_PEOPLE, $KEEP_ALIVE_YEARS_BIRTH, $KEEP_ALIVE_YEARS_DEATH; // Dead people... if ($SHOW_DEAD_PEOPLE>=$access_level && $this->isDead()) { $keep_alive=false; if ($KEEP_ALIVE_YEARS_BIRTH) { - preg_match_all('/\n1 (?:'.WT_EVENTS_BIRT.').*(?:\n[2-9].*)*(?:\n2 DATE (.+))/', $this->_gedrec, $matches, PREG_SET_ORDER); + preg_match_all('/\n1 (?:'.WT_EVENTS_BIRT.').*(?:\n[2-9].*)*(?:\n2 DATE (.+))/', $this->gedcom, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $date=new WT_Date($match[1]); if ($date->isOK() && $date->gregorianYear()+$KEEP_ALIVE_YEARS_BIRTH > date('Y')) { @@ -83,7 +79,7 @@ class WT_Person extends WT_GedcomRecord { } } if ($KEEP_ALIVE_YEARS_DEATH) { - preg_match_all('/\n1 (?:'.WT_EVENTS_DEAT.').*(?:\n[2-9].*)*(?:\n2 DATE (.+))/', $this->_gedrec, $matches, PREG_SET_ORDER); + preg_match_all('/\n1 (?:'.WT_EVENTS_DEAT.').*(?:\n[2-9].*)*(?:\n2 DATE (.+))/', $this->gedcom, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $date=new WT_Date($match[1]); if ($date->isOK() && $date->gregorianYear()+$KEEP_ALIVE_YEARS_DEATH > date('Y')) { @@ -97,8 +93,8 @@ class WT_Person extends WT_GedcomRecord { } } // Consider relationship privacy (unless an admin is applying download restrictions) - if (WT_USER_GEDCOM_ID && WT_USER_PATH_LENGTH && $this->getGedId()==WT_GED_ID && $access_level=WT_USER_ACCESS_LEVEL) { - $self = WT_Person::getInstance(WT_USER_GEDCOM_ID); + if (WT_USER_GEDCOM_ID && WT_USER_PATH_LENGTH && $this->getGedcomId()==WT_GED_ID && $access_level=WT_USER_ACCESS_LEVEL) { + $self = WT_Individual::getInstance(WT_USER_GEDCOM_ID); if ($self) { return get_relationship($this, $self, true, WT_USER_PATH_LENGTH)!==false; } @@ -114,9 +110,9 @@ class WT_Person extends WT_GedcomRecord { $rec='0 @'.$this->xref.'@ INDI'; if ($SHOW_LIVING_NAMES>=$access_level) { // Show all the NAME tags, including subtags - preg_match_all('/\n1 NAME.*(?:\n[2-9].*)*/', $this->_gedrec, $matches); + preg_match_all('/\n1 NAME.*(?:\n[2-9].*)*/', $this->gedcom, $matches); foreach ($matches[0] as $match) { - if (canDisplayFact($this->xref, $this->ged_id, $match, $access_level)) { + if (canDisplayFact($this->xref, $this->gedcom_id, $match, $access_level)) { $rec.=$match; } } @@ -124,31 +120,29 @@ class WT_Person extends WT_GedcomRecord { $rec.="\n1 NAME ".WT_I18N::translate('Private'); } // Just show the 1 FAMC/FAMS tag, not any subtags, which may contain private data - preg_match_all('/\n1 (?:FAMC|FAMS) @('.WT_REGEX_XREF.')@/', $this->_gedrec, $matches, PREG_SET_ORDER); + preg_match_all('/\n1 (?:FAMC|FAMS) @('.WT_REGEX_XREF.')@/', $this->gedcom, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $rela=WT_Family::getInstance($match[1]); - if ($rela && ($SHOW_PRIVATE_RELATIONSHIPS || $rela->canDisplayDetails($access_level))) { + if ($rela && ($SHOW_PRIVATE_RELATIONSHIPS || $rela->canShow($access_level))) { $rec.=$match[0]; } } // Don't privatize sex. - if (preg_match('/\n1 SEX [MFU]/', $this->_gedrec, $match)) { + if (preg_match('/\n1 SEX [MFU]/', $this->gedcom, $match)) { $rec.=$match[0]; } return $rec; } // Fetch the record from the database - protected static function fetchGedcomRecord($xref, $ged_id) { + protected static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; if ($statement===null) { - $statement=WT_DB::prepare( - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec ". - "FROM `##individuals` WHERE i_id=? AND i_file=?" - ); + $statement=WT_DB::prepare("SELECT i_gedcom FROM `##individuals` WHERE i_id=? AND i_file=?"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } // Static helper function to sort an array of people by birth date @@ -167,12 +161,12 @@ class WT_Person extends WT_GedcomRecord { global $MAX_ALIVE_AGE; // "1 DEAT Y" or "1 DEAT/2 DATE" or "1 DEAT/2 PLAC" - if (preg_match('/\n1 (?:'.WT_EVENTS_DEAT.')(?: Y|(?:\n[2-9].+)*\n2 (DATE|PLAC) )/', $this->_gedrec)) { + if (preg_match('/\n1 (?:'.WT_EVENTS_DEAT.')(?: Y|(?:\n[2-9].+)*\n2 (DATE|PLAC) )/', $this->gedcom)) { return true; } // If any event occured more than $MAX_ALIVE_AGE years ago, then assume the person is dead - if (preg_match_all('/\n2 DATE (.+)/', $this->_gedrec, $date_matches)) { + if (preg_match_all('/\n2 DATE (.+)/', $this->gedcom, $date_matches)) { foreach ($date_matches[1] as $date_match) { $date=new WT_Date($date_match); if ($date->isOK() && $date->MaxJD() <= WT_SERVER_JD - 365*$MAX_ALIVE_AGE) { @@ -181,7 +175,7 @@ class WT_Person extends WT_GedcomRecord { } // The individual has one or more dated events. All are less than $MAX_ALIVE_AGE years ago. // If one of these is a birth, the person must be alive. - if (preg_match('/\n1 BIRT(?:\n[2-9].+)*\n2 DATE /', $this->_gedrec)) { + if (preg_match('/\n1 BIRT(?:\n[2-9].+)*\n2 DATE /', $this->gedcom)) { return false; } } @@ -192,7 +186,7 @@ class WT_Person extends WT_GedcomRecord { foreach ($this->getChildFamilies(WT_PRIV_HIDE) as $family) { foreach ($family->getSpouses(WT_PRIV_HIDE) as $parent) { // Assume parents are no more than 45 years older than their children - preg_match_all('/\n2 DATE (.+)/', $parent->_gedrec, $date_matches); + preg_match_all('/\n2 DATE (.+)/', $parent->gedcom, $date_matches); foreach ($date_matches[1] as $date_match) { $date=new WT_Date($date_match); if ($date->isOK() && $date->MaxJD() <= WT_SERVER_JD - 365*($MAX_ALIVE_AGE+45)) { @@ -204,7 +198,7 @@ class WT_Person extends WT_GedcomRecord { // Check spouses foreach ($this->getSpouseFamilies(WT_PRIV_HIDE) as $family) { - preg_match_all('/\n2 DATE (.+)/', $family->_gedrec, $date_matches); + preg_match_all('/\n2 DATE (.+)/', $family->gedcom, $date_matches); foreach ($date_matches[1] as $date_match) { $date=new WT_Date($date_match); // Assume marriage occurs after age of 10 @@ -215,7 +209,7 @@ class WT_Person extends WT_GedcomRecord { // Check spouse dates $spouse=$family->getSpouse($this, WT_PRIV_HIDE); if ($spouse) { - preg_match_all('/\n2 DATE (.+)/', $spouse->_gedrec, $date_matches); + preg_match_all('/\n2 DATE (.+)/', $spouse->gedcom, $date_matches); foreach ($date_matches[1] as $date_match) { $date=new WT_Date($date_match); // Assume max age difference between spouses of 40 years @@ -226,7 +220,7 @@ class WT_Person extends WT_GedcomRecord { } // Check child dates foreach ($family->getChildren(WT_PRIV_HIDE) as $child) { - preg_match_all('/\n2 DATE (.+)/', $child->_gedrec, $date_matches); + preg_match_all('/\n2 DATE (.+)/', $child->gedcom, $date_matches); // Assume children born after age of 15 foreach ($date_matches[1] as $date_match) { $date=new WT_Date($date_match); @@ -237,7 +231,7 @@ class WT_Person extends WT_GedcomRecord { // Check grandchildren foreach ($child->getSpouseFamilies(WT_PRIV_HIDE) as $child_family) { foreach ($child_family->getChildren(WT_PRIV_HIDE) as $grandchild) { - preg_match_all('/\n2 DATE (.+)/', $grandchild->_gedrec, $date_matches); + preg_match_all('/\n2 DATE (.+)/', $grandchild->gedcom, $date_matches); // Assume grandchildren born after age of 30 foreach ($date_matches[1] as $date_match) { $date=new WT_Date($date_match); @@ -265,10 +259,10 @@ class WT_Person extends WT_GedcomRecord { $objectC = null; // Iterate over all of the media items for the person - preg_match_all('/\n(\d) OBJE @(' . WT_REGEX_XREF . ')@/', $this->getGedcomRecord(), $matches, PREG_SET_ORDER); + preg_match_all('/\n(\d) OBJE @(' . WT_REGEX_XREF . ')@/', $this->getGedcom(), $matches, PREG_SET_ORDER); foreach ($matches as $match) { $media = WT_Media::getInstance($match[2]); - if (!$media || !$media->canDisplayDetails() || $media->isExternal()) { + if (!$media || !$media->canShow() || $media->isExternal()) { continue; } $level = $match[1]; @@ -325,7 +319,7 @@ class WT_Person extends WT_GedcomRecord { */ function getBirthDate() { if (is_null($this->_getBirthDate)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach ($this->getAllBirthDates() as $date) { if ($date->isOK()) { $this->_getBirthDate=$date; @@ -348,7 +342,7 @@ class WT_Person extends WT_GedcomRecord { */ function getBirthPlace() { if (is_null($this->_getBirthPlace)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach ($this->getAllBirthPlaces() as $place) { if ($place) { $this->_getBirthPlace=$place; @@ -371,7 +365,7 @@ class WT_Person extends WT_GedcomRecord { */ function getCensBirthPlace() { if (is_null($this->_getBirthPlace)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach ($this->getAllBirthPlaces() as $place) { if ($place) { $this->_getBirthPlace=$place; @@ -408,7 +402,7 @@ class WT_Person extends WT_GedcomRecord { */ function getDeathDate($estimate = true) { if (is_null($this->_getDeathDate)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach ($this->getAllDeathDates() as $date) { if ($date->isOK()) { $this->_getDeathDate=$date; @@ -431,7 +425,7 @@ class WT_Person extends WT_GedcomRecord { */ function getDeathPlace() { if (is_null($this->_getDeathPlace)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach ($this->getAllDeathPlaces() as $place) { if ($place) { $this->_getDeathPlace=$place; @@ -498,7 +492,7 @@ class WT_Person extends WT_GedcomRecord { // Get all the dates/places for births/deaths - for the INDI lists function getAllBirthDates() { if (is_null($this->_getAllBirthDates)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach (explode('|', WT_EVENTS_BIRT) as $event) { if ($this->_getAllBirthDates=$this->getAllEventDates($event)) { break; @@ -512,7 +506,7 @@ class WT_Person extends WT_GedcomRecord { } function getAllBirthPlaces() { if (is_null($this->_getAllBirthPlaces)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach (explode('|', WT_EVENTS_BIRT) as $event) { if ($this->_getAllBirthPlaces=$this->getAllEventPlaces($event)) { break; @@ -526,7 +520,7 @@ class WT_Person extends WT_GedcomRecord { } function getAllDeathDates() { if (is_null($this->_getAllDeathDates)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach (explode('|', WT_EVENTS_DEAT) as $event) { if ($this->_getAllDeathDates=$this->getAllEventDates($event)) { break; @@ -540,7 +534,7 @@ class WT_Person extends WT_GedcomRecord { } function getAllDeathPlaces() { if (is_null($this->_getAllDeathPlaces)) { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { foreach (explode('|', WT_EVENTS_DEAT) as $event) { if ($this->_getAllDeathPlaces=$this->getAllEventPlaces($event)) { break; @@ -664,7 +658,7 @@ class WT_Person extends WT_GedcomRecord { // the privatize-gedcom function, and we are allowed to know this. function getSex() { if (is_null($this->sex)) { - if (preg_match('/\n1 SEX ([MF])/', $this->_gedrec, $match)) { + if (preg_match('/\n1 SEX ([MF])/', $this->gedcom, $match)) { $this->sex=$match[1]; } else { $this->sex='U'; @@ -753,7 +747,7 @@ class WT_Person extends WT_GedcomRecord { if ($access_level==WT_PRIV_HIDE) { // special case, (temporary - cannot make this generic as other code depends on the private cached values) $families=array(); - preg_match_all('/\n1 FAMS @('.WT_REGEX_XREF.')@/', $this->_gedrec, $match); + preg_match_all('/\n1 FAMS @('.WT_REGEX_XREF.')@/', $this->gedcom, $match); foreach ($match[1] as $pid) { $family=WT_Family::getInstance($pid); if ($family) { @@ -765,10 +759,10 @@ class WT_Person extends WT_GedcomRecord { if ($this->_spouseFamilies===null) { $this->_spouseFamilies=array(); - preg_match_all('/\n1 FAMS @('.WT_REGEX_XREF.')@/', $this->_gedrec, $match); + preg_match_all('/\n1 FAMS @('.WT_REGEX_XREF.')@/', $this->gedcom, $match); foreach ($match[1] as $pid) { $family=WT_Family::getInstance($pid); - if ($family && ($SHOW_PRIVATE_RELATIONSHIPS || $family->canDisplayDetails($access_level))) { + if ($family && ($SHOW_PRIVATE_RELATIONSHIPS || $family->canShow($access_level))) { $this->_spouseFamilies[]=$family; } } @@ -794,7 +788,7 @@ class WT_Person extends WT_GedcomRecord { // Get a count of the children for this individual function getNumberOfChildren() { - if (preg_match('/\n1 NCHI (\d+)(?:\n|$)/', $this->getGedcomRecord(), $match)) { + if (preg_match('/\n1 NCHI (\d+)(?:\n|$)/', $this->getGedcom(), $match)) { return $match[1]; } else { $children=array(); @@ -814,7 +808,7 @@ class WT_Person extends WT_GedcomRecord { if ($access_level==WT_PRIV_HIDE) { // special case, (temporary - cannot make this generic as other code depends on the private cached values) $families=array(); - preg_match_all('/\n1 FAMC @('.WT_REGEX_XREF.')@/', $this->_gedrec, $match); + preg_match_all('/\n1 FAMC @('.WT_REGEX_XREF.')@/', $this->gedcom, $match); foreach ($match[1] as $pid) { $family=WT_Family::getInstance($pid); if ($family) { @@ -826,10 +820,10 @@ class WT_Person extends WT_GedcomRecord { if ($this->_childFamilies===null) { $this->_childFamilies=array(); - preg_match_all('/\n1 FAMC @('.WT_REGEX_XREF.')@/', $this->_gedrec, $match); + preg_match_all('/\n1 FAMC @('.WT_REGEX_XREF.')@/', $this->gedcom, $match); foreach ($match[1] as $pid) { $family=WT_Family::getInstance($pid); - if ($family && ($SHOW_PRIVATE_RELATIONSHIPS || $family->canDisplayDetails($access_level))) { + if ($family && ($SHOW_PRIVATE_RELATIONSHIPS || $family->canShow($access_level))) { $this->_childFamilies[]=$family; } } @@ -852,19 +846,19 @@ class WT_Person extends WT_GedcomRecord { // If there is more than one FAMC record, choose the preferred parents: // a) records with '2 _PRIMARY' foreach ($families as $famid=>$fam) { - if (preg_match("/\n1 FAMC @{$famid}@\n(?:[2-9].*\n)*(?:2 _PRIMARY Y)/", $this->getGedcomRecord())) { + if (preg_match("/\n1 FAMC @{$famid}@\n(?:[2-9].*\n)*(?:2 _PRIMARY Y)/", $this->getGedcom())) { return $fam; } } // b) records with '2 PEDI birt' foreach ($families as $famid=>$fam) { - if (preg_match("/\n1 FAMC @{$famid}@\n(?:[2-9].*\n)*(?:2 PEDI birth)/", $this->getGedcomRecord())) { + if (preg_match("/\n1 FAMC @{$famid}@\n(?:[2-9].*\n)*(?:2 PEDI birth)/", $this->getGedcom())) { return $fam; } } // c) records with no '2 PEDI' foreach ($families as $famid=>$fam) { - if (!preg_match("/\n1 FAMC @{$famid}@\n(?:[2-9].*\n)*(?:2 PEDI)/", $this->getGedcomRecord())) { + if (!preg_match("/\n1 FAMC @{$famid}@\n(?:[2-9].*\n)*(?:2 PEDI)/", $this->getGedcom())) { return $fam; } } @@ -877,7 +871,7 @@ class WT_Person extends WT_GedcomRecord { * @return string FAMC:PEDI value [ adopted | birth | foster | sealing ] */ function getChildFamilyPedigree($famid) { - $subrec = get_sub_record(1, '1 FAMC @'.$famid.'@', $this->getGedcomRecord()); + $subrec = get_sub_record(1, '1 FAMC @'.$famid.'@', $this->getGedcom()); $pedi = get_gedcom_value('PEDI', 2, $subrec); // birth=default => return an empty string return ($pedi=='birth') ? '' : $pedi; @@ -925,35 +919,9 @@ class WT_Person extends WT_GedcomRecord { return $step_families; } - /** - * get global facts - * @return array - */ - function getGlobalFacts() { - $this->parseFacts(); - return $this->globalfacts; - } - /** - * get indi facts - * @return array - */ - function getIndiFacts() { - $this->parseFacts(); - return $this->indifacts; - } - - /** - * get other facts - * @return array - */ - function getOtherFacts() { - $this->parseFacts(); - return $this->otherfacts; - } - // A label for a parental family group function getChildFamilyLabel(WT_Family $family) { - if (preg_match('/\n1 FAMC @'.$family->getXref().'@(?:\n[2-9].*)*\n2 PEDI (.+)/', $this->getGedcomRecord(), $match)) { + if (preg_match('/\n1 FAMC @'.$family->getXref().'@(?:\n[2-9].*)*\n2 PEDI (.+)/', $this->getGedcom(), $match)) { // A specified pedigree return WT_Gedcom_Code_Pedi::getChildFamilyLabel($match[1]); } else { @@ -1001,8 +969,9 @@ class WT_Person extends WT_GedcomRecord { } } // It should not be possible to get here - throw new Exception('Invalid family in WT_Person::getStepFamilyLabel(' . $family . ')'); + throw new Exception('Invalid family in WT_Individual::getStepFamilyLabel(' . $family . ')'); } + /** * get the correct label for a family * @param Family $family the family to get the label for @@ -1025,595 +994,6 @@ class WT_Person extends WT_GedcomRecord { // I18N: %s is the spouse name return WT_I18N::translate('Family with %s', $spouse); } - /** - * get updated Person - * If there is an updated individual record in the gedcom file - * return a new person object for it - * @return Person - */ - function getUpdatedPerson() { - if ($this->getChanged()) { - return null; - } - if (WT_USER_CAN_EDIT && $this->canDisplayDetails()) { - $newrec = find_updated_record($this->xref, $this->ged_id); - if (!is_null($newrec)) { - $new = new WT_Person($newrec); - $new->setChanged(true); - return $new; - } - } - return null; - } - /** - * Parse the facts from the individual record - */ - function parseFacts() { - parent::parseFacts(); - //-- only run this function once - if ($this->facts_parsed) return; - //-- don't run this function if privacy does not allow viewing of details - if (!$this->canDisplayDetails()) return; - $sexfound = false; - //-- run the parseFacts() method from the parent class - $this->facts_parsed = true; - - //-- sort the fact info into different categories for people - foreach ($this->facts as $f=>$event) { - $fact = $event->getTag(); - if ($fact=='NAME') { - // -- handle special name fact case - $this->globalfacts[] = $event; - } elseif ($fact=='SOUR') { - // -- handle special source fact case - $this->otherfacts[] = $event; - } elseif ($fact=='NOTE') { - // -- handle special note fact case - $this->otherfacts[] = $event; - } elseif ($fact=='SEX') { - // -- handle special sex case - $this->globalfacts[] = $event; - $sexfound = true; - } elseif ($fact=='OBJE') { - } else { - $this->indifacts[] = $event; - } - } - //-- add a new sex fact if one was not found - if (!$sexfound) { - $this->globalfacts[] = new WT_Event('1 SEX U', $this, 'new'); - } - } - /** - * add facts from the family record - * @param boolean $otherfacts whether or not to add other related facts such as parents facts, associated people facts, and historical facts - */ - function add_family_facts($otherfacts = true) { - global $GEDCOM, $nonfacts, $nonfamfacts; - - if (!isset($nonfacts)) $nonfacts = array(); - if (!isset($nonfamfacts)) $nonfamfacts = array(); - - if (!$this->canDisplayDetails()) return; - $this->parseFacts(); - //-- Get the facts from the family with spouse (FAMS) - foreach ($this->getSpouseFamilies() as $family) { - $updfamily = $family->getUpdatedFamily(); //-- updated family ? - $spouse = $family->getSpouse($this); - - if ($updfamily) { - $family->diffMerge($updfamily); - } - $facts = $family->getFacts(); - $hasdiv = false; - /* @var $event WT_Event */ - foreach ($facts as $event) { - $fact = $event->getTag(); - if ($fact=='DIV') $hasdiv = true; - // -- handle special source fact case - if ($fact!='SOUR' && $fact!='NOTE' && $fact!='CHAN' && $fact!='_UID' && $fact!='RIN') { - if (!in_array($fact, $nonfacts) && !in_array($fact, $nonfamfacts)) { - $event->setSpouse($spouse); - if ($fact!='OBJE') { - $this->indifacts[]=$event; - } else { - $this->otherfacts[]=$event; - } - } - } - } - if ($otherfacts) { - if (!$hasdiv && !is_null($spouse)) $this->add_spouse_facts($spouse, $family->getGedcomRecord()); - $this->add_children_facts($family, '_CHIL', ''); - } - } - if ($otherfacts) { - $this->add_parents_facts($this, 1); - $this->add_historical_facts(); - $this->add_asso_facts(); - } - } - - // Add parents' (and parents' relatives') events to individual facts array - function add_parents_facts($person, $sosa) { - global $SHOW_RELATIVES_EVENTS; - - switch ($sosa) { - case 1: - foreach ($person->getChildFamilies() as $family) { - // Add siblings - $this->add_children_facts($family, '_SIBL', ''); - foreach ($family->getSpouses() as $spouse) { - foreach ($spouse->getSpouseFamilies() as $sfamily) { - if (!$family->equals($sfamily)) { - // Add half-siblings - $this->add_children_facts($sfamily, '_HSIB', 'par'); - } - } - // Add grandparents - $this->add_parents_facts($spouse, $spouse->getSex()=='F' ? 3 : 2); - } - } - - $rela=''; - break; - case 2: - $rela='fat'; - break; - case 3: - $rela='mot'; - break; - } - - // Only include events between birth and death - $bDate=$this->getEstimatedBirthDate(); - $dDate=$this->getEstimatedDeathDate(); - - foreach ($person->getChildFamilies() as $famid=>$family) { - foreach ($family->getSpouses() as $parent) { - if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT'.($sosa==1 ? '_PARE' : '_GPAR'))) { - foreach ($parent->getAllFactsByType(explode('|', WT_EVENTS_DEAT)) as $sEvent) { - if ($sEvent->getDate()->isOK() && WT_Date::Compare($bDate, $sEvent->getDate())<=0 && WT_Date::Compare($sEvent->getDate(), $dDate)<=0) { - switch ($sosa) { - case 1: - // Convert the event to a close relatives event - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1_PARE ', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_PARE\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - break; - case 2: - // Convert the event to a close relatives event - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1_GPA1 ', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_GPA1\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - break; - case 3: - // Convert the event to a close relatives event - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1_GPA2 ', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_GPA2\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - break; - } - // Create a new event - $this->indifacts[]=new WT_Event($tmp_rec."\n2 _ASSO @".$parent->getXref()."@", $parent, 0); - } - } - } - } - - if ($sosa==1 && strstr($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) { - // add father/mother marriages - foreach ($family->getSpouses() as $parent) { - foreach ($parent->getSpouseFamilies() as $sfamily) { - foreach ($sfamily->getAllFactsByType(explode('|', WT_EVENTS_MARR)) as $sEvent) { - if ($sEvent->getDate()->isOK() && WT_Date::Compare($bDate, $sEvent->getDate())<=0 && WT_Date::Compare($sEvent->getDate(), $dDate)<=0) { - if ($sfamily->equals($family)) { - if ($parent->getSex()=='F') { - // show current family marriage only once - continue; - } - // marriage of parents (to each other) - // Convert the event to a close relatives event - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_MARR.')/', '1 _$1_FAMC ', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_FAMC\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } else { - // marriage of a parent (to another spouse) - // Convert the event to a close relatives event - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_MARR.')/', '1 _$1_PARE ', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_PARE\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } - // Add links to both spouses - foreach ($sfamily->getSpouses() as $spouse) { - $tmp_rec .= "\n2 _ASSO @" . $spouse->getXref() . '@'; - } - // Create a new event - $tmp = new WT_Event($tmp_rec, $sfamily, 0); - if (!$sfamily->equals($family)) { - $tmp->setSpouse($parent); - } - $this->indifacts[]=$tmp; - } - } - } - } - } - } - } - - /** - * add children events to individual facts array - * - * @param string $family Family object - * @param string $option Family level indicator - * @param string $relation Relationship path indicator - * @return records added to indifacts array - */ - function add_children_facts($family, $option, $relation) { - global $SHOW_RELATIVES_EVENTS; - - // Deal with recursion. - switch ($option) { - case '_CHIL': - // Add grandchildren - foreach ($family->getChildren() as $child) { - foreach ($child->getSpouseFamilies() as $cfamily) { - switch ($child->getSex()) { - case 'M': - $this->add_children_facts($cfamily, '_GCHI', 'son'); - break; - case 'F': - $this->add_children_facts($cfamily, '_GCHI', 'dau'); - break; - case 'U': - $this->add_children_facts($cfamily, '_GCHI', 'chi'); - break; - } - } - } - break; - } - - // For each child in the family - foreach ($family->getChildren() as $child) { - if ($child->getXref()==$this->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->getAllFactsByType(explode('|', WT_EVENTS_BIRT)) as $sEvent) { - $sgdate=$sEvent->getDate(); - // Always show _BIRT_CHIL, even if the dates are not known - if ($option=='_CHIL' || $sgdate->isOK() && WT_Date::Compare($this->getEstimatedBirthDate(), $sgdate)<=0 && WT_Date::Compare($sgdate, $this->getEstimatedDeathDate())<=0) { - if ($option=='_GCHI' && $relation=='dau') { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_BIRT.')/', '1 _$1_GCH1', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_GCH1\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } elseif ($option=='_GCHI' && $relation=='son') { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_BIRT.')/', '1 _$1_GCH2', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_GCH2\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } else { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_BIRT.')/', '1 _$1'.$option, $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag().$option."\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } - $event=new WT_Event($tmp_rec."\n2 _ASSO @".$child->getXref()."@", $child, 0); - if (!in_array($event, $this->indifacts)) { - $this->indifacts[]=$event; - } - } - } - } - // add child's death - if (strpos($SHOW_RELATIVES_EVENTS, '_DEAT'.str_replace('_HSIB', '_SIBL', $option))!==false) { - foreach ($child->getAllFactsByType(explode('|', WT_EVENTS_DEAT)) as $sEvent) { - $sgdate=$sEvent->getDate(); - $srec = $sEvent->getGedcomRecord(); - if ($sgdate->isOK() && WT_Date::Compare($this->getEstimatedBirthDate(), $sgdate)<=0 && WT_Date::Compare($sgdate, $this->getEstimatedDeathDate())<=0) { - if ($option=='_GCHI' && $relation=='dau') { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1_GCH1', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_GCH1\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } elseif ($option=='_GCHI' && $relation=='son') { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1_GCH2', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_GCH2\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } else { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1'.$option, $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag().$option."\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } - $event=new WT_Event($tmp_rec."\n2 _ASSO @".$child->getXref()."@", $child, 0); - if (!in_array($event, $this->indifacts)) { - $this->indifacts[]=$event; - } - } - } - } - // add child's marriage - if (strstr($SHOW_RELATIVES_EVENTS, '_MARR'.str_replace('_HSIB', '_SIBL', $option))) { - foreach ($child->getSpouseFamilies() as $sfamily) { - foreach ($sfamily->getAllFactsByType(explode('|', WT_EVENTS_MARR)) as $sEvent) { - $sgdate=$sEvent->getDate(); - if ($sgdate->isOK() && WT_Date::Compare($this->getEstimatedBirthDate(), $sgdate)<=0 && WT_Date::Compare($sgdate, $this->getEstimatedDeathDate())<=0) { - if ($option=='_GCHI' && $relation=='dau') { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_MARR.')/', '1 _$1_GCH1', $sEvent->getGedcomRecord()); - $tmp_rec="1 _".$sEvent->getTag()."_GCH1\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } elseif ($option=='_GCHI' && $relation=='son') { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_MARR.')/', '1 _$1_GCH2', $sEvent->getGedcomRecord()); - $tmp_rec="1 _".$sEvent->getTag()."_GCH2\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } else { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_MARR.')/', '1 _$1'.$option, $sEvent->getGedcomRecord()); - $tmp_rec="1 _".$sEvent->getTag().$option."\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - } - // Add links to both spouses - foreach ($sfamily->getSpouses() as $spouse) { - $tmp_rec .= "\n2 _ASSO @" . $spouse->getXref() . '@'; - } - // Create a new event - $tmp = new WT_Event($tmp_rec, $sfamily, 0); - $tmp->setSpouse($child); - $this->indifacts[]=$tmp; - } - } - } - } - } - } - /** - * add spouse events to individual facts array - * - * bdate = indi birth date record - * ddate = indi death date record - * - * @param string $spouse Person object - * @param string $famrec family Gedcom record - * @return records added to indifacts array - */ - function add_spouse_facts($spouse, $famrec='') { - global $SHOW_RELATIVES_EVENTS; - - // do not show if divorced - if (preg_match('/\n1 (?:'.WT_EVENTS_DIV.')\b/', $famrec)) { - return; - } - // Only include events between birth and death - $bDate=$this->getEstimatedBirthDate(); - $dDate=$this->getEstimatedDeathDate(); - - // add spouse death - if ($spouse && strstr($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) { - foreach ($spouse->getAllFactsByType(explode('|', WT_EVENTS_DEAT)) as $sEvent) { - $sdate=$sEvent->getDate(); - if ($sdate->isOK() && WT_Date::Compare($this->getEstimatedBirthDate(), $sdate)<=0 && WT_Date::Compare($sdate, $this->getEstimatedDeathDate())<=0) { - // Convert the event to a close relatives event. - $tmp_rec=preg_replace('/^1 ('.WT_EVENTS_DEAT.')/', '1 _$1_SPOU ', $sEvent->getGedcomRecord()); // Full - $tmp_rec="1 _".$sEvent->getTag()."_SPOU\n2 DATE ".$sEvent->getValue('DATE')."\n2 PLAC ".$sEvent->getValue('PLAC'); // Abbreviated - // Create a new event - $this->indifacts[]=new WT_Event($tmp_rec."\n2 _ASSO @".$spouse->getXref()."@", $spouse, 0); - } - } - } - } - - /** - * add historical events to individual facts array - * - * @return records added to indifacts array - * - * Historical facts are imported from optional language file : histo.xx.php - * where xx is language code - * This file should contain records similar to : - * - * $histo[]="1 EVEN\n2 TYPE History\n2 DATE 11 NOV 1918\n2 NOTE WW1 Armistice"; - * $histo[]="1 EVEN\n2 TYPE History\n2 DATE 8 MAY 1945\n2 NOTE WW2 Armistice"; - * etc... - * - */ - function add_historical_facts() { - global $SHOW_RELATIVES_EVENTS; - if (!$SHOW_RELATIVES_EVENTS) return; - - // Only include events between birth and death - $bDate=$this->getEstimatedBirthDate(); - $dDate=$this->getEstimatedDeathDate(); - if (!$bDate->isOK()) return; - - if (file_exists(WT_Site::preference('INDEX_DIRECTORY').'histo.'.WT_LOCALE.'.php')) { - require WT_Site::preference('INDEX_DIRECTORY').'histo.'.WT_LOCALE.'.php'; - foreach ($histo as $indexval=>$hrec) { - $sdate=new WT_Date(get_gedcom_value('DATE', 2, $hrec)); - if ($sdate->isOK() && WT_Date::Compare($this->getEstimatedBirthDate(), $sdate)<=0 && WT_Date::Compare($sdate, $this->getEstimatedDeathDate())<=0) { - $event = new WT_Event($hrec, null, -1); - $this->indifacts[] = $event; - } - } - } - } - /** - * add events where pid is an ASSOciate - * - * @return records added to indifacts array - * - */ - function add_asso_facts() { - $associates=array_merge( - fetch_linked_indi($this->getXref(), 'ASSO', $this->ged_id), - fetch_linked_indi($this->getXref(), '_ASSO', $this->ged_id), - fetch_linked_fam ($this->getXref(), 'ASSO', $this->ged_id), - fetch_linked_fam ($this->getXref(), '_ASSO', $this->ged_id) - ); - foreach ($associates as $associate) { - foreach ($associate->getFacts() as $event) { - $srec = $event->getGedcomRecord(); - foreach (array('ASSO', '_ASSO') as $asso_tag) { - $arec = get_sub_record(2, '2 ' . $asso_tag . ' @' . $this->getXref() . '@', $srec); - if ($arec) { - // Extract the important details from the fact - $factrec='1 '.$event->getTag(); - if (preg_match('/\n2 DATE .*/', $srec, $match)) { - $factrec.=$match[0]; - } - if (preg_match('/\n2 PLAC .*/', $srec, $match)) { - $factrec.=$match[0]; - } - if ($associate instanceof WT_Family) { - foreach ($associate->getSpouses() as $spouse) { - $factrec.="\n2 $asso_tag @".$spouse->getXref().'@'; - } - } else { - $factrec.="\n2 $asso_tag @".$associate->getXref().'@'; - // CHR/BAPM events are commonly used. Generate the reverse relationship - if (preg_match('/^(?:BAPM|CHR)$/', $event->getTag()) && preg_match('/3 RELA god(?:parent|mother|father)/', $event->getGedcomRecord())) { - switch ($associate->getSex()) { - case 'M': - $factrec.="\n3 RELA godson"; - break; - case 'F': - $factrec.="\n3 RELA goddaughter"; - break; - case 'U': - $factrec.="\n3 RELA godchild"; - break; - } - } - } - $this->indifacts[] = new WT_Event($factrec, $associate, 0); - } - } - } - } - } - - /** - * Merge the facts from another Person object into this object - * for generating a diff view - * @param Person $diff the person to compare facts with - */ - function diffMerge($diff) { - if (is_null($diff)) return; - $this->parseFacts(); - $diff->parseFacts(); - //-- loop through new facts and add them to the list if they are any changes - //-- compare new and old facts of the Personal Fact and Details tab 1 - for ($i=0; $i<count($this->indifacts); $i++) { - $found=false; - $oldfactrec = $this->indifacts[$i]->getGedcomRecord(); - foreach ($diff->indifacts as $newfact) { - $newfactrec = $newfact->getGedcomRecord(); - //-- remove all whitespace for comparison - $tnf = preg_replace('/\s+/', ' ', $newfactrec); - $tif = preg_replace('/\s+/', ' ', $oldfactrec); - if ($tnf==$tif) { - $this->indifacts[$i] = $newfact; //-- make sure the correct linenumber is used - $found=true; - break; - } - } - //-- fact was deleted? - if (!$found) { - $this->indifacts[$i]->setIsOld(); - } - } - //-- check for any new facts being added - foreach ($diff->indifacts as $newfact) { - $found=false; - foreach ($this->indifacts as $fact) { - $tif = preg_replace('/\s+/', ' ', $fact->getGedcomRecord()); - $tnf = preg_replace('/\s+/', ' ', $newfact->getGedcomRecord()); - if ($tif==$tnf) { - $found=true; - break; - } - } - if (!$found) { - $newfact->setIsNew(); - $this->indifacts[]=$newfact; - } - } - //-- compare new and old facts of the Notes Sources and Media tab 2 - for ($i=0; $i<count($this->otherfacts); $i++) { - $found=false; - foreach ($diff->otherfacts as $newfact) { - if (trim($newfact->getGedcomRecord())==trim($this->otherfacts[$i]->getGedcomRecord())) { - $this->otherfacts[$i] = $newfact; //-- make sure the correct linenumber is used - $found=true; - break; - } - } - if (!$found) { - $this->otherfacts[$i]->setIsOld(); - } - } - foreach ($diff->otherfacts as $indexval => $newfact) { - $found=false; - foreach ($this->otherfacts as $indexval => $fact) { - if (trim($fact->getGedcomRecord())==trim($newfact->getGedcomRecord())) { - $found=true; - break; - } - } - if (!$found) { - $newfact->setIsNew(); - $this->otherfacts[]=$newfact; - } - } - - //-- compare new and old facts of the Global facts - for ($i=0; $i<count($this->globalfacts); $i++) { - $found=false; - foreach ($diff->globalfacts as $indexval => $newfact) { - if (trim($newfact->getGedcomRecord())==trim($this->globalfacts[$i]->getGedcomRecord())) { - $this->globalfacts[$i] = $newfact; //-- make sure the correct linenumber is used - $found=true; - break; - } - } - if (!$found) { - $this->globalfacts[$i]->setIsOld(); - } - } - foreach ($diff->globalfacts as $indexval => $newfact) { - $found=false; - foreach ($this->globalfacts as $indexval => $fact) { - if (trim($fact->getGedcomRecord())==trim($newfact->getGedcomRecord())) { - $found=true; - break; - } - } - if (!$found) { - $newfact->setIsNew(); - $this->globalfacts[]=$newfact; - } - } - - foreach ($diff->getChildFamilies() as $diff_family) { - $exists=false; - foreach ($this->getChildFamilies() as $family) { - if ($family->equals($diff_family)) { - $exists=true; - break; - } - } - if (!$exists) { - $this->_childFamilies[]=$diff_family; - } - } - - foreach ($diff->getSpouseFamilies() as $diff_family) { - $exists=false; - foreach ($this->getSpouseFamilies() as $family) { - if ($family->equals($diff_family)) { - $exists=true; - break; - } - } - if (!$exists) { - $this->_spouseFamilies[]=$diff_family; - } - } - } /** * get primary parents names for this person @@ -1677,19 +1057,19 @@ class WT_Person extends WT_GedcomRecord { // 1 NAME Carlos /Vasquez y Sante/ // 2 GIVN Carlos // 2 SURN Vasquez,Sante - protected function _addName($type, $full, $gedrec) { + protected function _addName($type, $full, $gedcom) { global $UNKNOWN_NN, $UNKNOWN_PN; //////////////////////////////////////////////////////////////////////////// // Extract the structured name parts - use for "sortable" names and indexes //////////////////////////////////////////////////////////////////////////// - $sublevel=1+(int)$gedrec[0]; - $NPFX=preg_match("/\n{$sublevel} NPFX (.+)/", $gedrec, $match) ? $match[1] : ''; - $GIVN=preg_match("/\n{$sublevel} GIVN (.+)/", $gedrec, $match) ? $match[1] : ''; - $SURN=preg_match("/\n{$sublevel} SURN (.+)/", $gedrec, $match) ? $match[1] : ''; - $NSFX=preg_match("/\n{$sublevel} NSFX (.+)/", $gedrec, $match) ? $match[1] : ''; - $NICK=preg_match("/\n{$sublevel} NICK (.+)/", $gedrec, $match) ? $match[1] : ''; + $sublevel=1+(int)$gedcom[0]; + $NPFX=preg_match("/\n{$sublevel} NPFX (.+)/", $gedcom, $match) ? $match[1] : ''; + $GIVN=preg_match("/\n{$sublevel} GIVN (.+)/", $gedcom, $match) ? $match[1] : ''; + $SURN=preg_match("/\n{$sublevel} SURN (.+)/", $gedcom, $match) ? $match[1] : ''; + $NSFX=preg_match("/\n{$sublevel} NSFX (.+)/", $gedcom, $match) ? $match[1] : ''; + $NICK=preg_match("/\n{$sublevel} NICK (.+)/", $gedcom, $match) ? $match[1] : ''; // SURN is an comma-separated list of surnames... if ($SURN) { @@ -1867,7 +1247,7 @@ class WT_Person extends WT_GedcomRecord { } else { $char = ($bwidth/6.5); } - if ($this->canDisplayName()) { + if ($this->canShowName()) { $tmp=$this->getAllNames(); $givn = $tmp[$this->getPrimaryName()]['givn']; $surn = $tmp[$this->getPrimaryName()]['surname']; diff --git a/library/WT/Media.php b/library/WT/Media.php index e370da631b..23643184df 100644 --- a/library/WT/Media.php +++ b/library/WT/Media.php @@ -30,62 +30,55 @@ if (!defined('WT_WEBTREES')) { class WT_Media extends WT_GedcomRecord { const RECORD_TYPE = 'OBJE'; + const SQL_FETCH = "SELECT m_gedcom FROM `##media` WHERE m_id=? AND m_file=?"; const URL_PREFIX = 'mediaviewer.php?mid='; public $title = null; // TODO: these should be private, with getTitle() and getFilename() functions public $file = null; // Create a Media object from either raw GEDCOM data or a database row - public function __construct($data) { - parent::__construct($data); + public function __construct($xref, $gedcom, $pending, $gedcom_id) { + parent::__construct($xref, $gedcom, $pending, $gedcom_id); - if (is_array($data)) { - // Construct from a row from the database - $this->file =$data['m_filename']; - $this->title=$data['m_titl']; + // TODO get this data from WT_Fact objects + if (preg_match('/\n1 FILE (.+)/', $gedcom.$pending, $match)) { + $this->file = $match[1]; } else { - // Construct from raw GEDCOM data - if (preg_match('/\n1 FILE (.+)/', $data, $match)) { - $this->file = $match[1]; - } else { - $this->file = ''; - } - if (preg_match('/\n\d TITL (.+)/', $data, $match)) { - $this->title = $match[1]; - } else { - $this->title = $this->file; - } + $this->file = ''; + } + if (preg_match('/\n\d TITL (.+)/', $gedcom.$pending, $match)) { + $this->title = $match[1]; + } else { + $this->title = $this->file; } } // Implement media-specific privacy logic ... - protected function _canDisplayDetailsByType($access_level) { + protected function _canShowByType($access_level) { // Hide media objects if they are attached to private records $linked_ids=WT_DB::prepare( "SELECT l_from FROM `##link` WHERE l_to=? AND l_file=?" - )->execute(array($this->xref, $this->ged_id))->fetchOneColumn(); + )->execute(array($this->xref, $this->gedcom_id))->fetchOneColumn(); foreach ($linked_ids as $linked_id) { $linked_record=WT_GedcomRecord::getInstance($linked_id); - if ($linked_record && !$linked_record->canDisplayDetails($access_level)) { + if ($linked_record && !$linked_record->canShow($access_level)) { return false; } } // ... otherwise apply default behaviour - return parent::_canDisplayDetailsByType($access_level); + return parent::_canShowByType($access_level); } // Fetch the record from the database - protected static function fetchGedcomRecord($xref, $ged_id) { + protected static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; if ($statement===null) { - $statement=WT_DB::prepare( - "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename". - " FROM `##media` WHERE m_id=? AND m_file=?" - ); + $statement=WT_DB::prepare("SELECT m_gedcom FROM `##media` WHERE m_id=? AND m_file=?"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } /** @@ -93,7 +86,7 @@ class WT_Media extends WT_GedcomRecord { * @return string */ public function getNote() { - return get_gedcom_value('NOTE', 1, $this->getGedcomRecord()); + return get_gedcom_value('NOTE', 1, $this->getGedcom()); } /** @@ -246,13 +239,13 @@ class WT_Media extends WT_GedcomRecord { * @return string */ public function getMediaType() { - $mediaType = strtolower(get_gedcom_value('FORM:TYPE', 2, $this->getGedcomRecord())); + $mediaType = strtolower(get_gedcom_value('FORM:TYPE', 2, $this->getGedcom())); return $mediaType; } // Is this object marked as a highlighted image? public function isPrimary() { - if (preg_match('/\n\d _PRIM ([YN])/', $this->getGedcomRecord(), $match)) { + if (preg_match('/\n\d _PRIM ([YN])/', $this->getGedcom(), $match)) { return $match[1]; } else { return ''; @@ -341,7 +334,7 @@ class WT_Media extends WT_GedcomRecord { $downloadstr = ($download) ? '&dl=1' : ''; return 'mediafirewall.php?mid=' . $this->getXref() . $thumbstr . $downloadstr . - '&ged=' . rawurlencode(get_gedcom_from_id($this->ged_id)) . + '&ged=' . rawurlencode(get_gedcom_from_id($this->gedcom_id)) . '&cb=' . $this->getEtag($which); } @@ -425,7 +418,7 @@ class WT_Media extends WT_GedcomRecord { // If this object has no name, what do we call it? public function getFallBackName() { - if ($this->canDisplayDetails()) { + if ($this->canShow()) { return basename($this->file); } else { return $this->getXref(); @@ -434,7 +427,7 @@ class WT_Media extends WT_GedcomRecord { // Get an array of structures containing all the names in the record public function getAllNames() { - if (strpos($this->getGedcomRecord(), "\n1 TITL ")) { + if (strpos($this->getGedcom(), "\n1 TITL ")) { // Earlier gedcom versions had level 1 titles return parent::_getAllNames('TITL', 1); } else { diff --git a/library/WT/MenuBar.php b/library/WT/MenuBar.php index 1cc5d647b7..0798f4cafc 100644 --- a/library/WT/MenuBar.php +++ b/library/WT/MenuBar.php @@ -2,7 +2,7 @@ // System for generating menus. // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -235,8 +235,8 @@ class WT_MenuBar { // Add a submenu showing relationship from this person to each of our favorites foreach (user_favorites_WT_Module::getFavorites(WT_USER_ID) as $favorite) { if ($favorite['type']=='INDI' && $favorite['gedcom_id']==WT_GED_ID) { - $person=WT_Person::getInstance($favorite['gid']); - if ($person instanceof WT_Person) { + $person=WT_Individual::getInstance($favorite['gid']); + if ($person instanceof WT_Individual) { $subsubmenu = new WT_Menu( $person->getFullName(), 'relationship.php?pid1='.$person->getXref().'&pid2='.$pid2.'&ged='.WT_GEDURL, @@ -517,7 +517,7 @@ class WT_MenuBar { case 'OBJE': case 'NOTE': $obj=WT_GedcomRecord::getInstance($favorite['gid']); - if ($obj && $obj->canDisplayName()) { + if ($obj && $obj->canShowName()) { $submenu=new WT_Menu($obj->getFullName(), $obj->getHtmlUrl()); $menu->addSubMenu($submenu); } diff --git a/library/WT/Note.php b/library/WT/Note.php index 0f1cedafa0..c9524b286f 100644 --- a/library/WT/Note.php +++ b/library/WT/Note.php @@ -30,23 +30,33 @@ if (!defined('WT_WEBTREES')) { class WT_Note extends WT_GedcomRecord { const RECORD_TYPE = 'NOTE'; + const SQL_FETCH = "SELECT o_gedcom FROM `##other` WHERE o_id=? AND o_file=?"; const URL_PREFIX = 'note.php?nid='; + // Get the text contents of the note + public function getNote() { + if (preg_match('/^0 @' . WT_REGEX_TAG . '@ NOTE ?(.*(?:\n1 CONT .*)*)/', $this->gedcom, $match)) { + return str_replace("\n1 CONT ", "\n", $match[1]); + } else { + return null; + } + } + // Implement note-specific privacy logic - protected function _canDisplayDetailsByType($access_level) { + protected function _canShowByType($access_level) { // Hide notes if they are attached to private records $linked_ids=WT_DB::prepare( "SELECT l_from FROM `##link` WHERE l_to=? AND l_file=?" - )->execute(array($this->xref, $this->ged_id))->fetchOneColumn(); + )->execute(array($this->xref, $this->gedcom_id))->fetchOneColumn(); foreach ($linked_ids as $linked_id) { $linked_record=WT_GedcomRecord::getInstance($linked_id); - if ($linked_record && !$linked_record->canDisplayDetails($access_level)) { + if ($linked_record && !$linked_record->canShow($access_level)) { return false; } } // Apply default behaviour - return parent::_canDisplayDetailsByType($access_level); + return parent::_canShowByType($access_level); } // Generate a private version of this record @@ -55,16 +65,14 @@ class WT_Note extends WT_GedcomRecord { } // Fetch the record from the database - protected static function fetchGedcomRecord($xref, $ged_id) { + protected static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; if ($statement===null) { - $statement=WT_DB::prepare( - "SELECT o_type AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec ". - "FROM `##other` WHERE o_id=? AND o_file=? AND o_type='NOTE'" - ); + $statement=WT_DB::prepare("SELECT o_gedcom FROM `##other` WHERE o_id=? AND o_file=? AND o_type='NOTE'"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } // The 'name' of a note record is the first line. This can be diff --git a/library/WT/Query/Media.php b/library/WT/Query/Media.php index 91c1b4a91c..241513846d 100644 --- a/library/WT/Query/Media.php +++ b/library/WT/Query/Media.php @@ -67,7 +67,7 @@ class WT_Query_Media { public static function mediaList($folder, $subfolders, $sort, $filter) { // All files in the folder, plus external files $sql = - "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename" . + "SELECT m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom" . " FROM `##media`" . " WHERE m_file=?"; $args = array( @@ -114,11 +114,11 @@ class WT_Query_Media { throw new Exception('Bad argument (sort=', $sort, ') in WT_Query_Media::mediaList()'); } - $rows = WT_DB::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_ASSOC); + $rows = WT_DB::prepare($sql)->execute($args)->fetchAll(); $list = array(); foreach ($rows as $row) { - $media = WT_Media::getInstance($row); - if ($media->canDisplayDetails()) { + $media = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($media->canShow()) { $list[] = $media; } } diff --git a/library/WT/Query/Name.php b/library/WT/Query/Name.php index 4e04895d48..01a674dbb1 100644 --- a/library/WT/Query/Name.php +++ b/library/WT/Query/Name.php @@ -387,7 +387,7 @@ class WT_Query_Name { // To search for names with no surnames, use $salpha="," public static function individuals($surn, $salpha, $galpha, $marnm, $fams, $ged_id) { $sql= - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec, n_full ". + "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom, n_full ". "FROM `##individuals` ". "JOIN `##name` ON (n_id=i_id AND n_file=i_file) ". ($fams ? "JOIN `##link` ON (n_id=l_from AND n_file=l_file AND l_type='FAMS') " : ""). @@ -413,12 +413,12 @@ class WT_Query_Name { $sql.=" ORDER BY CASE n_surn WHEN '@N.N.' THEN 1 ELSE 0 END, n_surn COLLATE '".WT_I18N::$collation."', CASE n_givn WHEN '@P.N.' THEN 1 ELSE 0 END, n_givn COLLATE '".WT_I18N::$collation."'"; $list=array(); - $rows=WT_DB::prepare($sql)->fetchAll(PDO::FETCH_ASSOC); + $rows=WT_DB::prepare($sql)->fetchAll(); foreach ($rows as $row) { - $person=WT_Person::getInstance($row); + $person=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); // The name from the database may be private - check the filtered list... foreach ($person->getAllNames() as $n=>$name) { - if ($name['fullNN']==$row['n_full']) { + if ($name['fullNN']==$row->n_full) { $person->setPrimaryName($n); // We need to clone $person, as we may have multiple references to the // same person in this list, and the "primary name" would otherwise diff --git a/library/WT/Report/Base.php b/library/WT/Report/Base.php index 30e3cd9828..e39b81b338 100644 --- a/library/WT/Report/Base.php +++ b/library/WT/Report/Base.php @@ -458,7 +458,7 @@ class Element { $t = str_replace(array("<br>", " "), array("\n", " "), $t); if (!WT_RNEW) { $t = strip_tags($t); - $t = unhtmlentities($t); + $t = htmlspecialchars_decode($t); } $this->text .= $t; @@ -975,7 +975,7 @@ class Footnote extends Element { $t = str_replace(array("<br>", " "), array("\n", " "), $t); if (!WT_RNEW) { $t = strip_tags($t); - $t = unhtmlentities($t); + $t = htmlspecialchars_decode($t); } $this->text .= $t; return 0; @@ -1669,7 +1669,7 @@ function GedcomSHandler($attrs) { $newgedrec = ""; if (count($tags)<2) { $tmp=WT_GedcomRecord::getInstance($attrs['id']); - $newgedrec=$tmp ? $tmp->getGedcomRecord() : ''; + $newgedrec=$tmp ? $tmp->getGedcom() : ''; } if (empty($newgedrec)) { $tgedrec = $gedrec; @@ -1680,14 +1680,14 @@ function GedcomSHandler($attrs) { $newgedrec = $vars[$match[1]]['gedcom']; } else { $tmp=WT_GedcomRecord::getInstance($match[1]); - $newgedrec=$tmp ? $tmp->getGedcomRecord() : ''; + $newgedrec=$tmp ? $tmp->getGedcom() : ''; } } else { if (preg_match("/@(.+)/", $tag, $match)) { $gmatch = array(); if (preg_match("/\d $match[1] @([^@]+)@/", $tgedrec, $gmatch)) { $tmp=WT_GedcomRecord::getInstance($gmatch[1]); - $newgedrec=$tmp ? $tmp->getGedcomRecord() : ''; + $newgedrec=$tmp ? $tmp->getGedcom() : ''; $tgedrec = $newgedrec; } else { $newgedrec = ""; @@ -1942,7 +1942,7 @@ function GetPersonNameSHandler($attrs) { if (is_null($record)) { return; } - if (!$record->canDisplayName()) { + if (!$record->canShowName()) { $currentElement->addText(WT_I18N::translate('Private')); } else { $name = $record->getFullName(); @@ -2189,12 +2189,7 @@ function RepeatTagEHandler() { // Save original values array_push($parserStack, $parser); $oldgedrec = $gedrec; - // PHP 5.2.3 has a bug with foreach (), so don't use that here, while 5.2.3 is on the market - // while () has the fastest execution speed - $count = count($repeats); - $i = 0; - while ($i < $count) { - $gedrec = $repeats[$i]; + foreach ($repeats as $gedrec) { //-- start the sax parser $repeat_parser = xml_parser_create(); $parser = $repeat_parser; @@ -2211,7 +2206,6 @@ function RepeatTagEHandler() { exit; } xml_parser_free($repeat_parser); - $i++; } // Restore original values $gedrec = $oldgedrec; @@ -2334,28 +2328,21 @@ function FactsSHandler($attrs) { $tag = $vars[$match[1]]['id']; } + $record = WT_GedcomRecord::getInstance($id); if (empty($attrs['diff']) && !empty($id)) { - $record = WT_GedcomRecord::getInstance($id); $facts = $record->getFacts(); - if (!is_array($facts)) { - $facts = array($facts); - } sort_facts($facts); $repeats = array(); $nonfacts=explode(',', $tag); foreach ($facts as $event) { if (!in_array($event->getTag(), $nonfacts)) { - $repeats[]=$event->getGedComRecord(); + $repeats[]=$event->getGedcom(); } } } else { - $record = new WT_GedcomRecord($gedrec); - $oldrecord = WT_GedcomRecord::getInstance($record->getXref()); - $oldrecord->diffMerge($record); - $facts = $oldrecord->getFacts(); - foreach ($facts as $fact) { - if ($fact->getIsNew() && $fact->getTag()<>'CHAN') { - $repeats[]=$fact->getGedcomRecord(); + foreach ($record->getFacts as $fact) { + if ($fact->isNew() && $fact->getTag()<>'CHAN') { + $repeats[]=$fact->getGedcom(); } } } @@ -2604,7 +2591,7 @@ function FootnoteSHandler($attrs) { $id = $match[2]; } $record=WT_GedcomRecord::GetInstance($id); - if ($record && $record->canDisplayDetails()) { + if ($record && $record->canShow()) { array_push($printDataStack, $printData); $printData = true; $style = ""; @@ -2665,7 +2652,7 @@ function AgeAtDeathSHandler() { $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $gedrec, $match)) { - $person=WT_Person::getInstance($match[1]); + $person=WT_Individual::getInstance($match[1]); // Recorded age $fact_age=get_gedcom_value('AGE', 2, $gedrec); if ($fact_age=='') { @@ -2776,11 +2763,11 @@ function HighlightedImageSHandler($attrs) { if (!empty($attrs['width'])) $width = (int)$attrs['width']; if (!empty($attrs['height'])) $height = (int)$attrs['height']; - $person=WT_Person::getInstance($id); + $person=WT_Individual::getInstance($id); $mediaobject = $person->findHighlightedMedia(); if ($mediaobject) { $attributes=$mediaobject->getImageAttributes('thumb'); - if (in_array($attributes['ext'], array('GIF','JPG','PNG','SWF','PSD','BMP','TIFF','TIFF','JPC','JP2','JPX','JB2','SWC','IFF','WBMP','XBM')) && $mediaobject->canDisplayDetails() && $mediaobject->fileExists('thumb')) { + if (in_array($attributes['ext'], array('GIF','JPG','PNG','SWF','PSD','BMP','TIFF','TIFF','JPC','JP2','JPX','JB2','SWC','IFF','WBMP','XBM')) && $mediaobject->canShow() && $mediaobject->fileExists('thumb')) { if (($width>0) and ($height==0)) { $perc = $width / $attributes['adjW']; $height= round($attributes['adjH']*$perc); @@ -2848,7 +2835,7 @@ function ImageSHandler($attrs) { if (preg_match("/\d OBJE @(.+)@/", $gedrec, $match)) { $mediaobject=WT_Media::getInstance($match[1], WT_GED_ID); $attributes=$mediaobject->getImageAttributes('thumb'); - if (in_array($attributes['ext'], array('GIF','JPG','PNG','SWF','PSD','BMP','TIFF','TIFF','JPC','JP2','JPX','JB2','SWC','IFF','WBMP','XBM')) && $mediaobject->canDisplayDetails() && $mediaobject->fileExists('thumb')) { + if (in_array($attributes['ext'], array('GIF','JPG','PNG','SWF','PSD','BMP','TIFF','TIFF','JPC','JP2','JPX','JB2','SWC','IFF','WBMP','XBM')) && $mediaobject->canShow() && $mediaobject->fileExists('thumb')) { if (($width>0) and ($height==0)) { $perc = $width / $attributes['adjW']; $height= round($attributes['adjH']*$perc); @@ -2972,7 +2959,7 @@ function ListSHandler($attrs) { switch ($listname) { case "pending": $rows=WT_DB::prepare( - "SELECT CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom". + "SELECT xref, gedcom_id, 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)". @@ -2983,7 +2970,7 @@ function ListSHandler($attrs) { )->execute(array(WT_GED_ID))->fetchAll(); $list=array(); foreach ($rows as $row) { - $list[]=new WT_GedcomRecord($row->gedcom); + $list[] = WT_GedcomRecord::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } break; case "individual": @@ -2995,7 +2982,7 @@ function ListSHandler($attrs) { foreach ($attrs as $attr=>$value) { if ((strpos($attr, "filter")===0) && $value) { // Substitute global vars - $value=preg_replace('/\$(\w+)/e', '$vars["\\1"]["id"]', $value); + $value=preg_replace_callback('/\$(\w+)/', function($matches) use ($vars) { return $vars[$matches[1]]['id']; }, $value); // 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={$sql_col_prefix}file AND {$attr}.d_gid={$sql_col_prefix}id)"; @@ -3171,7 +3158,7 @@ function ListSHandler($attrs) { if ($filters) { foreach ($list as $key=>$record) { foreach ($filters as $filter) { - if (!preg_match("/".$filter."/i", $record->getGedcomRecord())) { + if (!preg_match("/".$filter."/i", $record->getGedcom())) { unset($list[$key]); break; } @@ -3182,7 +3169,7 @@ function ListSHandler($attrs) { $mylist = array(); foreach ($list as $indi) { $key=$indi->getXref(); - $grec=$indi->getGedcomRecord(); + $grec=$indi->getGedcom(); $keep = true; foreach ($filters2 as $filter) { if ($keep) { @@ -3247,10 +3234,10 @@ function ListSHandler($attrs) { uasort($list, array("WT_GedcomRecord", "CompareChanDate")); break; case "BIRT:DATE": - uasort($list, array("WT_Person", "CompareBirtDate")); + uasort($list, array("WT_Individual", "CompareBirtDate")); break; case "DEAT:DATE": - uasort($list, array("WT_Person", "CompareDeatDate")); + uasort($list, array("WT_Individual", "CompareDeatDate")); break; case "MARR:DATE": uasort($list, array("WT_Family", "CompareMarrDate")); @@ -3315,8 +3302,8 @@ function ListEHandler() { $list_total = count($list); $list_private = 0; foreach ($list as $record) { - if ($record->canDisplayDetails()) { - $gedrec = $record->getGedcomRecord(); + if ($record->canShow()) { + $gedrec = $record->getGedcom(); //-- start the sax parser $repeat_parser = xml_parser_create(); $parser = $repeat_parser; @@ -3411,7 +3398,7 @@ function RelativesSHandler($attrs) { } $list = array(); - $person = WT_Person::getInstance($id); + $person = WT_Individual::getInstance($id); if (!empty($person)) { $list[$id] = $person; switch ($group) { @@ -3558,7 +3545,7 @@ function RelativesEHandler() { continue; // key can be something like "empty7" } $tmp=WT_GedcomRecord::getInstance($key); - $gedrec = $tmp->getGedcomRecord(); + $gedrec = $tmp->getGedcom(); //-- start the sax parser $repeat_parser = xml_parser_create(); $parser = $repeat_parser; diff --git a/library/WT/Repository.php b/library/WT/Repository.php index c104238a68..e1e6fefd17 100644 --- a/library/WT/Repository.php +++ b/library/WT/Repository.php @@ -30,19 +30,18 @@ if (!defined('WT_WEBTREES')) { class WT_Repository extends WT_GedcomRecord { const RECORD_TYPE = 'REPO'; + const SQL_FETCH = "SELECT o_gedcom FROM `##other` WHERE o_id=? AND o_file=?"; const URL_PREFIX = 'repo.php?rid='; // Fetch the record from the database - protected static function fetchGedcomRecord($xref, $ged_id) { + protected static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; if ($statement===null) { - $statement=WT_DB::prepare( - "SELECT o_type AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec ". - "FROM `##other` WHERE o_id=? AND o_file=?" - ); + $statement=WT_DB::prepare("SELECT o_gedcom FROM `##other` WHERE o_id=? AND o_file=?"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } // Generate a private version of this record diff --git a/library/WT/Source.php b/library/WT/Source.php index 3664e4af69..67c42c7793 100644 --- a/library/WT/Source.php +++ b/library/WT/Source.php @@ -30,21 +30,22 @@ if (!defined('WT_WEBTREES')) { class WT_Source extends WT_GedcomRecord { const RECORD_TYPE = 'SOUR'; + const SQL_FETCH = "SELECT s_gedcom FROM `##sources` WHERE s_id=? AND s_file=?"; const URL_PREFIX = 'source.php?sid='; // Implement source-specific privacy logic - protected function _canDisplayDetailsByType($access_level) { + protected function _canShowByType($access_level) { // Hide sources if they are attached to private repositories ... - preg_match_all('/\n1 REPO @(.+)@/', $this->_gedrec, $matches); + preg_match_all('/\n1 REPO @(.+)@/', $this->gedcom, $matches); foreach ($matches[1] as $match) { $repo=WT_Repository::getInstance($match); - if ($repo && !$repo->canDisplayDetails($access_level)) { + if ($repo && !$repo->canShow($access_level)) { return false; } } // ... otherwise apply default behaviour - return parent::_canDisplayDetailsByType($access_level); + return parent::_canShowByType($access_level); } // Generate a private version of this record @@ -53,20 +54,18 @@ class WT_Source extends WT_GedcomRecord { } // Fetch the record from the database - protected static function fetchGedcomRecord($xref, $ged_id) { + protected static function fetchGedcomRecord($xref, $gedcom_id) { static $statement=null; if ($statement===null) { - $statement=WT_DB::prepare( - "SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec ". - "FROM `##sources` WHERE s_id=? AND s_file=?" - ); + $statement=WT_DB::prepare("SELECT s_gedcom FROM `##sources` WHERE s_id=? AND s_file=?"); } - return $statement->execute(array($xref, $ged_id))->fetchOneRow(PDO::FETCH_ASSOC); + + return $statement->execute(array($xref, $gedcom_id))->fetchOne(); } public function getAuth() { - return get_gedcom_value('AUTH', 1, $this->getGedcomRecord()); + return get_gedcom_value('AUTH', 1, $this->getGedcom()); } // Get an array of structures containing all the names in the record diff --git a/library/WT/Stats.php b/library/WT/Stats.php index 3f538e1651..43bae5f13d 100644 --- a/library/WT/Stats.php +++ b/library/WT/Stats.php @@ -254,7 +254,7 @@ class WT_Stats { } function gedcomRootID() { - $root = WT_Person::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); + $root = WT_Individual::getInstance(get_gedcom_setting(WT_GED_ID, 'PEDIGREE_ROOT_ID')); $root = substr($root, 0, stripos($root, "@") ); return $root; } @@ -842,7 +842,7 @@ class WT_Stats { switch($type) { default: case 'full': - if ($record->canDisplayDetails()) { + if ($record->canShow()) { $result=$record->format_list('span', false, $record->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); @@ -996,7 +996,7 @@ class WT_Stats { $surn_countries=array(); $indis = WT_Query_Name::individuals(utf8_strtoupper($surname), '', '', false, false, WT_GED_ID); foreach ($indis as $person) { - if (preg_match_all('/^2 PLAC (?:.*, *)*(.*)/m', $person->getGedcomRecord(), $matches)) { + if (preg_match_all('/^2 PLAC (?:.*, *)*(.*)/m', $person->getGedcom(), $matches)) { // webtrees uses 3 letter country codes and localised country names, but google uses 2 letter codes. foreach ($matches[1] as $country) { $country=trim($country); @@ -1377,11 +1377,11 @@ class WT_Stats { ); if (!isset($rows[0])) {return '';} $row = $rows[0]; - $person=WT_Person::getInstance($row['id']); + $person=WT_Individual::getInstance($row['id']); switch($type) { default: case 'full': - if ($person->canDisplayName()) { + if ($person->canShowName()) { $result=$person->format_list('span', false, $person->getFullName()); } else { $result= WT_I18N::translate('This information is private and cannot be shown.'); @@ -1435,7 +1435,7 @@ class WT_Stats { if (!isset($rows[0])) {return '';} $top10 = array(); foreach ($rows as $row) { - $person = WT_Person::getInstance($row['deathdate']); + $person = WT_Individual::getInstance($row['deathdate']); $age = $row['age']; if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; @@ -1445,7 +1445,7 @@ class WT_Stats { $age = $age.'d'; } $age = get_age_at_event($age, true); - if ($person->canDisplayDetails()) { + if ($person->canShow()) { if ($type == 'list') { $top10[]="<li><a href=\"".$person->getHtmlUrl()."\">".$person->getFullName()."</a> (".$age.")"."</li>"; } else { @@ -1502,7 +1502,7 @@ class WT_Stats { if (!isset($rows)) {return 0;} $top10 = array(); foreach ($rows as $row) { - $person=WT_Person::getInstance($row['id']); + $person=WT_Individual::getInstance($row['id']); $age = (WT_CLIENT_JD-$row['age']); if ((int)($age/365.25)>0) { $age = (int)($age/365.25).'y'; @@ -1776,7 +1776,7 @@ class WT_Stats { switch($type) { default: case 'full': - if ($record->canDisplayDetails()) { + if ($record->canShow()) { $result=$record->format_list('span', false, $record->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); @@ -1871,11 +1871,11 @@ class WT_Stats { if (!isset($rows[0])) {return '';} $row=$rows[0]; if (isset($row['famid'])) $family=WT_Family::getInstance($row['famid']); - if (isset($row['i_id'])) $person=WT_Person::getInstance($row['i_id']); + if (isset($row['i_id'])) $person=WT_Individual::getInstance($row['i_id']); switch($type) { default: case 'full': - if ($family->canDisplayDetails()) { + if ($family->canShow()) { $result=$family->format_list('span', false, $person->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); @@ -1990,7 +1990,7 @@ class WT_Stats { $husb = $family->getHusband(); $wife = $family->getWife(); if (($husb->getAllDeathDates() && $wife->getAllDeathDates()) || !$husb->isDead() || !$wife->isDead()) { - if ($family->canDisplayDetails()) { + if ($family->canShow()) { if ($type == 'list') { $top10[] = "<li><a href=\"".$family->getHtmlUrl()."\">".$family->getFullName()."</a> (".$age.")"."</li>"; } else { @@ -2054,7 +2054,7 @@ class WT_Stats { $age = $age.'d'; } $age = get_age_at_event($age, true); - if ($family->canDisplayDetails()) { + if ($family->canShow()) { if ($type == 'list') { $top10[] = "<li><a href=\"".$family->getHtmlUrl()."\">".$family->getFullName()."</a> (".$age.")"."</li>"; } else { @@ -2102,11 +2102,11 @@ class WT_Stats { ); if (!isset($rows[0])) {return '';} $row=$rows[0]; - if (isset($row['id'])) $person=WT_Person::getInstance($row['id']); + if (isset($row['id'])) $person=WT_Individual::getInstance($row['id']); switch($type) { default: case 'full': - if ($person->canDisplayDetails()) { + if ($person->canShow()) { $result=$person->format_list('span', false, $person->getFullName()); } else { $result=WT_I18N::translate('This information is private and cannot be shown.'); @@ -2523,7 +2523,7 @@ class WT_Stats { switch($type) { default: case 'full': - if ($family->canDisplayDetails()) { + if ($family->canShow()) { $result=$family->format_list('span', false, $family->getFullName()); } else { $result = WT_I18N::translate('This information is private and cannot be shown.'); @@ -2556,7 +2556,7 @@ class WT_Stats { $top10 = array(); for ($c = 0; $c < $total; $c++) { $family=WT_Family::getInstance($rows[$c]['id']); - if ($family->canDisplayDetails()) { + if ($family->canShow()) { if ($type == 'list') { $top10[]= '<li><a href="'.$family->getHtmlUrl().'">'.$family->getFullName().'</a> - '. @@ -2618,10 +2618,10 @@ class WT_Stats { if ($one) $dist = array(); foreach ($rows as $fam) { $family = WT_Family::getInstance($fam['family']); - $child1 = WT_Person::getInstance($fam['ch1']); - $child2 = WT_Person::getInstance($fam['ch2']); + $child1 = WT_Individual::getInstance($fam['ch1']); + $child2 = WT_Individual::getInstance($fam['ch2']); if ($type == 'name') { - if ($child1->canDisplayDetails() && $child2->canDisplayDetails()) { + if ($child1->canShow() && $child2->canShow()) { $return = '<a href="'.$child2->getHtmlUrl().'">'.$child2->getFullName().'</a> '; $return .= WT_I18N::translate('and').' '; $return .= '<a href="'.$child1->getHtmlUrl().'">'.$child1->getFullName().'</a>'; @@ -2645,7 +2645,7 @@ class WT_Stats { } if ($type == 'list') { if ($one && !in_array($fam['family'], $dist)) { - if ($child1->canDisplayDetails() && $child2->canDisplayDetails()) { + if ($child1->canShow() && $child2->canShow()) { $return = "<li>"; $return .= "<a href=\"".$child2->getHtmlUrl()."\">".$child2->getFullName()."</a> "; $return .= WT_I18N::translate('and')." "; @@ -2656,7 +2656,7 @@ class WT_Stats { $top10[] = $return; $dist[] = $fam['family']; } - } else if (!$one && $child1->canDisplayDetails() && $child2->canDisplayDetails()) { + } else if (!$one && $child1->canShow() && $child2->canShow()) { $return = "<li>"; $return .= "<a href=\"".$child2->getHtmlUrl()."\">".$child2->getFullName()."</a> "; $return .= WT_I18N::translate('and')." "; @@ -2667,7 +2667,7 @@ class WT_Stats { $top10[] = $return; } } else { - if ($child1->canDisplayDetails() && $child2->canDisplayDetails()) { + if ($child1->canShow() && $child2->canShow()) { $return = $child2->format_list('span', false, $child2->getFullName()); $return .= "<br>".WT_I18N::translate('and')."<br>"; $return .= $child1->format_list('span', false, $child1->getFullName()); @@ -2830,14 +2830,14 @@ class WT_Stats { $chl = array(); foreach ($rows as $row) { $family=WT_Family::getInstance($row['id']); - if ($family->canDisplayDetails()) { + if ($family->canShow()) { if ($tot==0) { $per = 0; } else { $per = round(100 * $row['tot'] / $tot, 0); } $chd .= self::_array_to_extended_encoding(array($per)); - $chl[] = strip_tags(unhtmlentities($family->getFullName())).' - '.WT_I18N::number($row['tot']); + $chl[] = htmlspecialchars_decode(strip_tags($family->getFullName())).' - '.WT_I18N::number($row['tot']); } } $chl = rawurlencode(join('|', $chl)); @@ -2968,7 +2968,7 @@ class WT_Stats { $top10 = array(); foreach ($rows as $row) { $family=WT_Family::getInstance($row['family']); - if ($family->canDisplayDetails()) { + if ($family->canShow()) { if ($type == 'list') { $top10[] = "<li><a href=\"".$family->getHtmlUrl()."\">".$family->getFullName()."</a></li>"; } else { @@ -3085,7 +3085,7 @@ class WT_Stats { $top10 = array(); foreach ($rows as $row) { $family=WT_Family::getInstance($row['id']); - if ($family->canDisplayDetails()) { + if ($family->canShow()) { if ($type == 'list') { $top10[]= '<li><a href="'.$family->getHtmlUrl().'">'.$family->getFullName().'</a> - '. diff --git a/library/phpmailer/class.phpmailer.php b/library/phpmailer/class.phpmailer.php index 3c4f95bcd4..bfb8ecad01 100644 --- a/library/phpmailer/class.phpmailer.php +++ b/library/phpmailer/class.phpmailer.php @@ -2,15 +2,16 @@ /*~ class.phpmailer.php .---------------------------------------------------------------------------. | Software: PHPMailer - PHP email class | -| Version: 5.2 | -| Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ | +| Version: 5.2.6 | +| Site: https://github.com/PHPMailer/PHPMailer/ | | ------------------------------------------------------------------------- | -| Admin: Jim Jagielski (project admininistrator) | +| Admins: Marcus Bointon | +| Admins: Jim Jagielski | | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | -| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | +| : Marcus Bointon (coolbru) phpmailer@synchromedia.co.uk | | : Jim Jagielski (jimjag) jimjag@gmail.com | | Founder: Brent R. Matzelle (original founder) | -| Copyright (c) 2010-2011, Jim Jagielski. All Rights Reserved. | +| Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. | | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | | Copyright (c) 2001-2003, Brent R. Matzelle | | ------------------------------------------------------------------------- | @@ -23,20 +24,25 @@ */ /** - * PHPMailer - PHP email transport class + * PHPMailer - PHP email creation and transport class * NOTE: Requires PHP version 5 or later * @package PHPMailer * @author Andy Prevost * @author Marcus Bointon * @author Jim Jagielski - * @copyright 2010 - 2011 Jim Jagielski + * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost - * @version $Id$ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ -if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n"); +if (version_compare(PHP_VERSION, '5.0.0', '<') ) { + exit("Sorry, PHPMailer will only run on PHP version 5 or greater!\n"); +} +/** + * PHP email creation and transport class + * @package PHPMailer + */ class PHPMailer { ///////////////////////////////////////////////// @@ -53,7 +59,7 @@ class PHPMailer { * Sets the CharSet of the message. * @var string */ - public $CharSet = 'UTF-8'; + public $CharSet = 'iso-8859-1'; /** * Sets the Content-type of the message. @@ -87,35 +93,52 @@ class PHPMailer { public $FromName = 'Root User'; /** - * Sets the Sender email (Return-Path) of the message. If not empty, - * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * Sets the Sender email (Return-Path) of the message. + * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. * @var string */ public $Sender = ''; /** + * Sets the Return-Path of the message. If empty, it will + * be set to either From or Sender. + * @var string + */ + public $ReturnPath = ''; + + /** * Sets the Subject of the message. * @var string */ public $Subject = ''; /** - * Sets the Body of the message. This can be either an HTML or text body. - * If HTML then run IsHTML(true). + * An HTML or plain text message body. + * If HTML then call IsHTML(true). * @var string */ public $Body = ''; /** - * Sets the text-only body of the message. This automatically sets the - * email to multipart/alternative. This body can be read by mail - * clients that do not have HTML email capability such as mutt. Clients - * that can read HTML will view the normal Body. + * The plain-text message body. + * This body can be read by mail clients that do not have HTML email + * capability such as mutt & Eudora. + * Clients that can read HTML will view the normal Body. * @var string */ public $AltBody = ''; /** + * An iCal message part body + * Only supported in simple alt or alt_inline message types + * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator + * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ + * @link http://kigkonsult.se/iCalcreator/ + * @var string + */ + public $Ical = ''; + + /** * Stores the complete compiled MIME message body. * @var string * @access protected @@ -130,6 +153,13 @@ class PHPMailer { protected $MIMEHeader = ''; /** + * Stores the extra header list which CreateHeader() doesn't fold in + * @var string + * @access protected + */ + protected $mailHeader = ''; + + /** * Sets word wrapping on the body of the message to a given number of * characters. * @var int @@ -149,6 +179,13 @@ class PHPMailer { public $Sendmail = '/usr/sbin/sendmail'; /** + * Determine if mail() uses a fully sendmail compatible MTA that + * supports sendmail's "-oi -f" options + * @var boolean + */ + public $UseSendmailOptions = true; + + /** * Path to PHPMailer plugins. Useful if the SMTP class * is in a different directory than the PHP include path. * @var string @@ -176,12 +213,21 @@ class PHPMailer { */ public $MessageID = ''; + /** + * Sets the message Date to be used in the Date header. + * If empty, the current date will be added. + * @var string + */ + public $MessageDate = ''; + ///////////////////////////////////////////////// // PROPERTIES FOR SMTP ///////////////////////////////////////////////// /** - * Sets the SMTP hosts. All hosts must be separated by a + * Sets the SMTP hosts. + * + * All hosts must be separated by a * semicolon. You can also specify a different port * for each host by using this format: [hostname:port] * (e.g. "smtp1.example.com:25;smtp2.example.com"). @@ -203,8 +249,7 @@ class PHPMailer { public $Helo = ''; /** - * Sets connection prefix. - * Options are "", "ssl" or "tls" + * Sets connection prefix. Options are "", "ssl" or "tls" * @var string */ public $SMTPSecure = ''; @@ -228,6 +273,24 @@ class PHPMailer { public $Password = ''; /** + * Sets SMTP auth type. Options are LOGIN | PLAIN | NTLM | CRAM-MD5 (default LOGIN) + * @var string + */ + public $AuthType = ''; + + /** + * Sets SMTP realm. + * @var string + */ + public $Realm = ''; + + /** + * Sets SMTP workstation. + * @var string + */ + public $Workstation = ''; + + /** * Sets the SMTP server timeout in seconds. * This function will not work with the win32 version. * @var int @@ -241,6 +304,13 @@ class PHPMailer { public $SMTPDebug = false; /** + * Sets the function/method to use for debugging output. + * Right now we only honor "echo" or "error_log" + * @var string + */ + public $Debugoutput = "echo"; + + /** * Prevents the SMTP connection from being closed after each mail * sending. If this is set to true then to close the connection * requires an explicit call to SmtpClose(). @@ -255,60 +325,89 @@ class PHPMailer { */ public $SingleTo = false; - /** + /** + * Should we generate VERP addresses when sending via SMTP? + * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path + * @var bool + */ + public $do_verp = false; + + /** * If SingleTo is true, this provides the array to hold the email addresses * @var bool */ public $SingleToArray = array(); - /** - * Provides the ability to change the line ending + /** + * Should we allow sending messages with empty body? + * @var bool + */ + public $AllowEmpty = false; + + /** + * Provides the ability to change the generic line ending + * NOTE: The default remains '\n'. We force CRLF where we KNOW + * it must be used via self::CRLF * @var string */ public $LE = "\n"; - /** - * Used with DKIM DNS Resource Record + /** + * Used with DKIM Signing + * required parameter if DKIM is enabled + * + * domain selector example domainkey * @var string */ - public $DKIM_selector = 'phpmailer'; + public $DKIM_selector = ''; /** - * Used with DKIM DNS Resource Record - * optional, in format of email address 'you@yourdomain.com' + * Used with DKIM Signing + * required if DKIM is enabled, in format of email address 'you@yourdomain.com' typically used as the source of the email * @var string */ public $DKIM_identity = ''; /** - * Used with DKIM DNS Resource Record + * Used with DKIM Signing + * optional parameter if your private key requires a passphras * @var string */ public $DKIM_passphrase = ''; /** - * Used with DKIM DNS Resource Record - * optional, in format of email address 'you@yourdomain.com' + * Used with DKIM Singing + * required if DKIM is enabled, in format of email address 'domain.com' * @var string */ public $DKIM_domain = ''; /** - * Used with DKIM DNS Resource Record - * optional, in format of email address 'you@yourdomain.com' + * Used with DKIM Signing + * required if DKIM is enabled, path to private key file * @var string */ public $DKIM_private = ''; /** - * Callback Action function name - * the function that handles the result of the send email action. Parameters: + * Callback Action function name. + * The function that handles the result of the send email action. + * It is called out by Send() for each email sent. + * + * Value can be: + * - 'function_name' for function names + * - 'Class::Method' for static method calls + * - array($object, 'Method') for calling methods on $object + * See http://php.net/is_callable manual page for more details. + * + * Parameters: * bool $result result of the send action * string $to email address of the recipient * string $cc cc email addresses * string $bcc bcc email addresses * string $subject the subject * string $body the email body + * string $from email address of sender * @var string */ public $action_function = ''; //'callbackAction'; @@ -317,11 +416,11 @@ class PHPMailer { * Sets the PHPMailer Version number * @var string */ - public $Version = '5.2'; + public $Version = '5.2.6'; /** * What to use in the X-Mailer header - * @var string + * @var string NULL for default, whitespace for None, or actual string to use */ public $XMailer = ''; @@ -329,21 +428,85 @@ class PHPMailer { // PROPERTIES, PRIVATE AND PROTECTED ///////////////////////////////////////////////// - protected $smtp = NULL; + /** + * @var SMTP An instance of the SMTP sender class + * @access protected + */ + protected $smtp = null; + /** + * @var array An array of 'to' addresses + * @access protected + */ protected $to = array(); + /** + * @var array An array of 'cc' addresses + * @access protected + */ protected $cc = array(); + /** + * @var array An array of 'bcc' addresses + * @access protected + */ protected $bcc = array(); + /** + * @var array An array of reply-to name and address + * @access protected + */ protected $ReplyTo = array(); + /** + * @var array An array of all kinds of addresses: to, cc, bcc, replyto + * @access protected + */ protected $all_recipients = array(); + /** + * @var array An array of attachments + * @access protected + */ protected $attachment = array(); + /** + * @var array An array of custom headers + * @access protected + */ protected $CustomHeader = array(); + /** + * @var string The message's MIME type + * @access protected + */ protected $message_type = ''; + /** + * @var array An array of MIME boundary strings + * @access protected + */ protected $boundary = array(); + /** + * @var array An array of available languages + * @access protected + */ protected $language = array(); + /** + * @var integer The number of errors encountered + * @access protected + */ protected $error_count = 0; + /** + * @var string The filename of a DKIM certificate file + * @access protected + */ protected $sign_cert_file = ''; + /** + * @var string The filename of a DKIM key file + * @access protected + */ protected $sign_key_file = ''; + /** + * @var string The password of a DKIM key + * @access protected + */ protected $sign_key_pass = ''; + /** + * @var boolean Whether to throw exceptions for errors + * @access protected + */ protected $exceptions = false; ///////////////////////////////////////////////// @@ -353,12 +516,55 @@ class PHPMailer { const STOP_MESSAGE = 0; // message only, continue processing const STOP_CONTINUE = 1; // message?, likely ok to continue processing const STOP_CRITICAL = 2; // message, plus full stop, critical error reached + const CRLF = "\r\n"; // SMTP RFC specified EOL ///////////////////////////////////////////////// // METHODS, VARIABLES ///////////////////////////////////////////////// /** + * Calls actual mail() function, but in a safe_mode aware fashion + * Also, unless sendmail_path points to sendmail (or something that + * claims to be sendmail), don't pass params (not a perfect fix, + * but it will do) + * @param string $to To + * @param string $subject Subject + * @param string $body Message Body + * @param string $header Additional Header(s) + * @param string $params Params + * @access private + * @return bool + */ + private function mail_passthru($to, $subject, $body, $header, $params) { + if ( ini_get('safe_mode') || !($this->UseSendmailOptions) ) { + $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header); + } else { + $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header, $params); + } + return $rt; + } + + /** + * Outputs debugging info via user-defined method + * @param string $str + */ + protected function edebug($str) { + switch ($this->Debugoutput) { + case 'error_log': + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking display that's HTML-safe + echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, $this->CharSet)."<br>\n"; + break; + case 'echo': + default: + //Just echoes exactly what was received + echo $str; + } + } + + /** * Constructor * @param boolean $exceptions Should we throw external exceptions? */ @@ -367,6 +573,15 @@ class PHPMailer { } /** + * Destructor + */ + public function __destruct() { + if ($this->Mailer == 'smtp') { //Close any open SMTP connection nicely + $this->SmtpClose(); + } + } + + /** * Sets message type to HTML. * @param bool $ishtml * @return void @@ -460,7 +675,7 @@ class PHPMailer { * @return boolean */ public function AddReplyTo($address, $name = '') { - return $this->AddAnAddress('ReplyTo', $address, $name); + return $this->AddAnAddress('Reply-To', $address, $name); } /** @@ -469,29 +684,34 @@ class PHPMailer { * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' * @param string $address The email address to send to * @param string $name + * @throws phpmailerException * @return boolean true on success, false if address already used or invalid in some way * @access protected */ protected function AddAnAddress($kind, $address, $name = '') { - if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) { + if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) { $this->SetError($this->Lang('Invalid recipient array').': '.$kind); if ($this->exceptions) { throw new phpmailerException('Invalid recipient array: ' . $kind); } - echo $this->Lang('Invalid recipient array').': '.$kind; + if ($this->SMTPDebug) { + $this->edebug($this->Lang('Invalid recipient array').': '.$kind); + } return false; } $address = trim($address); $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - if (!self::ValidateAddress($address)) { + if (!$this->ValidateAddress($address)) { $this->SetError($this->Lang('invalid_address').': '. $address); if ($this->exceptions) { throw new phpmailerException($this->Lang('invalid_address').': '.$address); } - echo $this->Lang('invalid_address').': '.$address; + if ($this->SMTPDebug) { + $this->edebug($this->Lang('invalid_address').': '.$address); + } return false; } - if ($kind != 'ReplyTo') { + if ($kind != 'Reply-To') { if (!isset($this->all_recipients[strtolower($address)])) { array_push($this->$kind, array($address, $name)); $this->all_recipients[strtolower($address)] = true; @@ -506,29 +726,30 @@ class PHPMailer { return false; } -/** - * Set the From and FromName properties - * @param string $address - * @param string $name - * @return boolean - */ - public function SetFrom($address, $name = '', $auto = 1) { + /** + * Set the From and FromName properties + * @param string $address + * @param string $name + * @param boolean $auto Whether to also set the Sender address, defaults to true + * @throws phpmailerException + * @return boolean + */ + public function SetFrom($address, $name = '', $auto = true) { $address = trim($address); $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - if (!self::ValidateAddress($address)) { + if (!$this->ValidateAddress($address)) { $this->SetError($this->Lang('invalid_address').': '. $address); if ($this->exceptions) { throw new phpmailerException($this->Lang('invalid_address').': '.$address); } - echo $this->Lang('invalid_address').': '.$address; + if ($this->SMTPDebug) { + $this->edebug($this->Lang('invalid_address').': '.$address); + } return false; } $this->From = $address; $this->FromName = $name; if ($auto) { - if (empty($this->ReplyTo)) { - $this->AddAnAddress('ReplyTo', $address, $name); - } if (empty($this->Sender)) { $this->Sender = $address; } @@ -538,25 +759,30 @@ class PHPMailer { /** * Check that a string looks roughly like an email address should - * Static so it can be used without instantiation - * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator - * Conforms approximately to RFC2822 - * @link http://www.hexillion.com/samples/#Regex Original pattern found here + * Static so it can be used without instantiation, public so people can overload + * Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is + * based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to + * not allow a@b type valid addresses :( + * @link http://squiloople.com/2009/12/20/email-address-validation/ + * @copyright regex Copyright Michael Rushton 2009-10 | http://squiloople.com/ | Feel free to use and redistribute this code. But please keep this copyright notice. * @param string $address The email address to check * @return boolean * @static * @access public */ public static function ValidateAddress($address) { - if (function_exists('filter_var')) { //Introduced in PHP 5.2 - if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) { - return false; + if (defined('PCRE_VERSION')) { //Check this instead of extension_loaded so it works when that function is disabled + if (version_compare(PCRE_VERSION, '8.0') >= 0) { + return (boolean)preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address); + } else { + //Fall back to an older regex that doesn't need a recent PCRE + return (boolean)preg_match('/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', $address); + } } else { - return true; + //No PCRE! Do something _very_ approximate! + //Check the address is 3 chars or longer and contains an @ that's not the first or last char + return (strlen($address) >= 3 and strpos($address, '@') >= 1 and strpos($address, '@') != strlen($address) - 1); } - } else { - return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address); - } } ///////////////////////////////////////////////// @@ -567,6 +793,7 @@ class PHPMailer { * Creates message and assigns Mailer. If the message is * not sent successfully then it returns false. Use the ErrorInfo * variable to view description of the error. + * @throws phpmailerException * @return bool */ public function Send() { @@ -574,6 +801,7 @@ class PHPMailer { if(!$this->PreSend()) return false; return $this->PostSend(); } catch (phpmailerException $e) { + $this->mailHeader = ''; $this->SetError($e->getMessage()); if ($this->exceptions) { throw $e; @@ -582,8 +810,14 @@ class PHPMailer { } } - protected function PreSend() { + /** + * Prep mail by constructing all message entities + * @throws phpmailerException + * @return bool + */ + public function PreSend() { try { + $this->mailHeader = ""; if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL); } @@ -595,22 +829,33 @@ class PHPMailer { $this->error_count = 0; // reset errors $this->SetMessageType(); - //Refuse to send an empty message - if (empty($this->Body)) { + //Refuse to send an empty message unless we are specifically allowing it + if (!$this->AllowEmpty and empty($this->Body)) { throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL); } $this->MIMEHeader = $this->CreateHeader(); $this->MIMEBody = $this->CreateBody(); + // To capture the complete message when using mail(), create + // an extra header list which CreateHeader() doesn't fold in + if ($this->Mailer == 'mail') { + if (count($this->to) > 0) { + $this->mailHeader .= $this->AddrAppend("To", $this->to); + } else { + $this->mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;"); + } + $this->mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject)))); + } // digitally sign with DKIM if enabled - if ($this->DKIM_domain && $this->DKIM_private) { - $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody); + if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) { + $header_dkim = $this->DKIM_Add($this->MIMEHeader . $this->mailHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody); $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader; } return true; + } catch (phpmailerException $e) { $this->SetError($e->getMessage()); if ($this->exceptions) { @@ -620,7 +865,13 @@ class PHPMailer { } } - protected function PostSend() { + /** + * Actual Email transport function + * Send the email via the selected mechanism + * @throws phpmailerException + * @return bool + */ + public function PostSend() { try { // Choose the mailer and send through it switch($this->Mailer) { @@ -628,35 +879,39 @@ class PHPMailer { return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody); case 'smtp': return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody); + case 'mail': + return $this->MailSend($this->MIMEHeader, $this->MIMEBody); default: return $this->MailSend($this->MIMEHeader, $this->MIMEBody); } - } catch (phpmailerException $e) { $this->SetError($e->getMessage()); if ($this->exceptions) { throw $e; } - echo $e->getMessage()."\n"; - return false; + if ($this->SMTPDebug) { + $this->edebug($e->getMessage()."\n"); + } } + return false; } /** * Sends mail using the $Sendmail program. * @param string $header The message headers * @param string $body The message body + * @throws phpmailerException * @access protected * @return bool */ protected function SendmailSend($header, $body) { if ($this->Sender != '') { - $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); } else { $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); } if ($this->SingleTo === true) { - foreach ($this->SingleToArray as $key => $val) { + foreach ($this->SingleToArray as $val) { if(!@$mail = popen($sendmail, 'w')) { throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); } @@ -692,6 +947,7 @@ class PHPMailer { * Sends mail using the PHP mail() function. * @param string $header The message headers * @param string $body The message body + * @throws phpmailerException * @access protected * @return bool */ @@ -703,40 +959,27 @@ class PHPMailer { $to = implode(', ', $toArr); if (empty($this->Sender)) { - $params = "-oi -f %s"; + $params = " "; } else { - $params = sprintf("-oi -f %s", $this->Sender); + $params = sprintf("-f%s", $this->Sender); } if ($this->Sender != '' and !ini_get('safe_mode')) { $old_from = ini_get('sendmail_from'); ini_set('sendmail_from', $this->Sender); - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); + } + $rt = false; + if ($this->SingleTo === true && count($toArr) > 1) { + foreach ($toArr as $val) { + $rt = $this->mail_passthru($val, $this->Subject, $body, $header, $params); // implement call back function if it exists $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body); + $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body); } } else { - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body); - } + $rt = $this->mail_passthru($to, $this->Subject, $body, $header, $params); + // implement call back function if it exists + $isSent = ($rt == 1) ? 1 : 0; + $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body); } if (isset($old_from)) { ini_set('sendmail_from', $old_from); @@ -752,6 +995,7 @@ class PHPMailer { * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. * @param string $header The message headers * @param string $body The message body + * @throws phpmailerException * @uses SMTP * @access protected * @return bool @@ -765,7 +1009,8 @@ class PHPMailer { } $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; if(!$this->smtp->Mail($smtp_from)) { - throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL); + $this->SetError($this->Lang('from_failed') . $smtp_from . ' : ' .implode(',', $this->smtp->getError())); + throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); } // Attempt to send attach all recipients @@ -816,6 +1061,9 @@ class PHPMailer { } if($this->SMTPKeepAlive == true) { $this->smtp->Reset(); + } else { + $this->smtp->Quit(); + $this->smtp->Close(); } return true; } @@ -823,66 +1071,76 @@ class PHPMailer { /** * Initiates a connection to an SMTP server. * Returns false if the operation failed. + * @param array $options An array of options compatible with stream_context_create() * @uses SMTP * @access public + * @throws phpmailerException * @return bool */ - public function SmtpConnect() { + public function SmtpConnect($options = array()) { if(is_null($this->smtp)) { - $this->smtp = new SMTP(); + $this->smtp = new SMTP; + } + + //Already connected? + if ($this->smtp->Connected()) { + return true; } + $this->smtp->Timeout = $this->Timeout; $this->smtp->do_debug = $this->SMTPDebug; - $hosts = explode(';', $this->Host); + $this->smtp->Debugoutput = $this->Debugoutput; + $this->smtp->do_verp = $this->do_verp; $index = 0; - $connection = $this->smtp->Connected(); - - // Retry while there is no connection - try { - while($index < count($hosts) && !$connection) { - $hostinfo = array(); - if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { - $host = $hostinfo[1]; - $port = $hostinfo[2]; - } else { - $host = $hosts[$index]; - $port = $this->Port; - } - - $tls = ($this->SMTPSecure == 'tls'); - $ssl = ($this->SMTPSecure == 'ssl'); - - if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { + $tls = ($this->SMTPSecure == 'tls'); + $ssl = ($this->SMTPSecure == 'ssl'); + $hosts = explode(';', $this->Host); + $lastexception = null; - $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); + foreach ($hosts as $hostentry) { + $hostinfo = array(); + $host = $hostentry; + $port = $this->Port; + if (preg_match('/^(.+):([0-9]+)$/', $hostentry, $hostinfo)) { //If $hostentry contains 'address:port', override default + $host = $hostinfo[1]; + $port = $hostinfo[2]; + } + if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout, $options)) { + try { + if ($this->Helo) { + $hello = $this->Helo; + } else { + $hello = $this->ServerHostname(); + } $this->smtp->Hello($hello); if ($tls) { if (!$this->smtp->StartTLS()) { - throw new phpmailerException($this->Lang('tls')); + throw new phpmailerException($this->Lang('connect_host')); } - //We must resend HELO after tls negotiation $this->smtp->Hello($hello); } - - $connection = true; if ($this->SMTPAuth) { - if (!$this->smtp->Authenticate($this->Username, $this->Password)) { + if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, $this->Realm, $this->Workstation)) { throw new phpmailerException($this->Lang('authenticate')); } } - } - $index++; - if (!$connection) { - throw new phpmailerException($this->Lang('connect_host')); + return true; + } catch (phpmailerException $e) { + $lastexception = $e; + //We must have connected, but then failed TLS or Auth, so close connection nicely + $this->smtp->Quit(); } } - } catch (phpmailerException $e) { - $this->smtp->Reset(); - throw $e; } - return true; + //If we get here, all connection attempts have failed, so close connection hard + $this->smtp->Close(); + //As we've caught all exceptions, just report whatever the last one was + if ($this->exceptions and !is_null($lastexception)) { + throw $lastexception; + } + return false; } /** @@ -890,7 +1148,7 @@ class PHPMailer { * @return void */ public function SmtpClose() { - if(!is_null($this->smtp)) { + if ($this->smtp !== null) { if($this->smtp->Connected()) { $this->smtp->Quit(); $this->smtp->Close(); @@ -899,32 +1157,34 @@ class PHPMailer { } /** - * Sets the language for all class error messages. - * Returns false if it cannot load the language file. The default language is English. - * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") - * @param string $lang_path Path to the language file directory - * @access public - */ + * Sets the language for all class error messages. + * Returns false if it cannot load the language file. The default language is English. + * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") + * @param string $lang_path Path to the language file directory + * @return bool + * @access public + */ function SetLanguage($langcode = 'en', $lang_path = 'language/') { //Define full set of translatable strings $PHPMAILER_LANG = array( - 'provide_address' => 'You must provide at least one recipient email address.', + 'authenticate' => 'SMTP Error: Could not authenticate.', + 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', + 'data_not_accepted' => 'SMTP Error: Data not accepted.', + 'empty_message' => 'Message body empty', + 'encoding' => 'Unknown encoding: ', + 'execute' => 'Could not execute: ', + 'file_access' => 'Could not access file: ', + 'file_open' => 'File Error: Could not open file: ', + 'from_failed' => 'The following From address failed: ', + 'instantiate' => 'Could not instantiate mail function.', + 'invalid_address' => 'Invalid address', 'mailer_not_supported' => ' mailer is not supported.', - 'execute' => 'Could not execute: ', - 'instantiate' => 'Could not instantiate mail function.', - 'authenticate' => 'SMTP Error: Could not authenticate.', - 'from_failed' => 'The following From address failed: ', - 'recipients_failed' => 'SMTP Error: The following recipients failed: ', - 'data_not_accepted' => 'SMTP Error: Data not accepted.', - 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', - 'file_access' => 'Could not access file: ', - 'file_open' => 'File Error: Could not open file: ', - 'encoding' => 'Unknown encoding: ', - 'signing' => 'Signing Error: ', - 'smtp_error' => 'SMTP server error: ', - 'empty_message' => 'Message body empty', - 'invalid_address' => 'Invalid address', - 'variable_set' => 'Cannot set or reset variable: ' + 'provide_address' => 'You must provide at least one recipient email address.', + 'recipients_failed' => 'SMTP Error: The following recipients failed: ', + 'signing' => 'Signing Error: ', + 'smtp_connect_failed' => 'SMTP Connect() failed.', + 'smtp_error' => 'SMTP server error: ', + 'variable_set' => 'Cannot set or reset variable: ' ); //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"! $l = true; @@ -950,6 +1210,8 @@ class PHPMailer { /** * Creates recipient headers. * @access public + * @param string $type + * @param array $addr * @return string */ public function AddrAppend($type, $addr) { @@ -967,6 +1229,7 @@ class PHPMailer { /** * Formats an address correctly. * @access public + * @param string $addr * @return string */ public function AddrFormat($addr) { @@ -992,13 +1255,15 @@ class PHPMailer { // If utf-8 encoding is used, we will need to make sure we don't // split multibyte characters when we wrap $is_utf8 = (strtolower($this->CharSet) == "utf-8"); + $lelen = strlen($this->LE); + $crlflen = strlen(self::CRLF); $message = $this->FixEOL($message); - if (substr($message, -1) == $this->LE) { - $message = substr($message, 0, -1); + if (substr($message, -$lelen) == $this->LE) { + $message = substr($message, 0, -$lelen); } - $line = explode($this->LE, $message); + $line = explode($this->LE, $message); // Magic. We know FixEOL uses $LE $message = ''; for ($i = 0 ;$i < count($line); $i++) { $line_part = explode(' ', $line[$i]); @@ -1006,7 +1271,7 @@ class PHPMailer { for ($e = 0; $e<count($line_part); $e++) { $word = $line_part[$e]; if ($qp_mode and (strlen($word) > $length)) { - $space_left = $length - strlen($buf) - 1; + $space_left = $length - strlen($buf) - $crlflen; if ($e != 0) { if ($space_left > 20) { $len = $space_left; @@ -1020,13 +1285,16 @@ class PHPMailer { $part = substr($word, 0, $len); $word = substr($word, $len); $buf .= ' ' . $part; - $message .= $buf . sprintf("=%s", $this->LE); + $message .= $buf . sprintf("=%s", self::CRLF); } else { $message .= $buf . $soft_break; } $buf = ''; } while (strlen($word) > 0) { + if ($length <= 0) { + break; + } $len = $length; if ($is_utf8) { $len = $this->UTF8CharBoundary($word, $len); @@ -1039,7 +1307,7 @@ class PHPMailer { $word = substr($word, $len); if (strlen($word) > 0) { - $message .= $part . sprintf("=%s", $this->LE); + $message .= $part . sprintf("=%s", self::CRLF); } else { $buf = $part; } @@ -1054,7 +1322,7 @@ class PHPMailer { } } } - $message .= $buf . $this->LE; + $message .= $buf . self::CRLF; } return $message; @@ -1139,11 +1407,18 @@ class PHPMailer { $this->boundary[2] = 'b2_' . $uniq_id; $this->boundary[3] = 'b3_' . $uniq_id; - $result .= $this->HeaderLine('Date', self::RFCDate()); - if($this->Sender == '') { - $result .= $this->HeaderLine('Return-Path', trim($this->From)); + if ($this->MessageDate == '') { + $result .= $this->HeaderLine('Date', self::RFCDate()); + } else { + $result .= $this->HeaderLine('Date', $this->MessageDate); + } + + if ($this->ReturnPath) { + $result .= $this->HeaderLine('Return-Path', '<'.trim($this->ReturnPath).'>'); + } elseif ($this->Sender == '') { + $result .= $this->HeaderLine('Return-Path', '<'.trim($this->From).'>'); } else { - $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); + $result .= $this->HeaderLine('Return-Path', '<'.trim($this->Sender).'>'); } // To be created automatically by mail() @@ -1177,7 +1452,7 @@ class PHPMailer { } if(count($this->ReplyTo) > 0) { - $result .= $this->AddrAppend('Reply-to', $this->ReplyTo); + $result .= $this->AddrAppend('Reply-To', $this->ReplyTo); } // mail() sets the subject itself @@ -1191,10 +1466,13 @@ class PHPMailer { $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); } $result .= $this->HeaderLine('X-Priority', $this->Priority); - if($this->XMailer) { - $result .= $this->HeaderLine('X-Mailer', $this->XMailer); + if ($this->XMailer == '') { + $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (https://github.com/PHPMailer/PHPMailer/)'); } else { - $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)'); + $myXmailer = trim($this->XMailer); + if ($myXmailer) { + $result .= $this->HeaderLine('X-Mailer', $myXmailer); + } } if($this->ConfirmReadingTo != '') { @@ -1221,76 +1499,88 @@ class PHPMailer { public function GetMailMIME() { $result = ''; switch($this->message_type) { - case 'plain': - $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); - $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset="'.$this->CharSet.'"'); - break; case 'inline': $result .= $this->HeaderLine('Content-Type', 'multipart/related;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"'); break; case 'attach': case 'inline_attach': case 'alt_attach': case 'alt_inline_attach': $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"'); break; case 'alt': case 'alt_inline': $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"'); break; + default: + // Catches case 'plain': and case '': + $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset='.$this->CharSet); + break; + } + //RFC1341 part 5 says 7bit is assumed if not specified + if ($this->Encoding != '7bit') { + $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); } if($this->Mailer != 'mail') { - $result .= $this->LE.$this->LE; + $result .= $this->LE; } return $result; } /** + * Returns the MIME message (headers and body). Only really valid post PreSend(). + * @access public + * @return string + */ + public function GetSentMIMEMessage() { + return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; + } + + + /** * Assembles the message body. Returns an empty string on failure. * @access public + * @throws phpmailerException * @return string The assembled message body */ public function CreateBody() { $body = ''; if ($this->sign_key_file) { - $body .= $this->GetMailMIME(); + $body .= $this->GetMailMIME().$this->LE; } $this->SetWordWrap(); switch($this->message_type) { - case 'plain': - $body .= $this->EncodeString($this->Body, $this->Encoding); - break; case 'inline': $body .= $this->GetBoundary($this->boundary[1], '', '', ''); $body .= $this->EncodeString($this->Body, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->AttachAll("inline", $this->boundary[1]); + $body .= $this->AttachAll('inline', $this->boundary[1]); break; case 'attach': $body .= $this->GetBoundary($this->boundary[1], '', '', ''); $body .= $this->EncodeString($this->Body, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->AttachAll("attachment", $this->boundary[1]); + $body .= $this->AttachAll('attachment', $this->boundary[1]); break; case 'inline_attach': - $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->TextLine('--' . $this->boundary[1]); $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); - $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); $body .= $this->LE; $body .= $this->GetBoundary($this->boundary[2], '', '', ''); $body .= $this->EncodeString($this->Body, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->AttachAll("inline", $this->boundary[2]); + $body .= $this->AttachAll('inline', $this->boundary[2]); $body .= $this->LE; - $body .= $this->AttachAll("attachment", $this->boundary[1]); + $body .= $this->AttachAll('attachment', $this->boundary[1]); break; case 'alt': $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); @@ -1299,27 +1589,32 @@ class PHPMailer { $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); $body .= $this->EncodeString($this->Body, $this->Encoding); $body .= $this->LE.$this->LE; + if(!empty($this->Ical)) { + $body .= $this->GetBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', ''); + $body .= $this->EncodeString($this->Ical, $this->Encoding); + $body .= $this->LE.$this->LE; + } $body .= $this->EndBoundary($this->boundary[1]); break; case 'alt_inline': $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); $body .= $this->EncodeString($this->AltBody, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->TextLine('--' . $this->boundary[1]); $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); - $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); $body .= $this->LE; $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', ''); $body .= $this->EncodeString($this->Body, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->AttachAll("inline", $this->boundary[2]); + $body .= $this->AttachAll('inline', $this->boundary[2]); $body .= $this->LE; $body .= $this->EndBoundary($this->boundary[1]); break; case 'alt_attach': - $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->TextLine('--' . $this->boundary[1]); $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); - $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); $body .= $this->LE; $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', ''); $body .= $this->EncodeString($this->AltBody, $this->Encoding); @@ -1329,28 +1624,32 @@ class PHPMailer { $body .= $this->LE.$this->LE; $body .= $this->EndBoundary($this->boundary[2]); $body .= $this->LE; - $body .= $this->AttachAll("attachment", $this->boundary[1]); + $body .= $this->AttachAll('attachment', $this->boundary[1]); break; case 'alt_inline_attach': - $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->TextLine('--' . $this->boundary[1]); $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); - $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); $body .= $this->LE; $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', ''); $body .= $this->EncodeString($this->AltBody, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->TextLine("--" . $this->boundary[2]); + $body .= $this->TextLine('--' . $this->boundary[2]); $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); - $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3].'"'); $body .= $this->LE; $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', ''); $body .= $this->EncodeString($this->Body, $this->Encoding); $body .= $this->LE.$this->LE; - $body .= $this->AttachAll("inline", $this->boundary[3]); + $body .= $this->AttachAll('inline', $this->boundary[3]); $body .= $this->LE; $body .= $this->EndBoundary($this->boundary[2]); $body .= $this->LE; - $body .= $this->AttachAll("attachment", $this->boundary[1]); + $body .= $this->AttachAll('attachment', $this->boundary[1]); + break; + default: + // catch case 'plain' and case '' + $body .= $this->EncodeString($this->Body, $this->Encoding); break; } @@ -1358,17 +1657,20 @@ class PHPMailer { $body = ''; } elseif ($this->sign_key_file) { try { - $file = tempnam('', 'mail'); + if (!defined('PKCS7_TEXT')) { + throw new phpmailerException($this->Lang('signing').' OpenSSL extension missing.'); + } + $file = tempnam(sys_get_temp_dir(), 'mail'); file_put_contents($file, $body); //TODO check this worked - $signed = tempnam("", "signed"); - if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) { + $signed = tempnam(sys_get_temp_dir(), 'signed'); + if (@openssl_pkcs7_sign($file, $signed, 'file://'.realpath($this->sign_cert_file), array('file://'.realpath($this->sign_key_file), $this->sign_key_pass), null)) { @unlink($file); - @unlink($signed); $body = file_get_contents($signed); + @unlink($signed); } else { @unlink($file); @unlink($signed); - throw new phpmailerException($this->Lang("signing").openssl_error_string()); + throw new phpmailerException($this->Lang('signing').openssl_error_string()); } } catch (phpmailerException $e) { $body = ''; @@ -1377,13 +1679,16 @@ class PHPMailer { } } } - return $body; } /** * Returns the start of a message boundary. * @access protected + * @param string $boundary + * @param string $charSet + * @param string $contentType + * @param string $encoding * @return string */ protected function GetBoundary($boundary, $charSet, $contentType, $encoding) { @@ -1398,7 +1703,7 @@ class PHPMailer { $encoding = $this->Encoding; } $result .= $this->TextLine('--' . $boundary); - $result .= sprintf("Content-Type: %s; charset=\"%s\"", $contentType, $charSet); + $result .= sprintf("Content-Type: %s; charset=%s", $contentType, $charSet); $result .= $this->LE; $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); $result .= $this->LE; @@ -1409,6 +1714,7 @@ class PHPMailer { /** * Returns the end of a message boundary. * @access protected + * @param string $boundary * @return string */ protected function EndBoundary($boundary) { @@ -1430,8 +1736,10 @@ class PHPMailer { } /** - * Returns a formatted header line. + * Returns a formatted header line. * @access public + * @param string $name + * @param string $value * @return string */ public function HeaderLine($name, $value) { @@ -1441,6 +1749,7 @@ class PHPMailer { /** * Returns a formatted mail line. * @access public + * @param string $value * @return string */ public function TextLine($value) { @@ -1459,13 +1768,20 @@ class PHPMailer { * @param string $name Overrides the attachment name. * @param string $encoding File encoding (see $Encoding). * @param string $type File extension (MIME) type. + * @throws phpmailerException * @return bool */ - public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { + public function AddAttachment($path, $name = '', $encoding = 'base64', $type = '') { try { if ( !@is_file($path) ) { throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE); } + + //If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + $filename = basename($path); if ( $name == '' ) { $name = $filename; @@ -1487,10 +1803,10 @@ class PHPMailer { if ($this->exceptions) { throw $e; } - echo $e->getMessage()."\n"; - if ( $e->getCode() == self::STOP_CRITICAL ) { - return false; + if ($this->SMTPDebug) { + $this->edebug($e->getMessage()."\n"); } + return false; } return true; } @@ -1507,6 +1823,8 @@ class PHPMailer { * Attaches all fs, string, and binary attachments to the message. * Returns an empty string on failure. * @access protected + * @param string $disposition_type + * @param string $boundary * @return string */ protected function AttachAll($disposition_type, $boundary) { @@ -1520,6 +1838,8 @@ class PHPMailer { // CHECK IF IT IS A VALID DISPOSITION_FILTER if($attachment[6] == $disposition_type) { // Check for string attachment + $string = ''; + $path = ''; $bString = $attachment[5]; if ($bString) { $string = $attachment[0]; @@ -1547,7 +1867,13 @@ class PHPMailer { $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); } - $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + //If a filename contains any of these chars, it should be quoted, but not otherwise: RFC2183 & RFC2045 5.1 + //Fixes a warning in IETF's msglint MIME checker + if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) { + $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + } else { + $mime[] = sprintf("Content-Disposition: %s; filename=%s%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + } // Encode as string attachment if($bString) { @@ -1576,6 +1902,7 @@ class PHPMailer { * Returns an empty string on failure. * @param string $path The full path to the file * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @throws phpmailerException * @see EncodeFile() * @access protected * @return string @@ -1585,19 +1912,22 @@ class PHPMailer { if (!is_readable($path)) { throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE); } - if (function_exists('get_magic_quotes')) { - function get_magic_quotes() { - return false; + $magic_quotes = get_magic_quotes_runtime(); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime(0); + } else { + ini_set('magic_quotes_runtime', 0); } } - if (version_compare(PHP_VERSION, '5.3.0', '<')) { - $magic_quotes = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - } $file_buffer = file_get_contents($path); $file_buffer = $this->EncodeString($file_buffer, $encoding); - if (version_compare(PHP_VERSION, '5.3.0', '<')) { - set_magic_quotes_runtime($magic_quotes); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime($magic_quotes); + } else { + ini_set('magic_quotes_runtime', $magic_quotes); + } } return $file_buffer; } catch (Exception $e) { @@ -1643,6 +1973,8 @@ class PHPMailer { /** * Encode a header string to best (shortest) of Q, B, quoted or none. * @access public + * @param string $str + * @param string $position * @return string */ public function EncodeHeader($str, $position = 'text') { @@ -1670,18 +2002,18 @@ class PHPMailer { break; } - if ($x == 0) { + if ($x == 0) { //There are no chars that need encoding return ($str); } $maxlen = 75 - 7 - strlen($this->CharSet); // Try to select the encoding which should produce the shortest output - if (strlen($str)/3 < $x) { + if ($x > strlen($str)/3) { //More than a third of the content will need encoding, so B encoding will be most efficient $encoding = 'B'; if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { // Use a custom function which correctly encodes and wraps long // multibyte strings without breaking lines within a character - $encoded = $this->Base64EncodeWrapMB($str); + $encoded = $this->Base64EncodeWrapMB($str, "\n"); } else { $encoded = base64_encode($str); $maxlen -= $maxlen % 4; @@ -1691,7 +2023,7 @@ class PHPMailer { $encoding = 'Q'; $encoded = $this->EncodeQ($str, $position); $encoded = $this->WrapText($encoded, $maxlen, true); - $encoded = str_replace('='.$this->LE, "\n", trim($encoded)); + $encoded = str_replace('='.self::CRLF, "\n", trim($encoded)); } $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); @@ -1720,12 +2052,16 @@ class PHPMailer { * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php * @access public * @param string $str multi-byte text to wrap encode + * @param string $lf string to use as linefeed/end-of-line * @return string */ - public function Base64EncodeWrapMB($str) { + public function Base64EncodeWrapMB($str, $lf=null) { $start = "=?".$this->CharSet."?B?"; $end = "?="; $encoded = ""; + if ($lf === null) { + $lf = $this->LE; + } $mb_length = mb_strlen($str, $this->CharSet); // Each line must have length <= 75, including $start and $end @@ -1746,94 +2082,43 @@ class PHPMailer { } while (strlen($chunk) > $length); - $encoded .= $chunk . $this->LE; + $encoded .= $chunk . $lf; } // Chomp the last linefeed - $encoded = substr($encoded, 0, -strlen($this->LE)); + $encoded = substr($encoded, 0, -strlen($lf)); return $encoded; } /** - * Encode string to quoted-printable. - * Only uses standard PHP, slow, but will always work - * @access public - * @param string $string the text to encode - * @param integer $line_max Number of chars allowed on a line before wrapping - * @return string - */ - public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) { - $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); - $lines = preg_split('/(?:\r\n|\r|\n)/', $input); - $eol = "\r\n"; - $escape = '='; - $output = ''; - while( list(, $line) = each($lines) ) { - $linlen = strlen($line); - $newline = ''; - for($i = 0; $i < $linlen; $i++) { - $c = substr( $line, $i, 1 ); - $dec = ord( $c ); - if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E - $c = '=2E'; - } - if ( $dec == 32 ) { - if ( $i == ( $linlen - 1 ) ) { // convert space at eol only - $c = '=20'; - } else if ( $space_conv ) { - $c = '=20'; - } - } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required - $h2 = floor($dec/16); - $h1 = floor($dec%16); - $c = $escape.$hex[$h2].$hex[$h1]; - } - if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted - $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay - $newline = ''; - // check if newline first character will be point or not - if ( $dec == 46 ) { - $c = '=2E'; - } - } - $newline .= $c; - } // end of for - $output .= $newline.$eol; - } // end of while - return $output; - } - - /** - * Encode string to RFC2045 (6.7) quoted-printable format - * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version - * Also results in same content as you started with after decoding - * @see EncodeQPphp() - * @access public - * @param string $string the text to encode - * @param integer $line_max Number of chars allowed on a line before wrapping - * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function - * @return string - * @author Marcus Bointon - */ - public function EncodeQP($string, $line_max = 76, $space_conv = false) { + * Encode string to RFC2045 (6.7) quoted-printable format + * @access public + * @param string $string The text to encode + * @param integer $line_max Number of chars allowed on a line before wrapping + * @return string + * @link PHP version adapted from http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 + */ + public function EncodeQP($string, $line_max = 76) { if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) return quoted_printable_encode($string); } - $filters = stream_get_filters(); - if (!in_array('convert.*', $filters)) { //Got convert stream filter? - return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation - } - $fp = fopen('php://temp/', 'r+'); - $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks - $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); - $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); - fputs($fp, $string); - rewind($fp); - $out = stream_get_contents($fp); - stream_filter_remove($s); - $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange - fclose($fp); - return $out; + //Fall back to a pure PHP implementation + $string = str_replace(array('%20', '%0D%0A.', '%0D%0A', '%'), array(' ', "\r\n=2E", "\r\n", '='), rawurlencode($string)); + $string = preg_replace('/[^\r\n]{'.($line_max - 3).'}[^=\r\n]{2}/', "$0=\r\n", $string); + return $string; + } + + /** + * Wrapper to preserve BC for old QP encoding function that was removed + * @see EncodeQP() + * @access public + * @param string $string + * @param integer $line_max + * @param bool $space_conv + * @return string + */ + public function EncodeQPphp($string, $line_max = 76, $space_conv = false) { + return $this->EncodeQP($string, $line_max); } /** @@ -1845,29 +2130,37 @@ class PHPMailer { * @return string */ public function EncodeQ($str, $position = 'text') { - // There should not be any EOL in the string - $encoded = preg_replace('/[\r\n]*/', '', $str); - + //There should not be any EOL in the string + $pattern = ''; + $encoded = str_replace(array("\r", "\n"), '', $str); switch (strtolower($position)) { case 'phrase': - $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); + $pattern = '^A-Za-z0-9!*+\/ -'; break; + case 'comment': - $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); + $pattern = '\(\)"'; + //note that we don't break here! + //for this reason we build the $pattern without including delimiters and [] + case 'text': default: - // Replace every high ascii, control =, ? and _ characters - //TODO using /e (equivalent to eval()) is probably not a good idea - $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', - "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded); + //Replace every high ascii, control =, ? and _ characters + //We put \075 (=) as first value to make sure it's the first one in being converted, preventing double encode + $pattern = '\075\000-\011\013\014\016-\037\077\137\177-\377' . $pattern; break; } - // Replace every spaces to _ (more readable than =20) - $encoded = str_replace(' ', '_', $encoded); + if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { + foreach (array_unique($matches[0]) as $char) { + $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); + } + } + + //Replace every spaces to _ (more readable than =20) + return str_replace(' ', '_', $encoded); +} - return $encoded; - } /** * Adds a string or binary attachment (non-filesystem) to the list. @@ -1879,7 +2172,11 @@ class PHPMailer { * @param string $type File extension (MIME) type. * @return void */ - public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { + public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = '') { + //If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($filename); + } // Append to $attachment array $this->attachment[] = array( 0 => $string, @@ -1894,25 +2191,27 @@ class PHPMailer { } /** - * Adds an embedded attachment. This can include images, sounds, and - * just about any other document. Make sure to set the $type to an - * image type. For JPEG images use "image/jpeg" and for GIF images - * use "image/gif". + * Add an embedded attachment from a file. + * This can include images, sounds, and just about any other document type. * @param string $path Path to the attachment. - * @param string $cid Content ID of the attachment. Use this to identify - * the Id for accessing the image in an HTML form. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. * @param string $name Overrides the attachment name. * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool + * @param string $type File MIME type. + * @return bool True on successfully adding an attachment */ - public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - + public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '') { if ( !@is_file($path) ) { $this->SetError($this->Lang('file_access') . $path); return false; } + //If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + $filename = basename($path); if ( $name == '' ) { $name = $filename; @@ -1929,22 +2228,41 @@ class PHPMailer { 6 => 'inline', 7 => $cid ); - return true; } - public function AddStringEmbeddedImage($string, $cid, $filename = '', $encoding = 'base64', $type = 'application/octet-stream') { + + /** + * Add an embedded stringified attachment. + * This can include images, sounds, and just about any other document type. + * Be sure to set the $type to an image type for images: + * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'. + * @param string $string The attachment binary data. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name + * @param string $encoding File encoding (see $Encoding). + * @param string $type MIME type. + * @return bool True on successfully adding an attachment + */ + public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = '') { + //If a MIME type is not specified, try to work it out from the name + if ($type == '') { + $type = self::filenameToType($name); + } + // Append to $attachment array $this->attachment[] = array( 0 => $string, - 1 => $filename, - 2 => basename($filename), + 1 => $name, + 2 => $name, 3 => $encoding, 4 => $type, 5 => true, // isStringAttachment 6 => 'inline', 7 => $cid ); + return true; } /** @@ -1961,6 +2279,10 @@ class PHPMailer { return false; } + /** + * Returns true if an attachment (non-inline) is present. + * @return bool + */ public function AttachmentExists() { foreach($this->attachment as $attachment) { if ($attachment[6] == 'attachment') { @@ -1970,8 +2292,12 @@ class PHPMailer { return false; } + /** + * Does this message have an alternative body set? + * @return bool + */ public function AlternativeExists() { - return strlen($this->AltBody)>0; + return !empty($this->AltBody); } ///////////////////////////////////////////////// @@ -2055,6 +2381,7 @@ class PHPMailer { /** * Adds the error message to the error container. * @access protected + * @param string $msg * @return void */ protected function SetError($msg) { @@ -2075,13 +2402,10 @@ class PHPMailer { * @static */ public static function RFCDate() { - $tz = date('Z'); - $tzs = ($tz < 0) ? '-' : '+'; - $tz = abs($tz); - $tz = (int)($tz/3600)*100 + ($tz%3600)/60; - $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); - - return $result; + //Set the time zone to whatever the default is to avoid 500 errors + //Will default to UTC if it's not set properly in php.ini + date_default_timezone_set(@date_default_timezone_get()); + return date('D, j M Y H:i:s O'); } /** @@ -2104,6 +2428,7 @@ class PHPMailer { /** * Returns a message in the appropriate language. * @access protected + * @param string $key * @return string */ protected function Lang($key) { @@ -2128,84 +2453,121 @@ class PHPMailer { } /** - * Changes every end of line from CR or LF to CRLF. + * Changes every end of line from CRLF, CR or LF to $this->LE. * @access public + * @param string $str String to FixEOL * @return string */ public function FixEOL($str) { - $str = str_replace("\r\n", "\n", $str); - $str = str_replace("\r", "\n", $str); - $str = str_replace("\n", $this->LE, $str); - return $str; + // condense down to \n + $nstr = str_replace(array("\r\n", "\r"), "\n", $str); + // Now convert LE as needed + if ($this->LE !== "\n") { + $nstr = str_replace("\n", $this->LE, $nstr); + } + return $nstr; } /** - * Adds a custom header. + * Adds a custom header. $name value can be overloaded to contain + * both header name and value (name:value) * @access public + * @param string $name custom header name + * @param string $value header value * @return void */ - public function AddCustomHeader($custom_header) { - $this->CustomHeader[] = explode(':', $custom_header, 2); + public function AddCustomHeader($name, $value=null) { + if ($value === null) { + // Value passed in as name:value + $this->CustomHeader[] = explode(':', $name, 2); + } else { + $this->CustomHeader[] = array($name, $value); + } } /** - * Evaluates the message and returns modifications for inline images and backgrounds + * Creates a message from an HTML string, making modifications for inline images and backgrounds + * and creates a plain-text version by converting the HTML + * Overwrites any existing values in $this->Body and $this->AltBody * @access public - * @return $message + * @param string $message HTML message string + * @param string $basedir baseline directory for path + * @param bool $advanced Whether to use the advanced HTML to text converter + * @return string $message */ - public function MsgHTML($message, $basedir = '') { - preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); - if(isset($images[2])) { - foreach($images[2] as $i => $url) { + public function MsgHTML($message, $basedir = '', $advanced = false) { + preg_match_all("/(src|background)=[\"'](.*)[\"']/Ui", $message, $images); + if (isset($images[2])) { + foreach ($images[2] as $i => $url) { // do not change urls for absolute images (thanks to corvuscorax) if (!preg_match('#^[A-z]+://#', $url)) { $filename = basename($url); $directory = dirname($url); - ($directory == '.') ? $directory='': ''; - $cid = 'cid:' . md5($filename); - $ext = pathinfo($filename, PATHINFO_EXTENSION); - $mimeType = self::_mime_types($ext); - if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; } - if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; } - if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType) ) { - $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message); + if ($directory == '.') { + $directory = ''; + } + $cid = md5($url).'@phpmailer.0'; //RFC2392 S 2 + if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { + $basedir .= '/'; + } + if (strlen($directory) > 1 && substr($directory, -1) != '/') { + $directory .= '/'; + } + if ($this->AddEmbeddedImage($basedir.$directory.$filename, $cid, $filename, 'base64', self::_mime_types(self::mb_pathinfo($filename, PATHINFO_EXTENSION)))) { + $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"cid:".$cid."\"", $message); } } } } $this->IsHTML(true); - $this->Body = $message; - $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message))); - if (!empty($textMsg) && empty($this->AltBody)) { - $this->AltBody = html_entity_decode($textMsg); - } if (empty($this->AltBody)) { $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; } + //Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better + $this->Body = $this->NormalizeBreaks($message); + $this->AltBody = $this->NormalizeBreaks($this->html2text($message, $advanced)); + return $this->Body; + } + + /** + * Convert an HTML string into a plain text version + * @param string $html The HTML text to convert + * @param bool $advanced Should this use the more complex html2text converter or just a simple one? + * @return string + */ + public function html2text($html, $advanced = false) { + if ($advanced) { + require_once 'extras/class.html2text.php'; + $h = new html2text($html); + return $h->get_text(); + } + return html_entity_decode(trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), ENT_QUOTES, $this->CharSet); } /** * Gets the MIME type of the embedded or inline image - * @param string File extension + * @param string $ext File extension * @access public * @return string MIME type of ext * @static */ public static function _mime_types($ext = '') { $mimes = array( + 'xl' => 'application/excel', 'hqx' => 'application/mac-binhex40', 'cpt' => 'application/mac-compactpro', - 'doc' => 'application/msword', 'bin' => 'application/macbinary', + 'doc' => 'application/msword', + 'word' => 'application/msword', + 'class' => 'application/octet-stream', + 'dll' => 'application/octet-stream', 'dms' => 'application/octet-stream', + 'exe' => 'application/octet-stream', 'lha' => 'application/octet-stream', 'lzh' => 'application/octet-stream', - 'exe' => 'application/octet-stream', - 'class' => 'application/octet-stream', 'psd' => 'application/octet-stream', - 'so' => 'application/octet-stream', 'sea' => 'application/octet-stream', - 'dll' => 'application/octet-stream', + 'so' => 'application/octet-stream', 'oda' => 'application/oda', 'pdf' => 'application/pdf', 'ai' => 'application/postscript', @@ -2223,9 +2585,9 @@ class PHPMailer { 'dxr' => 'application/x-director', 'dvi' => 'application/x-dvi', 'gtar' => 'application/x-gtar', - 'php' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php' => 'application/x-httpd-php', 'phtml' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'js' => 'application/x-javascript', @@ -2233,69 +2595,131 @@ class PHPMailer { 'sit' => 'application/x-stuffit', 'tar' => 'application/x-tar', 'tgz' => 'application/x-tar', - 'xhtml' => 'application/xhtml+xml', 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', 'zip' => 'application/zip', 'mid' => 'audio/midi', 'midi' => 'audio/midi', - 'mpga' => 'audio/mpeg', 'mp2' => 'audio/mpeg', 'mp3' => 'audio/mpeg', + 'mpga' => 'audio/mpeg', 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', 'ram' => 'audio/x-pn-realaudio', 'rm' => 'audio/x-pn-realaudio', 'rpm' => 'audio/x-pn-realaudio-plugin', 'ra' => 'audio/x-realaudio', - 'rv' => 'video/vnd.rn-realvideo', 'wav' => 'audio/x-wav', 'bmp' => 'image/bmp', 'gif' => 'image/gif', 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', 'jpe' => 'image/jpeg', + 'jpg' => 'image/jpeg', 'png' => 'image/png', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', + 'eml' => 'message/rfc822', 'css' => 'text/css', 'html' => 'text/html', 'htm' => 'text/html', 'shtml' => 'text/html', - 'txt' => 'text/plain', - 'text' => 'text/plain', 'log' => 'text/plain', + 'text' => 'text/plain', + 'txt' => 'text/plain', 'rtx' => 'text/richtext', 'rtf' => 'text/rtf', 'xml' => 'text/xml', 'xsl' => 'text/xml', 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', 'mpe' => 'video/mpeg', - 'qt' => 'video/quicktime', + 'mpg' => 'video/mpeg', 'mov' => 'video/quicktime', + 'qt' => 'video/quicktime', + 'rv' => 'video/vnd.rn-realvideo', 'avi' => 'video/x-msvideo', - 'movie' => 'video/x-sgi-movie', - 'doc' => 'application/msword', - 'word' => 'application/msword', - 'xl' => 'application/excel', - 'eml' => 'message/rfc822' + 'movie' => 'video/x-sgi-movie' ); return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; } /** - * Set (or reset) Class Objects (variables) - * - * Usage Example: - * $page->set('X-Priority', '3'); - * - * @access public - * @param string $name Parameter Name - * @param mixed $value Parameter Value - * NOTE: will not work with arrays, there are no arrays to set/reset - * @todo Should this not be using __set() magic function? - */ + * Try to map a file name to a MIME type, default to application/octet-stream + * @param string $filename A file name or full path, does not need to exist as a file + * @return string + * @static + */ + public static function filenameToType($filename) { + //In case the path is a URL, strip any query string before getting extension + $qpos = strpos($filename, '?'); + if ($qpos !== false) { + $filename = substr($filename, 0, $qpos); + } + $pathinfo = self::mb_pathinfo($filename); + return self::_mime_types($pathinfo['extension']); + } + + /** + * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe. + * Works similarly to the one in PHP >= 5.2.0 + * @link http://www.php.net/manual/en/function.pathinfo.php#107461 + * @param string $path A filename or path, does not need to exist as a file + * @param integer|string $options Either a PATHINFO_* constant, or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2 + * @return string|array + * @static + */ + public static function mb_pathinfo($path, $options = null) { + $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); + $m = array(); + preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m); + if(array_key_exists(1, $m)) { + $ret['dirname'] = $m[1]; + } + if(array_key_exists(2, $m)) { + $ret['basename'] = $m[2]; + } + if(array_key_exists(5, $m)) { + $ret['extension'] = $m[5]; + } + if(array_key_exists(3, $m)) { + $ret['filename'] = $m[3]; + } + switch($options) { + case PATHINFO_DIRNAME: + case 'dirname': + return $ret['dirname']; + break; + case PATHINFO_BASENAME: + case 'basename': + return $ret['basename']; + break; + case PATHINFO_EXTENSION: + case 'extension': + return $ret['extension']; + break; + case PATHINFO_FILENAME: + case 'filename': + return $ret['filename']; + break; + default: + return $ret; + } + } + + /** + * Set (or reset) Class Objects (variables) + * + * Usage Example: + * $page->set('X-Priority', '3'); + * + * @access public + * @param string $name + * @param mixed $value + * NOTE: will not work with arrays, there are no arrays to set/reset + * @throws phpmailerException + * @return bool + * @todo Should this not be using __set() magic function? + */ public function set($name, $value = '') { try { if (isset($this->$name) ) { @@ -2315,20 +2739,33 @@ class PHPMailer { /** * Strips newlines to prevent header injection. * @access public - * @param string $str String + * @param string $str * @return string */ public function SecureHeader($str) { - $str = str_replace("\r", '', $str); - $str = str_replace("\n", '', $str); - return trim($str); + return trim(str_replace(array("\r", "\n"), '', $str)); } /** + * Normalize UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format + * Defaults to CRLF (for message bodies) and preserves consecutive breaks + * @param string $text + * @param string $breaktype What kind of line break to use, defaults to CRLF + * @return string + * @access public + * @static + */ + public static function NormalizeBreaks($text, $breaktype = "\r\n") { + return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text); + } + + + /** * Set the private key file and password to sign the message. * * @access public - * @param string $key_filename Parameter File Name + * @param string $cert_filename + * @param string $key_filename * @param string $key_pass Password for private key */ public function Sign($cert_filename, $key_filename, $key_pass) { @@ -2341,11 +2778,10 @@ class PHPMailer { * Set the private key file and password to sign the message. * * @access public - * @param string $key_filename Parameter File Name - * @param string $key_pass Password for private key + * @param string $txt + * @return string */ public function DKIM_QP($txt) { - $tmp = ''; $line = ''; for ($i = 0; $i < strlen($txt); $i++) { $ord = ord($txt[$i]); @@ -2363,8 +2799,16 @@ class PHPMailer { * * @access public * @param string $s Header + * @throws phpmailerException + * @return string */ public function DKIM_Sign($s) { + if (!defined('PKCS7_TEXT')) { + if ($this->exceptions) { + throw new phpmailerException($this->Lang("signing").' OpenSSL extension missing.'); + } + return ''; + } $privKeyStr = file_get_contents($this->DKIM_private); if ($this->DKIM_passphrase != '') { $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); @@ -2374,6 +2818,7 @@ class PHPMailer { if (openssl_sign($s, $signature, $privKey)) { return base64_encode($signature); } + return ''; } /** @@ -2381,6 +2826,7 @@ class PHPMailer { * * @access public * @param string $s Header + * @return string */ public function DKIM_HeaderC($s) { $s = preg_replace("/\r\n\s+/", " ", $s); @@ -2400,6 +2846,7 @@ class PHPMailer { * * @access public * @param string $body Message Body + * @return string */ public function DKIM_BodyC($body) { if ($body == '') return "\r\n"; @@ -2420,6 +2867,7 @@ class PHPMailer { * @param string $headers_line Header lines * @param string $subject Subject * @param string $body Body + * @return string */ public function DKIM_Add($headers_line, $subject, $body) { $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms @@ -2428,11 +2876,22 @@ class PHPMailer { $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) $subject_header = "Subject: $subject"; $headers = explode($this->LE, $headers_line); + $from_header = ''; + $to_header = ''; + $current = ''; foreach($headers as $header) { if (strpos($header, 'From:') === 0) { $from_header = $header; + $current = 'from_header'; } elseif (strpos($header, 'To:') === 0) { $to_header = $header; + $current = 'to_header'; + } else { + if($current && strpos($header, ' =?') === 0){ + $current .= $header; + } else { + $current = ''; + } } } $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); @@ -2453,21 +2912,38 @@ class PHPMailer { "\tb="; $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs); $signed = $this->DKIM_Sign($toSign); - return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n"; + return $dkimhdrs.$signed."\r\n"; } - protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body) { - if (!empty($this->action_function) && function_exists($this->action_function)) { - $params = array($isSent, $to, $cc, $bcc, $subject, $body); + /** + * Perform callback + * @param boolean $isSent + * @param string $to + * @param string $cc + * @param string $bcc + * @param string $subject + * @param string $body + * @param string $from + */ + protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null) { + if (!empty($this->action_function) && is_callable($this->action_function)) { + $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); call_user_func_array($this->action_function, $params); } } } +/** + * Exception handler for PHPMailer + * @package PHPMailer + */ class phpmailerException extends Exception { + /** + * Prettify error message output + * @return string + */ public function errorMessage() { $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n"; return $errorMsg; } } -?> diff --git a/library/phpmailer/class.smtp.php b/library/phpmailer/class.smtp.php index 22d8e951d8..4b02f99915 100644 --- a/library/phpmailer/class.smtp.php +++ b/library/phpmailer/class.smtp.php @@ -2,15 +2,16 @@ /*~ class.smtp.php .---------------------------------------------------------------------------. | Software: PHPMailer - PHP email class | -| Version: 5.2 | -| Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ | +| Version: 5.2.6 | +| Site: https://github.com/PHPMailer/PHPMailer/ | | ------------------------------------------------------------------------- | -| Admin: Jim Jagielski (project admininistrator) | +| Admins: Marcus Bointon | +| Admins: Jim Jagielski | | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | -| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | +| : Marcus Bointon (coolbru) phpmailer@synchromedia.co.uk | | : Jim Jagielski (jimjag) jimjag@gmail.com | | Founder: Brent R. Matzelle (original founder) | -| Copyright (c) 2010-2011, Jim Jagielski. All Rights Reserved. | +| Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. | | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | | Copyright (c) 2001-2003, Brent R. Matzelle | | ------------------------------------------------------------------------- | @@ -30,17 +31,17 @@ * @author Marcus Bointon * @copyright 2004 - 2008 Andy Prevost * @author Jim Jagielski - * @copyright 2010 - 2011 Jim Jagielski + * @copyright 2010 - 2012 Jim Jagielski * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) - * @version $Id$ */ /** - * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP - * commands except TURN which will always return a not implemented - * error. SMTP also provides some utility methods for sending mail - * to an SMTP server. - * original author: Chris Ryan + * PHP RFC821 SMTP client + * + * Implements all the RFC 821 SMTP commands except TURN which will always return a not implemented error. + * SMTP also provides some utility methods for sending mail to an SMTP server. + * @author Chris Ryan + * @package PHPMailer */ class SMTP { @@ -51,16 +52,23 @@ class SMTP { public $SMTP_PORT = 25; /** - * SMTP reply line ending + * SMTP reply line ending (don't change) * @var string */ public $CRLF = "\r\n"; /** - * Sets whether debugging is turned on - * @var bool + * Debug output level; 0 for no output + * @var int + */ + public $do_debug = 0; + + /** + * Sets the function/method to use for debugging output. + * Right now we only honor 'echo', 'html' or 'error_log' + * @var string */ - public $do_debug; // the level of debug to perform + public $Debugoutput = 'echo'; /** * Sets VERP use on/off (default is off) @@ -69,23 +77,64 @@ class SMTP { public $do_verp = false; /** + * Sets the SMTP timeout value for reads, in seconds + * @var int + */ + public $Timeout = 15; + + /** + * Sets the SMTP timelimit value for reads, in seconds + * @var int + */ + public $Timelimit = 30; + + /** * Sets the SMTP PHPMailer Version number * @var string */ - public $Version = '5.2'; + public $Version = '5.2.6'; ///////////////////////////////////////////////// // PROPERTIES, PRIVATE AND PROTECTED ///////////////////////////////////////////////// - private $smtp_conn; // the socket to the server - private $error; // error if any on the last call - private $helo_rply; // the reply the server sent to us for HELO + /** + * @var resource The socket to the server + */ + protected $smtp_conn; + /** + * @var string Error message, if any, for the last call + */ + protected $error; + /** + * @var string The reply the server sent to us for HELO + */ + protected $helo_rply; + + /** + * Outputs debugging info via user-defined method + * @param string $str + */ + protected function edebug($str) { + switch ($this->Debugoutput) { + case 'error_log': + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking display that's HTML-safe + echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, 'UTF-8')."<br>\n"; + break; + case 'echo': + default: + //Just echoes exactly what was received + echo $str; + } + } /** * Initialize the class so that the data is in a known state. * @access public - * @return void + * @return SMTP */ public function __construct() { $this->smtp_conn = 0; @@ -100,26 +149,25 @@ class SMTP { ///////////////////////////////////////////////// /** - * Connect to the server specified on the port specified. - * If the port is not specified use the default SMTP_PORT. - * If tval is specified then a connection will try and be - * established with the server for that number of seconds. - * If tval is not specified the default is 30 seconds to - * try on the connection. + * Connect to an SMTP server * * SMTP CODE SUCCESS: 220 * SMTP CODE FAILURE: 421 * @access public + * @param string $host SMTP server IP or host name + * @param int $port The port number to connect to, or use the default port if not specified + * @param int $timeout How long to wait for the connection to open + * @param array $options An array of options compatible with stream_context_create() * @return bool */ - public function Connect($host, $port = 0, $tval = 30) { - // set the error val to null so there is no confusion + public function Connect($host, $port = 0, $timeout = 30, $options = array()) { + // Clear errors to avoid confusion $this->error = null; - // make sure we are __not__ connected + // Make sure we are __not__ connected if($this->connected()) { - // already connected, generate error - $this->error = array("error" => "Already connected to a server"); + // Already connected, generate error + $this->error = array('error' => 'Already connected to a server'); return false; } @@ -127,33 +175,39 @@ class SMTP { $port = $this->SMTP_PORT; } - // connect to the smtp server - $this->smtp_conn = @fsockopen($host, // the host of the server - $port, // the port to use - $errno, // error number if any - $errstr, // error message if any - $tval); // give up after ? secs - // verify we connected properly + // Connect to the SMTP server + $errno = 0; + $errstr = ''; + $socket_context = stream_context_create($options); + //Need to suppress errors here as connection failures can be handled at a higher level + $this->smtp_conn = @stream_socket_client($host.":".$port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $socket_context); + + // Verify we connected properly if(empty($this->smtp_conn)) { - $this->error = array("error" => "Failed to connect to server", - "errno" => $errno, - "errstr" => $errstr); + $this->error = array('error' => 'Failed to connect to server', + 'errno' => $errno, + 'errstr' => $errstr); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ": $errstr ($errno)"); } return false; } // SMTP server can take longer to respond, give longer timeout for first read // Windows does not have support for this timeout function - if(substr(PHP_OS, 0, 3) != "WIN") - socket_set_timeout($this->smtp_conn, $tval, 0); + if(substr(PHP_OS, 0, 3) != 'WIN') { + $max = ini_get('max_execution_time'); + if ($max != 0 && $timeout > $max) { // Don't bother if unlimited + @set_time_limit($timeout); + } + stream_set_timeout($this->smtp_conn, $timeout, 0); + } // get any announcement $announce = $this->get_lines(); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $announce); } return true; @@ -172,26 +226,26 @@ class SMTP { $this->error = null; # to avoid confusion if(!$this->connected()) { - $this->error = array("error" => "Called StartTLS() without being connected"); + $this->error = array('error' => 'Called StartTLS() without being connected'); return false; } - fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); + $this->client_send('STARTTLS' . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 220) { $this->error = - array("error" => "STARTTLS not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'STARTTLS not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -208,61 +262,237 @@ class SMTP { * Performs SMTP authentication. Must be run after running the * Hello() method. Returns true if successfully authenticated. * @access public + * @param string $username + * @param string $password + * @param string $authtype + * @param string $realm + * @param string $workstation * @return bool */ - public function Authenticate($username, $password) { - // Start authentication - fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); + public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') { + if (empty($authtype)) { + $authtype = 'LOGIN'; + } - $rply = $this->get_lines(); - $code = substr($rply,0,3); + switch ($authtype) { + case 'PLAIN': + // Start authentication + $this->client_send('AUTH PLAIN' . $this->CRLF); - if($code != 334) { - $this->error = - array("error" => "AUTH not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; - } - return false; - } + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); - // Send encoded username - fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); + if($code != 334) { + $this->error = + array('error' => 'AUTH not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + // Send encoded username and password + $this->client_send(base64_encode("\0".$username."\0".$password) . $this->CRLF); - $rply = $this->get_lines(); - $code = substr($rply,0,3); + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); - if($code != 334) { - $this->error = - array("error" => "Username not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; - } - return false; + if($code != 235) { + $this->error = + array('error' => 'Authentication not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + break; + case 'LOGIN': + // Start authentication + $this->client_send('AUTH LOGIN' . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 334) { + $this->error = + array('error' => 'AUTH not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + + // Send encoded username + $this->client_send(base64_encode($username) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 334) { + $this->error = + array('error' => 'Username not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + + // Send encoded password + $this->client_send(base64_encode($password) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 235) { + $this->error = + array('error' => 'Password not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + break; + case 'NTLM': + /* + * ntlm_sasl_client.php + ** Bundled with Permission + ** + ** How to telnet in windows: http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx + ** PROTOCOL Documentation http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication + */ + require_once 'extras/ntlm_sasl_client.php'; + $temp = new stdClass(); + $ntlm_client = new ntlm_sasl_client_class; + if(! $ntlm_client->Initialize($temp)){//let's test if every function its available + $this->error = array('error' => $temp->error); + if($this->do_debug >= 1) { + $this->edebug('You need to enable some modules in your php.ini file: ' . $this->error['error']); + } + return false; + } + $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1 + + $this->client_send('AUTH NTLM ' . base64_encode($msg1) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 334) { + $this->error = + array('error' => 'AUTH not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + + $challenge = substr($rply, 3);//though 0 based, there is a white space after the 3 digit number....//msg2 + $challenge = base64_decode($challenge); + $ntlm_res = $ntlm_client->NTLMResponse(substr($challenge, 24, 8), $password); + $msg3 = $ntlm_client->TypeMsg3($ntlm_res, $username, $realm, $workstation);//msg3 + // Send encoded username + $this->client_send(base64_encode($msg3) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 235) { + $this->error = + array('error' => 'Could not authenticate', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + break; + case 'CRAM-MD5': + // Start authentication + $this->client_send('AUTH CRAM-MD5' . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 334) { + $this->error = + array('error' => 'AUTH not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + + // Get the challenge + $challenge = base64_decode(substr($rply, 4)); + + // Build the response + $response = $username . ' ' . $this->hmac($challenge, $password); + + // Send encoded credentials + $this->client_send(base64_encode($response) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply, 0, 3); + + if($code != 235) { + $this->error = + array('error' => 'Credentials not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); + if($this->do_debug >= 1) { + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); + } + return false; + } + break; } + return true; + } - // Send encoded password - fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); + /** + * Works like hash_hmac('md5', $data, $key) in case that function is not available + * @access protected + * @param string $data + * @param string $key + * @return string + */ + protected function hmac($data, $key) { + if (function_exists('hash_hmac')) { + return hash_hmac('md5', $data, $key); + } - $rply = $this->get_lines(); - $code = substr($rply,0,3); + // The following borrowed from http://php.net/manual/en/function.mhash.php#27225 - if($code != 235) { - $this->error = - array("error" => "Password not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + // RFC 2104 HMAC implementation for php. + // Creates an md5 HMAC. + // Eliminates the need to install mhash to compute a HMAC + // Hacked by Lance Rushing + + $b = 64; // byte length for md5 + if (strlen($key) > $b) { + $key = pack('H*', md5($key)); } - return false; - } + $key = str_pad($key, $b, chr(0x00)); + $ipad = str_pad('', $b, chr(0x36)); + $opad = str_pad('', $b, chr(0x5c)); + $k_ipad = $key ^ $ipad ; + $k_opad = $key ^ $opad; - return true; + return md5($k_opad . pack('H*', md5($k_ipad . $data))); } /** @@ -272,11 +502,11 @@ class SMTP { */ public function Connected() { if(!empty($this->smtp_conn)) { - $sock_status = socket_get_status($this->smtp_conn); - if($sock_status["eof"]) { + $sock_status = stream_get_meta_data($this->smtp_conn); + if($sock_status['eof']) { // the socket is valid but we are not connected if($this->do_debug >= 1) { - echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; + $this->edebug('SMTP -> NOTICE: EOF caught while checking if connected'); } $this->Close(); return false; @@ -312,7 +542,7 @@ class SMTP { * finializing the mail transaction. $msg_data is the message * that is to be send with the headers. Each header needs to be * on a single line followed by a <CRLF> with the message headers - * and the message body being seperated by and additional <CRLF>. + * and the message body being separated by and additional <CRLF>. * * Implements rfc 821: DATA <CRLF> * @@ -320,10 +550,11 @@ class SMTP { * [data] * <CRLF>.<CRLF> * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 552,554,451,452 - * SMTP CODE FAILURE: 451,554 - * SMTP CODE ERROR : 500,501,503,421 + * SMTP CODE FAILURE: 552, 554, 451, 452 + * SMTP CODE FAILURE: 451, 554 + * SMTP CODE ERROR : 500, 501, 503, 421 * @access public + * @param string $msg_data * @return bool */ public function Data($msg_data) { @@ -331,26 +562,26 @@ class SMTP { if(!$this->connected()) { $this->error = array( - "error" => "Called Data() without being connected"); + 'error' => 'Called Data() without being connected'); return false; } - fputs($this->smtp_conn,"DATA" . $this->CRLF); + $this->client_send('DATA' . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 354) { $this->error = - array("error" => "DATA command not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'DATA command not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -367,9 +598,9 @@ class SMTP { */ // normalize the line breaks so we know the explode works - $msg_data = str_replace("\r\n","\n",$msg_data); - $msg_data = str_replace("\r","\n",$msg_data); - $lines = explode("\n",$msg_data); + $msg_data = str_replace("\r\n", "\n", $msg_data); + $msg_data = str_replace("\r", "\n", $msg_data); + $lines = explode("\n", $msg_data); /* we need to find a good way to determine is headers are * in the msg_data or if it is a straight msg body @@ -380,31 +611,31 @@ class SMTP { * headers. */ - $field = substr($lines[0],0,strpos($lines[0],":")); + $field = substr($lines[0], 0, strpos($lines[0], ':')); $in_headers = false; - if(!empty($field) && !strstr($field," ")) { + if(!empty($field) && !strstr($field, ' ')) { $in_headers = true; } $max_line_length = 998; // used below; set here for ease in change - while(list(,$line) = @each($lines)) { + while(list(, $line) = @each($lines)) { $lines_out = null; - if($line == "" && $in_headers) { + if($line == '' && $in_headers) { $in_headers = false; } // ok we need to break this line up into several smaller lines while(strlen($line) > $max_line_length) { - $pos = strrpos(substr($line,0,$max_line_length)," "); + $pos = strrpos(substr($line, 0, $max_line_length), ' '); // Patch to fix DOS attack if(!$pos) { $pos = $max_line_length - 1; - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos); + $lines_out[] = substr($line, 0, $pos); + $line = substr($line, $pos); } else { - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos + 1); + $lines_out[] = substr($line, 0, $pos); + $line = substr($line, $pos + 1); } /* if processing headers add a LWSP-char to the front of new line @@ -417,34 +648,34 @@ class SMTP { $lines_out[] = $line; // send the lines to the server - while(list(,$line_out) = @each($lines_out)) { + while(list(, $line_out) = @each($lines_out)) { if(strlen($line_out) > 0) { - if(substr($line_out, 0, 1) == ".") { - $line_out = "." . $line_out; + if(substr($line_out, 0, 1) == '.') { + $line_out = '.' . $line_out; } } - fputs($this->smtp_conn,$line_out . $this->CRLF); + $this->client_send($line_out . $this->CRLF); } } // message data has been sent - fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); + $this->client_send($this->CRLF . '.' . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 250) { $this->error = - array("error" => "DATA not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'DATA not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -461,6 +692,7 @@ class SMTP { * SMTP CODE SUCCESS: 250 * SMTP CODE ERROR : 500, 501, 504, 421 * @access public + * @param string $host * @return bool */ public function Hello($host = '') { @@ -468,19 +700,19 @@ class SMTP { if(!$this->connected()) { $this->error = array( - "error" => "Called Hello() without being connected"); + 'error' => 'Called Hello() without being connected'); return false; } // if hostname for HELO was not specified send default if(empty($host)) { // determine appropriate default to send to server - $host = "localhost"; + $host = 'localhost'; } // Send extended hello first (RFC 2821) - if(!$this->SendHello("EHLO", $host)) { - if(!$this->SendHello("HELO", $host)) { + if(!$this->SendHello('EHLO', $host)) { + if(!$this->SendHello('HELO', $host)) { return false; } } @@ -490,26 +722,28 @@ class SMTP { /** * Sends a HELO/EHLO command. - * @access private + * @access protected + * @param string $hello + * @param string $host * @return bool */ - private function SendHello($hello, $host) { - fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); + protected function SendHello($hello, $host) { + $this->client_send($hello . ' ' . $host . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER: ' . $rply); } if($code != 250) { $this->error = - array("error" => $hello . " not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => $hello . ' not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -528,9 +762,10 @@ class SMTP { * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> * * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,421 + * SMTP CODE SUCCESS: 552, 451, 452 + * SMTP CODE SUCCESS: 500, 501, 421 * @access public + * @param string $from * @return bool */ public function Mail($from) { @@ -538,27 +773,27 @@ class SMTP { if(!$this->connected()) { $this->error = array( - "error" => "Called Mail() without being connected"); + 'error' => 'Called Mail() without being connected'); return false; } - $useVerp = ($this->do_verp ? "XVERP" : ""); - fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); + $useVerp = ($this->do_verp ? ' XVERP' : ''); + $this->client_send('MAIL FROM:<' . $from . '>' . $useVerp . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 250) { $this->error = - array("error" => "MAIL not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'MAIL not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -574,6 +809,7 @@ class SMTP { * SMTP CODE SUCCESS: 221 * SMTP CODE ERROR : 500 * @access public + * @param bool $close_on_error * @return bool */ public function Quit($close_on_error = true) { @@ -581,32 +817,32 @@ class SMTP { if(!$this->connected()) { $this->error = array( - "error" => "Called Quit() without being connected"); + 'error' => 'Called Quit() without being connected'); return false; } // send the quit command to the server - fputs($this->smtp_conn,"quit" . $this->CRLF); + $this->client_send('quit' . $this->CRLF); // get any good-bye messages $byemsg = $this->get_lines(); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $byemsg); } $rval = true; $e = null; - $code = substr($byemsg,0,3); + $code = substr($byemsg, 0, 3); if($code != 221) { // use e as a tmp var cause Close will overwrite $this->error - $e = array("error" => "SMTP server rejected quit command", - "smtp_code" => $code, - "smtp_rply" => substr($byemsg,4)); + $e = array('error' => 'SMTP server rejected quit command', + 'smtp_code' => $code, + 'smtp_rply' => substr($byemsg, 4)); $rval = false; if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $e['error'] . ': ' . $byemsg); } } @@ -623,10 +859,11 @@ class SMTP { * * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> * - * SMTP CODE SUCCESS: 250,251 - * SMTP CODE FAILURE: 550,551,552,553,450,451,452 - * SMTP CODE ERROR : 500,501,503,421 + * SMTP CODE SUCCESS: 250, 251 + * SMTP CODE FAILURE: 550, 551, 552, 553, 450, 451, 452 + * SMTP CODE ERROR : 500, 501, 503, 421 * @access public + * @param string $to * @return bool */ public function Recipient($to) { @@ -634,26 +871,26 @@ class SMTP { if(!$this->connected()) { $this->error = array( - "error" => "Called Recipient() without being connected"); + 'error' => 'Called Recipient() without being connected'); return false; } - fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); + $this->client_send('RCPT TO:<' . $to . '>' . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 250 && $code != 251) { $this->error = - array("error" => "RCPT not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'RCPT not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -668,7 +905,7 @@ class SMTP { * Implements rfc 821: RSET <CRLF> * * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500,501,504,421 + * SMTP CODE ERROR : 500, 501, 504, 421 * @access public * @return bool */ @@ -676,27 +913,26 @@ class SMTP { $this->error = null; // so no confusion is caused if(!$this->connected()) { - $this->error = array( - "error" => "Called Reset() without being connected"); + $this->error = array('error' => 'Called Reset() without being connected'); return false; } - fputs($this->smtp_conn,"RSET" . $this->CRLF); + $this->client_send('RSET' . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 250) { $this->error = - array("error" => "RSET failed", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'RSET failed', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -715,9 +951,10 @@ class SMTP { * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> * * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,502,421 + * SMTP CODE SUCCESS: 552, 451, 452 + * SMTP CODE SUCCESS: 500, 501, 502, 421 * @access public + * @param string $from * @return bool */ public function SendAndMail($from) { @@ -725,26 +962,26 @@ class SMTP { if(!$this->connected()) { $this->error = array( - "error" => "Called SendAndMail() without being connected"); + 'error' => 'Called SendAndMail() without being connected'); return false; } - fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); + $this->client_send('SAML FROM:' . $from . $this->CRLF); $rply = $this->get_lines(); - $code = substr($rply,0,3); + $code = substr($rply, 0, 3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> FROM SERVER:' . $rply); } if($code != 250) { $this->error = - array("error" => "SAML not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); + array('error' => 'SAML not accepted from server', + 'smtp_code' => $code, + 'smtp_msg' => substr($rply, 4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; + $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply); } return false; } @@ -765,15 +1002,28 @@ class SMTP { * @return bool */ public function Turn() { - $this->error = array("error" => "This method, TURN, of the SMTP ". - "is not implemented"); + $this->error = array('error' => 'This method, TURN, of the SMTP '. + 'is not implemented'); if($this->do_debug >= 1) { - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />'; + $this->edebug('SMTP -> NOTICE: ' . $this->error['error']); } return false; } /** + * Sends data to the server + * @param string $data + * @access public + * @return Integer number of bytes sent to the server or FALSE on error + */ + public function client_send($data) { + if ($this->do_debug >= 1) { + $this->edebug("CLIENT -> SMTP: $data"); + } + return fwrite($this->smtp_conn, $data); + } + + /** * Get the current error * @access public * @return array @@ -792,26 +1042,51 @@ class SMTP { * With SMTP we can tell if we have more lines to read if the * 4th character is '-' symbol. If it is a space then we don't * need to read anything else. - * @access private + * @access protected * @return string */ - private function get_lines() { - $data = ""; - while($str = @fgets($this->smtp_conn,515)) { + protected function get_lines() { + $data = ''; + $endtime = 0; + /* If for some reason the fp is bad, don't inf loop */ + if (!is_resource($this->smtp_conn)) { + return $data; + } + stream_set_timeout($this->smtp_conn, $this->Timeout); + if ($this->Timelimit > 0) { + $endtime = time() + $this->Timelimit; + } + while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { + $str = @fgets($this->smtp_conn, 515); if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />'; - echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />'; + $this->edebug("SMTP -> get_lines(): \$data was \"$data\""); + $this->edebug("SMTP -> get_lines(): \$str is \"$str\""); } $data .= $str; if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />'; + $this->edebug("SMTP -> get_lines(): \$data is \"$data\""); } // if 4th character is a space, we are done reading, break the loop - if(substr($str,3,1) == " ") { break; } + if(substr($str, 3, 1) == ' ') { break; } + // Timed-out? Log and break + $info = stream_get_meta_data($this->smtp_conn); + if ($info['timed_out']) { + if($this->do_debug >= 4) { + $this->edebug('SMTP -> get_lines(): timed-out (' . $this->Timeout . ' seconds)'); + } + break; + } + // Now check if reads took too long + if ($endtime) { + if (time() > $endtime) { + if($this->do_debug >= 4) { + $this->edebug('SMTP -> get_lines(): timelimit reached (' . $this->Timelimit . ' seconds)'); + } + break; + } + } } return $data; } } - -?> diff --git a/library/phpmailer/language/phpmailer.lang-ar.php b/library/phpmailer/language/phpmailer.lang-ar.php index b7c5057d0c..67364e967a 100644 --- a/library/phpmailer/language/phpmailer.lang-ar.php +++ b/library/phpmailer/language/phpmailer.lang-ar.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = 'لم نستطع الوصول للمل $PHPMAILER_LANG['file_open'] = 'File Error: لم نستطع فتح الملف: '; $PHPMAILER_LANG['from_failed'] = 'البريد التالي لم نستطع ارسال البريد له : '; $PHPMAILER_LANG['instantiate'] = 'لم نستطع توفير خدمة البريد.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer غير مدعوم.'; //$PHPMAILER_LANG['provide_address'] = 'You must provide at least one recipient email address.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: الأخطاء التالية ' . @@ -24,4 +24,3 @@ $PHPMAILER_LANG['signing'] = 'خطأ في التوقيع: '; //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-br.php b/library/phpmailer/language/phpmailer.lang-br.php index 6afe60b18c..87ecbdfa5e 100644 --- a/library/phpmailer/language/phpmailer.lang-br.php +++ b/library/phpmailer/language/phpmailer.lang-br.php @@ -3,24 +3,24 @@ * PHPMailer language file: refer to English translation for definitive list * Portuguese Version * By Paulo Henrique Garcia - paulo@controllerweb.com.br +* Edited by Lucas Guimarães - lucas@lucasguimaraes.com */ $PHPMAILER_LANG['authenticate'] = 'Erro de SMTP: Não foi possível autenticar.'; $PHPMAILER_LANG['connect_host'] = 'Erro de SMTP: Não foi possível conectar com o servidor SMTP.'; -$PHPMAILER_LANG['data_not_accepted'] = 'Erro de SMTP: Dados não aceitos.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; +$PHPMAILER_LANG['data_not_accepted'] = 'Erro de SMTP: Dados rejeitados.'; +$PHPMAILER_LANG['empty_message'] = 'Corpo da mensagem vazio'; $PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: '; $PHPMAILER_LANG['execute'] = 'Não foi possível executar: '; $PHPMAILER_LANG['file_access'] = 'Não foi possível acessar o arquivo: '; $PHPMAILER_LANG['file_open'] = 'Erro de Arquivo: Não foi possível abrir o arquivo: '; -$PHPMAILER_LANG['from_failed'] = 'Os endereços de rementente a seguir falharam: '; -$PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; -$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não suportado.'; -$PHPMAILER_LANG['provide_address'] = 'Você deve fornecer pelo menos um endereço de destinatário de email.'; +$PHPMAILER_LANG['from_failed'] = 'Os endereços dos remententes a seguir falharam: '; +$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.'; +$PHPMAILER_LANG['invalid_address'] = 'Não enviando, endereço de e-mail inválido: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.'; +$PHPMAILER_LANG['provide_address'] = 'Você deve fornecer pelo menos um endereço de destinatário de e-mail.'; $PHPMAILER_LANG['recipients_failed'] = 'Erro de SMTP: Os endereços de destinatário a seguir falharam: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['signing'] = 'Erro ao assinar: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.'; +$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou resetar a variável: '; diff --git a/library/phpmailer/language/phpmailer.lang-ca.php b/library/phpmailer/language/phpmailer.lang-ca.php index 4a160a21eb..dc563e77f6 100644 --- a/library/phpmailer/language/phpmailer.lang-ca.php +++ b/library/phpmailer/language/phpmailer.lang-ca.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = 'No es pot accedir a l\'arxiu: '; $PHPMAILER_LANG['file_open'] = 'Error d\'Arxiu: No es pot obrir l\'arxiu: '; $PHPMAILER_LANG['from_failed'] = 'La(s) següent(s) adreces de remitent han fallat: '; $PHPMAILER_LANG['instantiate'] = 'No s\'ha pogut crear una instància de la funció Mail.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer no està suportat'; $PHPMAILER_LANG['provide_address'] = 'S\'ha de proveir almenys una adreça d\'email com a destinatari.'; $PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Els següents destinataris han fallat: '; @@ -23,4 +23,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Els següents destinatari //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-ch.php b/library/phpmailer/language/phpmailer.lang-ch.php index 31ebd861cb..d28eba611b 100644 --- a/library/phpmailer/language/phpmailer.lang-ch.php +++ b/library/phpmailer/language/phpmailer.lang-ch.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = '不能访问文件:'; $PHPMAILER_LANG['file_open'] = '文件错误:不能打开文件:'; $PHPMAILER_LANG['from_failed'] = '下面的发送地址邮件发送失败了: '; $PHPMAILER_LANG['instantiate'] = '不能实现mail方法。'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' 您所选择的发送邮件的方法并不支持。'; $PHPMAILER_LANG['provide_address'] = '您必须提供至少一个 收信人的email地址。'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误: 下面的 收件人失败了: '; @@ -23,4 +23,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误: 下面的 收件人失败 //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-cz.php b/library/phpmailer/language/phpmailer.lang-cz.php index 1c8b206392..b1f0a51c28 100644 --- a/library/phpmailer/language/phpmailer.lang-cz.php +++ b/library/phpmailer/language/phpmailer.lang-cz.php @@ -14,7 +14,7 @@ $PHPMAILER_LANG['file_access'] = 'Soubor nenalezen: '; $PHPMAILER_LANG['file_open'] = 'File Error: Nelze otevøít soubor pro ètení: '; $PHPMAILER_LANG['from_failed'] = 'Následující adresa From je nesprávná: '; $PHPMAILER_LANG['instantiate'] = 'Nelze vytvoøit instanci emailové funkce.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailový klient není podporován.'; $PHPMAILER_LANG['provide_address'] = 'Musíte zadat alespoò jednu emailovou adresu pøíjemce.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Adresy pøíjemcù nejsou správné '; @@ -22,4 +22,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Adresy pøíjemcù nejsou //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-de.php b/library/phpmailer/language/phpmailer.lang-de.php index b2a76ce1b5..ba17a92a95 100644 --- a/library/phpmailer/language/phpmailer.lang-de.php +++ b/library/phpmailer/language/phpmailer.lang-de.php @@ -14,7 +14,7 @@ $PHPMAILER_LANG['file_access'] = 'Zugriff auf folgende Datei fehlgeschl $PHPMAILER_LANG['file_open'] = 'Datei Fehler: konnte folgende Datei nicht öffnen: '; $PHPMAILER_LANG['from_failed'] = 'Die folgende Absenderadresse ist nicht korrekt: '; $PHPMAILER_LANG['instantiate'] = 'Mail Funktion konnte nicht initialisiert werden.'; -$PHPMAILER_LANG['invalid_email'] = 'E-Mail wird nicht gesendet, die Adresse ist ungültig.'; +$PHPMAILER_LANG['invalid_address'] = 'E-Mail wird nicht gesendet, die Adresse ist ungültig.'; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer wird nicht unterstützt.'; $PHPMAILER_LANG['provide_address'] = 'Bitte geben Sie mindestens eine Empfänger E-Mailadresse an.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Fehler: Die folgenden Empfänger sind nicht korrekt: '; @@ -22,4 +22,3 @@ $PHPMAILER_LANG['signing'] = 'Fehler beim Signieren: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'Verbindung zu SMTP Server fehlgeschlagen.'; $PHPMAILER_LANG['smtp_error'] = 'Fehler vom SMTP Server: '; $PHPMAILER_LANG['variable_set'] = 'Kann Variable nicht setzen oder zurücksetzen: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-dk.php b/library/phpmailer/language/phpmailer.lang-dk.php index b26257316b..fdb0b17b85 100644 --- a/library/phpmailer/language/phpmailer.lang-dk.php +++ b/library/phpmailer/language/phpmailer.lang-dk.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = 'Ingen adgang til fil: '; $PHPMAILER_LANG['file_open'] = 'Fil fejl: Kunne ikke åbne filen: '; $PHPMAILER_LANG['from_failed'] = 'Følgende afsenderadresse er forkert: '; $PHPMAILER_LANG['instantiate'] = 'Kunne ikke initialisere email funktionen.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer understøttes ikke.'; $PHPMAILER_LANG['provide_address'] = 'Du skal indtaste mindst en modtagers emailadresse.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere er forkerte: '; @@ -23,4 +23,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere er for //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-eo.php b/library/phpmailer/language/phpmailer.lang-eo.php new file mode 100644 index 0000000000..799b331963 --- /dev/null +++ b/library/phpmailer/language/phpmailer.lang-eo.php @@ -0,0 +1,24 @@ +<?php +/** +* PHPMailer language file: refer to English translation for definitive list +* Esperanto version +*/ + +$PHPMAILER_LANG['authenticate'] = 'Eraro de servilo SMTP : aŭtentigo malsukcesis.'; +$PHPMAILER_LANG['connect_host'] = 'Eraro de servilo SMTP : konektado al servilo malsukcesis.'; +$PHPMAILER_LANG['data_not_accepted'] = 'Eraro de servilo SMTP : neĝustaj datumoj.'; +$PHPMAILER_LANG['empty_message'] = 'Teksto de mesaĝo mankas.'; +$PHPMAILER_LANG['encoding'] = 'Nekonata kodoprezento: '; +$PHPMAILER_LANG['execute'] = 'Lanĉi rulumadon ne eblis: '; +$PHPMAILER_LANG['file_access'] = 'Aliro al dosiero ne sukcesis: '; +$PHPMAILER_LANG['file_open'] = 'Eraro de dosiero: malfermo neeblas: '; +$PHPMAILER_LANG['from_failed'] = 'Jena adreso de sendinto malsukcesis: '; +$PHPMAILER_LANG['instantiate'] = 'Genero de retmesaĝa funkcio neeblis.'; +$PHPMAILER_LANG['invalid_address'] = 'Retadreso ne validas: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' mesaĝilo ne subtenata.'; +$PHPMAILER_LANG['provide_address'] = 'Vi devas tajpi almenaŭ unu recevontan retadreson.'; +$PHPMAILER_LANG['recipients_failed'] = 'Eraro de servilo SMTP : la jenaj poŝtrecivuloj kaŭzis eraron: '; +$PHPMAILER_LANG['signing'] = 'Eraro de subskribo: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP konektado malsukcesis.'; +$PHPMAILER_LANG['smtp_error'] = 'Eraro de servilo SMTP : '; +$PHPMAILER_LANG['variable_set'] = 'Variablo ne pravalorizeblas aŭ ne repravalorizeblas: '; diff --git a/library/phpmailer/language/phpmailer.lang-es.php b/library/phpmailer/language/phpmailer.lang-es.php index 69b6817482..b81520f285 100644 --- a/library/phpmailer/language/phpmailer.lang-es.php +++ b/library/phpmailer/language/phpmailer.lang-es.php @@ -3,24 +3,24 @@ * PHPMailer language file: refer to English translation for definitive list * Spanish version * Versión en español +* Edited by Matt Sturdy - matt.sturdy@gmail.com */ $PHPMAILER_LANG['authenticate'] = 'Error SMTP: No se pudo autentificar.'; -$PHPMAILER_LANG['connect_host'] = 'Error SMTP: No puedo conectar al servidor SMTP.'; +$PHPMAILER_LANG['connect_host'] = 'Error SMTP: No se pudo conectar al servidor SMTP.'; $PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; +$PHPMAILER_LANG['empty_message'] = 'Cuerpo del mensaje vacío'; $PHPMAILER_LANG['encoding'] = 'Codificación desconocida: '; -$PHPMAILER_LANG['execute'] = 'No puedo ejecutar: '; -$PHPMAILER_LANG['file_access'] = 'No puedo acceder al archivo: '; -$PHPMAILER_LANG['file_open'] = 'Error de Archivo: No puede abrir el archivo: '; +$PHPMAILER_LANG['execute'] = 'No se pudo ejecutar: '; +$PHPMAILER_LANG['file_access'] = 'No se pudo acceder al archivo: '; +$PHPMAILER_LANG['file_open'] = 'Error de Archivo: No se pudo abrir el archivo: '; $PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: '; -$PHPMAILER_LANG['instantiate'] = 'No pude crear una instancia de la función Mail.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +$PHPMAILER_LANG['instantiate'] = 'No se pudo crear una instancia de la función Mail.'; +$PHPMAILER_LANG['invalid_address'] = 'No se pudo enviar: dirección de email inválido: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer no está soportado.'; -$PHPMAILER_LANG['provide_address'] = 'Debe proveer al menos una dirección de email como destinatario.'; -$PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinatarios fallaron: '; +$PHPMAILER_LANG['provide_address'] = 'Debe proveer al menos una dirección de email como destino.'; +$PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinos fallaron: '; $PHPMAILER_LANG['signing'] = 'Error al firmar: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() se falló.'; +$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'No se pudo ajustar o reajustar la variable: '; diff --git a/library/phpmailer/language/phpmailer.lang-et.php b/library/phpmailer/language/phpmailer.lang-et.php index cf61779b08..eee4e58e88 100644 --- a/library/phpmailer/language/phpmailer.lang-et.php +++ b/library/phpmailer/language/phpmailer.lang-et.php @@ -3,24 +3,24 @@ * PHPMailer language file: refer to English translation for definitive list * Estonian Version * By Indrek Päri +* Revised By Elan Ruusamäe <glen@delfi.ee> */ $PHPMAILER_LANG['authenticate'] = 'SMTP Viga: Autoriseerimise viga.'; $PHPMAILER_LANG['connect_host'] = 'SMTP Viga: Ei õnnestunud luua ühendust SMTP serveriga.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Viga: Vigased andmed.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; -$PHPMAILER_LANG['encoding'] = 'Tundmatu Unknown kodeering: '; +$PHPMAILER_LANG['empty_message'] = 'Tühi kirja sisu'; +$PHPMAILER_LANG["encoding"] = 'Tundmatu kodeering: '; $PHPMAILER_LANG['execute'] = 'Tegevus ebaõnnestus: '; $PHPMAILER_LANG['file_access'] = 'Pole piisavalt õiguseid järgneva faili avamiseks: '; $PHPMAILER_LANG['file_open'] = 'Faili Viga: Faili avamine ebaõnnestus: '; $PHPMAILER_LANG['from_failed'] = 'Järgnev saatja e-posti aadress on vigane: '; $PHPMAILER_LANG['instantiate'] = 'mail funktiooni käivitamine ebaõnnestus.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +$PHPMAILER_LANG['invalid_address'] = 'Saatmine peatatud, e-posti address vigane: '; $PHPMAILER_LANG['provide_address'] = 'Te peate määrama vähemalt ühe saaja e-posti aadressi.'; $PHPMAILER_LANG['mailer_not_supported'] = ' maileri tugi puudub.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Viga: Järgnevate saajate e-posti aadressid on vigased: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG["signing"] = 'Viga allkirjastamisel: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() ebaõnnestus.'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP serveri viga: '; +$PHPMAILER_LANG['variable_set'] = 'Ei õnnestunud määrata või lähtestada muutujat: '; diff --git a/library/phpmailer/language/phpmailer.lang-fi.php b/library/phpmailer/language/phpmailer.lang-fi.php index 12a845aad6..16a02e1380 100644 --- a/library/phpmailer/language/phpmailer.lang-fi.php +++ b/library/phpmailer/language/phpmailer.lang-fi.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = 'Seuraavaan tiedostoon ei ole oikeuksi $PHPMAILER_LANG['file_open'] = 'Tiedostovirhe: Ei voida avata tiedostoa: '; $PHPMAILER_LANG['from_failed'] = 'Seuraava lähettäjän osoite on virheellinen: '; $PHPMAILER_LANG['instantiate'] = 'mail-funktion luonti epäonnistui.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = 'postivälitintyyppiä ei tueta.'; $PHPMAILER_LANG['provide_address'] = 'Aseta vähintään yksi vastaanottajan sähköpostiosoite.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP-virhe: seuraava vastaanottaja osoite on virheellinen.'; @@ -24,4 +24,3 @@ $PHPMAILER_LANG['encoding'] = 'Tuntematon koodaustyyppi: '; //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-fo.php b/library/phpmailer/language/phpmailer.lang-fo.php index 6bd9b0a213..fc5d6d5654 100644 --- a/library/phpmailer/language/phpmailer.lang-fo.php +++ b/library/phpmailer/language/phpmailer.lang-fo.php @@ -16,7 +16,7 @@ $PHPMAILER_LANG['file_access'] = 'Kundi ikki tilganga fílu: '; $PHPMAILER_LANG['file_open'] = 'Fílu feilur: Kundi ikki opna fílu: '; $PHPMAILER_LANG['from_failed'] = 'fylgjandi Frá/From adressa miseydnaðist: '; $PHPMAILER_LANG['instantiate'] = 'Kuni ikki instantiera mail funktión.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' er ikki supporterað.'; $PHPMAILER_LANG['provide_address'] = 'Tú skal uppgeva minst móttakara-emailadressu(r).'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Feilur: Fylgjandi móttakarar miseydnaðust: '; @@ -24,4 +24,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Feilur: Fylgjandi móttakarar mi //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-fr.php b/library/phpmailer/language/phpmailer.lang-fr.php index c99ac3caf9..b8dfc7743d 100644 --- a/library/phpmailer/language/phpmailer.lang-fr.php +++ b/library/phpmailer/language/phpmailer.lang-fr.php @@ -4,22 +4,21 @@ * French Version */ -$PHPMAILER_LANG['authenticate'] = 'Erreur SMTP : Echec de l\'authentification.'; -$PHPMAILER_LANG['connect_host'] = 'Erreur SMTP : Impossible de se connecter au serveur SMTP.'; -$PHPMAILER_LANG['data_not_accepted'] = 'Erreur SMTP : Données incorrects.'; -$PHPMAILER_LANG['empty_message'] = 'Corps de message vide'; -$PHPMAILER_LANG['encoding'] = 'Encodage inconnu : '; -$PHPMAILER_LANG['execute'] = 'Impossible de lancer l\'exécution : '; -$PHPMAILER_LANG['file_access'] = 'Impossible d\'accéder au fichier : '; -$PHPMAILER_LANG['file_open'] = 'Erreur Fichier : ouverture impossible : '; -$PHPMAILER_LANG['from_failed'] = 'L\'adresse d\'expéditeur suivante a échouée : '; +$PHPMAILER_LANG['authenticate'] = 'Erreur SMTP : échec de l\'authentification.'; +$PHPMAILER_LANG['connect_host'] = 'Erreur SMTP : impossible de se connecter au serveur SMTP.'; +$PHPMAILER_LANG['data_not_accepted'] = 'Erreur SMTP : données incorrectes.'; +$PHPMAILER_LANG['empty_message'] = 'Corps de message vide.'; +$PHPMAILER_LANG['encoding'] = 'Encodage inconnu: '; +$PHPMAILER_LANG['execute'] = 'Impossible de lancer l\'exécution: '; +$PHPMAILER_LANG['file_access'] = 'Impossible d\'accéder au fichier: '; +$PHPMAILER_LANG['file_open'] = 'Erreur de fichier : ouverture impossible: '; +$PHPMAILER_LANG['from_failed'] = 'L\'adresse d\'expéditeur suivante a échouée: '; $PHPMAILER_LANG['instantiate'] = 'Impossible d\'instancier la fonction mail.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +$PHPMAILER_LANG['invalid_address'] = 'L\'adresse courriel n\'est pas valide: '; $PHPMAILER_LANG['mailer_not_supported'] = ' client de messagerie non supporté.'; $PHPMAILER_LANG['provide_address'] = 'Vous devez fournir au moins une adresse de destinataire.'; -$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : Les destinataires suivants sont en erreur : '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : les destinataires suivants sont en erreur: '; +$PHPMAILER_LANG['signing'] = 'Erreur de signature: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Échec de la connexion SMTP.'; +$PHPMAILER_LANG['smtp_error'] = 'Erreur du serveur SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'Ne peut initialiser ou réinitialiser une variable: '; diff --git a/library/phpmailer/language/phpmailer.lang-he.php b/library/phpmailer/language/phpmailer.lang-he.php new file mode 100644 index 0000000000..e30b596d60 --- /dev/null +++ b/library/phpmailer/language/phpmailer.lang-he.php @@ -0,0 +1,25 @@ +<?php +/** +* PHPMailer language file: refer to English translation for definitive list +* Hebrew Version, UTF-8 +* by : Ronny Sherer <ronny@hoojima.com> +*/ + +$PHPMAILER_LANG['authenticate'] = 'שגיאת SMTP: פעולת האימות נכשלה.'; +$PHPMAILER_LANG['connect_host'] = 'שגיאת SMTP: לא הצלחתי להתחבר לשרת SMTP.'; +$PHPMAILER_LANG['data_not_accepted'] = 'שגיאת SMTP: מידע לא התקבל.'; +$PHPMAILER_LANG['empty_message'] = 'גוף ההודעה ריק'; +$PHPMAILER_LANG['invalid_address'] = 'כתובת שגויה'; +$PHPMAILER_LANG['encoding'] = 'קידוד לא מוכר: '; +$PHPMAILER_LANG['execute'] = 'לא הצלחתי להפעיל את: '; +$PHPMAILER_LANG['file_access'] = 'לא ניתן לגשת לקובץ: '; +$PHPMAILER_LANG['file_open'] = 'שגיאת קובץ: לא ניתן לגשת לקובץ: '; +$PHPMAILER_LANG['from_failed'] = 'כתובות הנמענים הבאות נכשלו: '; +$PHPMAILER_LANG['instantiate'] = 'לא הצלחתי להפעיל את פונקציית המייל.'; +$PHPMAILER_LANG['mailer_not_supported'] = ' אינה נתמכת.'; +$PHPMAILER_LANG['provide_address'] = 'חובה לספק לפחות כתובת אחת של מקבל המייל.'; +$PHPMAILER_LANG['recipients_failed'] = 'שגיאת SMTP: הנמענים הבאים נכשלו: '; +$PHPMAILER_LANG['signing'] = 'שגיאת חתימה: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; +$PHPMAILER_LANG['smtp_error'] = 'שגיאת שרת SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'לא ניתן לקבוע או לשנות את המשתנה: '; diff --git a/library/phpmailer/language/phpmailer.lang-hu.php b/library/phpmailer/language/phpmailer.lang-hu.php index caca0b50f1..d8d1926796 100644 --- a/library/phpmailer/language/phpmailer.lang-hu.php +++ b/library/phpmailer/language/phpmailer.lang-hu.php @@ -1,25 +1,24 @@ <?php /** * PHPMailer language file: refer to English translation for definitive list -* Hungarian Version +* Hungarian Version by @dominicus-75 */ -$PHPMAILER_LANG['authenticate'] = 'SMTP Hiba: Sikertelen autentikáció.'; -$PHPMAILER_LANG['connect_host'] = 'SMTP Hiba: Nem tudtam csatlakozni az SMTP host-hoz.'; -$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hiba: Nem elfogadható adat.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; +$PHPMAILER_LANG['authenticate'] = 'SMTP hiba: az azonosítás sikertelen.'; +$PHPMAILER_LANG['connect_host'] = 'SMTP hiba: nem lehet kapcsolódni az SMTP-szerverhez.'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP hiba: adatok visszautasítva.'; +$PHPMAILER_LANG['empty_message'] = 'Üres az üzenettörzs.'; $PHPMAILER_LANG['encoding'] = 'Ismeretlen kódolás: '; -$PHPMAILER_LANG['execute'] = 'Nem tudtam végrehajtani: '; -$PHPMAILER_LANG['file_access'] = 'Nem sikerült elérni a következõ fájlt: '; -$PHPMAILER_LANG['file_open'] = 'Fájl Hiba: Nem sikerült megnyitni a következõ fájlt: '; -$PHPMAILER_LANG['from_failed'] = 'Az alábbi Feladó cím hibás: '; -$PHPMAILER_LANG['instantiate'] = 'Nem sikerült példányosítani a mail funkciót.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; -$PHPMAILER_LANG['provide_address'] = 'Meg kell adnod legalább egy címzett email címet.'; -$PHPMAILER_LANG['mailer_not_supported'] = ' levelezõ nem támogatott.'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP Hiba: Az alábbi címzettek hibásak: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['execute'] = 'Nem lehet végrehajtani: '; +$PHPMAILER_LANG['file_access'] = 'A következő fájl nem elérhető: '; +$PHPMAILER_LANG['file_open'] = 'Fájl hiba: a következő fájlt nem lehet megnyitni: '; +$PHPMAILER_LANG['from_failed'] = 'A feladóként megadott következő cím hibás: '; +$PHPMAILER_LANG['instantiate'] = 'A PHP mail() függvényt nem sikerült végrehajtani.'; +$PHPMAILER_LANG['invalid_address'] = 'Érvénytelen cím: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' a mailer-osztály nem támogatott.'; +$PHPMAILER_LANG['provide_address'] = 'Legalább egy címzettet fel kell tüntetni.'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP hiba: a címzettként megadott következő címek hibásak: '; +$PHPMAILER_LANG['signing'] = 'Hibás aláírás: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Hiba az SMTP-kapcsolatban.'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP-szerver hiba: '; +$PHPMAILER_LANG['variable_set'] = 'A következő változók beállítása nem sikerült: '; diff --git a/library/phpmailer/language/phpmailer.lang-it.php b/library/phpmailer/language/phpmailer.lang-it.php index fc1fcb8d2e..27ab0ead00 100644 --- a/library/phpmailer/language/phpmailer.lang-it.php +++ b/library/phpmailer/language/phpmailer.lang-it.php @@ -3,25 +3,24 @@ * PHPMailer language file: refer to English translation for definitive list * Italian version * @package PHPMailer -* @author Ilias Bartolini <brain79@inwind.it> +* @author Ilias Bartolini <brain79@inwind.it>, Stefano Sabatini <sabas88@gmail.com> */ $PHPMAILER_LANG['authenticate'] = 'SMTP Error: Impossibile autenticarsi.'; $PHPMAILER_LANG['connect_host'] = 'SMTP Error: Impossibile connettersi all\'host SMTP.'; -$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Data non accettati dal server.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; -$PHPMAILER_LANG['encoding'] = 'Encoding set dei caratteri sconosciuto: '; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Dati non accettati dal server.'; +$PHPMAILER_LANG['empty_message'] = 'Il corpo del messaggio è vuoto'; +$PHPMAILER_LANG['encoding'] = 'Codifica dei caratteri sconosciuta: '; $PHPMAILER_LANG['execute'] = 'Impossibile eseguire l\'operazione: '; $PHPMAILER_LANG['file_access'] = 'Impossibile accedere al file: '; $PHPMAILER_LANG['file_open'] = 'File Error: Impossibile aprire il file: '; $PHPMAILER_LANG['from_failed'] = 'I seguenti indirizzi mittenti hanno generato errore: '; $PHPMAILER_LANG['instantiate'] = 'Impossibile istanziare la funzione mail'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +$PHPMAILER_LANG['invalid_address'] = 'Impossibile inviare, l\'indirizzo email non è valido: '; $PHPMAILER_LANG['provide_address'] = 'Deve essere fornito almeno un indirizzo ricevente'; $PHPMAILER_LANG['mailer_not_supported'] = 'Mailer non supportato'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: I seguenti indirizzi destinatari hanno generato errore: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: I seguenti indirizzi destinatari hanno generato un errore: '; +$PHPMAILER_LANG['signing'] = 'Errore nella firma: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fallita.'; +$PHPMAILER_LANG['smtp_error'] = 'Errore del server SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'Impossibile impostare o resettare la variabile: '; diff --git a/library/phpmailer/language/phpmailer.lang-ja.php b/library/phpmailer/language/phpmailer.lang-ja.php index 63cfb23b6a..ca6de909da 100644 --- a/library/phpmailer/language/phpmailer.lang-ja.php +++ b/library/phpmailer/language/phpmailer.lang-ja.php @@ -3,6 +3,7 @@ * PHPMailer language file: refer to English translation for definitive list * Japanese Version * By Mitsuhiro Yoshida - http://mitstek.com/ +* Modified by Yoshi Sakai - http://bluemooninc.jp/ */ $PHPMAILER_LANG['authenticate'] = 'SMTPエラー: 認証できませんでした。'; @@ -13,9 +14,9 @@ $PHPMAILER_LANG['encoding'] = '不明なエンコーディング: '; $PHPMAILER_LANG['execute'] = '実行できませんでした: '; $PHPMAILER_LANG['file_access'] = 'ファイルにアクセスできません: '; $PHPMAILER_LANG['file_open'] = 'ファイルエラー: ファイルを開けません: '; -$PHPMAILER_LANG['from_failed'] = '次のFromアドレスに間違いがあります: '; +$PHPMAILER_LANG['from_failed'] = 'Fromアドレスを登録する際にエラーが発生しました: '; $PHPMAILER_LANG['instantiate'] = 'メール関数が正常に動作しませんでした。'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['provide_address'] = '少なくとも1つメールアドレスを 指定する必要があります。'; $PHPMAILER_LANG['mailer_not_supported'] = ' メーラーがサポートされていません。'; $PHPMAILER_LANG['recipients_failed'] = 'SMTPエラー: 次の受信者アドレスに 間違いがあります: '; @@ -23,4 +24,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTPエラー: 次の受信者アドレ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-lt.php b/library/phpmailer/language/phpmailer.lang-lt.php new file mode 100644 index 0000000000..5dba58a932 --- /dev/null +++ b/library/phpmailer/language/phpmailer.lang-lt.php @@ -0,0 +1,24 @@ +<?php +/** +* PHPMailer language file: refer to English translation for definitive list +* Lithuanian version by Dainius Kaupaitis <dk@sum.lt> +*/ + +$PHPMAILER_LANG['authenticate'] = 'SMTP klaida: autentifikacija nepavyko.'; +$PHPMAILER_LANG['connect_host'] = 'SMTP klaida: nepavyksta prisijungti prie SMTP stoties.'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP klaida: duomenys nepriimti.'; +$PHPMAILER_LANG['empty_message'] = 'Laiško turinys tuščias'; +$PHPMAILER_LANG['encoding'] = 'Neatpažinta koduotė: '; +$PHPMAILER_LANG['execute'] = 'Nepavyko įvykdyti komandos: '; +$PHPMAILER_LANG['file_access'] = 'Byla nepasiekiama: '; +$PHPMAILER_LANG['file_open'] = 'Bylos klaida: Nepavyksta atidaryti: '; +$PHPMAILER_LANG['from_failed'] = 'Neteisingas siuntėjo adresas: '; +$PHPMAILER_LANG['instantiate'] = 'Nepavyko paleisti mail funkcijos.'; +$PHPMAILER_LANG['invalid_address'] = 'Neteisingas adresas'; +$PHPMAILER_LANG['mailer_not_supported'] = ' pašto stotis nepalaikoma.'; +$PHPMAILER_LANG['provide_address'] = 'Nurodykite bent vieną gavėjo adresą.'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP klaida: nepavyko išsiųsti šiems gavėjams: '; +$PHPMAILER_LANG['signing'] = 'Prisijungimo klaida: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP susijungimo klaida'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP stoties klaida: '; +$PHPMAILER_LANG['variable_set'] = 'Nepavyko priskirti reikšmės kintamajam: '; diff --git a/library/phpmailer/language/phpmailer.lang-nl.php b/library/phpmailer/language/phpmailer.lang-nl.php index d2c380b09d..c86d7699bf 100644 --- a/library/phpmailer/language/phpmailer.lang-nl.php +++ b/library/phpmailer/language/phpmailer.lang-nl.php @@ -1,25 +1,24 @@ <?php /** -* PHPMailer language file: refer to English translation for definitive list -* Dutch Version +* PHPMailer language file: refer to class.phpmailer.php for definitive list. +* Dutch Version by Tuxion <team@tuxion.nl> */ -$PHPMAILER_LANG['authenticate'] = 'SMTP Fout: authenticatie mislukt.'; -$PHPMAILER_LANG['connect_host'] = 'SMTP Fout: Kon niet verbinden met SMTP host.'; -$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Fout: Data niet geaccepteerd.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; -$PHPMAILER_LANG['encoding'] = 'Onbekende codering: '; -$PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: '; -$PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: '; -$PHPMAILER_LANG['file_open'] = 'Bestandsfout: Kon bestand niet openen: '; -$PHPMAILER_LANG['from_failed'] = 'De volgende afzender adressen zijn mislukt: '; -$PHPMAILER_LANG['instantiate'] = 'Kon mail functie niet initialiseren.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; -$PHPMAILER_LANG['provide_address'] = 'Er moet tenmiste één ontvanger emailadres opgegeven worden.'; -$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP Fout: De volgende ontvangers zijn mislukt: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['authenticate'] = 'SMTP-fout: authenticatie mislukt.';//SMTP Error: Could not authenticate. +$PHPMAILER_LANG['connect_host'] = 'SMTP-fout: kon niet verbinden met SMTP-host.';//SMTP Error: Could not connect to SMTP host. +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-fout: data niet geaccepteerd.';//SMTP Error: Data not accepted. +$PHPMAILER_LANG['empty_message'] = 'Berichttekst is leeg';//Message body empty +$PHPMAILER_LANG['encoding'] = 'Onbekende codering: ';//Unknown encoding: +$PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: ';//Could not execute: +$PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: ';//Could not access file: +$PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen: ';//File Error: Could not open file: +$PHPMAILER_LANG['from_failed'] = 'Het volgende afzendersadres is mislukt: ';//The following From address failed: +$PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.';//Could not instantiate mail function. +$PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres';//Invalid address +$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';// mailer is not supported. +$PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.';//You must provide at least one recipient email address. +$PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';//SMTP Error: The following recipients failed: +$PHPMAILER_LANG['signing'] = 'Signeerfout: ';//Signing Error: +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Verbinding mislukt.'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfout: ';//SMTP server error: +$PHPMAILER_LANG['variable_set'] = 'Kan de volgende variablen niet instellen of resetten: ';//Cannot set or reset variable: diff --git a/library/phpmailer/language/phpmailer.lang-no.php b/library/phpmailer/language/phpmailer.lang-no.php index 65cb884399..e6975203e3 100644 --- a/library/phpmailer/language/phpmailer.lang-no.php +++ b/library/phpmailer/language/phpmailer.lang-no.php @@ -7,19 +7,18 @@ $PHPMAILER_LANG['authenticate'] = 'SMTP Feil: Kunne ikke authentisere.'; $PHPMAILER_LANG['connect_host'] = 'SMTP Feil: Kunne ikke koble til SMTP host.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Feil: Data ble ikke akseptert.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; -$PHPMAILER_LANG['encoding'] = 'Ukjent encoding: '; +$PHPMAILER_LANG['empty_message'] = 'Meldingsinnholdet er tomt'; +$PHPMAILER_LANG['encoding'] = 'Ukjent tegnkoding: '; $PHPMAILER_LANG['execute'] = 'Kunne ikke utføre: '; -$PHPMAILER_LANG['file_access'] = 'Kunne ikke få tilgang til filen: '; +$PHPMAILER_LANG['file_access'] = 'Får ikke tilgang til filen: '; $PHPMAILER_LANG['file_open'] = 'Fil feil: Kunne ikke åpne filen: '; -$PHPMAILER_LANG['from_failed'] = 'Følgende Fra feilet: '; -$PHPMAILER_LANG['instantiate'] = 'Kunne ikke instantiate mail funksjonen.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; -$PHPMAILER_LANG['provide_address'] = 'Du må ha med minst en mottager adresse.'; +$PHPMAILER_LANG['from_failed'] = 'Følgende avsenderadresse feilet: '; +$PHPMAILER_LANG['instantiate'] = 'Kunne ikke initialisere mailfunksjonen.'; +$PHPMAILER_LANG['invalid_address'] = 'Meldingen ble ikke sendt, følgende adresse er ugyldig: '; +$PHPMAILER_LANG['provide_address'] = 'Du må angi minst en mottakeradresse.'; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer er ikke supportert.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Feil: Følgende mottagere feilet: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['signing'] = 'Signeringsfeil: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() feilet.'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfeil: '; +$PHPMAILER_LANG['variable_set'] = 'Kan ikke sette eller resette variabelen: ';
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-pl.php b/library/phpmailer/language/phpmailer.lang-pl.php index 6e9a82fda6..5a4ad38318 100644 --- a/library/phpmailer/language/phpmailer.lang-pl.php +++ b/library/phpmailer/language/phpmailer.lang-pl.php @@ -3,22 +3,22 @@ * PHPMailer language file: refer to English translation for definitive list * Polish Version */ -$PHPMAILER_LANG = array( - 'provide_address' => 'Należy podać prawidłowy adres email Odbiorcy.', - 'mailer_not_supported' => 'Wybrana metoda wysyłania wiadomości nie jest obsługiwana.', - 'execute' => 'Nie można uruchomić: ', - 'instantiate' => 'Nie można wywołać funkcji mail(). Sprawdź konfigurację serwera.', - 'authenticate' => 'Błąd SMTP: Nie można przeprowadzić uwierzytelniania.', - 'from_failed' => 'Następujący adres Nadawcy jest jest nieprawidłowy: ', - 'recipients_failed' => 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi: ', - 'data_not_accepted' => 'Błąd SMTP: Dane nie zostały przyjęte.', - 'connect_host' => 'Błąd SMTP: Nie można połączyć się z wybranym hostem.', - 'file_access' => 'Brak dostępu do pliku: ', - 'file_open' => 'Nie można otworzyć pliku: ', - 'encoding' => 'Nieznany sposób kodowania znaków: ', - 'signing' => 'Błąd logowania: ', - 'smtp_error' => 'Błąd serwera SMTP: ', - 'empty_message' => 'Pusta treść wiadomości', - 'invalid_address' => 'Adres email jest nieprawidłowy', - 'variable_set' => 'Nie można ustawić lub zresetować zmiennej: ' -);
\ No newline at end of file + +$PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: Nie można przeprowadzić autentykacji.'; +$PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: Nie można połączyć się z wybranym hostem.'; +$PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: Dane nie zostały przyjęte.'; +$PHPMAILER_LANG['empty_message'] = 'Wiadomość jest pusta.'; +$PHPMAILER_LANG['encoding'] = 'Nieznany sposób kodowania znaków: '; +$PHPMAILER_LANG['execute'] = 'Nie można uruchomić: '; +$PHPMAILER_LANG['file_access'] = 'Brak dostępu do pliku: '; +$PHPMAILER_LANG['file_open'] = 'Nie można otworzyć pliku: '; +$PHPMAILER_LANG['from_failed'] = 'Następujący adres Nadawcy jest nieprawidłowy: '; +$PHPMAILER_LANG['instantiate'] = 'Nie można wywołać funkcji mail(). Sprawdź konfigurację serwera.'; +$PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości, następujący adres Odbiorcy jest nieprawidłowy: '; +$PHPMAILER_LANG['provide_address'] = 'Należy podać prawidłowy adres email Odbiorcy.'; +$PHPMAILER_LANG['mailer_not_supported'] = 'Wybrana metoda wysyłki wiadomości nie jest obsługiwana.'; +$PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi: '; +$PHPMAILER_LANG['signing'] = 'Błąd podpisywania wiadomości: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() zakończone niepowodzeniem.'; +$PHPMAILER_LANG['smtp_error'] = 'Błąd SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'Nie można zmienić zmiennej: '; diff --git a/library/phpmailer/language/phpmailer.lang-ro.php b/library/phpmailer/language/phpmailer.lang-ro.php index f6aa922556..1727cef04a 100644 --- a/library/phpmailer/language/phpmailer.lang-ro.php +++ b/library/phpmailer/language/phpmailer.lang-ro.php @@ -16,7 +16,7 @@ $PHPMAILER_LANG['file_access'] = 'Nu pot accesa fisierul: '; $PHPMAILER_LANG['file_open'] = 'Eroare de fisier: Nu pot deschide fisierul: '; $PHPMAILER_LANG['from_failed'] = 'Urmatoarele adrese From au dat eroare: '; $PHPMAILER_LANG['instantiate'] = 'Nu am putut instantia functia mail.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer nu este suportat.'; $PHPMAILER_LANG['provide_address'] = 'Trebuie sa adaugati cel putin un recipient (adresa de mail).'; $PHPMAILER_LANG['recipients_failed'] = 'Eroare SMTP: Urmatoarele adrese de mail au dat eroare: '; @@ -24,4 +24,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'Eroare SMTP: Urmatoarele adrese de ma //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-ru.php b/library/phpmailer/language/phpmailer.lang-ru.php index d6990525de..9e583dae05 100644 --- a/library/phpmailer/language/phpmailer.lang-ru.php +++ b/library/phpmailer/language/phpmailer.lang-ru.php @@ -7,19 +7,18 @@ $PHPMAILER_LANG['authenticate'] = 'Ошибка SMTP: ошибка авторизации.'; $PHPMAILER_LANG['connect_host'] = 'Ошибка SMTP: не удается подключиться к серверу SMTP.'; $PHPMAILER_LANG['data_not_accepted'] = 'Ошибка SMTP: данные не приняты.'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; $PHPMAILER_LANG['encoding'] = 'Неизвестный вид кодировки: '; $PHPMAILER_LANG['execute'] = 'Невозможно выполнить команду: '; $PHPMAILER_LANG['file_access'] = 'Нет доступа к файлу: '; $PHPMAILER_LANG['file_open'] = 'Файловая ошибка: не удается открыть файл: '; $PHPMAILER_LANG['from_failed'] = 'Неверный адрес отправителя: '; $PHPMAILER_LANG['instantiate'] = 'Невозможно запустить функцию mail.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['provide_address'] = 'Пожалуйста, введите хотя бы один адрес e-mail получателя.'; $PHPMAILER_LANG['mailer_not_supported'] = ' - почтовый сервер не поддерживается.'; $PHPMAILER_LANG['recipients_failed'] = 'Ошибка SMTP: отправка по следующим адресам получателей не удалась: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['empty_message'] = 'Пустое тело сообщения'; +$PHPMAILER_LANG['invalid_address'] = 'Не отослано, неправильный формат email адреса: '; +$PHPMAILER_LANG['signing'] = 'Ошибка подписывания: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Ошибка соединения с SMTP-сервером'; +$PHPMAILER_LANG['smtp_error'] = 'Ошибка SMTP-сервера: '; +$PHPMAILER_LANG['variable_set'] = 'Невозможно установить или переустановить переменную: '; diff --git a/library/phpmailer/language/phpmailer.lang-se.php b/library/phpmailer/language/phpmailer.lang-se.php index 67e05f59c6..65d197995c 100644 --- a/library/phpmailer/language/phpmailer.lang-se.php +++ b/library/phpmailer/language/phpmailer.lang-se.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = 'Ingen åtkomst till fil: '; $PHPMAILER_LANG['file_open'] = 'Fil fel: Kunde inte öppna fil: '; $PHPMAILER_LANG['from_failed'] = 'Följande avsändaradress är felaktig: '; $PHPMAILER_LANG['instantiate'] = 'Kunde inte initiera e-postfunktion.'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['provide_address'] = 'Du måste ange minst en mottagares e-postadress.'; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer stöds inte.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP fel: Följande mottagare är felaktig: '; @@ -23,4 +23,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP fel: Följande mottagare är fel //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-sk.php b/library/phpmailer/language/phpmailer.lang-sk.php new file mode 100644 index 0000000000..1722a5f526 --- /dev/null +++ b/library/phpmailer/language/phpmailer.lang-sk.php @@ -0,0 +1,25 @@ +<?php +/** +* PHPMailer language file: refer to English translation for definitive list +* Slovak Version +* Author: Michal Tinka <michaltinka@gmail.com> +*/ + +$PHPMAILER_LANG['authenticate'] = 'SMTP Error: Chyba autentifikácie.'; +$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Nebolo možné nadviazať spojenie so SMTP serverom.'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Dáta neboli prijaté'; +$PHPMAILER_LANG['empty_message'] = 'Prázdne telo správy.'; +$PHPMAILER_LANG['encoding'] = 'Neznáme kódovanie: '; +$PHPMAILER_LANG['execute'] = 'Nedá sa vykonať: '; +$PHPMAILER_LANG['file_access'] = 'Súbor nebol nájdený: '; +$PHPMAILER_LANG['file_open'] = 'File Error: Súbor sa otvoriť pre čítanie: '; +$PHPMAILER_LANG['from_failed'] = 'Následujúca adresa From je nesprávna: '; +$PHPMAILER_LANG['instantiate'] = 'Nedá sa vytvoriť inštancia emailovej funkcie.'; +$PHPMAILER_LANG['invalid_address'] = 'Neodoslané, emailová adresa je nesprávna: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' emailový klient nieje podporovaný.'; +$PHPMAILER_LANG['provide_address'] = 'Musíte zadať aspoň jednu emailovú adresu príjemcu.'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Adresy príjemcov niesu správne '; +$PHPMAILER_LANG['signing'] = 'Chyba prihlasovania: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() zlyhalo.'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP chyba serveru: '; +$PHPMAILER_LANG['variable_set'] = 'Nemožno nastaviť alebo resetovať premennú: '; diff --git a/library/phpmailer/language/phpmailer.lang-tr.php b/library/phpmailer/language/phpmailer.lang-tr.php index b066353f9e..abba0818d4 100644 --- a/library/phpmailer/language/phpmailer.lang-tr.php +++ b/library/phpmailer/language/phpmailer.lang-tr.php @@ -3,24 +3,24 @@ * PHPMailer language file: refer to English translation for definitive list * Turkish version * Türkçe Versiyonu -* Tercüme Adem GENÇ - tutastes@gmail.com +* ÝZYAZILIM - Elçin Özel - Can Yýlmaz - Mehmet Benlioðlu */ -$PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Kimlik doğrulanamıyor.'; -$PHPMAILER_LANG['connect_host'] = 'SMTP Hatası: SMTP hosta bağlanamıyor.'; +$PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Doğrulanamıyor.'; +$PHPMAILER_LANG['connect_host'] = 'SMTP Hatası: SMTP hosta bağlanılamıyor.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hatası: Veri kabul edilmedi.'; $PHPMAILER_LANG['empty_message'] = 'Mesaj içeriği boş'; -$PHPMAILER_LANG['encoding'] = 'Bilinmeyen kodlama: '; -$PHPMAILER_LANG['execute'] = 'Çalıştırılamıyor: '; +$PHPMAILER_LANG['encoding'] = 'Bilinmeyen şifreleme: '; +$PHPMAILER_LANG['execute'] = 'Çalıtırılamıyor: '; $PHPMAILER_LANG['file_access'] = 'Dosyaya erişilemiyor: '; -$PHPMAILER_LANG['file_open'] = 'Dosya Hatası: Dosya açılamadı: '; -$PHPMAILER_LANG['from_failed'] = 'Aşağıdaki adresler başarısız oldu: '; -$PHPMAILER_LANG['instantiate'] = 'Email fonksiyonu kanıt sunulamadı.'; -$PHPMAILER_LANG['invalid_email'] = 'Geçersiz email adresi'; -$PHPMAILER_LANG['provide_address'] = 'En az bir alıcı email adresini vermeniz gerekmektedir.'; +$PHPMAILER_LANG['file_open'] = 'Dosya Hatası: Dosya açılamıyor: '; +$PHPMAILER_LANG['from_failed'] = 'Başarısız olan gönderici adresi: '; +$PHPMAILER_LANG['instantiate'] = 'Örnek mail fonksiyonu oluşturulamadı.'; +$PHPMAILER_LANG['invalid_address'] = 'Gönderilmedi, email adresi geçersiz: '; +$PHPMAILER_LANG['provide_address'] = 'En az bir tane mail adresi belirtmek zorundasınız alıcının email adresi.'; $PHPMAILER_LANG['mailer_not_supported'] = ' mailler desteklenmemektedir.'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP Hatası: Aşağıdaki alıcılara teslim edilemedi: '; -$PHPMAILER_LANG['signing'] = 'Hata İmzalama: '; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP Hatası: alıcılara ulaımadı: '; +$PHPMAILER_LANG['signing'] = 'İmzalama hatası: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP bağlantı() başarısız.'; $PHPMAILER_LANG['smtp_error'] = 'SMTP sunucu hatası: '; -$PHPMAILER_LANG['variable_set'] = 'Ayarlayamıyor veya değişken sıfırlanamıyor: '; -?>
\ No newline at end of file +$PHPMAILER_LANG['variable_set'] = 'Ayarlanamıyor yada sıfırlanamıyor: '; diff --git a/library/phpmailer/language/phpmailer.lang-uk.php b/library/phpmailer/language/phpmailer.lang-uk.php new file mode 100644 index 0000000000..112bba8468 --- /dev/null +++ b/library/phpmailer/language/phpmailer.lang-uk.php @@ -0,0 +1,24 @@ +<?php +/** +* PHPMailer language file: refer to English translation for definitive list +* Ukrainian Version by Yuriy Rudyy <yrudyy@prs.net.ua> +*/ + +$PHPMAILER_LANG['authenticate'] = 'Помилка SMTP: помилка авторизації.'; +$PHPMAILER_LANG['connect_host'] = 'Помилка SMTP: не вдається підєднатися до серверу SMTP.'; +$PHPMAILER_LANG['data_not_accepted'] = 'Помилка SMTP: дані не прийняті.'; +$PHPMAILER_LANG['encoding'] = 'Невідомий тип кодування: '; +$PHPMAILER_LANG['execute'] = 'Неможливо виконати команду: '; +$PHPMAILER_LANG['file_access'] = 'Немає доступу до файлу: '; +$PHPMAILER_LANG['file_open'] = 'Помилка файлової системи: не вдається відкрити файл: '; +$PHPMAILER_LANG['from_failed'] = 'Невірна адреса відправника: '; +$PHPMAILER_LANG['instantiate'] = 'Неможливо запустити функцію mail.'; +$PHPMAILER_LANG['provide_address'] = 'Будь-ласка, введіть хоча б одну адресу e-mail отримувача.'; +$PHPMAILER_LANG['mailer_not_supported'] = ' - поштовий сервер не підтримується.'; +$PHPMAILER_LANG['recipients_failed'] = 'Помилка SMTP: відправти наступним отрмувачам не вдалася: '; +$PHPMAILER_LANG['empty_message'] = 'Пусте тіло повідомлення'; +$PHPMAILER_LANG['invalid_address'] = 'Не відправлено, невірний формат email адреси: '; +$PHPMAILER_LANG['signing'] = 'Помилка підпису: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Помилка зєднання із SMTP-сервером'; +$PHPMAILER_LANG['smtp_error'] = 'Помилка SMTP-сервера: '; +$PHPMAILER_LANG['variable_set'] = 'Неможливо встановити або перевстановити змінну: '; diff --git a/library/phpmailer/language/phpmailer.lang-zh.php b/library/phpmailer/language/phpmailer.lang-zh.php index fef66f8cb1..b0e8f4e091 100644 --- a/library/phpmailer/language/phpmailer.lang-zh.php +++ b/library/phpmailer/language/phpmailer.lang-zh.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_open'] = '文件錯誤:無法打開文件:'; $PHPMAILER_LANG['from_failed'] = '發送地址錯誤:'; $PHPMAILER_LANG['execute'] = '無法執行:'; $PHPMAILER_LANG['instantiate'] = '未知函數調用。'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['provide_address'] = '必須提供至少一個收件人地址。'; $PHPMAILER_LANG['mailer_not_supported'] = '發信客戶端不被支持。'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP 錯誤:收件人地址錯誤:'; @@ -23,4 +23,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP 錯誤:收件人地址錯誤:'; //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/library/phpmailer/language/phpmailer.lang-zh_cn.php b/library/phpmailer/language/phpmailer.lang-zh_cn.php index b188404359..78eb9acf36 100644 --- a/library/phpmailer/language/phpmailer.lang-zh_cn.php +++ b/library/phpmailer/language/phpmailer.lang-zh_cn.php @@ -15,7 +15,7 @@ $PHPMAILER_LANG['file_access'] = '无法访问文件:'; $PHPMAILER_LANG['file_open'] = '文件错误:无法打开文件:'; $PHPMAILER_LANG['from_failed'] = '发送地址错误:'; $PHPMAILER_LANG['instantiate'] = '未知函数调用。'; -//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: '; +//$PHPMAILER_LANG['invalid_address'] = 'Not sending, email address is invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = '发信客户端不被支持。'; $PHPMAILER_LANG['provide_address'] = '必须提供至少一个收件人地址。'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误:'; @@ -23,4 +23,3 @@ $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误:'; //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -?>
\ No newline at end of file diff --git a/mediafirewall.php b/mediafirewall.php index 827ec29ca1..7251805996 100644 --- a/mediafirewall.php +++ b/mediafirewall.php @@ -230,7 +230,7 @@ function isImageTypeSupported($reqtype) { $useTTF = function_exists('imagettftext'); // Media object missing/private? -if (!$media || !$media->canDisplayDetails()) { +if (!$media || !$media->canShow()) { send404AndExit(); } // Media file somewhere else? diff --git a/medialist.php b/medialist.php index b4d45ef1a4..8e22d21bf7 100644 --- a/medialist.php +++ b/medialist.php @@ -287,8 +287,8 @@ if ($search) { } echo '<br>'; echo '<div style="white-space: normal; width: 95%;">'; - print_fact_sources($mediaobject->getGedcomRecord(), 1); - print_fact_notes($mediaobject->getGedcomRecord(), 1); + print_fact_sources($mediaobject->getGedcom(), 1); + print_fact_notes($mediaobject->getGedcom(), 1); echo '</div>'; foreach ($mediaobject->fetchLinkedIndividuals() as $individual) { echo '<a href="' . $individual->getHtmlUrl() . '">' . WT_I18N::translate('View Person') . ' — ' . $individual->getFullname().'</a><br>'; diff --git a/mediaviewer.php b/mediaviewer.php index 845611893f..2c6b3f5c0b 100644 --- a/mediaviewer.php +++ b/mediaviewer.php @@ -31,9 +31,9 @@ require_once WT_ROOT.'includes/functions/functions_print_lists.php'; $controller=new WT_Controller_Media(); -if ($controller->record && $controller->record->canDisplayDetails()) { +if ($controller->record && $controller->record->canShow()) { $controller->pageHeader(); - if ($controller->record->isMarkedDeleted()) { + if ($controller->record->isOld()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -51,7 +51,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { ' ', help_link('pending_changes'), '</p>'; } - } elseif (find_updated_record($controller->record->getXref(), WT_GED_ID)!==null) { + } elseif ($controller->record->isNew()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', diff --git a/modules_v3/GEDFact_assistant/_CENS/addnoteaction_assisted.php b/modules_v3/GEDFact_assistant/_CENS/addnoteaction_assisted.php index 858d232fb4..89b0ecd310 100644 --- a/modules_v3/GEDFact_assistant/_CENS/addnoteaction_assisted.php +++ b/modules_v3/GEDFact_assistant/_CENS/addnoteaction_assisted.php @@ -90,13 +90,13 @@ if (!empty($NOTE)) { } if ($pid_array != '') { - $xref = append_gedrec($newgedrec, WT_GED_ID); + $record = WT_GedcomRecord::createRecord($newgedrec, WT_GED_ID); } else { - $xref=''; + $record=''; echo '<div class="indent">No individuals entered, close and try again </div>'; } -if ($xref) { +if ($record) { $controller->addInlineJavascript(' if (parent.opener.document.getElementById("pids_array_edit") == null || parent.opener.document.getElementById("pids_array_edit") == "undefined") { } else { @@ -106,6 +106,6 @@ if ($xref) { } else { parent.opener.document.addform.pids_array_add.value="' . $pid_array . '"; } - openerpasteid("' . $xref . '") + openerpasteid("' . $record->getXref() . '") '); } diff --git a/modules_v3/GEDFact_assistant/_CENS/census_1_ctrl.php b/modules_v3/GEDFact_assistant/_CENS/census_1_ctrl.php index 97969e5f7a..0fa8dfe06f 100644 --- a/modules_v3/GEDFact_assistant/_CENS/census_1_ctrl.php +++ b/modules_v3/GEDFact_assistant/_CENS/census_1_ctrl.php @@ -4,7 +4,7 @@ // Census information about an individual // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -43,7 +43,7 @@ $ctry = 'UK'; // === Set $married to "Not married as we only want the Birth name here" === $married=-1; -$person=WT_Person::getInstance($pid); +$person=WT_Individual::getInstance($pid); // var_dump($person->getAllNames()); $nam = $person->getAllNames(); if ($person->getDeathYear() == 0) { $DeathYr = ""; } else { $DeathYr = $person->getDeathYear(); } diff --git a/modules_v3/GEDFact_assistant/_CENS/census_3_search_add.php b/modules_v3/GEDFact_assistant/_CENS/census_3_search_add.php index 60ded5a136..d7b372eb63 100644 --- a/modules_v3/GEDFact_assistant/_CENS/census_3_search_add.php +++ b/modules_v3/GEDFact_assistant/_CENS/census_3_search_add.php @@ -128,7 +128,7 @@ if (!defined('WT_WEBTREES')) { if (isset($people["husb"])) { //-- Parents Husbands Parents -------------------------------------- - $gparent=WT_Person::getInstance($people["husb"]->getXref()); + $gparent=WT_Individual::getInstance($people["husb"]->getXref()); $fams = $gparent->getChildFamilies(); foreach ($fams as $famid=>$family) { if (!is_null($family)) { @@ -177,7 +177,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($people["husb"]->canDisplayDetails())) { + if (($people["husb"]->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $people["husb"]->getXref() ; // pid = PID @@ -250,7 +250,7 @@ if (!defined('WT_WEBTREES')) { if (isset($people["wife"])) { //-- Parents Wifes Parent Family --------------------------- - $gparent=WT_Person::getInstance($people["wife"]->getXref()); + $gparent=WT_Individual::getInstance($people["wife"]->getXref()); $fams = $gparent->getChildFamilies(); foreach ($fams as $famid=>$family) { if (!is_null($family)) { @@ -309,7 +309,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($people["wife"]->canDisplayDetails())) { + if (($people["wife"]->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $people["wife"]->getXref() ; // pid = PID @@ -454,7 +454,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($child->canDisplayDetails())) { + if (($child->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $child->getXref(); // pid = PID @@ -562,7 +562,7 @@ if (!defined('WT_WEBTREES')) { if (isset($people["husb"])) { //-- Step Husbands Parent Family -------------------------------------- - $gparent=WT_Person::getInstance($people["husb"]->getXref()); + $gparent=WT_Individual::getInstance($people["husb"]->getXref()); $fams = $gparent->getChildFamilies(); foreach ($fams as $famid=>$family) { if (!is_null($family)) { @@ -617,7 +617,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($people["husb"]->canDisplayDetails())) { + if (($people["husb"]->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $people["husb"]->getXref(); // pid = PID @@ -695,7 +695,7 @@ if (!defined('WT_WEBTREES')) { if (isset($people["wife"])) { //-- Step Wifes Parent Family -------------------------------------- - $gparent=WT_Person::getInstance($people["wife"]->getXref()); + $gparent=WT_Individual::getInstance($people["wife"]->getXref()); $fams = $gparent->getChildFamilies(); foreach ($fams as $famid=>$family) { if (!is_null($family)) { @@ -761,7 +761,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($people["wife"]->canDisplayDetails())) { + if (($people["wife"]->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $people["wife"]->getXref() ; // pid = PID @@ -895,7 +895,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($child->canDisplayDetails())) { + if (($child->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $child->getXref() ; // pid = PID @@ -992,7 +992,7 @@ if (!defined('WT_WEBTREES')) { if (isset($people["husb"])) { //-- Spouse Husbands Parents -------------------------------------- - $gparent=WT_Person::getInstance($people["husb"]->getXref()); + $gparent=WT_Individual::getInstance($people["husb"]->getXref()); $fams = $gparent->getChildFamilies(); foreach ($fams as $family) { if (!is_null($family)) { @@ -1048,7 +1048,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($people["husb"]->canDisplayDetails())) { + if (($people["husb"]->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $people["husb"]->getXref() ; // pid = PID @@ -1125,7 +1125,7 @@ if (!defined('WT_WEBTREES')) { if (isset($people["wife"])) { //-- Spouse Wifes Parents -------------------------------------- - $gparent=WT_Person::getInstance($people["wife"]->getXref()); + $gparent=WT_Individual::getInstance($people["wife"]->getXref()); $fams = $gparent->getChildFamilies(); foreach ($fams as $family) { if (!is_null($family)) { @@ -1193,7 +1193,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($people["wife"]->canDisplayDetails())) { + if (($people["wife"]->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $people["wife"]->getXref() ; // pid = PID @@ -1331,7 +1331,7 @@ if (!defined('WT_WEBTREES')) { <td align="left" class="facts_value nowrap"> <font size=1> <?php - if (($child->canDisplayDetails())) { + if (($child->canShow())) { ?> <a href='#' onclick='insertRowToTable("<?php echo $child->getXref() ; // pid = PID @@ -1442,7 +1442,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if (!isset($OLD_PGENS)) $OLD_PGENS = $DEFAULT_PEDIGREE_GENERATIONS; if (!isset($talloffset)) $talloffset = $PEDIGREE_LAYOUT; - $person=WT_Person::getInstance($pid); + $person=WT_Individual::getInstance($pid); if ($pid==false || empty($person)) { $spouselinks = false; $parentlinks = false; @@ -1454,9 +1454,9 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", $spouselinks = ""; $parentlinks = ""; $step_parentlinks = ""; - $disp=$person->canDisplayDetails(); + $disp=$person->canShow(); - if ($person->canDisplayName() && !$SEARCH_SPIDER) { + if ($person->canShowName() && !$SEARCH_SPIDER) { //-- draw a box for the family popup if ($TEXT_DIRECTION=="rtl") { @@ -1512,7 +1512,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($husb || $num>0) { if ($husb) { //-- Parent Husbands Parents ---------------------- - $gparent=WT_Person::getInstance($husb->getXref()); + $gparent=WT_Individual::getInstance($husb->getXref()); $parfams = $gparent->getChildFamilies(); foreach ($parfams as $pfamily) { if (!is_null($pfamily)) { @@ -1525,7 +1525,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", //-- Parent Husbands Details ---------------------- $person_parent="Yes"; $tmp=$husb->getXref(); - if ($husb->canDisplayName()) { + if ($husb->canShowName()) { $nam = $husb->getAllNames(); $fulln = rtrim($nam[0]['givn'],'*')." ".$nam[0]['surname']; $fulln = str_replace("@N.N.", "(".WT_I18N::translate('unknown').")", $fulln); @@ -1594,7 +1594,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($wife || $num>0) { if ($wife) { //-- Parent Wifes Parents ---------------------- - $gparent=WT_Person::getInstance($wife->getXref()); + $gparent=WT_Individual::getInstance($wife->getXref()); $parfams = $gparent->getChildFamilies(); foreach ($parfams as $pfamily) { if (!is_null($pfamily)) { @@ -1607,7 +1607,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", //-- Parent Wifes Details ---------------------- $person_parent="Yes"; $tmp=$wife->getXref(); - if ($wife->canDisplayName()) { + if ($wife->canShowName()) { $married = WT_Date::Compare($censdate, $marrdate); $nam = $wife->getAllNames(); $fulln = rtrim($nam[0]['givn'],'*')." ".$nam[0]['surname']; @@ -1721,7 +1721,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if (($husb || $num>0) && $husb->getLabel() != ".") { if ($husb) { //-- Step Husbands Parents ----------------------------- - $gparent=WT_Person::getInstance($husb->getXref()); + $gparent=WT_Individual::getInstance($husb->getXref()); $parfams = $gparent->getChildFamilies(); foreach ($parfams as $pfamily) { if (!is_null($pfamily)) { @@ -1734,7 +1734,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", //-- Step Husband Details ------------------------------ $person_step="Yes"; $tmp=$husb->getXref(); - if ($husb->canDisplayName()) { + if ($husb->canShowName()) { $nam = $husb->getAllNames(); $fulln = rtrim($nam[0]['givn'],'*')." ".$nam[0]['surname']; $fulln = str_replace("@N.N.", "(".WT_I18N::translate('unknown').")", $fulln); @@ -1806,7 +1806,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($wife || $num>0) { if ($wife) { //-- Step Wifes Parents --------------------------- - $gparent=WT_Person::getInstance($wife->getXref()); + $gparent=WT_Individual::getInstance($wife->getXref()); $parfams = $gparent->getChildFamilies(); foreach ($parfams as $pfamily) { if (!is_null($pfamily)) { @@ -1819,7 +1819,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", //-- Step Wife Details ------------------------------ $person_step="Yes"; $tmp=$wife->getXref(); - if ($wife->canDisplayName()) { + if ($wife->canShowName()) { $married = WT_Date::Compare($censdate, $marrdate); $nam = $wife->getAllNames(); $fulln = rtrim($nam[0]['givn'],'*')." ".$nam[0]['surname']; @@ -1932,7 +1932,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($spouse) { //-- Spouse Parents ----------------------------- - $gparent=WT_Person::getInstance($spouse->getXref()); + $gparent=WT_Individual::getInstance($spouse->getXref()); $spousefams = $gparent->getChildFamilies(); foreach ($spousefams as $pfamily) { if (!is_null($pfamily)) { @@ -1945,7 +1945,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", //-- Spouse Details ----------------------------- $tmp=$spouse->getXref(); - if ($spouse->canDisplayName()) { + if ($spouse->canShowName()) { $married = WT_Date::Compare($censdate, $marrdate); $nam = $spouse->getAllNames(); $fulln = rtrim($nam[0]['givn'],'*')." ".$nam[0]['surname']; @@ -2035,7 +2035,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", $persons="Yes"; //-- Childs Parents --------------------- - $gparent=WT_Person::getInstance($child->getXref()); + $gparent=WT_Individual::getInstance($child->getXref()); $fams = $gparent->getChildFamilies(); $chfams = $gparent->getSpouseFamilies(); foreach ($fams as $family) { @@ -2077,7 +2077,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", } // Childs Details ------------------------- $spouselinks .= "<li>"; - if ($child->canDisplayName()) { + if ($child->canShowName()) { $nam = $child->getAllNames(); $fulln = rtrim($nam[0]['givn'],'*')." ".$nam[0]['surname']; $fulln = str_replace("@N.N.", "(".WT_I18N::translate('unknown').")", $fulln); diff --git a/modules_v3/GEDFact_assistant/_MEDIA/media_0_inverselink.php b/modules_v3/GEDFact_assistant/_MEDIA/media_0_inverselink.php index 3ec3cb93ba..a8a4d82e88 100644 --- a/modules_v3/GEDFact_assistant/_MEDIA/media_0_inverselink.php +++ b/modules_v3/GEDFact_assistant/_MEDIA/media_0_inverselink.php @@ -36,7 +36,7 @@ $update_CHAN = safe_REQUEST($_REQUEST, 'preserve_last_changed', WT_REGEX_UNSAFE) $controller->addExternalJavascript(WT_STATIC_URL.'js/autocomplete.js'); $paramok = true; -if (!empty($linktoid)) $paramok = WT_GedcomRecord::getInstance($linktoid)->canDisplayDetails(); +if (!empty($linktoid)) $paramok = WT_GedcomRecord::getInstance($linktoid)->canShow(); if ($action == 'choose' && $paramok) { @@ -139,7 +139,7 @@ if ($action == 'choose' && $paramok) { echo "<td align='center'><input alt='", WT_I18N::translate('Keep Link in list'), "', title='", WT_I18N::translate('Keep Link in list'), "' type='radio' id='", $record->getXref(), "_off' name='", $record->getXref(), "' checked></td>"; echo "<td align='center'><input alt='", WT_I18N::translate('Remove Link from list'), "', title='", WT_I18N::translate('Remove Link from list'), "' type='radio' id='", $record->getXref(), "_on' name='", $record->getXref(), "'></td>"; - if ($record instanceof WT_Person) { + if ($record instanceof WT_Individual) { ?> <td align="center"><a href="#" class="icon-button_family" title="<?php echo WT_I18N::translate('Family navigator'); ?>" name="family_'<?php echo $record->getXref(); ?>'" onclick="openFamNav('<?php echo $record->getXref(); ?>'); return false;"></a></td> <?php @@ -173,7 +173,7 @@ if ($action == 'choose' && $paramok) { if ($linktoid=="") { // ---- } else { - $record=WT_Person::getInstance($linktoid); + $record=WT_Individual::getInstance($linktoid); echo '<b>', $record->getFullName(), '</b>'; } echo '<table><tr><td>'; diff --git a/modules_v3/GEDFact_assistant/_MEDIA/media_1_ctrl.php b/modules_v3/GEDFact_assistant/_MEDIA/media_1_ctrl.php index 1264df8029..ab5e17cba2 100644 --- a/modules_v3/GEDFact_assistant/_MEDIA/media_1_ctrl.php +++ b/modules_v3/GEDFact_assistant/_MEDIA/media_1_ctrl.php @@ -35,7 +35,7 @@ global $summary, $censyear, $censdate; $pid = safe_get('pid'); $year = "1901"; -$censevent = new WT_Event("1 CENS\n2 DATE 03 MAR".$year."", null, 0); +$censevent = new WT_Fact("1 CENS\n2 DATE 03 MAR".$year."", null, 0); $censdate = $censevent->getDate(); $censyear = $censdate->date1->y; $ctry = "UK"; @@ -49,7 +49,7 @@ if ($pid=="") { echo "<br><br>"; } else { - $person=WT_Person::getInstance($pid); + $person=WT_Individual::getInstance($pid); if ($person->getDeathYear() == 0) { $DeathYr = ""; } else { $DeathYr = $person->getDeathYear(); } if ($person->getBirthYear() == 0) { $BirthYr = ""; } else { $BirthYr = $person->getBirthYear(); } $currpid=$pid; @@ -169,7 +169,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($people["husb"]->canDisplayDetails())) { + if (($people["husb"]->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $people["husb"]->getXref() ; // pid = PID @@ -237,7 +237,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($people["wife"]->canDisplayDetails())) { + if (($people["wife"]->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $people["wife"]->getXref() ; // pid = PID @@ -323,7 +323,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($child->canDisplayDetails())) { + if (($child->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $child->getXref() ; // pid = PID @@ -419,7 +419,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($people["husb"]->canDisplayDetails())) { + if (($people["husb"]->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $people["husb"]->getXref() ; // pid = PID @@ -500,7 +500,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($people["wife"]->canDisplayDetails())) { + if (($people["wife"]->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $people["wife"]->getXref() ; // pid = PID @@ -576,7 +576,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($child->canDisplayDetails())) { + if (($child->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $child->getXref() ; // pid = PID @@ -661,7 +661,7 @@ if ($pid=="") { <td align="left" class="facts_value" > <font size=1> <?php - if (($people["husb"]->canDisplayDetails())) { + if (($people["husb"]->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $people["husb"]->getXref() ; // pid = PID @@ -744,7 +744,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($people["wife"]->canDisplayDetails())) { + if (($people["wife"]->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $people["wife"]->getXref() ; // pid = PID @@ -822,7 +822,7 @@ if ($pid=="") { <td align="left" class="facts_value"> <font size=1> <?php - if (($child->canDisplayDetails())) { + if (($child->canShow())) { ?> <a href='#' onclick='opener.insertRowToTable("<?php echo $child->getXref() ; // pid = PID @@ -907,7 +907,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if (!isset($OLD_PGENS)) $OLD_PGENS = $DEFAULT_PEDIGREE_GENERATIONS; if (!isset($talloffset)) $talloffset = $PEDIGREE_LAYOUT; - $person=WT_Person::getInstance($pid); + $person=WT_Individual::getInstance($pid); if ($pid==false || empty($person)) { $spouselinks = false; $parentlinks = false; @@ -919,9 +919,9 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", $spouselinks = ""; $parentlinks = ""; $step_parentlinks = ""; - $disp=$person->canDisplayDetails(); + $disp=$person->canShow(); - if ($person->canDisplayName() && !$SEARCH_SPIDER) { + if ($person->canShowName() && !$SEARCH_SPIDER) { //-- draw a box for the family popup if ($TEXT_DIRECTION=="rtl") { $spouselinks .= "<table id=\"flyoutFamRTL\" class=\"person_box$isF\"><tr><td class=\"name2 font9 rtl\">"; @@ -958,7 +958,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($husb) { $person_parent="Yes"; $tmp=$husb->getXref(); - if ($husb->canDisplayName()) { + if ($husb->canShowName()) { $fulln =strip_tags($husb->getFullName()); $parentlinks .= "<a href=\"#\" onclick=\"opener.insertRowToTable("; $parentlinks .= "'".$husb->getXref()."', "; // pid = PID @@ -995,7 +995,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($wife) { $person_parent="Yes"; $tmp=$wife->getXref(); - if ($wife->canDisplayName()) { + if ($wife->canShowName()) { $married = WT_Date::Compare($censdate, $marrdate); $fulln =strip_tags($wife->getFullName()); $parentlinks .= "<a href=\"#\" onclick=\"opener.insertRowToTable("; @@ -1048,7 +1048,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($husb) { $person_step="Yes"; $tmp=$husb->getXref(); - if ($husb->canDisplayName()) { + if ($husb->canShowName()) { $fulln =strip_tags($husb->getFullName()); $parentlinks .= "<a href=\"individual.php?pid={$tmp}&tab={$tabno}&gedcom=".WT_GEDURL."\">"; $parentlinks .= $husb->getFullName(); @@ -1068,7 +1068,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($wife) { $person_step="Yes"; $tmp=$wife->getXref(); - if ($wife->canDisplayName()) { + if ($wife->canShowName()) { $married = WT_Date::Compare($censdate, $marrdate); $fulln =addslashes($wife->getFullName()); $parentlinks .= "<a href=\"individual.php?pid={$tmp}&tab={$tabno}&gedcom=".WT_GEDURL."\">"; @@ -1096,7 +1096,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", if ($spouse || $num>0) { if ($spouse) { $tmp=$spouse->getXref(); - if ($spouse->canDisplayName()) { + if ($spouse->canShowName()) { $married = WT_Date::Compare($censdate, $marrdate); $fulln =strip_tags($spouse->getFullName()); $spouselinks .= "<a href=\"#\" onclick=\"opener.insertRowToTable("; @@ -1145,7 +1145,7 @@ function print_pedigree_person_nav2($pid, $style=1, $count=0, $personcount="1", foreach ($children as $c=>$child) { if ($child) { $persons="Yes"; - if ($child->canDisplayName()) { + if ($child->canShowName()) { $fulln =strip_tags($child->getFullName()); $spouselinks .= "<li>"; $spouselinks .= "<a href=\"#\" onclick=\"opener.insertRowToTable("; diff --git a/modules_v3/batch_update/admin_batch_update.php b/modules_v3/batch_update/admin_batch_update.php index 8ad5b6d145..7032345d6d 100644 --- a/modules_v3/batch_update/admin_batch_update.php +++ b/modules_v3/batch_update/admin_batch_update.php @@ -135,9 +135,9 @@ class batch_update { $newrecord=$this->PLUGIN->updateRecord($this->xref, $record); if ($newrecord!=$record) { if ($newrecord) { - replace_gedrec($this->xref, WT_GED_ID, $newrecord, $this->PLUGIN->chan); + WT_GedcomRecord::getInstance($this->xref)->updateRecord($newrecord, $this->PLUGIN->chan); } else { - delete_gedrec($this->xref, WT_GED_ID); + WT_GedcomRecord::getInstance($this->xref)->deleteRecord(); } } } @@ -150,9 +150,9 @@ class batch_update { $newrecord=$this->PLUGIN->updateRecord($xref, $record); if ($newrecord!=$record) { if ($newrecord) { - replace_gedrec($xref, WT_GED_ID, $newrecord, $this->PLUGIN->chan); + WT_GedcomRecord::getInstance($this->xref)->updateRecord($newrecord, $this->PLUGIN->chan); } else { - delete_gedrec($xref, WT_GED_ID); + WT_GedcomRecord::getInstance($this->xref)->deleteRecord(); } } } @@ -162,7 +162,7 @@ class batch_update { case 'delete': $record=self::getLatestRecord($this->xref, $this->all_xrefs[$this->xref]); if ($this->PLUGIN->doesRecordNeedUpdate($this->xref, $record)) { - delete_gedrec($this->xref, WT_GED_ID); + WT_GedcomRecord::getInstance($this->xref)->deleteRecord(); } $this->xref=$this->findNextXref($this->xref); break; @@ -170,7 +170,7 @@ class batch_update { foreach ($this->all_xrefs as $xref=>$type) { $record=self::getLatestRecord($xref, $type); if ($this->PLUGIN->doesRecordNeedUpdate($xref, $record)) { - delete_gedrec($xref, WT_GED_ID); + WT_GedcomRecord::getInstance($this->xref)->deleteRecord(); } } $xref->xref=''; diff --git a/modules_v3/batch_update/plugins/death_y.php b/modules_v3/batch_update/plugins/death_y.php index d7afa25895..011c68497a 100644 --- a/modules_v3/batch_update/plugins/death_y.php +++ b/modules_v3/batch_update/plugins/death_y.php @@ -2,7 +2,7 @@ // Batch Update plugin for phpGedView - add missing 1 BIRT/DEAT Y // // webtrees: Web based Family History software -// Copyright (C) 2011 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2008 Greg Roach. All rights reserved. @@ -38,7 +38,7 @@ class death_y_bu_plugin extends base_plugin { } static function doesRecordNeedUpdate($xref, $gedrec) { - return !preg_match('/\n1 ('.WT_EVENTS_DEAT.')/', $gedrec) && WT_Person::getInstance($xref)->isDead(); + return !preg_match('/\n1 ('.WT_EVENTS_DEAT.')/', $gedrec) && WT_Individual::getInstance($xref)->isDead(); } static function updateRecord($xref, $gedrec) { diff --git a/modules_v3/charts/module.php b/modules_v3/charts/module.php index 989be576ef..0c26023730 100644 --- a/modules_v3/charts/module.php +++ b/modules_v3/charts/module.php @@ -72,11 +72,11 @@ class charts_WT_Module extends WT_Module implements WT_Module_Block { } $PEDIGREE_FULL_DETAILS = $show_full; - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); if (!$person) { $pid = $PEDIGREE_ROOT_ID; set_block_setting($block_id, 'pid', $pid); - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); } if ($type!='treenav' && $person) { @@ -223,7 +223,7 @@ class charts_WT_Module extends WT_Module implements WT_Module_Block { <input type="text" name="pid" id="pid" value="<?php echo $pid; ?>" size="5"> <?php echo print_findindi_link('pid'); - $root=WT_Person::getInstance($pid); + $root=WT_Individual::getInstance($pid); if ($root) { echo ' <span class="list_item">', $root->getFullName(), $root->format_first_major_fact(WT_EVENTS_BIRT, 1), '</span>'; } diff --git a/modules_v3/clippings/clippings_ctrl.php b/modules_v3/clippings/clippings_ctrl.php index 21f5d286c8..3fbe7d4517 100644 --- a/modules_v3/clippings/clippings_ctrl.php +++ b/modules_v3/clippings/clippings_ctrl.php @@ -130,19 +130,19 @@ class WT_Controller_Clippings { } } elseif ($this->type == 'indi') { if ($others == 'parents') { - foreach (WT_Person::getInstance($this->id)->getChildFamilies() as $family) { + foreach (WT_Individual::getInstance($this->id)->getChildFamilies() as $family) { $this->add_family_members($family); } } elseif ($others == 'ancestors') { - $this->add_ancestors_to_cart(WT_Person::getInstance($this->id), $this->level1); + $this->add_ancestors_to_cart(WT_Individual::getInstance($this->id), $this->level1); } elseif ($others == 'ancestorsfamilies') { - $this->add_ancestors_to_cart_families(WT_Person::getInstance($this->id), $this->level2); + $this->add_ancestors_to_cart_families(WT_Individual::getInstance($this->id), $this->level2); } elseif ($others == 'members') { - foreach (WT_Person::getInstance($this->id)->getSpouseFamilies() as $family) { + foreach (WT_Individual::getInstance($this->id)->getSpouseFamilies() as $family) { $this->add_family_members($family); } } elseif ($others == 'descendants') { - foreach (WT_Person::getInstance($this->id)->getSpouseFamilies() as $family) { + foreach (WT_Individual::getInstance($this->id)->getSpouseFamilies() as $family) { $this->add_clipping($family); $this->add_family_descendancy($family, $this->level3); } @@ -195,7 +195,7 @@ class WT_Controller_Clippings { foreach (array_keys($WT_SESSION->cart[WT_GED_ID]) as $xref) { $object=WT_GedcomRecord::getInstance($xref); if ($object) { // The object may have been deleted since we added it to the cart.... - list($record)=$object->privatizeGedcom($access_level); + $record = $object->privatizeGedcom($access_level); // Remove links to objects that aren't in the cart preg_match_all('/\n1 '.WT_REGEX_TAG.' @('.WT_REGEX_XREF.')@(\n[2-9].*)*/', $record, $matches, PREG_SET_ORDER); foreach ($matches as $match) { @@ -319,10 +319,10 @@ class WT_Controller_Clippings { function add_clipping($record) { global $WT_SESSION; - if ($record->canDisplayName()) { + if ($record->canShowName()) { $WT_SESSION->cart[WT_GED_ID][$record->getXref()]=true; // Add directly linked records - preg_match_all('/\n\d (?:OBJE|NOTE|SOUR|REPO) @('.WT_REGEX_XREF.')@/', $record->getGedcomRecord(), $matches); + preg_match_all('/\n\d (?:OBJE|NOTE|SOUR|REPO) @('.WT_REGEX_XREF.')@/', $record->getGedcom(), $matches); foreach ($matches[1] as $match) { $WT_SESSION->cart[WT_GED_ID][$match]=true; } diff --git a/modules_v3/clippings/module.php b/modules_v3/clippings/module.php index 32bdd50c8c..1a7be1444b 100644 --- a/modules_v3/clippings/module.php +++ b/modules_v3/clippings/module.php @@ -333,7 +333,7 @@ class clippings_WT_Module extends WT_Module implements WT_Module_Menu, WT_Module $submenu = new WT_Menu($this->getTitle(), 'module.php?mod=clippings&mod_action=index&ged='.WT_GEDURL, 'menu-clippingscart'); $menu->addSubmenu($submenu); } - if (!empty($controller->record) && $controller->record->canDisplayDetails()) { + if (!empty($controller->record) && $controller->record->canShow()) { $submenu = new WT_Menu(WT_I18N::translate('Add to clippings cart'), 'module.php?mod=clippings&mod_action=index&action=add&id='.$controller->record->getXref(), 'menu-clippingsadd'); $menu->addSubmenu($submenu); } @@ -393,7 +393,7 @@ class clippings_WT_Module extends WT_Module implements WT_Module_Menu, WT_Module if ($ret) return $this->askAddOptions($record); } } elseif (!empty($add1)) { - $record = WT_Person::getInstance($add1); + $record = WT_Individual::getInstance($add1); if ($record) { $clip_ctrl->id=$record->getXref(); $clip_ctrl->type=strtolower($record::RECORD_TYPE); @@ -456,7 +456,7 @@ class clippings_WT_Module extends WT_Module implements WT_Module_Menu, WT_Module $out .=$record->getSexImage(); } $out .= ' '.$record->getFullName().' '; - if ($record::RECORD_TYPE == 'INDI' && $record->canDisplayDetails()) { + if ($record::RECORD_TYPE == 'INDI' && $record->canShow()) { $out .= ' ('.$record->getLifeSpan().')'; } $out .= '</a>'; @@ -477,7 +477,7 @@ class clippings_WT_Module extends WT_Module implements WT_Module_Menu, WT_Module WT_I18N::translate('Download Now'). '</a>'; } - $record=WT_Person::getInstance($pid); + $record=WT_Individual::getInstance($pid); if ($record && !array_key_exists($record->getXref(), $WT_SESSION->cart[WT_GED_ID])) { $out .= '<br><a href="module.php?mod='.$this->getName().'&mod_action=ajax&sb_action=clippings&add='.$pid.'&pid='.$pid.'" class="add_cart"><i class="icon-clippings"></i> '.WT_I18N::translate('Add %s to cart', $record->getFullName()).'</a>'; } diff --git a/modules_v3/descendancy/module.php b/modules_v3/descendancy/module.php index e9e7a6abdf..7eeef47220 100644 --- a/modules_v3/descendancy/module.php +++ b/modules_v3/descendancy/module.php @@ -132,7 +132,7 @@ class descendancy_WT_Module extends WT_Module implements WT_Module_Sidebar { '</div>'; } - public function getPersonLi(WT_Person $person, $generations=0) { + public function getPersonLi(WT_Individual $person, $generations=0) { $out = '<li id="sb_desc_'.$person->getXref().'" class="sb_desc_indi_li"><a href="module.php?mod='.$this->getName().'&mod_action=ajax&sb_action=descendancy&pid='.$person->getXref().'" title="'.$person->getXref().'" class="sb_desc_indi">'; if ($generations>0) { $out .= '<i class="icon-minus plusminus"></i>'; @@ -140,7 +140,7 @@ class descendancy_WT_Module extends WT_Module implements WT_Module_Sidebar { $out .= '<i class="icon-plus plusminus"></i>'; } $out .= $person->getSexImage().' '.$person->getFullName().' '; - if ($person->canDisplayDetails()) { + if ($person->canShow()) { $out .= ' ('.$person->getLifeSpan().')'; } $out .= '</a> <a href="'.$person->getHtmlUrl().'" class="icon-button_indi"></a>'; @@ -158,7 +158,7 @@ class descendancy_WT_Module extends WT_Module implements WT_Module_Sidebar { return $out; } - public function getFamilyLi(WT_Family $family, WT_Person $person, $generations=0) { + public function getFamilyLi(WT_Family $family, WT_Individual $person, $generations=0) { $out = '<li id="sb_desc_'.$family->getXref().'" class="sb_desc_indi_li"><a href="module.php?mod='.$this->getName().'&mod_action=ajax&sb_action=descendancy&famid='.$family->getXref().'" title="'.$family->getXref().'" class="sb_desc_indi">'; $out .= '<i class="icon-minus plusminus"></i>'; $out .= $person->getSexImage().$person->getFullName(); @@ -181,19 +181,19 @@ class descendancy_WT_Module extends WT_Module implements WT_Module_Sidebar { public function search($query) { if (strlen($query)<2) return ''; $rows=WT_DB::prepare( - "SELECT ? AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`, `##name`". " WHERE (i_id LIKE ? OR n_sort LIKE ?)". " AND i_id=n_id AND i_file=n_file AND i_file=?". " ORDER BY n_sort" ) - ->execute(array('INDI', "%{$query}%", "%{$query}%", WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->execute(array("%{$query}%", "%{$query}%", WT_GED_ID)) + ->fetchAll(); $out = ''; foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if ($person->canDisplayName()) { + $person=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($person->canShowName()) { $out .= $this->getPersonLi($person); } } @@ -206,8 +206,8 @@ class descendancy_WT_Module extends WT_Module implements WT_Module_Sidebar { public function loadSpouses($pid, $generations=0) { $out = ''; - $person = WT_Person::getInstance($pid); - if ($person && $person->canDisplayDetails()) { + $person = WT_Individual::getInstance($pid); + if ($person && $person->canShow()) { foreach($person->getSpouseFamilies() as $family) { $spouse = $family->getSpouse($person); if ($spouse) { @@ -229,7 +229,7 @@ class descendancy_WT_Module extends WT_Module implements WT_Module_Sidebar { public function loadChildren($famid, $generations=0) { $out = ''; $family = WT_Family::getInstance($famid); - if ($family->canDisplayDetails()) { + if ($family->canShow()) { $children = $family->getChildren(); if (count($children)>0) { foreach($children as $child) { diff --git a/modules_v3/extra_info/module.php b/modules_v3/extra_info/module.php index 1d65ef1eb4..581c111b3c 100644 --- a/modules_v3/extra_info/module.php +++ b/modules_v3/extra_info/module.php @@ -2,7 +2,7 @@ // A sidebar to show extra/non-genealogical information about an individual
//
// webtrees: Web based Family History software
-// Copyright (C) 2012 webtrees development team.
+// Copyright (C) 2013 webtrees development team.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -49,16 +49,21 @@ class extra_info_WT_Module extends WT_Module implements WT_Module_Sidebar { // Implement WT_Module_Sidebar
public function getSidebarContent() {
global $SHOW_COUNTER, $controller;
+
+ $indifacts = array();
+ // The individual's own facts
+ foreach ($controller->record->getFacts() as $fact) {
+ if (self::showFact($fact) && $fact->canShow()) {
+ $indifacts[] = $fact;
+ }
+ }
ob_start();
- $indifacts = $controller->getIndiFacts();
- if (count($indifacts)==0) {
+ if (!$indifacts) {
echo WT_I18N::translate('There are no Facts for this individual.');
} else {
foreach ($indifacts as $fact) {
- if (in_array($fact->getTag(), WT_Gedcom_Tag::getReferenceFacts())) {
- print_fact($fact, $controller->record);
- }
+ print_fact($fact, $controller->record);
}
}
echo '<div id="hitcounter">';
@@ -75,4 +80,21 @@ class extra_info_WT_Module extends WT_Module implements WT_Module_Sidebar { public function getSidebarAjaxContent() {
return '';
}
+
+ // Does this module display a particular fact
+ public static function showFact(WT_Fact $fact) {
+ switch ($fact->getTag()) {
+ case 'AFN':
+ case 'CHAN':
+ case 'IDNO':
+ case 'REFN':
+ case 'RFN':
+ case 'RIN':
+ case 'SSN':
+ case '_UID':
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/modules_v3/families/module.php b/modules_v3/families/module.php index 3a15b93269..4794c9aa19 100644 --- a/modules_v3/families/module.php +++ b/modules_v3/families/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -187,9 +187,9 @@ class families_WT_Module extends WT_Module implements WT_Module_Sidebar { $families=WT_Query_Name::families($surname, $alpha, '', true, WT_GED_ID); $out = '<ul>'; foreach ($families as $family) { - if ($family->canDisplayName()) { + if ($family->canShowName()) { $out .= '<li><a href="'.$family->getHtmlUrl().'">'.$family->getFullName().' '; - if ($family->canDisplayDetails()) { + if ($family->canShow()) { $marriage_year=$family->getMarriageYear(); if ($marriage_year) { $out.=' ('.$marriage_year.')'; @@ -209,17 +209,17 @@ class families_WT_Module extends WT_Module implements WT_Module_Sidebar { //-- search for INDI names $rows=WT_DB::prepare( - "SELECT ? AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT i_id AS xref". " FROM `##individuals`, `##name`". " WHERE (i_id LIKE ? OR n_sort LIKE ?)". " AND i_id=n_id AND i_file=n_file AND i_file=?". " ORDER BY n_sort" ) - ->execute(array('INDI', "%{$query}%", "%{$query}%", WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->execute(array("%{$query}%", "%{$query}%", WT_GED_ID)) + ->fetchAll(); $ids = array(); foreach ($rows as $row) { - $ids[] = $row['xref']; + $ids[] = $row->xref; } $vars=array('FAM'); @@ -235,16 +235,16 @@ class families_WT_Module extends WT_Module implements WT_Module_Sidebar { } $vars[]=WT_GED_ID; - $rows=WT_DB::prepare("SELECT ? AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec FROM `##families` WHERE {$where} AND f_file=?") + $rows=WT_DB::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(PDO::FETCH_ASSOC); + ->fetchAll(); $out = '<ul>'; foreach ($rows as $row) { - $family=WT_Family::getInstance($row); - if ($family->canDisplayName()) { + $family=WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($family->canShowName()) { $out .= '<li><a href="'.$family->getHtmlUrl().'">'.$family->getFullName().' '; - if ($family->canDisplayDetails()) { + if ($family->canShow()) { $marriage_year=$family->getMarriageYear(); if ($marriage_year) { $out.=' ('.$marriage_year.')'; diff --git a/modules_v3/family_nav/module.php b/modules_v3/family_nav/module.php index 2e383ea714..ed8256cae8 100644 --- a/modules_v3/family_nav/module.php +++ b/modules_v3/family_nav/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -293,7 +293,7 @@ class family_nav_WT_Module extends WT_Module implements WT_Module_Sidebar { $parentlinks = ''; $step_parentlinks = ''; - if ($person->canDisplayName() && !$SEARCH_SPIDER) { + if ($person->canShowName() && !$SEARCH_SPIDER) { //-- draw a box for the family flyout $parentlinks .= '<div class="flyout4"><b>' . WT_I18N::translate('Parents') . '</b></div>'; $step_parentlinks .= '<div class="flyout4"><b>' . WT_I18N::translate('Parents') . '</b></div>'; diff --git a/modules_v3/faq/module.php b/modules_v3/faq/module.php index 300808366a..7b945266cd 100644 --- a/modules_v3/faq/module.php +++ b/modules_v3/faq/module.php @@ -314,8 +314,7 @@ class faq_WT_Module extends WT_Module implements WT_Module_Menu, WT_Module_Block echo '<a href="#body">', WT_I18N::translate('back to top'), '</a>'; echo '</div>'; echo '</div>'; - // PHP5.3 echo '<div class="faq_body">', substr($faqbody, 0, 1)=='<' ? $faqbody : nl2br($faqbody, false), '</div>'; - echo '<div class="faq_body">', substr($faqbody, 0, 1)=='<' ? $faqbody : nl2br($faqbody), '</div>'; + echo '<div class="faq_body">', substr($faqbody, 0, 1)=='<' ? $faqbody : nl2br($faqbody, false), '</div>'; echo '<hr>'; } } diff --git a/modules_v3/gedcom_favorites/module.php b/modules_v3/gedcom_favorites/module.php index d65769338e..e4f382d589 100644 --- a/modules_v3/gedcom_favorites/module.php +++ b/modules_v3/gedcom_favorites/module.php @@ -64,7 +64,7 @@ class gedcom_favorites_WT_Module extends WT_Module implements WT_Module_Block { if ($gid) { $record=WT_GedcomRecord::getInstance($gid); - if ($record && $record->canDisplayDetails()) { + if ($record && $record->canShow()) { self::addFavorite(array( 'user_id' =>$ctype=='user' ? WT_USER_ID : null, 'gedcom_id'=>WT_GED_ID, @@ -131,8 +131,8 @@ class gedcom_favorites_WT_Module extends WT_Module implements WT_Module_Block { $content .= '</div>'; } else { $record=WT_GedcomRecord::getInstance($favorite['gid']); - if ($record && $record->canDisplayDetails()) { - if ($record instanceof WT_Person) { + if ($record && $record->canShow()) { + if ($record instanceof WT_Individual) { $content .= '<div id="box'.$favorite["gid"].'.0" class="person_box action_header'; switch($record->getsex()) { case 'M': diff --git a/modules_v3/googlemap/googlemap.php b/modules_v3/googlemap/googlemap.php index 3861c21ebf..27f26bd708 100644 --- a/modules_v3/googlemap/googlemap.php +++ b/modules_v3/googlemap/googlemap.php @@ -154,7 +154,7 @@ function setup_map() { <?php } -function build_indiv_map($indifacts, $famids) { +function build_indiv_map(WT_Individual $indi, $indifacts, $famids) { global $controller, $GOOGLEMAP_MAX_ZOOM, $GOOGLEMAP_YSIZE, $GM_DEFAULT_TOP_VALUE; // Create the markers list array @@ -165,8 +165,8 @@ function build_indiv_map($indifacts, $famids) { $i = 0; foreach ($indifacts as $key => $value) { $fact = $value->getTag(); - $fact_data=$value->getDetail(); - $factrec = $value->getGedComRecord(); + $fact_data=$value->getValue(); + $factrec = $value->getGedcom(); $placerec = null; if ($value->getPlace()!=null) { @@ -181,9 +181,13 @@ function build_indiv_map($indifacts, $famids) { if (!empty($placerec)) { $ctla = preg_match("/\d LATI (.*)/", $placerec, $match1); $ctlo = preg_match("/\d LONG (.*)/", $placerec, $match2); - $spouse = $value->getSpouse(); + if ($value->getParent() instanceof WT_Family) { + $spouse = $value->getParent()->getSpouse($indi); + } else { + $spouse = null; + } if ($spouse) { - $useThisItem = $spouse->canDisplayDetails(); + $useThisItem = $spouse->canShow(); } else { $useThisItem = true; } @@ -265,13 +269,13 @@ function build_indiv_map($indifacts, $famids) { if ($famrec) { $num = preg_match_all("/1\s*CHIL\s*@(.*)@/", $famrec, $smatch, PREG_SET_ORDER); for ($j=0; $j<$num; $j++) { - $person=WT_Person::getInstance($smatch[$j][1]); - if ($person->canDisplayDetails()) { + $person=WT_Individual::getInstance($smatch[$j][1]); + if ($person->canShow()) { $srec = find_person_record($smatch[$j][1], WT_GED_ID); $birthrec = ''; $placerec = ''; - foreach ($person->getAllFactsByType('BIRT') as $sEvent) { - $birthrec = $sEvent->getGedcomRecord(); + foreach ($person->getFacts('BIRT') as $sEvent) { + $birthrec = $sEvent->getGedcom(); $placerec = get_sub_record(2, '2 PLAC', $birthrec); if (!empty($placerec)) { $ctd = preg_match("/\d DATE (.*)/", $birthrec, $matchd); @@ -424,7 +428,7 @@ function build_indiv_map($indifacts, $famids) { echo '<span class="field">', $marker['info'], '</span><br>'; } if (!empty($marker['name'])) { - $person=WT_Person::getInstance($marker['name']); + $person=WT_Individual::getInstance($marker['name']); if ($person) { echo '<a href="', $person->getHtmlUrl(), '">', $person->getFullName(), '</a>'; } diff --git a/modules_v3/googlemap/module.php b/modules_v3/googlemap/module.php index 7ef37e4fd7..e727be8565 100644 --- a/modules_v3/googlemap/module.php +++ b/modules_v3/googlemap/module.php @@ -144,8 +144,22 @@ class googlemap_WT_Module extends WT_Module implements WT_Module_Config, WT_Modu foreach ($families as $family) { $famids[] = $family->getXref(); } - $controller->record->add_family_facts(false); - build_indiv_map($controller->record->getIndiFacts(), $famids); + $indifacts = array(); + foreach ($controller->record->getFacts() as $fact) { + if ($fact->canShow()) { + $indifacts[] = $fact; + } + } + foreach ($controller->record->getSpouseFamilies() as $family) { + foreach ($family->getFacts() as $fact) { + if ($fact->canShow()) { + $indifacts[] = $fact; + } + } + } + sort_facts($indifacts); + + build_indiv_map($controller->record, $indifacts, $famids); echo '</div>'; echo '</td>'; echo '</tr></table>'; @@ -739,7 +753,7 @@ class googlemap_WT_Module extends WT_Module implements WT_Module_Config, WT_Modu for ($i=0; $i<($controller->treesize); $i++) { // -- check to see if we have moved to the next generation if ($i+1 >= pow(2, $curgen)) {$curgen++;} - $person = WT_Person::getInstance($controller->treeid[$i]); + $person = WT_Individual::getInstance($controller->treeid[$i]); if (!empty($person)) { $name = $person->getFullName(); if ($name == WT_I18N::translate('Private')) $priv++; @@ -1238,7 +1252,7 @@ class googlemap_WT_Module extends WT_Module implements WT_Module_Config, WT_Modu for ($i=0; $i<($controller->treesize); $i++) { // moved up to grab the sex of the individuals - $person = WT_Person::getInstance($controller->treeid[$i]); + $person = WT_Individual::getInstance($controller->treeid[$i]); if ($person) { $name = $person->getFullName(); diff --git a/modules_v3/googlemap/wt_v3_googlemap.js.php b/modules_v3/googlemap/wt_v3_googlemap.js.php index ed3295fd36..1a6baf121f 100644 --- a/modules_v3/googlemap/wt_v3_googlemap.js.php +++ b/modules_v3/googlemap/wt_v3_googlemap.js.php @@ -438,10 +438,10 @@ $STREETVIEW=get_module_setting('googlemap', 'GM_USE_STREETVIEW'); // create thumbnail images of highlighted images if (!empty($pid)) { - $this_person = WT_Person::getInstance($pid); + $this_person = WT_Individual::getInstance($pid); } if (!empty($gmark['name'])) { - $person = WT_Person::getInstance($gmark['name']); + $person = WT_Individual::getInstance($gmark['name']); } else { $person = null; } @@ -482,7 +482,7 @@ $STREETVIEW=get_module_setting('googlemap', 'GM_USE_STREETVIEW'); "<?php echo $gmark['lng']; ?>", "<?php if (!empty($gmark['date'])) { $date=new WT_Date($gmark['date']); echo addslashes($date->Display(true)); } else { echo WT_I18N::translate('Date not known'); } ?>", "<?php if (!empty($gmark['info'])) { echo addslashes($gmark['info']); } else { echo NULL; } ?>", - "<?php if (!empty($gmark['name'])) { $person=WT_Person::getInstance($gmark['name']); if ($person) { echo '<a href=\"', $person->getHtmlUrl(), '\">', addslashes($person->getFullName()), '<\/a>'; } } ?>", + "<?php if (!empty($gmark['name'])) { $person=WT_Individual::getInstance($gmark['name']); if ($person) { echo '<a href=\"', $person->getHtmlUrl(), '\">', addslashes($person->getFullName()), '<\/a>'; } } ?>", "<?php echo addslashes(print_fact_place_map($gmark['placerec'])); ?>", "<?php echo $gmark['index'].''; ?>", "<?php echo $gmark['tabindex'].''; ?>", @@ -492,7 +492,7 @@ $STREETVIEW=get_module_setting('googlemap', 'GM_USE_STREETVIEW'); "<?php echo strip_tags(preg_replace('/\"/', '\\\"', print_fact_place_map($gmark['placerec']))); ?>", // Element 11. persons Name - "<?php if (!empty($gmark['name'])) { $person=WT_Person::getInstance($gmark['name']); if ($person) { echo addslashes($person->getFullName()); } } ?>", + "<?php if (!empty($gmark['name'])) { $person=WT_Individual::getInstance($gmark['name']); if ($person) { echo addslashes($person->getFullName()); } } ?>", // Element 12. Other people's Highlighted image. "<?php if (!empty($gmark['name'])) { echo $image2; } else { echo ''; } ?>", diff --git a/modules_v3/individuals/module.php b/modules_v3/individuals/module.php index 599b354b17..20f9677054 100644 --- a/modules_v3/individuals/module.php +++ b/modules_v3/individuals/module.php @@ -186,9 +186,9 @@ class individuals_WT_Module extends WT_Module implements WT_Module_Sidebar { $indis=WT_Query_Name::individuals($surname, $alpha, '', true, false, WT_GED_ID); $out = '<ul>'; foreach ($indis as $person) { - if ($person->canDisplayName()) { + if ($person->canShowName()) { $out .= '<li><a href="'.$person->getHtmlUrl().'">'.$person->getSexImage().' '.$person->getFullName().' '; - if ($person->canDisplayDetails()) { + if ($person->canShow()) { $bd = $person->getLifeSpan(); if (!empty($bd)) { $out .= ' ('.$bd.')'; @@ -207,22 +207,22 @@ class individuals_WT_Module extends WT_Module implements WT_Module_Sidebar { } $rows= WT_DB::prepare( - "SELECT ? AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`, `##name`". " WHERE (i_id LIKE ? OR n_sort LIKE ?)". " AND i_id=n_id AND i_file=n_file AND i_file=?". " ORDER BY n_sort COLLATE '".WT_I18N::$collation."'". " LIMIT 50" ) - ->execute(array('INDI', "%{$query}%", "%{$query}%", WT_GED_ID)) - ->fetchAll(PDO::FETCH_ASSOC); + ->execute(array("%{$query}%", "%{$query}%", WT_GED_ID)) + ->fetchAll(); $out = '<ul>'; foreach ($rows as $row) { - $person=WT_Person::getInstance($row); - if ($person->canDisplayName()) { + $person = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); + if ($person->canShowName()) { $out .= '<li><a href="'.$person->getHtmlUrl().'">'.$person->getSexImage().' '.$person->getFullName().' '; - if ($person->canDisplayDetails()) { + if ($person->canShow()) { $bd = $person->getLifeSpan(); if (!empty($bd)) $out .= ' ('.$bd.')'; } diff --git a/modules_v3/lightbox/css/album_page.css b/modules_v3/lightbox/css/album_page.css index 6619302f2c..46f9d8dc37 100644 --- a/modules_v3/lightbox/css/album_page.css +++ b/modules_v3/lightbox/css/album_page.css @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * @version $Id$ + * $Id$ */ /* lightbox_plus.css version 3.00 29/06/2007 */ @@ -35,20 +35,18 @@ .pic{border:0; border-color:#fff; border-style:solid; padding:0;} .thumbcontainer{display:block; width:100%;} #lb_icons{text-align:justify;} -#thumblist_1,#thumblist_2,#thumblist_3,#thumblist_4,#thumblist_5,#thumblist_1a,#thumblist_2a,#thumblist_3a,#thumblist_4a,#thumblist_5a{display:block; float:left; list-style-type:none;} -#thumblist_1 li,#thumblist_2 li,#thumblist_3 li,#thumblist_4 li,#thumblist_5 li,#thumblist_1a li,#thumblist_2a li,#thumblist_3a li,#thumblist_4a li,#thumblist_5a li{display:block; float:left; list-style-type:none; margin-right:5px; padding-bottom:0; padding-left:4px; padding-right:4px;} +.thumblist {display:block; float:left; list-style-type:none;} +.thumblist li {display:block; float:left; list-style-type:none; margin-right:5px; padding-bottom:0; padding-left:4px; padding-right:4px;} li.li_norm{border:2px solid transparent; height:112px;} li.li_new{border:2px solid #00f;} li.li_old{border:2px solid red;} -#thumblist_1 a img,#thumblist_2 a img,#thumblist_3 a img,#thumblist_4 a img,#thumblist_5 a img,#thumblist_1a a img,#thumblist_2a a img,#thumblist_3a a img,#thumblist_4a a img,#thumblist_5a a img{border:1px; border-style:none; padding:1px;max-height:78px;max-width:100px;height:auto;width:auto;} -#thumblist_1 a:hover img,#thumblist_2 a:hover img,#thumblist_3 a:hover img,#thumblist_4 a:hover img,#thumblist_5 a:hover img,#thumblist_1a a:hover img,#thumblist_2a a:hover img,#thumblist_3a a:hover img,#thumblist_4a a:hover img,#thumblist_5a a:hover img{background-color:#BDB071; border:0; border-style:none; padding:1px;} +.thumblist a img {border:1px; border-style:none; padding:1px;max-height:78px;max-width:100px;height:auto;width:auto;} +.thumblist a:hover img {background-color:#BDB071; border:0; border-style:none; padding:1px;} .clearlist:after{clear:both; content:"."; display:block; height:0; visibility:hidden;} #lightbox_content span {padding:10px;} #lightbox_content span img {vertical-align:top;} -/* Hides from IE-mac \ */ -* html .clearfix{height:1%;} -#clearlist{display:block;} +#clearlist {display:block;} /* RTL changes */ -html[dir='rtl'] #thumblist_1,html[dir='rtl'] #thumblist_2,html[dir='rtl'] #thumblist_3,html[dir='rtl'] #thumblist_4,html[dir='rtl'] #thumblist_5,html[dir='rtl'] #thumblist_1a,html[dir='rtl'] #thumblist_2a,html[dir='rtl'] #thumblist_3a,html[dir='rtl'] #thumblist_4a,html[dir='rtl'] #thumblist_5a{float:right;} -html[dir='rtl'] #thumblist_1 li,html[dir='rtl'] #thumblist_2 li,html[dir='rtl'] #thumblist_3 li,html[dir='rtl'] #thumblist_4 li,html[dir='rtl'] #thumblist_5 li,html[dir='rtl'] #thumblist_1a li,html[dir='rtl'] #thumblist_2a li,html[dir='rtl'] #thumblist_3a li,html[dir='rtl'] #thumblist_4a li,html[dir='rtl'] #thumblist_5a li{float:right; margin-left:5px;} +html[dir='rtl'] #thumblist {float:right;} +html[dir='rtl'] #thumblist li {float:right; margin-left:5px;} diff --git a/modules_v3/lightbox/functions/lightbox_print_media.php b/modules_v3/lightbox/functions/lightbox_print_media.php deleted file mode 100644 index 970eb373dd..0000000000 --- a/modules_v3/lightbox/functions/lightbox_print_media.php +++ /dev/null @@ -1,460 +0,0 @@ -<?php -// Lightbox Album module for webtrees -// -// Display media Items using Lightbox -// -// webtrees: Web based Family History software -// Copyright (C) 2013 webtrees development team. -// -// Derived from PhpGedView -// Copyright (C) 2007 to 2009 PGV Development Team. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// $Id$ - -if (!defined('WT_WEBTREES')) { - header('HTTP/1.0 403 Forbidden'); - exit; -} - -/** - * ----------------------------------------------------------------------------- - * Print the links to media objects - * @param string $pid The the xref id of the object to find media records related to - * @param int $level The level of media object to find - * @param boolean $related Whether or not to grab media from related records - */ -function lightbox_print_media($pid, $level=1, $related=false, $kind=1, $noedit=false) { - global $GEDCOM; - global $res, $rowm; - global $rownum, $rownum1, $rownum2, $rownum3, $rownum4; - - $ged_id=get_id_from_gedcom($GEDCOM); - $person = WT_Person::getInstance($pid); - $ctf=0; - if ($level>0) { - $regexp = '/\n' . $level . ' OBJE @(.*)@/'; - } else { - $regexp = '/\n\d OBJE @(.*)@/'; - } - //-- find all of the related ids - $ids = array($person->getXref()); - if ($related) { - foreach ($person->getSpouseFamilies() as $family) { - $ids[] = $family->getXref(); - $ctf += preg_match_all($regexp, $family->getGedcomRecord(), $match, PREG_SET_ORDER); - } - } - //-- If they exist, get a list of the sorted current objects in the indi gedcom record - (1 _WT_OBJE_SORT @xxx@ .... etc) ---------- - $sort_current_objes = array(); - $sort_ct = preg_match_all('/\n1 _WT_OBJE_SORT @(.*)@/', $person->getGedcomRecord(), $sort_match, PREG_SET_ORDER); - for ($i=0; $i<$sort_ct; $i++) { - if (!isset($sort_current_objes[$sort_match[$i][1]])) { - $sort_current_objes[$sort_match[$i][1]] = 1; - } else { - $sort_current_objes[$sort_match[$i][1]]++; - } - $sort_obje_links[$sort_match[$i][1]][] = $sort_match[$i][0]; - } - - // create ORDER BY list from Gedcom sorted records list --------------------------- - $orderbylist = 'ORDER BY '; // initialize - foreach ($sort_match as $id) { - $orderbylist .= "m_id='$id[1]' DESC, "; - } - $orderbylist = rtrim($orderbylist, ', '); - - //-- get a list of the current objects in the record - $current_objes = array(); - $ct = preg_match_all($regexp, $person->getGedcomRecord(), $match, PREG_SET_ORDER); - for ($i=0; $i<$ct; $i++) { - if (!isset($current_objes[$match[$i][1]])) { - $current_objes[$match[$i][1]] = 1; - } else { - $current_objes[$match[$i][1]]++; - } - $obje_links[$match[$i][1]][] = $match[$i][0]; - } - - $media_found = false; - - // Get the related media items - $sqlmm = - "SELECT DISTINCT m_id, m_ext, m_filename, m_titl, m_file, m_gedcom, l_from AS pid" . - " FROM `##media`" . - " JOIN `##link` ON (m_id=l_to AND m_file=l_file AND l_type='OBJE')" . - " WHERE m_file=? AND l_from IN ("; - $i=0; - $vars=array(WT_GED_ID); - foreach ($ids as $media_id) { - if ($i>0) $sqlmm .= ", "; - $sqlmm .= "?"; - $vars[]=$media_id; - $i++; - } - $sqlmm .= ')'; - - // Set type of media from call in album - switch ($kind) { - case 1: - $tt=WT_I18N::translate('Photo'); - $sqlmm.="AND (m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ?)"; - $vars[]='%TYPE photo%'; - $vars[]='%TYPE map%'; - $vars[]='%TYPE painting%'; - $vars[]='%TYPE tombstone%'; - break; - case 2: - $tt=WT_I18N::translate('Document'); - $sqlmm.="AND (m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ?)"; - $vars[]='%TYPE card%'; - $vars[]='%TYPE certificate%'; - $vars[]='%TYPE document%'; - $vars[]='%TYPE magazine%'; - $vars[]='%TYPE manuscript%'; - $vars[]='%TYPE newspaper%'; - break; - case 3: - $tt=WT_I18N::translate('Census'); - $sqlmm.="AND (m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ?)"; - $vars[]='%TYPE electronic%'; - $vars[]='%TYPE fiche%'; - $vars[]='%TYPE film%'; - break; - case 4: - $tt=WT_I18N::translate('Other'); - $sqlmm.="AND (m_gedcom NOT LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ? OR m_gedcom LIKE ?)"; - $vars[]='%TYPE %'; - $vars[]='%TYPE coat%'; - $vars[]='%TYPE book%'; - $vars[]='%TYPE audio%'; - $vars[]='%TYPE video%'; - $vars[]='%TYPE other%'; - break; - case 5: - default: - $tt = WT_I18N::translate('Not in DB'); - break; - } - - if ($sort_ct>0) { - $sqlmm .= $orderbylist; - } - - $rows=WT_DB::prepare($sqlmm)->execute($vars)->fetchAll(PDO::FETCH_ASSOC); - - $foundObjs = array(); - $numm = count($rows); - - // Begin to Layout the Album Media Rows - if ($numm>0 || $kind==5) { - if ($kind!=5) { - echo '<table width="100%" class="facts_table"><tr>'; - echo '<td width="100" align="center" class="descriptionbox" style="vertical-align:middle;">'; - echo '<b>', $tt, '</b>'; - echo '</td>'; - echo '<td class="facts_value" >'; - echo '<table class="facts_table" width="100%" cellpadding="0"><tr><td >'; - echo '<div id="thumbcontainer', $kind, '">'; - echo '<ul class="section" id="thumblist_', $kind, '">'; - } - // ================================================== - // Start pulling media items into thumbcontainer div ============================== - foreach ($rows as $rowm) { - if (isset($foundObjs[$rowm['m_id']])) { - if (isset($current_objes[$rowm['m_id']])) { - $current_objes[$rowm['m_id']]--; - } - continue; - } - $rows=array(); - - //-- if there is a change to this media item then get the - //-- updated media item and show it - if (($newrec=find_updated_record($rowm['m_id'], $ged_id)) && $kind!=5 ) { - $row = array(); - $row['m_id'] = $rowm['m_id']; - $row['m_file'] = $ged_id; - $row['m_filename'] = get_gedcom_value('FILE', 1, $newrec); - $row['m_titl'] = get_gedcom_value('TITL', 1, $newrec); - if (empty($row['m_titl'])) $row['m_titl'] = get_gedcom_value('FILE:TITL', 1, $newrec); - $row['m_gedcom'] = $newrec; - $et = preg_match('/\.(\w+)$/', $row['m_filename'], $ematch); - $ext = ''; - if ($et>0) $ext = $ematch[1]; - $row['m_ext'] = $ext; - $row['pid'] = $pid; - $rows['new'] = $row; - $rows['old'] = $rowm; - } else { - if (!isset($current_objes[$rowm['m_id']]) && ($rowm['pid']==$pid)) { - $rows['old'] = $rowm; - } else { - $rows['normal'] = $rowm; - if (isset($current_objes[$rowm['m_id']])) { - $current_objes[$rowm['m_id']]--; - } - } - } - foreach ($rows as $rtype => $rowm) { - if ($kind!=5) { - $res = lightbox_print_media_row($rtype, $rowm, $pid); - } - $media_found = $media_found || $res; - $foundObjs[$rowm['m_id']]=true; - } - } - - // TODO the following logic assumes that each media file is linked only - // once from each individual. But if you are baptised and buried in - // the same church, and have a photo of it in both events, it fails. - - // ===================================================================================== - //-- Objects are removed from the $current_objes list as they are printed. - //-- Any “Extra” objects left in the list are new objects recently added to the gedcom - //-- but not yet accepted into the database. - //-- We will print them too, and put any “Extra Items not in DB” into a new Row. - - // Compare Items count in Database versus Item count in GEDCOM - if ($kind==5 && $ct+$ctf!=$numm) { - // If any items are left in $current_objes list for this individual, put them into $kind 5 (“Not in DB”) row - echo '<table width="100%" class="facts_table"><tr>'; - echo '<td width="100" align="center" class="descriptionbox" style="vertical-align:middle;">'; - echo '<b>', $tt, '</b>'; - echo '</td>'; - echo '<td class="facts_value" >'; - echo '<table class="facts_table" width="100%" cellpadding="0"><tr><td >'; - echo '<div id="thumbcontainer', $kind, '">'; - echo '<ul class="section" id="thumblist_', $kind, '">'; - foreach ($current_objes as $media_id=>$value) { - while ($value>0) { - $objSubrec = array_pop($obje_links[$media_id]); - $row = array(); - $newrec = find_gedcom_record($media_id, $ged_id, true); - $row['m_id'] = $media_id; - $row['m_file']=$ged_id; - $row['m_filename'] = get_gedcom_value("FILE", 1, $newrec); - $row['m_titl'] = get_gedcom_value("TITL", 1, $newrec); - if (empty($row['m_titl'])) $row['m_titl'] = get_gedcom_value("FILE:TITL", 1, $newrec); - $row['m_gedcom'] = $newrec; - $et = preg_match("/(\.\w+)$/", $row['m_file'], $ematch); - $ext = ""; - if ($et>0) $ext = substr(trim($ematch[1]), 1); - $row['m_ext'] = $ext; - $row['pid'] = $pid; - $res = lightbox_print_media_row('new', $row, $pid); - $media_found = $media_found || $res; - $value--; - } - } - } - // No “Extra” Media Items ============================ - if ($kind==5 && $ct+$ctf==$numm) { - // “Extra” Media Item in GEDCOM but NOT in DB ======== - } else if ($kind==5 && $ct+$ctf!=$numm) { - echo '</ul>'; - echo '</div>'; - echo '<div class="clearlist">'; - echo '</div>'; - echo '</td></tr></table>'; - echo '</td>'; - echo '</tr>'; - echo '</table>'; - // Media Item in GEDCOM & in DB ====================== - } else { - echo '</ul>'; - echo '</div>'; - echo '<div class="clearlist">'; - echo '</div>'; - echo '</td></tr></table>'; - if ($kind==3 && $numm > 0) { - echo '<font size="1">'; - echo 'UK census images have been obtained from The National Archives, the custodian of the original records, and appear here with their approval on the condition that no commercial use is made of them without permission. Requests for commercial publication of these or other UK census images appearing on this website should be directed to: Image Library, The National Archives, Kew, Surrey, TW9 4DU, United Kingdom.'; - echo '</font>'; - } - echo '</td>'; - echo '</tr>'; - echo '</table>'; - } - } - if ($media_found) return $is_media='YES'; - else return $is_media='NO'; -} - -/** - * print a media row in a table - * @param string $rtype whether this is a 'new', 'old', or 'normal' media row... this is used to determine if the rows should be printed with an outline color - * @param array $rowm An array with the details about this media item - * @param string $pid The record id this media item was attached to - */ -function lightbox_print_media_row($rtype, $rowm, $pid) { - - global $sort_i, $notes; - - $media=WT_Media::getInstance($rowm['m_id']); - - if ($media && !$media->canDisplayDetails()) { - // This media object is private; - return false; - } - - if (!canDisplayFact($rowm['m_id'], $rowm['m_file'], $rowm['m_gedcom'])) { - // The link to this media object is private. e.g. 1 OBJE/2 RESN - return false; - } - - // Highlight Album Thumbnails - Changed=new (blue), Changed=old (red), Changed=no (none) - if ($rtype=='new') { - echo '<li class="li_new">'; - } else if ($rtype=='old') { - echo '<li class="li_old">'; - } else { - echo '<li class="li_norm">'; - } - - // Get the title of the media - if ($media) { - $mediaTitle = $media->getFullName(); - } else { - $mediaTitle = $rowm['m_id']; - } - - //Get media item Notes - $haystack = $rowm['m_gedcom']; - $needle = '1 NOTE'; - $before = substr($haystack, 0, strpos($haystack, $needle)); - $after = substr(strstr($haystack, $needle), strlen($needle)); - $final = $before.$needle.$after; - $notes = htmlspecialchars(addslashes(print_fact_notes($final, 1, true, true)), ENT_QUOTES); - - // Prepare Below Thumbnail menu ---------------------------------------------------- - $mtitle = '<div style="max-width:120px;overflow:hidden;text-overflow:ellipsis;">' . $mediaTitle . '</div>'; - $menu = new WT_Menu(); - $menu->addLabel($mtitle, 'right'); - - if ($rtype=='old') { - // Do not print menu if item has changed and this is the old item - } else { - // Continue printing menu - $menu->addClass('', 'submenu'); - - // View Notes - if (strpos($rowm['m_gedcom'], "\n1 NOTE")) { - $submenu = new WT_Menu(WT_I18N::translate('View Notes'), '#'); - // Notes Tooltip ---------------------------------------------------- - $submenu->addOnclick("modalNotes('". $notes ."','". WT_I18N::translate('View Notes') ."'); return false;"); - $submenu->addClass("submenuitem"); - $menu->addSubMenu($submenu); - } - //View Details - $submenu = new WT_Menu(WT_I18N::translate('View Details'), WT_SERVER_NAME.WT_SCRIPT_PATH . "mediaviewer.php?mid=".$rowm['m_id'].'&ged='.WT_GEDURL, 'right'); - $submenu->addClass("submenuitem"); - $menu->addSubMenu($submenu); - - //View Sources - $source_menu = null; - foreach ($media->getAllFactsByType('SOUR') as $source_fact) { - $source = WT_Source::getInstance(trim($source_fact->detail, '@')); - if ($source && $source->canDisplayDetails()) { - if (!$source_menu) { - // Group sources under a top level menu - $source_menu = new WT_Menu(WT_I18N::translate('Sources'), '#', null, 'right', 'right'); - $source_menu->addClass('submenuitem', 'submenu'); - } - //now add a link to the actual source as a submenu - $submenu = new WT_Menu(new WT_Menu(strip_tags($source->getFullName()), $source->getHtmlUrl())); - $submenu->addClass('submenuitem', 'submenu'); - $source_menu->addSubMenu($submenu); - } - } - if ($source_menu) { - $menu->addSubMenu($source_menu); - } - - if (WT_USER_CAN_EDIT) { - // Edit Media - $submenu = new WT_Menu(WT_I18N::translate('Edit media')); - $submenu->addOnclick("return window.open('addmedia.php?action=editmedia&pid={$rowm['m_id']}', '_blank', edit_window_specs);"); - $submenu->addClass("submenuitem"); - $menu->addSubMenu($submenu); - if (WT_USER_IS_ADMIN) { - // Manage Links - if (array_key_exists('GEDFact_assistant', WT_Module::getActiveModules())) { - $submenu = new WT_Menu(WT_I18N::translate('Manage links')); - $submenu->addOnclick("return window.open('inverselink.php?mediaid={$rowm['m_id']}&linkto=manage', '_blank', find_window_specs);"); - $submenu->addClass("submenuitem"); - $menu->addSubMenu($submenu); - } else { - $submenu = new WT_Menu(WT_I18N::translate('Set link'), '#', null, 'right', 'right'); - $submenu->addClass('submenuitem', 'submenu'); - - $ssubmenu = new WT_Menu(WT_I18N::translate('To Person')); - $ssubmenu->addOnclick("return window.open('inverselink.php?mediaid={$rowm['m_id']}&linkto=person', '_blank', find_window_specs);"); - $ssubmenu->addClass('submenuitem', 'submenu'); - $submenu->addSubMenu($ssubmenu); - - $ssubmenu = new WT_Menu(WT_I18N::translate('To Family')); - $ssubmenu->addOnclick("return window.open('inverselink.php?mediaid={$rowm['m_id']}&linkto=family', '_blank', find_window_specs);"); - $ssubmenu->addClass('submenuitem', 'submenu'); - $submenu->addSubMenu($ssubmenu); - - $ssubmenu = new WT_Menu(WT_I18N::translate('To Source')); - $ssubmenu->addOnclick("return window.open('inverselink.php?mediaid={$rowm['m_id']}&linkto=source', '_blank', find_window_specs);"); - $ssubmenu->addClass('submenuitem', 'submenu'); - $submenu->addSubMenu($ssubmenu); - - $menu->addSubMenu($submenu); - } - // Unlink Media - $submenu = new WT_Menu(WT_I18N::translate('Unlink Media')); - $submenu->addOnclick("return delete_fact('$pid', 'OBJE', '".$rowm['m_id']."', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');"); - $submenu->addClass("submenuitem"); - $menu->addSubMenu($submenu); - } - } - } - - // Start Thumbnail Enclosure table --------------------------------------------- - // Pull table up 90px if media object is a “streetview” - if (strpos($rowm['m_filename'], 'http://maps.google.')===0) { - echo '<table width="10px" style="margin-top:-90px;" class="pic" border="0"><tr>'; - } else { - echo '<table width="10px" class="pic" border="0"><tr>'; - } - echo '<td align="center" rowspan="2">'; - echo '<div style="width:1px; height:100px;"></div>'; - echo '</td>'; - echo '<td colspan="3" valign="middle" align="center">'; - if ($media) { - echo $media->displayImage(); - } - echo '</td></tr>'; - - //View Edit Menu ---------------------------------- - echo '<tr>'; - echo '<td width="5px"></td>'; - echo '<td valign="bottom" align="center" class="nowrap">'; - echo $menu->getMenu(); - echo '</td>'; - echo '<td width="5px"></td>'; - echo '</tr>'; - echo '</table>'; - $media_data = $rowm['m_id']; - echo '<input type="hidden" name="order1[', $media_data, ']" value="', $sort_i, '">'; - $sort_i++; - echo '</li>'; - return true; -} diff --git a/modules_v3/lightbox/module.php b/modules_v3/lightbox/module.php index 46df579133..6ba96df435 100644 --- a/modules_v3/lightbox/module.php +++ b/modules_v3/lightbox/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -29,6 +29,8 @@ if (!defined('WT_WEBTREES')) { } class lightbox_WT_Module extends WT_Module implements WT_Module_Tab { + private $facts; + // Extend WT_Module public function getTitle() { return /* I18N: Name of a module */ WT_I18N::translate('Album'); @@ -46,19 +48,39 @@ class lightbox_WT_Module extends WT_Module implements WT_Module_Tab { // Implement WT_Module_Tab public function hasTabContent() { - return WT_USER_CAN_EDIT || $this->get_media_count()>0; + return WT_USER_CAN_EDIT || $this->get_facts(); } // Implement WT_Module_Tab public function isGrayedOut() { - return $this->get_media_count()==0; + return !$this->get_facts(); } // Implement WT_Module_Tab public function getTabContent() { global $controller, $sort_i; - require_once WT_ROOT.WT_MODULES_DIR.'lightbox/functions/lightbox_print_media.php'; + // Group the media objects by type. + // (The old code further grouped them into 5 categories - was this really wanted??) + $types = WT_Gedcom_Tag::getFileFormTypes(); + $groups = array(); + foreach ($this->get_facts() as $fact) { + preg_match_all('/(?:^1|\n\d) OBJE @(' . WT_REGEX_XREF . ')@/', $fact->getGedcom(), $matches); + foreach ($matches[1] as $match) { + $media = WT_Media::getInstance($match); + if ($media->canShow()) { + $type = $media->getMediaType(); + if (!array_key_exists($type, $types)) { + $type = 'other'; + } + if (!isset($groups[$type])) { + $groups[$type] = array(); + } + $groups[$type][] = array('fact' => $fact, 'media' => $media); + } + } + } + $html='<div id="'.$this->getName().'_content">'; //Show Lightbox-Album header Links if (WT_USER_CAN_EDIT) { @@ -76,7 +98,7 @@ class lightbox_WT_Module extends WT_Module implements WT_Module_Tab { $html.=WT_I18N::translate('Link to an existing media object'); $html.='</a></span>'; } - if (WT_USER_GEDCOM_ADMIN && $this->get_media_count()>1) { + if (WT_USER_GEDCOM_ADMIN && $this->get_facts()) { // Popup Reorder Media $html.='<span><a href="#" onclick="reorder_media(\''.$controller->record->getXref().'\')">'; $html.='<img src="'.WT_STATIC_URL.WT_MODULES_DIR.'lightbox/images/images.png" id="head_icon" class="icon" title="'.WT_I18N::translate('Re-order media').'" alt="'.WT_I18N::translate('Re-order media').'">'; @@ -89,60 +111,186 @@ class lightbox_WT_Module extends WT_Module implements WT_Module_Tab { $media_found = false; // Used when sorting media on album tab page - $html.='<table width="100%" cellpadding="0" border="0"><tr>'; - $html.='<td width="100%" valign="top" >'; - ob_start(); - lightbox_print_media($controller->record->getXref(), 0, true, 1); // map, painting, photo, tombstone) - lightbox_print_media($controller->record->getXref(), 0, true, 2); // card, certificate, document, magazine, manuscript, newspaper - lightbox_print_media($controller->record->getXref(), 0, true, 3); // electronic, fiche, film - lightbox_print_media($controller->record->getXref(), 0, true, 4); // audio, book, coat, video, other - lightbox_print_media($controller->record->getXref(), 0, true, 5); // footnotes - return - $html. - ob_get_clean(). - '</td></tr></table></div>'; - } + $html.='<table width="100%" cellpadding="0" border="0">'; + foreach ($groups as $type=>$media_list) { + $html .= '<tr>'; + $html .= '<td class="facts_label width20">'; + $html .= $types[$type]; + $html .= '</td>'; + $html .= '<td class="facts_value">'; + $html .= '<div class="thumbcontainer">'; + $html .= '<ul class="thumblist">'; + foreach ($media_list as $media_list_item) { + if ($media_list_item['fact']->isNew()) { + $html .= '<li class="li_new">'; + } elseif ($media_list_item['fact']->isOld()) { + $html .= '<li class="li_old">'; + } else { + $html .= '<li class="li_norm">'; + } + // ...and now the actual image + if (strpos($media_list_item['media']->getFilename(), 'http://maps.google.')===0) { + $html .= '<table width="10px" style="margin-top:-90px;" class="pic" border="0"><tr>'; + } else { + $html .= '<table width="10px" class="pic" border="0"><tr>'; + } + $html .= '<td align="center" rowspan="2">'; + $html .= '<div style="width:1px; height:100px;"></div>'; + $html .= '</td>'; + $html .= '<td colspan="3" valign="middle" align="center">'; + $html .= $media_list_item['media']->displayImage(); + $html .= '</td></tr>'; - // Implement WT_Module_Tab - public function canLoadAjax() { - global $SEARCH_SPIDER; + //View Edit Menu ---------------------------------- + $html .= '<tr>'; + $html .= '<td width="5px"></td>'; + $html .= '<td valign="bottom" align="center" class="nowrap">'; - return !$SEARCH_SPIDER; // Search engines cannot use AJAX - } - // Implement WT_Module_Tab - public function getPreLoadContent() { - return ''; - } - protected $mediaCount = null; + //Get media item Notes + $haystack = $media_list_item['media']->getGedcom(); + $needle = '1 NOTE'; + $before = substr($haystack, 0, strpos($haystack, $needle)); + $after = substr(strstr($haystack, $needle), strlen($needle)); + $final = $before.$needle.$after; + $notes = htmlspecialchars(addslashes(print_fact_notes($final, 1, true, true)), ENT_QUOTES); - private function get_media_count() { + // Prepare Below Thumbnail menu ---------------------------------------------------- + $mtitle = '<div style="max-width:120px;overflow:hidden;text-overflow:ellipsis;">' . $media_list_item['media']->getFullName() . '</div>'; + $menu = new WT_Menu(); + $menu->addLabel($mtitle, 'right'); + + if ($media_list_item['fact']->isOld()) { + // Do not print menu if item has changed and this is the old item + } else { + // Continue printing menu + $menu->addClass('', 'submenu'); + + // View Notes + if (strpos($media_list_item['media']->getGedcom(), "\n1 NOTE")) { + $submenu = new WT_Menu(WT_I18N::translate('View Notes'), '#'); + // Notes Tooltip ---------------------------------------------------- + $submenu->addOnclick("modalNotes('". $notes ."','". WT_I18N::translate('View Notes') ."'); return false;"); + $submenu->addClass("submenuitem"); + $menu->addSubMenu($submenu); + } + //View Details + $submenu = new WT_Menu(WT_I18N::translate('View Details'), WT_SERVER_NAME.WT_SCRIPT_PATH . "mediaviewer.php?mid=".$media_list_item['media']->getXref().'&ged='.WT_GEDURL, 'right'); + $submenu->addClass("submenuitem"); + $menu->addSubMenu($submenu); + + //View Sources + $source_menu = null; + foreach ($media->getFacts('SOUR') as $source_fact) { + $source = WT_Source::getInstance(trim($source_fact->detail, '@')); + if ($source && $source->canShow()) { + if (!$source_menu) { + // Group sources under a top level menu + $source_menu = new WT_Menu(WT_I18N::translate('Sources'), '#', null, 'right', 'right'); + $source_menu->addClass('submenuitem', 'submenu'); + } + //now add a link to the actual source as a submenu + $submenu = new WT_Menu(new WT_Menu(strip_tags($source->getFullName()), $source->getHtmlUrl())); + $submenu->addClass('submenuitem', 'submenu'); + $source_menu->addSubMenu($submenu); + } + } + if ($source_menu) { + $menu->addSubMenu($source_menu); + } + + if (WT_USER_CAN_EDIT) { + // Edit Media + $submenu = new WT_Menu(WT_I18N::translate('Edit media')); + $submenu->addOnclick("return window.open('addmedia.php?action=editmedia&pid=".$media_list_item['media']->getXref()."', '_blank', edit_window_specs);"); + $submenu->addClass("submenuitem"); + $menu->addSubMenu($submenu); + if (WT_USER_IS_ADMIN) { + // Manage Links + if (array_key_exists('GEDFact_assistant', WT_Module::getActiveModules())) { + $submenu = new WT_Menu(WT_I18N::translate('Manage links')); + $submenu->addOnclick("return window.open('inverselink.php?mediaid=".$media_list_item['media']->getXref()."&linkto=manage', '_blank', find_window_specs);"); + $submenu->addClass("submenuitem"); + $menu->addSubMenu($submenu); + } else { + $submenu = new WT_Menu(WT_I18N::translate('Set link'), '#', null, 'right', 'right'); + $submenu->addClass('submenuitem', 'submenu'); + + $ssubmenu = new WT_Menu(WT_I18N::translate('To Person')); + $ssubmenu->addOnclick("return window.open('inverselink.php?mediaid=".$media_list_item['media']->getXref()."&linkto=person', '_blank', find_window_specs);"); + $ssubmenu->addClass('submenuitem', 'submenu'); + $submenu->addSubMenu($ssubmenu); + + $ssubmenu = new WT_Menu(WT_I18N::translate('To Family')); + $ssubmenu->addOnclick("return window.open('inverselink.php?mediaid=".$media_list_item['media']->getXref()."&linkto=family', '_blank', find_window_specs);"); + $ssubmenu->addClass('submenuitem', 'submenu'); + $submenu->addSubMenu($ssubmenu); + + $ssubmenu = new WT_Menu(WT_I18N::translate('To Source')); + $ssubmenu->addOnclick("return window.open('inverselink.php?mediaid=".$media_list_item['media']->getXref()."&linkto=source', '_blank', find_window_specs);"); + $ssubmenu->addClass('submenuitem', 'submenu'); + $submenu->addSubMenu($ssubmenu); + + $menu->addSubMenu($submenu); + } + // Unlink Media + $submenu = new WT_Menu(WT_I18N::translate('Unlink Media')); + $submenu->addOnclick("return delete_fact('".$media_list_item['media']->getXref()."', 'OBJE', '".$media_list_item['media']->getXref()."', '".WT_I18N::translate('Are you sure you want to delete this fact?')."');"); + $submenu->addClass("submenuitem"); + $menu->addSubMenu($submenu); + } + } + $html .= $menu->getMenu(); + } + $html .= '</td>'; + $html .= '<td width="5px"></td>'; + $html .= '</tr>'; + $html .= '</table>'; + $html .= '<input type="hidden" name="order1[' . $media_list_item['media']->getXref() . ']" value="' . $sort_i . '">'; + $sort_i++; + $html .= '</li>'; + } + $html .= '</ul>'; + $html .= '<div class="clearlist"></div>'; + $html .= '</td>'; + $html .= '</tr>'; + } + $html .= '</table></div>'; + return $html; + } + + private function get_facts() { global $controller; - if ($this->mediaCount===null) { - $this->mediaCount = 0; - preg_match_all('/\d OBJE @(' . WT_REGEX_XREF . ')@/', $controller->record->getGedcomRecord(), $matches); - foreach ($matches[1] as $match) { - $obje = WT_Media::getInstance($match); - if ($obje && $obje->canDisplayDetails()) { - $this->mediaCount++; + if ($this->facts === null) { + $facts = $controller->record->getFacts(); + foreach ($controller->record->getSpouseFamilies() as $family) { + if ($family->canShow()) { + foreach ($family->getFacts() as $fact) { + $facts[] = $fact; + } } } - foreach ($controller->record->getSpouseFamilies() as $sfam) { - preg_match_all('/\d OBJE @(' . WT_REGEX_XREF . ')@/', $sfam->getGedcomRecord(), $matches); - foreach ($matches[1] as $match) { - $obje = WT_Media::getInstance($match); - if ($obje && $obje->canDisplayDetails()) { - $this->mediaCount++; - } + $this->facts = array(); + foreach ($facts as $fact) { + if (preg_match('/(?:^1|\n\d) OBJE @' . WT_REGEX_XREF . '@/', $fact->getGedcom())) { + $this->facts[] = $fact; } } } - return $this->mediaCount; + return $this->facts; + } + + // Implement WT_Module_Tab + public function canLoadAjax() { + global $SEARCH_SPIDER; + + return !$SEARCH_SPIDER; // Search engines cannot use AJAX } - private function getJS() { + // Implement WT_Module_Tab + public function getPreLoadContent() { return ''; } } diff --git a/modules_v3/media/module.php b/modules_v3/media/module.php index 21dc794102..8750a95ffa 100644 --- a/modules_v3/media/module.php +++ b/modules_v3/media/module.php @@ -29,6 +29,8 @@ if (!defined('WT_WEBTREES')) { } class media_WT_Module extends WT_Module implements WT_Module_Tab { + private $facts; + // Extend WT_Module public function getTitle() { return /* I18N: Name of a module */ WT_I18N::translate('Media'); @@ -44,16 +46,14 @@ class media_WT_Module extends WT_Module implements WT_Module_Tab { return 50; } - protected $mediaCount = null; - // Implement WT_Module_Tab public function hasTabContent() { - return WT_USER_CAN_EDIT || $this->get_media_count()>0; + return WT_USER_CAN_EDIT || $this->get_facts(); } // Implement WT_Module_Tab public function isGrayedOut() { - return $this->get_media_count()==0; + return !$this->get_facts(); } // Implement WT_Module_Tab @@ -62,31 +62,51 @@ class media_WT_Module extends WT_Module implements WT_Module_Tab { ob_start(); echo '<table class="facts_table">'; - // Reorder media ------------------------------------ - if (WT_USER_GEDCOM_ADMIN && $this->get_media_count()>1) { - echo '<tr><td colspan="2" class="descriptionbox rela">'; - echo '<span><a href="#" onclick="reorder_media(\''.$controller->record->getXref().'\'); return false;"><i class="icon-media-shuffle"></i>'; - echo WT_I18N::translate('Re-order media'); - echo '</a></span>'; - echo '</td></tr>'; + if (WT_USER_GEDCOM_ADMIN && $this->get_facts()) { + ?> + <tr> + <td colspan="2" class="descriptionbox rela"> + <span> + <a href="#" onclick="reorder_media(\''.$controller->record->getXref().'\'); return false;"> + <i class="icon-media-shuffle"></i> + <?php echo WT_I18N::translate('Re-order media'); ?> + </a> + </span> + </td> + </tr> + <?php } - $media_found = print_main_media($controller->record->getXref(), 0, true); - if (!$media_found) { + foreach ($this->get_facts() as $fact) { + if ($fact->getTag() == 'OBJE') { + print_main_media($fact, 1); + } else { + for ($i=2; $i<4; ++$i) { + print_main_media($fact, $i); + } + } + } + if (!$this->get_facts()) { echo '<tr><td id="no_tab4" colspan="2" class="facts_value">', WT_I18N::translate('There are no media objects for this individual.'), '</td></tr>'; } - //-- New Media link - if (WT_USER_CAN_EDIT && $controller->record->canDisplayDetails() && get_gedcom_setting(WT_GED_ID, 'MEDIA_UPLOAD') >= WT_USER_ACCESS_LEVEL) { - ?> + // New media link + if ($controller->record->canEdit() && get_gedcom_setting(WT_GED_ID, 'MEDIA_UPLOAD') >= WT_USER_ACCESS_LEVEL) { + ?> <tr> - <td class="facts_label"><?php echo WT_Gedcom_Tag::getLabel('OBJE'); ?></td> + <td class="facts_label"> + <?php echo WT_Gedcom_Tag::getLabel('OBJE'); ?> + </td> <td class="facts_value"> - <a href="#" onclick="window.open('addmedia.php?action=showmediaform&linktoid=<?php echo $controller->record->getXref(); ?>&ged=<?php echo WT_GEDURL; ?>', '_blank', edit_window_specs); return false;"> <?php echo WT_I18N::translate('Add a new media object'); ?></a> + <a href="#" onclick="window.open('addmedia.php?action=showmediaform&linktoid=<?php echo $controller->record->getXref(); ?>&ged=<?php echo WT_GEDURL; ?>', '_blank', edit_window_specs); return false;"> + <?php echo WT_I18N::translate('Add a new media object'); ?> + </a> <?php echo help_link('OBJE'); ?> <br> - <a href="#" onclick="window.open('inverselink.php?linktoid=<?php echo $controller->record->getXref(); ?>&ged=<?php echo WT_GEDURL; ?>&linkto=person', '_blank', find_window_specs); return false;"><?php echo WT_I18N::translate('Link to an existing media object'); ?></a> + <a href="#" onclick="window.open('inverselink.php?linktoid=<?php echo $controller->record->getXref(); ?>&ged=<?php echo WT_GEDURL; ?>&linkto=person', '_blank', find_window_specs); return false;"> + <?php echo WT_I18N::translate('Link to an existing media object'); ?> + </a> </td> </tr> - <?php + <?php } ?> </table> @@ -94,33 +114,27 @@ class media_WT_Module extends WT_Module implements WT_Module_Tab { return '<div id="'.$this->getName().'_content">'.ob_get_clean().'</div>'; } - /** - * get the number of media items for this person - * @return int - */ - function get_media_count() { + // Get all facts containing media links for this person and their spouse-family records + function get_facts() { global $controller; - if ($this->mediaCount===null) { - $this->mediaCount = 0; - preg_match_all('/\d OBJE @(' . WT_REGEX_XREF . ')@/', $controller->record->getGedcomRecord(), $matches); - foreach ($matches[1] as $match) { - $obje = WT_Media::getInstance($match); - if ($obje && $obje->canDisplayDetails()) { - $this->mediaCount++; + if ($this->facts === null) { + $facts = $controller->record->getFacts(); + foreach ($controller->record->getSpouseFamilies() as $family) { + if ($family->canShow()) { + foreach ($family->getFacts() as $fact) { + $facts[] = $fact; + } } } - foreach ($controller->record->getSpouseFamilies() as $sfam) { - preg_match_all('/\d OBJE @(' . WT_REGEX_XREF . ')@/', $sfam->getGedcomRecord(), $matches); - foreach ($matches[1] as $match) { - $obje = WT_Media::getInstance($match); - if ($obje && $obje->canDisplayDetails()) { - $this->mediaCount++; - } + $this->facts = array(); + foreach ($facts as $fact) { + if (preg_match('/(?:^1|\n\d) OBJE @' . WT_REGEX_XREF . '@/', $fact->getGedcom())) { + $this->facts[] = $fact; } } } - return $this->mediaCount; + return $this->facts; } // Implement WT_Module_Tab diff --git a/modules_v3/notes/module.php b/modules_v3/notes/module.php index c799033869..1a683092ff 100644 --- a/modules_v3/notes/module.php +++ b/modules_v3/notes/module.php @@ -29,6 +29,8 @@ if (!defined('WT_WEBTREES')) { } class notes_WT_Module extends WT_Module implements WT_Module_Tab { + private $facts; + // Extend WT_Module public function getTitle() { return /* I18N: Name of a module */ WT_I18N::translate('Notes'); @@ -44,73 +46,72 @@ class notes_WT_Module extends WT_Module implements WT_Module_Tab { return 40; } - protected $noteCount = null; + // Implement WT_Module_Tab + public function hasTabContent() { + return WT_USER_CAN_EDIT || $this->get_facts(); + } // Implement WT_Module_Tab + public function isGrayedOut() { + return !$this->get_facts(); + } + // Implement WT_Module_Tab public function getTabContent() { global $SHOW_LEVEL2_NOTES, $NAV_NOTES, $controller; ob_start(); + echo '<table class="facts_table">'; ?> - <table class="facts_table"> - <tr> - <td colspan="2" class="descriptionbox rela"> - <input id="checkbox_note2" type="checkbox" <?php if ($SHOW_LEVEL2_NOTES) echo ' checked="checked"'; ?> onclick="jQuery('tr.row_note2').toggle();"> - <label for="checkbox_note2"><?php echo WT_I18N::translate('Show all notes'); ?></label> - <?php echo help_link('show_fact_sources'); ?> - </td> - </tr> + <tr> + <td colspan="2" class="descriptionbox rela"> + <input id="checkbox_note2" type="checkbox" <?php if ($SHOW_LEVEL2_NOTES) echo ' checked="checked"'; ?> onclick="jQuery('tr.row_note2').toggle();"> + <label for="checkbox_note2"><?php echo WT_I18N::translate('Show all notes'); ?></label> + <?php echo help_link('show_fact_sources'); ?> + </td> + </tr> <?php - $globalfacts = $controller->getGlobalFacts(); - foreach ($globalfacts as $event) { - $fact = $event->getTag(); - if ($fact=='NAME') { - print_main_notes($event, 2); + foreach ($this->get_facts() as $fact) { + if ($fact->getTag() == 'NOTE') { + print_main_notes($fact, 1); + } else { + for ($i=2; $i<4; ++$i) { + print_main_notes($fact, $i); + } } } - $otherfacts = $controller->getOtherFacts(); - foreach ($otherfacts as $event) { - $fact = $event->getTag(); - if ($fact=='NOTE') { - print_main_notes($event, 1); + if (!$this->get_facts()) { + echo '<tr><td id="no_tab4" colspan="2" class="facts_value">', WT_I18N::translate('There are no Notes for this individual.'), '</td></tr>'; } - } - // 2nd to 5th level notes/sources - $controller->record->add_family_facts(false); - foreach ($controller->getIndiFacts() as $factrec) { - for ($i=2; $i<6; $i++) { - print_main_notes($factrec, $i); - } - } - if ($this->get_note_count()==0) { - echo '<tr><td id="no_tab2" colspan="2" class="facts_value">', WT_I18N::translate('There are no Notes for this individual.'), '</td></tr>'; - } - //-- New Note Link + + // New note link if ($controller->record->canEdit()) { ?> - <tr> - <td class="facts_label"><?php echo WT_Gedcom_Tag::getLabel('NOTE'); ?></td> - <td class="facts_value"> - <a href="#" onclick="add_new_record('<?php echo $controller->record->getXref(); ?>','NOTE'); return false;"> - <?php echo WT_I18N::translate('Add a new note'); ?> - </a> - <?php echo help_link('add_note'); ?> - </td> - </tr> - <tr> - <td class="facts_label"><?php echo WT_Gedcom_Tag::getLabel('SHARED_NOTE'); ?></td> - <td class="facts_value"> - <a href="#" onclick="add_new_record('<?php echo $controller->record->getXref(); ?>','SHARED_NOTE'); return false;"> - <?php echo WT_I18N::translate('Add a new shared note'); ?> - </a> - <?php echo help_link('add_shared_note'); ?> - </td> - </tr> - <?php + <tr> + <td class="facts_label"> + <?php echo WT_Gedcom_Tag::getLabel('NOTE'); ?> + </td> + <td class="facts_value"> + <a href="#" onclick="add_new_record('<?php echo $controller->record->getXref(); ?>','NOTE'); return false;"> + <?php echo WT_I18N::translate('Add a new note'); ?> + </a> + <?php echo help_link('add_note'); ?> + </td> + </tr> + <tr> + <td class="facts_label"> + <?php echo WT_Gedcom_Tag::getLabel('SHARED_NOTE'); ?> + </td> + <td class="facts_value"> + <a href="#" onclick="add_new_record('<?php echo $controller->record->getXref(); ?>','SHARED_NOTE'); return false;"> + <?php echo WT_I18N::translate('Add a new shared note'); ?> + </a> + <?php echo help_link('add_shared_note'); ?> + </td> + </tr> + <?php } ?> </table> - <br> <?php if (!$SHOW_LEVEL2_NOTES) { echo '<script>jQuery("tr.row_note2").toggle();</script>'; @@ -118,27 +119,29 @@ class notes_WT_Module extends WT_Module implements WT_Module_Tab { return '<div id="'.$this->getName().'_content">'.ob_get_clean().'</div>'; } - function get_note_count() { + function get_facts() { global $controller; - if ($this->noteCount===null) { - $ct = preg_match_all("/\d NOTE /", $controller->record->getGedcomRecord(), $match, PREG_SET_ORDER); - foreach ($controller->record->getSpouseFamilies() as $sfam) - $ct += preg_match("/\d NOTE /", $sfam->getGedcomRecord()); - $this->noteCount = $ct; + if ($this->facts === null) { + $facts = $controller->record->getFacts(); + foreach ($controller->record->getSpouseFamilies() as $family) { + if ($family->canShow()) { + foreach ($family->getFacts() as $fact) { + $facts[] = $fact; + } + } + } + $this->facts = array(); + foreach ($facts as $fact) { + if (preg_match('/(?:^1|\n\d) NOTE/', $fact->getGedcom())) { + $this->facts[] = $fact; + } + } } - return $this->noteCount; + return $this->facts; } // Implement WT_Module_Tab - public function hasTabContent() { - return WT_USER_CAN_EDIT || $this->get_note_count()>0; - } - // Implement WT_Module_Tab - public function isGrayedOut() { - return $this->get_note_count()==0; - } - // Implement WT_Module_Tab public function canLoadAjax() { global $SEARCH_SPIDER; diff --git a/modules_v3/personal_facts/module.php b/modules_v3/personal_facts/module.php index 8e3257eae5..ca557b457c 100644 --- a/modules_v3/personal_facts/module.php +++ b/modules_v3/personal_facts/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -54,57 +54,117 @@ class personal_facts_WT_Module extends WT_Module implements WT_Module_Tab { global $EXPAND_RELATIVES_EVENTS, $controller; $EXPAND_HISTO_EVENTS = false; + $indifacts = array(); + // The individual's own facts + foreach ($controller->record->getFacts() as $fact) { + switch ($fact->getTag()) { + case 'SEX': + case 'NAME': + case 'SOUR': + case 'OBJE': + case 'NOTE': + case 'FAMC': + case 'FAMS': + break; + default: + if (!array_key_exists('extra_info', WT_Module::getActiveSidebars()) || !extra_info_WT_Module::showFact($fact)) { + if ($fact->canShow()) { + $indifacts[] = $fact; + } + } + break; + } + } + + // Add spouse-family facts + foreach ($controller->record->getSpouseFamilies() as $family) { + $spouse = $family->getSpouse($controller->record); + $divorced = false; + foreach ($family->getFacts() as $fact) { + switch ($fact->getTag()) { + case 'SOUR': + case 'NOTE': + case 'CHAN': + case '_UID': + case 'RIN': + case 'HUSB': + case 'WIFE': + case 'CHIL': + break; + default: + if ($fact->getTag() == 'DIV') { + $divorced = true; + } + if ($fact->canShow()) { + $indifacts[] = $fact; + } + break; + } + } + + // Don't show family facts for divorced spouses + if (!$divorced) { + foreach (self::spouse_facts($controller->record, $spouse) as $fact) { + $indifacts[] = $fact; + } + } + foreach (self::child_facts($controller->record, $family, '_CHIL', '') as $fact) { + $indifacts[] = $fact; + } + } + + foreach (self::parent_facts($controller->record, 1) as $fact) { + $indifacts[] = $fact; + } + foreach (self::historical_facts($controller->record) as $fact) { + $indifacts[] = $fact; + } + foreach (self::associate_facts($controller->record) as $fact) { + $indifacts[] = $fact; + } + + sort_facts($indifacts); + + ob_start(); + + echo '<table class="facts_table">'; echo '<script>'; if (!$EXPAND_RELATIVES_EVENTS) { - echo "jQuery('tr.row_rela').toggle();"; + echo "jQuery('tr.rela').toggle();"; } if (!$EXPAND_HISTO_EVENTS) { - echo "jQuery('tr.row_histo').toggle();"; + echo "jQuery('tr.histo').toggle();"; } echo '</script>'; - //-- only need to add family facts on this tab - if (!isset($controller->skipFamilyFacts)) { - $controller->record->add_family_facts(); + if (!$indifacts) { + echo '<tr><td colspan="2" class="facts_value">', WT_I18N::translate('There are no Facts for this individual.'), '</td></tr>'; } - ob_start(); - echo '<table class="facts_table">'; - $indifacts = $controller->getIndiFacts(); - if (count($indifacts)==0) { - echo '<tr><td colspan="2" class="facts_value">', WT_I18N::translate('There are no Facts for this individual.'), '</td></tr>'; + echo '<tr><td colspan="2" class="descriptionbox rela"><input id="checkbox_rela_facts" type="checkbox"'; + if ($EXPAND_RELATIVES_EVENTS) { + echo ' checked="checked"'; } - if (!isset($controller->skipFamilyFacts)) { - echo '<tr id="row_top"><td colspan="2" class="descriptionbox rela"><input id="checkbox_rela_facts" type="checkbox"'; - if ($EXPAND_RELATIVES_EVENTS) { + echo ' onclick="jQuery(\'tr.rela\').toggle();"><label for="checkbox_rela_facts">', WT_I18N::translate('Events of close relatives'), '</label>'; + if (file_exists(WT_Site::preference('INDEX_DIRECTORY').'histo.'.WT_LOCALE.'.php')) { + echo ' <input id="checkbox_histo" type="checkbox"'; + if ($EXPAND_HISTO_EVENTS) { echo ' checked="checked"'; } - echo ' onclick="jQuery(\'tr.row_rela\').toggle();"><label for="checkbox_rela_facts">', WT_I18N::translate('Events of close relatives'), '</label>'; - if (file_exists(WT_Site::preference('INDEX_DIRECTORY').'histo.'.WT_LOCALE.'.php')) { - echo ' <input id="checkbox_histo" type="checkbox"'; - if ($EXPAND_HISTO_EVENTS) { - echo ' checked="checked"'; - } - echo ' onclick="jQuery(\'tr.row_histo\').toggle();"><label for="checkbox_histo">', WT_I18N::translate('Historical facts'), '</label>'; - } - echo '</td></tr>'; + echo ' onclick="jQuery(\'tr.histo\').toggle();"><label for="checkbox_histo">', WT_I18N::translate('Historical facts'), '</label>'; } + echo '</td></tr>'; + foreach ($indifacts as $fact) { - if ($fact->getParentObject() instanceof WT_Family) { - // Print all family facts - print_fact($fact, $controller->record); - } else { - // Individual/reference facts (e.g. CHAN, IDNO, RFN, AFN, REFN, RIN, _UID) can be shown in the sidebar - if (!in_array($fact->getTag(), WT_Gedcom_Tag::getReferenceFacts()) || !array_key_exists('extra_info', WT_Module::getActiveSidebars())) { - print_fact($fact, $controller->record); - } - } + print_fact($fact, $controller->record); } + //-- new fact link if ($controller->record->canEdit()) { print_add_new_fact($controller->record->getXref(), $indifacts, 'INDI'); } echo '</table>'; + return '<div id="'.$this->getName().'_content">'.ob_get_clean().'</div>'; } @@ -124,4 +184,325 @@ class personal_facts_WT_Module extends WT_Module implements WT_Module_Tab { public function getPreLoadContent() { return ''; } + + // Extra facts to be shown on this tabparent + private static function spouse_facts(WT_Individual $person, WT_Individual $spouse) { + global $SHOW_RELATIVES_EVENTS; + + $facts = array(); + if ($spouse && strstr($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) { + // Only include events between birth and death + $birt_date = $person->getEstimatedBirthDate(); + $deat_date = $person->getEstimatedDeathDate(); + + foreach ($spouse->getFacts(WT_EVENTS_DEAT) as $fact) { + + $fact_date = $fact->getDate(); + if ($fact_date->isOK() && WT_Date::Compare($birt_date, $fact_date)<=0 && WT_Date::Compare($fact_date, $deat_date)<=0) { + // Convert the event to a close relatives event. + $rela_fact = clone($fact); + $rela_fact->setTag('_'.$fact->getTag().'_SPOU'); + $facts[] = $rela_fact; + } + } + } + + return $facts; + } + + private static function child_facts(WT_Individual $person, WT_Family $family, $option, $relation) { + global $SHOW_RELATIVES_EVENTS; + + $facts = array(); + + // Only include events between birth and death + $birt_date = $person->getEstimatedBirthDate(); + $deat_date = $person->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::child_facts($person, $cfamily, '_GCHI', 'son') as $fact) { + $facts[] = $fact; + } + break; + case 'F': + foreach (self::child_facts($person, $cfamily, '_GCHI', 'dau') as $fact) { + $facts[] = $fact; + } + break; + case 'U': + foreach (self::child_facts($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() && WT_Date::Compare($birt_date, $sgdate)<=0 && WT_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(); + $srec = $fact->getGedcom(); + if ($sgdate->isOK() && WT_Date::Compare($birt_date, $sgdate)<=0 && WT_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() && WT_Date::Compare($birt_date, $sgdate)<=0 && WT_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; + } + + private static function parent_facts(WT_Individual $person, $sosa) { + global $SHOW_RELATIVES_EVENTS; + + $facts = array(); + + if ($sosa==1) { + foreach ($person->getChildFamilies() as $family) { + // Add siblings + foreach (self::child_facts($person, $family, '_SIBL', '') as $fact) { + $facts[] = $fact; + } + foreach ($family->getSpouses() as $spouse) { + foreach ($spouse->getSpouseFamilies() as $sfamily) { + if (!$family->equals($sfamily)) { + // Add half-siblings + foreach (self::child_facts($person, $sfamily, '_HSIB', '') as $fact) { + $facts[] = $fact; + } + } + } + // Add grandparents + foreach (self::parent_facts($spouse, $spouse->getSex()=='F' ? 3 : 2) as $fact) { + $facts[] = $fact; + } + } + } + } + + // Only include events between birth and death + $birt_date=$person->getEstimatedBirthDate(); + $deat_date=$person->getEstimatedDeathDate(); + + foreach ($person->getChildFamilies() as $family) { + foreach ($family->getSpouses() as $parent) { + if (strstr($SHOW_RELATIVES_EVENTS, '_DEAT'.($sosa==1 ? '_PARE' : '_GPAR'))) { + foreach ($parent->getFacts(WT_EVENTS_DEAT) as $fact) { + if ($fact->getDate()->isOK() && WT_Date::Compare($birt_date, $fact->getDate())<=0 && WT_Date::Compare($fact->getDate(), $deat_date)<=0) { + switch ($sosa) { + case 1: + // Convert the event to a close relatives event. + $rela_fact = clone($fact); + $rela_fact->setTag('_'.$fact->getTag().'_PARE'); + $facts[] = $rela_fact; + break; + case 2: + // Convert the event to a close relatives event + $rela_fact = clone($fact); + $rela_fact->setTag('_'.$fact->getTag().'_GPA1'); + $facts[] = $rela_fact; + break; + case 3: + // Convert the event to a close relatives event + $rela_fact = clone($fact); + $rela_fact->setTag('_'.$fact->getTag().'_GPA2'); + $facts[] = $rela_fact; + break; + } + } + } + } + } + + if ($sosa==1 && strstr($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) { + // add father/mother marriages + foreach ($family->getSpouses() as $parent) { + foreach ($parent->getSpouseFamilies() as $sfamily) { + foreach ($sfamily->getFacts(WT_EVENTS_MARR) as $fact) { + if ($fact->getDate()->isOK() && WT_Date::Compare($birt_date, $fact->getDate())<=0 && WT_Date::Compare($fact->getDate(), $deat_date)<=0) { + if ($sfamily->equals($family)) { + if ($parent->getSex()=='F') { + // show current family marriage only once + continue; + } + // marriage of parents (to each other) + $rela_fact = clone($fact); + $rela_fact->setTag('_'.$fact->getTag().'_FAMC'); + $facts[] = $rela_fact; + break; + + } else { + // marriage of a parent (to another spouse) + // Convert the event to a close relatives event + $rela_fact = clone($fact); + $rela_fact->setTag('_'.$fact->getTag().'_PARE'); + $facts[] = $rela_fact; + } + } + } + } + } + } + } + + return $facts; + } + + private static function historical_facts(WT_Individual $person) { + global $SHOW_RELATIVES_EVENTS; + if (!$SHOW_RELATIVES_EVENTS) return; + + $facts = array(); + + // Only include events between birth and death + $birt_date = $person->getEstimatedBirthDate(); + $deat_date = $person->getEstimatedDeathDate(); + + if (file_exists(WT_Site::preference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php')) { + require WT_Site::preference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php'; + foreach ($histo as $hist) { + $sdate = new WT_Date(get_gedcom_value('DATE', 2, $hist)); + if ($sdate->isOK() && WT_Date::Compare($birt_date, $sdate)<=0 && WT_Date::Compare($sdate, $deat_date)<=0) { + $facts[] = new WT_Fact($hist, null, 'histo'); + } + } + } + + return $facts; + } + + private static function associate_facts(WT_Individual $person) { + $facts = array(); + + $associates=array_merge( + fetch_linked_indi($person->getXref(), 'ASSO', $person->getGedcomId()), + fetch_linked_indi($person->getXref(), '_ASSO', $person->getGedcomId()), + fetch_linked_fam ($person->getXref(), 'ASSO', $person->getGedcomId()), + fetch_linked_fam ($person->getXref(), '_ASSO', $person->getGedcomId()) + ); + foreach ($associates as $associate) { + foreach ($associate->getFacts() as $fact) { + $srec = $fact->getGedcom(); + foreach (array('ASSO', '_ASSO') as $asso_tag) { + $arec = get_sub_record(2, '2 ' . $asso_tag . ' @' . $person->getXref() . '@', $srec); + if ($arec) { + // Extract the important details from the fact + $factrec='1 '.$fact->getTag(); + if (preg_match('/\n2 DATE .*/', $srec, $match)) { + $factrec.=$match[0]; + } + if (preg_match('/\n2 PLAC .*/', $srec, $match)) { + $factrec.=$match[0]; + } + if ($associate instanceof WT_Family) { + foreach ($associate->getSpouses() as $spouse) { + $factrec.="\n2 $asso_tag @".$spouse->getXref().'@'; + } + } else { + $factrec.="\n2 $asso_tag @".$associate->getXref().'@'; + // CHR/BAPM events are commonly used. Generate the reverse relationship + if (preg_match('/^(?:BAPM|CHR)$/', $fact->getTag()) && preg_match('/3 RELA god(?:parent|mother|father)/', $fact->getGedcom())) { + switch ($associate->getSex()) { + case 'M': + $factrec.="\n3 RELA godson"; + break; + case 'F': + $factrec.="\n3 RELA goddaughter"; + break; + case 'U': + $factrec.="\n3 RELA godchild"; + break; + } + } + } + $facts[] = new WT_Fact($factrec, $associate, 'asso'); + } + } + } + } + + return $facts; + } } diff --git a/modules_v3/random_media/module.php b/modules_v3/random_media/module.php index 4175d11265..0abaceb0d4 100644 --- a/modules_v3/random_media/module.php +++ b/modules_v3/random_media/module.php @@ -94,13 +94,13 @@ class random_media_WT_Module extends WT_Module implements WT_Module_Block { while ($all_media) { $n=array_rand($all_media); $media=WT_Media::getInstance($all_media[$n]); - if ($media->canDisplayDetails() && !$media->isExternal()) { + if ($media->canShow() && !$media->isExternal()) { // Check if it is linked to a suitable individual foreach ($media->fetchLinkedIndividuals() as $indi) { if ( $filter=='all' || - $filter=='indi' && strpos($indi->getGedcomRecord(), "\n1 OBJE @" . $media->getXref() . '@') !==false || - $filter=='event' && strpos($indi->getGedcomRecord(), "\n2 OBJE @" . $media->getXref() . '@') !==false + $filter=='indi' && strpos($indi->getGedcom(), "\n1 OBJE @" . $media->getXref() . '@') !==false || + $filter=='event' && strpos($indi->getGedcom(), "\n2 OBJE @" . $media->getXref() . '@') !==false ) { // Found one :-) $random_media=$media; @@ -187,7 +187,7 @@ class random_media_WT_Module extends WT_Module implements WT_Module_Block { $content .= '<a href="' . $source->getHtmlUrl() . '">' . WT_I18N::translate('View Source') . ' — ' . $source->getFullname().'</a><br>'; } $content .= '<br><div class="indent">'; - $content .= print_fact_notes($random_media->getGedcomRecord(), "1", false, true); + $content .= print_fact_notes($random_media->getGedcom(), "1", false, true); $content .= '</div>'; $content .= '</td></tr></table>'; $content .= '</div>'; // random_picture_content diff --git a/modules_v3/relatives/module.php b/modules_v3/relatives/module.php index 557422cd00..16f450c8ec 100644 --- a/modules_v3/relatives/module.php +++ b/modules_v3/relatives/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -48,232 +48,167 @@ class relatives_WT_Module extends WT_Module implements WT_Module_Tab { return 20; } - function printFamilyHeader($url, $label) { - echo '<table><tr>'; - echo '<td><i class="icon-cfamily"></i></td>'; - echo '<td><span class="subheaders">', $label, '</span>'; - echo ' - <a href="', $url, '">', WT_I18N::translate('View Family'), '</a></td>'; - echo '</tr></table>'; - } - - /** - * print parents informations - * @param Family family - * @param Array people - * @param String family type - * @return html table rows - */ - function printParentsRows($family, $people, $type) { - global $personcount, $SHOW_PEDIGREE_PLACES, $controller, $SEARCH_SPIDER; + // print parents informations + function printFamily(WT_Family $family, $type, $label) { + global $controller; + global $personcount; // TODO: use a unique id instead? - $elderdate = ""; - //-- new father/husband - $styleadd = ""; - if (isset($people["newhusb"])) { - $styleadd = "red"; - ?> + ?> + <table> <tr> - <td class="facts_labelblue"><?php echo $people["newhusb"]->getLabel(); ?></td> - <td class="<?php echo $controller->getPersonStyle($people["newhusb"]); ?>"> - <?php print_pedigree_person($people["newhusb"], 2, 0, $personcount++); ?> + <td> + <i class="icon-cfamily"></i> + </td> + <td> + <span class="subheaders"> <?php echo $label; ?> </span> - + <a href="<?php echo $family->getHtmlUrl() ; ?>"><?php echo WT_I18N::translate('View Family'); ?></a> </td> </tr> - <?php - $elderdate = $people["newhusb"]->getBirthDate(); - } - //-- father/husband - if (isset($people["husb"])) { + </table> + <table class="facts_table"> + <?php + + ///// HUSB ///// + $found = false; + foreach ($family->getFacts('HUSB') as $fact) { + $found |= !$fact->isOld(); + if ($fact->isNew()) { + $class = 'facts_label new'; + } elseif ($fact->isOld()) { + $class = 'facts_label old'; + } else { + $class = 'facts_label'; + } + $person = $fact->getTarget(); + if ($person->equals($controller->record)) { + $label = '<i class="icon-selected"></i>'; + } else { + $label = get_relationship_name(get_relationship($controller->record, $person, true, 3)); + } ?> <tr> - <td class="facts_label<?php echo $styleadd; ?>"><?php echo $people["husb"]->getLabel(); ?></td> - <td class="<?php echo $controller->getPersonStyle($people["husb"]); ?>"> - <?php print_pedigree_person($people["husb"], 2, 0, $personcount++); ?> + <td class="<?php echo $class; ?>"> + <?php echo $label; ?> + </td> + <td class="<?php echo $controller->getPersonStyle($person); ?>"> + <?php print_pedigree_person($person, 2, 0, $personcount++); ?> </td> </tr> <?php - $elderdate = $people["husb"]->getBirthDate(); - } - //-- missing father - if ($type=="parents" && !isset($people["husb"]) && !isset($people["newhusb"])) { - if ($controller->record->canEdit()) { - ?> - <tr> - <td class="facts_label"><?php echo WT_I18N::translate('Add a new father'); ?></td> - <td class="facts_value"><a href="#" onclick="return addnewparentfamily('<?php echo $controller->record->getXref(); ?>', 'HUSB', '<?php echo $family->getXref(); ?>');"><?php echo WT_I18N::translate('Add a new father'); ?></a></td> - </tr> - <?php - } - } - //-- missing husband - if ($type=="spouse" && !isset($people["husb"]) && !isset($people["newhusb"])) { - if ($controller->record->canEdit()) { - ?> - <tr> - <td class="facts_label"><?php echo WT_I18N::translate('Add husband'); ?></td> - <td class="facts_value"><a href="#" onclick="return addnewspouse('<?php echo $family->getXref(); ?>', 'HUSB');"><?php echo WT_I18N::translate('Add a husband to this family'); ?></a></td> - </tr> - <?php - } } - //-- new mother/wife - $styleadd = ""; - if (isset($people["newwife"])) { - $styleadd = "red"; + if (!$found && $family->canEdit()) { ?> <tr> - <td class="facts_labelblue"><?php echo $people["newwife"]->getLabel($elderdate); ?></td> - <td class="<?php echo $controller->getPersonStyle($people["newwife"]); ?>"> - <?php print_pedigree_person($people["newwife"], 2, 0, $personcount++); ?> - </td> + <td class="facts_label"><?php echo WT_I18N::translate('Add husband'); ?></td> + <td class="facts_value"><a href="#" onclick="return addnewspouse('<?php echo $family->getXref(); ?>', 'HUSB');"><?php echo WT_I18N::translate('Add a husband to this family'); ?></a></td> </tr> <?php } - //-- mother/wife - if (isset($people["wife"])) { + + ///// MARR ///// + $found = false; + foreach ($family->getFacts('MARR|_NMR') as $fact) { + $found |= !$fact->isOld(); + if ($fact->isNew()) { + $class = 'facts_label new'; + } elseif ($fact->isOld()) { + $class = 'facts_label old'; + } else { + $class = 'facts_label'; + } ?> <tr> - <td class="facts_label<?php echo $styleadd; ?>"><?php echo $people["wife"]->getLabel($elderdate); ?></td> - <td class="<?php echo $controller->getPersonStyle($people["wife"]); ?>"> - <?php print_pedigree_person($people["wife"], 2, 0, $personcount++); ?> + <td class="facts_label"> + + </td> + <td class="facts_value"> + <?php echo WT_Gedcom_Tag::getLabelValue($fact->getTag(), $fact->getPlace() . ' — ' . $fact->getDate()->Display(false)); ?> </td> </tr> <?php } - //-- missing mother - if ($type=="parents" && !isset($people["wife"]) && !isset($people["newwife"])) { - if ($controller->record->canEdit()) { - ?> - <tr> - <td class="facts_label"><?php echo WT_I18N::translate('Add a new mother'); ?></td> - <td class="facts_value"><a href="#" onclick="return addnewparentfamily('<?php echo $controller->record->getXref(); ?>', 'WIFE', '<?php echo $family->getXref(); ?>');"><?php echo WT_I18N::translate('Add a new mother'); ?></a></td> - </tr> - <?php - } - } - //-- missing wife - if ($type=="spouse" && !isset($people["wife"]) && !isset($people["newwife"])) { - if ($controller->record->canEdit()) { - ?> - <tr> - <td class="facts_label"><?php echo WT_I18N::translate('Add wife'); ?></td> - <td class="facts_value"><a href="#" onclick="return addnewspouse('<?php echo $family->getXref(); ?>', 'WIFE');"><?php echo WT_I18N::translate('Add a wife to this family'); ?></a></td> - </tr> - <?php - } - } - //-- marriage row - if ($family->getMarriageRecord()!="" || WT_USER_CAN_EDIT) { + if (!$found && $family->canEdit()) { + // Add a new marriage ?> <tr> <td class="facts_label"> </td> <td class="facts_value"> - <?php $marr_type = strtoupper($family->getMarriageType()); - if ($marr_type=='CIVIL' || $marr_type=='PARTNERS' || $marr_type=='RELIGIOUS' || $marr_type=='UNKNOWN') { - $marr_fact = 'MARR_' . $marr_type; - } else { - $marr_fact = 'MARR'; - } - $famid = $family->getXref(); - $place = $family->getMarriagePlace(); - $date = $family->getMarriageDate(); - if ($date && $date->isOK() || $place) { - if ($date) { - $details=$date->Display(false); - } - if ($place) { - if ($details) { - $details .= ' — '; - } - $tmp=new WT_Place($place, WT_GED_ID); - $details .= $tmp->getShortName(); - } - echo WT_Gedcom_Tag::getLabelValue('MARR', $details); - } else if (get_sub_record(1, "1 _NMR", find_family_record($famid, WT_GED_ID))) { - $husb = $family->getHusband(); - $wife = $family->getWife(); - if (empty($wife) && !empty($husb)) { - echo WT_Gedcom_Tag::getLabel('_NMR', $husb); - } elseif (empty($husb) && !empty($wife)) { - echo WT_Gedcom_Tag::getLabel('_NMR', $wife); - } else { - echo WT_Gedcom_Tag::getLabel('_NMR'); - } - } else if ($family->getMarriageRecord()=="" && $controller->record->canEdit()) { - echo "<a href=\"#\" onclick=\"return add_new_record('".$famid."', 'MARR');\">".WT_I18N::translate('Add marriage details')."</a>"; - } else { - echo WT_Gedcom_Tag::getLabelValue($marr_fact, WT_I18N::translate('yes')); - } - ?> + <a href="#" onclick="return add_new_record('<?php echo $family->getXref(); ?>', 'MARR');"> + <?php echo WT_I18N::translate('Add marriage details'); ?> + </a> </td> </tr> <?php } - } - - /** - * print children informations - * @param Family family - * @param Array people - * @param String family type - * @return html table rows - */ - function printChildrenRows($family, $people, $type) { - global $personcount, $controller; - $elderdate = $family->getMarriageDate(); - $key=0; - foreach ($people["children"] as $child) { - $label = $child->getLabel(); - $styleadd = ""; + ///// WIFE ///// + $found = false; + foreach ($family->getFacts('WIFE') as $fact) { + $found |= !$fact->isOld(); + if ($fact->isNew()) { + $class = 'facts_label new'; + } elseif ($fact->isOld()) { + $class = 'facts_label old'; + } else { + $class = 'facts_label'; + } + $person = $fact->getTarget(); + if ($person->equals($controller->record)) { + $label = '<i class="icon-selected"></i>'; + } else { + $label = get_relationship_name(get_relationship($controller->record, $person, true, 3)); + } ?> <tr> - <td class="facts_label<?php echo $styleadd; ?>"><?php if ($styleadd=="red") echo $child->getLabel(); else echo $child->getLabel($elderdate, $key+1); ?></td> - <td class="<?php echo $controller->getPersonStyle($child); ?>"> - <?php - print_pedigree_person($child, 2, 0, $personcount++); - ?> + <td class="<?php echo $class; ?>"> + <?php echo $label; ?> + </td> + <td class="<?php echo $controller->getPersonStyle($person); ?>"> + <?php print_pedigree_person($person, 2, 0, $personcount++); ?> </td> </tr> <?php - $elderdate = $child->getBirthDate(); - ++$key; } - foreach ($people["newchildren"] as $child) { - $label = $child->getLabel(); - $styleadd = "blue"; + if (!$found && $family->canEdit()) { ?> <tr> - <td class="facts_label<?php echo $styleadd; ?>"><?php if ($styleadd=="red") echo $child->getLabel(); else echo $child->getLabel($elderdate, $key+1); ?></td> - <td class="<?php echo $controller->getPersonStyle($child); ?>"> - <?php - print_pedigree_person($child, 2, 0, $personcount++); - ?> - </td> + <td class="facts_label"><?php echo WT_I18N::translate('Add wife'); ?></td> + <td class="facts_value"><a href="#" onclick="return addnewspouse('<?php echo $family->getXref(); ?>', 'WIFE');"><?php echo WT_I18N::translate('Add a wife to this family'); ?></a></td> </tr> <?php - $elderdate = $child->getBirthDate(); - ++$key; } - foreach ($people["delchildren"] as $child) { - $label = $child->getLabel(); - $styleadd = "red"; + + ///// CHIL ///// + foreach ($family->getFacts('CHIL') as $fact) { + if ($fact->isNew()) { + $class = 'facts_label new'; + } elseif ($fact->isOld()) { + $class = 'facts_label old'; + } else { + $class = 'facts_label'; + } + $person = $fact->getTarget(); + if ($person->equals($controller->record)) { + $label = '<i class="icon-selected"></i>'; + } else { + $label = get_relationship_name(get_relationship($controller->record, $person, true, 3)); + } ?> <tr> - <td class="facts_label<?php echo $styleadd; ?>"><?php if ($styleadd=="red") echo $child->getLabel(); else echo $child->getLabel($elderdate, $key+1); ?></td> - <td class="<?php echo $controller->getPersonStyle($child); ?>"> - <?php - print_pedigree_person($child, 2, 0, $personcount++); - ?> + <td class="<?php echo $class; ?>"> + <?php echo $label; ?> + </td> + <td class="<?php echo $controller->getPersonStyle($person); ?>"> + <?php print_pedigree_person($person, 2, 0, $personcount++); ?> </td> </tr> <?php - $elderdate = $child->getBirthDate(); - ++$key; } - if (isset($family) && $controller->record->canEdit()) { - if ($type == "spouse") { + // Re-order children / add a new child + if ($family->canEdit()) { + if ($type == 'FAMS') { $child_u = WT_I18N::translate('Add a new son or daughter'); $child_m = WT_I18N::translate('son'); $child_f = WT_I18N::translate('daughter'); @@ -282,10 +217,10 @@ class relatives_WT_Module extends WT_Module implements WT_Module_Tab { $child_m = WT_I18N::translate('brother'); $child_f = WT_I18N::translate('sister'); } - ?> + ?> <tr> <td class="facts_label"> - <?php if (WT_USER_CAN_EDIT && isset($people["children"][1])) { ?> + <?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 WT_I18N::translate('Re-order children'); ?></a> <?php } ?> </td> @@ -299,6 +234,10 @@ class relatives_WT_Module extends WT_Module implements WT_Module_Tab { </tr> <?php } + + echo '</table>'; + + return; } // Implement WT_Module_Tab @@ -320,60 +259,38 @@ class relatives_WT_Module extends WT_Module implements WT_Module_Tab { <?php $personcount=0; $families = $controller->record->getChildFamilies(); - if (count($families)==0) { - if ($controller->record->canEdit()) { - ?> - <table class="facts_table"> - <tr> - <td class="facts_value"><a href="#" onclick="return addnewparent('<?php echo $controller->record->getXref(); ?>', 'HUSB');"><?php echo WT_I18N::translate('Add a new father'); ?></td> - </tr> - <tr> - <td class="facts_value"><a href="#" onclick="return addnewparent('<?php echo $controller->record->getXref(); ?>', 'WIFE');"><?php echo WT_I18N::translate('Add a new mother'); ?></a></td> - </tr> - </table> - <?php - } + if (!$families && $controller->record->canEdit()) { + ?> + <table class="facts_table"> + <tr> + <td class="facts_value"><a href="#" onclick="return addnewparent('<?php echo $controller->record->getXref(); ?>', 'HUSB');"><?php echo WT_I18N::translate('Add a new father'); ?></td> + </tr> + <tr> + <td class="facts_value"><a href="#" onclick="return addnewparent('<?php echo $controller->record->getXref(); ?>', 'WIFE');"><?php echo WT_I18N::translate('Add a new mother'); ?></a></td> + </tr> + </table> + <?php } // parents foreach ($families as $family) { - $people = $controller->buildFamilyList($family, "parents"); - $this->printFamilyHeader($family->getHtmlUrl(), $controller->record->getChildFamilyLabel($family)); - echo '<table class="facts_table">'; - $this->printParentsRows($family, $people, "parents"); - $this->printChildrenRows($family, $people, "parents"); - echo '</table>'; + $this->printFamily($family, 'FAMC', $controller->record->getChildFamilyLabel($family)); } // step-parents foreach ($controller->record->getChildStepFamilies() as $family) { - $people = $controller->buildFamilyList($family, "step-parents"); - $this->printFamilyHeader($family->getHtmlUrl(), $controller->record->getStepFamilyLabel($family)); - echo '<table class="facts_table">'; - $this->printParentsRows($family, $people, "parents"); - $this->printChildrenRows($family, $people, "parents"); - echo '</table>'; + $this->printFamily($family, 'FAMC', $controller->record->getStepFamilyLabel($family)); } // spouses $families = $controller->record->getSpouseFamilies(); foreach ($families as $family) { - $people = $controller->buildFamilyList($family, "spouse"); - $this->printFamilyHeader($family->getHtmlUrl(), $controller->record->getSpouseFamilyLabel($family)); - echo '<table class="facts_table">'; - $this->printParentsRows($family, $people, "spouse"); - $this->printChildrenRows($family, $people, "spouse"); - echo '</table>'; + $this->printFamily($family, 'FAMS', $controller->record->getSpouseFamilyLabel($family)); } // step-children foreach ($controller->record->getSpouseStepFamilies() as $family) { - $people = $controller->buildFamilyList($family, "step-children"); - $this->printFamilyHeader($family->getHtmlUrl(), $family->getFullName()); - echo '<table class="facts_table">'; - $this->printParentsRows($family, $people, "spouse"); - $this->printChildrenRows($family, $people, "spouse"); - echo '</table>'; + $this->printFamily($family, 'FAMS', $family->getFullName()); } if (!$SHOW_AGE_DIFF) { @@ -407,11 +324,6 @@ class relatives_WT_Module extends WT_Module implements WT_Module_Tab { <a href="#" onclick="return linkspouse('<?php echo $controller->record->getXref(); ?>','WIFE');"><?php echo WT_I18N::translate('Add a wife using an existing person'); ?></a> </td> </tr> - <tr> - <td class="facts_value"> - <a href="#" onclick="return add_fams('<?php echo $controller->record->getXref(); ?>','HUSB');"><?php echo WT_I18N::translate('Link this person to an existing family as a husband'); ?></a> - </td> - </tr> <?php } if ($controller->record->getSex()!="M") { ?> <tr> @@ -424,11 +336,6 @@ class relatives_WT_Module extends WT_Module implements WT_Module_Tab { <a href="#" onclick="return linkspouse('<?php echo $controller->record->getXref(); ?>','HUSB');"><?php echo WT_I18N::translate('Add a husband using an existing person'); ?></a> </td> </tr> - <tr> - <td class="facts_value"> - <a href="#" onclick="return add_fams('<?php echo $controller->record->getXref(); ?>','WIFE');"><?php echo WT_I18N::translate('Link this person to an existing family as a wife'); ?></a> - </td> - </tr> <?php } ?> <tr> <td class="facts_value"> diff --git a/modules_v3/review_changes/module.php b/modules_v3/review_changes/module.php index 3d6e3206c2..e09f2a413a 100644 --- a/modules_v3/review_changes/module.php +++ b/modules_v3/review_changes/module.php @@ -119,7 +119,7 @@ class review_changes_WT_Module extends WT_Module implements WT_Module_Block { )->execute(array(WT_GED_ID))->fetchAll(); foreach ($changes as $change) { $record=WT_GedcomRecord::getInstance($change->xref); - if ($record->canDisplayDetails()) { + if ($record->canShow()) { $content.='<b>'.$record->getFullName().'</b>'; $content.=$block ? '<br>' : ' '; $content.='<a href="'.$record->getHtmlUrl().'">'.WT_I18N::translate('View the changes').'</a>'; diff --git a/modules_v3/sitemap/module.php b/modules_v3/sitemap/module.php index 35c70ba21c..51072b398e 100644 --- a/modules_v3/sitemap/module.php +++ b/modules_v3/sitemap/module.php @@ -130,67 +130,67 @@ class sitemap_WT_Module extends WT_Module implements WT_Module_Config { switch ($rec_type) { case 'i': $rows=WT_DB::prepare( - "SELECT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec". + "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom". " FROM `##individuals`". " WHERE i_file=?". " ORDER BY i_id". " LIMIT ".self::RECORDS_PER_VOLUME." OFFSET ".($volume*self::RECORDS_PER_VOLUME) - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - $records[]=WT_Person::getInstance($row); + $records[]=WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } break; case 's': $rows=WT_DB::prepare( - "SELECT 'SOUR' AS type, s_id AS xref, s_file AS ged_id, s_gedcom AS gedrec". + "SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom". " FROM `##sources`". " WHERE s_file=?". " ORDER BY s_id". " LIMIT ".self::RECORDS_PER_VOLUME." OFFSET ".($volume*self::RECORDS_PER_VOLUME) - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - $records[]=WT_Source::getInstance($row); + $records[]=WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } break; case 'r': $rows=WT_DB::prepare( - "SELECT 'REPO' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec". + "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". " FROM `##other`". " WHERE o_file=? AND o_type='REPO'". " ORDER BY o_id". " LIMIT ".self::RECORDS_PER_VOLUME." OFFSET ".($volume*self::RECORDS_PER_VOLUME) - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - $records[]=WT_Repository::getInstance($row); + $records[]=WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } break; case 'n': $rows=WT_DB::prepare( - "SELECT 'NOTE' AS type, o_id AS xref, o_file AS ged_id, o_gedcom AS gedrec". + "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom". " FROM `##other`". " WHERE o_file=? AND o_type='NOTE'". " ORDER BY o_id". " LIMIT ".self::RECORDS_PER_VOLUME." OFFSET ".($volume*self::RECORDS_PER_VOLUME) - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - $records[]=WT_Note::getInstance($row); + $records[]=WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } break; case 'm': $rows=WT_DB::prepare( - "SELECT 'OBJE' AS type, m_id AS xref, m_file AS ged_id, m_gedcom AS gedrec, m_titl, m_filename". + "SELECT m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom". " FROM `##media`". " WHERE m_file=?". " ORDER BY m_id". " LIMIT ".self::RECORDS_PER_VOLUME." OFFSET ".($volume*self::RECORDS_PER_VOLUME) - )->execute(array($ged_id))->fetchAll(PDO::FETCH_ASSOC); + )->execute(array($ged_id))->fetchAll(); foreach ($rows as $row) { - $records[]=WT_Media::getInstance($row); + $records[]=WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom); } break; } foreach ($records as $record) { - if ($record->canDisplayName()) { + if ($record->canShowName()) { $data.='<url>'; $data.='<loc>'.WT_SERVER_NAME.WT_SCRIPT_PATH.$record->getHtmlUrl().'</loc>'; $chan=$record->getChangeEvent(); diff --git a/modules_v3/sources_tab/module.php b/modules_v3/sources_tab/module.php index da493e3b50..d1644cf362 100644 --- a/modules_v3/sources_tab/module.php +++ b/modules_v3/sources_tab/module.php @@ -29,6 +29,8 @@ if (!defined('WT_WEBTREES')) { } class sources_tab_WT_Module extends WT_Module implements WT_Module_Tab { + private $facts; + // Extend WT_Module public function getTitle() { return /* I18N: Name of a module */ WT_I18N::translate('Sources'); @@ -44,49 +46,60 @@ class sources_tab_WT_Module extends WT_Module implements WT_Module_Tab { return 30; } - protected $sourceCount = null; + // Implement WT_Module_Tab + public function hasTabContent() { + return WT_USER_CAN_EDIT || $this->get_facts(); + } // Implement WT_Module_Tab + public function isGrayedOut() { + return !$this->get_facts(); + } + // Implement WT_Module_Tab public function getTabContent() { global $SHOW_LEVEL2_NOTES, $NAV_SOURCES, $controller; ob_start(); + echo '<table class="facts_table">'; + ?> + <tr> + <td colspan="2" class="descriptionbox rela"> + <input id="checkbox_sour2" type="checkbox" <?php if ($SHOW_LEVEL2_NOTES) echo " checked=\"checked\""; ?> onclick="jQuery('tr.row_sour2').toggle();"> + <label for="checkbox_sour2"><?php echo WT_I18N::translate('Show all sources'), help_link('show_fact_sources'); ?></label> + </td> + </tr> + <?php + foreach ($this->get_facts() as $fact) { + if ($fact->getTag() == 'SOUR') { + print_main_sources($fact, 1); + } else { + for ($i=2; $i<4; ++$i) { + print_main_sources($fact, $i); + } + } + } + if (!$this->get_facts()) { + echo '<tr><td id="no_tab4" colspan="2" class="facts_value">', WT_I18N::translate('There are no Source citations for this individual.'), '</td></tr>'; + } + + // New Source Link + if ($controller->record->canEdit()) { ?> - <table class="facts_table"> <tr> - <td colspan="2" class="descriptionbox rela"> - <input id="checkbox_sour2" type="checkbox" <?php if ($SHOW_LEVEL2_NOTES) echo " checked=\"checked\""; ?> onclick="jQuery('tr.row_sour2').toggle();"> - <label for="checkbox_sour2"><?php echo WT_I18N::translate('Show all sources'), help_link('show_fact_sources'); ?></label> + <td class="facts_label"> + <?php echo WT_Gedcom_Tag::getLabel('SOUR'); ?> </td> - </tr> - <?php - $otheritems = $controller->getOtherFacts(); - foreach ($otheritems as $event) { - if ($event->getTag()=='SOUR') { - print_main_sources($event, 1); - } - } - // 2nd level sources [ 1712181 ] - $controller->record->add_family_facts(false); - foreach ($controller->getIndiFacts() as $event) { - print_main_sources($event, 2); - } - if ($this->get_source_count()==0) echo "<tr><td id=\"no_tab3\" colspan=\"2\" class=\"facts_value\">".WT_I18N::translate('There are no Source citations for this individual.')."</td></tr>"; - //-- New Source Link - if ($controller->record->canEdit()) { - ?> - <tr> - <td class="facts_label"><?php echo WT_Gedcom_Tag::getLabel('SOUR'); ?></td> - <td class="facts_value"> - <a href="#" onclick="add_new_record('<?php echo $controller->record->getXref(); ?>','SOUR'); return false;"><?php echo WT_I18N::translate('Add a new source citation'); ?></a> + <td class="facts_value"> + <a href="#" onclick="add_new_record('<?php echo $controller->record->getXref(); ?>','SOUR'); return false;"> + <?php echo WT_I18N::translate('Add a new source citation'); ?> + </a> <?php echo help_link('add_source'); ?> - </td> - </tr> + </td> + </tr> <?php - } + } ?> </table> - <br> <?php if (!$SHOW_LEVEL2_NOTES) { echo '<script>jQuery("tr.row_sour2").toggle();</script>'; @@ -94,27 +107,29 @@ class sources_tab_WT_Module extends WT_Module implements WT_Module_Tab { return '<div id="'.$this->getName().'_content">'.ob_get_clean().'</div>'; } - function get_source_count() { + function get_facts() { global $controller; - if ($this->sourceCount===null) { - $ct = preg_match_all("/\d SOUR @(.*)@/", $controller->record->getGedcomRecord(), $match, PREG_SET_ORDER); - foreach ($controller->record->getSpouseFamilies() as $sfam) - $ct += preg_match("/\d SOUR /", $sfam->getGedcomRecord()); - $this->sourceCount = $ct; + if ($this->facts === null) { + $facts = $controller->record->getFacts(); + foreach ($controller->record->getSpouseFamilies() as $family) { + if ($family->canShow()) { + foreach ($family->getFacts() as $fact) { + $facts[] = $fact; } - return $this->sourceCount; + } + } + $this->facts = array(); + foreach ($facts as $fact) { + if (preg_match('/(?:^1|\n\d) SOUR/', $fact->getGedcom())) { + $this->facts[] = $fact; + } + } + } + return $this->facts; } // Implement WT_Module_Tab - public function hasTabContent() { - return WT_USER_CAN_EDIT || $this->get_source_count()>0; - } - // Implement WT_Module_Tab - public function isGrayedOut() { - return $this->get_source_count()==0; - } - // Implement WT_Module_Tab public function canLoadAjax() { global $SEARCH_SPIDER; diff --git a/modules_v3/stories/module.php b/modules_v3/stories/module.php index c3e3d082ed..77dcb2ee20 100644 --- a/modules_v3/stories/module.php +++ b/modules_v3/stories/module.php @@ -252,7 +252,7 @@ class stories_WT_Module extends WT_Module implements WT_Module_Block, WT_Module_ echo '<input type="text" name="xref" id="pid" size="4" value="'.$xref.'">'; echo print_findindi_link('pid'); if ($xref) { - $person=WT_Person::getInstance($xref); + $person=WT_Individual::getInstance($xref); if ($person) { echo ' ', $person->format_list('span'); } @@ -355,7 +355,7 @@ class stories_WT_Module extends WT_Module implements WT_Module_Block, WT_Module_ echo '<tbody>'; foreach ($stories as $story) { $story_title = get_block_setting($story->block_id, 'title'); - $indi=WT_Person::getInstance($story->xref); + $indi=WT_Individual::getInstance($story->xref); if ($indi) { echo '<tr><td><a href="', $indi->getHtmlUrl().'#stories">', $story_title, '<a></td> <td><a href="', $indi->getHtmlUrl().'#stories">'.$indi->getFullName(), '</a></td>'; @@ -417,12 +417,12 @@ class stories_WT_Module extends WT_Module implements WT_Module_Block, WT_Module_ </tr></thead> <tbody>'; foreach ($stories as $story) { - $indi=WT_Person::getInstance($story->xref); + $indi=WT_Individual::getInstance($story->xref); $story_title = get_block_setting($story->block_id, 'title'); $languages=get_block_setting($story->block_id, 'languages'); if (!$languages || in_array(WT_LOCALE, explode(',', $languages))) { if ($indi) { - if ($indi->canDisplayDetails()) { + if ($indi->canShow()) { echo '<tr><td><a href="'.$indi->getHtmlUrl().'#stories">'.$story_title.'</a></td><td><a href="'.$indi->getHtmlUrl().'#stories">'.$indi->getFullName().'</a></td></tr>'; } } else { diff --git a/modules_v3/todo/module.php b/modules_v3/todo/module.php index 3ccb2f21ac..21b919c3fd 100644 --- a/modules_v3/todo/module.php +++ b/modules_v3/todo/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -105,7 +105,7 @@ class todo_WT_Module extends WT_Module implements WT_Module_Block { $end_jd=$show_future ? 99999999 : WT_CLIENT_JD; foreach (get_calendar_events(0, $end_jd, '_TODO', WT_GED_ID) as $todo) { $record=WT_GedcomRecord::getInstance($todo['id']); - if ($record && $record->canDisplayDetails()) { + if ($record && $record->canShow()) { $user_name = preg_match('/\n2 _WT_USER (.+)/', $todo['factrec'], $match) ? $match[1] : ''; if ($user_name==WT_USER_NAME || !$user_name && $show_unassigned || $user_name && $show_other) { $content.='<tr>'; diff --git a/modules_v3/top10_pageviews/module.php b/modules_v3/top10_pageviews/module.php index 54891ebe87..d0bbc7595c 100644 --- a/modules_v3/top10_pageviews/module.php +++ b/modules_v3/top10_pageviews/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay @@ -80,7 +80,7 @@ class top10_pageviews_WT_Module extends WT_Module implements WT_Module_Block { } foreach ($top10 as $id=>$count) { $record=WT_GedcomRecord::getInstance($id); - if ($record && $record->canDisplayDetails()) { + if ($record && $record->canShow()) { $content .= '<tr valign="top">'; if ($count_placement=='before') { $content .= '<td dir="ltr" align="right">['.$count.']</td>'; diff --git a/modules_v3/top10_surnames/module.php b/modules_v3/top10_surnames/module.php index 5a9e8d1620..63a4b7622f 100644 --- a/modules_v3/top10_surnames/module.php +++ b/modules_v3/top10_surnames/module.php @@ -2,7 +2,7 @@ // Classes and libraries for module system // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2010 John Finlay diff --git a/modules_v3/tree/class_treeview.php b/modules_v3/tree/class_treeview.php index 07065fbdf8..81cb5ef422 100644 --- a/modules_v3/tree/class_treeview.php +++ b/modules_v3/tree/class_treeview.php @@ -55,7 +55,7 @@ class TreeView { * @param string $rootPersonId the id of the root person * @param int $generations number of generations to draw */ - public function drawViewport(WT_Person $rootPerson, $generations) { + public function drawViewport(WT_Individual $rootPerson, $generations) { global $GEDCOM, $controller; if (WT_SCRIPT_NAME == 'individual.php') { @@ -118,7 +118,7 @@ class TreeView { */ public function getDetails($pid) { - $person = WT_Person::getInstance($pid); + $person = WT_Individual::getInstance($pid); $r = $this->getPersonDetails($person, $person, null); foreach ($person->getSpouseFamilies() as $family) { if (!empty($family)) { @@ -309,7 +309,7 @@ class TreeView { /** * Draw a person name preceded by sex icon, with parents as tooltip - * @param WT_Person $p a person + * @param WT_Individual $p a person * @param $dashed if = 'dashed' print dashed top border to separate multiple spuses */ private function drawPersonName($p, $dashed='') { diff --git a/modules_v3/user_blog/module.php b/modules_v3/user_blog/module.php index 74af7cad48..4eaf49915a 100644 --- a/modules_v3/user_blog/module.php +++ b/modules_v3/user_blog/module.php @@ -86,8 +86,7 @@ class user_blog_WT_Module extends WT_Module implements WT_Module_Block { $content .= "<div class=\"news_date\">".format_timestamp($news['date']).'</div>'; if ($news["text"]==strip_tags($news["text"])) { // No HTML? - // PHP5.3 $news["text"]=nl2br($news["text"], false); - $news["text"]=nl2br($news["text"]); + $news["text"]=nl2br($news["text"], false); } $content .= $news["text"]."<br><br>"; $content .= "<a href=\"#\" onclick=\"window.open('editnews.php?news_id='+".$key.", '_blank', indx_window_specs); return false;\">".WT_I18N::translate('Edit')."</a> | "; diff --git a/modules_v3/user_favorites/module.php b/modules_v3/user_favorites/module.php index 662a359678..deb741f806 100644 --- a/modules_v3/user_favorites/module.php +++ b/modules_v3/user_favorites/module.php @@ -67,10 +67,10 @@ class user_favorites_WT_Module extends gedcom_favorites_WT_Module { case 'menu-add-favorite': // Process the "add to user favorites" menu item on indi/fam/etc. pages $record=WT_GedcomRecord::getInstance(safe_POST_xref('xref')); - if (WT_USER_ID && $record->canDisplayName()) { + if (WT_USER_ID && $record->canShowName()) { self::addFavorite(array( 'user_id' =>WT_USER_ID, - 'gedcom_id'=>$record->getGedId(), + 'gedcom_id'=>$record->getGedcomId(), 'gid' =>$record->getXref(), 'type' =>$record::RECORD_TYPE, 'url' =>null, diff --git a/modules_v3/user_messages/module.php b/modules_v3/user_messages/module.php index f9025b6dd7..95f304565e 100644 --- a/modules_v3/user_messages/module.php +++ b/modules_v3/user_messages/module.php @@ -109,8 +109,7 @@ class user_messages_WT_Module extends WT_Module implements WT_Module_Block { $content.='</td>'; $content.='</tr>'; $content.='<tr><td class="list_value_wrap" colspan="5"><div id="message'.$message->message_id.'" style="display:none;">'; - // PHP5.3 $content.=expand_urls(nl2br(htmlspecialchars($message->body), false)).'<br><br>'; - $content.=expand_urls(nl2br(htmlspecialchars($message->body))).'<br><br>'; + $content.=expand_urls(nl2br(htmlspecialchars($message->body), false)).'<br><br>'; if (strpos($message->subject, /* I18N: When replying to an email, the subject becomes “RE: <subject>” */ WT_I18N::translate('RE: '))!==0) { $message->subject= WT_I18N::translate('RE: ').$message->subject; } @@ -30,9 +30,9 @@ require_once WT_ROOT.'includes/functions/functions_print_lists.php'; $controller=new WT_Controller_Note(); -if ($controller->record && $controller->record->canDisplayDetails()) { +if ($controller->record && $controller->record->canShow()) { $controller->pageHeader(); - if ($controller->record->isMarkedDeleted()) { + if ($controller->record->isOld()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -50,7 +50,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { ' ', help_link('pending_changes'), '</p>'; } - } elseif (find_updated_record($controller->record->getXref(), WT_GED_ID)!==null) { + } elseif ($controller->record->isNew()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -80,7 +80,7 @@ $linkToID=$controller->record->getXref(); // Tell addmedia.php what to link to $controller ->addInlineJavascript('function show_gedcom_record() {var recwin=window.open("gedrecord.php?pid=' . $controller->record->getXref() . '", "_blank", edit_window_specs);}') - ->addInlineJavascript('function edit_note() {var win04 = window.open("edit_interface.php?action=editnote&pid=' . $linkToID . '", "win04", edit_window_specs);if (window.focus) {win04.focus();}}') + ->addInlineJavascript('function edit_note() {var win04 = window.open("edit_interface.php?action=editnote&xref=' . $linkToID . '", "win04", edit_window_specs);if (window.focus) {win04.focus();}}') ->addInlineJavascript('jQuery("#note-tabs").tabs();') ->addInlineJavascript('jQuery("#note-tabs").css("visibility", "visible");'); @@ -89,87 +89,85 @@ $linked_fam = $controller->record->fetchLinkedFamilies(); $linked_obje = $controller->record->fetchLinkedMedia(); $linked_sour = $controller->record->fetchLinkedSources(); -echo '<div id="note-details">'; -echo '<h2>', $controller->record->getFullName(), '</h2>'; -echo '<div id="note-tabs"> - <ul> - <li><a href="#note-edit"><span>', WT_I18N::translate('Details'), '</span></a></li>'; - if ($linked_indi) { - echo '<li><a href="#indi-note"><span id="indisource">', WT_I18N::translate('Individuals'), '</span></a></li>'; - } - if ($linked_fam) { - echo '<li><a href="#fam-note"><span id="famsource">', WT_I18N::translate('Families'), '</span></a></li>'; - } - if ($linked_obje) { - echo '<li><a href="#media-note"><span id="mediasource">', WT_I18N::translate('Media objects'), '</span></a></li>'; - } - if ($linked_sour) { - echo '<li><a href="#source-note"><span id="notesource">', WT_I18N::translate('Sources'), '</span></a></li>'; - } - echo '</ul>'; - - // Shared Note details --------------------- - $noterec=$controller->record->getGedcomRecord(); - preg_match("/0 @".$controller->record->getXref()."@ NOTE(.*)/", $noterec, $n1match); - $note = print_note_record("<br>".$n1match[1], 1, $noterec, false, true, true); - - echo '<div id="note-edit">'; - echo '<table class="facts_table">'; - echo '<tr><td align="left" class="descriptionbox">'; - if (WT_USER_CAN_EDIT) { - echo '<a href="#" onclick="edit_note()" title="', WT_I18N::translate('Edit'), '">'; - echo '<i class="icon-note"></i>'; - echo WT_I18N::translate('Shared note'), '</a>'; - echo '<div class="editfacts">'; - echo '<div class="editlink"><a class="editicon" href="#" onclick="edit_note()" title="', WT_I18N::translate('Edit'), '"><span class="link_text">', WT_I18N::translate('Edit'), '</span></div></a>'; - echo '</div>'; - } else { - echo '<i class="icon-note"></i>'; - echo WT_I18N::translate('Shared note'); - } - echo '</td><td class="optionbox wrap width80">'; - echo $note; - echo "<br>"; - echo "</td></tr>"; +$facts = array(); +foreach ($controller->record->getFacts() as $fact) { + if ($fact->getTag() != 'CONT') { + $facts[] = $fact; + } +} - $notefacts=$controller->record->getFacts(); - foreach ($notefacts as $fact) { - if ($fact->getTag()!='CONT') { +?> +<div id="note-details"> + <h2><?php echo $controller->record->getFullName(); ?></h2> + <div id="note-tabs"> + <ul> + <li><a href="#note-edit"><span><?php echo WT_I18N::translate('Details'); ?></span></a></li> + <?php if ($linked_indi) { ?> + <li><a href="#indi-note"><span id="indisource"><?php echo WT_I18N::translate('Individuals'); ?></span></a></li> + <?php } ?> + <?php if ($linked_fam) { ?> + <li><a href="#fam-note"><span id="famsource"><?php echo WT_I18N::translate('Families'); ?>/span></a></li> + <?php } ?> + <?php if ($linked_obje) { ?> + echo '<li><a href="#media-note"><span id="mediasource"><?php echo WT_I18N::translate('Media objects'); ?></span></a></li> + <?php } ?> + <?php if ($linked_sour) { ?> + echo '<li><a href="#source-note"><span id="notesource"><?php echo WT_I18N::translate('Sources'); ?></span></a></li> + <?php } ?> + </ul> + <div id="note-edit"> + <table class="facts_table"> + <tr> + <td align="left" class="descriptionbox"> + <?php if (WT_USER_CAN_EDIT) { ?> + <a href="#" onclick="edit_note()" title="<?php echo WT_I18N::translate('Edit'); ?>"> + <i class="icon-note"></i> <?php echo WT_I18N::translate('Shared note'); ?> + </a> + <div class="editfacts"> + <div class="editlink"> + <a class="editicon" href="#" onclick="edit_note()" title="<?php echo WT_I18N::translate('Edit'); ?>"> + <span class="link_text">', WT_I18N::translate('Edit'), '</span> + </a> + </div> + <?php } else { ?> + <i class="icon-note"></i> + <?php echo WT_I18N::translate('Shared note'); ?> + <?php } ?> + </td> + <td class="optionbox wrap width80" style="white-space: pre-wrap;"><?php echo $controller->record->getNote(); ?></td> + </tr> + <?php + foreach ($facts as $fact) { print_fact($fact, $controller->record); } - } - // Print media - print_main_media($controller->record->getXref()); - // new fact link - if ($controller->record->canEdit()) { - print_add_new_fact($controller->record->getXref(), $notefacts, 'NOTE'); - } - echo '</table> - </div>'; // close "note-edit" - - // Individuals linked to this shared note + print_main_media($controller->record->getXref()); + if ($controller->record->canEdit()) { + print_add_new_fact($controller->record->getXref(), $facts, 'NOTE'); + } + ?> + </table> + </div> +<?php if ($linked_indi) { echo '<div id="indi-note">'; echo format_indi_table($controller->record->fetchLinkedIndividuals(), $controller->record->getFullName()); - echo '</div>'; //close "indi-note" + echo '</div>'; } - // Families linked to this shared note if ($linked_fam) { echo '<div id="fam-note">'; echo format_fam_table($controller->record->fetchLinkedFamilies(), $controller->record->getFullName()); - echo '</div>'; //close "fam-note" + echo '</div>'; } - // Media Items linked to this shared note if ($linked_obje) { echo '<div id="media-note">'; echo format_media_table($controller->record->fetchLinkedMedia(), $controller->record->getFullName()); - echo '</div>'; //close "media-note" + echo '</div>'; } - // Sources linked to this shared note if ($linked_sour) { echo '<div id="source-note">'; echo format_sour_table($controller->record->fetchLinkedSources(), $controller->record->getFullName()); - echo '</div>'; //close "source-note" + echo '</div>'; } -echo '</div>'; //close div "note-tabs" -echo '</div>'; //close div "note-details" +?> + </div> +</div> diff --git a/pedigree.php b/pedigree.php index e1348e3dad..5a88cec160 100644 --- a/pedigree.php +++ b/pedigree.php @@ -2,7 +2,7 @@ // View for the pedigree tree. // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -110,7 +110,7 @@ for ($i=($controller->treesize-1); $i>=0; $i--) { $iref = $i; } // Can we go back to an earlier generation? - $can_go_back=$curgen==1 && WT_Person::getInstance($controller->treeid[$i]) && WT_Person::getInstance($controller->treeid[$i])->getChildFamilies(); + $can_go_back=$curgen==1 && WT_Individual::getInstance($controller->treeid[$i]) && WT_Individual::getInstance($controller->treeid[$i])->getChildFamilies(); if ($talloffset == 2) { // oldest at top echo '<div id="uparrow" dir="'; @@ -141,7 +141,7 @@ for ($i=($controller->treesize-1); $i>=0; $i--) { if (($talloffset == 3) && ($curgen ==2)) {$yoffset +=10;} echo $xoffset, "px; top:", $yoffset, "px; width:", ($controller->pbwidth), "px; height:", $controller->pbheight, "px; z-index:", $zindex, ";\">"; if (!isset($controller->treeid[$i])) {$controller->treeid[$i] = false;} - print_pedigree_person(WT_Person::getInstance($controller->treeid[$i]), 1, $iref, 1); + print_pedigree_person(WT_Individual::getInstance($controller->treeid[$i]), 1, $iref, 1); if ($can_go_back) { $did = 1; if ($i > (int)($controller->treesize/2) + (int)($controller->treesize/4)) { diff --git a/placelist.php b/placelist.php index 5c75015b37..0d48359e98 100644 --- a/placelist.php +++ b/placelist.php @@ -204,8 +204,8 @@ case 'hierarchy': foreach ($positions as $position) { $record=WT_GedcomRecord::getInstance($position); - if ($record && $record->canDisplayDetails()) { - if ($record instanceof WT_Person) { + if ($record && $record->canShow()) { + if ($record instanceof WT_Individual) { $myindilist[]=$record; } if ($record instanceof WT_Family) { diff --git a/relationship.php b/relationship.php index de1b464928..5c43ac4570 100644 --- a/relationship.php +++ b/relationship.php @@ -50,14 +50,14 @@ $Dbyspacing = 0; $Dbasexoffset = 0; $Dbaseyoffset = 0; -$person1=WT_Person::getInstance($pid1); -$person2=WT_Person::getInstance($pid2); +$person1=WT_Individual::getInstance($pid1); +$person2=WT_Individual::getInstance($pid2); $controller ->addInlineJavascript('var pastefield; function paste_id(value) { pastefield.value=value; }') // For the 'find indi' link ->addExternalJavascript(WT_STATIC_URL.'js/autocomplete.js'); -if ($person1 && $person1->canDisplayName() && $person2 && $person2->canDisplayName()) { +if ($person1 && $person1->canShowName() && $person2 && $person2->canShowName()) { $controller ->setPageTitle(WT_I18N::translate(/* I18N: %s are individual’s names */ 'Relationships between %1$s and %2$s', $person1->getFullName(), $person2->getFullName())) ->PageHeader(); @@ -30,9 +30,9 @@ require_once WT_ROOT.'includes/functions/functions_print_lists.php'; $controller=new WT_Controller_Repository(); -if ($controller->record && $controller->record->canDisplayDetails()) { +if ($controller->record && $controller->record->canShow()) { $controller->pageHeader(); - if ($controller->record->isMarkedDeleted()) { + if ($controller->record->isOld()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -50,7 +50,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { ' ', help_link('pending_changes'), '</p>'; } - } elseif (find_updated_record($controller->record->getXref(), WT_GED_ID)!==null) { + } elseif ($controller->record->isNew()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', diff --git a/search.php b/search.php index d0559042a2..f544318a82 100644 --- a/search.php +++ b/search.php @@ -2,7 +2,7 @@ // Searches based on user query. // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. diff --git a/site-offline.php b/site-offline.php index 73ad0ef240..946c43e45a 100644 --- a/site-offline.php +++ b/site-offline.php @@ -2,7 +2,7 @@ // Site Unavailable // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2103 webtrees development team. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/source.php b/source.php index 2ea14a98bd..1d15aa72d2 100644 --- a/source.php +++ b/source.php @@ -30,9 +30,9 @@ require_once WT_ROOT.'includes/functions/functions_print_lists.php'; $controller=new WT_Controller_Source(); -if ($controller->record && $controller->record->canDisplayDetails()) { +if ($controller->record && $controller->record->canShow()) { $controller->pageHeader(); - if ($controller->record->isMarkedDeleted()) { + if ($controller->record->isOld()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', @@ -50,7 +50,7 @@ if ($controller->record && $controller->record->canDisplayDetails()) { ' ', help_link('pending_changes'), '</p>'; } - } elseif (find_updated_record($controller->record->getXref(), WT_GED_ID)!==null) { + } elseif ($controller->record->isNew()) { if (WT_USER_CAN_ACCEPT) { echo '<p class="ui-state-highlight">', diff --git a/themes/clouds/header.php b/themes/clouds/header.php index 8a4ccb7493..3341ca92f9 100644 --- a/themes/clouds/header.php +++ b/themes/clouds/header.php @@ -79,6 +79,7 @@ if ($view!='simple') { // Use "simple" headers for popup windows '<div class="hsearch">', '<form style="display:inline;" action="search.php" method="post">', '<input type="hidden" name="action" value="general">', + '<input type="hidden" name="ged" value="', WT_GEDCOM, '">', '<input type="hidden" name="topsearch" value="yes">', '<input type="search" name="query" size="15" placeholder="', WT_I18N::translate('Search'), '" dir="auto">', '<input class="search-icon" type="image" src="', $WT_IMAGES['search'], '" alt="', WT_I18N::translate('Search'), '" title="', WT_I18N::translate('Search'), '">', diff --git a/themes/clouds/style.css b/themes/clouds/style.css index 225594275e..82ff1543c1 100644 --- a/themes/clouds/style.css +++ b/themes/clouds/style.css @@ -292,7 +292,6 @@ height: auto; #menu-fam-addfav {background-position:left -736px;} html[dir=rtl] #menu-fam-addfav {background-position:right -736px;} #menu-fam-change {background-position:left -759px;} html[dir=rtl] #menu-fam-change {background-position:right -759px;} #menu-fam-del {background-position:left -713px;} html[dir=rtl] #menu-fam-del {background-position:right -713px;} -#menu-fam-editraw {background-position:left -667px;} html[dir=rtl] #menu-fam-editraw {background-position:right -667px;} #menu-fam-orderchil {background-position:left -759px;} html[dir=rtl] #menu-fam-orderchil {background-position:right -759px;} /* Clipping Icons */ @@ -300,7 +299,6 @@ height: auto; #menu-clippingsadd {background-position:left -621px;} html[dir=rtl] #menu-clippingsadd {background-position:right -621px;} /* Edit Icons */ -#menu-indi-editraw {background-position:left -667px;} html[dir=rtl] #menu-indi-editraw {background-position:right -667px;} #menu-indi-addname {background-position:left -690px;} html[dir=rtl] #menu-indi-addname {background-position:right -690px;} #menu-indi-editsex {background-position:left -690px;} html[dir=rtl] #menu-indi-editsex {background-position:right -690px;} #menu-indi-del {background-position:left -713px;} html[dir=rtl] #menu-indi-del {background-position:right -713px;} @@ -310,13 +308,11 @@ height: auto; #menu-note-addfav {background-position:left -736px;} html[dir=rtl] #menu-note-fav {background-position:right -736px;} #menu-note-del {background-position:left -713px;} html[dir=rtl] #menu-note-del {background-position:right -713px;} #menu-note-edit {background-position:left -805px;} html[dir=rtl] #menu-note-edit {background-position:right -805px;} -#menu-note-editraw {background-position:left -667px;} html[dir=rtl] #menu-note-editraw {background-position:right -667px;} /* Objects */ #menu-obje-addfav {background-position:left -736px;} html[dir=rtl] #menu-obje-addfav {background-position:right -736px;} #menu-obje-del {background-position:left -713px;} html[dir=rtl] #menu-obje-del {background-position:right -713px;} #menu-obje-edit {background-position:left -852px;} html[dir=rtl] #menu-obje-edit {background-position:right -852px;} -#menu-obje-editraw {background-position:left -667px;} html[dir=rtl] #menu-obje-editraw {background-position:right -667px;} #menu-obje-link {background-position:left -875px;} html[dir=rtl] #menu-obje-link {background-position:right -875px;} #menu-obje-link-fam {background-position:left -437px;} html[dir=rtl] #menu-obje-link-fam {background-position:right -437px;} #menu-obje-link-indi {background-position:left -460px;} html[dir=rtl] #menu-obje-link-indi {background-position:right -460px;} @@ -326,13 +322,11 @@ height: auto; #menu-repo-addfav {background-position:left -736px;} html[dir=rtl] #menu-repo-addfav {background-position:right -736px;} #menu-repo-del {background-position:left -713px;} html[dir=rtl] #menu-repo-de {background-position:right -713px;} #menu-repo-edit {background-position:left -897px;} html[dir=rtl] #menu-repo-edit {background-position:right -897px;} -#menu-repo-editraw {background-position:left -667px;} html[dir=rtl] #menu-repo-editraw {background-position:right -667px;} /* Source */ #menu-sour-addfav {background-position:left -736px;} html[dir=rtl] #menu-sour-addfav {background-position:right -736px;} #menu-sour-del {background-position:left -713px;} html[dir=rtl] #menu-sour-del {background-position:right -713px;} #menu-sour-edit {background-position:left -782px;} html[dir=rtl] #menu-sour-edit {background-position:right -782px;} -#menu-sour-editraw {background-position:left -667px;} html[dir=rtl] #menu-sour-editraw {background-position:right -667px;} /* Stories */ #menu-story-sub {background-position:left -920px;} html[dir=rtl] #menu-story-sub {background-position:right -920px;} @@ -448,10 +442,6 @@ text-decoration:none; :focus {outline-style:none;} -.facts_labelred,.facts_valuered { -border:solid #ff0000 2px; -} - .subheaders { color:#000066; } @@ -920,22 +910,6 @@ border:1pt solid #dddddd; padding:5px; } -.facts_labelred,.facts_labelblue { -background:#99ddff; -padding:4px 4px 4px 4px; -width:20%; -text-align:center; -} - -.facts_valuered,.facts_valueblue { -background:#ffffff; -padding:4px 4px 4px 4px; -} - -.facts_labelblue,.facts_valueblue { -border:solid #0000ff 2px; -} - .quickfacts a {font-size:9px;padding:0 3px;} .tab_cell_active { @@ -1435,15 +1409,9 @@ font-size:9px; background:#dfeeff; } -/* Pending edits */ -.change_new,.nameblue { -border:solid #0000ff 2px!important; -} - -.change_old,.namered { -color:#000000 !important; -text-decoration:line-through!important; -} +/* Pending edits - TODO perhaps show differently in different contexts? */ +.new { outline: solid blue 1px; } +.old { outline: solid red 1px; } .note_details { display:none; @@ -3095,8 +3063,7 @@ html[dir=rtl] input:required:valid, html[dir=rtl] textarea:required:valid, html[ #edit_interface-page textarea[id*="NOTE"] {height:240px;} #edit_interface-page textarea[id*="TEXT"], #edit_interface-page textarea[id*="PUBL"] {height:140px;} #edit_interface-page textarea[id^="newgedrec"] {line-height:18px;width:605px;} -#edit_interface-page textarea#newgedrec1 {height:20px;} -#edit_interface-page textarea#newgedrec2 {height:364px;} +#edit_interface-page textarea#gedcom {height:364px;} #edit_interface-page textarea[id*="ADDR"], #edit_interface-page input[id*="ADDR"] {height:80px;width:300px;} #edit_interface-page #changefam {padding:5px;} #edit_interface-page #changefam table {margin:10px auto;min-width:400px;max-width:650px;} diff --git a/themes/colors/css/aquamarine.css b/themes/colors/css/aquamarine.css index 48e1459c9d..8b3a3e5aec 100644 --- a/themes/colors/css/aquamarine.css +++ b/themes/colors/css/aquamarine.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#dcf2f9; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #fc6d1d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/ash.css b/themes/colors/css/ash.css index cdfa99b52c..e0d34e1e13 100644 --- a/themes/colors/css/ash.css +++ b/themes/colors/css/ash.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#ededee; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #2a2b2d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/belgianchocolate.css b/themes/colors/css/belgianchocolate.css index 2f57a6d79a..dbb087d86e 100644 --- a/themes/colors/css/belgianchocolate.css +++ b/themes/colors/css/belgianchocolate.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#f6edd5; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #971702 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/bluelagoon.css b/themes/colors/css/bluelagoon.css index 2f7fb8a460..316083b4f8 100644 --- a/themes/colors/css/bluelagoon.css +++ b/themes/colors/css/bluelagoon.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#e6f5ff; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #2385c2 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/bluemarine.css b/themes/colors/css/bluemarine.css index 748f91cc50..eef5d587dd 100644 --- a/themes/colors/css/bluemarine.css +++ b/themes/colors/css/bluemarine.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#e0e7ff; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #6598cb 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/coffeeandcream.css b/themes/colors/css/coffeeandcream.css index 6f42f70d51..cd9a2f8b56 100644 --- a/themes/colors/css/coffeeandcream.css +++ b/themes/colors/css/coffeeandcream.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#F4EAD1; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #971702 2px; -} - /* Light Text */ .makeMenu li a { color:#553e2f; diff --git a/themes/colors/css/coldday.css b/themes/colors/css/coldday.css index fb90fccc71..7ef2606767 100644 --- a/themes/colors/css/coldday.css +++ b/themes/colors/css/coldday.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#e6e1ff; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #4d91ff 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/colors.css b/themes/colors/css/colors.css index ebfbe0f4f5..accf37dcda 100644 --- a/themes/colors/css/colors.css +++ b/themes/colors/css/colors.css @@ -194,7 +194,6 @@ html[dir=rtl] #main-menu > li > ul > li:first-child {text-align:center;} #menu-fam-addfav {background-position:left -832px;} html[dir=rtl] #menu-fam-addfav {background-position:right -832px;} #menu-fam-change {background-position:left -858px;} html[dir=rtl] #menu-fam-change {background-position:right -858px;} #menu-fam-del {background-position:left -936px;} html[dir=rtl] #menu-fam-del {background-position:right -936px;} -#menu-fam-editraw {background-position:left -754px;} html[dir=rtl] #menu-fam-editraw {background-position:right -754px;} #menu-fam-orderchil {background-position:left -858px;} html[dir=rtl] #menu-fam-orderchil {background-position:right -858px;} /* Clipping Icons */ @@ -202,7 +201,6 @@ html[dir=rtl] #main-menu > li > ul > li:first-child {text-align:center;} #menu-clippingsadd {background-position:left -702px;} html[dir=rtl] #menu-clippingsadd {background-position:right -702px;} /* Edit Icons */ -#menu-indi-editraw {background-position:left -754px;} html[dir=rtl] #menu-indi-editraw {background-position:right -754px;} #menu-indi-addname {background-position:left -780px;} html[dir=rtl] #menu-indi-addname {background-position:right -780px;} #menu-indi-editsex {background-position:left -780px;} html[dir=rtl] #menu-indi-editsex {background-position:right -780px;} #menu-indi-del {background-position:left -806px;} html[dir=rtl] #menu-indi-del {background-position:right -806px;} @@ -212,13 +210,11 @@ html[dir=rtl] #main-menu > li > ul > li:first-child {text-align:center;} #menu-note-addfav {background-position:left -832px;} html[dir=rtl] #menu-note-fav {background-position:right -832px;} #menu-note-del {background-position:left -806px;} html[dir=rtl] #menu-note-del {background-position:right -806px;} #menu-note-edit {background-position:left -910px;} html[dir=rtl] #menu-note-edit {background-position:right -910px;} -#menu-note-editraw {background-position:left -754px;} html[dir=rtl] #menu-note-editraw {background-position:right -754px;} /* Objects */ #menu-obje-addfav {background-position:left -832px;} html[dir=rtl] #menu-obje-addfav {background-position:right -832px;} #menu-obje-del {background-position:left -1040px;} html[dir=rtl] #menu-obje-del {background-position:right -1040px;} #menu-obje-edit {background-position:left -962px;} html[dir=rtl] #menu-obje-edit {background-position:right -962px;} -#menu-obje-editraw {background-position:left -754px;} html[dir=rtl] #menu-obje-editraw {background-position:right -754px;} #menu-obje-link {background-position:left -988px;} html[dir=rtl] #menu-obje-link {background-position:right -988px;} #menu-obje-link-fam {background-position:left -494px;} html[dir=rtl] #menu-obje-link-fam {background-position:right -494px;} #menu-obje-link-indi {background-position:left -520px;} html[dir=rtl] #menu-obje-link-indi {background-position:right -520px;} @@ -228,13 +224,11 @@ html[dir=rtl] #main-menu > li > ul > li:first-child {text-align:center;} #menu-repo-addfav {background-position:left -832px;} html[dir=rtl] #menu-repo-addfav {background-position:right -832px;} #menu-repo-del {background-position:left -806px;} html[dir=rtl] #menu-repo-del {background-position:right -806px;} #menu-repo-edit {background-position:left -1014px;} html[dir=rtl] #menu-repo-edit {background-position:right -1014px;} -#menu-repo-editraw {background-position:left -754px;} html[dir=rtl] #menu-repo-editraw {background-position:right -754px;} /* Source */ #menu-sour-addfav {background-position:left -832px;} html[dir=rtl] #menu-sour-addfav {background-position:right -832px;} #menu-sour-del {background-position:left -1066px;} html[dir=rtl] #menu-sour-del {background-position:right -1066px;} #menu-sour-edit {background-position:left -884px;} html[dir=rtl] #menu-sour-edit {background-position:right -884px;} -#menu-sour-editraw {background-position:left -754px;} html[dir=rtl] #menu-sour-editraw {background-position:right -754px;} /* Stories */ #menu-story-sub {background-position:left -1092px;} html[dir=rtl] #menu-story-sub {background-position:right -1040px;} @@ -391,9 +385,6 @@ html[dir=rtl] .list_value, html[dir=rtl] .list_value_wrap {text-align:right;} .facts_label02,.facts_label03 {border-radius:3px;font-weight:700;padding:4px;text-align:center;} .facts_value {border:1pt solid #999999;border-radius:3px;padding:4px;} .facts_value02 {background:#ffffff;border:1pt solid #dddddd;padding:5px;} -.facts_labelred,.facts_labelblue {background:#99ddff;padding:4px;text-align:center;width:20%;} -.facts_valuered,.facts_valueblue {background:#ffffff;padding:4px;} -.facts_labelblue,.facts_valueblue {border:solid #00f 2px;} .quickfacts a {font-size:9px;padding:0 3px;} .tab_cell_active {border-right:1pt solid #999999;font-size:10px;padding:2pt;text-align:center;width:20%;} @@ -497,9 +488,9 @@ html[dir=rtl] .optionbox input {margin-left:5px;} .font11 {font-size:11px;} .font12 {font-size:12px;} -/* Pending edits */ -.change_new,.nameblue {border:solid #00f 2px !important;} -.change_old,.namered {color:#000 !important;text-decoration:line-through !important;} +/* Pending edits - TODO perhaps show differently in different contexts? */ +.new { outline: solid blue 1px; } +.old { outline: solid red 1px; } a.showit {color:#000000;position:relative;text-decoration:none;z-index:24;} a.showit:hover {background:#ffff99;cursor:crosshair;z-index:25;} @@ -1140,8 +1131,7 @@ a.icon-uarrow:hover {width:20px;height:20px;background-image:url(../image #edit_interface-page textarea[id*="NOTE"] {height:240px;} #edit_interface-page textarea[id*="TEXT"], #edit_interface-page textarea[id*="PUBL"] {height:140px;} #edit_interface-page textarea[id^="newgedrec"] {line-height:18px;width:605px;} -#edit_interface-page textarea#newgedrec1 {height:20px;} -#edit_interface-page textarea#newgedrec2 {height:364px;} +#edit_interface-page textarea#gedcom {height:364px;} #edit_interface-page textarea[id*="ADDR"], #edit_interface-page input[id*="ADDR"] {height:80px;width:300px;} #edit_interface-page #changefam {padding:5px;} #edit_interface-page #changefam table {margin:10px auto;min-width:400px;max-width:650px;} diff --git a/themes/colors/css/greenbeam.css b/themes/colors/css/greenbeam.css index e438fc5ca8..343caa1d0f 100644 --- a/themes/colors/css/greenbeam.css +++ b/themes/colors/css/greenbeam.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#E6FFC7; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #03961e 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/mediterranio.css b/themes/colors/css/mediterranio.css index 20c87ad728..34a36a1109 100644 --- a/themes/colors/css/mediterranio.css +++ b/themes/colors/css/mediterranio.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#fef9dc; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #fc6d1d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/mercury.css b/themes/colors/css/mercury.css index f4dcc2ed1e..34d4939713 100644 --- a/themes/colors/css/mercury.css +++ b/themes/colors/css/mercury.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#f0f2f5; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #a9adbc 2px; -} - /* Light Text */ .makeMenu li a { color:#707070; diff --git a/themes/colors/css/nocturnal.css b/themes/colors/css/nocturnal.css index bf877901ca..1b9e4cd1ca 100644 --- a/themes/colors/css/nocturnal.css +++ b/themes/colors/css/nocturnal.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#e0e1f0; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #0a2352 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/olivia.css b/themes/colors/css/olivia.css index 2d867f5004..523deef7c4 100644 --- a/themes/colors/css/olivia.css +++ b/themes/colors/css/olivia.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#eef9dc; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #fc6d1d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/pinkplastic.css b/themes/colors/css/pinkplastic.css index 3775d8203e..60c4afb8a1 100644 --- a/themes/colors/css/pinkplastic.css +++ b/themes/colors/css/pinkplastic.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#fbdaed; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #fc6d1d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/sage.css b/themes/colors/css/sage.css index 63afafc7d4..828316768b 100644 --- a/themes/colors/css/sage.css +++ b/themes/colors/css/sage.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#eeeedd; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #ff0000 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/shinytomato.css b/themes/colors/css/shinytomato.css index 4c6e916563..79db027d72 100644 --- a/themes/colors/css/shinytomato.css +++ b/themes/colors/css/shinytomato.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#f0eaf0; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #fc6d1d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/css/tealtop.css b/themes/colors/css/tealtop.css index 324ac2653e..3c4d8eea2f 100644 --- a/themes/colors/css/tealtop.css +++ b/themes/colors/css/tealtop.css @@ -2,7 +2,7 @@ * Style for Colors theme * * webtrees: Web based Family History software - * Copyright (C) 2011 webtrees development team. + * Copyright (C) 2013 webtrees development team. * * Derived from PhpGedView * Copyright (C) 2002 to 2010 PGV Development Team. All rights reserved. @@ -73,10 +73,6 @@ background:#d2f4e6; color:#f00; } -.facts_labelred,.facts_valuered { -border:solid #fc6d1d 2px; -} - /* Light Text */ .makeMenu li a { color:#FFFFFF; diff --git a/themes/colors/header.php b/themes/colors/header.php index 069d510668..4056904fcd 100644 --- a/themes/colors/header.php +++ b/themes/colors/header.php @@ -122,6 +122,7 @@ if ($view!='simple') { // Use "simple" headers for popup windows '<li>', '<form style="display:inline;" action="search.php" method="post">', '<input type="hidden" name="action" value="general">', + '<input type="hidden" name="ged" value="', WT_GEDCOM, '">', '<input type="hidden" name="topsearch" value="yes">', '<input type="search" name="query" size="15" placeholder="', WT_I18N::translate('Search'), '" dir="auto">', '<input class="search-icon" type="image" src="', $WT_IMAGES['search'], '" alt="', WT_I18N::translate('Search'), '" title="', WT_I18N::translate('Search'), '">', diff --git a/themes/fab/header.php b/themes/fab/header.php index 342ce4b84e..a223f88211 100644 --- a/themes/fab/header.php +++ b/themes/fab/header.php @@ -96,6 +96,7 @@ if ($view!='simple') { // Use “simple” headers for popup windows echo '<li><form style="display:inline;" action="search.php" method="post">', '<input type="hidden" name="action" value="general">', + '<input type="hidden" name="ged" value="', WT_GEDCOM, '">', '<input type="hidden" name="topsearch" value="yes">', '<input type="search" name="query" size="20" placeholder="', WT_I18N::translate('Search'), '" dir="auto">', '</form></li>', diff --git a/themes/fab/style.css b/themes/fab/style.css index ab52054201..70cae16922 100644 --- a/themes/fab/style.css +++ b/themes/fab/style.css @@ -173,14 +173,9 @@ html[dir=rtl] #header-title { width:100%; } -/* Pending edits */ -.change_new, .nameblue { - border:solid #0000ff 2px !important; -} -.change_old, .namered { - color:#888888 !important; - text-decoration:line-through !important; -} +/* Pending edits - TODO perhaps show differently in different contexts? */ +.new { outline: solid blue 1px; } +.old { outline: solid red 1px; } /* Use CSS menus based on nested <ul> */ .makeMenu li { @@ -1670,8 +1665,7 @@ a.icon-uarrow:hover {width:20px;height:20px;background-image:url(images/u #edit_interface-page textarea[id*="NOTE"] {height:240px;} #edit_interface-page textarea[id*="TEXT"], #edit_interface-page textarea[id*="PUBL"] {height:140px;} #edit_interface-page textarea[id^="newgedrec"] {line-height:18px;width:605px;} -#edit_interface-page textarea#newgedrec1 {height:20px;} -#edit_interface-page textarea#newgedrec2 {height:364px;} +#edit_interface-page textarea#gedcom {height:364px;} #edit_interface-page textarea[id*="ADDR"], #edit_interface-page input[id*="ADDR"] {height:80px;width:300px;} #edit_interface-page #changefam {padding:5px;} #edit_interface-page #changefam table {margin:10px auto;min-width:400px;max-width:650px;} diff --git a/themes/minimal/header.php b/themes/minimal/header.php index 15a01d6fd4..961792160b 100644 --- a/themes/minimal/header.php +++ b/themes/minimal/header.php @@ -98,6 +98,7 @@ if ($view!='simple') { echo '<li><form style="display:inline;" action="search.php" method="post">', '<input type="hidden" name="action" value="general">', + '<input type="hidden" name="ged" value="', WT_GEDCOM, '">', '<input type="hidden" name="topsearch" value="yes">', '<input type="search" name="query" size="20" placeholder="', WT_I18N::translate('Search'), '" dir="auto">', '</form></li></div>', diff --git a/themes/minimal/style.css b/themes/minimal/style.css index ab24e74705..6daceb0a41 100644 --- a/themes/minimal/style.css +++ b/themes/minimal/style.css @@ -246,30 +246,6 @@ table.center { padding:5px; } -.facts_labelred, .facts_labelblue { - color:#333333; - background-color:#eeeeee; - font-size:12px; - padding:4px 4px 4px 4px; - width:20%; - text-align:center; -} - -.facts_valuered, .facts_valueblue { - background-color:#ffffff; - color:#555555; - font-size:12px; - padding:4px 4px 4px 4px; -} - -.facts_labelred, .facts_valuered { - border:solid #ff0000 2px; -} - -.facts_labelblue, .facts_valueblue { - border:solid #0000ff 2px; -} - .quickfacts a {font-size:9px;padding:0 3px;} .tabs_table { @@ -340,14 +316,6 @@ table.center { text-decoration:underline; } -.namered { - border:solid #ff0000 1px; -} - -.nameblue { - border:solid #0000ff 1px; -} - .details1 { font-size:10px; } @@ -931,14 +899,9 @@ margin:20px; border:solid #555555 1px; } -/* Change indicators */ -.change_new { - border:solid #0000ff 2px; -} - -.change_old { - border:solid #ff0000 2px; -} +/* Pending edits - TODO perhaps show differently in different contexts? */ +.new { outline: solid blue 1px; } +.old { outline: solid red 1px; } .note_details { display:none; @@ -1887,8 +1850,7 @@ a.icon-udarrow {width:20px;height:20px;background-image:url(images/u #edit_interface-page textarea[id*="NOTE"] {height:240px;} #edit_interface-page textarea[id*="TEXT"], #edit_interface-page textarea[id*="PUBL"] {height:140px;} #edit_interface-page textarea[id^="newgedrec"] {line-height:18px;width:605px;} -#edit_interface-page textarea#newgedrec1 {height:20px;} -#edit_interface-page textarea#newgedrec2 {height:364px;} +#edit_interface-page textarea#gedcom {height:364px;} #edit_interface-page textarea[id*="ADDR"], #edit_interface-page input[id*="ADDR"] {height:80px;width:300px;} #edit_interface-page #changefam {padding:5px;} #edit_interface-page #changefam table {margin:10px auto;min-width:400px;max-width:650px;} diff --git a/themes/webtrees/header.php b/themes/webtrees/header.php index 312e30f5c2..1158595f0d 100644 --- a/themes/webtrees/header.php +++ b/themes/webtrees/header.php @@ -89,6 +89,7 @@ if ($view!='simple') { '<div class="header_search">', '<form action="search.php" method="post">', '<input type="hidden" name="action" value="general">', + '<input type="hidden" name="ged" value="', WT_GEDCOM, '">', '<input type="hidden" name="topsearch" value="yes">', '<input type="search" name="query" size="25" placeholder="', WT_I18N::translate('Search'), '" dir="auto">', '<input type="image" class="image" src="', $WT_IMAGES['search'], '" alt="', WT_I18N::translate('Search'), '" title="', WT_I18N::translate('Search'), '">', diff --git a/themes/webtrees/style.css b/themes/webtrees/style.css index 44e5d0356f..5ea69fc885 100644 --- a/themes/webtrees/style.css +++ b/themes/webtrees/style.css @@ -90,10 +90,6 @@ table.center {margin-left:auto;margin-right:auto;} .facts_label03 {background-color:#81a9cb;} .facts_value {background-color:#edf7fd;border:solid #81a9cb 1px;font-size:12px;padding:4px;} .facts_value02 {background-color:#edf7fd;border:solid #81a9cb 1px;font-size:12px;padding:5px;} -.facts_labelred, .facts_labelblue {color:#ffffff;background-color:#81a9cb;font-size:12px;padding:4px;width:20%;text-align:center;} -.facts_valuered, .facts_valueblue {background-color:#edf7fd;font-size:12px;padding:4px;} -.facts_labelred, .facts_valuered {border:solid #ff0000 2px;} -.facts_labelblue, .facts_valueblue {border:solid #0000ff 2px;} .quickfacts a {font-size:9px;padding:0 3px;} .tabs_table {width:99%;} .tab_cell_active {background-color:#ffffff;border-left:outset #81a9cb 2px;border-top:outset #81a9cb 2px;border-right:outset #81a9cb 2px;text-align:center;font-weight:bold;font-size:10pt;} @@ -276,11 +272,9 @@ html[dir=rtl] .header_search {float:left;} /* Message box */ .messagebox {background-color:#c2ceef;border:solid #81a9cb 1px;} -/* Pending edits */ -.change_new, .nameblue {border:solid #0000ff 2px !important;} - -.change_old, .namered {color:#000000 !important;text-decoration:line-through !important;} -/* ====== */ +/* Pending edits - TODO perhaps show differently in different contexts? */ +.new { outline: solid blue 1px; } +.old { outline: solid red 1px; } .note_details {display:none;} a.showit {position:relative;z-index:24;text-decoration:none;} @@ -609,7 +603,6 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-fam-addfav {background-position:left -870px;} html[dir=rtl] #menu-fam-addfav {background-position:right -870px;} #menu-fam-change {background-position:left -90px;} html[dir=rtl] #menu-fam-change {background-position:right -90px;} #menu-fam-del {background-position:left -840px;} html[dir=rtl] #menu-fam-del {background-position:right -840px;} -#menu-fam-editraw {background-position:left -240px;} html[dir=rtl] #menu-fam-editraw {background-position:right -240px;} #menu-fam-orderchil {background-position:left -1080px;} html[dir=rtl] #menu-fam-orderchil {background-position:right -1080px;} #menu-help-contents {background-position:left -300px;} html[dir=rtl] #menu-help-contents {background-position:right -300px;} #menu-help-faq {background-position:left -300px;} html[dir=rtl] #menu-help-faq {background-position:right -300px;} @@ -621,7 +614,6 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-indi-addfav {background-position:left -870px;} html[dir=rtl] #menu-indi-addfav {background-position:right -870px;} #menu-indi-addname {background-position:left -780px;} html[dir=rtl] #menu-indi-addname {background-position:right -780px;} #menu-indi-del {background-position:left -840px;} html[dir=rtl] #menu-indi-del {background-position:right -840px;} -#menu-indi-editraw {background-position:left -240px;} html[dir=rtl] #menu-indi-editraw {background-position:right -240px;} #menu-indi-editsex {background-position:left -810px;} html[dir=rtl] #menu-indi-editsex {background-position:right -810px;} #menu-list-fam {background-position:left -90px;} html[dir=rtl] #menu-list-fam {background-position:right -90px;} #menu-list-indi {background-position:left -120px;} html[dir=rtl] #menu-list-indi {background-position:right -120px;} @@ -637,11 +629,9 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-note-addfav {background-position:left -870px;} html[dir=rtl] #menu-note-addfav {background-position:right -870px;} #menu-note-del {background-position:left -840px;} html[dir=rtl] #menu-note-del {background-position:right -840px;} #menu-note-edit {background-position:left -1020px;} html[dir=rtl] #menu-note-edit {background-position:right -1020px;} -#menu-note-editraw {background-position:left -240px;} html[dir=rtl] #menu-note-editraw {background-position:right -240px;} #menu-obje-addfav {background-position:left -870px;} html[dir=rtl] #menu-obje-addfav {background-position:right -870px;} #menu-obje-del {background-position:left -840px;} html[dir=rtl] #menu-obje-del {background-position:right -840px;} #menu-obje-edit {background-position:left -1110px;} html[dir=rtl] #menu-obje-edit {background-position:right -1110px;} -#menu-obje-editraw {background-position:left -240px;} html[dir=rtl] #menu-obje-editraw {background-position:right -240px;} #menu-obje-link {background-position:left -1140px;} html[dir=rtl] #menu-obje-link {background-position:right -1140px;} #menu-obje-link-fam {background-position:left -90px;} html[dir=rtl] #menu-obje-link-fam {background-position:right -90px;} #menu-obje-link-indi {background-position:left -300px;} html[dir=rtl] #menu-obje-link-indi {background-position:right -300px;} @@ -649,7 +639,6 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-repo-addfav {background-position:left -870px;} html[dir=rtl] #menu-repo-addfav {background-position:right -870px;} #menu-repo-del {background-position:left -840px;} html[dir=rtl] #menu-repo-del {background-position:right -840px;} #menu-repo-edit {background-position:left -990px;} html[dir=rtl] #menu-repo-edit {background-position:right -990px;} -#menu-repo-editraw {background-position:left -240px;} html[dir=rtl] #menu-repo-editraw {background-position:right -240px;} #menu-report li {background-position:left -570px;} html[dir=rtl] #menu-report li {background-position:right -570px;} #menu-search-advanced {background-position:left -600px;} html[dir=rtl] #menu-search-advanced {background-position:right -600px;} #menu-search-general {background-position:left -600px;} html[dir=rtl] #menu-search-general {background-position:right -600px;} @@ -658,8 +647,7 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-sour-addfav {background-position:left -870px;} html[dir=rtl] #menu-sour-addfav {background-position:right -870px;} #menu-sour-del {background-position:left -840px;} html[dir=rtl] #menu-sour-del {background-position:right -840px;} #menu-sour-edit {background-position:left -960px;} html[dir=rtl] #menu-sour-edit {background-position:right -960px;} -#menu-sour-editraw {background-position:left -240px;} html[dir=rtl] #menu-sour-editraw {background-position:right -240px;} -#menu-story-sub {background-position:left -1208px;} html[dir=rtl] #menu-sour-editraw {background-position:right -1208px;} +#menu-story-sub {background-position:left -1208px;} html[dir=rtl] #menu-story-sub {background-position:right -1208px;} #menu-tree li {background-position:left -240px;} html[dir=rtl] #menu-tree li {background-position:right -240px;} #menu-language li {text-align:left;} /* The language menu is always LTR, even on RTL pages */ @@ -1081,8 +1069,7 @@ a.icon-udarrow:hover {width:20px;height:20px;background-image:url(images/udarrow #edit_interface-page textarea[id*="NOTE"] {height:240px;} #edit_interface-page textarea[id*="TEXT"], #edit_interface-page textarea[id*="PUBL"] {height:140px;} #edit_interface-page textarea[id^="newgedrec"] {line-height:18px;width:605px;} -#edit_interface-page textarea#newgedrec1 {height:20px;} -#edit_interface-page textarea#newgedrec2 {height:364px;} +#edit_interface-page textarea#gedcom {height:364px;} #edit_interface-page textarea[id*="ADDR"], #edit_interface-page input[id*="ADDR"] {height:80px;width:300px;} #edit_interface-page #changefam {padding:5px;} #edit_interface-page #changefam table {margin:10px auto;min-width:400px;max-width:650px;} diff --git a/themes/xenea/header.php b/themes/xenea/header.php index 364158c7c4..65113e9c03 100644 --- a/themes/xenea/header.php +++ b/themes/xenea/header.php @@ -77,6 +77,7 @@ if ($view!='simple') { // Use "simple" headers for popup windows echo '<form action="search.php" method="post">', '<input type="hidden" name="action" value="general">', + '<input type="hidden" name="ged" value="', WT_GEDCOM, '">', '<input type="hidden" name="topsearch" value="yes">', '<input type="search" name="query" size="12" placeholder="', WT_I18N::translate('Search'), '" dir="auto">', '<input type="submit" name="search" value=">">', diff --git a/themes/xenea/style.css b/themes/xenea/style.css index 128158f21f..129c2120f4 100644 --- a/themes/xenea/style.css +++ b/themes/xenea/style.css @@ -238,7 +238,6 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-fam-addfav {background-position:left -736px;} html[dir=rtl] #menu-fam-addfav {background-position:right -736px;} #menu-fam-change {background-position:left -759px;} html[dir=rtl] #menu-fam-change {background-position:right -759px;} #menu-fam-del {background-position:left -713px;} html[dir=rtl] #menu-fam-del {background-position:right -713px;} -#menu-fam-editraw {background-position:left -667px;} html[dir=rtl] #menu-fam-editraw {background-position:right -667px;} #menu-fam-orderchil {background-position:left -759px;} html[dir=rtl] #menu-fam-orderchil {background-position:right -759px;} /* Clipping Icons */ @@ -246,7 +245,6 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-clippingsadd {background-position:left -621px;} html[dir=rtl] #menu-clippingsadd {background-position:right -621px;} /* Edit Icons */ -#menu-indi-editraw {background-position:left -667px;} html[dir=rtl] #menu-indi-editraw {background-position:right -667px;} #menu-indi-addname {background-position:left -690px;} html[dir=rtl] #menu-indi-addname {background-position:right -690px;} #menu-indi-editsex {background-position:left -690px;} html[dir=rtl] #menu-indi-editsex {background-position:right -690px;} #menu-indi-del {background-position:left -713px;} html[dir=rtl] #menu-indi-del {background-position:right -713px;} @@ -256,13 +254,11 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} #menu-note-addfav {background-position:left -736px;} html[dir=rtl] #menu-note-fav {background-position:right -736px;} #menu-note-del {background-position:left -713px;} html[dir=rtl] #menu-note-del {background-position:right -713px;} #menu-note-edit {background-position:left -805px;} html[dir=rtl] #menu-note-edit {background-position:right -805px;} -#menu-note-editraw {background-position:left -667px;} html[dir=rtl] #menu-note-editraw {background-position:right -667px;} /* Objects */ #menu-obje-addfav {background-position:left -736px;} html[dir=rtl] #menu-obje-addfav {background-position:right -736px;} #menu-obje-del {background-position:left -713px;} html[dir=rtl] #menu-obje-del {background-position:right -713px;} #menu-obje-edit {background-position:left -852px;} html[dir=rtl] #menu-obje-edit {background-position:right -852px;} -#menu-obje-editraw {background-position:left -667px;} html[dir=rtl] #menu-obje-editraw {background-position:right -667px;} #menu-obje-link {background-position:left -875px;} html[dir=rtl] #menu-obje-link {background-position:right -875px;} #menu-obje-link-fam {background-position:left -437px;} html[dir=rtl] #menu-obje-link-fam {background-position:right -437px;} #menu-obje-link-indi {background-position:left -460px;} html[dir=rtl] #menu-obje-link-indi {background-position:right -460px;} @@ -271,13 +267,11 @@ html[dir=rtl] #main-menu li li a {float:right;padding:1px 5px 1px 10px;} /* Repository */ #menu-repo-addfav {background-position:left -736px;} html[dir=rtl] #menu-repo-addfav {background-position:right -736px;} #menu-repo-del {background-position:left -713px;} html[dir=rtl] #menu-repo-del {background-position:right -713px;} -#menu-repo-editraw {background-position:left -667px;} html[dir=rtl] #menu-repo-editraw {background-position:right -667px;} /* Source */ #menu-sour-addfav {background-position:left -736px;} html[dir=rtl] #menu-sour-addfav {background-position:right -736px;} #menu-sour-del {background-position:left -713px;} html[dir=rtl] #menu-sour-del {background-position:right -713px;} #menu-sour-edit {background-position:left -782px;} html[dir=rtl] #menu-sour-edit {background-position:right -782px;} -#menu-sour-editraw {background-position:left -667px;} html[dir=rtl] #menu-sour-editraw {background-position:right -667px;} /* Stories */ #menu-story-sub {background-position:left -920px;} html[dir=rtl] #menu-story-sub {background-position:right -920px;} @@ -430,30 +424,6 @@ th { padding:5px; } -.facts_labelred, .facts_labelblue { - color:#000066; - background-color:#9dd8ff; - font-size:12px; - padding:4px; - width:20%; - text-align:center; -} - -.facts_valuered, .facts_valueblue { - background-color:#fbfdff; - color:#000066; - font-size:12px; - padding:4px; -} - -.facts_labelred, .facts_valuered { - border:solid #ff0000 2px; -} - -.facts_labelblue, .facts_valueblue { - border:solid #0000ff 2px; -} - .quickfacts a {font-size:9px;padding:0 3px;} .tabs_table { @@ -540,14 +510,6 @@ a:hover .nameZoom { font-weight:bold;font-size:14px; } -.namered { - border:solid #ff0000 1px; -} - -.nameblue { - border:solid #0000ff 1px; -} - .name2 { color:#000066; font-weight:bold;font-size:11px; @@ -1254,14 +1216,9 @@ h4 { border:solid #c3dfff 1px; } -/* Change indicators */ -.change_new { - border:solid #0000ff 2px; -} - -.change_old { - border:solid #ff0000 2px; -} +/* Pending edits - TODO perhaps show differently in different contexts? */ +.new { outline: solid blue 1px; } +.old { outline: solid red 1px; } .note_details { display:none; @@ -2207,8 +2164,7 @@ a.icon-uarrow:hover {width:20px;height:20px;background-image:url(images/u #edit_interface-page textarea[id*="NOTE"] {height:240px;} #edit_interface-page textarea[id*="TEXT"], #edit_interface-page textarea[id*="PUBL"] {height:140px;} #edit_interface-page textarea[id^="newgedrec"] {line-height:18px;width:605px;} -#edit_interface-page textarea#newgedrec1 {height:20px;} -#edit_interface-page textarea#newgedrec2 {height:364px;} +#edit_interface-page textarea#gedcom {height:364px;} #edit_interface-page textarea[id*="ADDR"], #edit_interface-page input[id*="ADDR"] {height:80px;width:300px;} #edit_interface-page #changefam {padding:5px;} #edit_interface-page #changefam table {margin:10px auto;min-width:400px;max-width:650px;} diff --git a/timeline.php b/timeline.php index d85ba813f5..2f77578a0c 100644 --- a/timeline.php +++ b/timeline.php @@ -4,7 +4,7 @@ // Use the $pids array to set which individuals to show on the chart // // webtrees: Web based Family History software -// Copyright (C) 2012 webtrees development team. +// Copyright (C) 2013 webtrees development team. // // Derived from PhpGedView // Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. @@ -255,7 +255,7 @@ $controller->checkPrivacy(); ?> <td class="person<?php echo $col; ?>" style="padding: 5px;"> <?php - if ($indi && $indi->canDisplayDetails()) { + if ($indi && $indi->canShow()) { if ($indi->getSex()=="M") { echo $indi->getSexImage('large', '', WT_I18N::translate('Male')); } elseif ($indi->getSex()=="F") { |
