/**
  * 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;
 }
 /**
  * Default previewer for plugins with no custom preview.
  *
  * @param GedcomRecord $record
  *
  * @return string
  */
 public function getActionPreview(GedcomRecord $record)
 {
     $old_lines = preg_split('/[\\n]+/', $record->getGedcom());
     $new_lines = preg_split('/[\\n]+/', $this->updateRecord($record->getXref(), $record->getGedcom()));
     // Find matching lines using longest-common-subsequence algorithm.
     $lcs = self::longestCommonSubsequence($old_lines, $new_lines, 0, count($old_lines) - 1, 0, count($new_lines) - 1);
     $diff_lines = array();
     $last_old = -1;
     $last_new = -1;
     while ($lcs) {
         list($old, $new) = array_shift($lcs);
         while ($last_old < $old - 1) {
             $diff_lines[] = self::decorateDeletedText($old_lines[++$last_old]);
         }
         while ($last_new < $new - 1) {
             $diff_lines[] = self::decorateInsertedText($new_lines[++$last_new]);
         }
         $diff_lines[] = $new_lines[$new];
         $last_old = $old;
         $last_new = $new;
     }
     while ($last_old < count($old_lines) - 1) {
         $diff_lines[] = self::decorateDeletedText($old_lines[++$last_old]);
     }
     while ($last_new < count($new_lines) - 1) {
         $diff_lines[] = self::decorateInsertedText($new_lines[++$last_new]);
     }
     return '<pre class="gedcom-data">' . self::createEditLinks(implode("\n", $diff_lines)) . '</pre>';
 }
 /**
  * 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'));
     }
 }
 /**
  * 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;
 }
Example #5
0
 /**
  * Accept all pending changes for a specified record.
  *
  * @param GedcomRecord $record
  */
 public static function rejectAllChanges(GedcomRecord $record)
 {
     Database::prepare("UPDATE `##change`" . " SET status = 'rejected'" . " WHERE status = 'pending' AND xref = :xref AND gedcom_id = :tree_id")->execute(array('xref' => $record->getXref(), 'tree_id' => $record->getTree()->getTreeId()));
 }
Example #6
0
 /**
  * Create a form to edit a Fact object.
  *
  * @param GedcomRecord $record
  * @param Fact $fact
  *
  * @return string
  */
 public static function createEditForm(GedcomRecord $record, Fact $fact)
 {
     global $tags, $WT_TREE;
     $pid = $record->getXref();
     $tags = array();
     $gedlines = explode("\n", $fact->getGedcom());
     $linenum = 0;
     $fields = explode(' ', $gedlines[$linenum]);
     $glevel = $fields[0];
     $level = $glevel;
     $type = $fact->getTag();
     $parent = $fact->getParent();
     $level0type = $parent::RECORD_TYPE;
     $level1type = $type;
     $i = $linenum;
     $inSource = false;
     $levelSource = 0;
     $add_date = true;
     // List of tags we would expect at the next level
     // NB add_missing_subtags() already takes care of the simple cases
     // where a level 1 tag is missing a level 2 tag. Here we only need to
     // handle the more complicated cases.
     $expected_subtags = array('SOUR' => array('PAGE', 'DATA'), 'DATA' => array('TEXT'), 'PLAC' => array('MAP'), 'MAP' => array('LATI', 'LONG'));
     if ($record->getTree()->getPreference('FULL_SOURCES')) {
         $expected_subtags['SOUR'][] = 'QUAY';
         $expected_subtags['DATA'][] = 'DATE';
     }
     if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $record->getTree()->getPreference('ADVANCED_PLAC_FACTS'), $match)) {
         $expected_subtags['PLAC'] = array_merge($match[1], $expected_subtags['PLAC']);
     }
     $stack = array(0 => $level0type);
     // Loop on existing tags :
     while (true) {
         // Keep track of our hierarchy, e.g. 1=>BIRT, 2=>PLAC, 3=>FONE
         $stack[(int) $level] = $type;
         // Merge them together, e.g. BIRT:PLAC:FONE
         $label = implode(':', array_slice($stack, 1, $level));
         $text = '';
         for ($j = 2; $j < count($fields); $j++) {
             if ($j > 2) {
                 $text .= ' ';
             }
             $text .= $fields[$j];
         }
         $text = rtrim($text);
         while ($i + 1 < count($gedlines) && preg_match("/" . ($level + 1) . ' CONT ?(.*)/', $gedlines[$i + 1], $cmatch) > 0) {
             $text .= "\n" . $cmatch[1];
             $i++;
         }
         if ($type === 'SOUR') {
             $inSource = true;
             $levelSource = $level;
         } elseif ($levelSource >= $level) {
             $inSource = false;
         }
         if ($type !== 'DATA' && $type !== 'CONT') {
             $tags[] = $type;
             $person = Individual::getInstance($pid, $WT_TREE);
             $subrecord = $level . ' ' . $type . ' ' . $text;
             if ($inSource && $type === 'DATE') {
                 self::addSimpleTag($subrecord, '', GedcomTag::getLabel($label, $person));
             } elseif (!$inSource && $type === 'DATE') {
                 self::addSimpleTag($subrecord, $level1type, GedcomTag::getLabel($label, $person));
                 if ($level === '2') {
                     // We already have a date - no need to add one.
                     $add_date = false;
                 }
             } elseif ($type === 'STAT') {
                 self::addSimpleTag($subrecord, $level1type, GedcomTag::getLabel($label, $person));
             } elseif ($level0type === 'REPO') {
                 $repo = Repository::getInstance($pid, $WT_TREE);
                 self::addSimpleTag($subrecord, $level0type, GedcomTag::getLabel($label, $repo));
             } else {
                 self::addSimpleTag($subrecord, $level0type, GedcomTag::getLabel($label, $person));
             }
         }
         // Get a list of tags present at the next level
         $subtags = array();
         for ($ii = $i + 1; isset($gedlines[$ii]) && preg_match('/^\\s*(\\d+)\\s+(\\S+)/', $gedlines[$ii], $mm) && $mm[1] > $level; ++$ii) {
             if ($mm[1] == $level + 1) {
                 $subtags[] = $mm[2];
             }
         }
         // Insert missing tags
         if (!empty($expected_subtags[$type])) {
             foreach ($expected_subtags[$type] as $subtag) {
                 if (!in_array($subtag, $subtags)) {
                     if (!$inSource || $subtag !== 'DATA') {
                         self::addSimpleTag($level + 1 . ' ' . $subtag, '', GedcomTag::getLabel($label . ':' . $subtag));
                     }
                     if (!empty($expected_subtags[$subtag])) {
                         foreach ($expected_subtags[$subtag] as $subsubtag) {
                             self::addSimpleTag($level + 2 . ' ' . $subsubtag, '', GedcomTag::getLabel($label . ':' . $subtag . ':' . $subsubtag));
                         }
                     }
                 }
             }
         }
         // Awkward special cases
         if ($level == 2 && $type === 'DATE' && in_array($level1type, Config::dateAndTime()) && !in_array('TIME', $subtags)) {
             self::addSimpleTag('3 TIME');
             // TIME is NOT a valid 5.5.1 tag
         }
         if ($level == 2 && $type === 'STAT' && GedcomCodeTemp::isTagLDS($level1type) && !in_array('DATE', $subtags)) {
             self::addSimpleTag('3 DATE', '', GedcomTag::getLabel('STAT:DATE'));
         }
         $i++;
         if (isset($gedlines[$i])) {
             $fields = explode(' ', $gedlines[$i]);
             $level = $fields[0];
             if (isset($fields[1])) {
                 $type = trim($fields[1]);
             } else {
                 $level = 0;
             }
         } else {
             $level = 0;
         }
         if ($level <= $glevel) {
             break;
         }
     }
     if ($level1type !== '_PRIM') {
         self::insertMissingSubtags($level1type, $add_date);
     }
     return $level1type;
 }
 /**
  * Inserts a clipping into the clipping cart
  *
  * @param GedcomRecord $record
  */
 public function addClipping(GedcomRecord $record)
 {
     if ($record->canShowName()) {
         $this->cart[$record->getTree()->getTreeId()][$record->getXref()] = true;
         // Add directly linked records
         preg_match_all('/\\n\\d (?:OBJE|NOTE|SOUR|REPO) @(' . WT_REGEX_XREF . ')@/', $record->getGedcom(), $matches);
         foreach ($matches[1] as $match) {
             $this->cart[$record->getTree()->getTreeId()][$match] = true;
         }
     }
 }
 /**
  * Default previewer for plugins with no custom preview.
  *
  * @param GedcomRecord $record
  *
  * @return string
  */
 public function getActionPreview(GedcomRecord $record)
 {
     $old_lines = preg_split('/[\\n]+/', $record->getGedcom());
     $new_lines = preg_split('/[\\n]+/', $this->updateRecord($record->getXref(), $record->getGedcom()));
     $algorithm = new MyersDiff();
     $differences = $algorithm->calculate($old_lines, $new_lines);
     $diff_lines = array();
     foreach ($differences as $difference) {
         switch ($difference[1]) {
             case MyersDiff::DELETE:
                 $diff_lines[] = self::decorateDeletedText($difference[0]);
                 break;
             case MyersDiff::INSERT:
                 $diff_lines[] = self::decorateInsertedText($difference[0]);
                 break;
             default:
                 $diff_lines[] = $difference[0];
         }
     }
     return '<pre class="gedcom-data">' . self::createEditLinks(implode("\n", $diff_lines)) . '</pre>';
 }