summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Functions/FunctionsPrint.php6
-rw-r--r--app/Functions/FunctionsPrintFacts.php8
-rw-r--r--app/Http/Controllers/EditGedcomRecordController.php167
-rw-r--r--app/Http/Controllers/IndividualController.php2
-rw-r--r--app/Theme/AbstractTheme.php2
-rw-r--r--edit_interface.php323
-rw-r--r--resources/views/edit/add-fact.php94
-rw-r--r--resources/views/edit/edit-fact.php125
-rw-r--r--resources/views/family-page.php8
-rw-r--r--resources/views/individual-page-menu.php4
-rw-r--r--resources/views/individual-page.php2
-rw-r--r--resources/views/media-page.php6
-rw-r--r--resources/views/modules/notes/tab.php4
-rw-r--r--resources/views/modules/relatives/family.php2
-rw-r--r--resources/views/modules/sources_tab/tab.php2
-rw-r--r--resources/views/source-page.php2
-rw-r--r--routes/web.php3
17 files changed, 412 insertions, 348 deletions
diff --git a/app/Functions/FunctionsPrint.php b/app/Functions/FunctionsPrint.php
index ef0db29d5d..a499666915 100644
--- a/app/Functions/FunctionsPrint.php
+++ b/app/Functions/FunctionsPrint.php
@@ -539,8 +539,8 @@ class FunctionsPrint {
echo I18N::translate('Fact or event');
echo '</th>';
echo '<td>';
- echo '<form action="edit_interface.php" onsubmit="if ($(&quot;#add-fact&quot;).val() === null) {event.preventDefault();}">';
- echo '<input type="hidden" name="action" value="add">';
+ echo '<form onsubmit="if ($(&quot;#add-fact&quot;).val() === null) {event.preventDefault();}">';
+ echo '<input type="hidden" name="route" value="add-fact">';
echo '<input type="hidden" name="xref" value="' . e($record->getXref()) . '">';
echo '<input type="hidden" name="ged" value="' . e($tree->getName()) . '">';
echo '<select id="add-fact" name="fact">';
@@ -557,7 +557,7 @@ class FunctionsPrint {
echo '</form>';
echo '<span class="quickfacts">';
foreach ($quickfacts as $fact) {
- echo '<a href="edit_interface.php?action=add&amp;fact=' . $fact . '&amp;xref=' . e($record->getXref()) . '&amp;ged=' . e($tree->getName()) . '">', GedcomTag::getLabel($fact), '</a>';
+ echo '<a href="' . e(route('add-fact', ['fact' => $fact, 'xref' => $record->getXref(), 'ged' => $tree->getName()])) . '">', GedcomTag::getLabel($fact), '</a>';
}
echo '</span>';
echo '</td></tr>';
diff --git a/app/Functions/FunctionsPrintFacts.php b/app/Functions/FunctionsPrintFacts.php
index fbfa90ba9e..8eb6150646 100644
--- a/app/Functions/FunctionsPrintFacts.php
+++ b/app/Functions/FunctionsPrintFacts.php
@@ -191,7 +191,7 @@ class FunctionsPrintFacts {
?>
<?= $label ?>
<div class="editfacts">
- <?= FontAwesome::linkIcon('edit', I18N::translate('Edit'), ['class' => 'btn btn-link', 'href' => 'edit_interface.php?action=edit&xref=' . $parent->getXref() . '&fact_id=' . $fact->getFactId() . '&ged=' . e($tree->getName())]) ?>
+ <?= FontAwesome::linkIcon('edit', I18N::translate('Edit'), ['class' => 'btn btn-link', 'href' => route('edit-fact', ['xref' => $parent->getXref(), 'fact_id' => $fact->getFactId(), 'ged' . $tree->getName()])]) ?>
<?= FontAwesome::linkIcon('copy', I18N::translate('Copy'), ['class' => 'btn btn-link', 'href' => '#', 'onclick' => 'return copy_fact("' . e($tree->getName()) . '", "' . e($parent->getXref()) . '", "' . $fact->getFactId() . '");']) ?>
<?= FontAwesome::linkIcon('delete', I18N::translate('Delete'), ['class' => 'btn btn-link', 'href' => '#', 'onclick' => 'return delete_fact("' . I18N::translate('Are you sure you want to delete this fact?') . '", "' . e($tree->getName()) . '", "' . e($parent->getXref()) . '", "' . $fact->getFactId() . '");']) ?>
</div>
@@ -751,7 +751,7 @@ class FunctionsPrintFacts {
echo GedcomTag::getLabel($factname, $parent);
}
} elseif ($can_edit) {
- echo '<a href="edit_interface.php?action=edit&amp;xref=' . $parent->getXref() . '&amp;fact_id=' . $fact->getFactId() . '&amp;ged=' . e($tree->getName()) . '" title="', I18N::translate('Edit'), '">';
+ echo '<a href="' . e(route('edit-fact', ['xref' => $parent->getXref(), 'fact_id' => $fact->getFactId(), 'ged', $tree->getName()])) . '" title="', I18N::translate('Edit'), '">';
if ($tree->getPreference('SHOW_FACT_ICONS')) {
if ($level == 1) {
echo '<i class="icon-source"></i> ';
@@ -763,7 +763,7 @@ class FunctionsPrintFacts {
// Inline sources can't be edited. Attempting to save one will convert it
// into a link, and delete it.
// e.g. "1 SOUR my source" becomes "1 SOUR @my source@" which does not exist.
- echo FontAwesome::linkIcon('edit', I18N::translate('Edit'), ['class' => 'btn btn-link', 'href' => 'edit_interface.php?action=edit&xref=' . $parent->getXref() . '&fact_id=' . $fact->getFactId() . '&ged=' . e($tree->getName())]);
+ echo FontAwesome::linkIcon('edit', I18N::translate('Edit'), ['class' => 'btn btn-link', 'href' => route('edit-fact', ['xref' => $parent->getXref(), 'fact_id' => $fact->getFactId(), 'ged' => $tree->getName()])]);
echo FontAwesome::linkIcon('copy', I18N::translate('Copy'), ['class' => 'btn btn-link', 'href' => '#', 'onclick' => 'return copy_fact("' . e($tree->getName()) . '", "' . e($parent->getXref()) . '", "' . $fact->getFactId() . '");']);
}
echo FontAwesome::linkIcon('delete', I18N::translate('Delete'), ['class' => 'btn btn-link', 'href' => '#', 'onclick' => 'return delete_fact("' . I18N::translate('Are you sure you want to delete this fact?') . '", "' . e($tree->getName()) . '", "' . e($parent->getXref()) . '", "' . $fact->getFactId() . '");']);
@@ -978,7 +978,7 @@ class FunctionsPrintFacts {
echo GedcomTag::getLabel('NOTE');
}
echo '<div class="editfacts">';
- echo FontAwesome::linkIcon('edit', I18N::translate('Edit'), ['class' => 'btn btn-link', 'href' => 'edit_interface.php?action=edit&xref=' . $parent->getXref() . '&fact_id=' . $fact->getFactId() . '&ged=' . e($tree->getName())]);
+ echo FontAwesome::linkIcon('edit', I18N::translate('Edit'), ['class' => 'btn btn-link', 'href' => route('edit-fact', ['xref' => $parent->getXref(), 'fact_id' => $fact->getFactId(), 'ged' => $tree->getName()])]);
echo FontAwesome::linkIcon('copy', I18N::translate('Copy'), ['class' => 'btn btn-link', 'href' => '#', 'onclick' => 'return copy_fact("' . e($tree->getName()) . '", "' . e($parent->getXref()) . '", "' . $fact->getFactId() . '");']);
echo FontAwesome::linkIcon('delete', I18N::translate('Delete'), ['class' => 'btn btn-link', 'href' => '#', 'onclick' => 'return delete_fact("' . I18N::translate('Are you sure you want to delete this fact?') . '", "' . e($tree->getName()) . '", "' . e($parent->getXref()) . '", "' . $fact->getFactId() . '");']);
echo '</div>';
diff --git a/app/Http/Controllers/EditGedcomRecordController.php b/app/Http/Controllers/EditGedcomRecordController.php
index de4558fb8e..d2f9fb8bd8 100644
--- a/app/Http/Controllers/EditGedcomRecordController.php
+++ b/app/Http/Controllers/EditGedcomRecordController.php
@@ -22,12 +22,17 @@ use Fisharebest\Webtrees\FlashMessages;
use Fisharebest\Webtrees\Functions\FunctionsDb;
use Fisharebest\Webtrees\Functions\FunctionsEdit;
use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\GedcomTag;
use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Individual;
+use Fisharebest\Webtrees\Module;
+use Fisharebest\Webtrees\Module\CensusAssistantModule;
use Fisharebest\Webtrees\Session;
use Fisharebest\Webtrees\Tree;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Controller for edit forms and responses.
@@ -316,4 +321,166 @@ class EditGedcomRecordController extends AbstractBaseController {
return new RedirectResponse($record->url());
}
+
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function addFact(Request $request): Response {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
+
+ $xref = $request->get('xref', '');
+ $fact = $request->get('fact', '');
+
+ $record = GedcomRecord::getInstance($xref, $tree);
+ $this->checkRecordAccess($record, true);
+
+ $title = $record->getFullName() . ' - ' . GedcomTag::getLabel($fact, $record);
+
+ return $this->viewResponse('edit/add-fact', [
+ 'fact' => $fact,
+ 'record' => $record,
+ 'title' => $title,
+ 'tree' => $tree,
+ ]);
+ }
+
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function editFact(Request $request): Response {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
+
+ $xref = $request->get('xref', '');
+ $fact_id = $request->get('fact_id', '');
+
+ $record = GedcomRecord::getInstance($xref, $tree);
+ $this->checkRecordAccess($record, true);
+
+ // Find the fact to edit
+ $edit_fact = null;
+ foreach ($record->getFacts() as $fact) {
+ if ($fact->getFactId() === $fact_id && $fact->canEdit()) {
+ $edit_fact = $fact;
+ break;
+ }
+ }
+ if ($edit_fact === null) {
+ throw new NotFoundHttpException;
+ }
+
+ $can_edit_raw = Auth::isAdmin() || $tree->getPreference('SHOW_GEDCOM_RECORD');
+
+ $title = $record->getFullName() . ' - ' . GedcomTag::getLabel($edit_fact->getTag());
+
+ return $this->viewResponse('edit/edit-fact', [
+ 'can_edit_raw' => $can_edit_raw,
+ 'edit_fact' => $edit_fact,
+ 'record' => $record,
+ 'title' => $title,
+ 'tree' => $tree,
+ ]);
+ }
+
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function updateFact(Request $request): RedirectResponse {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
+
+ $xref = $request->get('xref', '');
+ $fact_id = $request->get('fact_id', '');
+
+ $record = GedcomRecord::getInstance($xref, $tree);
+ $this->checkRecordAccess($record, true);
+
+ $keep_chan = (bool) $request->get('keep_chan');
+
+ // Arrays for each GEDCOM line
+ global $glevels, $tag, $text, $islink;
+
+ $glevels = $request->get('glevels', []);
+ $tag = $request->get('tag', []);
+ $text = $request->get('text', []);
+ $islink = $request->get('islink', []);
+
+ // If the fact has a DATE or PLAC, then delete any value of Y
+ if ($text[0] === 'Y') {
+ foreach ($tag as $n => $value) {
+ if ($glevels[$n] == 2 && ($value === 'DATE' || $value === 'PLAC') && $text[$n] !== '') {
+ $text[0] = '';
+ break;
+ }
+ }
+ }
+
+ $newged = '';
+ if (!empty($_POST['NAME'])) {
+ $newged .= "\n1 NAME " . $_POST['NAME'];
+ $name_facts = ['TYPE', 'NPFX', 'GIVN', 'NICK', 'SPFX', 'SURN', 'NSFX'];
+ foreach ($name_facts as $name_fact) {
+ if (!empty($_POST[$name_fact])) {
+ $newged .= "\n2 " . $name_fact . ' ' . $_POST[$name_fact];
+ }
+ }
+ }
+
+ 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 = FunctionsEdit::handleUpdates($newged);
+
+ // Add new names after existing names
+ if (!empty($_POST['NAME'])) {
+ preg_match_all('/[_0-9A-Z]+/', $tree->getPreference('ADVANCED_NAME_FACTS'), $match);
+ $name_facts = array_unique(array_merge(['_MARNM'], $match[0]));
+ foreach ($name_facts as $name_fact) {
+ // Ignore advanced facts that duplicate standard facts.
+ if (!in_array($name_fact, ['TYPE', 'NPFX', 'GIVN', 'NICK', 'SPFX', 'SURN', 'NSFX']) && !empty($_POST[$name_fact])) {
+ $newged .= "\n2 " . $name_fact . ' ' . $_POST[$name_fact];
+ }
+ }
+ }
+
+ $newged = substr($newged, 1); // Remove leading newline
+
+ /** @var CensusAssistantModule $census_assistant */
+ $census_assistant = Module::getModuleByName('GEDFact_assistant');
+ if ($census_assistant !== null && $record instanceof Individual) {
+ $newged = $census_assistant->updateCensusAssistant($record, $fact_id, $newged, $keep_chan);
+ }
+
+ $record->updateFact($fact_id, $newged, !$keep_chan);
+
+ // For the GEDFact_assistant module
+ $pid_array = $request->get('pid_array', []);
+ if ($pid_array) {
+ foreach (explode(',', $pid_array) as $pid) {
+ if ($pid !== $xref) {
+ $indi = Individual::getInstance($pid, $tree);
+ if ($indi && $indi->canEdit()) {
+ $indi->updateFact($fact_id, $newged, !$keep_chan);
+ }
+ }
+ }
+ }
+
+ return new RedirectResponse($record->url());
+ }
}
diff --git a/app/Http/Controllers/IndividualController.php b/app/Http/Controllers/IndividualController.php
index 1370761d9a..97ba2f3005 100644
--- a/app/Http/Controllers/IndividualController.php
+++ b/app/Http/Controllers/IndividualController.php
@@ -370,7 +370,7 @@ class IndividualController extends AbstractBaseController {
if ($individual->canEdit() && !$fact->isPendingDeletion()) {
$edit_links = FontAwesome::linkIcon('edit', I18N::translate('Edit the gender'), [
'class' => 'btn btn-link',
- 'href' => 'edit_interface.php?action=edit&xref=' . $individual->getXref() . '&fact_id=' . $fact->getFactId() . '&ged=' . e($individual->getTree()->getName()),
+ 'href' => route('edit-fact', ['xref' => $individual->getXref(), 'fact_id' => $fact->getFactId(), 'ged' => $individual->getTree()->getName()])
]);
} else {
$edit_links = '';
diff --git a/app/Theme/AbstractTheme.php b/app/Theme/AbstractTheme.php
index 6510843c1a..24d3c0b9f6 100644
--- a/app/Theme/AbstractTheme.php
+++ b/app/Theme/AbstractTheme.php
@@ -16,11 +16,9 @@
namespace Fisharebest\Webtrees\Theme;
use Fisharebest\Webtrees\Auth;
-use Fisharebest\Webtrees\Controller\PageController;
use Fisharebest\Webtrees\Database;
use Fisharebest\Webtrees\Fact;
use Fisharebest\Webtrees\Filter;
-use Fisharebest\Webtrees\FlashMessages;
use Fisharebest\Webtrees\Functions\Functions;
use Fisharebest\Webtrees\GedcomRecord;
use Fisharebest\Webtrees\GedcomTag;
diff --git a/edit_interface.php b/edit_interface.php
index e7993c536a..f7ceed5b9c 100644
--- a/edit_interface.php
+++ b/edit_interface.php
@@ -30,329 +30,6 @@ $action = Filter::post('action', null, Filter::get('action'));
$controller = new PageController;
switch ($action) {
-case 'edit':
- //////////////////////////////////////////////////////////////////////////////
- // Edit a fact
- //////////////////////////////////////////////////////////////////////////////
- $tree = $controller->tree();
- $xref = Filter::get('xref', WT_REGEX_XREF);
- $fact_id = Filter::get('fact_id');
-
- $record = GedcomRecord::getInstance($xref, $tree);
- check_record_access($record);
-
- // Find the fact to edit
- $edit_fact = null;
- foreach ($record->getFacts() as $fact) {
- if ($fact->getFactId() === $fact_id && $fact->canEdit()) {
- $edit_fact = $fact;
- break;
- }
- }
- if (!$edit_fact) {
- header('Location: ' . $record->url());
- break;
- }
-
- $controller
- ->setPageTitle($record->getFullName() . ' - ' . GedcomTag::getLabel($edit_fact->getTag()))
- ->pageHeader();
-
- echo '<h2>', $controller->getPageTitle(), '</h2>';
- FunctionsPrint::initializeCalendarPopup();
- echo '<form name="editform" method="post" enctype="multipart/form-data">';
- echo '<input type="hidden" name="ged" value="', e($tree->getName()), '">';
- echo '<input type="hidden" name="action" value="update">';
- echo '<input type="hidden" name="fact_id" value="', $fact_id, '">';
- echo '<input type="hidden" name="xref" value="', $xref, '">';
- echo '<input type="hidden" name="prev_action" value="edit">';
- echo Filter::getCsrf();
- FunctionsEdit::createEditForm($edit_fact);
- echo keep_chan($record);
-
- $level1type = $edit_fact->getTag();
- switch ($record::RECORD_TYPE) {
- case 'REPO':
- // REPO:NAME facts may take a NOTE (but the REPO record may not).
- if ($level1type === 'NAME') {
- echo view('cards/add-note', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- echo view('addSimpleTag($tree, ', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- break;
- case 'FAM':
- case 'INDI':
- // FAM and INDI records have real facts. They can take NOTE/SOUR/OBJE/etc.
- if ($level1type !== 'SEX' && $level1type !== 'NOTE' && $level1type !== 'ALIA') {
- if ($level1type !== 'SOUR') {
- echo view('cards/add-source-citation', [
- 'level' => 2,
- 'full_citations' => $tree->getPreference('FULL_SOURCES'),
- 'tree' => $tree,
- ]); }
- if ($level1type !== 'OBJE') {
- if ($tree->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($tree)) {
- echo view('cards/add-media-object', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- }
- echo view('cards/add-note', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- echo view('cards/add-shared-note', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- if ($level1type !== 'ASSO' && $level1type !== 'NOTE' && $level1type !== 'SOUR') {
- echo view('cards/add-associate', [
- 'id' => Uuid::uuid4()->toString(),
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- // allow to add godfather and godmother for CHR fact or best man and bridesmaid for MARR fact in one window
- if (in_array($level1type, Config::twoAssociates())) {
- echo view('cards/add-associate', [
- 'id' => Uuid::uuid4()->toString(),
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- if ($level1type !== 'SOUR') {
- echo view('cards/add-restriction', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- }
- break;
- default:
- // Other types of record do not have these lower-level records
- break;
- }
-
- ?>
- <div class="row form-group">
- <div class="col-sm-9 offset-sm-3">
- <button class="btn btn-primary" type="submit">
- <?= FontAwesome::decorativeIcon('save') ?>
- <?= /* I18N: A button label. */
- I18N::translate('save') ?>
- </button>
- <a class="btn btn-secondary" href="<?= e($record->url()) ?>">
- <?= FontAwesome::decorativeIcon('cancel') ?>
- <?= /* I18N: A button label. */
- I18N::translate('cancel') ?>
- </a>
- <?php if (Auth::isAdmin() || $tree->getPreference('SHOW_GEDCOM_RECORD')): ?>
- <a class="btn btn-link" href="<?= e(route('edit-raw-fact', ['xref' => $xref, 'fact_id' => $fact_id, 'ged' => $tree->getName()])) ?>">
- <?= I18N::translate('Edit the raw GEDCOM') ?>
- </a>
- <?php endif; ?>
- </div>
- </div>
-
- </form>
- <?php
- echo view('modals/on-screen-keyboard');
- echo view('modals/ajax');
- break;
-
-case 'add':
- //////////////////////////////////////////////////////////////////////////////
- // Add a new fact
- //////////////////////////////////////////////////////////////////////////////
- $tree = $controller->tree();
- $xref = Filter::get('xref', WT_REGEX_XREF);
- $fact = Filter::get('fact', WT_REGEX_TAG);
-
- $record = GedcomRecord::getInstance($xref, $tree);
- check_record_access($record);
-
- $controller
- ->setPageTitle($record->getFullName() . ' - ' . GedcomTag::getLabel($fact, $record))
- ->pageHeader();
-
- $level0type = $record::RECORD_TYPE;
-
- echo '<h2>', $controller->getPageTitle(), '</h2>';
-
- FunctionsPrint::initializeCalendarPopup();
- echo '<form name="addform" method="post" enctype="multipart/form-data">';
- echo '<input type="hidden" name="ged" value="', e($tree->getName()), '">';
- echo '<input type="hidden" name="action" value="update">';
- echo '<input type="hidden" name="xref" value="', $xref, '">';
- echo '<input type="hidden" name="prev_action" value="add">';
- echo '<input type="hidden" name="fact_type" value="' . $fact . '">';
- echo Filter::getCsrf();
- FunctionsEdit::createAddForm($tree, $fact);
- echo keep_chan($record);
-
- // Genealogical facts (e.g. for INDI and FAM records) can have 2 SOUR/NOTE/OBJE/ASSO/RESN ...
- if ($level0type === 'INDI' || $level0type === 'FAM') {
- // ... but not facts which are simply links to other records
- if ($fact !== 'OBJE' && $fact !== 'NOTE' && $fact !== 'SHARED_NOTE' && $fact !== 'REPO' && $fact !== 'SOUR' && $fact !== 'SUBM' && $fact !== 'ASSO' && $fact !== 'ALIA' && $fact !== 'SEX') {
- echo view('cards/add-source-citation', [
- 'level' => 2,
- 'full_citations' => $tree->getPreference('FULL_SOURCES'),
- 'tree' => $tree,
- ]);
- if ($tree->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($tree)) {
- echo view('cards/add-media-object', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- // Don’t add notes to notes!
- if ($fact !== 'NOTE') {
- echo view('cards/add-note', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- echo view('cards/add-shared-note', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- echo view('cards/add-associate', [
- 'id' => Uuid::uuid4()->toString(),
- 'level' => 2,
- 'tree' => $tree,
- ]);
- // allow to add godfather and godmother for CHR fact or best man and bridesmaid for MARR fact in one window
- if (in_array($fact, Config::twoAssociates())) {
- echo view('cards/add-associate', [
- 'id' => Uuid::uuid4()->toString(),
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- echo view('cards/add-restriction', [
- 'level' => 2,
- 'tree' => $tree,
- ]);
- }
- }
- ?>
- <div class="row form-group">
- <div class="col-sm-9 offset-sm-3">
- <button class="btn btn-primary" type="submit">
- <?= FontAwesome::decorativeIcon('save') ?>
- <?= /* I18N: A button label. */
- I18N::translate('save') ?>
- </button>
- <a class="btn btn-secondary" href="<?= e($record->url()) ?>">
- <?= FontAwesome::decorativeIcon('cancel') ?>
- <?= /* I18N: A button label. */
- I18N::translate('cancel') ?>
- </a>
- </div>
- </div>
- </form>
- <?php
- echo view('modals/on-screen-keyboard');
- echo view('modals/ajax');
-
- break;
-
-case 'update':
- //////////////////////////////////////////////////////////////////////////////
- // Save a new/updated fact
- //////////////////////////////////////////////////////////////////////////////
- $tree = $controller->tree();
- $xref = Filter::post('xref', WT_REGEX_XREF);
- $fact_id = Filter::post('fact_id');
- $keep_chan = Filter::postBool('keep_chan');
-
- $record = GedcomRecord::getInstance($xref, $tree);
- check_record_access($record);
-
- // Arrays for each GEDCOM line
- $glevels = Filter::postArray('glevels', '[0-9]');
- $tag = Filter::postArray('tag', WT_REGEX_TAG);
- $text = Filter::postArray('text');
- $islink = Filter::postArray('islink', '[01]');
-
- // If the fact has a DATE or PLAC, then delete any value of Y
- if ($text[0] === 'Y') {
- foreach ($tag as $n => $value) {
- if ($glevels[$n] == 2 && ($value === 'DATE' || $value === 'PLAC') && $text[$n] !== '') {
- $text[0] = '';
- break;
- }
- }
- }
-
- $newged = '';
- if (!empty($_POST['NAME'])) {
- $newged .= "\n1 NAME " . $_POST['NAME'];
- $name_facts = ['TYPE', 'NPFX', 'GIVN', 'NICK', 'SPFX', 'SURN', 'NSFX'];
- foreach ($name_facts as $name_fact) {
- if (!empty($_POST[$name_fact])) {
- $newged .= "\n2 " . $name_fact . ' ' . $_POST[$name_fact];
- }
- }
- }
-
- 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 = FunctionsEdit::handleUpdates($newged);
-
- // Add new names after existing names
- if (!empty($_POST['NAME'])) {
- preg_match_all('/[_0-9A-Z]+/', $tree->getPreference('ADVANCED_NAME_FACTS'), $match);
- $name_facts = array_unique(array_merge(['_MARNM'], $match[0]));
- foreach ($name_facts as $name_fact) {
- // Ignore advanced facts that duplicate standard facts.
- if (!in_array($name_fact, ['TYPE', 'NPFX', 'GIVN', 'NICK', 'SPFX', 'SURN', 'NSFX']) && !empty($_POST[$name_fact])) {
- $newged .= "\n2 " . $name_fact . ' ' . $_POST[$name_fact];
- }
- }
- }
-
- $newged = substr($newged, 1); // Remove leading newline
-
- /** @var CensusAssistantModule $census_assistant */
- $census_assistant = Module::getModuleByName('GEDFact_assistant');
- if ($census_assistant !== null && $record instanceof Individual) {
- $newged = $census_assistant->updateCensusAssistant($record, $fact_id, $newged, $keep_chan);
- }
-
- $record->updateFact($fact_id, $newged, !$keep_chan);
-
- // For the GEDFact_assistant module
- $pid_array = Filter::post('pid_array');
- if ($pid_array) {
- foreach (explode(',', $pid_array) as $pid) {
- if ($pid !== $xref) {
- $indi = Individual::getInstance($pid, $tree);
- if ($indi && $indi->canEdit()) {
- $indi->updateFact($fact_id, $newged, !$keep_chan);
- }
- }
- }
- }
-
- header('Location: ' . $record->url());
- break;
-
case 'add_child_to_family_action':
//////////////////////////////////////////////////////////////////////////////
// Add a child to an existing family
diff --git a/resources/views/edit/add-fact.php b/resources/views/edit/add-fact.php
new file mode 100644
index 0000000000..834042279e
--- /dev/null
+++ b/resources/views/edit/add-fact.php
@@ -0,0 +1,94 @@
+<?php use Fisharebest\Webtrees\Auth; ?>
+<?php use Fisharebest\Webtrees\Bootstrap4; ?>
+<?php use Fisharebest\Webtrees\Config; ?>
+<?php use Fisharebest\Webtrees\FontAwesome; ?>
+<?php use Fisharebest\Webtrees\Functions\FunctionsEdit; ?>
+<?php use Fisharebest\Webtrees\Functions\FunctionsPrint; ?>
+<?php use Fisharebest\Webtrees\GedcomTag; ?>
+<?php use Fisharebest\Webtrees\I18N; ?>
+<?php use Ramsey\Uuid\Uuid; ?>
+
+<h2 class="wt-page-title"><?= $title ?></h2>
+
+<form class="wt-page-content" action="<?= e(route('update-fact', ['ged' => $tree->getName(), 'xref' => $record->getXref()])) ?>" method="post">
+ <?= csrf_field() ?>
+
+ <?php FunctionsEdit::createAddForm($tree, $fact) ?>
+
+ <?php if (($record::RECORD_TYPE === 'INDI' || $record::RECORD_TYPE === 'FAM') && $fact !== 'OBJE' && $fact !== 'NOTE' && $fact !== 'SHARED_NOTE' && $fact !== 'REPO' && $fact !== 'SOUR' && $fact !== 'SUBM' && $fact !== 'ASSO' && $fact !== 'ALIA' && $fact !== 'SEX'): ?>
+ <?= view('cards/add-source-citation', [
+ 'level' => 2,
+ 'full_citations' => $tree->getPreference('FULL_SOURCES'),
+ 'tree' => $tree,
+ ]); ?>
+
+ <?php if ($tree->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($tree)): ?>
+ <?= view('cards/add-media-object', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]) ?>
+ <?php endif ?>
+
+ <?php if ($fact !== 'NOTE'): ?>
+ <?= view('cards/add-note', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]) ?>
+
+ <?= view('cards/add-shared-note', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]) ?>
+ <?php endif ?>
+
+ <?= view('cards/add-associate', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'level' => 2,
+ 'tree' => $tree,
+ ]) ?>
+ <?php if (in_array($fact, Config::twoAssociates())): ?>
+ <?= view('cards/add-associate', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'level' => 2,
+ 'tree' => $tree,
+ ]) ?>
+ <?php endif ?>
+
+ <?= view('cards/add-restriction', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]) ?>
+ <?php endif ?>
+
+ <div class="form-group row">
+ <label class="col-sm-3 col-form-label" for="keep_chan">
+ <?= I18N::translate('Last change') ?>
+ </label>
+ <div class="col-sm-9">
+ <?= Bootstrap4::checkbox(I18N::translate('Keep the existing “last change” information'), true, ['name' => 'keep_chan', 'checked' => (bool) $tree->getPreference('NO_UPDATE_CHAN')]) ?>
+ <?= GedcomTag::getLabelValue('DATE', $record->lastChangeTimestamp()) ?>
+ <?= GedcomTag::getLabelValue('_WT_USER', e($record->lastChangeUser())) ?>
+ </div>
+ </div>
+
+ <div class="form-group row">
+ <div class="col-sm-3 wt-page-options-label">
+ </div>
+ <div class="col-sm-9 wt-page-options-value">
+ <button class="btn btn-primary" type="submit">
+ <?= FontAwesome::decorativeIcon('save') ?>
+ <?= /* I18N: A button label. */
+ I18N::translate('save') ?>
+ </button>
+ <a class="btn btn-secondary" href="<?= e($record->url()) ?>">
+ <?= FontAwesome::decorativeIcon('cancel') ?>
+ <?= /* I18N: A button label. */
+ I18N::translate('cancel') ?>
+ </a>
+ </div>
+ </div>
+</form>
+
+<?= view('modals/on-screen-keyboard') ?>
+<?= view('modals/ajax') ?>
+<?php FunctionsPrint::initializeCalendarPopup(); ?>
diff --git a/resources/views/edit/edit-fact.php b/resources/views/edit/edit-fact.php
new file mode 100644
index 0000000000..34a580789c
--- /dev/null
+++ b/resources/views/edit/edit-fact.php
@@ -0,0 +1,125 @@
+<?php use Fisharebest\Webtrees\Auth; ?>
+<?php use Fisharebest\Webtrees\Bootstrap4; ?>
+<?php use Fisharebest\Webtrees\Config; ?>
+<?php use Fisharebest\Webtrees\FontAwesome; ?>
+<?php use Fisharebest\Webtrees\Functions\FunctionsEdit; ?>
+<?php use Fisharebest\Webtrees\Functions\FunctionsPrint; ?>
+<?php use Fisharebest\Webtrees\GedcomTag; ?>
+<?php use Fisharebest\Webtrees\I18N; ?>
+<?php use Ramsey\Uuid\Uuid; ?>
+
+<h2 class="wt-page-title"><?= $title ?></h2>
+
+<form class="wt-page-content" action="<?= e(route('update-fact', ['ged' => $tree->getName(), 'xref' => $record->getXref(), 'fact_id' => $edit_fact->getFactId()])) ?>" method="post"> <?= csrf_field() ?>
+
+ <?php FunctionsEdit::createEditForm($edit_fact) ?>
+
+ <?php
+ $level1type = $edit_fact->getTag();
+ switch ($record::RECORD_TYPE) {
+ case 'REPO':
+ // REPO:NAME facts may take a NOTE (but the REPO record may not).
+ if ($level1type === 'NAME') {
+ echo view('cards/add-note', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ echo view('addSimpleTag($tree, ', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ }
+ break;
+ case 'FAM':
+ case 'INDI':
+ // FAM and INDI records have real facts. They can take NOTE/SOUR/OBJE/etc.
+ if ($level1type !== 'SEX' && $level1type !== 'NOTE' && $level1type !== 'ALIA') {
+ if ($level1type !== 'SOUR') {
+ echo view('cards/add-source-citation', [
+ 'level' => 2,
+ 'full_citations' => $tree->getPreference('FULL_SOURCES'),
+ 'tree' => $tree,
+ ]); }
+ if ($level1type !== 'OBJE') {
+ if ($tree->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($tree)) {
+ echo view('cards/add-media-object', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ }
+ }
+ echo view('cards/add-note', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ echo view('cards/add-shared-note', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ if ($level1type !== 'ASSO' && $level1type !== 'NOTE' && $level1type !== 'SOUR') {
+ echo view('cards/add-associate', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ }
+ // allow to add godfather and godmother for CHR fact or best man and bridesmaid for MARR fact in one window
+ if (in_array($level1type, Config::twoAssociates())) {
+ echo view('cards/add-associate', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ }
+ if ($level1type !== 'SOUR') {
+ echo view('cards/add-restriction', [
+ 'level' => 2,
+ 'tree' => $tree,
+ ]);
+ }
+ }
+ break;
+ default:
+ // Other types of record do not have these lower-level records
+ break;
+ }
+
+ ?>
+
+ <div class="form-group row">
+ <label class="col-sm-3 col-form-label" for="keep_chan">
+ <?= I18N::translate('Last change') ?>
+ </label>
+ <div class="col-sm-9">
+ <?= Bootstrap4::checkbox(I18N::translate('Keep the existing “last change” information'), true, ['name' => 'keep_chan', 'checked' => (bool) $tree->getPreference('NO_UPDATE_CHAN')]) ?>
+ <?= GedcomTag::getLabelValue('DATE', $record->lastChangeTimestamp()) ?>
+ <?= GedcomTag::getLabelValue('_WT_USER', e($record->lastChangeUser())) ?>
+ </div>
+ </div>
+
+ <div class="form-group row">
+ <div class="col-sm-3 wt-page-options-label">
+ </div>
+ <div class="col-sm-9 wt-page-options-value">
+ <button class="btn btn-primary" type="submit">
+ <?= FontAwesome::decorativeIcon('save') ?>
+ <?= /* I18N: A button label. */
+ I18N::translate('save') ?>
+ </button>
+ <a class="btn btn-secondary" href="<?= e($record->url()) ?>">
+ <?= FontAwesome::decorativeIcon('cancel') ?>
+ <?= /* I18N: A button label. */
+ I18N::translate('cancel') ?>
+ </a>
+ <?php if ($can_edit_raw): ?>
+ <a class="btn btn-link" href="<?= e(route('edit-raw-fact', ['xref' => $record->getXref(), 'fact_id' => $edit_fact->getFactId(), 'ged' => $tree->getName()])) ?>">
+ <?= I18N::translate('Edit the raw GEDCOM') ?>
+ </a>
+ <?php endif; ?>
+ </div>
+ </div>
+</form>
+
+<?= view('modals/on-screen-keyboard') ?>
+<?= view('modals/ajax') ?>
+<?php FunctionsPrint::initializeCalendarPopup(); ?>
diff --git a/resources/views/family-page.php b/resources/views/family-page.php
index faa5fce10f..974c71a5c2 100644
--- a/resources/views/family-page.php
+++ b/resources/views/family-page.php
@@ -85,7 +85,7 @@
<?= I18N::translate('Note') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'NOTE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'NOTE'])) ?>">
<?= I18N::translate('Add a note') ?>
</a>
</td>
@@ -96,7 +96,7 @@
<?= I18N::translate('Shared note') ?>
</th>
<td class="optionbox">
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'SHARED_NOTE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'SHARED_NOTE'])) ?>">
<?= I18N::translate('Add a shared note') ?>
</a>
</td>
@@ -108,7 +108,7 @@
<?= I18N::translate('Media object') ?>
</th>
<td class="optionbox">
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'OBJE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'OBJE'])) ?>">
<?= I18N::translate('Add a media object') ?>
</a>
</td>
@@ -120,7 +120,7 @@
<?= I18N::translate('Source') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'SOUR'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $record->getTree()->getName(), 'xref' => $record->getXref(), 'fact' => 'SOUR'])) ?>">
<?= I18N::translate('Add a source citation') ?>
</a>
</td>
diff --git a/resources/views/individual-page-menu.php b/resources/views/individual-page-menu.php
index 1d37cac6c3..cdb971a31c 100644
--- a/resources/views/individual-page-menu.php
+++ b/resources/views/individual-page-menu.php
@@ -10,7 +10,7 @@
</button>
<div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu">
<?php if ($count_sex === 0): ?>
- <a class="dropdown-item menu-indi-editraw" href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'fact' => 'SEX', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref()])) ?>">
+ <a class="dropdown-item menu-indi-editraw" href="<?= e(route('add-fact', ['fact' => 'SEX', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref()])) ?>">
<?= I18N::translate('Edit the gender') ?>
</a>
@@ -27,7 +27,7 @@
<?php endif ?>
<?php if (empty($individual->getFacts('SEX'))): ?>
- <a class="dropdown-item menu-indi-editraw" href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'fact' => 'SEX', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref()])) ?>">
+ <a class="dropdown-item menu-indi-editraw" href="<?= e(route('add-fact', ['fact' => 'SEX', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref()])) ?>">
<?= I18N::translate('Edit the gender') ?>
</a>
<?php endif ?>
diff --git a/resources/views/individual-page.php b/resources/views/individual-page.php
index 8786e737dd..50848d5f79 100644
--- a/resources/views/individual-page.php
+++ b/resources/views/individual-page.php
@@ -65,7 +65,7 @@
<?php endif ?>
<?php if ($individual->getTree()->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($individual->getTree())): ?>
- <div><a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'OBJE'])) ?>">
+ <div><a href="<?= e(route('add-fact', ['ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'OBJE'])) ?>">
<?= I18N::translate('Add a media object') ?>
</a></div>
<?php endif ?>
diff --git a/resources/views/media-page.php b/resources/views/media-page.php
index 06eb7cca98..84dd6caf1d 100644
--- a/resources/views/media-page.php
+++ b/resources/views/media-page.php
@@ -120,7 +120,7 @@
<?= I18N::translate('Source') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $media->getTree()->getName(), 'xref' => $media->getXref(), 'fact' => 'SOUR'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $media->getTree()->getName(), 'xref' => $media->getXref(), 'fact' => 'SOUR'])) ?>">
<?= I18N::translate('Add a source citation') ?>
</a>
</td>
@@ -130,7 +130,7 @@
<?= I18N::translate('Shared note') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $media->getTree()->getName(), 'xref' => $media->getXref(), 'fact' => 'SHARED_NOTE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $media->getTree()->getName(), 'xref' => $media->getXref(), 'fact' => 'SHARED_NOTE'])) ?>">
<?= I18N::translate('Add a shared note') ?>
</a>
</td>
@@ -140,7 +140,7 @@
<?= I18N::translate('Restriction') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $media->getTree()->getName(), 'xref' => $media->getXref(), 'fact' => 'RESN'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $media->getTree()->getName(), 'xref' => $media->getXref(), 'fact' => 'RESN'])) ?>">
<?= I18N::translate('Add a restriction') ?>
</a>
</td>
diff --git a/resources/views/modules/notes/tab.php b/resources/views/modules/notes/tab.php
index 64b248e135..12d3ef8b90 100644
--- a/resources/views/modules/notes/tab.php
+++ b/resources/views/modules/notes/tab.php
@@ -35,7 +35,7 @@
<?= I18N::translate('Note') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'NOTE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'NOTE'])) ?>">
<?= I18N::translate('Add a note') ?>
</a>
</td>
@@ -45,7 +45,7 @@
<?= I18N::translate('Shared note') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'SHARED_NOTE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'SHARED_NOTE'])) ?>">
<?= I18N::translate('Add a shared note') ?>
</a>
</td>
diff --git a/resources/views/modules/relatives/family.php b/resources/views/modules/relatives/family.php
index 1b6b300747..de2d854540 100644
--- a/resources/views/modules/relatives/family.php
+++ b/resources/views/modules/relatives/family.php
@@ -123,7 +123,7 @@
<th scope="row">
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $family->getTree()->getName(), 'xref' => $family->getXref(), 'fact' => 'MARR'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $family->getTree()->getName(), 'xref' => $family->getXref(), 'fact' => 'MARR'])) ?>">
<?= I18N::translate('Add marriage details') ?>
</a>
</td>
diff --git a/resources/views/modules/sources_tab/tab.php b/resources/views/modules/sources_tab/tab.php
index 0918076156..01d77ebcde 100644
--- a/resources/views/modules/sources_tab/tab.php
+++ b/resources/views/modules/sources_tab/tab.php
@@ -33,7 +33,7 @@
<?= I18N::translate('Source') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'SOUR'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $individual->getTree()->getName(), 'xref' => $individual->getXref(), 'fact' => 'SOUR'])) ?>">
<?= I18N::translate('Add a source citation') ?>
</a>
</td>
diff --git a/resources/views/source-page.php b/resources/views/source-page.php
index 095eeb937d..a3e4f3c856 100644
--- a/resources/views/source-page.php
+++ b/resources/views/source-page.php
@@ -77,7 +77,7 @@
<?= I18N::translate('Media object') ?>
</th>
<td>
- <a href="<?= e(Html::url('edit_interface.php', ['action' => 'add', 'ged' => $source->getTree()->getName(), 'xref' => $source->getXref(), 'fact' => 'OBJE'])) ?>">
+ <a href="<?= e(route('add-fact', ['ged' => $source->getTree()->getName(), 'xref' => $source->getXref(), 'fact' => 'OBJE'])) ?>">
<?= I18N::translate('Add a media object') ?>
</a>
</td>
diff --git a/routes/web.php b/routes/web.php
index a4387f4972..57e5ca6d99 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -179,6 +179,9 @@ if ($tree instanceof Tree && $tree->getPreference('imported') === '1' && Auth::i
'POST:delete-fact' => 'EditGedcomRecordController@deleteFact',
'POST:paste-fact' => 'EditGedcomRecordController@pasteFact',
'POST:delete-record' => 'EditGedcomRecordController@deleteRecord',
+ 'GET:add-fact' => 'EditGedcomRecordController@addFact',
+ 'GET:edit-fact' => 'EditGedcomRecordController@editFact',
+ 'POST:update-fact' => 'EditGedcomRecordController@updateFact',
'GET:search-replace' => 'SearchController@replace',
'POST:search-replace' => 'SearchController@replaceAction',
'GET:add-child-to-family' => 'EditFamilyController@addChild',