summaryrefslogtreecommitdiff
path: root/app/Http/Controllers/BranchesController.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Http/Controllers/BranchesController.php')
-rw-r--r--app/Http/Controllers/BranchesController.php532
1 files changed, 270 insertions, 262 deletions
diff --git a/app/Http/Controllers/BranchesController.php b/app/Http/Controllers/BranchesController.php
index df352e1372..cadc5cdfe9 100644
--- a/app/Http/Controllers/BranchesController.php
+++ b/app/Http/Controllers/BranchesController.php
@@ -31,83 +31,87 @@ use Symfony\Component\HttpFoundation\Response;
/**
* Find all branches of families with a given surname.
*/
-class BranchesController extends AbstractBaseController {
- /**
- * A form to request the page parameters.
- *
- * @param Request $request
- *
- * @return Response
- */
- public function page(Request $request): Response {
- $surname = $request->get('surname', '');
- $soundex_std = (bool) $request->get('soundex_std');
- $soundex_dm = (bool) $request->get('soundex_dm');
+class BranchesController extends AbstractBaseController
+{
+ /**
+ * A form to request the page parameters.
+ *
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function page(Request $request): Response
+ {
+ $surname = $request->get('surname', '');
+ $soundex_std = (bool)$request->get('soundex_std');
+ $soundex_dm = (bool)$request->get('soundex_dm');
- if ($surname !== '') {
- $title = /* I18N: %s is a surname */
- I18N::translate('Branches of the %s family', e($surname));
- } else {
- $title = /* I18N: Branches of a family tree */
- I18N::translate('Branches');
- }
+ if ($surname !== '') {
+ $title = /* I18N: %s is a surname */
+ I18N::translate('Branches of the %s family', e($surname));
+ } else {
+ $title = /* I18N: Branches of a family tree */
+ I18N::translate('Branches');
+ }
- return $this->viewResponse('branches-page', [
- 'soundex_dm' => $soundex_dm,
- 'soundex_std' => $soundex_std,
- 'surname' => $surname,
- 'title' => $title,
- ]);
- }
+ return $this->viewResponse('branches-page', [
+ 'soundex_dm' => $soundex_dm,
+ 'soundex_std' => $soundex_std,
+ 'surname' => $surname,
+ 'title' => $title,
+ ]);
+ }
- /**
- * @param Request $request
- *
- * @return Response
- */
- public function list(Request $request): Response {
- /** @var Tree $tree */
- $tree = $request->attributes->get('tree');
+ /**
+ * @param Request $request
+ *
+ * @return Response
+ */
+ public function list(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');
- $soundex_dm = (bool) $request->get('soundex_dm');
- $soundex_std = (bool) $request->get('soundex_std');
- $surname = $request->get('surname', '');
+ $soundex_dm = (bool)$request->get('soundex_dm');
+ $soundex_std = (bool)$request->get('soundex_std');
+ $surname = $request->get('surname', '');
- // Highlight direct-line ancestors of this individual.
- $self = Individual::getInstance($tree->getUserPreference($user, 'gedcomid'), $tree);
+ // Highlight direct-line ancestors of this individual.
+ $self = Individual::getInstance($tree->getUserPreference($user, 'gedcomid'), $tree);
- if ($surname !== '') {
- $individuals = $this->loadIndividuals($tree, $surname, $soundex_dm, $soundex_std);
- } else {
- $individuals = [];
- }
+ if ($surname !== '') {
+ $individuals = $this->loadIndividuals($tree, $surname, $soundex_dm, $soundex_std);
+ } else {
+ $individuals = [];
+ }
- if ($self !== null) {
- $ancestors = $this->allAncestors($self);
- } else {
- $ancestors = [];
- }
+ if ($self !== null) {
+ $ancestors = $this->allAncestors($self);
+ } else {
+ $ancestors = [];
+ }
- // @TODO - convert this to use views
- $html = view('branches-list', [
- 'branches' => $this->getPatriarchsHtml($individuals, $ancestors, $surname, $soundex_dm, $soundex_std),
- ]);
+ // @TODO - convert this to use views
+ $html = view('branches-list', [
+ 'branches' => $this->getPatriarchsHtml($individuals, $ancestors, $surname, $soundex_dm, $soundex_std),
+ ]);
- return new Response($html);
- }
+ return new Response($html);
+ }
- /**
- * Find all ancestors of an individual, indexed by the Sosa-Stradonitz number.
- *
- * @param Individual $individual
- *
- * @return Individual[]
- */
- protected function allAncestors(Individual $individual): array {
- /** @var Individual[] $ancestors */
+ /**
+ * Find all ancestors of an individual, indexed by the Sosa-Stradonitz number.
+ *
+ * @param Individual $individual
+ *
+ * @return Individual[]
+ */
+ protected function allAncestors(Individual $individual): array
+ {
+ /** @var Individual[] $ancestors */
$ancestors = [
1 => $individual,
];
@@ -115,9 +119,9 @@ class BranchesController extends AbstractBaseController {
do {
$sosa = key($ancestors);
- $family = $ancestors[$sosa]->getPrimaryChildFamily();
+ $family = $ancestors[$sosa]->getPrimaryChildFamily();
- if ($family !== null) {
+ if ($family !== null) {
if ($family->getHusband() !== null) {
$ancestors[$sosa * 2] = $family->getHusband();
}
@@ -125,219 +129,223 @@ class BranchesController extends AbstractBaseController {
$ancestors[$sosa * 2 + 1] = $family->getWife();
}
}
- } while (next($ancestors));
+ } while (next($ancestors));
- return $ancestors;
- }
+ return $ancestors;
+ }
- /**
- * Fetch all individuals with a matching surname
- *
- * @param Tree $tree
- * @param string $surname
- * @param bool $soundex_dm
- * @param bool $soundex_std
- *
- * @return Individual[]
- */
- private function loadIndividuals(Tree $tree, string $surname, bool $soundex_dm, bool $soundex_std): array {
- $sql =
- "SELECT DISTINCT i_id AS xref, i_gedcom AS gedcom" .
- " FROM `##individuals`" .
- " JOIN `##name` ON (i_id=n_id AND i_file=n_file)" .
- " WHERE n_file = ?" .
- " AND n_type != ?" .
- " AND (n_surn = ? OR n_surname = ?";
+ /**
+ * Fetch all individuals with a matching surname
+ *
+ * @param Tree $tree
+ * @param string $surname
+ * @param bool $soundex_dm
+ * @param bool $soundex_std
+ *
+ * @return Individual[]
+ */
+ private function loadIndividuals(Tree $tree, string $surname, bool $soundex_dm, bool $soundex_std): array
+ {
+ $sql =
+ "SELECT DISTINCT i_id AS xref, i_gedcom AS gedcom" .
+ " FROM `##individuals`" .
+ " JOIN `##name` ON (i_id=n_id AND i_file=n_file)" .
+ " WHERE n_file = ?" .
+ " AND n_type != ?" .
+ " AND (n_surn = ? OR n_surname = ?";
- $args = [
- $tree->getTreeId(),
- '_MARNM',
- $surname,
- $surname,
- ];
- if ($soundex_std) {
- $sdx = Soundex::russell($surname);
- if ($sdx !== '') {
- foreach (explode(':', $sdx) as $value) {
- $sql .= " OR n_soundex_surn_std LIKE CONCAT('%', ?, '%')";
- $args[] = $value;
- }
- }
- }
+ $args = [
+ $tree->getTreeId(),
+ '_MARNM',
+ $surname,
+ $surname,
+ ];
+ if ($soundex_std) {
+ $sdx = Soundex::russell($surname);
+ if ($sdx !== '') {
+ foreach (explode(':', $sdx) as $value) {
+ $sql .= " OR n_soundex_surn_std LIKE CONCAT('%', ?, '%')";
+ $args[] = $value;
+ }
+ }
+ }
- if ($soundex_dm) {
- $sdx = Soundex::daitchMokotoff($surname);
- if ($sdx !== '') {
- foreach (explode(':', $sdx) as $value) {
- $sql .= " OR n_soundex_surn_dm LIKE CONCAT('%', ?, '%')";
- $args[] = $value;
- }
- }
- }
- $sql .= ')';
+ if ($soundex_dm) {
+ $sdx = Soundex::daitchMokotoff($surname);
+ if ($sdx !== '') {
+ foreach (explode(':', $sdx) as $value) {
+ $sql .= " OR n_soundex_surn_dm LIKE CONCAT('%', ?, '%')";
+ $args[] = $value;
+ }
+ }
+ }
+ $sql .= ')';
- $rows = Database::prepare($sql)->execute($args)->fetchAll();
+ $rows = Database::prepare($sql)->execute($args)->fetchAll();
- $individuals = [];
- foreach ($rows as $row) {
- $individuals[] = Individual::getInstance($row->xref, $tree, $row->gedcom);
- }
+ $individuals = [];
+ foreach ($rows as $row) {
+ $individuals[] = Individual::getInstance($row->xref, $tree, $row->gedcom);
+ }
- usort($individuals, '\Fisharebest\Webtrees\Individual::compareBirthDate');
+ usort($individuals, '\Fisharebest\Webtrees\Individual::compareBirthDate');
- return $individuals;
- }
+ return $individuals;
+ }
- /**
- * For each individual with no ancestors, list their descendants.
- *
- * @param Individual[] $individuals
- * @param Individual[] $ancestors
- * @param string $surname
- * @param bool $soundex_dm
- * @param bool $soundex_std
- *
- * @return string
- */
- public function getPatriarchsHtml(array $individuals, array $ancestors, string $surname, bool $soundex_dm, bool $soundex_std): string {
- $html = '';
- foreach ($individuals as $individual) {
- foreach ($individual->getChildFamilies() as $family) {
- foreach ($family->getSpouses() as $parent) {
- if (in_array($parent, $individuals, true)) {
- continue 3;
- }
- }
- }
- $html .= $this->getDescendantsHtml($individuals, $ancestors, $surname, $soundex_dm, $soundex_std, $individual, null);
- }
+ /**
+ * For each individual with no ancestors, list their descendants.
+ *
+ * @param Individual[] $individuals
+ * @param Individual[] $ancestors
+ * @param string $surname
+ * @param bool $soundex_dm
+ * @param bool $soundex_std
+ *
+ * @return string
+ */
+ public function getPatriarchsHtml(array $individuals, array $ancestors, string $surname, bool $soundex_dm, bool $soundex_std): string
+ {
+ $html = '';
+ foreach ($individuals as $individual) {
+ foreach ($individual->getChildFamilies() as $family) {
+ foreach ($family->getSpouses() as $parent) {
+ if (in_array($parent, $individuals, true)) {
+ continue 3;
+ }
+ }
+ }
+ $html .= $this->getDescendantsHtml($individuals, $ancestors, $surname, $soundex_dm, $soundex_std, $individual, null);
+ }
- return $html;
- }
+ return $html;
+ }
- /**
- * Generate a recursive list of descendants of an individual.
- * If parents are specified, we can also show the pedigree (adopted, etc.).
- *
- * @param array $individuals
- * @param array $ancestors
- * @param string $surname
- * @param bool $soundex_dm
- * @param bool $soundex_std
- * @param Individual $individual
- * @param Family|null $parents
- *
- * @return string
- */
- private function getDescendantsHtml(array $individuals, array $ancestors, string $surname, bool $soundex_dm, bool $soundex_std, Individual $individual, Family $parents = null) {
- // A person has many names. Select the one that matches the searched surname
- $person_name = '';
- foreach ($individual->getAllNames() as $name) {
- list($surn1) = explode(',', $name['sort']);
- if (// one name is a substring of the other
- stripos($surn1, $surname) !== false ||
- stripos($surname, $surn1) !== false ||
- // one name sounds like the other
- $soundex_std && Soundex::compare(Soundex::russell($surn1), Soundex::russell($surname)) ||
- $soundex_dm && Soundex::compare(Soundex::daitchMokotoff($surn1), Soundex::daitchMokotoff($surname))
- ) {
- $person_name = $name['full'];
- break;
- }
- }
+ /**
+ * Generate a recursive list of descendants of an individual.
+ * If parents are specified, we can also show the pedigree (adopted, etc.).
+ *
+ * @param array $individuals
+ * @param array $ancestors
+ * @param string $surname
+ * @param bool $soundex_dm
+ * @param bool $soundex_std
+ * @param Individual $individual
+ * @param Family|null $parents
+ *
+ * @return string
+ */
+ private function getDescendantsHtml(array $individuals, array $ancestors, string $surname, bool $soundex_dm, bool $soundex_std, Individual $individual, Family $parents = null)
+ {
+ // A person has many names. Select the one that matches the searched surname
+ $person_name = '';
+ foreach ($individual->getAllNames() as $name) {
+ list($surn1) = explode(',', $name['sort']);
+ if (// one name is a substring of the other
+ stripos($surn1, $surname) !== false ||
+ stripos($surname, $surn1) !== false ||
+ // one name sounds like the other
+ $soundex_std && Soundex::compare(Soundex::russell($surn1), Soundex::russell($surname)) ||
+ $soundex_dm && Soundex::compare(Soundex::daitchMokotoff($surn1), Soundex::daitchMokotoff($surname))
+ ) {
+ $person_name = $name['full'];
+ break;
+ }
+ }
- // No matching name? Typically children with a different surname. The branch stops here.
- if (!$person_name) {
- return '<li title="' . strip_tags($individual->getFullName()) . '">' . $individual->getSexImage() . '…</li>';
- }
+ // No matching name? Typically children with a different surname. The branch stops here.
+ if (!$person_name) {
+ return '<li title="' . strip_tags($individual->getFullName()) . '">' . $individual->getSexImage() . '…</li>';
+ }
- // Is this individual one of our ancestors?
- $sosa = array_search($individual, $ancestors, true);
- if ($sosa !== false) {
- $sosa_class = 'search_hit';
- $sosa_html = ' <a class="details1 ' . $individual->getBoxStyle() . '" title="' . I18N::translate('Sosa') . '" href="' . e(route('relationships', [
- 'xref1' => $individual->getXref(),
- 'xref2' => $ancestors[1]->getXref(),
- 'ged' => $individual->getTree()->getName(),
- ])) . '" rel="nofollow">' . $sosa . '</a>' . self::sosaGeneration($sosa);
- } else {
- $sosa_class = '';
- $sosa_html = '';
- }
+ // Is this individual one of our ancestors?
+ $sosa = array_search($individual, $ancestors, true);
+ if ($sosa !== false) {
+ $sosa_class = 'search_hit';
+ $sosa_html = ' <a class="details1 ' . $individual->getBoxStyle() . '" title="' . I18N::translate('Sosa') . '" href="' . e(route('relationships', [
+ 'xref1' => $individual->getXref(),
+ 'xref2' => $ancestors[1]->getXref(),
+ 'ged' => $individual->getTree()->getName(),
+ ])) . '" rel="nofollow">' . $sosa . '</a>' . self::sosaGeneration($sosa);
+ } else {
+ $sosa_class = '';
+ $sosa_html = '';
+ }
- // Generate HTML for this individual, and all their descendants
- $indi_html = $individual->getSexImage() . '<a class="' . $sosa_class . '" href="' . e($individual->url()) . '">' . $person_name . '</a> ' . $individual->getLifeSpan() . $sosa_html;
+ // Generate HTML for this individual, and all their descendants
+ $indi_html = $individual->getSexImage() . '<a class="' . $sosa_class . '" href="' . e($individual->url()) . '">' . $person_name . '</a> ' . $individual->getLifeSpan() . $sosa_html;
- // If this is not a birth pedigree (e.g. an adoption), highlight it
- if ($parents) {
- $pedi = '';
- foreach ($individual->getFacts('FAMC') as $fact) {
- if ($fact->getTarget() === $parents) {
- $pedi = $fact->getAttribute('PEDI');
- break;
- }
- }
- if ($pedi !== '' && $pedi !== 'birth') {
- $indi_html = '<span class="red">' . GedcomCodePedi::getValue($pedi, $individual) . '</span> ' . $indi_html;
- }
- }
+ // If this is not a birth pedigree (e.g. an adoption), highlight it
+ if ($parents) {
+ $pedi = '';
+ foreach ($individual->getFacts('FAMC') as $fact) {
+ if ($fact->getTarget() === $parents) {
+ $pedi = $fact->getAttribute('PEDI');
+ break;
+ }
+ }
+ if ($pedi !== '' && $pedi !== 'birth') {
+ $indi_html = '<span class="red">' . GedcomCodePedi::getValue($pedi, $individual) . '</span> ' . $indi_html;
+ }
+ }
- // spouses and children
- $spouse_families = $individual->getSpouseFamilies();
- if ($spouse_families) {
- usort($spouse_families, '\Fisharebest\Webtrees\Family::compareMarrDate');
- $fam_html = '';
- foreach ($spouse_families as $family) {
- $fam_html .= $indi_html; // Repeat the individual details for each spouse.
+ // spouses and children
+ $spouse_families = $individual->getSpouseFamilies();
+ if ($spouse_families) {
+ usort($spouse_families, '\Fisharebest\Webtrees\Family::compareMarrDate');
+ $fam_html = '';
+ foreach ($spouse_families as $family) {
+ $fam_html .= $indi_html; // Repeat the individual details for each spouse.
- $spouse = $family->getSpouse($individual);
- if ($spouse) {
- $sosa = array_search($spouse, $ancestors, true);
- if ($sosa) {
- $sosa_class = 'search_hit';
- $sosa_html = ' <a class="details1 ' . $spouse->getBoxStyle() . '" title="' . I18N::translate('Sosa') . '" href="' . e(route('relationships', [
- 'xref2' => $ancestors[1]->getXref(),
- 'ged' => $individual->getTree()->getName(),
- ])) . '" rel="nofollow"> ' . $sosa . ' </a>' . self::sosaGeneration($sosa);
- } else {
- $sosa_class = '';
- $sosa_html = '';
- }
- $marriage_year = $family->getMarriageYear();
- if ($marriage_year) {
- $fam_html .= ' <a href="' . e($family->url()) . '" title="' . strip_tags($family->getMarriageDate()->display()) . '"><i class="icon-rings"></i>' . $marriage_year . '</a>';
- } elseif ($family->getFirstFact('MARR')) {
- $fam_html .= ' <a href="' . e($family->url()) . '" title="' . I18N::translate('Marriage') . '"><i class="icon-rings"></i></a>';
- } else {
- $fam_html .= ' <a href="' . e($family->url()) . '" title="' . I18N::translate('Not married') . '"><i class="icon-rings"></i></a>';
- }
- $fam_html .= ' ' . $spouse->getSexImage() . '<a class="' . $sosa_class . '" href="' . e($spouse->url()) . '">' . $spouse->getFullName() . '</a> ' . $spouse->getLifeSpan() . ' ' . $sosa_html;
- }
+ $spouse = $family->getSpouse($individual);
+ if ($spouse) {
+ $sosa = array_search($spouse, $ancestors, true);
+ if ($sosa) {
+ $sosa_class = 'search_hit';
+ $sosa_html = ' <a class="details1 ' . $spouse->getBoxStyle() . '" title="' . I18N::translate('Sosa') . '" href="' . e(route('relationships', [
+ 'xref2' => $ancestors[1]->getXref(),
+ 'ged' => $individual->getTree()->getName(),
+ ])) . '" rel="nofollow"> ' . $sosa . ' </a>' . self::sosaGeneration($sosa);
+ } else {
+ $sosa_class = '';
+ $sosa_html = '';
+ }
+ $marriage_year = $family->getMarriageYear();
+ if ($marriage_year) {
+ $fam_html .= ' <a href="' . e($family->url()) . '" title="' . strip_tags($family->getMarriageDate()->display()) . '"><i class="icon-rings"></i>' . $marriage_year . '</a>';
+ } elseif ($family->getFirstFact('MARR')) {
+ $fam_html .= ' <a href="' . e($family->url()) . '" title="' . I18N::translate('Marriage') . '"><i class="icon-rings"></i></a>';
+ } else {
+ $fam_html .= ' <a href="' . e($family->url()) . '" title="' . I18N::translate('Not married') . '"><i class="icon-rings"></i></a>';
+ }
+ $fam_html .= ' ' . $spouse->getSexImage() . '<a class="' . $sosa_class . '" href="' . e($spouse->url()) . '">' . $spouse->getFullName() . '</a> ' . $spouse->getLifeSpan() . ' ' . $sosa_html;
+ }
- $fam_html .= '<ol>';
- foreach ($family->getChildren() as $child) {
- $fam_html .= $this->getDescendantsHtml($individuals, $ancestors, $surname, $soundex_dm, $soundex_std, $child, $family);
- }
- $fam_html .= '</ol>';
- }
+ $fam_html .= '<ol>';
+ foreach ($family->getChildren() as $child) {
+ $fam_html .= $this->getDescendantsHtml($individuals, $ancestors, $surname, $soundex_dm, $soundex_std, $child, $family);
+ }
+ $fam_html .= '</ol>';
+ }
- return '<li>' . $fam_html . '</li>';
- } else {
- // No spouses - just show the individual
- return '<li>' . $indi_html . '</li>';
- }
- }
+ return '<li>' . $fam_html . '</li>';
+ } else {
+ // No spouses - just show the individual
+ return '<li>' . $indi_html . '</li>';
+ }
+ }
- /**
- * Convert a SOSA number into a generation number. e.g. 8 = great-grandfather = 3 generations
- *
- * @param int $sosa
- *
- * @return string
- */
- private static function sosaGeneration($sosa) {
- $generation = (int) log($sosa, 2) + 1;
+ /**
+ * Convert a SOSA number into a generation number. e.g. 8 = great-grandfather = 3 generations
+ *
+ * @param int $sosa
+ *
+ * @return string
+ */
+ private static function sosaGeneration($sosa)
+ {
+ $generation = (int)log($sosa, 2) + 1;
- return '<sup title="' . I18N::translate('Generation') . '">' . $generation . '</sup>';
- }
+ return '<sup title="' . I18N::translate('Generation') . '">' . $generation . '</sup>';
+ }
}