/**
* Print a form to add an individual or edit an individual’s name
*
* @param string $nextaction
* @param Individual $person
* @param Family $family
* @param Fact $name_fact
* @param string $famtag
* @param string $gender
*/
function print_indi_form($nextaction, Individual $person = null, Family $family = null, Fact $name_fact = null, $famtag = 'CHIL', $gender = 'U')
{
global $WT_TREE, $bdm, $controller;
if ($person) {
$xref = $person->getXref();
} elseif ($family) {
$xref = $family->getXref();
} else {
$xref = 'new';
}
// Different cultures do surnames differently
$surname_tradition = SurnameTradition::create($WT_TREE->getPreference('SURNAME_TRADITION'));
$name_fields = array();
if ($name_fact) {
// Editing an existing name
$name_fact_id = $name_fact->getFactId();
$name_type = $name_fact->getAttribute('TYPE');
$namerec = $name_fact->getGedcom();
foreach (Config::standardNameFacts() as $tag) {
if ($tag === 'NAME') {
$name_fields[$tag] = $name_fact->getValue();
} else {
$name_fields[$tag] = $name_fact->getAttribute($tag);
}
}
// Populate any missing 2 XXXX fields from the 1 NAME field
$npfx_accept = implode('|', Config::namePrefixes());
if (preg_match('/(((' . $npfx_accept . ')\\.? +)*)([^\\n\\/"]*)("(.*)")? *\\/(([a-z]{2,3} +)*)(.*)\\/ *(.*)/i', $name_fields['NAME'], $name_bits)) {
if (empty($name_fields['NPFX'])) {
$name_fields['NPFX'] = $name_bits[1];
}
if (empty($name_fields['SPFX']) && empty($name_fields['SURN'])) {
$name_fields['SPFX'] = trim($name_bits[7]);
// For names with two surnames, there will be four slashes.
// Turn them into a list
$name_fields['SURN'] = preg_replace('~/[^/]*/~', ',', $name_bits[9]);
}
if (empty($name_fields['GIVN'])) {
$name_fields['GIVN'] = $name_bits[4];
}
if (empty($name_fields['NICK']) && !empty($name_bits[6]) && !preg_match('/^2 NICK/m', $namerec)) {
$name_fields['NICK'] = $name_bits[6];
}
}
} else {
// Creating a new name
$name_fact_id = null;
$name_type = null;
$namerec = null;
// Populate the standard NAME field and subfields
foreach (Config::standardNameFacts() as $tag) {
$name_fields[$tag] = '';
}
// Inherit surname from parents, spouse or child
if ($family) {
$father = $family->getHusband();
if ($father && $father->getFirstFact('NAME')) {
$father_name = $father->getFirstFact('NAME')->getValue();
} else {
$father_name = '';
}
$mother = $family->getWife();
if ($mother && $mother->getFirstFact('NAME')) {
$mother_name = $mother->getFirstFact('NAME')->getValue();
} else {
$mother_name = '';
}
} else {
$father = null;
$mother = null;
$father_name = '';
$mother_name = '';
}
if ($person && $person->getFirstFact('NAME')) {
$indi_name = $person->getFirstFact('NAME')->getValue();
} else {
$indi_name = '';
}
switch ($nextaction) {
case 'add_child_to_family_action':
$name_fields = $surname_tradition->newChildNames($father_name, $mother_name, $gender) + $name_fields;
break;
case 'add_child_to_individual_action':
if ($person->getSex() === 'F') {
$name_fields = $surname_tradition->newChildNames('', $indi_name, $gender) + $name_fields;
} else {
$name_fields = $surname_tradition->newChildNames($indi_name, '', $gender) + $name_fields;
}
break;
case 'add_parent_to_individual_action':
$name_fields = $surname_tradition->newParentNames($indi_name, $gender) + $name_fields;
break;
case 'add_spouse_to_family_action':
if ($father) {
$name_fields = $surname_tradition->newSpouseNames($father_name, $gender) + $name_fields;
} else {
$name_fields = $surname_tradition->newSpouseNames($mother_name, $gender) + $name_fields;
}
break;
case 'add_spouse_to_individual_action':
$name_fields = $surname_tradition->newSpouseNames($indi_name, $gender) + $name_fields;
break;
case 'add_unlinked_indi_action':
case 'update':
if ($surname_tradition->hasSurnames()) {
$name_fields['NAME'] = '//';
}
break;
}
}
$bdm = '';
// used to copy '1 SOUR' to '2 SOUR' for BIRT DEAT MARR
echo '<div id="edit_interface-page">';
echo '<h4>', $controller->getPageTitle(), '</h4>';
FunctionsPrint::initializeCalendarPopup();
echo '<form method="post" name="addchildform" onsubmit="return checkform();">';
echo '<input type="hidden" name="ged" value="', $WT_TREE->getNameHtml(), '">';
echo '<input type="hidden" name="action" value="', $nextaction, '">';
echo '<input type="hidden" name="fact_id" value="', $name_fact_id, '">';
echo '<input type="hidden" name="xref" value="', $xref, '">';
echo '<input type="hidden" name="famtag" value="', $famtag, '">';
echo '<input type="hidden" name="gender" value="', $gender, '">';
echo '<input type="hidden" name="goto" value="">';
// set by javascript
echo Filter::getCsrf();
echo '<table class="facts_table">';
switch ($nextaction) {
case 'add_child_to_family_action':
case 'add_child_to_individual_action':
// When adding a new child, specify the pedigree
FunctionsEdit::addSimpleTag('0 PEDI');
break;
case 'update':
// When adding/editing a name, specify the type
FunctionsEdit::addSimpleTag('0 TYPE ' . $name_type, '', '', null, $person);
break;
}
// First - new/existing standard name fields
foreach ($name_fields as $tag => $value) {
if (substr_compare($tag, '_', 0, 1) !== 0) {
FunctionsEdit::addSimpleTag('0 ' . $tag . ' ' . $value);
}
}
// Second - new/existing advanced name fields
if ($surname_tradition->hasMarriedNames() || preg_match('/\\n2 _MARNM /', $namerec)) {
$adv_name_fields = array('_MARNM' => '');
} else {
$adv_name_fields = array();
}
if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('ADVANCED_NAME_FACTS'), $match)) {
foreach ($match[1] as $tag) {
$adv_name_fields[$tag] = '';
}
}
foreach (array_keys($adv_name_fields) as $tag) {
// Edit existing tags, grouped together
if (preg_match_all('/2 ' . $tag . ' (.+)/', $namerec, $match)) {
foreach ($match[1] as $value) {
FunctionsEdit::addSimpleTag('2 ' . $tag . ' ' . $value, '', GedcomTag::getLabel('NAME:' . $tag, $person));
if ($tag === '_MARNM') {
preg_match_all('/\\/([^\\/]*)\\//', $value, $matches);
FunctionsEdit::addSimpleTag('2 _MARNM_SURN ' . implode(',', $matches[1]));
}
}
}
// Allow a new tag to be entered
if (!array_key_exists($tag, $name_fields)) {
FunctionsEdit::addSimpleTag('0 ' . $tag, '', GedcomTag::getLabel('NAME:' . $tag, $person));
if ($tag === '_MARNM') {
FunctionsEdit::addSimpleTag('0 _MARNM_SURN');
}
}
}
// Third - new/existing custom name fields
foreach ($name_fields as $tag => $value) {
if (substr_compare($tag, '_', 0, 1) === 0) {
FunctionsEdit::addSimpleTag('0 ' . $tag . ' ' . $value);
if ($tag === '_MARNM') {
preg_match_all('/\\/([^\\/]*)\\//', $value, $matches);
FunctionsEdit::addSimpleTag('2 _MARNM_SURN ' . implode(',', $matches[1]));
}
}
}
// Fourth - SOUR, NOTE, _CUSTOM, etc.
if ($namerec) {
$gedlines = explode("\n", $namerec);
// -- find the number of lines in the record
$fields = explode(' ', $gedlines[0]);
$glevel = $fields[0];
$level = $glevel;
$type = trim($fields[1]);
$tags = array();
$i = 0;
do {
if ($type !== 'TYPE' && !array_key_exists($type, $name_fields) && !array_key_exists($type, $adv_name_fields)) {
$text = '';
for ($j = 2; $j < count($fields); $j++) {
if ($j > 2) {
$text .= ' ';
}
$text .= $fields[$j];
}
while ($i + 1 < count($gedlines) && preg_match('/' . ($level + 1) . ' CONT ?(.*)/', $gedlines[$i + 1], $cmatch) > 0) {
$text .= "\n" . $cmatch[2];
$i++;
}
FunctionsEdit::addSimpleTag($level . ' ' . $type . ' ' . $text);
}
$tags[] = $type;
$i++;
if (isset($gedlines[$i])) {
$fields = explode(' ', $gedlines[$i]);
$level = $fields[0];
if (isset($fields[1])) {
$type = $fields[1];
}
}
} while ($level > $glevel && $i < count($gedlines));
}
// If we are adding a new individual, add the basic details
if ($nextaction !== 'update') {
echo '</table><br><table class="facts_table">';
// 1 SEX
if ($famtag === 'HUSB' || $gender === 'M') {
FunctionsEdit::addSimpleTag("0 SEX M");
} elseif ($famtag === 'WIFE' || $gender === 'F') {
FunctionsEdit::addSimpleTag('0 SEX F');
} else {
FunctionsEdit::addSimpleTag('0 SEX');
}
$bdm = 'BD';
if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
foreach ($matches[1] as $match) {
if (!in_array($match, explode('|', WT_EVENTS_DEAT))) {
FunctionsEdit::addSimpleTags($match);
}
}
}
//-- if adding a spouse add the option to add a marriage fact to the new family
if ($nextaction === 'add_spouse_to_individual_action' || $nextaction === 'add_spouse_to_family_action') {
$bdm .= 'M';
if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FAMFACTS'), $matches)) {
foreach ($matches[1] as $match) {
FunctionsEdit::addSimpleTags($match);
}
}
}
if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
foreach ($matches[1] as $match) {
if (in_array($match, explode('|', WT_EVENTS_DEAT))) {
FunctionsEdit::addSimpleTags($match);
}
}
}
}
echo keep_chan($person);
echo '</table>';
if ($nextaction === 'update') {
// GEDCOM 5.5.1 spec says NAME doesn’t get a OBJE
FunctionsEdit::printAddLayer('SOUR');
FunctionsEdit::printAddLayer('NOTE');
FunctionsEdit::printAddLayer('SHARED_NOTE');
FunctionsEdit::printAddLayer('RESN');
} else {
FunctionsEdit::printAddLayer('SOUR', 1);
FunctionsEdit::printAddLayer('NOTE', 1);
FunctionsEdit::printAddLayer('SHARED_NOTE', 1);
FunctionsEdit::printAddLayer('RESN', 1);
}
// If we are editing an existing name, allow raw GEDCOM editing
if ($name_fact && (Auth::isAdmin() || $WT_TREE->getPreference('SHOW_GEDCOM_RECORD'))) {
echo '<br><br><a href="edit_interface.php?action=editrawfact&xref=', $xref, '&fact_id=', $name_fact->getFactId(), '&ged=', $WT_TREE->getNameUrl(), '">', I18N::translate('Edit raw GEDCOM'), '</a>';
}
echo '<p id="save-cancel">';
echo '<input type="submit" class="save" value="', I18N::translate('save'), '">';
if (preg_match('/^add_(child|spouse|parent|unlinked_indi)/', $nextaction)) {
echo '<input type="submit" class="save" value="', I18N::translate('go to new individual'), '" onclick="document.addchildform.goto.value=\'new\';">';
}
echo '<input type="button" class="cancel" value="', I18N::translate('close'), '" onclick="window.close();">';
echo '</p>';
echo '</form>';
$controller->addInlineJavascript('
SURNAME_TRADITION="' . $WT_TREE->getPreference('SURNAME_TRADITION') . '";
gender="' . $gender . '";
famtag="' . $famtag . '";
function trim(str) {
str=str.replace(/\\s\\s+/g, " ");
return str.replace(/(^\\s+)|(\\s+$)/g, "");
}
function lang_class(str) {
if (str.match(/[\\u0370-\\u03FF]/)) return "greek";
if (str.match(/[\\u0400-\\u04FF]/)) return "cyrillic";
if (str.match(/[\\u0590-\\u05FF]/)) return "hebrew";
if (str.match(/[\\u0600-\\u06FF]/)) return "arabic";
return "latin"; // No matched text implies latin :-)
}
// Generate a full name from the name components
function generate_name() {
var npfx = jQuery("#NPFX").val();
var givn = jQuery("#GIVN").val();
var spfx = jQuery("#SPFX").val();
var surn = jQuery("#SURN").val();
var nsfx = jQuery("#NSFX").val();
if (SURNAME_TRADITION === "polish" && (gender === "F" || famtag === "WIFE")) {
surn = surn.replace(/ski$/, "ska");
surn = surn.replace(/cki$/, "cka");
surn = surn.replace(/dzki$/, "dzka");
surn = surn.replace(/żki$/, "żka");
}
// Commas are used in the GIVN and SURN field to separate lists of surnames.
// For example, to differentiate the two Spanish surnames from an English
// double-barred name.
// Commas *may* be used in other fields, and will form part of the NAME.
if (WT_LOCALE=="vi" || WT_LOCALE=="hu") {
// Default format: /SURN/ GIVN
return trim(npfx+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/ "+givn.replace(/ *, */g, " ")+" "+nsfx);
} else if (WT_LOCALE=="zh") {
// Default format: /SURN/GIVN
return trim(npfx+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/"+givn.replace(/ *, */g, " ")+" "+nsfx);
} else {
// Default format: GIVN /SURN/
return trim(npfx+" "+givn.replace(/ *, */g, " ")+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/ "+nsfx);
}
}
// Update the NAME and _MARNM fields from the name components
// and also display the value in read-only "gedcom" format.
function updatewholename() {
// Don’t update the name if the user manually changed it
if (manualChange) {
return;
}
var npfx = jQuery("#NPFX").val();
var givn = jQuery("#GIVN").val();
var spfx = jQuery("#SPFX").val();
var surn = jQuery("#SURN").val();
var nsfx = jQuery("#NSFX").val();
var name = generate_name();
jQuery("#NAME").val(name);
jQuery("#NAME_display").text(name);
// Married names inherit some NSFX values, but not these
nsfx = nsfx.replace(/^(I|II|III|IV|V|VI|Junior|Jr\\.?|Senior|Sr\\.?)$/i, "");
// Update _MARNM field from _MARNM_SURN field and display it
// Be careful of mixing latin/hebrew/etc. character sets.
var ip = document.getElementsByTagName("input");
var marnm_id = "";
var romn = "";
var heb = "";
for (var i = 0; i < ip.length; i++) {
var val = trim(ip[i].value);
if (ip[i].id.indexOf("_HEB") === 0)
heb = val;
if (ip[i].id.indexOf("ROMN") === 0)
romn = val;
if (ip[i].id.indexOf("_MARNM") === 0) {
if (ip[i].id.indexOf("_MARNM_SURN") === 0) {
var msurn = "";
if (val !== "") {
var lc = lang_class(document.getElementById(ip[i].id).value);
if (lang_class(name) === lc)
msurn = trim(npfx + " " + givn + " /" + val + "/ " + nsfx);
else if (lc === "hebrew")
msurn = heb.replace(/\\/.*\\//, "/" + val + "/");
else if (lang_class(romn) === lc)
msurn = romn.replace(/\\/.*\\//, "/" + val + "/");
}
document.getElementById(marnm_id).value = msurn;
document.getElementById(marnm_id+"_display").innerHTML = msurn;
} else {
marnm_id = ip[i].id;
}
}
}
}
// Toggle the name editor fields between
// <input type="hidden"> <span style="display:inline">
// <input type="text"> <span style="display:hidden">
var oldName = "";
// Calls to generate_name() trigger an update - hence need to
// set the manual change to true first. We are probably
// listening to the wrong events on the input fields...
var manualChange = true;
manualChange = generate_name() !== jQuery("#NAME").val();
function convertHidden(eid) {
var input1 = jQuery("#" + eid);
var input2 = jQuery("#" + eid + "_display");
// Note that IE does not allow us to change the type of an input, so we must create a new one.
if (input1.attr("type")=="hidden") {
input1.replaceWith(input1.clone().attr("type", "text"));
input2.hide();
} else {
input1.replaceWith(input1.clone().attr("type", "hidden"));
input2.show();
}
}
/**
* if the user manually changed the NAME field, then update the textual
* HTML representation of it
* If the value changed set manualChange to true so that changing
* the other fields doesn’t change the NAME line
*/
function updateTextName(eid) {
var element = document.getElementById(eid);
if (element) {
if (element.value!=oldName) manualChange = true;
var delement = document.getElementById(eid+"_display");
if (delement) {
delement.innerHTML = element.value;
}
}
}
function checkform() {
var ip=document.getElementsByTagName("input");
for (var i=0; i<ip.length; i++) {
// ADD slashes to _HEB and _AKA names
if (ip[i].id.indexOf("_AKA")==0 || ip[i].id.indexOf("_HEB")==0 || ip[i].id.indexOf("ROMN")==0)
if (ip[i].value.indexOf("/")<0 && ip[i].value!="")
ip[i].value=ip[i].value.replace(/([^\\s]+)\\s*$/, "/$1/");
// Blank out temporary _MARNM_SURN
if (ip[i].id.indexOf("_MARNM_SURN")==0)
ip[i].value="";
// Convert "xxx yyy" and "xxx y yyy" surnames to "xxx,yyy"
if ((SURNAME_TRADITION=="spanish" || "SURNAME_TRADITION"=="portuguese") && ip[i].id.indexOf("SURN")==0) {
ip[i].value=document.forms[0].SURN.value.replace(/^\\s*([^\\s,]{2,})\\s+([iIyY] +)?([^\\s,]{2,})\\s*$/, "$1,$3");
}
}
return true;
}
// If the name isn’t initially formed from the components in a standard way,
// then don’t automatically update it.
if (document.getElementById("NAME").value!=generate_name() && document.getElementById("NAME").value!="//") {
convertHidden("NAME");
}
');
echo '</div>';
}