diff options
| -rw-r--r-- | app/Functions/FunctionsPrint.php | 6 | ||||
| -rw-r--r-- | app/Functions/FunctionsPrintFacts.php | 8 | ||||
| -rw-r--r-- | app/Http/Controllers/EditGedcomRecordController.php | 167 | ||||
| -rw-r--r-- | app/Http/Controllers/IndividualController.php | 2 | ||||
| -rw-r--r-- | app/Theme/AbstractTheme.php | 2 | ||||
| -rw-r--r-- | edit_interface.php | 323 | ||||
| -rw-r--r-- | resources/views/edit/add-fact.php | 94 | ||||
| -rw-r--r-- | resources/views/edit/edit-fact.php | 125 | ||||
| -rw-r--r-- | resources/views/family-page.php | 8 | ||||
| -rw-r--r-- | resources/views/individual-page-menu.php | 4 | ||||
| -rw-r--r-- | resources/views/individual-page.php | 2 | ||||
| -rw-r--r-- | resources/views/media-page.php | 6 | ||||
| -rw-r--r-- | resources/views/modules/notes/tab.php | 4 | ||||
| -rw-r--r-- | resources/views/modules/relatives/family.php | 2 | ||||
| -rw-r--r-- | resources/views/modules/sources_tab/tab.php | 2 | ||||
| -rw-r--r-- | resources/views/source-page.php | 2 | ||||
| -rw-r--r-- | routes/web.php | 3 |
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 ($("#add-fact").val() === null) {event.preventDefault();}">'; - echo '<input type="hidden" name="action" value="add">'; + echo '<form onsubmit="if ($("#add-fact").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&fact=' . $fact . '&xref=' . e($record->getXref()) . '&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&xref=' . $parent->getXref() . '&fact_id=' . $fact->getFactId() . '&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', |
