1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/webtrees_ynh.git synced 2024-09-03 18:26:37 +02:00
webtrees_ynh/sources/app/Controller/IndividualController.php

421 lines
13 KiB
PHP

<?php
/**
* webtrees: online genealogy
* Copyright (C) 2016 webtrees development team
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Fisharebest\Webtrees\Controller;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Database;
use Fisharebest\Webtrees\Fact;
use Fisharebest\Webtrees\Family;
use Fisharebest\Webtrees\Filter;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
use Fisharebest\Webtrees\Functions\FunctionsPrintFacts;
use Fisharebest\Webtrees\GedcomCode\GedcomCodeName;
use Fisharebest\Webtrees\GedcomTag;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Menu;
use Fisharebest\Webtrees\Module;
use Fisharebest\Webtrees\User;
/**
* Controller for the individual page
*/
class IndividualController extends GedcomRecordController {
/** @var int Count of names */
public $name_count = 0;
/** @var int Count of names. */
public $total_names = 0;
/** ModuleTabInterface[] List of tabs to show */
public $tabs;
/**
* Startup activity
*
* @param Individual|null $record
*/
public function __construct($record) {
parent::__construct($record);
// If we can display the details, add them to the page header
if ($this->record && $this->record->canShow()) {
$this->setPageTitle($this->record->getFullName() . ' ' . $this->record->getLifeSpan());
$this->tabs = Module::getActiveTabs($this->record->getTree());
}
}
/**
* Get significant information from this page, to allow other pages such as
* charts and reports to initialise with the same records
*
* @return Individual
*/
public function getSignificantIndividual() {
if ($this->record) {
return $this->record;
}
return parent::getSignificantIndividual();
}
/**
* Get significant information from this page, to allow other pages such as
* charts and reports to initialise with the same records
*
* @return Family
*/
public function getSignificantFamily() {
if ($this->record) {
foreach ($this->record->getChildFamilies() as $family) {
return $family;
}
foreach ($this->record->getSpouseFamilies() as $family) {
return $family;
}
}
return parent::getSignificantFamily();
}
/**
* Handle AJAX requests - to generate the tab content
*/
public function ajaxRequest() {
// Search engines should not make AJAX requests
if (Auth::isSearchEngine()) {
http_response_code(403);
exit;
}
// Initialise tabs
$tab = Filter::get('module');
// A request for a non-existant tab?
if (array_key_exists($tab, $this->tabs)) {
$mod = $this->tabs[$tab];
} else {
http_response_code(404);
exit;
}
header("Content-Type: text/html; charset=UTF-8"); // AJAX calls do not have the meta tag headers and need this set
header("X-Robots-Tag: noindex,follow"); // AJAX pages should not show up in search results, any links can be followed though
echo $mod->getTabContent();
if (WT_DEBUG_SQL) {
echo Database::getQueryLog();
}
}
/**
* print information for a name record
*
* @param Fact $event the event object
*/
public function printNameRecord(Fact $event) {
$factrec = $event->getGedcom();
// Create a dummy record, so we can extract the formatted NAME value from the event.
$dummy = new Individual(
'xref',
"0 @xref@ INDI\n1 DEAT Y\n" . $factrec,
null,
$event->getParent()->getTree()
);
$all_names = $dummy->getAllNames();
$primary_name = $all_names[0];
$this->name_count++;
if ($this->name_count > 1) { echo '<h3 class="name_two">', $dummy->getFullName(), '</h3>'; } // Other names accordion element
echo '<div class="indi_name_details';
if ($event->isPendingDeletion()) {
echo ' old';
}
if ($event->isPendingAddition()) {
echo ' new';
}
echo '">';
echo '<div class="name1">';
echo '<dl><dt class="label">', I18N::translate('Name'), '</dt>';
$dummy->setPrimaryName(0);
echo '<dd class="field">', $dummy->getFullName();
if ($this->name_count == 1) {
if (Auth::isAdmin()) {
$user = User::findByGenealogyRecord($this->record);
if ($user) {
echo '<span> - <a class="warning" href="admin_users.php?filter=' . Filter::escapeHtml($user->getUserName()) . '">' . Filter::escapeHtml($user->getUserName()) . '</a></span>';
}
}
}
if ($this->record->canEdit() && !$event->isPendingDeletion()) {
echo "<div class=\"deletelink noprint\"><a class=\"deleteicon\" href=\"#\" onclick=\"return delete_fact('" . I18N::translate('Are you sure you want to delete this fact?') . "', '" . $this->record->getXref() . "', '" . $event->getFactId() . "');\" title=\"" . I18N::translate('Delete this name') . "\"><span class=\"link_text\">" . I18N::translate('Delete this name') . "</span></a></div>";
echo "<div class=\"editlink noprint\"><a href=\"#\" class=\"editicon\" onclick=\"edit_name('" . $this->record->getXref() . "', '" . $event->getFactId() . "'); return false;\" title=\"" . I18N::translate('Edit the name') . "\"><span class=\"link_text\">" . I18N::translate('Edit the name') . "</span></a></div>";
}
echo '</dd>';
echo '</dl>';
echo '</div>';
$ct = preg_match_all('/\n2 (\w+) (.*)/', $factrec, $nmatch, PREG_SET_ORDER);
for ($i = 0; $i < $ct; $i++) {
echo '<div>';
$fact = $nmatch[$i][1];
if ($fact != 'SOUR' && $fact != 'NOTE' && $fact != 'SPFX') {
echo '<dl><dt class="label">', GedcomTag::getLabel($fact, $this->record), '</dt>';
echo '<dd class="field">'; // Before using dir="auto" on this field, note that Gecko treats this as an inline element but WebKit treats it as a block element
if (isset($nmatch[$i][2])) {
$name = Filter::escapeHtml($nmatch[$i][2]);
$name = str_replace('/', '', $name);
$name = preg_replace('/(\S*)\*/', '<span class="starredname">\\1</span>', $name);
switch ($fact) {
case 'TYPE':
echo GedcomCodeName::getValue($name, $this->record);
break;
case 'SURN':
// The SURN field is not necessarily the surname.
// Where it is not a substring of the real surname, show it after the real surname.
$surname = Filter::escapeHtml($primary_name['surname']);
if (strpos($primary_name['surname'], str_replace(',', ' ', $nmatch[$i][2])) !== false) {
echo '<span dir="auto">' . $surname . '</span>';
} else {
echo I18N::translate('%1$s (%2$s)', '<span dir="auto">' . $surname . '</span>', '<span dir="auto">' . $name . '</span>');
}
break;
default:
echo '<span dir="auto">' . $name . '</span>';
break;
}
}
echo '</dd>';
echo '</dl>';
}
echo '</div>';
}
if (preg_match("/\n2 SOUR/", $factrec)) {
echo '<div id="indi_sour" class="clearfloat">', FunctionsPrintFacts::printFactSources($factrec, 2), '</div>';
}
if (preg_match("/\n2 NOTE/", $factrec)) {
echo '<div id="indi_note" class="clearfloat">', FunctionsPrint::printFactNotes($factrec, 2), '</div>';
}
echo '</div>';
}
/**
* print information for a sex record
*
* @param Fact $event the Event object
*/
public function printSexRecord(Fact $event) {
$sex = $event->getValue();
if (empty($sex)) {
$sex = 'U';
}
echo '<span id="sex" class="';
if ($event->isPendingDeletion()) {
echo 'old ';
}
if ($event->isPendingAddition()) {
echo 'new ';
}
switch ($sex) {
case 'M':
echo 'male_gender"';
if ($event->canEdit()) {
echo ' title="', I18N::translate('Male'), ' - ', I18N::translate('Edit'), '"';
echo ' onclick="edit_record(\'' . $this->record->getXref() . '\', \'' . $event->getFactId() . '\'); return false;">';
} else {
echo ' title="', I18N::translate('Male'), '">';
}
break;
case 'F':
echo 'female_gender"';
if ($event->canEdit()) {
echo ' title="', I18N::translate('Female'), ' - ', I18N::translate('Edit'), '"';
echo ' onclick="edit_record(\'' . $this->record->getXref() . '\', \'' . $event->getFactId() . '\'); return false;">';
} else {
echo ' title="', I18N::translate('Female'), '">';
}
break;
default:
echo 'unknown_gender"';
if ($event->canEdit()) {
echo ' title="', I18N::translateContext('unknown gender', 'Unknown'), ' - ', I18N::translate('Edit'), '"';
echo ' onclick="edit_record(\'' . $this->record->getXref() . '\', \'' . $event->getFactId() . '\'); return false;">';
} else {
echo ' title="', I18N::translateContext('unknown gender', 'Unknown'), '">';
}
break;
}
echo '</span>';
}
/**
* get edit menu
*/
public function getEditMenu() {
if (!$this->record || $this->record->isPendingDeletion()) {
return null;
}
// edit menu
$menu = new Menu(I18N::translate('Edit'), '#', 'menu-indi');
if (Auth::isEditor($this->record->getTree())) {
$menu->addSubmenu(new Menu(I18N::translate('Add a name'), '#', 'menu-indi-addname', array(
'onclick' => 'return add_name("' . $this->record->getXref() . '");',
)));
$has_sex_record = false;
foreach ($this->record->getFacts() as $fact) {
if ($fact->getTag() === 'SEX' && $fact->canEdit()) {
$menu->addSubmenu(new Menu(I18N::translate('Edit the gender'), '#', 'menu-indi-editsex', array(
'onclick' => 'return edit_record("' . $this->record->getXref() . '", "' . $fact->getFactId() . '");',
)));
$has_sex_record = true;
break;
}
}
if (!$has_sex_record) {
$menu->addSubmenu(new Menu(I18N::translate('Edit the gender'), '#', 'menu-indi-editsex', array(
'onclick' => 'return add_new_record("' . $this->record->getXref() . '", "SEX");',
)));
}
if (count($this->record->getSpouseFamilies()) > 1) {
$menu->addSubmenu(new Menu(I18N::translate('Re-order families'), '#', 'menu-indi-orderfam', array(
'onclick' => 'return reorder_families("' . $this->record->getXref() . '");',
)));
}
// delete
$menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-indi-del', array(
'onclick' => 'return delete_record("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");',
)));
}
// edit raw
if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
$menu->addSubmenu(new Menu(I18N::translate('Edit the raw GEDCOM'), '#', 'menu-indi-editraw', array(
'onclick' => 'return edit_raw("' . $this->record->getXref() . '");',
)));
}
return $menu;
}
/**
* get the person box stylesheet class for the given person
*
* @param Individual $person
*
* @return string returns 'person_box', 'person_boxF', or 'person_boxNN'
*/
public function getPersonStyle($person) {
switch ($person->getSex()) {
case 'M':
$class = 'person_box';
break;
case 'F':
$class = 'person_boxF';
break;
default:
$class = 'person_boxNN';
break;
}
if ($person->isPendingDeletion()) {
$class .= ' old';
} elseif ($person->isPendingAddtion()) {
$class .= ' new';
}
return $class;
}
/**
* Get significant information from this page, to allow other pages such as
* charts and reports to initialise with the same records
*
* @return string
*/
public function getSignificantSurname() {
if ($this->record) {
list($surn) = explode(',', $this->record->getSortName());
return $surn;
} else {
return '';
}
}
/**
* Get the contents of sidebar.
*
* @return string
*/
public function getSideBarContent() {
global $controller;
$html = '';
$active = 0;
$n = 0;
foreach (Module::getActiveSidebars($this->record->getTree()) as $mod) {
if ($mod->hasSidebarContent()) {
$html .= '<h3 id="' . $mod->getName() . '"><a href="#">' . $mod->getTitle() . '</a></h3>';
$html .= '<div id="sb_content_' . $mod->getName() . '">' . $mod->getSidebarContent() . '</div>';
// The family navigator should be opened by default
if ($mod->getName() == 'family_nav') {
$active = $n;
}
++$n;
}
}
if ($html) {
$controller
->addInlineJavascript('
jQuery("#sidebarAccordion").accordion({
active:' . $active . ',
heightStyle: "content",
collapsible: true,
});
');
return '<div id="sidebar"><div id="sidebarAccordion">' . $html . '</div></div>';
} else {
return '';
}
}
/**
* Get the description for the family.
*
* For example, "XXX's family with new wife".
*
* @param Family $family
* @param Individual $individual
*
* @return string
*/
public function getSpouseFamilyLabel(Family $family, Individual $individual) {
$spouse = $family->getSpouse($individual);
if ($spouse) {
return
/* I18N: %s is the spouse name */
I18N::translate('Family with %s', $spouse->getFullName());
} else {
return $family->getFullName();
}
}
}