summaryrefslogtreecommitdiff
path: root/app/Http/Controllers/AdminTreesController.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Http/Controllers/AdminTreesController.php')
-rw-r--r--app/Http/Controllers/AdminTreesController.php3318
1 files changed, 1851 insertions, 1467 deletions
diff --git a/app/Http/Controllers/AdminTreesController.php b/app/Http/Controllers/AdminTreesController.php
index 28203c9ea7..da5ddd62d8 100644
--- a/app/Http/Controllers/AdminTreesController.php
+++ b/app/Http/Controllers/AdminTreesController.php
@@ -54,1688 +54,2072 @@ use Throwable;
/**
* Controller for tree administration.
*/
-class AdminTreesController extends AbstractBaseController {
- // Show a reduced page when there are more than a certain number of trees
- const MULTIPLE_TREE_THRESHOLD = 500;
+class AdminTreesController extends AbstractBaseController
+{
+ // Show a reduced page when there are more than a certain number of trees
+ const MULTIPLE_TREE_THRESHOLD = 500;
- protected $layout = 'layouts/administration';
+ protected $layout = 'layouts/administration';
- /**
- * /**
- * @param Request $request
- *
- * @return Response
- */
- public function check(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function check(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- // We need to work with raw GEDCOM data, as we are looking for errors
- // which may prevent the GedcomRecord objects from working.
+ // We need to work with raw GEDCOM data, as we are looking for errors
+ // which may prevent the GedcomRecord objects from working.
- $rows = Database::prepare(
- "SELECT i_id AS xref, 'INDI' AS type, i_gedcom AS gedrec FROM `##individuals` WHERE i_file=?" .
- " UNION " .
- "SELECT f_id AS xref, 'FAM' AS type, f_gedcom AS gedrec FROM `##families` WHERE f_file=?" .
- " UNION " .
- "SELECT s_id AS xref, 'SOUR' AS type, s_gedcom AS gedrec FROM `##sources` WHERE s_file=?" .
- " UNION " .
- "SELECT m_id AS xref, 'OBJE' AS type, m_gedcom AS gedrec FROM `##media` WHERE m_file=?" .
- " UNION " .
- "SELECT o_id AS xref, o_type AS type, o_gedcom AS gedrec FROM `##other` WHERE o_file=? AND o_type NOT IN ('HEAD', 'TRLR')"
- )->execute([$tree->getTreeId(), $tree->getTreeId(), $tree->getTreeId(), $tree->getTreeId(), $tree->getTreeId()])->fetchAll();
+ $rows = Database::prepare(
+ "SELECT i_id AS xref, 'INDI' AS type, i_gedcom AS gedrec FROM `##individuals` WHERE i_file=?" .
+ " UNION " .
+ "SELECT f_id AS xref, 'FAM' AS type, f_gedcom AS gedrec FROM `##families` WHERE f_file=?" .
+ " UNION " .
+ "SELECT s_id AS xref, 'SOUR' AS type, s_gedcom AS gedrec FROM `##sources` WHERE s_file=?" .
+ " UNION " .
+ "SELECT m_id AS xref, 'OBJE' AS type, m_gedcom AS gedrec FROM `##media` WHERE m_file=?" .
+ " UNION " .
+ "SELECT o_id AS xref, o_type AS type, o_gedcom AS gedrec FROM `##other` WHERE o_file=? AND o_type NOT IN ('HEAD', 'TRLR')"
+ )->execute([
+ $tree->getTreeId(),
+ $tree->getTreeId(),
+ $tree->getTreeId(),
+ $tree->getTreeId(),
+ $tree->getTreeId(),
+ ])->fetchAll();
- $records = [];
- foreach ($rows as $row) {
- $records[$row->xref] = $row;
- }
+ $records = [];
+ foreach ($rows as $row) {
+ $records[$row->xref] = $row;
+ }
- // Need to merge pending new/changed/deleted records
+ // Need to merge pending new/changed/deleted records
- $rows = Database::prepare(
- "SELECT xref, SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(CASE WHEN old_gedcom='' THEN new_gedcom ELSE old_gedcom END, '\n', 1), ' ', 3), ' ', -1) AS type, new_gedcom AS gedrec" .
- " FROM (" .
- " SELECT MAX(change_id) AS change_id" .
- " FROM `##change`" .
- " WHERE gedcom_id=? AND status='pending'" .
- " GROUP BY xref" .
- " ) AS t1" .
- " JOIN `##change` t2 USING (change_id)"
- )->execute([$tree->getTreeId()])->fetchAll();
+ $rows = Database::prepare(
+ "SELECT xref, SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(CASE WHEN old_gedcom='' THEN new_gedcom ELSE old_gedcom END, '\n', 1), ' ', 3), ' ', -1) AS type, new_gedcom AS gedrec" .
+ " FROM (" .
+ " SELECT MAX(change_id) AS change_id" .
+ " FROM `##change`" .
+ " WHERE gedcom_id=? AND status='pending'" .
+ " GROUP BY xref" .
+ " ) AS t1" .
+ " JOIN `##change` t2 USING (change_id)"
+ )->execute([$tree->getTreeId()])->fetchAll();
- foreach ($rows as $row) {
- if ($row->gedrec) {
- // new/updated record
- $records[$row->xref] = $row;
- } else {
- // deleted record
- unset($records[$row->xref]);
- }
- }
+ foreach ($rows as $row) {
+ if ($row->gedrec) {
+ // new/updated record
+ $records[$row->xref] = $row;
+ } else {
+ // deleted record
+ unset($records[$row->xref]);
+ }
+ }
- // LOOK FOR BROKEN LINKS
- $XREF_LINKS = [
- 'NOTE' => 'NOTE',
- 'SOUR' => 'SOUR',
- 'REPO' => 'REPO',
- 'OBJE' => 'OBJE',
- 'SUBM' => 'SUBM',
- 'FAMC' => 'FAM',
- 'FAMS' => 'FAM',
- //'ADOP'=>'FAM', // Need to handle this case specially. We may have both ADOP and FAMC links to the same FAM, but only store one.
- 'HUSB' => 'INDI',
- 'WIFE' => 'INDI',
- 'CHIL' => 'INDI',
- 'ASSO' => 'INDI',
- '_ASSO' => 'INDI', // A webtrees extension
- 'ALIA' => 'INDI',
- 'AUTH' => 'INDI', // A webtrees extension
- 'ANCI' => 'SUBM',
- 'DESI' => 'SUBM',
- '_WT_OBJE_SORT' => 'OBJE',
- '_LOC' => '_LOC',
- ];
+ // LOOK FOR BROKEN LINKS
+ $XREF_LINKS = [
+ 'NOTE' => 'NOTE',
+ 'SOUR' => 'SOUR',
+ 'REPO' => 'REPO',
+ 'OBJE' => 'OBJE',
+ 'SUBM' => 'SUBM',
+ 'FAMC' => 'FAM',
+ 'FAMS' => 'FAM',
+ //'ADOP'=>'FAM', // Need to handle this case specially. We may have both ADOP and FAMC links to the same FAM, but only store one.
+ 'HUSB' => 'INDI',
+ 'WIFE' => 'INDI',
+ 'CHIL' => 'INDI',
+ 'ASSO' => 'INDI',
+ '_ASSO' => 'INDI',
+ // A webtrees extension
+ 'ALIA' => 'INDI',
+ 'AUTH' => 'INDI',
+ // A webtrees extension
+ 'ANCI' => 'SUBM',
+ 'DESI' => 'SUBM',
+ '_WT_OBJE_SORT' => 'OBJE',
+ '_LOC' => '_LOC',
+ ];
- $RECORD_LINKS = [
- 'INDI' => ['NOTE', 'OBJE', 'SOUR', 'SUBM', 'ASSO', '_ASSO', 'FAMC', 'FAMS', 'ALIA', '_WT_OBJE_SORT', '_LOC'],
- 'FAM' => ['NOTE', 'OBJE', 'SOUR', 'SUBM', 'ASSO', '_ASSO', 'HUSB', 'WIFE', 'CHIL', '_LOC'],
- 'SOUR' => ['NOTE', 'OBJE', 'REPO', 'AUTH'],
- 'REPO' => ['NOTE'],
- 'OBJE' => ['NOTE'], // The spec also allows SOUR, but we treat this as a warning
- 'NOTE' => [], // The spec also allows SOUR, but we treat this as a warning
- 'SUBM' => ['NOTE', 'OBJE'],
- 'SUBN' => ['SUBM'],
- '_LOC' => ['SOUR', 'OBJE', '_LOC'],
- ];
+ $RECORD_LINKS = [
+ 'INDI' => [
+ 'NOTE',
+ 'OBJE',
+ 'SOUR',
+ 'SUBM',
+ 'ASSO',
+ '_ASSO',
+ 'FAMC',
+ 'FAMS',
+ 'ALIA',
+ '_WT_OBJE_SORT',
+ '_LOC',
+ ],
+ 'FAM' => [
+ 'NOTE',
+ 'OBJE',
+ 'SOUR',
+ 'SUBM',
+ 'ASSO',
+ '_ASSO',
+ 'HUSB',
+ 'WIFE',
+ 'CHIL',
+ '_LOC',
+ ],
+ 'SOUR' => [
+ 'NOTE',
+ 'OBJE',
+ 'REPO',
+ 'AUTH',
+ ],
+ 'REPO' => ['NOTE'],
+ 'OBJE' => ['NOTE'],
+ // The spec also allows SOUR, but we treat this as a warning
+ 'NOTE' => [],
+ // The spec also allows SOUR, but we treat this as a warning
+ 'SUBM' => [
+ 'NOTE',
+ 'OBJE',
+ ],
+ 'SUBN' => ['SUBM'],
+ '_LOC' => [
+ 'SOUR',
+ 'OBJE',
+ '_LOC',
+ ],
+ ];
- $errors = [];
- $warnings = [];
+ $errors = [];
+ $warnings = [];
- // Generate lists of all links
- $all_links = [];
- $upper_links = [];
- foreach ($records as $record) {
- $all_links[$record->xref] = [];
- $upper_links[strtoupper($record->xref)] = $record->xref;
- preg_match_all('/\n\d (' . WT_REGEX_TAG . ') @([^#@\n][^\n@]*)@/', $record->gedrec, $matches, PREG_SET_ORDER);
- foreach ($matches as $match) {
- $all_links[$record->xref][$match[2]] = $match[1];
- }
- }
+ // Generate lists of all links
+ $all_links = [];
+ $upper_links = [];
+ foreach ($records as $record) {
+ $all_links[$record->xref] = [];
+ $upper_links[strtoupper($record->xref)] = $record->xref;
+ preg_match_all('/\n\d (' . WT_REGEX_TAG . ') @([^#@\n][^\n@]*)@/', $record->gedrec, $matches, PREG_SET_ORDER);
+ foreach ($matches as $match) {
+ $all_links[$record->xref][$match[2]] = $match[1];
+ }
+ }
- foreach ($all_links as $xref1 => $links) {
- $type1 = $records[$xref1]->type;
- foreach ($links as $xref2 => $type2) {
- $type3 = isset($records[$xref2]) ? $records[$xref2]->type : '';
- if (!array_key_exists($xref2, $all_links)) {
- if (array_key_exists(strtoupper($xref2), $upper_links)) {
- $warnings[] =
- $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) . ' ' .
- /* I18N: placeholders are GEDCOM XREFs, such as R123 */
- I18N::translate('%1$s does not exist. Did you mean %2$s?', $this->checkLink($tree, $xref2), $this->checkLink($tree, $upper_links[strtoupper($xref2)]));
- } else {
- $errors[] =
- $this->checkLinkMessage($tree,
- $type1, $xref1, $type2, $xref2) . ' ' .
- /* I18N: placeholders are GEDCOM XREFs, such as R123 */
- I18N::translate('%1$s does not exist.', $this->checkLink($tree, $xref2));
- }
- } elseif ($type2 === 'SOUR' && $type1 === 'NOTE') {
- // Notes are intended to add explanations and comments to other records. They should not have their own sources.
- } elseif ($type2 === 'SOUR' && $type1 === 'OBJE') {
- // Media objects are intended to illustrate other records, facts, and source/citations. They should not have their own sources.
- } elseif ($type2 === 'OBJE' && $type1 === 'REPO') {
- $warnings[] =
- $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) .
- ' ' .
- I18N::translate('This type of link is not allowed here.');
- } elseif (!array_key_exists($type1, $RECORD_LINKS) || !in_array($type2, $RECORD_LINKS[$type1]) || !array_key_exists($type2, $XREF_LINKS)) {
- $errors[] =
- $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) .
- ' ' .
- I18N::translate('This type of link is not allowed here.');
- } elseif ($XREF_LINKS[$type2] !== $type3) {
- // Target XREF does exist - but is invalid
- $errors[] =
- $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) . ' ' .
- /* I18N: %1$s is an internal ID number such as R123. %2$s and %3$s are record types, such as INDI or SOUR */
- I18N::translate('%1$s is a %2$s but a %3$s is expected.', $this->checkLink($tree, $xref2), $this->formatType($type3), $this->formatType($type2));
- } elseif (
- $type2 === 'FAMC' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'CHIL') ||
- $type2 === 'FAMS' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'HUSB' && $all_links[$xref2][$xref1] !== 'WIFE') ||
- $type2 === 'CHIL' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'FAMC') ||
- $type2 === 'HUSB' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'FAMS') ||
- $type2 === 'WIFE' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'FAMS')
- ) {
- $errors[] =
- $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) . ' ' .
- /* I18N: %1$s and %2$s are internal ID numbers such as R123 */
- I18N::translate('%1$s does not have a link back to %2$s.', $this->checkLink($tree, $xref2), $this->checkLink($tree, $xref1));
- }
- }
- }
+ foreach ($all_links as $xref1 => $links) {
+ $type1 = $records[$xref1]->type;
+ foreach ($links as $xref2 => $type2) {
+ $type3 = isset($records[$xref2]) ? $records[$xref2]->type : '';
+ if (!array_key_exists($xref2, $all_links)) {
+ if (array_key_exists(strtoupper($xref2), $upper_links)) {
+ $warnings[] =
+ $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) . ' ' .
+ /* I18N: placeholders are GEDCOM XREFs, such as R123 */
+ I18N::translate('%1$s does not exist. Did you mean %2$s?', $this->checkLink($tree, $xref2), $this->checkLink($tree, $upper_links[strtoupper($xref2)]));
+ } else {
+ $errors[] =
+ $this->checkLinkMessage($tree,
+ $type1, $xref1, $type2, $xref2) . ' ' .
+ /* I18N: placeholders are GEDCOM XREFs, such as R123 */
+ I18N::translate('%1$s does not exist.', $this->checkLink($tree, $xref2));
+ }
+ } elseif ($type2 === 'SOUR' && $type1 === 'NOTE') {
+ // Notes are intended to add explanations and comments to other records. They should not have their own sources.
+ } elseif ($type2 === 'SOUR' && $type1 === 'OBJE') {
+ // Media objects are intended to illustrate other records, facts, and source/citations. They should not have their own sources.
+ } elseif ($type2 === 'OBJE' && $type1 === 'REPO') {
+ $warnings[] =
+ $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) .
+ ' ' .
+ I18N::translate('This type of link is not allowed here.');
+ } elseif (!array_key_exists($type1, $RECORD_LINKS) || !in_array($type2, $RECORD_LINKS[$type1]) || !array_key_exists($type2, $XREF_LINKS)) {
+ $errors[] =
+ $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) .
+ ' ' .
+ I18N::translate('This type of link is not allowed here.');
+ } elseif ($XREF_LINKS[$type2] !== $type3) {
+ // Target XREF does exist - but is invalid
+ $errors[] =
+ $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) . ' ' .
+ /* I18N: %1$s is an internal ID number such as R123. %2$s and %3$s are record types, such as INDI or SOUR */
+ I18N::translate('%1$s is a %2$s but a %3$s is expected.', $this->checkLink($tree, $xref2), $this->formatType($type3), $this->formatType($type2));
+ } elseif (
+ $type2 === 'FAMC' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'CHIL') ||
+ $type2 === 'FAMS' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'HUSB' && $all_links[$xref2][$xref1] !== 'WIFE') ||
+ $type2 === 'CHIL' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'FAMC') ||
+ $type2 === 'HUSB' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'FAMS') ||
+ $type2 === 'WIFE' && (!array_key_exists($xref1, $all_links[$xref2]) || $all_links[$xref2][$xref1] !== 'FAMS')
+ ) {
+ $errors[] =
+ $this->checkLinkMessage($tree, $type1, $xref1, $type2, $xref2) . ' ' .
+ /* I18N: %1$s and %2$s are internal ID numbers such as R123 */
+ I18N::translate('%1$s does not have a link back to %2$s.', $this->checkLink($tree, $xref2), $this->checkLink($tree, $xref1));
+ }
+ }
+ }
- $title = I18N::translate('Check for errors') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate('Check for errors') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-check', [
- 'errors' => $errors,
- 'title' => $title,
- 'tree' => $tree,
- 'warnings' => $warnings,
- ]);
- }
+ return $this->viewResponse('admin/trees-check', [
+ 'errors' => $errors,
+ 'title' => $title,
+ 'tree' => $tree,
+ 'warnings' => $warnings,
+ ]);
+ }
- /**
- * Create a message linking one record to another.
- *
- * @param Tree $tree
- * @param string $type1
- * @param string $xref1
- * @param string $type2
- * @param string $xref2
- *
- * @return string
- */
- private function checkLinkMessage(Tree $tree, $type1, $xref1, $type2, $xref2) {
- return /* I18N: The placeholders are GEDCOM XREFs and tags. e.g. “INDI I123 contains a FAMC link to F234.” */
- I18N::translate(
- '%1$s %2$s has a %3$s link to %4$s.',
- $this->formatType($type1),
- $this->checkLink($tree, $xref1),
- $this->formatType($type2),
- $this->checkLink($tree, $xref2)
- );
- }
+ /**
+ * Create a message linking one record to another.
+ *
+ * @param Tree $tree
+ * @param string $type1
+ * @param string $xref1
+ * @param string $type2
+ * @param string $xref2
+ *
+ * @return string
+ */
+ private function checkLinkMessage(Tree $tree, $type1, $xref1, $type2, $xref2)
+ {
+ return /* I18N: The placeholders are GEDCOM XREFs and tags. e.g. “INDI I123 contains a FAMC link to F234.” */
+ I18N::translate(
+ '%1$s %2$s has a %3$s link to %4$s.',
+ $this->formatType($type1),
+ $this->checkLink($tree, $xref1),
+ $this->formatType($type2),
+ $this->checkLink($tree, $xref2)
+ );
+ }
- /**
- * Format a link to a record.
- *
- * @param Tree $tree
- * @param string $xref
- *
- * @return string
- */
- private function checkLink(Tree $tree, string $xref) {
- return '<b><a href="' . e(route('record', ['xref' => $xref, 'ged' => $tree->getName()])) . '">' . $xref . '</a></b>';
- }
+ /**
+ * Format a link to a record.
+ *
+ * @param Tree $tree
+ * @param string $xref
+ *
+ * @return string
+ */
+ private function checkLink(Tree $tree, string $xref)
+ {
+ return '<b><a href="' . e(route('record', [
+ 'xref' => $xref,
+ 'ged' => $tree->getName(),
+ ])) . '">' . $xref . '</a></b>';
+ }
- /**
- * Format a record type.
- *
- * @param string $type
- *
- * @return string
- */
- private function formatType($type) {
- return '<b title="' . GedcomTag::getLabel($type) . '">' . $type . '</b>';
- }
+ /**
+ * Format a record type.
+ *
+ * @param string $type
+ *
+ * @return string
+ */
+ private function formatType($type)
+ {
+ return '<b title="' . GedcomTag::getLabel($type) . '">' . $type . '</b>';
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function create(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function create(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $tree_name = $request->get('tree_name', '');
- $tree_title = $request->get('tree_title', '');
+ $tree_name = $request->get('tree_name', '');
+ $tree_title = $request->get('tree_title', '');
- // We use the tree name as a file name, so no directory separators allowed.
- $tree_name = basename($tree_name);
+ // We use the tree name as a file name, so no directory separators allowed.
+ $tree_name = basename($tree_name);
- if ($tree_name !== '' && $tree_title !== '') {
- if (Tree::findByName($tree_name)) {
- FlashMessages::addMessage(I18N::translate('The family tree “%s” already exists.', e($tree_name)), 'danger');
- } else {
- $tree = Tree::create($tree_name, $tree_title);
- FlashMessages::addMessage(I18N::translate('The family tree “%s” has been created.', e($tree->getName())), 'success');
- }
- }
+ if ($tree_name !== '' && $tree_title !== '') {
+ if (Tree::findByName($tree_name)) {
+ FlashMessages::addMessage(I18N::translate('The family tree “%s” already exists.', e($tree_name)), 'danger');
+ } else {
+ $tree = Tree::create($tree_name, $tree_title);
+ FlashMessages::addMessage(I18N::translate('The family tree “%s” has been created.', e($tree->getName())), 'success');
+ }
+ }
- $url = route('admin-trees', ['ged' => $tree->getName()]);
+ $url = route('admin-trees', ['ged' => $tree->getName()]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function delete(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function delete(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- FlashMessages::addMessage(/* I18N: %s is the name of a family tree */
- I18N::translate('The family tree “%s” has been deleted.', e($tree->getTitle())), 'success');
+ FlashMessages::addMessage(/* I18N: %s is the name of a family tree */
+ I18N::translate('The family tree “%s” has been deleted.', e($tree->getTitle())), 'success');
- $tree->delete();
+ $tree->delete();
- $url = route('admin-trees');
+ $url = route('admin-trees');
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function duplicates(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function duplicates(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $duplicates = $this->duplicateRecords($tree);
+ $duplicates = $this->duplicateRecords($tree);
- $title = I18N::translate('Find duplicates') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate('Find duplicates') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-duplicates', [
- 'duplicates' => $duplicates,
- 'title' => $title,
- 'tree' => $tree,
- ]);
- }
+ return $this->viewResponse('admin/trees-duplicates', [
+ 'duplicates' => $duplicates,
+ 'title' => $title,
+ 'tree' => $tree,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function export(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function export(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $title = I18N::translate('Export a GEDCOM file') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate('Export a GEDCOM file') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-export', [
- 'title' => $title,
- 'tree' => $tree,
- ]);
- }
+ return $this->viewResponse('admin/trees-export', [
+ 'title' => $title,
+ 'tree' => $tree,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function exportClient(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function exportClient(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- // Validate user parameters
- $convert = (bool) $request->get('convert');
- $zip = (bool) $request->get('zip');
- $media = (bool) $request->get('media');
- $media_path = $request->get('media-path');
- $privatize_export = $request->get('privatize_export');
+ // Validate user parameters
+ $convert = (bool)$request->get('convert');
+ $zip = (bool)$request->get('zip');
+ $media = (bool)$request->get('media');
+ $media_path = $request->get('media-path');
+ $privatize_export = $request->get('privatize_export');
- $exportOptions = [
- 'privatize' => $privatize_export,
- 'toANSI' => $convert ? 'yes' : 'no',
- 'path' => $media_path,
- ];
+ $exportOptions = [
+ 'privatize' => $privatize_export,
+ 'toANSI' => $convert ? 'yes' : 'no',
+ 'path' => $media_path,
+ ];
- // What to call the downloaded file
- $download_filename = $tree->getName();
- if (strtolower(substr($download_filename, -4, 4)) != '.ged') {
- $download_filename .= '.ged';
- }
+ // What to call the downloaded file
+ $download_filename = $tree->getName();
+ if (strtolower(substr($download_filename, -4, 4)) != '.ged') {
+ $download_filename .= '.ged';
+ }
- if ($zip || $media) {
- // Export the GEDCOM to an in-memory stream.
- $tmp_stream = tmpfile();
- FunctionsExport::exportGedcom($tree, $tmp_stream, $exportOptions);
- rewind($tmp_stream);
+ if ($zip || $media) {
+ // Export the GEDCOM to an in-memory stream.
+ $tmp_stream = tmpfile();
+ FunctionsExport::exportGedcom($tree, $tmp_stream, $exportOptions);
+ rewind($tmp_stream);
- // Create a new/empty .ZIP file
- $temp_zip_file = tempnam(sys_get_temp_dir(), 'webtrees-zip-');
- $zip_filesystem = new Filesystem(new ZipArchiveAdapter($temp_zip_file));
- $zip_filesystem->writeStream($download_filename, $tmp_stream);
+ // Create a new/empty .ZIP file
+ $temp_zip_file = tempnam(sys_get_temp_dir(), 'webtrees-zip-');
+ $zip_filesystem = new Filesystem(new ZipArchiveAdapter($temp_zip_file));
+ $zip_filesystem->writeStream($download_filename, $tmp_stream);
- if ($media) {
- $rows = Database::prepare(
- "SELECT m_id, m_gedcom FROM `##media` WHERE m_file = :tree_id"
- )->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
- $path = $tree->getPreference('MEDIA_DIRECTORY');
- foreach ($rows as $row) {
- $record = Media::getInstance($row->m_id, $tree, $row->m_gedcom);
- if ($record->canShow()) {
- foreach ($record->mediaFiles() as $media_file) {
- if (file_exists($media_file->getServerFilename())) {
- $fp = fopen($media_file->getServerFilename(), 'r');
- $zip_filesystem->writeStream($path . $media_file->filename(), $fp);
- fclose($fp);
- }
- }
- }
- }
- }
+ if ($media) {
+ $rows = Database::prepare(
+ "SELECT m_id, m_gedcom FROM `##media` WHERE m_file = :tree_id"
+ )->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
+ $path = $tree->getPreference('MEDIA_DIRECTORY');
+ foreach ($rows as $row) {
+ $record = Media::getInstance($row->m_id, $tree, $row->m_gedcom);
+ if ($record->canShow()) {
+ foreach ($record->mediaFiles() as $media_file) {
+ if (file_exists($media_file->getServerFilename())) {
+ $fp = fopen($media_file->getServerFilename(), 'r');
+ $zip_filesystem->writeStream($path . $media_file->filename(), $fp);
+ fclose($fp);
+ }
+ }
+ }
+ }
+ }
- // The ZipArchiveAdapter may or may not close the stream.
- if (is_resource($tmp_stream)) {
- fclose($tmp_stream);
- }
+ // The ZipArchiveAdapter may or may not close the stream.
+ if (is_resource($tmp_stream)) {
+ fclose($tmp_stream);
+ }
- // Need to force-close the filesystem
- $zip_filesystem = null;
+ // Need to force-close the filesystem
+ $zip_filesystem = null;
- $response = new BinaryFileResponse($temp_zip_file);
- $response->deleteFileAfterSend(true);
+ $response = new BinaryFileResponse($temp_zip_file);
+ $response->deleteFileAfterSend(true);
- $response->headers->set('Content-Type', 'application/zip');
- $response->setContentDisposition(
- ResponseHeaderBag::DISPOSITION_ATTACHMENT,
- $download_filename . '.zip'
- );
- } else {
- $response = new StreamedResponse(function () use ($tree, $exportOptions) {
- $stream = fopen('php://output', 'w');
- FunctionsExport::exportGedcom($tree, $stream, $exportOptions);
- fclose($stream);
- });
+ $response->headers->set('Content-Type', 'application/zip');
+ $response->setContentDisposition(
+ ResponseHeaderBag::DISPOSITION_ATTACHMENT,
+ $download_filename . '.zip'
+ );
+ } else {
+ $response = new StreamedResponse(function () use ($tree, $exportOptions) {
+ $stream = fopen('php://output', 'w');
+ FunctionsExport::exportGedcom($tree, $stream, $exportOptions);
+ fclose($stream);
+ });
- $charset = $convert ? 'ISO-8859-1' : 'UTF-8';
+ $charset = $convert ? 'ISO-8859-1' : 'UTF-8';
- $response->headers->set('Content-Type', 'text/plain; charset=' . $charset);
- $contentDisposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $download_filename);
- $response->headers->set('Content-Disposition', $contentDisposition);
- }
+ $response->headers->set('Content-Type', 'text/plain; charset=' . $charset);
+ $contentDisposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $download_filename);
+ $response->headers->set('Content-Disposition', $contentDisposition);
+ }
- return $response;
- }
+ return $response;
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function exportServer(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function exportServer(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $filename = WT_DATA_DIR . $tree->getName();
+ $filename = WT_DATA_DIR . $tree->getName();
- // Force a ".ged" suffix
- if (strtolower(substr($filename, -4)) != '.ged') {
- $filename .= '.ged';
- }
+ // Force a ".ged" suffix
+ if (strtolower(substr($filename, -4)) != '.ged') {
+ $filename .= '.ged';
+ }
- try {
- // To avoid partial trees on timeout/diskspace/etc, write to a temporary file first
- $stream = fopen($filename . '.tmp', 'w');
- $tree->exportGedcom($stream);
- fclose($stream);
- rename($filename . '.tmp', $filename);
+ try {
+ // To avoid partial trees on timeout/diskspace/etc, write to a temporary file first
+ $stream = fopen($filename . '.tmp', 'w');
+ $tree->exportGedcom($stream);
+ fclose($stream);
+ rename($filename . '.tmp', $filename);
- FlashMessages::addMessage(/* I18N: %s is a filename */
- I18N::translate('The family tree has been exported to %s.', Html::filename($filename)), 'success');
- } catch (Throwable $ex) {
- DebugBar::addThrowable($ex);
+ FlashMessages::addMessage(/* I18N: %s is a filename */
+ I18N::translate('The family tree has been exported to %s.', Html::filename($filename)), 'success');
+ } catch (Throwable $ex) {
+ DebugBar::addThrowable($ex);
- FlashMessages::addMessage(
- I18N::translate('The file %s could not be created.', Html::filename($filename)) . '<hr><samp dir="ltr">' . $ex->getMessage() . '</samp>',
- 'danger'
- );
- }
+ FlashMessages::addMessage(
+ I18N::translate('The file %s could not be created.', Html::filename($filename)) . '<hr><samp dir="ltr">' . $ex->getMessage() . '</samp>',
+ 'danger'
+ );
+ }
- $url = route('admin-trees', [
- 'ged' => $tree->getName(),
- ]);
+ $url = route('admin-trees', [
+ 'ged' => $tree->getName(),
+ ]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function importAction(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function importAction(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $source = $request->get('source');
- $keep_media = (bool) $request->get('keep_media');
- $WORD_WRAPPED_NOTES = (bool) $request->get('WORD_WRAPPED_NOTES');
- $GEDCOM_MEDIA_PATH = $request->get('GEDCOM_MEDIA_PATH');
+ $source = $request->get('source');
+ $keep_media = (bool)$request->get('keep_media');
+ $WORD_WRAPPED_NOTES = (bool)$request->get('WORD_WRAPPED_NOTES');
+ $GEDCOM_MEDIA_PATH = $request->get('GEDCOM_MEDIA_PATH');
- // Save these choices as defaults
- $tree->setPreference('keep_media', $keep_media ? '1' : '0');
- $tree->setPreference('WORD_WRAPPED_NOTES', $WORD_WRAPPED_NOTES ? '1' : '0');
- $tree->setPreference('GEDCOM_MEDIA_PATH', $GEDCOM_MEDIA_PATH);
+ // Save these choices as defaults
+ $tree->setPreference('keep_media', $keep_media ? '1' : '0');
+ $tree->setPreference('WORD_WRAPPED_NOTES', $WORD_WRAPPED_NOTES ? '1' : '0');
+ $tree->setPreference('GEDCOM_MEDIA_PATH', $GEDCOM_MEDIA_PATH);
- if ($source === 'client') {
- if (isset($_FILES['tree_name'])) {
- if ($_FILES['tree_name']['error'] == 0 && is_readable($_FILES['tree_name']['tmp_name'])) {
- $tree->importGedcomFile($_FILES['tree_name']['tmp_name'], $_FILES['tree_name']['name']);
- } else {
- FlashMessages::addMessage(Functions::fileUploadErrorText($_FILES['tree_name']['error']), 'danger');
- }
- } else {
- FlashMessages::addMessage(I18N::translate('No GEDCOM file was received.'), 'danger');
- }
- }
+ if ($source === 'client') {
+ if (isset($_FILES['tree_name'])) {
+ if ($_FILES['tree_name']['error'] == 0 && is_readable($_FILES['tree_name']['tmp_name'])) {
+ $tree->importGedcomFile($_FILES['tree_name']['tmp_name'], $_FILES['tree_name']['name']);
+ } else {
+ FlashMessages::addMessage(Functions::fileUploadErrorText($_FILES['tree_name']['error']), 'danger');
+ }
+ } else {
+ FlashMessages::addMessage(I18N::translate('No GEDCOM file was received.'), 'danger');
+ }
+ }
- if ($source === 'server') {
- $basename = basename($request->get('tree_name'));
+ if ($source === 'server') {
+ $basename = basename($request->get('tree_name'));
- if ($basename) {
- $tree->importGedcomFile(WT_DATA_DIR . $basename, $basename);
- } else {
- FlashMessages::addMessage(I18N::translate('No GEDCOM file was received.'), 'danger');
- }
- }
+ if ($basename) {
+ $tree->importGedcomFile(WT_DATA_DIR . $basename, $basename);
+ } else {
+ FlashMessages::addMessage(I18N::translate('No GEDCOM file was received.'), 'danger');
+ }
+ }
- $url = route('admin-trees', ['ged' => $tree->getName()]);
+ $url = route('admin-trees', ['ged' => $tree->getName()]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function importForm(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function importForm(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $default_gedcom_file = $tree->getPreference('gedcom_filename');
- $gedcom_media_path = $tree->getPreference('GEDCOM_MEDIA_PATH');
- $gedcom_files = $this->gedcomFiles(WT_DATA_DIR);
+ $default_gedcom_file = $tree->getPreference('gedcom_filename');
+ $gedcom_media_path = $tree->getPreference('GEDCOM_MEDIA_PATH');
+ $gedcom_files = $this->gedcomFiles(WT_DATA_DIR);
- $title = I18N::translate('Import a GEDCOM file') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate('Import a GEDCOM file') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-import', [
- 'default_gedcom_file' => $default_gedcom_file,
- 'gedcom_files' => $gedcom_files,
- 'gedcom_media_path' => $gedcom_media_path,
- 'title' => $title,
- ]);
- }
+ return $this->viewResponse('admin/trees-import', [
+ 'default_gedcom_file' => $default_gedcom_file,
+ 'gedcom_files' => $gedcom_files,
+ 'gedcom_media_path' => $gedcom_media_path,
+ 'title' => $title,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function index(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function index(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $multiple_tree_threshold = (int) Site::getPreference('MULTIPLE_TREE_THRESHOLD', self::MULTIPLE_TREE_THRESHOLD);
- $gedcom_files = $this->gedcomFiles(WT_DATA_DIR);
+ $multiple_tree_threshold = (int)Site::getPreference('MULTIPLE_TREE_THRESHOLD', self::MULTIPLE_TREE_THRESHOLD);
+ $gedcom_files = $this->gedcomFiles(WT_DATA_DIR);
- $all_trees = Tree::getAll();
+ $all_trees = Tree::getAll();
- // On sites with hundreds or thousands of trees, this page becomes very large.
- // Just show the current tree, the default tree, and unimported trees
- if (count($all_trees) >= $multiple_tree_threshold) {
- $all_trees = array_filter($all_trees, function (Tree $x) use ($tree) {
- return $x->getPreference('imported') === '0' || $tree->getTreeId() === $x->getTreeId() || $x->getName() === Site::getPreference('DEFAULT_GEDCOM');
- });
- }
+ // On sites with hundreds or thousands of trees, this page becomes very large.
+ // Just show the current tree, the default tree, and unimported trees
+ if (count($all_trees) >= $multiple_tree_threshold) {
+ $all_trees = array_filter($all_trees, function (Tree $x) use ($tree) {
+ return $x->getPreference('imported') === '0' || $tree->getTreeId() === $x->getTreeId() || $x->getName() === Site::getPreference('DEFAULT_GEDCOM');
+ });
+ }
- $default_tree_name = $this->generateNewTreeName();
- $default_tree_title = I18N::translate('My family tree');
+ $default_tree_name = $this->generateNewTreeName();
+ $default_tree_title = I18N::translate('My family tree');
- $all_users = User::all();
+ $all_users = User::all();
- $title = I18N::translate('Manage family trees');
+ $title = I18N::translate('Manage family trees');
- return $this->viewResponse('admin/trees', [
- 'all_trees' => $all_trees,
- 'all_users' => $all_users,
- 'default_tree_name' => $default_tree_name,
- 'default_tree_title' => $default_tree_title,
- 'gedcom_files' => $gedcom_files,
- 'multiple_tree_threshold' => $multiple_tree_threshold,
- 'title' => $title,
- ]);
- }
+ return $this->viewResponse('admin/trees', [
+ 'all_trees' => $all_trees,
+ 'all_users' => $all_users,
+ 'default_tree_name' => $default_tree_name,
+ 'default_tree_title' => $default_tree_title,
+ 'gedcom_files' => $gedcom_files,
+ 'multiple_tree_threshold' => $multiple_tree_threshold,
+ 'title' => $title,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function merge(Request $request): Response {
- $tree1_name = $request->get('tree1_name');
- $tree2_name = $request->get('tree2_name');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function merge(Request $request): Response
+ {
+ $tree1_name = $request->get('tree1_name');
+ $tree2_name = $request->get('tree2_name');
- $tree1 = Tree::findByName($tree1_name);
- $tree2 = Tree::findByName($tree2_name);
+ $tree1 = Tree::findByName($tree1_name);
+ $tree2 = Tree::findByName($tree2_name);
- if ($tree1 !== null && $tree2 !== null && $tree1->getTreeId() !== $tree2->getTreeId()) {
- $xrefs = $this->commonXrefs($tree1, $tree2);
- } else {
- $xrefs = [];
- }
+ if ($tree1 !== null && $tree2 !== null && $tree1->getTreeId() !== $tree2->getTreeId()) {
+ $xrefs = $this->commonXrefs($tree1, $tree2);
+ } else {
+ $xrefs = [];
+ }
- $tree_list = Tree::getNameList();
+ $tree_list = Tree::getNameList();
- $title = I18N::translate(I18N::translate('Merge family trees'));
+ $title = I18N::translate(I18N::translate('Merge family trees'));
- return $this->viewResponse('admin/trees-merge', [
- 'tree_list' => $tree_list,
- 'tree1' => $tree1,
- 'tree2' => $tree2,
- 'title' => $title,
- 'xrefs' => $xrefs,
- ]);
- }
+ return $this->viewResponse('admin/trees-merge', [
+ 'tree_list' => $tree_list,
+ 'tree1' => $tree1,
+ 'tree2' => $tree2,
+ 'title' => $title,
+ 'xrefs' => $xrefs,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function mergeAction(Request $request): RedirectResponse {
- $tree1_name = $request->get('tree1_name');
- $tree2_name = $request->get('tree2_name');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function mergeAction(Request $request): RedirectResponse
+ {
+ $tree1_name = $request->get('tree1_name');
+ $tree2_name = $request->get('tree2_name');
- $tree1 = Tree::findByName($tree1_name);
- $tree2 = Tree::findByName($tree2_name);
+ $tree1 = Tree::findByName($tree1_name);
+ $tree2 = Tree::findByName($tree2_name);
- if ($tree1 !== null && $tree2 !== null && $tree1 !== $tree2 && empty($this->commonXrefs($tree1, $tree2))) {
- Database::prepare(
- "INSERT INTO `##individuals` (i_id, i_file, i_rin, i_sex, i_gedcom)" .
- " SELECT i_id, ?, i_rin, i_sex, i_gedcom FROM `##individuals` AS individuals2 WHERE i_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ if ($tree1 !== null && $tree2 !== null && $tree1 !== $tree2 && empty($this->commonXrefs($tree1, $tree2))) {
+ Database::prepare(
+ "INSERT INTO `##individuals` (i_id, i_file, i_rin, i_sex, i_gedcom)" .
+ " SELECT i_id, ?, i_rin, i_sex, i_gedcom FROM `##individuals` AS individuals2 WHERE i_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##families` (f_id, f_file, f_husb, f_wife, f_gedcom, f_numchil)" .
- " SELECT f_id, ?, f_husb, f_wife, f_gedcom, f_numchil FROM `##families` AS families2 WHERE f_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##families` (f_id, f_file, f_husb, f_wife, f_gedcom, f_numchil)" .
+ " SELECT f_id, ?, f_husb, f_wife, f_gedcom, f_numchil FROM `##families` AS families2 WHERE f_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##sources` (s_id, s_file, s_name, s_gedcom)" .
- " SELECT s_id, ?, s_name, s_gedcom FROM `##sources` AS sources2 WHERE s_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##sources` (s_id, s_file, s_name, s_gedcom)" .
+ " SELECT s_id, ?, s_name, s_gedcom FROM `##sources` AS sources2 WHERE s_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##media` (m_id, m_file, m_gedcom)" .
- " SELECT m_id, ?, m_gedcom FROM `##media` AS media2 WHERE m_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##media` (m_id, m_file, m_gedcom)" .
+ " SELECT m_id, ?, m_gedcom FROM `##media` AS media2 WHERE m_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##media_file` (m_id, m_file, multimedia_file_refn, multimedia_format, source_media_type, descriptive_title)" .
- " SELECT m_id, ?, multimedia_file_refn, multimedia_format, source_media_type, descriptive_title FROM `##media_file` AS media_file2 WHERE m_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##media_file` (m_id, m_file, multimedia_file_refn, multimedia_format, source_media_type, descriptive_title)" .
+ " SELECT m_id, ?, multimedia_file_refn, multimedia_format, source_media_type, descriptive_title FROM `##media_file` AS media_file2 WHERE m_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##other` (o_id, o_file, o_type, o_gedcom)" .
- " SELECT o_id, ?, o_type, o_gedcom FROM `##other` AS other2 WHERE o_file = ? AND o_type NOT IN ('HEAD', 'TRLR')"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##other` (o_id, o_file, o_type, o_gedcom)" .
+ " SELECT o_id, ?, o_type, o_gedcom FROM `##other` AS other2 WHERE o_file = ? AND o_type NOT IN ('HEAD', 'TRLR')"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##name` (n_file, n_id, n_num, n_type, n_sort, n_full, n_surname, n_surn, n_givn, n_soundex_givn_std, n_soundex_surn_std, n_soundex_givn_dm, n_soundex_surn_dm)" .
- " SELECT ?, n_id, n_num, n_type, n_sort, n_full, n_surname, n_surn, n_givn, n_soundex_givn_std, n_soundex_surn_std, n_soundex_givn_dm, n_soundex_surn_dm FROM `##name` AS name2 WHERE n_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##name` (n_file, n_id, n_num, n_type, n_sort, n_full, n_surname, n_surn, n_givn, n_soundex_givn_std, n_soundex_surn_std, n_soundex_givn_dm, n_soundex_surn_dm)" .
+ " SELECT ?, n_id, n_num, n_type, n_sort, n_full, n_surname, n_surn, n_givn, n_soundex_givn_std, n_soundex_surn_std, n_soundex_givn_dm, n_soundex_surn_dm FROM `##name` AS name2 WHERE n_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##placelinks` (pl_p_id, pl_gid, pl_file)" .
- " SELECT pl_p_id, pl_gid, ? FROM `##placelinks` AS placelinks2 WHERE pl_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##placelinks` (pl_p_id, pl_gid, pl_file)" .
+ " SELECT pl_p_id, pl_gid, ? FROM `##placelinks` AS placelinks2 WHERE pl_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##dates` (d_day, d_month, d_mon, d_year, d_julianday1, d_julianday2, d_fact, d_gid, d_file, d_type)" .
- " SELECT d_day, d_month, d_mon, d_year, d_julianday1, d_julianday2, d_fact, d_gid, ?, d_type FROM `##dates` AS dates2 WHERE d_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##dates` (d_day, d_month, d_mon, d_year, d_julianday1, d_julianday2, d_fact, d_gid, d_file, d_type)" .
+ " SELECT d_day, d_month, d_mon, d_year, d_julianday1, d_julianday2, d_fact, d_gid, ?, d_type FROM `##dates` AS dates2 WHERE d_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##default_resn` (gedcom_id, xref, tag_type, resn)" .
- " SELECT ?, xref, tag_type, resn FROM `##default_resn` AS default_resn2 WHERE gedcom_id = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##default_resn` (gedcom_id, xref, tag_type, resn)" .
+ " SELECT ?, xref, tag_type, resn FROM `##default_resn` AS default_resn2 WHERE gedcom_id = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- Database::prepare(
- "INSERT INTO `##link` (l_file, l_from, l_type, l_to)" .
- " SELECT ?, l_from, l_type, l_to FROM `##link` AS link2 WHERE l_file = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ Database::prepare(
+ "INSERT INTO `##link` (l_file, l_from, l_type, l_to)" .
+ " SELECT ?, l_from, l_type, l_to FROM `##link` AS link2 WHERE l_file = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- // This table may contain old (deleted) references, which could clash. IGNORE these.
- Database::prepare(
- "INSERT IGNORE INTO `##change` (change_time, status, gedcom_id, xref, old_gedcom, new_gedcom, user_id)" .
- " SELECT change_time, status, ?, xref, old_gedcom, new_gedcom, user_id FROM `##change` AS change2 WHERE gedcom_id = ?"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ // This table may contain old (deleted) references, which could clash. IGNORE these.
+ Database::prepare(
+ "INSERT IGNORE INTO `##change` (change_time, status, gedcom_id, xref, old_gedcom, new_gedcom, user_id)" .
+ " SELECT change_time, status, ?, xref, old_gedcom, new_gedcom, user_id FROM `##change` AS change2 WHERE gedcom_id = ?"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- // This table may contain old (deleted) references, which could clash. IGNORE these.
- Database::prepare(
- "INSERT IGNORE INTO `##hit_counter` (gedcom_id, page_name, page_parameter, page_count)" .
- " SELECT ?, page_name, page_parameter, page_count FROM `##hit_counter` AS hit_counter2 WHERE gedcom_id = ? AND page_name <> 'index.php'"
- )->execute([$tree2->getTreeId(), $tree1->getTreeId()]);
+ // This table may contain old (deleted) references, which could clash. IGNORE these.
+ Database::prepare(
+ "INSERT IGNORE INTO `##hit_counter` (gedcom_id, page_name, page_parameter, page_count)" .
+ " SELECT ?, page_name, page_parameter, page_count FROM `##hit_counter` AS hit_counter2 WHERE gedcom_id = ? AND page_name <> 'index.php'"
+ )->execute([
+ $tree2->getTreeId(),
+ $tree1->getTreeId(),
+ ]);
- FlashMessages::addMessage(I18N::translate('The family trees have been merged successfully.'), 'success');
+ FlashMessages::addMessage(I18N::translate('The family trees have been merged successfully.'), 'success');
- $url = route('admin-trees', [
- 'ged' => $tree2->getName(),
- ]);
- } else {
- $url = route('admin-trees-merge', [
- 'tree1_name' => $tree1->getName(),
- 'tree2_name' => $tree2->getName(),
- ]);
- }
+ $url = route('admin-trees', [
+ 'ged' => $tree2->getName(),
+ ]);
+ } else {
+ $url = route('admin-trees-merge', [
+ 'tree1_name' => $tree1->getName(),
+ 'tree2_name' => $tree2->getName(),
+ ]);
+ }
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function places(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function places(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $search = $request->get('search', '');
- $replace = $request->get('replace', '');
+ $search = $request->get('search', '');
+ $replace = $request->get('replace', '');
- if ($search !== '' && $replace !== '') {
- $changes = $this->changePlacesPreview($tree, $search, $replace);
- } else {
- $changes = [];
- }
+ if ($search !== '' && $replace !== '') {
+ $changes = $this->changePlacesPreview($tree, $search, $replace);
+ } else {
+ $changes = [];
+ }
- $title = I18N::translate(/* I18N: Renumber the records in a family tree */
- 'Renumber family tree') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate(/* I18N: Renumber the records in a family tree */
+ 'Renumber family tree') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-places', [
- 'changes' => $changes,
- 'replace' => $replace,
- 'search' => $search,
- 'title' => $title,
- ]);
- }
+ return $this->viewResponse('admin/trees-places', [
+ 'changes' => $changes,
+ 'replace' => $replace,
+ 'search' => $search,
+ 'title' => $title,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function placesAction(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function placesAction(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $search = $request->get('search', '');
- $replace = $request->get('replace', '');
+ $search = $request->get('search', '');
+ $replace = $request->get('replace', '');
- $changes = $this->changePlacesUpdate($tree, $search, $replace);
+ $changes = $this->changePlacesUpdate($tree, $search, $replace);
- $feedback = I18N::translate('The following places have been changed:') . '<ul>';
- foreach ($changes as $old_place => $new_place) {
- $feedback .= '<li>' . e($old_place) . ' &rarr; ' . e($new_place) . '</li>';
- }
- $feedback .= '</ul>';
+ $feedback = I18N::translate('The following places have been changed:') . '<ul>';
+ foreach ($changes as $old_place => $new_place) {
+ $feedback .= '<li>' . e($old_place) . ' &rarr; ' . e($new_place) . '</li>';
+ }
+ $feedback .= '</ul>';
- FlashMessages::addMessage($feedback, 'success');
+ FlashMessages::addMessage($feedback, 'success');
- $url = route('admin-trees-places', [
- 'ged' => $tree->getName(),
- 'replace' => $replace,
- 'search' => $search,
- ]);
+ $url = route('admin-trees-places', [
+ 'ged' => $tree->getName(),
+ 'replace' => $replace,
+ 'search' => $search,
+ ]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function preferences(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function preferences(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $french_calendar_start = new Date('22 SEP 1792');
- $french_calendar_end = new Date('31 DEC 1805');
- $gregorian_calendar_start = new Date('15 OCT 1582');
+ $french_calendar_start = new Date('22 SEP 1792');
+ $french_calendar_end = new Date('31 DEC 1805');
+ $gregorian_calendar_start = new Date('15 OCT 1582');
- $surname_list_styles = [
- 'style1' => /* I18N: Layout option for lists of names */
- I18N::translate('list'),
- 'style2' => /* I18N: Layout option for lists of names */
- I18N::translate('table'),
- 'style3' => /* I18N: Layout option for lists of names */
- I18N::translate('tag cloud'),
- ];
+ $surname_list_styles = [
+ 'style1' => /* I18N: Layout option for lists of names */
+ I18N::translate('list'),
+ 'style2' => /* I18N: Layout option for lists of names */
+ I18N::translate('table'),
+ 'style3' => /* I18N: Layout option for lists of names */
+ I18N::translate('tag cloud'),
+ ];
- $page_layouts = [
- 0 => /* I18N: page orientation */
- I18N::translate('Portrait'),
- 1 => /* I18N: page orientation */
- I18N::translate('Landscape'),
- ];
+ $page_layouts = [
+ 0 => /* I18N: page orientation */
+ I18N::translate('Portrait'),
+ 1 => /* I18N: page orientation */
+ I18N::translate('Landscape'),
+ ];
- $formats = [
- '' => /* I18N: None of the other options */
- I18N::translate('none'),
- 'markdown' => /* I18N: https://en.wikipedia.org/wiki/Markdown */
- I18N::translate('markdown'),
- ];
+ $formats = [
+ '' => /* I18N: None of the other options */
+ I18N::translate('none'),
+ 'markdown' => /* I18N: https://en.wikipedia.org/wiki/Markdown */
+ I18N::translate('markdown'),
+ ];
- $source_types = [
- 0 => I18N::translate('none'),
- 1 => I18N::translate('facts'),
- 2 => I18N::translate('records'),
- ];
+ $source_types = [
+ 0 => I18N::translate('none'),
+ 1 => I18N::translate('facts'),
+ 2 => I18N::translate('records'),
+ ];
- $theme_options = ['' => I18N::translate('<default theme>')] + Theme::themeNames();
+ $theme_options = ['' => I18N::translate('<default theme>')] + Theme::themeNames();
- $privacy_options = [
- Auth::PRIV_USER => I18N::translate('Show to members'),
- Auth::PRIV_NONE => I18N::translate('Show to managers'),
- Auth::PRIV_HIDE => I18N::translate('Hide from everyone'),
- ];
+ $privacy_options = [
+ Auth::PRIV_USER => I18N::translate('Show to members'),
+ Auth::PRIV_NONE => I18N::translate('Show to managers'),
+ Auth::PRIV_HIDE => I18N::translate('Hide from everyone'),
+ ];
- $tags = array_unique(array_merge(
- explode(',', $tree->getPreference('INDI_FACTS_ADD')), explode(',', $tree->getPreference('INDI_FACTS_UNIQUE')),
- explode(',', $tree->getPreference('FAM_FACTS_ADD')), explode(',', $tree->getPreference('FAM_FACTS_UNIQUE')),
- explode(',', $tree->getPreference('NOTE_FACTS_ADD')), explode(',', $tree->getPreference('NOTE_FACTS_UNIQUE')),
- explode(',', $tree->getPreference('SOUR_FACTS_ADD')), explode(',', $tree->getPreference('SOUR_FACTS_UNIQUE')),
- explode(',', $tree->getPreference('REPO_FACTS_ADD')), explode(',', $tree->getPreference('REPO_FACTS_UNIQUE')),
- ['SOUR', 'REPO', 'OBJE', '_PRIM', 'NOTE', 'SUBM', 'SUBN', '_UID', 'CHAN']
- ));
+ $tags = array_unique(array_merge(
+ explode(',', $tree->getPreference('INDI_FACTS_ADD')), explode(',', $tree->getPreference('INDI_FACTS_UNIQUE')),
+ explode(',', $tree->getPreference('FAM_FACTS_ADD')), explode(',', $tree->getPreference('FAM_FACTS_UNIQUE')),
+ explode(',', $tree->getPreference('NOTE_FACTS_ADD')), explode(',', $tree->getPreference('NOTE_FACTS_UNIQUE')),
+ explode(',', $tree->getPreference('SOUR_FACTS_ADD')), explode(',', $tree->getPreference('SOUR_FACTS_UNIQUE')),
+ explode(',', $tree->getPreference('REPO_FACTS_ADD')), explode(',', $tree->getPreference('REPO_FACTS_UNIQUE')),
+ [
+ 'SOUR',
+ 'REPO',
+ 'OBJE',
+ '_PRIM',
+ 'NOTE',
+ 'SUBM',
+ 'SUBN',
+ '_UID',
+ 'CHAN',
+ ]
+ ));
- $all_tags = [];
- foreach ($tags as $tag) {
- if ($tag) {
- $all_tags[$tag] = GedcomTag::getLabel($tag);
- }
- }
+ $all_tags = [];
+ foreach ($tags as $tag) {
+ if ($tag) {
+ $all_tags[$tag] = GedcomTag::getLabel($tag);
+ }
+ }
- uasort($all_tags, '\Fisharebest\Webtrees\I18N::strcasecmp');
+ uasort($all_tags, '\Fisharebest\Webtrees\I18N::strcasecmp');
- $resns = Database::prepare(
- "SELECT default_resn_id, tag_type, xref, resn" .
- " FROM `##default_resn`" .
- " LEFT JOIN `##name` ON (gedcom_id=n_file AND xref=n_id AND n_num=0)" .
- " WHERE gedcom_id=?" .
- " ORDER BY xref IS NULL, n_sort, xref, tag_type"
- )->execute([$tree->getTreeId()])->fetchAll();
+ $resns = Database::prepare(
+ "SELECT default_resn_id, tag_type, xref, resn" .
+ " FROM `##default_resn`" .
+ " LEFT JOIN `##name` ON (gedcom_id=n_file AND xref=n_id AND n_num=0)" .
+ " WHERE gedcom_id=?" .
+ " ORDER BY xref IS NULL, n_sort, xref, tag_type"
+ )->execute([$tree->getTreeId()])->fetchAll();
- foreach ($resns as $resn) {
- $resn->record = GedcomRecord::getInstance($resn->xref, $tree);
- if ($resn->tag_type) {
- $resn->tag_label = GedcomTag::getLabel($resn->tag_type);
- } else {
- $resn->tag_label = '';
- }
- }
- usort($resns, function (stdClass $x, stdClass $y) {
- return I18N::strcasecmp($x->tag_label, $y->tag_label);
- });
+ foreach ($resns as $resn) {
+ $resn->record = GedcomRecord::getInstance($resn->xref, $tree);
+ if ($resn->tag_type) {
+ $resn->tag_label = GedcomTag::getLabel($resn->tag_type);
+ } else {
+ $resn->tag_label = '';
+ }
+ }
+ usort($resns, function (stdClass $x, stdClass $y) {
+ return I18N::strcasecmp($x->tag_label, $y->tag_label);
+ });
- // For historical reasons, we have two fields in one
- $calendar_formats = explode('_and_', $tree->getPreference('CALENDAR_FORMAT') . '_and_');
+ // For historical reasons, we have two fields in one
+ $calendar_formats = explode('_and_', $tree->getPreference('CALENDAR_FORMAT') . '_and_');
- // Split into separate fields
- $relatives_events = explode(',', $tree->getPreference('SHOW_RELATIVES_EVENTS'));
+ // Split into separate fields
+ $relatives_events = explode(',', $tree->getPreference('SHOW_RELATIVES_EVENTS'));
- $pedigree_individual = Individual::getInstance($tree->getPreference('PEDIGREE_ROOT_ID'), $tree);
+ $pedigree_individual = Individual::getInstance($tree->getPreference('PEDIGREE_ROOT_ID'), $tree);
- $members = array_filter(User::all(), function (User $user) use ($tree) {
- return Auth::isMember($tree, $user);
- });
+ $members = array_filter(User::all(), function (User $user) use ($tree) {
+ return Auth::isMember($tree, $user);
+ });
- $all_fam_facts = GedcomTag::getPicklistFacts('FAM');
- $all_indi_facts = GedcomTag::getPicklistFacts('INDI');
- $all_name_facts = GedcomTag::getPicklistFacts('NAME');
- $all_plac_facts = GedcomTag::getPicklistFacts('PLAC');
- $all_repo_facts = GedcomTag::getPicklistFacts('REPO');
- $all_sour_facts = GedcomTag::getPicklistFacts('SOUR');
+ $all_fam_facts = GedcomTag::getPicklistFacts('FAM');
+ $all_indi_facts = GedcomTag::getPicklistFacts('INDI');
+ $all_name_facts = GedcomTag::getPicklistFacts('NAME');
+ $all_plac_facts = GedcomTag::getPicklistFacts('PLAC');
+ $all_repo_facts = GedcomTag::getPicklistFacts('REPO');
+ $all_sour_facts = GedcomTag::getPicklistFacts('SOUR');
- $all_surname_traditions = SurnameTradition::allDescriptions();
+ $all_surname_traditions = SurnameTradition::allDescriptions();
- $tree_count = count(Tree::getAll());
+ $tree_count = count(Tree::getAll());
- $title = I18N::translate('Preferences') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate('Preferences') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-preferences', [
- 'all_fam_facts' => $all_fam_facts,
- 'all_indi_facts' => $all_indi_facts,
- 'all_name_facts' => $all_name_facts,
- 'all_plac_facts' => $all_plac_facts,
- 'all_repo_facts' => $all_repo_facts,
- 'all_sour_facts' => $all_sour_facts,
- 'all_surname_traditions' => $all_surname_traditions,
- 'calendar_formats' => $calendar_formats,
- 'formats' => $formats,
- 'french_calendar_end' => $french_calendar_end,
- 'french_calendar_start' => $french_calendar_start,
- 'gregorian_calendar_start' => $gregorian_calendar_start,
- 'members' => $members,
- 'page_layouts' => $page_layouts,
- 'pedigree_individual' => $pedigree_individual,
- 'privacy_options' => $privacy_options,
- 'relatives_events' => $relatives_events,
- 'source_types' => $source_types,
- 'surname_list_styles' => $surname_list_styles,
- 'theme_options' => $theme_options,
- 'title' => $title,
- 'tree' => $tree,
- 'tree_count' => $tree_count,
- ]);
- }
+ return $this->viewResponse('admin/trees-preferences', [
+ 'all_fam_facts' => $all_fam_facts,
+ 'all_indi_facts' => $all_indi_facts,
+ 'all_name_facts' => $all_name_facts,
+ 'all_plac_facts' => $all_plac_facts,
+ 'all_repo_facts' => $all_repo_facts,
+ 'all_sour_facts' => $all_sour_facts,
+ 'all_surname_traditions' => $all_surname_traditions,
+ 'calendar_formats' => $calendar_formats,
+ 'formats' => $formats,
+ 'french_calendar_end' => $french_calendar_end,
+ 'french_calendar_start' => $french_calendar_start,
+ 'gregorian_calendar_start' => $gregorian_calendar_start,
+ 'members' => $members,
+ 'page_layouts' => $page_layouts,
+ 'pedigree_individual' => $pedigree_individual,
+ 'privacy_options' => $privacy_options,
+ 'relatives_events' => $relatives_events,
+ 'source_types' => $source_types,
+ 'surname_list_styles' => $surname_list_styles,
+ 'theme_options' => $theme_options,
+ 'title' => $title,
+ 'tree' => $tree,
+ 'tree_count' => $tree_count,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function renumber(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function renumber(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $xrefs = $this->duplicateXrefs($tree);
+ $xrefs = $this->duplicateXrefs($tree);
- $title = I18N::translate(/* I18N: Renumber the records in a family tree */
- 'Renumber family tree') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate(/* I18N: Renumber the records in a family tree */
+ 'Renumber family tree') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-renumber', [
- 'title' => $title,
- 'xrefs' => $xrefs,
- ]);
- }
+ return $this->viewResponse('admin/trees-renumber', [
+ 'title' => $title,
+ 'xrefs' => $xrefs,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function preferencesUpdate(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function preferencesUpdate(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- // Coming soon
- if ((bool) $request->get('all_trees')) {
- FlashMessages::addMessage(I18N::translate('The preferences for all family trees have been updated.'), 'success');
- }
- if ((bool) $request->get('new_trees')) {
- FlashMessages::addMessage(I18N::translate('The preferences for new family trees have been updated.'), 'success');
- }
+ // Coming soon
+ if ((bool)$request->get('all_trees')) {
+ FlashMessages::addMessage(I18N::translate('The preferences for all family trees have been updated.'), 'success');
+ }
+ if ((bool)$request->get('new_trees')) {
+ FlashMessages::addMessage(I18N::translate('The preferences for new family trees have been updated.'), 'success');
+ }
- $tree->setPreference('ADVANCED_NAME_FACTS', implode(',', $request->get('ADVANCED_NAME_FACTS', [])));
- $tree->setPreference('ADVANCED_PLAC_FACTS', implode(',', $request->get('ADVANCED_PLAC_FACTS', [])));
- $tree->setPreference('ALLOW_THEME_DROPDOWN', (string) (bool) $request->get('ALLOW_THEME_DROPDOWN'));
- // For backwards compatibility with webtrees 1.x we store the two calendar formats in one variable
- // e.g. "gregorian_and_jewish"
- $tree->setPreference('CALENDAR_FORMAT', implode('_and_', array_unique([
- $request->get('CALENDAR_FORMAT0', 'none'),
- $request->get('CALENDAR_FORMAT1', 'none'),
- ])));
- $tree->setPreference('CHART_BOX_TAGS', implode(',', $request->get('CHART_BOX_TAGS', [])));
- $tree->setPreference('CONTACT_USER_ID', $request->get('CONTACT_USER_ID'));
- $tree->setPreference('DEFAULT_PEDIGREE_GENERATIONS', (string) (int) $request->get('DEFAULT_PEDIGREE_GENERATIONS'));
- $tree->setPreference('EXPAND_NOTES', (string) (bool) $request->get('EXPAND_NOTES'));
- $tree->setPreference('EXPAND_SOURCES', (string) (bool) $request->get('EXPAND_SOURCES'));
- $tree->setPreference('FAM_FACTS_ADD', implode(',', $request->get('FAM_FACTS_ADD', [])));
- $tree->setPreference('FAM_FACTS_QUICK', implode(',', $request->get('FAM_FACTS_QUICK', [])));
- $tree->setPreference('FAM_FACTS_UNIQUE', implode(',', $request->get('FAM_FACTS_UNIQUE', [])));
- $tree->setPreference('FULL_SOURCES', (string) (bool) $request->get('FULL_SOURCES'));
- $tree->setPreference('FORMAT_TEXT', $request->get('FORMAT_TEXT'));
- $tree->setPreference('GENERATE_UIDS', (string) (bool) $request->get('GENERATE_UIDS'));
- $tree->setPreference('GEONAMES_ACCOUNT', $request->get('GEONAMES_ACCOUNT'));
- $tree->setPreference('HIDE_GEDCOM_ERRORS', (string) (bool) $request->get('HIDE_GEDCOM_ERRORS'));
- $tree->setPreference('INDI_FACTS_ADD', implode(',', $request->get('INDI_FACTS_ADD', [])));
- $tree->setPreference('INDI_FACTS_QUICK', implode(',', $request->get('INDI_FACTS_QUICK', [])));
- $tree->setPreference('INDI_FACTS_UNIQUE', implode(',', $request->get('INDI_FACTS_UNIQUE', [])));
- $tree->setPreference('LANGUAGE', $request->get('LANGUAGE'));
- $tree->setPreference('MAX_DESCENDANCY_GENERATIONS', (string) (int) $request->get('MAX_DESCENDANCY_GENERATIONS'));
- $tree->setPreference('MAX_PEDIGREE_GENERATIONS', (string) (int) $request->get('MAX_PEDIGREE_GENERATIONS'));
- $tree->setPreference('MEDIA_UPLOAD', $request->get('MEDIA_UPLOAD'));
- $tree->setPreference('META_DESCRIPTION', $request->get('META_DESCRIPTION'));
- $tree->setPreference('META_TITLE', $request->get('META_TITLE'));
- $tree->setPreference('NO_UPDATE_CHAN', (string) (bool) $request->get('NO_UPDATE_CHAN'));
- $tree->setPreference('PEDIGREE_LAYOUT', (string) (bool) $request->get('PEDIGREE_LAYOUT'));
- $tree->setPreference('PEDIGREE_ROOT_ID', $request->get('PEDIGREE_ROOT_ID', WT_REGEX_XREF));
- $tree->setPreference('PEDIGREE_SHOW_GENDER', (string) (bool) $request->get('PEDIGREE_SHOW_GENDER'));
- $tree->setPreference('PREFER_LEVEL2_SOURCES', $request->get('PREFER_LEVEL2_SOURCES'));
- $tree->setPreference('QUICK_REQUIRED_FACTS', implode(',', $request->get('QUICK_REQUIRED_FACTS', [])));
- $tree->setPreference('QUICK_REQUIRED_FAMFACTS', implode(',', $request->get('QUICK_REQUIRED_FAMFACTS', [])));
- $tree->setPreference('REPO_FACTS_ADD', implode(',', $request->get('REPO_FACTS_ADD', [])));
- $tree->setPreference('REPO_FACTS_QUICK', implode(',', $request->get('REPO_FACTS_QUICK', [])));
- $tree->setPreference('REPO_FACTS_UNIQUE', implode(',', $request->get('REPO_FACTS_UNIQUE', [])));
- $tree->setPreference('SHOW_COUNTER', (string) (bool) $request->get('SHOW_COUNTER'));
- $tree->setPreference('SHOW_EST_LIST_DATES', (string) (bool) $request->get('SHOW_EST_LIST_DATES'));
- $tree->setPreference('SHOW_FACT_ICONS', (string) (bool) $request->get('SHOW_FACT_ICONS'));
- $tree->setPreference('SHOW_GEDCOM_RECORD', (string) (bool) $request->get('SHOW_GEDCOM_RECORD'));
- $tree->setPreference('SHOW_HIGHLIGHT_IMAGES', (string) (bool) $request->get('SHOW_HIGHLIGHT_IMAGES'));
- $tree->setPreference('SHOW_LAST_CHANGE', (string) (bool) $request->get('SHOW_LAST_CHANGE'));
- $tree->setPreference('SHOW_LDS_AT_GLANCE', (string) (bool) $request->get('SHOW_LDS_AT_GLANCE'));
- $tree->setPreference('SHOW_MEDIA_DOWNLOAD', $request->get('SHOW_MEDIA_DOWNLOAD'));
- $tree->setPreference('SHOW_NO_WATERMARK', $request->get('SHOW_NO_WATERMARK'));
- $tree->setPreference('SHOW_PARENTS_AGE', (string) (bool) $request->get('SHOW_PARENTS_AGE'));
- $tree->setPreference('SHOW_PEDIGREE_PLACES', $request->get('SHOW_PEDIGREE_PLACES'));
- $tree->setPreference('SHOW_PEDIGREE_PLACES_SUFFIX', (string) (bool) $request->get('SHOW_PEDIGREE_PLACES_SUFFIX'));
- $tree->setPreference('SHOW_RELATIVES_EVENTS', implode(',', $request->get('SHOW_RELATIVES_EVENTS', [])));
- $tree->setPreference('SOUR_FACTS_ADD', implode(',', $request->get('SOUR_FACTS_ADD', [])));
- $tree->setPreference('SOUR_FACTS_QUICK', implode(',', $request->get('SOUR_FACTS_QUICK', [])));
- $tree->setPreference('SOUR_FACTS_UNIQUE', implode(',', $request->get('SOUR_FACTS_UNIQUE', [])));
- $tree->setPreference('SUBLIST_TRIGGER_I', (string) (int) $request->get('SUBLIST_TRIGGER_I', 200));
- $tree->setPreference('SURNAME_LIST_STYLE', $request->get('SURNAME_LIST_STYLE'));
- $tree->setPreference('SURNAME_TRADITION', $request->get('SURNAME_TRADITION'));
- $tree->setPreference('THEME_DIR', $request->get('THEME_DIR'));
- $tree->setPreference('USE_SILHOUETTE', (string) (bool) $request->get('USE_SILHOUETTE'));
- $tree->setPreference('WEBMASTER_USER_ID', $request->get('WEBMASTER_USER_ID'));
- $tree->setPreference('WEBTREES_EMAIL', $request->get('WEBTREES_EMAIL'));
- $tree->setPreference('title', $request->get('title'));
+ $tree->setPreference('ADVANCED_NAME_FACTS', implode(',', $request->get('ADVANCED_NAME_FACTS', [])));
+ $tree->setPreference('ADVANCED_PLAC_FACTS', implode(',', $request->get('ADVANCED_PLAC_FACTS', [])));
+ $tree->setPreference('ALLOW_THEME_DROPDOWN', (string)(bool)$request->get('ALLOW_THEME_DROPDOWN'));
+ // For backwards compatibility with webtrees 1.x we store the two calendar formats in one variable
+ // e.g. "gregorian_and_jewish"
+ $tree->setPreference('CALENDAR_FORMAT', implode('_and_', array_unique([
+ $request->get('CALENDAR_FORMAT0', 'none'),
+ $request->get('CALENDAR_FORMAT1', 'none'),
+ ])));
+ $tree->setPreference('CHART_BOX_TAGS', implode(',', $request->get('CHART_BOX_TAGS', [])));
+ $tree->setPreference('CONTACT_USER_ID', $request->get('CONTACT_USER_ID'));
+ $tree->setPreference('DEFAULT_PEDIGREE_GENERATIONS', (string)(int)$request->get('DEFAULT_PEDIGREE_GENERATIONS'));
+ $tree->setPreference('EXPAND_NOTES', (string)(bool)$request->get('EXPAND_NOTES'));
+ $tree->setPreference('EXPAND_SOURCES', (string)(bool)$request->get('EXPAND_SOURCES'));
+ $tree->setPreference('FAM_FACTS_ADD', implode(',', $request->get('FAM_FACTS_ADD', [])));
+ $tree->setPreference('FAM_FACTS_QUICK', implode(',', $request->get('FAM_FACTS_QUICK', [])));
+ $tree->setPreference('FAM_FACTS_UNIQUE', implode(',', $request->get('FAM_FACTS_UNIQUE', [])));
+ $tree->setPreference('FULL_SOURCES', (string)(bool)$request->get('FULL_SOURCES'));
+ $tree->setPreference('FORMAT_TEXT', $request->get('FORMAT_TEXT'));
+ $tree->setPreference('GENERATE_UIDS', (string)(bool)$request->get('GENERATE_UIDS'));
+ $tree->setPreference('GEONAMES_ACCOUNT', $request->get('GEONAMES_ACCOUNT'));
+ $tree->setPreference('HIDE_GEDCOM_ERRORS', (string)(bool)$request->get('HIDE_GEDCOM_ERRORS'));
+ $tree->setPreference('INDI_FACTS_ADD', implode(',', $request->get('INDI_FACTS_ADD', [])));
+ $tree->setPreference('INDI_FACTS_QUICK', implode(',', $request->get('INDI_FACTS_QUICK', [])));
+ $tree->setPreference('INDI_FACTS_UNIQUE', implode(',', $request->get('INDI_FACTS_UNIQUE', [])));
+ $tree->setPreference('LANGUAGE', $request->get('LANGUAGE'));
+ $tree->setPreference('MAX_DESCENDANCY_GENERATIONS', (string)(int)$request->get('MAX_DESCENDANCY_GENERATIONS'));
+ $tree->setPreference('MAX_PEDIGREE_GENERATIONS', (string)(int)$request->get('MAX_PEDIGREE_GENERATIONS'));
+ $tree->setPreference('MEDIA_UPLOAD', $request->get('MEDIA_UPLOAD'));
+ $tree->setPreference('META_DESCRIPTION', $request->get('META_DESCRIPTION'));
+ $tree->setPreference('META_TITLE', $request->get('META_TITLE'));
+ $tree->setPreference('NO_UPDATE_CHAN', (string)(bool)$request->get('NO_UPDATE_CHAN'));
+ $tree->setPreference('PEDIGREE_LAYOUT', (string)(bool)$request->get('PEDIGREE_LAYOUT'));
+ $tree->setPreference('PEDIGREE_ROOT_ID', $request->get('PEDIGREE_ROOT_ID', WT_REGEX_XREF));
+ $tree->setPreference('PEDIGREE_SHOW_GENDER', (string)(bool)$request->get('PEDIGREE_SHOW_GENDER'));
+ $tree->setPreference('PREFER_LEVEL2_SOURCES', $request->get('PREFER_LEVEL2_SOURCES'));
+ $tree->setPreference('QUICK_REQUIRED_FACTS', implode(',', $request->get('QUICK_REQUIRED_FACTS', [])));
+ $tree->setPreference('QUICK_REQUIRED_FAMFACTS', implode(',', $request->get('QUICK_REQUIRED_FAMFACTS', [])));
+ $tree->setPreference('REPO_FACTS_ADD', implode(',', $request->get('REPO_FACTS_ADD', [])));
+ $tree->setPreference('REPO_FACTS_QUICK', implode(',', $request->get('REPO_FACTS_QUICK', [])));
+ $tree->setPreference('REPO_FACTS_UNIQUE', implode(',', $request->get('REPO_FACTS_UNIQUE', [])));
+ $tree->setPreference('SHOW_COUNTER', (string)(bool)$request->get('SHOW_COUNTER'));
+ $tree->setPreference('SHOW_EST_LIST_DATES', (string)(bool)$request->get('SHOW_EST_LIST_DATES'));
+ $tree->setPreference('SHOW_FACT_ICONS', (string)(bool)$request->get('SHOW_FACT_ICONS'));
+ $tree->setPreference('SHOW_GEDCOM_RECORD', (string)(bool)$request->get('SHOW_GEDCOM_RECORD'));
+ $tree->setPreference('SHOW_HIGHLIGHT_IMAGES', (string)(bool)$request->get('SHOW_HIGHLIGHT_IMAGES'));
+ $tree->setPreference('SHOW_LAST_CHANGE', (string)(bool)$request->get('SHOW_LAST_CHANGE'));
+ $tree->setPreference('SHOW_LDS_AT_GLANCE', (string)(bool)$request->get('SHOW_LDS_AT_GLANCE'));
+ $tree->setPreference('SHOW_MEDIA_DOWNLOAD', $request->get('SHOW_MEDIA_DOWNLOAD'));
+ $tree->setPreference('SHOW_NO_WATERMARK', $request->get('SHOW_NO_WATERMARK'));
+ $tree->setPreference('SHOW_PARENTS_AGE', (string)(bool)$request->get('SHOW_PARENTS_AGE'));
+ $tree->setPreference('SHOW_PEDIGREE_PLACES', $request->get('SHOW_PEDIGREE_PLACES'));
+ $tree->setPreference('SHOW_PEDIGREE_PLACES_SUFFIX', (string)(bool)$request->get('SHOW_PEDIGREE_PLACES_SUFFIX'));
+ $tree->setPreference('SHOW_RELATIVES_EVENTS', implode(',', $request->get('SHOW_RELATIVES_EVENTS', [])));
+ $tree->setPreference('SOUR_FACTS_ADD', implode(',', $request->get('SOUR_FACTS_ADD', [])));
+ $tree->setPreference('SOUR_FACTS_QUICK', implode(',', $request->get('SOUR_FACTS_QUICK', [])));
+ $tree->setPreference('SOUR_FACTS_UNIQUE', implode(',', $request->get('SOUR_FACTS_UNIQUE', [])));
+ $tree->setPreference('SUBLIST_TRIGGER_I', (string)(int)$request->get('SUBLIST_TRIGGER_I', 200));
+ $tree->setPreference('SURNAME_LIST_STYLE', $request->get('SURNAME_LIST_STYLE'));
+ $tree->setPreference('SURNAME_TRADITION', $request->get('SURNAME_TRADITION'));
+ $tree->setPreference('THEME_DIR', $request->get('THEME_DIR'));
+ $tree->setPreference('USE_SILHOUETTE', (string)(bool)$request->get('USE_SILHOUETTE'));
+ $tree->setPreference('WEBMASTER_USER_ID', $request->get('WEBMASTER_USER_ID'));
+ $tree->setPreference('WEBTREES_EMAIL', $request->get('WEBTREES_EMAIL'));
+ $tree->setPreference('title', $request->get('title'));
- // Only accept valid folders for MEDIA_DIRECTORY
- $MEDIA_DIRECTORY = preg_replace('/[\/\\\\]+/', '/', $request->get('MEDIA_DIRECTORY') . '/');
- if (substr($MEDIA_DIRECTORY, 0, 1) === '/') {
- $MEDIA_DIRECTORY = substr($MEDIA_DIRECTORY, 1);
- }
+ // Only accept valid folders for MEDIA_DIRECTORY
+ $MEDIA_DIRECTORY = preg_replace('/[\/\\\\]+/', '/', $request->get('MEDIA_DIRECTORY') . '/');
+ if (substr($MEDIA_DIRECTORY, 0, 1) === '/') {
+ $MEDIA_DIRECTORY = substr($MEDIA_DIRECTORY, 1);
+ }
- if ($MEDIA_DIRECTORY) {
- if (is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
- $tree->setPreference('MEDIA_DIRECTORY', $MEDIA_DIRECTORY);
- } elseif (File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
- $tree->setPreference('MEDIA_DIRECTORY', $MEDIA_DIRECTORY);
- FlashMessages::addMessage(I18N::translate('The folder %s has been created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)), 'info');
- } else {
- FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)), 'danger');
- }
- }
+ if ($MEDIA_DIRECTORY) {
+ if (is_dir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
+ $tree->setPreference('MEDIA_DIRECTORY', $MEDIA_DIRECTORY);
+ } elseif (File::mkdir(WT_DATA_DIR . $MEDIA_DIRECTORY)) {
+ $tree->setPreference('MEDIA_DIRECTORY', $MEDIA_DIRECTORY);
+ FlashMessages::addMessage(I18N::translate('The folder %s has been created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)), 'info');
+ } else {
+ FlashMessages::addMessage(I18N::translate('The folder %s does not exist, and it could not be created.', Html::filename(WT_DATA_DIR . $MEDIA_DIRECTORY)), 'danger');
+ }
+ }
- $gedcom = $request->get('gedcom');
- if ($gedcom && $gedcom !== $tree->getName()) {
- try {
- Database::prepare("UPDATE `##gedcom` SET gedcom_name = ? WHERE gedcom_id = ?")->execute([$gedcom, $tree->getTreeId()]);
- Database::prepare("UPDATE `##site_setting` SET setting_value = ? WHERE setting_name='DEFAULT_GEDCOM' AND setting_value = ?")->execute([$gedcom, $tree->getName()]);
- } catch (\Exception $ex) {
- DebugBar::addThrowable($ex);
+ $gedcom = $request->get('gedcom');
+ if ($gedcom && $gedcom !== $tree->getName()) {
+ try {
+ Database::prepare("UPDATE `##gedcom` SET gedcom_name = ? WHERE gedcom_id = ?")->execute([
+ $gedcom,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare("UPDATE `##site_setting` SET setting_value = ? WHERE setting_name='DEFAULT_GEDCOM' AND setting_value = ?")->execute([
+ $gedcom,
+ $tree->getName(),
+ ]);
+ } catch (\Exception $ex) {
+ DebugBar::addThrowable($ex);
- // Probably a duplicate name.
- }
- }
+ // Probably a duplicate name.
+ }
+ }
- FlashMessages::addMessage(I18N::translate('The preferences for the family tree “%s” have been updated.', e($tree->getTitle())), 'success');
+ FlashMessages::addMessage(I18N::translate('The preferences for the family tree “%s” have been updated.', e($tree->getTitle())), 'success');
- $url = route('admin-trees', ['ged' => $tree->getName()]);
+ $url = route('admin-trees', ['ged' => $tree->getName()]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function renumberAction(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function renumberAction(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $xrefs = $this->duplicateXrefs($tree);
+ $xrefs = $this->duplicateXrefs($tree);
- foreach ($xrefs as $old_xref => $type) {
- $new_xref = $tree->getNewXref();
- switch ($type) {
- case 'INDI':
- Database::prepare(
- "UPDATE `##individuals` SET i_id = ?, i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_id = ? AND i_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ INDI\n", "0 @$new_xref@ INDI\n", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'HUSB') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " HUSB @$old_xref@", " HUSB @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'WIFE') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " WIFE @$old_xref@", " WIFE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'CHIL') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " CHIL @$old_xref@", " CHIL @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'ASSO') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " ASSO @$old_xref@", " ASSO @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = '_ASSO') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " _ASSO @$old_xref@", " _ASSO @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'ASSO') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " ASSO @$old_xref@", " ASSO @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = '_ASSO') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " _ASSO @$old_xref@", " _ASSO @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##placelinks` SET pl_gid = ? WHERE pl_gid = ? AND pl_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##dates` SET d_gid = ? WHERE d_gid = ? AND d_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##user_gedcom_setting` SET setting_value = ? WHERE setting_value = ? AND gedcom_id = ? AND setting_name IN ('gedcomid', 'rootid')"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- break;
- case 'FAM':
- Database::prepare(
- "UPDATE `##families` SET f_id = ?, f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_id = ? AND f_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ FAM\n", "0 @$new_xref@ FAM\n", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'FAMC') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " FAMC @$old_xref@", " FAMC @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'FAMS') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " FAMS @$old_xref@", " FAMS @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##placelinks` SET pl_gid = ? WHERE pl_gid = ? AND pl_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##dates` SET d_gid = ? WHERE d_gid = ? AND d_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- break;
- case 'SOUR':
- Database::prepare(
- "UPDATE `##sources` SET s_id = ?, s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_id = ? AND s_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ SOUR\n", "0 @$new_xref@ SOUR\n", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'SOUR') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " SOUR @$old_xref@", " SOUR @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'SOUR') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " SOUR @$old_xref@", " SOUR @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ? AND l_type = 'SOUR') SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
- )->execute([$old_xref, " SOUR @$old_xref@", " SOUR @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ? AND l_type = 'SOUR') SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
- )->execute([$old_xref, " SOUR @$old_xref@", " SOUR @$new_xref@", $tree->getTreeId()]);
- break;
- case 'REPO':
- Database::prepare(
- "UPDATE `##other` SET o_id = ?, o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_id = ? AND o_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ REPO\n", "0 @$new_xref@ REPO\n", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ? AND l_type = 'REPO') SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
- )->execute([$old_xref, " REPO @$old_xref@", " REPO @$new_xref@", $tree->getTreeId()]);
- break;
- case 'NOTE':
- Database::prepare(
- "UPDATE `##other` SET o_id = ?, o_gedcom = REPLACE(REPLACE(o_gedcom, ?, ?), ?, ?) WHERE o_id = ? AND o_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ NOTE\n", "0 @$new_xref@ NOTE\n", "0 @$old_xref@ NOTE ", "0 @$new_xref@ NOTE ", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'NOTE') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " NOTE @$old_xref@", " NOTE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'NOTE') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " NOTE @$old_xref@", " NOTE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ? AND l_type = 'NOTE') SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
- )->execute([$old_xref, " NOTE @$old_xref@", " NOTE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ? AND l_type = 'NOTE') SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
- )->execute([$old_xref, " NOTE @$old_xref@", " NOTE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ? AND l_type = 'NOTE') SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
- )->execute([$old_xref, " NOTE @$old_xref@", " NOTE @$new_xref@", $tree->getTreeId()]);
- break;
- case 'OBJE':
- Database::prepare(
- "UPDATE `##media` SET m_id = ?, m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_id = ? AND m_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ OBJE\n", "0 @$new_xref@ OBJE\n", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##media_file` SET m_id = ? WHERE m_id = ? AND m_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'OBJE') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " OBJE @$old_xref@", " OBJE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'OBJE') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " OBJE @$old_xref@", " OBJE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ? AND l_type = 'OBJE') SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
- )->execute([$old_xref, " OBJE @$old_xref@", " OBJE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ? AND l_type = 'OBJE') SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
- )->execute([$old_xref, " OBJE @$old_xref@", " OBJE @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ? AND l_type = 'OBJE') SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
- )->execute([$old_xref, " OBJE @$old_xref@", " OBJE @$new_xref@", $tree->getTreeId()]);
- break;
- default:
- Database::prepare(
- "UPDATE `##other` SET o_id = ?, o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_id = ? AND o_file = ?"
- )->execute([$new_xref, "0 @$old_xref@ $type\n", "0 @$new_xref@ $type\n", $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ?) SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
- )->execute([$old_xref, " @$old_xref@", " @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ?) SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
- )->execute([$old_xref, " @$old_xref@", " @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ?) SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
- )->execute([$old_xref, " @$old_xref@", " @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ?) SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
- )->execute([$old_xref, " @$old_xref@", " @$new_xref@", $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ?) SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
- )->execute([$old_xref, " @$old_xref@", " @$new_xref@", $tree->getTreeId()]);
- break;
- }
- Database::prepare(
- "UPDATE `##name` SET n_id = ? WHERE n_id = ? AND n_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##default_resn` SET xref = ? WHERE xref = ? AND gedcom_id = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##hit_counter` SET page_parameter = ? WHERE page_parameter = ? AND gedcom_id = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##link` SET l_from = ? WHERE l_from = ? AND l_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- Database::prepare(
- "UPDATE `##link` SET l_to = ? WHERE l_to = ? AND l_file = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
+ foreach ($xrefs as $old_xref => $type) {
+ $new_xref = $tree->getNewXref();
+ switch ($type) {
+ case 'INDI':
+ Database::prepare(
+ "UPDATE `##individuals` SET i_id = ?, i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_id = ? AND i_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ INDI\n",
+ "0 @$new_xref@ INDI\n",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'HUSB') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " HUSB @$old_xref@",
+ " HUSB @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'WIFE') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " WIFE @$old_xref@",
+ " WIFE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'CHIL') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " CHIL @$old_xref@",
+ " CHIL @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'ASSO') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " ASSO @$old_xref@",
+ " ASSO @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = '_ASSO') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " _ASSO @$old_xref@",
+ " _ASSO @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'ASSO') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " ASSO @$old_xref@",
+ " ASSO @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = '_ASSO') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " _ASSO @$old_xref@",
+ " _ASSO @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##placelinks` SET pl_gid = ? WHERE pl_gid = ? AND pl_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##dates` SET d_gid = ? WHERE d_gid = ? AND d_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##user_gedcom_setting` SET setting_value = ? WHERE setting_value = ? AND gedcom_id = ? AND setting_name IN ('gedcomid', 'rootid')"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ break;
+ case 'FAM':
+ Database::prepare(
+ "UPDATE `##families` SET f_id = ?, f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_id = ? AND f_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ FAM\n",
+ "0 @$new_xref@ FAM\n",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'FAMC') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " FAMC @$old_xref@",
+ " FAMC @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'FAMS') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " FAMS @$old_xref@",
+ " FAMS @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##placelinks` SET pl_gid = ? WHERE pl_gid = ? AND pl_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##dates` SET d_gid = ? WHERE d_gid = ? AND d_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ break;
+ case 'SOUR':
+ Database::prepare(
+ "UPDATE `##sources` SET s_id = ?, s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_id = ? AND s_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ SOUR\n",
+ "0 @$new_xref@ SOUR\n",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'SOUR') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " SOUR @$old_xref@",
+ " SOUR @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'SOUR') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " SOUR @$old_xref@",
+ " SOUR @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ? AND l_type = 'SOUR') SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
+ )->execute([
+ $old_xref,
+ " SOUR @$old_xref@",
+ " SOUR @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ? AND l_type = 'SOUR') SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
+ )->execute([
+ $old_xref,
+ " SOUR @$old_xref@",
+ " SOUR @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ break;
+ case 'REPO':
+ Database::prepare(
+ "UPDATE `##other` SET o_id = ?, o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_id = ? AND o_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ REPO\n",
+ "0 @$new_xref@ REPO\n",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ? AND l_type = 'REPO') SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
+ )->execute([
+ $old_xref,
+ " REPO @$old_xref@",
+ " REPO @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ break;
+ case 'NOTE':
+ Database::prepare(
+ "UPDATE `##other` SET o_id = ?, o_gedcom = REPLACE(REPLACE(o_gedcom, ?, ?), ?, ?) WHERE o_id = ? AND o_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ NOTE\n",
+ "0 @$new_xref@ NOTE\n",
+ "0 @$old_xref@ NOTE ",
+ "0 @$new_xref@ NOTE ",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'NOTE') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " NOTE @$old_xref@",
+ " NOTE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'NOTE') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " NOTE @$old_xref@",
+ " NOTE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ? AND l_type = 'NOTE') SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
+ )->execute([
+ $old_xref,
+ " NOTE @$old_xref@",
+ " NOTE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ? AND l_type = 'NOTE') SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
+ )->execute([
+ $old_xref,
+ " NOTE @$old_xref@",
+ " NOTE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ? AND l_type = 'NOTE') SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
+ )->execute([
+ $old_xref,
+ " NOTE @$old_xref@",
+ " NOTE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ break;
+ case 'OBJE':
+ Database::prepare(
+ "UPDATE `##media` SET m_id = ?, m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_id = ? AND m_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ OBJE\n",
+ "0 @$new_xref@ OBJE\n",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##media_file` SET m_id = ? WHERE m_id = ? AND m_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ? AND l_type = 'OBJE') SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " OBJE @$old_xref@",
+ " OBJE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ? AND l_type = 'OBJE') SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " OBJE @$old_xref@",
+ " OBJE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ? AND l_type = 'OBJE') SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
+ )->execute([
+ $old_xref,
+ " OBJE @$old_xref@",
+ " OBJE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ? AND l_type = 'OBJE') SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
+ )->execute([
+ $old_xref,
+ " OBJE @$old_xref@",
+ " OBJE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ? AND l_type = 'OBJE') SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
+ )->execute([
+ $old_xref,
+ " OBJE @$old_xref@",
+ " OBJE @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ break;
+ default:
+ Database::prepare(
+ "UPDATE `##other` SET o_id = ?, o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_id = ? AND o_file = ?"
+ )->execute([
+ $new_xref,
+ "0 @$old_xref@ $type\n",
+ "0 @$new_xref@ $type\n",
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##individuals` JOIN `##link` ON (l_file = i_file AND l_to = ?) SET i_gedcom = REPLACE(i_gedcom, ?, ?) WHERE i_file = ?"
+ )->execute([
+ $old_xref,
+ " @$old_xref@",
+ " @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##families` JOIN `##link` ON (l_file = f_file AND l_to = ?) SET f_gedcom = REPLACE(f_gedcom, ?, ?) WHERE f_file = ?"
+ )->execute([
+ $old_xref,
+ " @$old_xref@",
+ " @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##media` JOIN `##link` ON (l_file = m_file AND l_to = ?) SET m_gedcom = REPLACE(m_gedcom, ?, ?) WHERE m_file = ?"
+ )->execute([
+ $old_xref,
+ " @$old_xref@",
+ " @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##sources` JOIN `##link` ON (l_file = s_file AND l_to = ?) SET s_gedcom = REPLACE(s_gedcom, ?, ?) WHERE s_file = ?"
+ )->execute([
+ $old_xref,
+ " @$old_xref@",
+ " @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##other` JOIN `##link` ON (l_file = o_file AND l_to = ?) SET o_gedcom = REPLACE(o_gedcom, ?, ?) WHERE o_file = ?"
+ )->execute([
+ $old_xref,
+ " @$old_xref@",
+ " @$new_xref@",
+ $tree->getTreeId(),
+ ]);
+ break;
+ }
+ Database::prepare(
+ "UPDATE `##name` SET n_id = ? WHERE n_id = ? AND n_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##default_resn` SET xref = ? WHERE xref = ? AND gedcom_id = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##hit_counter` SET page_parameter = ? WHERE page_parameter = ? AND gedcom_id = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##link` SET l_from = ? WHERE l_from = ? AND l_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ Database::prepare(
+ "UPDATE `##link` SET l_to = ? WHERE l_to = ? AND l_file = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
- unset($xrefs[$old_xref]);
+ unset($xrefs[$old_xref]);
- try {
- Database::prepare(
- "UPDATE `##favorite` SET xref = ? WHERE xref = ? AND gedcom_id = ?"
- )->execute([$new_xref, $old_xref, $tree->getTreeId()]);
- } catch (\Exception $ex) {
- DebugBar::addThrowable($ex);
+ try {
+ Database::prepare(
+ "UPDATE `##favorite` SET xref = ? WHERE xref = ? AND gedcom_id = ?"
+ )->execute([
+ $new_xref,
+ $old_xref,
+ $tree->getTreeId(),
+ ]);
+ } catch (\Exception $ex) {
+ DebugBar::addThrowable($ex);
- // Perhaps the favorites module was not installed?
- }
+ // Perhaps the favorites module was not installed?
+ }
- // How much time do we have left?
- if (microtime(true) - WT_START_TIME > ini_get('max_execution_time') - 5) {
- FlashMessages::addMessage(I18N::translate('The server’s time limit has been reached.'), 'warning');
- break;
- }
- }
+ // How much time do we have left?
+ if (microtime(true) - WT_START_TIME > ini_get('max_execution_time') - 5) {
+ FlashMessages::addMessage(I18N::translate('The server’s time limit has been reached.'), 'warning');
+ break;
+ }
+ }
- $url = route('admin-trees-renumber', ['ged' => $tree->getName()]);
+ $url = route('admin-trees-renumber', ['ged' => $tree->getName()]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function setDefault(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function setDefault(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- Site::setPreference('DEFAULT_GEDCOM', $tree->getName());
+ Site::setPreference('DEFAULT_GEDCOM', $tree->getName());
- FlashMessages::addMessage(/* I18N: %s is the name of a family tree */
- I18N::translate('The family tree “%s” will be shown to visitors when they first arrive at this website.', e($tree->getTitle())), 'success');
+ FlashMessages::addMessage(/* I18N: %s is the name of a family tree */
+ I18N::translate('The family tree “%s” will be shown to visitors when they first arrive at this website.', e($tree->getTitle())), 'success');
- $url = route('admin-trees');
+ $url = route('admin-trees');
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return RedirectResponse
- */
- public function synchronize(Request $request): RedirectResponse {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return RedirectResponse
+ */
+ public function synchronize(Request $request): RedirectResponse
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- $gedcom_files = $this->gedcomFiles(WT_DATA_DIR);
+ $gedcom_files = $this->gedcomFiles(WT_DATA_DIR);
- foreach ($gedcom_files as $gedcom_file) {
- // Only import files that have changed
- $filemtime = (string) filemtime(WT_DATA_DIR . $gedcom_file);
+ foreach ($gedcom_files as $gedcom_file) {
+ // Only import files that have changed
+ $filemtime = (string)filemtime(WT_DATA_DIR . $gedcom_file);
- $tree = Tree::findByName($gedcom_file) ?? Tree::create($gedcom_file, $gedcom_file);
+ $tree = Tree::findByName($gedcom_file) ?? Tree::create($gedcom_file, $gedcom_file);
- if ($tree->getPreference('filemtime') !== $filemtime) {
- $tree->importGedcomFile(WT_DATA_DIR . $gedcom_file, $gedcom_file);
- $tree->setPreference('filemtime', $filemtime);
+ if ($tree->getPreference('filemtime') !== $filemtime) {
+ $tree->importGedcomFile(WT_DATA_DIR . $gedcom_file, $gedcom_file);
+ $tree->setPreference('filemtime', $filemtime);
- FlashMessages::addMessage(I18N::translate('The GEDCOM file “%s” has been imported.', e($gedcom_file)), 'success');
- }
- }
+ FlashMessages::addMessage(I18N::translate('The GEDCOM file “%s” has been imported.', e($gedcom_file)), 'success');
+ }
+ }
- foreach (Tree::getAll() as $tree) {
- if (!in_array($tree->getName(), $gedcom_files)) {
- FlashMessages::addMessage(I18N::translate('The family tree “%s” has been deleted.', e($tree->getTitle())), 'success');
- $tree->delete();
- }
- }
+ foreach (Tree::getAll() as $tree) {
+ if (!in_array($tree->getName(), $gedcom_files)) {
+ FlashMessages::addMessage(I18N::translate('The family tree “%s” has been deleted.', e($tree->getTitle())), 'success');
+ $tree->delete();
+ }
+ }
- $url = route('admin-trees', ['ged' => $tree->getName()]);
+ $url = route('admin-trees', ['ged' => $tree->getName()]);
- return new RedirectResponse($url);
- }
+ return new RedirectResponse($url);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function unconnected(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function unconnected(Request $request): Response
+ {
+ /** @var Tree $tree */
+ $tree = $request->attributes->get('tree');
- /** @var User $user */
- $user = $request->attributes->get('user');
+ /** @var User $user */
+ $user = $request->attributes->get('user');
- $associates = (bool) $request->get('associates');
+ $associates = (bool)$request->get('associates');
- if ($associates) {
- $sql = "SELECT l_from, l_to FROM `##link` WHERE l_file = :tree_id AND l_type IN ('FAMS', 'FAMC', 'ASSO', '_ASSO')";
- } else {
- $sql = "SELECT l_from, l_to FROM `##link` WHERE l_file = :tree_id AND l_type IN ('FAMS', 'FAMC')";
- }
+ if ($associates) {
+ $sql = "SELECT l_from, l_to FROM `##link` WHERE l_file = :tree_id AND l_type IN ('FAMS', 'FAMC', 'ASSO', '_ASSO')";
+ } else {
+ $sql = "SELECT l_from, l_to FROM `##link` WHERE l_file = :tree_id AND l_type IN ('FAMS', 'FAMC')";
+ }
- $rows = Database::prepare($sql)->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
- $graph = [];
+ $rows = Database::prepare($sql)->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
+ $graph = [];
- foreach ($rows as $row) {
- $graph[$row->l_from][$row->l_to] = 1;
- $graph[$row->l_to][$row->l_from] = 1;
- }
+ foreach ($rows as $row) {
+ $graph[$row->l_from][$row->l_to] = 1;
+ $graph[$row->l_to][$row->l_from] = 1;
+ }
- $algorithm = new ConnectedComponent($graph);
- $components = $algorithm->findConnectedComponents();
- $root = $tree->significantIndividual($user);
- $xref = $root->getXref();
+ $algorithm = new ConnectedComponent($graph);
+ $components = $algorithm->findConnectedComponents();
+ $root = $tree->significantIndividual($user);
+ $xref = $root->getXref();
- /** @var Individual[][] */
- $individual_groups = [];
+ /** @var Individual[][] */
+ $individual_groups = [];
- foreach ($components as $component) {
- if (!in_array($xref, $component)) {
- $individuals = [];
- foreach ($component as $xref) {
- $individuals[] = Individual::getInstance($xref, $tree);
- }
- // The database query may return pending additions/deletions, which may not exist.
- $individual_groups[] = array_filter($individuals);
- }
- }
+ foreach ($components as $component) {
+ if (!in_array($xref, $component)) {
+ $individuals = [];
+ foreach ($component as $xref) {
+ $individuals[] = Individual::getInstance($xref, $tree);
+ }
+ // The database query may return pending additions/deletions, which may not exist.
+ $individual_groups[] = array_filter($individuals);
+ }
+ }
- $title = I18N::translate('Find unrelated individuals') . ' — ' . e($tree->getTitle());
+ $title = I18N::translate('Find unrelated individuals') . ' — ' . e($tree->getTitle());
- return $this->viewResponse('admin/trees-unconnected', [
- 'associates' => $associates,
- 'root' => $root,
- 'individual_groups' => $individual_groups,
- 'title' => $title,
- ]);
- }
+ return $this->viewResponse('admin/trees-unconnected', [
+ 'associates' => $associates,
+ 'root' => $root,
+ 'individual_groups' => $individual_groups,
+ 'title' => $title,
+ ]);
+ }
- /**
- * Find a list of place names that would be updated.
- *
- * @param Tree $tree
- * @param string $search
- * @param string $replace
- *
- * @return string[]
- */
- private function changePlacesPreview(Tree $tree, string $search, string $replace): array {
- $changes = [];
+ /**
+ * Find a list of place names that would be updated.
+ *
+ * @param Tree $tree
+ * @param string $search
+ * @param string $replace
+ *
+ * @return string[]
+ */
+ private function changePlacesPreview(Tree $tree, string $search, string $replace): array
+ {
+ $changes = [];
- $rows = Database::prepare(
- "SELECT i_id AS xref, COALESCE(new_gedcom, i_gedcom) AS gedcom" .
- " FROM `##individuals`" .
- " LEFT JOIN `##change` ON (i_id = xref AND i_file=gedcom_id AND status='pending')" .
- " WHERE i_file = ?" .
- " AND COALESCE(new_gedcom, i_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
- )->execute([$tree->getTreeId(), preg_quote($search)])->fetchAll();
- foreach ($rows as $row) {
- $record = Individual::getInstance($row->xref, $tree, $row->gedcom);
- foreach ($record->getFacts() as $fact) {
- $old_place = $fact->getAttribute('PLAC');
- if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
- $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
- $changes[$old_place] = $new_place;
- }
- }
- }
- $rows = Database::prepare(
- "SELECT f_id AS xref, COALESCE(new_gedcom, f_gedcom) AS gedcom" .
- " FROM `##families`" .
- " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" .
- " WHERE f_file = ?" .
- " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
- )->execute([$tree->getTreeId(), preg_quote($search)])->fetchAll();
- foreach ($rows as $row) {
- $record = Family::getInstance($row->xref, $tree, $row->gedcom);
- foreach ($record->getFacts() as $fact) {
- $old_place = $fact->getAttribute('PLAC');
- if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
- $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
- $changes[$old_place] = $new_place;
- }
- }
- }
+ $rows = Database::prepare(
+ "SELECT i_id AS xref, COALESCE(new_gedcom, i_gedcom) AS gedcom" .
+ " FROM `##individuals`" .
+ " LEFT JOIN `##change` ON (i_id = xref AND i_file=gedcom_id AND status='pending')" .
+ " WHERE i_file = ?" .
+ " AND COALESCE(new_gedcom, i_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
+ )->execute([
+ $tree->getTreeId(),
+ preg_quote($search),
+ ])->fetchAll();
+ foreach ($rows as $row) {
+ $record = Individual::getInstance($row->xref, $tree, $row->gedcom);
+ foreach ($record->getFacts() as $fact) {
+ $old_place = $fact->getAttribute('PLAC');
+ if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
+ $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
+ $changes[$old_place] = $new_place;
+ }
+ }
+ }
+ $rows = Database::prepare(
+ "SELECT f_id AS xref, COALESCE(new_gedcom, f_gedcom) AS gedcom" .
+ " FROM `##families`" .
+ " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" .
+ " WHERE f_file = ?" .
+ " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
+ )->execute([
+ $tree->getTreeId(),
+ preg_quote($search),
+ ])->fetchAll();
+ foreach ($rows as $row) {
+ $record = Family::getInstance($row->xref, $tree, $row->gedcom);
+ foreach ($record->getFacts() as $fact) {
+ $old_place = $fact->getAttribute('PLAC');
+ if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
+ $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
+ $changes[$old_place] = $new_place;
+ }
+ }
+ }
- asort($changes);
+ asort($changes);
- return $changes;
- }
+ return $changes;
+ }
- /**
- * Find a list of place names that would be updated.
- *
- * @param Tree $tree
- * @param string $search
- * @param string $replace
- *
- * @return string[]
- */
- private function changePlacesUpdate(Tree $tree, string $search, string $replace): array {
- $changes = [];
+ /**
+ * Find a list of place names that would be updated.
+ *
+ * @param Tree $tree
+ * @param string $search
+ * @param string $replace
+ *
+ * @return string[]
+ */
+ private function changePlacesUpdate(Tree $tree, string $search, string $replace): array
+ {
+ $changes = [];
- $rows = Database::prepare(
- "SELECT i_id AS xref, COALESCE(new_gedcom, i_gedcom) AS gedcom" .
- " FROM `##individuals`" .
- " LEFT JOIN `##change` ON (i_id = xref AND i_file=gedcom_id AND status='pending')" .
- " WHERE i_file = ?" .
- " AND COALESCE(new_gedcom, i_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
- )->execute([$tree->getTreeId(), preg_quote($search)])->fetchAll();
- foreach ($rows as $row) {
- $record = Individual::getInstance($row->xref, $tree, $row->gedcom);
- foreach ($record->getFacts() as $fact) {
- $old_place = $fact->getAttribute('PLAC');
- if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
- $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
- $changes[$old_place] = $new_place;
- $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom());
- $record->updateFact($fact->getFactId(), $gedcom, false);
- }
- }
- }
- $rows = Database::prepare(
- "SELECT f_id AS xref, COALESCE(new_gedcom, f_gedcom) AS gedcom" .
- " FROM `##families`" .
- " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" .
- " WHERE f_file = ?" .
- " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
- )->execute([$tree->getTreeId(), preg_quote($search)])->fetchAll();
- foreach ($rows as $row) {
- $record = Family::getInstance($row->xref, $tree, $row->gedcom);
- foreach ($record->getFacts() as $fact) {
- $old_place = $fact->getAttribute('PLAC');
- if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
- $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
- $changes[$old_place] = $new_place;
- $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom());
- $record->updateFact($fact->getFactId(), $gedcom, false);
- }
- }
- }
+ $rows = Database::prepare(
+ "SELECT i_id AS xref, COALESCE(new_gedcom, i_gedcom) AS gedcom" .
+ " FROM `##individuals`" .
+ " LEFT JOIN `##change` ON (i_id = xref AND i_file=gedcom_id AND status='pending')" .
+ " WHERE i_file = ?" .
+ " AND COALESCE(new_gedcom, i_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
+ )->execute([
+ $tree->getTreeId(),
+ preg_quote($search),
+ ])->fetchAll();
+ foreach ($rows as $row) {
+ $record = Individual::getInstance($row->xref, $tree, $row->gedcom);
+ foreach ($record->getFacts() as $fact) {
+ $old_place = $fact->getAttribute('PLAC');
+ if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
+ $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
+ $changes[$old_place] = $new_place;
+ $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom());
+ $record->updateFact($fact->getFactId(), $gedcom, false);
+ }
+ }
+ }
+ $rows = Database::prepare(
+ "SELECT f_id AS xref, COALESCE(new_gedcom, f_gedcom) AS gedcom" .
+ " FROM `##families`" .
+ " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" .
+ " WHERE f_file = ?" .
+ " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')"
+ )->execute([
+ $tree->getTreeId(),
+ preg_quote($search),
+ ])->fetchAll();
+ foreach ($rows as $row) {
+ $record = Family::getInstance($row->xref, $tree, $row->gedcom);
+ foreach ($record->getFacts() as $fact) {
+ $old_place = $fact->getAttribute('PLAC');
+ if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) {
+ $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place);
+ $changes[$old_place] = $new_place;
+ $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom());
+ $record->updateFact($fact->getFactId(), $gedcom, false);
+ }
+ }
+ }
- asort($changes);
+ asort($changes);
- return $changes;
- }
+ return $changes;
+ }
- /**
- * Every XREF used by two trees at the same time.
- *
- * @param Tree $tree1
- * @param Tree $tree2
- *
- * @return string[]
- */
- private function commonXrefs(Tree $tree1, Tree $tree2): array {
- return Database::prepare(
- "SELECT xref, type FROM (" .
- " SELECT i_id AS xref, 'INDI' AS type FROM `##individuals` WHERE i_file = ?" .
- " UNION " .
- " SELECT f_id AS xref, 'FAM' AS type FROM `##families` WHERE f_file = ?" .
- " UNION " .
- " SELECT s_id AS xref, 'SOUR' AS type FROM `##sources` WHERE s_file = ?" .
- " UNION " .
- " SELECT m_id AS xref, 'OBJE' AS type FROM `##media` WHERE m_file = ?" .
- " UNION " .
- " SELECT o_id AS xref, o_type AS type FROM `##other` WHERE o_file = ? AND o_type NOT IN ('HEAD', 'TRLR')" .
- ") AS this_tree JOIN (" .
- " SELECT xref FROM `##change` WHERE gedcom_id = ?" .
- " UNION " .
- " SELECT i_id AS xref FROM `##individuals` WHERE i_file = ?" .
- " UNION " .
- " SELECT f_id AS xref FROM `##families` WHERE f_file = ?" .
- " UNION " .
- " SELECT s_id AS xref FROM `##sources` WHERE s_file = ?" .
- " UNION " .
- " SELECT m_id AS xref FROM `##media` WHERE m_file = ?" .
- " UNION " .
- " SELECT o_id AS xref FROM `##other` WHERE o_file = ? AND o_type NOT IN ('HEAD', 'TRLR')" .
- ") AS other_trees USING (xref)"
- )->execute([
- $tree1->getTreeId(),
- $tree1->getTreeId(),
- $tree1->getTreeId(),
- $tree1->getTreeId(),
- $tree1->getTreeId(),
- $tree2->getTreeId(),
- $tree2->getTreeId(),
- $tree2->getTreeId(),
- $tree2->getTreeId(),
- $tree2->getTreeId(),
- $tree2->getTreeId(),
- ])->fetchAssoc();
- }
+ /**
+ * Every XREF used by two trees at the same time.
+ *
+ * @param Tree $tree1
+ * @param Tree $tree2
+ *
+ * @return string[]
+ */
+ private function commonXrefs(Tree $tree1, Tree $tree2): array
+ {
+ return Database::prepare(
+ "SELECT xref, type FROM (" .
+ " SELECT i_id AS xref, 'INDI' AS type FROM `##individuals` WHERE i_file = ?" .
+ " UNION " .
+ " SELECT f_id AS xref, 'FAM' AS type FROM `##families` WHERE f_file = ?" .
+ " UNION " .
+ " SELECT s_id AS xref, 'SOUR' AS type FROM `##sources` WHERE s_file = ?" .
+ " UNION " .
+ " SELECT m_id AS xref, 'OBJE' AS type FROM `##media` WHERE m_file = ?" .
+ " UNION " .
+ " SELECT o_id AS xref, o_type AS type FROM `##other` WHERE o_file = ? AND o_type NOT IN ('HEAD', 'TRLR')" .
+ ") AS this_tree JOIN (" .
+ " SELECT xref FROM `##change` WHERE gedcom_id = ?" .
+ " UNION " .
+ " SELECT i_id AS xref FROM `##individuals` WHERE i_file = ?" .
+ " UNION " .
+ " SELECT f_id AS xref FROM `##families` WHERE f_file = ?" .
+ " UNION " .
+ " SELECT s_id AS xref FROM `##sources` WHERE s_file = ?" .
+ " UNION " .
+ " SELECT m_id AS xref FROM `##media` WHERE m_file = ?" .
+ " UNION " .
+ " SELECT o_id AS xref FROM `##other` WHERE o_file = ? AND o_type NOT IN ('HEAD', 'TRLR')" .
+ ") AS other_trees USING (xref)"
+ )->execute([
+ $tree1->getTreeId(),
+ $tree1->getTreeId(),
+ $tree1->getTreeId(),
+ $tree1->getTreeId(),
+ $tree1->getTreeId(),
+ $tree2->getTreeId(),
+ $tree2->getTreeId(),
+ $tree2->getTreeId(),
+ $tree2->getTreeId(),
+ $tree2->getTreeId(),
+ $tree2->getTreeId(),
+ ])->fetchAssoc();
+ }
- /**
- * @param Tree $tree
- *
- * @return array
- */
- private function duplicateRecords(Tree $tree): array {
- $repositories = Database::prepare(
- "SELECT GROUP_CONCAT(n_id) AS xrefs " .
- " FROM `##other`" .
- " JOIN `##name` ON o_id = n_id AND o_file = n_file" .
- " WHERE o_file = :tree_id AND o_type = 'REPO'" .
- " GROUP BY n_full" .
- " HAVING COUNT(n_id) > 1"
- )->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
+ /**
+ * @param Tree $tree
+ *
+ * @return array
+ */
+ private function duplicateRecords(Tree $tree): array
+ {
+ $repositories = Database::prepare(
+ "SELECT GROUP_CONCAT(n_id) AS xrefs " .
+ " FROM `##other`" .
+ " JOIN `##name` ON o_id = n_id AND o_file = n_file" .
+ " WHERE o_file = :tree_id AND o_type = 'REPO'" .
+ " GROUP BY n_full" .
+ " HAVING COUNT(n_id) > 1"
+ )->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
- $repositories = array_map(
- function (stdClass $x) use ($tree) {
- $tmp = explode(',', $x->xrefs);
+ $repositories = array_map(
+ function (stdClass $x) use ($tree) {
+ $tmp = explode(',', $x->xrefs);
- return array_map(function ($y) use ($tree) {
- return Repository::getInstance($y, $tree);
- }, $tmp);
- }, $repositories
- );
+ return array_map(function ($y) use ($tree) {
+ return Repository::getInstance($y, $tree);
+ }, $tmp);
+ }, $repositories
+ );
- $sources = Database::prepare(
- "SELECT GROUP_CONCAT(n_id) AS xrefs " .
- " FROM `##sources`" .
- " JOIN `##name` ON s_id = n_id AND s_file = n_file" .
- " WHERE s_file = :tree_id" .
- " GROUP BY n_full" .
- " HAVING COUNT(n_id) > 1"
- )->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
+ $sources = Database::prepare(
+ "SELECT GROUP_CONCAT(n_id) AS xrefs " .
+ " FROM `##sources`" .
+ " JOIN `##name` ON s_id = n_id AND s_file = n_file" .
+ " WHERE s_file = :tree_id" .
+ " GROUP BY n_full" .
+ " HAVING COUNT(n_id) > 1"
+ )->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
- $sources = array_map(
- function (stdClass $x) use ($tree) {
- $tmp = explode(',', $x->xrefs);
+ $sources = array_map(
+ function (stdClass $x) use ($tree) {
+ $tmp = explode(',', $x->xrefs);
- return array_map(function ($y) use ($tree) {
- return Source::getInstance($y, $tree);
- }, $tmp);
- }, $sources
- );
+ return array_map(function ($y) use ($tree) {
+ return Source::getInstance($y, $tree);
+ }, $tmp);
+ }, $sources
+ );
- $individuals = Database::prepare(
- "SELECT DISTINCT GROUP_CONCAT(d_gid ORDER BY d_gid) AS xrefs" .
- " FROM `##dates` AS d" .
- " JOIN `##name` ON d_file = n_file AND d_gid = n_id" .
- " WHERE d_file = :tree_id AND d_fact IN ('BIRT', 'CHR', 'BAPM', 'DEAT', 'BURI')" .
- " GROUP BY d_day, d_month, d_year, d_type, d_fact, n_type, n_full" .
- " HAVING COUNT(DISTINCT d_gid) > 1"
- )->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
+ $individuals = Database::prepare(
+ "SELECT DISTINCT GROUP_CONCAT(d_gid ORDER BY d_gid) AS xrefs" .
+ " FROM `##dates` AS d" .
+ " JOIN `##name` ON d_file = n_file AND d_gid = n_id" .
+ " WHERE d_file = :tree_id AND d_fact IN ('BIRT', 'CHR', 'BAPM', 'DEAT', 'BURI')" .
+ " GROUP BY d_day, d_month, d_year, d_type, d_fact, n_type, n_full" .
+ " HAVING COUNT(DISTINCT d_gid) > 1"
+ )->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
- $individuals = array_map(
- function (stdClass $x) use ($tree) {
- $tmp = explode(',', $x->xrefs);
+ $individuals = array_map(
+ function (stdClass $x) use ($tree) {
+ $tmp = explode(',', $x->xrefs);
- return array_map(function ($y) use ($tree) {
- return Individual::getInstance($y, $tree);
- }, $tmp);
- }, $individuals
- );
+ return array_map(function ($y) use ($tree) {
+ return Individual::getInstance($y, $tree);
+ }, $tmp);
+ }, $individuals
+ );
- $families = Database::prepare(
- "SELECT GROUP_CONCAT(f_id) AS xrefs " .
- " FROM `##families`" .
- " WHERE f_file = :tree_id" .
- " GROUP BY LEAST(f_husb, f_wife), GREATEST(f_husb, f_wife)" .
- " HAVING COUNT(f_id) > 1"
- )->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
+ $families = Database::prepare(
+ "SELECT GROUP_CONCAT(f_id) AS xrefs " .
+ " FROM `##families`" .
+ " WHERE f_file = :tree_id" .
+ " GROUP BY LEAST(f_husb, f_wife), GREATEST(f_husb, f_wife)" .
+ " HAVING COUNT(f_id) > 1"
+ )->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
- $families = array_map(
- function (stdClass $x) use ($tree) {
- $tmp = explode(',', $x->xrefs);
+ $families = array_map(
+ function (stdClass $x) use ($tree) {
+ $tmp = explode(',', $x->xrefs);
- return array_map(function ($y) use ($tree) {
- return Family::getInstance($y, $tree);
- }, $tmp);
- }, $families
- );
+ return array_map(function ($y) use ($tree) {
+ return Family::getInstance($y, $tree);
+ }, $tmp);
+ }, $families
+ );
- $media = Database::prepare(
- "SELECT GROUP_CONCAT(m_id) AS xrefs " .
- " FROM `##media`" .
- " JOIN `##media_file` USING (m_id, m_file)" .
- " WHERE m_file = :tree_id AND descriptive_title <> ''" .
- " GROUP BY descriptive_title" .
- " HAVING COUNT(m_id) > 1"
- )->execute([
- 'tree_id' => $tree->getTreeId(),
- ])->fetchAll();
+ $media = Database::prepare(
+ "SELECT GROUP_CONCAT(m_id) AS xrefs " .
+ " FROM `##media`" .
+ " JOIN `##media_file` USING (m_id, m_file)" .
+ " WHERE m_file = :tree_id AND descriptive_title <> ''" .
+ " GROUP BY descriptive_title" .
+ " HAVING COUNT(m_id) > 1"
+ )->execute([
+ 'tree_id' => $tree->getTreeId(),
+ ])->fetchAll();
- $media = array_map(
- function (stdClass $x) use ($tree) {
- $tmp = explode(',', $x->xrefs);
+ $media = array_map(
+ function (stdClass $x) use ($tree) {
+ $tmp = explode(',', $x->xrefs);
- return array_map(function ($y) use ($tree) {
- return Media::getInstance($y, $tree);
- }, $tmp);
- }, $media
- );
+ return array_map(function ($y) use ($tree) {
+ return Media::getInstance($y, $tree);
+ }, $tmp);
+ }, $media
+ );
- return [
- I18N::translate('Repositories') => $repositories,
- I18N::translate('Sources') => $sources,
- I18N::translate('Individuals') => $individuals,
- I18N::translate('Families') => $families,
- I18N::translate('Media objects') => $media,
- ];
- }
+ return [
+ I18N::translate('Repositories') => $repositories,
+ I18N::translate('Sources') => $sources,
+ I18N::translate('Individuals') => $individuals,
+ I18N::translate('Families') => $families,
+ I18N::translate('Media objects') => $media,
+ ];
+ }
- /**
- * Every XREF used by this tree and also used by some other tree
- *
- * @param Tree $tree
- *
- * @return string[]
- */
- private function duplicateXrefs(Tree $tree): array {
- return Database::prepare(
- "SELECT xref, type FROM (" .
- " SELECT i_id AS xref, 'INDI' AS type FROM `##individuals` WHERE i_file = :tree_id_1" .
- " UNION " .
- " SELECT f_id AS xref, 'FAM' AS type FROM `##families` WHERE f_file = :tree_id_2" .
- " UNION " .
- " SELECT s_id AS xref, 'SOUR' AS type FROM `##sources` WHERE s_file = :tree_id_3" .
- " UNION " .
- " SELECT m_id AS xref, 'OBJE' AS type FROM `##media` WHERE m_file = :tree_id_4" .
- " UNION " .
- " SELECT o_id AS xref, o_type AS type FROM `##other` WHERE o_file = :tree_id_5 AND o_type NOT IN ('HEAD', 'TRLR')" .
- ") AS this_tree JOIN (" .
- " SELECT xref FROM `##change` WHERE gedcom_id <> :tree_id_6" .
- " UNION " .
- " SELECT i_id AS xref FROM `##individuals` WHERE i_file <> :tree_id_7" .
- " UNION " .
- " SELECT f_id AS xref FROM `##families` WHERE f_file <> :tree_id_8" .
- " UNION " .
- " SELECT s_id AS xref FROM `##sources` WHERE s_file <> :tree_id_9" .
- " UNION " .
- " SELECT m_id AS xref FROM `##media` WHERE m_file <> :tree_id_10" .
- " UNION " .
- " SELECT o_id AS xref FROM `##other` WHERE o_file <> :tree_id_11 AND o_type NOT IN ('HEAD', 'TRLR')" .
- ") AS other_trees USING (xref)"
- )->execute([
- 'tree_id_1' => $tree->getTreeId(),
- 'tree_id_2' => $tree->getTreeId(),
- 'tree_id_3' => $tree->getTreeId(),
- 'tree_id_4' => $tree->getTreeId(),
- 'tree_id_5' => $tree->getTreeId(),
- 'tree_id_6' => $tree->getTreeId(),
- 'tree_id_7' => $tree->getTreeId(),
- 'tree_id_8' => $tree->getTreeId(),
- 'tree_id_9' => $tree->getTreeId(),
- 'tree_id_10' => $tree->getTreeId(),
- 'tree_id_11' => $tree->getTreeId(),
- ])->fetchAssoc();
- }
+ /**
+ * Every XREF used by this tree and also used by some other tree
+ *
+ * @param Tree $tree
+ *
+ * @return string[]
+ */
+ private function duplicateXrefs(Tree $tree): array
+ {
+ return Database::prepare(
+ "SELECT xref, type FROM (" .
+ " SELECT i_id AS xref, 'INDI' AS type FROM `##individuals` WHERE i_file = :tree_id_1" .
+ " UNION " .
+ " SELECT f_id AS xref, 'FAM' AS type FROM `##families` WHERE f_file = :tree_id_2" .
+ " UNION " .
+ " SELECT s_id AS xref, 'SOUR' AS type FROM `##sources` WHERE s_file = :tree_id_3" .
+ " UNION " .
+ " SELECT m_id AS xref, 'OBJE' AS type FROM `##media` WHERE m_file = :tree_id_4" .
+ " UNION " .
+ " SELECT o_id AS xref, o_type AS type FROM `##other` WHERE o_file = :tree_id_5 AND o_type NOT IN ('HEAD', 'TRLR')" .
+ ") AS this_tree JOIN (" .
+ " SELECT xref FROM `##change` WHERE gedcom_id <> :tree_id_6" .
+ " UNION " .
+ " SELECT i_id AS xref FROM `##individuals` WHERE i_file <> :tree_id_7" .
+ " UNION " .
+ " SELECT f_id AS xref FROM `##families` WHERE f_file <> :tree_id_8" .
+ " UNION " .
+ " SELECT s_id AS xref FROM `##sources` WHERE s_file <> :tree_id_9" .
+ " UNION " .
+ " SELECT m_id AS xref FROM `##media` WHERE m_file <> :tree_id_10" .
+ " UNION " .
+ " SELECT o_id AS xref FROM `##other` WHERE o_file <> :tree_id_11 AND o_type NOT IN ('HEAD', 'TRLR')" .
+ ") AS other_trees USING (xref)"
+ )->execute([
+ 'tree_id_1' => $tree->getTreeId(),
+ 'tree_id_2' => $tree->getTreeId(),
+ 'tree_id_3' => $tree->getTreeId(),
+ 'tree_id_4' => $tree->getTreeId(),
+ 'tree_id_5' => $tree->getTreeId(),
+ 'tree_id_6' => $tree->getTreeId(),
+ 'tree_id_7' => $tree->getTreeId(),
+ 'tree_id_8' => $tree->getTreeId(),
+ 'tree_id_9' => $tree->getTreeId(),
+ 'tree_id_10' => $tree->getTreeId(),
+ 'tree_id_11' => $tree->getTreeId(),
+ ])->fetchAssoc();
+ }
- /**
- * Find a list of GEDCOM files in a folder
- *
- * @param string $folder
- *
- * @return array
- */
- private function gedcomFiles(string $folder): array {
- $d = opendir($folder);
- $files = [];
- while (($f = readdir($d)) !== false) {
- if (!is_dir(WT_DATA_DIR . $f) && is_readable(WT_DATA_DIR . $f)) {
- $fp = fopen(WT_DATA_DIR . $f, 'rb');
- $header = fread($fp, 64);
- fclose($fp);
- if (preg_match('/^(' . WT_UTF8_BOM . ')?0 *HEAD/', $header)) {
- $files[] = $f;
- }
- }
- }
- sort($files);
+ /**
+ * Find a list of GEDCOM files in a folder
+ *
+ * @param string $folder
+ *
+ * @return array
+ */
+ private function gedcomFiles(string $folder): array
+ {
+ $d = opendir($folder);
+ $files = [];
+ while (($f = readdir($d)) !== false) {
+ if (!is_dir(WT_DATA_DIR . $f) && is_readable(WT_DATA_DIR . $f)) {
+ $fp = fopen(WT_DATA_DIR . $f, 'rb');
+ $header = fread($fp, 64);
+ fclose($fp);
+ if (preg_match('/^(' . WT_UTF8_BOM . ')?0 *HEAD/', $header)) {
+ $files[] = $f;
+ }
+ }
+ }
+ sort($files);
- return $files;
- }
+ return $files;
+ }
- /**
- * Generate a unqiue name for new trees
- *
- * @return string
- */
- private function generateNewTreeName(): string {
- $tree_name = 'tree';
- $tree_number = 1;
- $existing_trees = Tree::getNameList();
+ /**
+ * Generate a unqiue name for new trees
+ *
+ * @return string
+ */
+ private function generateNewTreeName(): string
+ {
+ $tree_name = 'tree';
+ $tree_number = 1;
+ $existing_trees = Tree::getNameList();
- while (array_key_exists($tree_name . $tree_number, $existing_trees)) {
- $tree_number++;
- }
+ while (array_key_exists($tree_name . $tree_number, $existing_trees)) {
+ $tree_number++;
+ }
- return $tree_name . $tree_number;
- }
+ return $tree_name . $tree_number;
+ }
}