Example #1
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     $xref = Filter::get('nid', WT_REGEX_XREF);
     $this->record = Note::getInstance($xref, $WT_TREE);
     parent::__construct();
 }
 /**
  * get edit menu
  */
 public function getEditMenu()
 {
     if (!$this->record || $this->record->isPendingDeletion()) {
         return null;
     }
     // edit menu
     $menu = new Menu(I18N::translate('Edit'), '#', 'menu-record');
     // edit raw
     if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
         $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-record-editraw', array('onclick' => 'return edit_raw("' . $this->record->getXref() . '");')));
     }
     // delete
     if (Auth::isEditor($this->record->getTree())) {
         $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-record-del', array('onclick' => 'return delete_record("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");')));
     }
     // add to favorites
     if (Module::getModuleByName('user_favorites')) {
         $menu->addSubmenu(new Menu(I18N::translate('Add to favorites'), '#', 'menu-record-addfav', array('onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite" ,{xref:"' . $this->record->getXref() . '"},function(){location.reload();})')));
     }
     // Get the link for the first submenu and set it as the link for the main menu
     if ($menu->getSubmenus()) {
         $submenus = $menu->getSubmenus();
         $menu->setLink($submenus[0]->getLink());
         $menu->setAttrs($submenus[0]->getAttrs());
     }
     return $menu;
 }
 /**
  * get edit menu
  */
 public function getEditMenu()
 {
     if (!$this->record || $this->record->isPendingDeletion()) {
         return null;
     }
     // edit menu
     $menu = new Menu(I18N::translate('Edit'), '#', 'menu-record');
     // edit raw
     if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
         $menu->addSubmenu(new Menu(I18N::translate('Edit the raw GEDCOM'), '#', 'menu-record-editraw', array('onclick' => 'return edit_raw("' . $this->record->getXref() . '");')));
     }
     // delete
     if (Auth::isEditor($this->record->getTree())) {
         $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-record-del', array('onclick' => 'return delete_record("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");')));
     }
     return $menu;
 }
 /**
  * Convert custom markup into HTML
  *
  * @param Note $note
  *
  * @return string
  */
 public static function formatCensusNote(Note $note)
 {
     global $WT_TREE;
     if (preg_match('/(.*)((?:\\n.*)*)\\n\\.start_formatted_area\\.\\n(.+)\\n(.+(?:\\n.+)*)\\n.end_formatted_area\\.((?:\\n.*)*)/', $note->getNote(), $match)) {
         // This looks like a census-assistant shared note
         $title = Filter::escapeHtml($match[1]);
         $preamble = Filter::escapeHtml($match[2]);
         $header = Filter::escapeHtml($match[3]);
         $data = Filter::escapeHtml($match[4]);
         $postamble = Filter::escapeHtml($match[5]);
         // Get the column headers for the census to which this note refers
         // requires the fact place & date to match the specific census
         // censusPlace() (Soundex match) and censusDate() functions
         $fmt_headers = array();
         $linkedRecords = array_merge($note->linkedIndividuals('NOTE'), $note->linkedFamilies('NOTE'));
         $firstRecord = array_shift($linkedRecords);
         if ($firstRecord) {
             $countryCode = '';
             $date = '';
             foreach ($firstRecord->getFacts('CENS') as $fact) {
                 if (trim($fact->getAttribute('NOTE'), '@') === $note->getXref()) {
                     $date = $fact->getAttribute('DATE');
                     $place = explode(',', strip_tags($fact->getPlace()->getFullName()));
                     $countryCode = Soundex::daitchMokotoff(array_pop($place));
                     break;
                 }
             }
             foreach (Census::allCensusPlaces() as $censusPlace) {
                 if (Soundex::compare($countryCode, Soundex::daitchMokotoff($censusPlace->censusPlace()))) {
                     foreach ($censusPlace->allCensusDates() as $census) {
                         if ($census->censusDate() == $date) {
                             foreach ($census->columns() as $column) {
                                 $abbrev = $column->abbreviation();
                                 if ($abbrev) {
                                     $description = $column->title() ? $column->title() : I18N::translate('Description unavailable');
                                     $fmt_headers[$abbrev] = '<span title="' . $description . '">' . $abbrev . '</span>';
                                 }
                             }
                             break 2;
                         }
                     }
                 }
             }
         }
         // Substitute header labels and format as HTML
         $thead = '<tr><th>' . strtr(str_replace('|', '</th><th>', $header), $fmt_headers) . '</th></tr>';
         $thead = str_replace('.b.', '', $thead);
         // Format data as HTML
         $tbody = '';
         foreach (explode("\n", $data) as $row) {
             $tbody .= '<tr>';
             foreach (explode('|', $row) as $column) {
                 $tbody .= '<td>' . $column . '</td>';
             }
             $tbody .= '</tr>';
         }
         return $title . "\n" . '<div class="markdown">' . '<p>' . $preamble . '</p>' . '<table>' . '<thead>' . $thead . '</thead>' . '<tbody>' . $tbody . '</tbody>' . '</table>' . '<p>' . $postamble . '</p>' . '</div>';
     } else {
         // Not a census-assistant shared note - apply default formatting
         return Filter::formatText($note->getNote(), $WT_TREE);
     }
 }
Example #5
0
 /**
  * Notes (inline and objects) linked to this fact
  *
  * @return string[]|Note[]
  */
 public function getNotes()
 {
     $notes = array();
     preg_match_all('/\\n2 NOTE ?(.*(?:\\n3.*)*)/', $this->getGedcom(), $matches);
     foreach ($matches[1] as $match) {
         $note = preg_replace("/\n3 CONT ?/", "\n", $match);
         if (preg_match('/@(' . WT_REGEX_XREF . ')@/', $note, $nmatch)) {
             $note = Note::getInstance($nmatch[1], $this->getParent()->getTree());
             if ($note && $note->canShow()) {
                 // A note object
                 $notes[] = $note;
             }
         } else {
             // An inline note
             $notes[] = $note;
         }
     }
     return $notes;
 }
Example #6
0
 /**
  * Get the current view of a record, allowing for pending changes
  *
  * @param string $xref
  * @param string $type
  *
  * @return string
  */
 public static function getLatestRecord($xref, $type)
 {
     global $WT_TREE;
     switch ($type) {
         case 'INDI':
             return Individual::getInstance($xref, $WT_TREE)->getGedcom();
         case 'FAM':
             return Family::getInstance($xref, $WT_TREE)->getGedcom();
         case 'SOUR':
             return Source::getInstance($xref, $WT_TREE)->getGedcom();
         case 'REPO':
             return Repository::getInstance($xref, $WT_TREE)->getGedcom();
         case 'OBJE':
             return Media::getInstance($xref, $WT_TREE)->getGedcom();
         case 'NOTE':
             return Note::getInstance($xref, $WT_TREE)->getGedcom();
         default:
             return GedcomRecord::getInstance($xref, $WT_TREE)->getGedcom();
     }
 }
Example #7
0
 /**
  * Find notes linked to this record.
  *
  * @param string $link
  *
  * @return Note[]
  */
 public function linkedNotes($link)
 {
     $rows = Database::prepare("SELECT o_id AS xref, 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 = :tree_id AND o_type = 'NOTE' AND l_type = :link AND l_to = :xref" . " ORDER BY n_sort COLLATE :collation")->execute(array('tree_id' => $this->tree->getTreeId(), 'link' => $link, 'xref' => $this->xref, 'collation' => I18N::collation()))->fetchAll();
     $list = array();
     foreach ($rows as $row) {
         $record = Note::getInstance($row->xref, $this->tree, $row->gedcom);
         if ($record->canShowName()) {
             $list[] = $record;
         }
     }
     return $list;
 }
Example #8
0
namespace Fisharebest\Webtrees;

/**
 * Defined in session.php
 *
 * @global Tree $WT_TREE
 */
global $WT_TREE;
use Fisharebest\Webtrees\Controller\NoteController;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
use Fisharebest\Webtrees\Functions\FunctionsPrintFacts;
use Fisharebest\Webtrees\Functions\FunctionsPrintLists;
use Fisharebest\Webtrees\Module\CensusAssistantModule;
define('WT_SCRIPT_NAME', 'note.php');
require './includes/session.php';
$record = Note::getInstance(Filter::get('nid', WT_REGEX_XREF), $WT_TREE);
$controller = new NoteController($record);
if ($controller->record && $controller->record->canShow()) {
    if ($controller->record->isPendingDeletion()) {
        if (Auth::isModerator($controller->record->getTree())) {
            FlashMessages::addMessage(I18N::translate('This note has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning');
        } elseif (Auth::isEditor($controller->record->getTree())) {
            FlashMessages::addMessage(I18N::translate('This note has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning');
        }
    } elseif ($controller->record->isPendingAddtion()) {
        if (Auth::isModerator($controller->record->getTree())) {
            FlashMessages::addMessage(I18N::translate('This note has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning');
        } elseif (Auth::isEditor($controller->record->getTree())) {
            FlashMessages::addMessage(I18N::translate('This note has been edited. The changes need to be reviewed by a moderator.') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning');
        }
    }
Example #9
0
        ?>
" onclick="window.close();">
			</p>
		</form>
	</div>
	<?php 
        break;
    case 'editnoteaction':
        $xref = Filter::post('xref', WT_REGEX_XREF);
        $keep_chan = Filter::postBool('keep_chan');
        $note = Filter::post('NOTE');
        if (!Filter::checkCsrf()) {
            header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME . '?action=editnote&xref=' . $xref);
            return;
        }
        $record = Note::getInstance($xref, $WT_TREE);
        check_record_access($record);
        $controller->setPageTitle(I18N::translate('Edit shared note'))->pageHeader();
        // We have user-supplied data in a replacement string - escape it against backreferences
        $note = str_replace(array('\\', '$'), array('\\\\', '\\$'), $note);
        $gedrec = preg_replace('/^0 @' . $record->getXref() . '@ NOTE.*(\\n1 CONT.*)*/', '0 @' . $record->getXref() . '@ NOTE ' . preg_replace("/\r?\n/", "\n1 CONT ", $note), $record->getGedcom());
        $record->updateRecord($gedrec, !$keep_chan);
        $controller->addInlineJavascript('closePopupAndReloadParent();');
        break;
        ////////////////////////////////////////////////////////////////////////////////
        // Create a new repository
        ////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////
    // Create a new repository
    ////////////////////////////////////////////////////////////////////////////////
    case 'addnewrepository':
 /**
  * get gedcom tag value
  *
  * @param string  $tag    The tag to find, use : to delineate subtags
  * @param int $level  The gedcom line level of the first tag to find, setting level to 0 will cause it to use 1+ the level of the incoming record
  * @param string  $gedrec The gedcom record to get the value from
  *
  * @return string the value of a gedcom tag from the given gedcom record
  */
 private function getGedcomValue($tag, $level, $gedrec)
 {
     global $WT_TREE;
     if (empty($gedrec)) {
         return '';
     }
     $tags = explode(':', $tag);
     $origlevel = $level;
     if ($level == 0) {
         $level = $gedrec[0] + 1;
     }
     $subrec = $gedrec;
     foreach ($tags as $t) {
         $lastsubrec = $subrec;
         $subrec = Functions::getSubRecord($level, "{$level} {$t}", $subrec);
         if (empty($subrec) && $origlevel == 0) {
             $level--;
             $subrec = Functions::getSubRecord($level, "{$level} {$t}", $lastsubrec);
         }
         if (empty($subrec)) {
             if ($t == "TITL") {
                 $subrec = Functions::getSubRecord($level, "{$level} ABBR", $lastsubrec);
                 if (!empty($subrec)) {
                     $t = "ABBR";
                 }
             }
             if (empty($subrec)) {
                 if ($level > 0) {
                     $level--;
                 }
                 $subrec = Functions::getSubRecord($level, "@ {$t}", $gedrec);
                 if (empty($subrec)) {
                     return '';
                 }
             }
         }
         $level++;
     }
     $level--;
     $ct = preg_match("/{$level} {$t}(.*)/", $subrec, $match);
     if ($ct == 0) {
         $ct = preg_match("/{$level} @.+@ (.+)/", $subrec, $match);
     }
     if ($ct == 0) {
         $ct = preg_match("/@ {$t} (.+)/", $subrec, $match);
     }
     if ($ct > 0) {
         $value = trim($match[1]);
         if ($t == 'NOTE' && preg_match('/^@(.+)@$/', $value, $match)) {
             $note = Note::getInstance($match[1], $WT_TREE);
             if ($note) {
                 $value = $note->getNote();
             } else {
                 //-- set the value to the id without the @
                 $value = $match[1];
             }
         }
         if ($level != 0 || $t != "NOTE") {
             $value .= Functions::getCont($level + 1, $subrec);
         }
         return $value;
     }
     return "";
 }
Example #11
0
 /**
  * A separate file for each family tree and each record type.
  * These files depend on access levels, so only cache for visitors.
  *
  * @param int    $ged_id
  * @param string $rec_type
  * @param string $volume
  */
 private function generateFile($ged_id, $rec_type, $volume)
 {
     $tree = Tree::findById($ged_id);
     // Check the cache
     $timestamp = $this->getSetting('sitemap-' . $ged_id . '-' . $rec_type . '-' . $volume . '.timestamp');
     if ($timestamp > WT_TIMESTAMP - self::CACHE_LIFE && !Auth::check()) {
         $data = $this->getSetting('sitemap-' . $ged_id . '-' . $rec_type . '-' . $volume . '.xml');
     } else {
         $data = '<url><loc>' . WT_BASE_URL . 'index.php?ctype=gedcom&amp;ged=' . $tree->getNameUrl() . '</loc></url>' . PHP_EOL;
         $records = array();
         switch ($rec_type) {
             case 'i':
                 $rows = Database::prepare("SELECT i_id AS xref, i_gedcom AS gedcom" . " FROM `##individuals`" . " WHERE i_file = :tree_id" . " ORDER BY i_id" . " LIMIT :limit OFFSET :offset")->execute(array('tree_id' => $ged_id, 'limit' => self::RECORDS_PER_VOLUME, 'offset' => self::RECORDS_PER_VOLUME * $volume))->fetchAll();
                 foreach ($rows as $row) {
                     $records[] = Individual::getInstance($row->xref, $tree, $row->gedcom);
                 }
                 break;
             case 's':
                 $rows = Database::prepare("SELECT s_id AS xref, s_gedcom AS gedcom" . " FROM `##sources`" . " WHERE s_file = :tree_id" . " ORDER BY s_id" . " LIMIT :limit OFFSET :offset")->execute(array('tree_id' => $ged_id, 'limit' => self::RECORDS_PER_VOLUME, 'offset' => self::RECORDS_PER_VOLUME * $volume))->fetchAll();
                 foreach ($rows as $row) {
                     $records[] = Source::getInstance($row->xref, $tree, $row->gedcom);
                 }
                 break;
             case 'r':
                 $rows = Database::prepare("SELECT o_id AS xref, o_gedcom AS gedcom" . " FROM `##other`" . " WHERE o_file = :tree_id AND o_type = 'REPO'" . " ORDER BY o_id" . " LIMIT :limit OFFSET :offset")->execute(array('tree_id' => $ged_id, 'limit' => self::RECORDS_PER_VOLUME, 'offset' => self::RECORDS_PER_VOLUME * $volume))->fetchAll();
                 foreach ($rows as $row) {
                     $records[] = Repository::getInstance($row->xref, $tree, $row->gedcom);
                 }
                 break;
             case 'n':
                 $rows = Database::prepare("SELECT o_id AS xref, o_gedcom AS gedcom" . " FROM `##other`" . " WHERE o_file = :tree_id AND o_type = 'NOTE'" . " ORDER BY o_id" . " LIMIT :limit OFFSET :offset")->execute(array('tree_id' => $ged_id, 'limit' => self::RECORDS_PER_VOLUME, 'offset' => self::RECORDS_PER_VOLUME * $volume))->fetchAll();
                 foreach ($rows as $row) {
                     $records[] = Note::getInstance($row->xref, $tree, $row->gedcom);
                 }
                 break;
             case 'm':
                 $rows = Database::prepare("SELECT m_id AS xref, m_gedcom AS gedcom" . " FROM `##media`" . " WHERE m_file = :tree_id" . " ORDER BY m_id" . " LIMIT :limit OFFSET :offset")->execute(array('tree_id' => $ged_id, 'limit' => self::RECORDS_PER_VOLUME, 'offset' => self::RECORDS_PER_VOLUME * $volume))->fetchAll();
                 foreach ($rows as $row) {
                     $records[] = Media::getInstance($row->xref, $tree, $row->gedcom);
                 }
                 break;
         }
         foreach ($records as $record) {
             if ($record->canShowName()) {
                 $data .= '<url>';
                 $data .= '<loc>' . WT_BASE_URL . $record->getHtmlUrl() . '</loc>';
                 $chan = $record->getFirstFact('CHAN');
                 if ($chan) {
                     $date = $chan->getDate();
                     if ($date->isOK()) {
                         $data .= '<lastmod>' . $date->minimumDate()->Format('%Y-%m-%d') . '</lastmod>';
                     }
                 }
                 $data .= '</url>' . PHP_EOL;
             }
         }
         $data = '<' . '?xml version="1.0" encoding="UTF-8" ?' . '>' . PHP_EOL . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">' . PHP_EOL . $data . '</urlset>' . PHP_EOL;
         // Cache this data - but only for visitors, as we don’t want
         // visitors to see data created by signed-in users.
         if (!Auth::check()) {
             $this->setSetting('sitemap-' . $ged_id . '-' . $rec_type . '-' . $volume . '.xml', $data);
             $this->setSetting('sitemap-' . $ged_id . '-' . $rec_type . '-' . $volume . '.timestamp', WT_TIMESTAMP);
         }
     }
     header('Content-Type: application/xml');
     header('Content-Length: ' . strlen($data));
     echo $data;
 }
Example #12
0
 /**
  * add a new tag input field
  *
  * called for each fact to be edited on a form.
  * Fact level=0 means a new empty form : data are POSTed by name
  * else data are POSTed using arrays :
  * glevels[] : tag level
  *  islink[] : tag is a link
  *     tag[] : tag name
  *    text[] : tag value
  *
  * @param string $tag fact record to edit (eg 2 DATE xxxxx)
  * @param string $upperlevel optional upper level tag (eg BIRT)
  * @param string $label An optional label to echo instead of the default
  * @param string $extra optional text to display after the input field
  * @param Individual $person For male/female translations
  *
  * @return string
  */
 public static function addSimpleTag($tag, $upperlevel = '', $label = '', $extra = null, Individual $person = null)
 {
     global $tags, $main_fact, $xref, $bdm, $action, $WT_TREE;
     // Keep track of SOUR fields, so we can reference them in subsequent PAGE fields.
     static $source_element_id;
     $subnamefacts = array('NPFX', 'GIVN', 'SPFX', 'SURN', 'NSFX', '_MARNM_SURN');
     preg_match('/^(?:(\\d+) (' . WT_REGEX_TAG . ') ?(.*))/', $tag, $match);
     list(, $level, $fact, $value) = $match;
     $level = (int) $level;
     // element name : used to POST data
     if ($level === 0) {
         if ($upperlevel) {
             $element_name = $upperlevel . '_' . $fact;
         } else {
             $element_name = $fact;
         }
     } else {
         $element_name = 'text[]';
     }
     if ($level === 1) {
         $main_fact = $fact;
     }
     // element id : used by javascript functions
     if ($level === 0) {
         $element_id = $fact;
     } else {
         $element_id = $fact . Uuid::uuid4();
     }
     if ($upperlevel) {
         $element_id = $upperlevel . '_' . $fact . Uuid::uuid4();
     }
     // field value
     $islink = substr($value, 0, 1) === '@' && substr($value, 0, 2) !== '@#';
     if ($islink) {
         $value = trim(substr($tag, strlen($fact) + 3), ' @\\r');
     } else {
         $value = (string) substr($tag, strlen($fact) + 3);
     }
     if ($fact === 'REPO' || $fact === 'SOUR' || $fact === 'OBJE' || $fact === 'FAMC') {
         $islink = true;
     }
     if ($fact === 'SHARED_NOTE_EDIT' || $fact === 'SHARED_NOTE') {
         $islink = true;
         $fact = 'NOTE';
     }
     // label
     echo '<tr id="', $element_id, '_tr"';
     if ($fact === 'MAP' || ($fact === 'LATI' || $fact === 'LONG') && $value === '') {
         echo ' style="display:none;"';
     }
     echo '>';
     if (in_array($fact, $subnamefacts) || $fact === 'LATI' || $fact === 'LONG') {
         echo '<td class="optionbox wrap width25">';
     } else {
         echo '<td class="descriptionbox wrap width25">';
     }
     // tag name
     if ($label) {
         echo $label;
     } elseif ($upperlevel) {
         echo GedcomTag::getLabel($upperlevel . ':' . $fact);
     } else {
         echo GedcomTag::getLabel($fact);
     }
     // If using GEDFact-assistant window
     if ($action === 'addnewnote_assisted') {
         // Do not print on GEDFact Assistant window
     } else {
         // Not all facts have help text.
         switch ($fact) {
             case 'NAME':
                 if ($upperlevel !== 'REPO' && $upperlevel !== 'UNKNOWN') {
                     echo FunctionsPrint::helpLink($fact);
                 }
                 break;
             case 'DATE':
             case 'PLAC':
             case 'RESN':
             case 'ROMN':
             case 'SURN':
             case '_HEB':
                 echo FunctionsPrint::helpLink($fact);
                 break;
         }
     }
     // tag level
     if ($level > 0) {
         if ($fact === 'TEXT' && $level > 1) {
             echo '<input type="hidden" name="glevels[]" value="', $level - 1, '">';
             echo '<input type="hidden" name="islink[]" value="0">';
             echo '<input type="hidden" name="tag[]" value="DATA">';
             // leave data text[] value empty because the following TEXT line will cause the DATA to be added
             echo '<input type="hidden" name="text[]" value="">';
         }
         echo '<input type="hidden" name="glevels[]" value="', $level, '">';
         echo '<input type="hidden" name="islink[]" value="', $islink, '">';
         echo '<input type="hidden" name="tag[]" value="', $fact, '">';
     }
     echo '</td>';
     // value
     echo '<td class="optionbox wrap">';
     // retrieve linked NOTE
     if ($fact === 'NOTE' && $islink) {
         $note1 = Note::getInstance($value, $WT_TREE);
         if ($note1) {
             $noterec = $note1->getGedcom();
             preg_match('/' . $value . '/i', $noterec, $notematch);
             $value = $notematch[0];
         }
     }
     // Show names for spouses in MARR/HUSB/AGE and MARR/WIFE/AGE
     if ($fact === 'HUSB' || $fact === 'WIFE') {
         $family = Family::getInstance($xref, $WT_TREE);
         if ($family) {
             $spouse_link = $family->getFirstFact($fact);
             if ($spouse_link) {
                 $spouse = $spouse_link->getTarget();
                 if ($spouse) {
                     echo $spouse->getFullName();
                 }
             }
         }
     }
     if (in_array($fact, Config::emptyFacts()) && ($value === '' || $value === 'Y' || $value === 'y')) {
         echo '<input type="hidden" id="', $element_id, '" name="', $element_name, '" value="', $value, '">';
         if ($level <= 1) {
             echo '<input type="checkbox" ';
             if ($value) {
                 echo 'checked';
             }
             echo ' onclick="document.getElementById(\'' . $element_id . '\').value = (this.checked) ? \'Y\' : \'\';">';
             echo I18N::translate('yes');
         }
         if ($fact === 'CENS' && $value === 'Y') {
             echo self::censusDateSelector(WT_LOCALE, $xref);
             if (Module::getModuleByName('GEDFact_assistant') && GedcomRecord::getInstance($xref, $WT_TREE) instanceof Individual) {
                 echo '<div></div><a href="#" style="display: none;" id="assistant-link" onclick="return activateCensusAssistant();">' . I18N::translate('Create a new shared note using assistant') . '</a></div>';
             }
         }
     } elseif ($fact === 'TEMP') {
         echo self::selectEditControl($element_name, GedcomCodeTemp::templeNames(), I18N::translate('No temple - living ordinance'), $value);
     } elseif ($fact === 'ADOP') {
         echo self::editFieldAdoption($element_name, $value, '', $person);
     } elseif ($fact === 'PEDI') {
         echo self::editFieldPedigree($element_name, $value, '', $person);
     } elseif ($fact === 'STAT') {
         echo self::selectEditControl($element_name, GedcomCodeStat::statusNames($upperlevel), '', $value);
     } elseif ($fact === 'RELA') {
         echo self::editFieldRelationship($element_name, strtolower($value));
     } elseif ($fact === 'QUAY') {
         echo self::selectEditControl($element_name, GedcomCodeQuay::getValues(), '', $value);
     } elseif ($fact === '_WT_USER') {
         echo self::editFieldUsername($element_name, $value);
     } elseif ($fact === 'RESN') {
         echo self::editFieldRestriction($element_name, $value);
     } elseif ($fact === '_PRIM') {
         echo '<select id="', $element_id, '" name="', $element_name, '" >';
         echo '<option value=""></option>';
         echo '<option value="Y" ';
         if ($value === 'Y') {
             echo ' selected';
         }
         echo '>', I18N::translate('always'), '</option>';
         echo '<option value="N" ';
         if ($value === 'N') {
             echo 'selected';
         }
         echo '>', I18N::translate('never'), '</option>';
         echo '</select>';
         echo '<p class="small text-muted">', I18N::translate('Use this image for charts and on the individual’s page.'), '</p>';
     } elseif ($fact === 'SEX') {
         echo '<select id="', $element_id, '" name="', $element_name, '"><option value="M" ';
         if ($value === 'M') {
             echo 'selected';
         }
         echo '>', I18N::translate('Male'), '</option><option value="F" ';
         if ($value === 'F') {
             echo 'selected';
         }
         echo '>', I18N::translate('Female'), '</option><option value="U" ';
         if ($value === 'U' || empty($value)) {
             echo 'selected';
         }
         echo '>', I18N::translateContext('unknown gender', 'Unknown'), '</option></select>';
     } elseif ($fact === 'TYPE' && $level === 3) {
         //-- Build the selector for the Media 'TYPE' Fact
         echo '<select name="text[]"><option selected value="" ></option>';
         $selectedValue = strtolower($value);
         if (!array_key_exists($selectedValue, GedcomTag::getFileFormTypes())) {
             echo '<option selected value="', Filter::escapeHtml($value), '" >', Filter::escapeHtml($value), '</option>';
         }
         foreach (GedcomTag::getFileFormTypes() as $typeName => $typeValue) {
             echo '<option value="', $typeName, '" ';
             if ($selectedValue === $typeName) {
                 echo 'selected';
             }
             echo '>', $typeValue, '</option>';
         }
         echo '</select>';
     } elseif ($fact === 'NAME' && $upperlevel !== 'REPO' && $upperlevel !== 'UNKNOWN' || $fact === '_MARNM') {
         // Populated in javascript from sub-tags
         echo '<input type="hidden" id="', $element_id, '" name="', $element_name, '" onchange="updateTextName(\'', $element_id, '\');" value="', Filter::escapeHtml($value), '" class="', $fact, '">';
         echo '<span id="', $element_id, '_display" dir="auto">', Filter::escapeHtml($value), '</span>';
         echo ' <a href="#edit_name" onclick="convertHidden(\'', $element_id, '\'); return false;" class="icon-edit_indi" title="' . I18N::translate('Edit name') . '"></a>';
     } else {
         // textarea
         if ($fact === 'TEXT' || $fact === 'ADDR' || $fact === 'NOTE' && !$islink) {
             echo '<textarea id="', $element_id, '" name="', $element_name, '" dir="auto">', Filter::escapeHtml($value), '</textarea><br>';
         } else {
             // text
             // If using GEDFact-assistant window
             if ($action === 'addnewnote_assisted') {
                 echo '<input type="text" id="', $element_id, '" name="', $element_name, '" value="', Filter::escapeHtml($value), '" style="width:4.1em;" dir="ltr"';
             } else {
                 echo '<input type="text" id="', $element_id, '" name="', $element_name, '" value="', Filter::escapeHtml($value), '" dir="ltr"';
             }
             echo ' class="', $fact, '"';
             if (in_array($fact, $subnamefacts)) {
                 echo ' onblur="updatewholename();" onkeyup="updatewholename();"';
             }
             // Extra markup for specific fact types
             switch ($fact) {
                 case 'ALIA':
                 case 'ASSO':
                 case '_ASSO':
                     echo ' data-autocomplete-type="ASSO" data-autocomplete-extra="input.DATE"';
                     break;
                 case 'DATE':
                     echo ' onblur="valid_date(this);" onmouseout="valid_date(this);"';
                     break;
                 case 'GIVN':
                     echo ' autofocus data-autocomplete-type="GIVN"';
                     break;
                 case 'LATI':
                     echo ' onblur="valid_lati_long(this, \'N\', \'S\');" onmouseout="valid_lati_long(this, \'N\', \'S\');"';
                     break;
                 case 'LONG':
                     echo ' onblur="valid_lati_long(this, \'E\', \'W\');" onmouseout="valid_lati_long(this, \'E\', \'W\');"';
                     break;
                 case 'NOTE':
                     // Shared notes. Inline notes are handled elsewhere.
                     echo ' data-autocomplete-type="NOTE"';
                     break;
                 case 'OBJE':
                     echo ' data-autocomplete-type="OBJE"';
                     break;
                 case 'PAGE':
                     echo ' data-autocomplete-type="PAGE" data-autocomplete-extra="#' . $source_element_id . '"';
                     break;
                 case 'PLAC':
                     echo ' data-autocomplete-type="PLAC"';
                     break;
                 case 'REPO':
                     echo ' data-autocomplete-type="REPO"';
                     break;
                 case 'SOUR':
                     $source_element_id = $element_id;
                     echo ' data-autocomplete-type="SOUR"';
                     break;
                 case 'SURN':
                 case '_MARNM_SURN':
                     echo ' data-autocomplete-type="SURN"';
                     break;
                 case 'TIME':
                     echo ' pattern="([0-1][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?" dir="ltr" placeholder="' . I18N::translate('hh:mm or hh:mm:ss') . '"';
                     break;
             }
             echo '>';
         }
         $tmp_array = array('TYPE', 'TIME', 'NOTE', 'SOUR', 'REPO', 'OBJE', 'ASSO', '_ASSO', 'AGE');
         // split PLAC
         if ($fact === 'PLAC') {
             echo '<div id="', $element_id, '_pop" style="display: inline;">';
             echo FunctionsPrint::printSpecialCharacterLink($element_id), ' ', FunctionsPrint::printFindPlaceLink($element_id);
             echo '<span  onclick="jQuery(\'tr[id^=', $upperlevel, '_LATI],tr[id^=', $upperlevel, '_LONG],tr[id^=LATI],tr[id^=LONG]\').toggle(\'fast\'); return false;" class="icon-target" title="', GedcomTag::getLabel('LATI'), ' / ', GedcomTag::getLabel('LONG'), '"></span>';
             echo '</div>';
             if (Module::getModuleByName('places_assistant')) {
                 \PlacesAssistantModule::setup_place_subfields($element_id);
                 \PlacesAssistantModule::print_place_subfields($element_id);
             }
         } elseif (!in_array($fact, $tmp_array)) {
             echo FunctionsPrint::printSpecialCharacterLink($element_id);
         }
     }
     // MARRiage TYPE : hide text field and show a selection list
     if ($fact === 'TYPE' && $level === 2 && $tags[0] === 'MARR') {
         echo '<script>';
         echo 'document.getElementById(\'', $element_id, '\').style.display=\'none\'';
         echo '</script>';
         echo '<select id="', $element_id, '_sel" onchange="document.getElementById(\'', $element_id, '\').value=this.value;" >';
         foreach (array('Unknown', 'Civil', 'Religious', 'Partners') as $key) {
             if ($key === 'Unknown') {
                 echo '<option value="" ';
             } else {
                 echo '<option value="', $key, '" ';
             }
             $a = strtolower($key);
             $b = strtolower($value);
             if ($b !== '' && strpos($a, $b) !== false || strpos($b, $a) !== false) {
                 echo 'selected';
             }
             echo '>', GedcomTag::getLabel('MARR_' . strtoupper($key)), '</option>';
         }
         echo '</select>';
     } elseif ($fact === 'TYPE' && $level === 0) {
         // NAME TYPE : hide text field and show a selection list
         $onchange = 'onchange="document.getElementById(\'' . $element_id . '\').value=this.value;"';
         echo self::editFieldNameType($element_name, $value, $onchange, $person);
         echo '<script>document.getElementById("', $element_id, '").style.display="none";</script>';
     }
     // popup links
     switch ($fact) {
         case 'DATE':
             echo self::printCalendarPopup($element_id);
             break;
         case 'FAMC':
         case 'FAMS':
             echo FunctionsPrint::printFindFamilyLink($element_id);
             break;
         case 'ALIA':
         case 'ASSO':
         case '_ASSO':
             echo FunctionsPrint::printFindIndividualLink($element_id, $element_id . '_description');
             break;
         case 'FILE':
             FunctionsPrint::printFindMediaLink($element_id, '0file');
             break;
         case 'SOUR':
             echo FunctionsPrint::printFindSourceLink($element_id, $element_id . '_description'), ' ', self::printAddNewSourceLink($element_id);
             //-- checkboxes to apply '1 SOUR' to BIRT/MARR/DEAT as '2 SOUR'
             if ($level === 1) {
                 echo '<br>';
                 switch ($WT_TREE->getPreference('PREFER_LEVEL2_SOURCES')) {
                     case '2':
                         // records
                         $level1_checked = 'checked';
                         $level2_checked = '';
                         break;
                     case '1':
                         // facts
                         $level1_checked = '';
                         $level2_checked = 'checked';
                         break;
                     case '0':
                         // none
                     // none
                     default:
                         $level1_checked = '';
                         $level2_checked = '';
                         break;
                 }
                 if (strpos($bdm, 'B') !== false) {
                     echo ' <label><input type="checkbox" name="SOUR_INDI" ', $level1_checked, ' value="1">', I18N::translate('Individual'), '</label>';
                     if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
                         foreach ($matches[1] as $match) {
                             if (!in_array($match, explode('|', WT_EVENTS_DEAT))) {
                                 echo ' <label><input type="checkbox" name="SOUR_', $match, '" ', $level2_checked, ' value="1">', GedcomTag::getLabel($match), '</label>';
                             }
                         }
                     }
                 }
                 if (strpos($bdm, 'D') !== false) {
                     if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
                         foreach ($matches[1] as $match) {
                             if (in_array($match, explode('|', WT_EVENTS_DEAT))) {
                                 echo ' <label><input type="checkbox" name="SOUR_', $match, '"', $level2_checked, ' value="1">', GedcomTag::getLabel($match), '</label>';
                             }
                         }
                     }
                 }
                 if (strpos($bdm, 'M') !== false) {
                     echo ' <label><input type="checkbox" name="SOUR_FAM" ', $level1_checked, ' value="1">', I18N::translate('Family'), '</label>';
                     if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FAMFACTS'), $matches)) {
                         foreach ($matches[1] as $match) {
                             echo ' <label><input type="checkbox" name="SOUR_', $match, '"', $level2_checked, ' value="1">', GedcomTag::getLabel($match), '</label>';
                         }
                     }
                 }
             }
             break;
         case 'REPO':
             echo FunctionsPrint::printFindRepositoryLink($element_id), ' ', self::printAddNewRepositoryLink($element_id);
             break;
         case 'NOTE':
             // Shared Notes Icons ========================================
             if ($islink) {
                 // Print regular Shared Note icons ---------------------------
                 echo ' ', FunctionsPrint::printFindNoteLink($element_id, $element_id . '_description'), ' ', self::printAddNewNoteLink($element_id);
                 if ($value) {
                     echo ' ', self::printEditNoteLink($value);
                 }
             }
             break;
         case 'OBJE':
             echo FunctionsPrint::printFindMediaLink($element_id, '1media');
             if (!$value) {
                 echo ' ', self::printAddNewMediaLink($element_id);
                 $value = 'new';
             }
             break;
     }
     echo '<div id="' . $element_id . '_description">';
     // current value
     if ($fact === 'DATE') {
         $date = new Date($value);
         echo $date->display();
     }
     if (($fact === 'ASSO' || $fact === '_ASSO') && $value === '') {
         if ($level === 1) {
             echo '<p class="small text-muted">' . I18N::translate('An associate is another individual who was involved with this individual, such as a friend or an employer.') . '</p>';
         } else {
             echo '<p class="small text-muted">' . I18N::translate('An associate is another individual who was involved with this fact or event, such as a witness or a priest.') . '</p>';
         }
     }
     if ($value && $value !== 'new' && $islink) {
         switch ($fact) {
             case 'ALIA':
             case 'ASSO':
             case '_ASSO':
                 $tmp = Individual::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'SOUR':
                 $tmp = Source::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'NOTE':
                 $tmp = Note::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'OBJE':
                 $tmp = Media::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
             case 'REPO':
                 $tmp = Repository::getInstance($value, $WT_TREE);
                 if ($tmp) {
                     echo ' ', $tmp->getFullName();
                 }
                 break;
         }
     }
     // pastable values
     if ($fact === 'FORM' && $upperlevel === 'OBJE') {
         FunctionsPrint::printAutoPasteLink($element_id, Config::fileFormats());
     }
     echo '</div>', $extra, '</td></tr>';
     return $element_id;
 }
 /**
  * Startup activity
  */
 public function __construct()
 {
     // Automatically fix broken links
     if ($this->record && $this->record->canEdit()) {
         $broken_links = 0;
         foreach ($this->record->getFacts('HUSB|WIFE|CHIL|FAMS|FAMC|REPO') as $fact) {
             if (!$fact->isPendingDeletion() && $fact->getTarget() === null) {
                 $this->record->deleteFact($fact->getFactId(), false);
                 FlashMessages::addMessage(I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $this->record->getFullName(), $fact->getValue()));
                 $broken_links = true;
             }
         }
         foreach ($this->record->getFacts('NOTE|SOUR|OBJE') as $fact) {
             // These can be links or inline.  Only delete links.
             if (!$fact->isPendingDeletion() && $fact->getTarget() === null && preg_match('/^@.*@$/', $fact->getValue())) {
                 $this->record->deleteFact($fact->getFactId(), false);
                 FlashMessages::addMessage(I18N::translate('The link from “%1$s” to “%2$s” has been deleted.', $this->record->getFullName(), $fact->getValue()));
                 $broken_links = true;
             }
         }
         if ($broken_links) {
             // Reload the updated family
             $this->record = GedcomRecord::getInstance($this->record->getXref(), $this->record->getTree());
         }
     }
     parent::__construct();
     // We want robots to index this page
     $this->setMetaRobots('index,follow');
     // Set a page title
     if ($this->record) {
         if ($this->record->canShowName()) {
             // e.g. "John Doe" or "1881 Census of Wales"
             $this->setPageTitle($this->record->getFullName());
         } else {
             // e.g. "Individual" or "Source"
             $record = $this->record;
             $this->setPageTitle(GedcomTag::getLabel($record::RECORD_TYPE));
         }
     } else {
         // No such record
         $this->setPageTitle(I18N::translate('Private'));
     }
 }
Example #14
0
 /**
  * Search the shared notes
  *
  * @param string[] $query Search terms
  * @param Tree[] $trees The tree to search
  *
  * @return Note[]
  */
 public static function searchNotes(array $query, array $trees)
 {
     // Convert the query into a regular expression
     $queryregex = array();
     $sql = "SELECT o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom FROM `##other` WHERE o_type = 'NOTE'";
     $args = array();
     foreach ($query as $n => $q) {
         $queryregex[] = preg_quote(I18N::strtoupper($q), '/');
         $sql .= " AND o_gedcom COLLATE :collate_" . $n . " LIKE CONCAT('%', :query_" . $n . ", '%')";
         $args['collate_' . $n] = I18N::collation();
         $args['query_' . $n] = Filter::escapeLike($q);
     }
     $sql .= " AND o_file IN (";
     foreach ($trees as $n => $tree) {
         $sql .= $n ? ", " : "";
         $sql .= ":tree_id_" . $n;
         $args['tree_id_' . $n] = $tree->getTreeId();
     }
     $sql .= ")";
     $list = array();
     $rows = Database::prepare($sql)->execute($args)->fetchAll();
     foreach ($rows as $row) {
         // SQL may have matched on private data or gedcom tags, so check again against privatized data.
         $record = Note::getInstance($row->xref, Tree::findById($row->gedcom_id), $row->gedcom);
         // Ignore non-genealogy data
         $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
         $gedrec = preg_replace('/\\n\\d ' . WT_REGEX_TAG . ' ?/', '', $gedrec);
         // Re-apply the filtering
         $gedrec = I18N::strtoupper($gedrec);
         foreach ($queryregex as $regex) {
             if (!preg_match('/' . $regex . '/', $gedrec)) {
                 continue 2;
             }
         }
         $list[] = $record;
     }
     $list = array_filter($list, function (Note $x) {
         return $x->canShowName();
     });
     return $list;
 }
Example #15
0
 /**
  * Print a row for the notes tab on the individual page.
  *
  * @param Fact $fact
  * @param int $level
  */
 public static function printMainNotes(Fact $fact, $level)
 {
     $factrec = $fact->getGedcom();
     $fact_id = $fact->getFactId();
     $parent = $fact->getParent();
     $pid = $parent->getXref();
     if ($fact->isPendingAddition()) {
         $styleadd = ' new';
         $can_edit = $level == 1 && $fact->canEdit();
     } elseif ($fact->isPendingDeletion()) {
         $styleadd = ' old';
         $can_edit = false;
     } else {
         $styleadd = '';
         $can_edit = $level == 1 && $fact->canEdit();
     }
     $ct = preg_match_all("/{$level} NOTE (.*)/", $factrec, $match, PREG_SET_ORDER);
     for ($j = 0; $j < $ct; $j++) {
         // Note object, or inline note?
         if (preg_match("/{$level} NOTE @(.*)@/", $match[$j][0], $nmatch)) {
             $note = Note::getInstance($nmatch[1], $fact->getParent()->getTree());
             if ($note && !$note->canShow()) {
                 continue;
             }
         } else {
             $note = null;
         }
         if ($level >= 2) {
             echo '<tr class="row_note2"><td class="descriptionbox rela ', $styleadd, ' width20">';
         } else {
             echo '<tr><td class="descriptionbox ', $styleadd, ' width20">';
         }
         if ($can_edit) {
             echo '<a onclick="return edit_record(\'', $pid, '\', \'', $fact_id, '\');" href="#" title="', I18N::translate('Edit'), '">';
             if ($level < 2) {
                 if ($fact->getParent()->getTree()->getPreference('SHOW_FACT_ICONS')) {
                     echo '<i class="icon-note"></i> ';
                 }
                 if ($note) {
                     echo GedcomTag::getLabel('SHARED_NOTE');
                 } else {
                     echo GedcomTag::getLabel('NOTE');
                 }
                 echo '</a>';
                 echo '<div class="editfacts">';
                 echo "<div class=\"editlink\"><a class=\"editicon\" onclick=\"return edit_record('{$pid}', '{$fact_id}');\" href=\"#\" title=\"" . I18N::translate('Edit') . "\"><span class=\"link_text\">" . I18N::translate('Edit') . "</span></a></div>";
                 echo '<div class="copylink"><a class="copyicon" href="#" onclick="return copy_fact(\'', $pid, '\', \'', $fact_id, '\');" title="' . I18N::translate('Copy') . '"><span class="link_text">' . I18N::translate('Copy') . '</span></a></div>';
                 echo "<div class=\"deletelink\"><a class=\"deleteicon\" onclick=\"return delete_fact('" . I18N::translate('Are you sure you want to delete this fact?') . "', '{$pid}', '{$fact_id}');\" href=\"#\" title=\"" . I18N::translate('Delete') . "\"><span class=\"link_text\">" . I18N::translate('Delete') . "</span></a></div>";
                 if ($note) {
                     echo '<a class="icon-note" href="', $note->getHtmlUrl(), '" title="' . I18N::translate('View') . '"><span class="link_text">' . I18N::translate('View') . '</span></a>';
                 }
                 echo '</div>';
             }
         } else {
             if ($level < 2) {
                 if ($fact->getParent()->getTree()->getPreference('SHOW_FACT_ICONS')) {
                     echo '<i class="icon-note"></i> ';
                 }
                 if ($note) {
                     echo GedcomTag::getLabel('SHARED_NOTE');
                 } else {
                     echo GedcomTag::getLabel('NOTE');
                 }
             }
             $factlines = explode("\n", $factrec);
             // 1 BIRT Y\n2 NOTE ...
             $factwords = explode(" ", $factlines[0]);
             // 1 BIRT Y
             $factname = $factwords[1];
             // BIRT
             $parent = GedcomRecord::getInstance($pid, $fact->getParent()->getTree());
             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 = trim($ematch[1]);
                     echo $factname;
                 } else {
                     echo GedcomTag::getLabel($factname, $parent);
                 }
             } elseif ($factname != 'NOTE') {
                 // Note is already printed
                 echo GedcomTag::getLabel($factname, $parent);
                 if ($note) {
                     echo '<div class="editfacts"><a class="icon-note" href="', $note->getHtmlUrl(), '" title="' . I18N::translate('View') . '"><span class="link_text">' . I18N::translate('View') . '</span></a></div>';
                 }
             }
         }
         echo '</td>';
         if ($note) {
             // Note objects
             if (Module::getModuleByName('GEDFact_assistant')) {
                 // If Census assistant installed, allow it to format the note
                 $text = CensusAssistantModule::formatCensusNote($note);
             } else {
                 $text = Filter::formatText($note->getNote(), $fact->getParent()->getTree());
             }
         } else {
             // Inline notes
             $nrec = Functions::getSubRecord($level, "{$level} NOTE", $factrec, $j + 1);
             $text = $match[$j][1] . Functions::getCont($level + 1, $nrec);
             $text = Filter::formatText($text, $fact->getParent()->getTree());
         }
         echo '<td class="optionbox', $styleadd, ' wrap">';
         echo $text;
         if (!empty($noterec)) {
             echo self::printFactSources($noterec, 1);
         }
         // 2 RESN tags.  Note, there can be more than one, such as "privacy" and "locked"
         if (preg_match_all("/\n2 RESN (.+)/", $factrec, $matches)) {
             foreach ($matches[1] as $match) {
                 echo '<br><span class="label">', GedcomTag::getLabel('RESN'), ':</span> <span class="field">';
                 switch ($match) {
                     case 'none':
                         // Note: "2 RESN none" is not valid gedcom, and the GUI will not let you add it.
                         // However, webtrees privacy rules will interpret it as "show an otherwise private fact to public".
                         echo '<i class="icon-resn-none"></i> ', I18N::translate('Show to visitors');
                         break;
                     case 'privacy':
                         echo '<i class="icon-resn-privacy"></i> ', I18N::translate('Show to members');
                         break;
                     case 'confidential':
                         echo '<i class="icon-resn-confidential"></i> ', I18N::translate('Show to managers');
                         break;
                     case 'locked':
                         echo '<i class="icon-resn-locked"></i> ', I18N::translate('Only managers can edit');
                         break;
                     default:
                         echo $match;
                         break;
                 }
                 echo '</span>';
             }
         }
         echo '</td></tr>';
     }
 }
Example #16
0
 /**
  * Export the database in GEDCOM format
  *
  * @param Tree $tree Which tree to export
  * @param resource $gedout Handle to a writable stream
  * @param string[] $exportOptions Export options are as follows:
  *                                'privatize':    which Privacy rules apply? (none, visitor, user, manager)
  *                                'toANSI':       should the output be produced in ISO-8859-1 instead of UTF-8? (yes, no)
  *                                'path':         what constant should prefix all media file paths? (eg: media/  or c:\my pictures\my family
  *                                'slashes':      what folder separators apply to media file paths? (forward, backward)
  */
 public static function exportGedcom(Tree $tree, $gedout, $exportOptions)
 {
     switch ($exportOptions['privatize']) {
         case 'gedadmin':
             $access_level = Auth::PRIV_NONE;
             break;
         case 'user':
             $access_level = Auth::PRIV_USER;
             break;
         case 'visitor':
             $access_level = Auth::PRIV_PRIVATE;
             break;
         case 'none':
             $access_level = Auth::PRIV_HIDE;
             break;
     }
     $head = self::gedcomHeader($tree);
     if ($exportOptions['toANSI'] == 'yes') {
         $head = str_replace('UTF-8', 'ANSI', $head);
         $head = utf8_decode($head);
     }
     $head = self::reformatRecord($head);
     fwrite($gedout, $head);
     // Buffer the output. Lots of small fwrite() calls can be very slow when writing large gedcoms.
     $buffer = '';
     // Generate the OBJE/SOUR/REPO/NOTE records first, as their privacy calcualations involve
     // database queries, and we wish to avoid large gaps between queries due to MySQL connection timeouts.
     $tmp_gedcom = '';
     $rows = Database::prepare("SELECT m_id AS xref, m_gedcom AS gedcom" . " FROM `##media` WHERE m_file = :tree_id ORDER BY m_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Media::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         $rec = self::convertMediaPath($rec, $exportOptions['path']);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $tmp_gedcom .= self::reformatRecord($rec);
     }
     $rows = Database::prepare("SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom" . " FROM `##sources` WHERE s_file = :tree_id ORDER BY s_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Source::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $tmp_gedcom .= self::reformatRecord($rec);
     }
     $rows = Database::prepare("SELECT o_type AS type, o_id AS xref, o_gedcom AS gedcom" . " FROM `##other` WHERE o_file = :tree_id AND o_type NOT IN ('HEAD', 'TRLR') ORDER BY o_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         switch ($row->type) {
             case 'NOTE':
                 $record = Note::getInstance($row->xref, $tree, $row->gedcom);
                 break;
             case 'REPO':
                 $record = Repository::getInstance($row->xref, $tree, $row->gedcom);
                 break;
             default:
                 $record = GedcomRecord::getInstance($row->xref, $tree, $row->gedcom);
                 break;
         }
         $rec = $record->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $tmp_gedcom .= self::reformatRecord($rec);
     }
     $rows = Database::prepare("SELECT i_id AS xref, i_gedcom AS gedcom" . " FROM `##individuals` WHERE i_file = :tree_id ORDER BY i_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Individual::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $buffer .= self::reformatRecord($rec);
         if (strlen($buffer) > 65536) {
             fwrite($gedout, $buffer);
             $buffer = '';
         }
     }
     $rows = Database::prepare("SELECT f_id AS xref, f_gedcom AS gedcom" . " FROM `##families` WHERE f_file = :tree_id ORDER BY f_id")->execute(array('tree_id' => $tree->getTreeId()))->fetchAll();
     foreach ($rows as $row) {
         $rec = Family::getInstance($row->xref, $tree, $row->gedcom)->privatizeGedcom($access_level);
         if ($exportOptions['toANSI'] === 'yes') {
             $rec = utf8_decode($rec);
         }
         $buffer .= self::reformatRecord($rec);
         if (strlen($buffer) > 65536) {
             fwrite($gedout, $buffer);
             $buffer = '';
         }
     }
     fwrite($gedout, $buffer);
     fwrite($gedout, $tmp_gedcom);
     fwrite($gedout, '0 TRLR' . WT_EOL);
 }
Example #17
0
        if ($linkto == "repository") {
            echo I18N::translate('Repository'), "</td>";
            echo '<td  class="optionbox wrap">';
            if ($linktoid == "") {
                echo '<input class="pedigree_form" type="text" name="linktoid" id="linktorid" size="3" value="', $linktoid, '">';
            } else {
                $record = Repository::getInstance($linktoid, $WT_TREE);
                echo $record->formatList('span', false, $record->getFullName());
            }
        }
        if ($linkto == "note") {
            echo I18N::translate('Shared note'), "</td>";
            echo '<td  class="optionbox wrap">';
            if ($linktoid == "") {
                echo '<input class="pedigree_form" type="text" name="linktoid" id="linktonid" size="3" value="', $linktoid, '">';
            } else {
                $record = Note::getInstance($linktoid, $WT_TREE);
                echo $record->formatList('span', false, $record->getFullName());
            }
        }
        echo '</td></tr>';
        echo '<tr><td class="topbottombar" colspan="2"><input type="submit" value="', I18N::translate('Set link'), '"></td></tr>';
        echo '</table>';
        echo '</form>';
    } elseif ($action == "update" && $paramok) {
        $record = GedcomRecord::getInstance($linktoid, $WT_TREE);
        $record->createFact('1 OBJE @' . $mediaid . '@', true);
        $controller->addInlineJavascript('closePopupAndReloadParent();');
    }
    echo '<button onclick="closePopupAndReloadParent();">', I18N::translate('close'), '</button>';
}
Example #18
0
 /**
  * Print all of the notes in this fact record
  *
  * @param string $factrec The factrecord to print the notes from
  * @param int $level The level of the factrecord
  * @param bool $textOnly Don't print the "Note: " introduction
  *
  * @return string HTML
  */
 public static function printFactNotes($factrec, $level, $textOnly = false)
 {
     global $WT_TREE;
     $data = '';
     $previous_spos = 0;
     $nlevel = $level + 1;
     $ct = preg_match_all("/{$level} NOTE (.*)/", $factrec, $match, PREG_SET_ORDER);
     for ($j = 0; $j < $ct; $j++) {
         $spos1 = strpos($factrec, $match[$j][0], $previous_spos);
         $spos2 = strpos($factrec . "\n{$level}", "\n{$level}", $spos1 + 1);
         if (!$spos2) {
             $spos2 = strlen($factrec);
         }
         $previous_spos = $spos2;
         $nrec = substr($factrec, $spos1, $spos2 - $spos1);
         if (!isset($match[$j][1])) {
             $match[$j][1] = '';
         }
         if (!preg_match('/@(.*)@/', $match[$j][1], $nmatch)) {
             $data .= self::printNoteRecord($match[$j][1], $nlevel, $nrec, $textOnly);
         } else {
             $note = Note::getInstance($nmatch[1], $WT_TREE);
             if ($note) {
                 if ($note->canShow()) {
                     $noterec = $note->getGedcom();
                     $nt = preg_match("/0 @{$nmatch['1']}@ NOTE (.*)/", $noterec, $n1match);
                     $data .= self::printNoteRecord($nt > 0 ? $n1match[1] : "", 1, $noterec, $textOnly);
                     if (!$textOnly) {
                         if (strpos($noterec, '1 SOUR') !== false) {
                             $data .= FunctionsPrintFacts::printFactSources($noterec, 1);
                         }
                     }
                 }
             } else {
                 $data = '<div class="fact_NOTE"><span class="label">' . I18N::translate('Note') . '</span>: <span class="field error">' . $nmatch[1] . '</span></div>';
             }
         }
         if (!$textOnly) {
             if (strpos($factrec, "{$nlevel} SOUR") !== false) {
                 $data .= "<div class=\"indent\">";
                 $data .= FunctionsPrintFacts::printFactSources($nrec, $nlevel);
                 $data .= "</div>";
             }
         }
     }
     return $data;
 }
 /**
  * Convert custom markup into HTML
  *
  * @param Note $note
  *
  * @return string
  */
 public static function formatCensusNote(Note $note)
 {
     global $WT_TREE;
     $headers = array('AgM' => 'Age at first marriage', 'Age' => 'Age at last birthday', 'Assets' => 'Assets = Owned,Rented - Value,Rent - Radio - Farm', 'BIC' => 'Born in County', 'BOE' => 'Born outside England', 'BP' => 'Birthplace - (Chapman format)', 'Birthplace' => 'Birthplace (Full format)', 'Bmth' => 'Month of birth - If born within Census year', 'ChB' => 'Children born alive', 'ChD' => 'Children who have died', 'ChL' => 'Children still living', 'DOB' => 'Date of birth', 'Edu' => 'Education - At School, Can Read, Can Write', 'EmD' => 'Employed?', 'EmN' => 'Unemployed?', 'EmR' => 'Employer?', 'Employ' => 'Employment', 'Eng?' => 'English spoken?', 'EngL' => 'English spoken?, if not, Native Language', 'FBP' => 'Father’s Birthplace - (Chapman format)', 'Health' => 'Health - 1.Blind, 2.Deaf & Dumb, 3.Idiotic, 4.Insane, 5.Disabled etc', 'Home' => 'Home Ownership - Owned/Rented-Free/Mortgaged-Farm/House-Farm Schedule number', 'Industry' => 'Industry', 'Infirm' => 'Infirmities - 1. Deaf & Dumb, 2. Blind, 3. Lunatic, 4. Imbecile/feeble-minded', 'Lang' => 'If Foreign Born - Native Language', 'MBP' => 'Mother’s Birthplace - (Chapman format)', 'MC' => 'Marital Condition - Married, Single, Unmarried, Widowed or Divorced', 'Mmth' => 'Month of marriage - If married during Census Year', 'MnsE' => 'Months employed during Census Year', 'MnsU' => 'Months unemployed during Census Year', 'N/A' => 'If Foreign Born - Naturalized, Alien', 'NL' => 'If Foreign Born - Native Language', 'Name' => 'Full Name or Married name if married', 'Occupation' => 'Occupation', 'Par' => 'Parentage - Father if foreign born, Mother if foreign born', 'Race' => 'Race or Color - Black, White, Mulatto, Asian, Indian, Chinese etc', 'Relation' => 'Relationship to Head of Household', 'Sex' => 'Male or Female', 'Situ' => 'Situation - Disease, Infirmity, Convict, Pauper etc', 'Ten' => 'Tenure - Owned/Rented, (if owned)Free/Morgaged', 'Vet' => 'War Veteran?', 'WH' => 'Working at Home?', 'War' => 'War or Expedition', 'WksU' => 'Weeks unemployed during Census Year', 'YOI' => 'If Foreign Born - Year of immigration', 'YON' => 'If Foreign Born - Year of naturalization', 'YUS' => 'If Foreign Born - Years in the USA', 'YrsM' => 'Years Married, or Y if married in Census Year');
     if (preg_match('/(.*)((?:\\n.*)*)\\n\\.start_formatted_area\\.\\n(.*)((?:\\n.*)*)\\n.end_formatted_area\\.((?:\\n.*)*)/', $note->getNote(), $match)) {
         // This looks like a census-assistant shared note
         $title = Filter::escapeHtml($match[1]);
         $preamble = Filter::escapeHtml($match[2]);
         $header = Filter::escapeHtml($match[3]);
         $data = Filter::escapeHtml($match[4]);
         $postamble = Filter::escapeHtml($match[5]);
         $fmt_headers = array();
         foreach ($headers as $key => $value) {
             $fmt_headers[$key] = '<span title="' . Filter::escapeHtml($value) . '">' . $key . '</span>';
         }
         // Substitue header labels and format as HTML
         $thead = '<tr><th>' . strtr(str_replace('|', '</th><th>', $header), $fmt_headers) . '</th></tr>';
         $thead = str_replace('.b.', '', $thead);
         // Format data as HTML
         $tbody = '';
         foreach (explode("\n", $data) as $row) {
             $tbody .= '<tr>';
             foreach (explode('|', $row) as $column) {
                 $tbody .= '<td>' . $column . '</td>';
             }
             $tbody .= '</tr>';
         }
         return $title . "\n" . '<p>' . $preamble . '</p>' . '<table class="table-census-assistant">' . '<thead>' . $thead . '</thead>' . '<tbody>' . $tbody . '</tbody>' . '</table>' . '<p>' . $postamble . '</p>';
     } else {
         // Not a census-assistant shared note - apply default formatting
         return Filter::formatText($note->getNote(), $WT_TREE);
     }
 }