18c2e8227SGreg Roach<?php 28c2e8227SGreg Roach/** 38c2e8227SGreg Roach * webtrees: online genealogy 46bdf7674SGreg Roach * Copyright (C) 2017 webtrees development team 58c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify 68c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by 78c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or 88c2e8227SGreg Roach * (at your option) any later version. 98c2e8227SGreg Roach * This program is distributed in the hope that it will be useful, 108c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 118c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 128c2e8227SGreg Roach * GNU General Public License for more details. 138c2e8227SGreg Roach * You should have received a copy of the GNU General Public License 148c2e8227SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 158c2e8227SGreg Roach */ 1615d603e7SGreg Roach 1776692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module; 1876692c8bSGreg Roach 193a7bc14aSDavid Druryuse Fisharebest\Webtrees\Census\Census; 20ad51e0bbSGreg Roachuse Fisharebest\Webtrees\Census\CensusInterface; 210e62c4b8SGreg Roachuse Fisharebest\Webtrees\Family; 220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Filter; 2315d603e7SGreg Roachuse Fisharebest\Webtrees\FontAwesome; 24ad51e0bbSGreg Roachuse Fisharebest\Webtrees\Functions\Functions; 253d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsDb; 2615d603e7SGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsEdit; 270e62c4b8SGreg Roachuse Fisharebest\Webtrees\GedcomRecord; 280e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 2999f222b3SGreg Roachuse Fisharebest\Webtrees\Individual; 30ad51e0bbSGreg Roachuse Fisharebest\Webtrees\Menu; 310e62c4b8SGreg Roachuse Fisharebest\Webtrees\Note; 32dc46b574SDavid Druryuse Fisharebest\Webtrees\Soundex; 338c2e8227SGreg Roach 348c2e8227SGreg Roach/** 358c2e8227SGreg Roach * Class CensusAssistantModule 368c2e8227SGreg Roach */ 3715834aaeSGreg Roachclass CensusAssistantModule extends AbstractModule { 388c2e8227SGreg Roach /** {@inheritdoc} */ 398c2e8227SGreg Roach public function getTitle() { 4015d603e7SGreg Roach return /* I18N: Name of a module */ 4115d603e7SGreg Roach I18N::translate('Census assistant'); 428c2e8227SGreg Roach } 438c2e8227SGreg Roach 448c2e8227SGreg Roach /** {@inheritdoc} */ 458c2e8227SGreg Roach public function getDescription() { 4615d603e7SGreg Roach return /* I18N: Description of the “Census assistant” module */ 4715d603e7SGreg Roach I18N::translate('An alternative way to enter census transcripts and link them to individuals.'); 488c2e8227SGreg Roach } 498c2e8227SGreg Roach 5076692c8bSGreg Roach /** 5176692c8bSGreg Roach * This is a general purpose hook, allowing modules to respond to routes 5276692c8bSGreg Roach * of the form module.php?mod=FOO&mod_action=BAR 5376692c8bSGreg Roach * 5476692c8bSGreg Roach * @param string $mod_action 5576692c8bSGreg Roach */ 568c2e8227SGreg Roach public function modAction($mod_action) { 5715d603e7SGreg Roach global $WT_TREE; 5815d603e7SGreg Roach 598c2e8227SGreg Roach switch ($mod_action) { 6015d603e7SGreg Roach case 'census-header': 6115d603e7SGreg Roach header('Content-Type: text/html; charset=utf8'); 6215d603e7SGreg Roach $census = Filter::get('census'); 6315d603e7SGreg Roach echo $this->censusTableHeader(new $census); 648c2e8227SGreg Roach break; 6515d603e7SGreg Roach 6615d603e7SGreg Roach case 'census-individual': 6715d603e7SGreg Roach header('Content-Type: text/html; charset=utf8'); 6815d603e7SGreg Roach $census = Filter::get('census'); 6915d603e7SGreg Roach $individual = Individual::getInstance(Filter::get('xref'), $WT_TREE); 7015d603e7SGreg Roach $head = Individual::getInstance(Filter::get('head'), $WT_TREE); 7115d603e7SGreg Roach echo $this->censusTableRow(new $census, $individual, $head); 7215d603e7SGreg Roach break; 7315d603e7SGreg Roach 7440990b78SGreg Roach case 'media_find': 75764a01d9SGreg Roach self::mediaFind(); 768c2e8227SGreg Roach break; 778c2e8227SGreg Roach case 'media_query_3a': 78764a01d9SGreg Roach self::mediaQuery(); 798c2e8227SGreg Roach break; 808c2e8227SGreg Roach default: 818c2e8227SGreg Roach http_response_code(404); 828c2e8227SGreg Roach } 838c2e8227SGreg Roach } 848c2e8227SGreg Roach 858c2e8227SGreg Roach /** 8615d603e7SGreg Roach * @param Individual $individual 878c2e8227SGreg Roach */ 8815d603e7SGreg Roach public function createCensusAssistant(Individual $individual) { 8915d603e7SGreg Roach ?> 9040990b78SGreg Roach 9115d603e7SGreg Roach <div id="census-assistant-link" hidden> 9215d603e7SGreg Roach <a href="#"> 9315d603e7SGreg Roach <?= I18N::translate('Create a shared note using the census assistant') ?> 9415d603e7SGreg Roach </a> 9515d603e7SGreg Roach </div> 9640990b78SGreg Roach 9715d603e7SGreg Roach <div id="census-assistant" hidden> 9815d603e7SGreg Roach <input type="hidden" name="ca_census" id="ca-census"> 9915d603e7SGreg Roach <div class="form-group"> 10015d603e7SGreg Roach <div class="input-group"> 10115d603e7SGreg Roach <label for="census-assistant-title" class="input-group-addon"> 10215d603e7SGreg Roach <?= I18N::translate('Title') ?> 10315d603e7SGreg Roach </label> 10415d603e7SGreg Roach <input class="form-control" id="ca-title" name="ca_title" value=""> 10515d603e7SGreg Roach </div> 10615d603e7SGreg Roach </div> 10740990b78SGreg Roach 10815d603e7SGreg Roach <div class="row"> 10915d603e7SGreg Roach <div class="form-group col-sm-6"> 11015d603e7SGreg Roach <div class="input-group"> 11115d603e7SGreg Roach <label for="census-assistant-citation" class="input-group-addon"> 11215d603e7SGreg Roach <?= I18N::translate('Citation') ?> 11315d603e7SGreg Roach </label> 11415d603e7SGreg Roach <input class="form-control" id="census-assistant-citation" name="ca_citation"> 11515d603e7SGreg Roach </div> 11615d603e7SGreg Roach </div> 11740990b78SGreg Roach 11815d603e7SGreg Roach <div class="form-group col-sm-6"> 11915d603e7SGreg Roach <div class="input-group"> 12015d603e7SGreg Roach <label for="census-assistant-place" class="input-group-addon"> 12115d603e7SGreg Roach <?= I18N::translate('Place') ?> 12215d603e7SGreg Roach </label> 12315d603e7SGreg Roach <input class="form-control" id="census-assistant-place" name="ca_place"> 12415d603e7SGreg Roach </div> 12515d603e7SGreg Roach </div> 12615d603e7SGreg Roach </div> 12740990b78SGreg Roach 12815d603e7SGreg Roach <div class="form-group"> 12915d603e7SGreg Roach <div class="input-group"> 13015d603e7SGreg Roach <span class="input-group-addon"><?= I18N::translate('Individuals') ?></span> 13115d603e7SGreg Roach <?= FunctionsEdit::formControlIndividual($individual, ['id' => 'census-assistant-individual', 'style' => 'width:100%']) ?> 13215d603e7SGreg Roach <span class="input-group-btn"> 13315d603e7SGreg Roach <button type="button" class="btn btn-primary" id="census-assistant-add"> 13415d603e7SGreg Roach <?= FontAwesome::semanticIcon('add', I18N::translate('Add')) ?> 13515d603e7SGreg Roach </button> 13615d603e7SGreg Roach </span> 13715d603e7SGreg Roach <span class="input-group-btn"> 13815d603e7SGreg Roach <button type="button" class="btn btn-primary" id="census-assistant-head" 13915d603e7SGreg Roach title="<?= I18N::translate('Head of household') ?>"> 14015d603e7SGreg Roach <?= FontAwesome::semanticIcon('individual', I18N::translate('Head of household')) ?> 14115d603e7SGreg Roach </button> 14215d603e7SGreg Roach </span> 14315d603e7SGreg Roach </div> 14415d603e7SGreg Roach </div> 14515d603e7SGreg Roach 14615d603e7SGreg Roach <table class="table table-bordered table-small table-responsive wt-census-assistant-table" 14715d603e7SGreg Roach id="census-assistant-table"> 14815d603e7SGreg Roach <thead class="wt-census-assistant-header"></thead> 14915d603e7SGreg Roach <tbody class="wt-census-assistant-body"></tbody> 15015d603e7SGreg Roach </table> 15115d603e7SGreg Roach 15215d603e7SGreg Roach <div class="form-group"> 15315d603e7SGreg Roach <div class="input-group"> 15415d603e7SGreg Roach <label for="census-assistant-notes" class="input-group-addon"> 15515d603e7SGreg Roach <?= I18N::translate('Notes') ?> 15615d603e7SGreg Roach </label> 15715d603e7SGreg Roach <input class="form-control" id="census-assistant-notes" name="ca_notes"> 15815d603e7SGreg Roach </div> 15915d603e7SGreg Roach </div> 16015d603e7SGreg Roach </div> 16115d603e7SGreg Roach 16215d603e7SGreg Roach <script> 16315d603e7SGreg Roach // When a census date/place is selected, activate the census-assistant 16415d603e7SGreg Roach function censusAssistantSelect () { 16515d603e7SGreg Roach var censusAssistantLink = document.querySelector('#census-assistant-link'); 16615d603e7SGreg Roach var censusAssistant = document.querySelector('#census-assistant'); 16715d603e7SGreg Roach var censusOption = this.options[this.selectedIndex]; 16815d603e7SGreg Roach var census = censusOption.dataset.census; 16915d603e7SGreg Roach var censusPlace = censusOption.dataset.place; 17015d603e7SGreg Roach var censusYear = censusOption.value.substr(-4); 17115d603e7SGreg Roach 17215d603e7SGreg Roach if (censusOption.value !== '') { 17315d603e7SGreg Roach censusAssistantLink.removeAttribute('hidden'); 17440990b78SGreg Roach } else { 17515d603e7SGreg Roach censusAssistantLink.setAttribute('hidden', ''); 17640990b78SGreg Roach } 17715d603e7SGreg Roach 17815d603e7SGreg Roach censusAssistant.setAttribute('hidden', ''); 17915d603e7SGreg Roach document.querySelector('#ca-census').value = census; 18015d603e7SGreg Roach document.querySelector('#ca-title').value = censusYear + ' ' + censusPlace + ' - <?= I18N::translate('Census transcript') ?> - <?= strip_tags($individual->getFullName()) ?> - <?= I18N::translate('Household') ?>'; 18115d603e7SGreg Roach 18215d603e7SGreg Roach fetch('module.php?mod=GEDFact_assistant&mod_action=census-header&census=' + census) 18315d603e7SGreg Roach .then(function (response) { 18415d603e7SGreg Roach return response.text(); 18515d603e7SGreg Roach }) 18615d603e7SGreg Roach .then(function (text) { 18715d603e7SGreg Roach document.querySelector('#census-assistant-table thead').innerHTML = text; 18815d603e7SGreg Roach document.querySelector('#census-assistant-table tbody').innerHTML = ''; 18915d603e7SGreg Roach }); 190ad51e0bbSGreg Roach } 19115d603e7SGreg Roach 19215d603e7SGreg Roach // When the census assistant is activated, show the input fields 19315d603e7SGreg Roach function censusAssistantLink () { 19415d603e7SGreg Roach document.querySelector('#census-selector').setAttribute('hidden', ''); 19515d603e7SGreg Roach this.setAttribute('hidden', ''); 19615d603e7SGreg Roach document.getElementById('census-assistant').removeAttribute('hidden'); 19715d603e7SGreg Roach // Set the current individual as the head of household. 19815d603e7SGreg Roach censusAssistantHead(); 19915d603e7SGreg Roach 20015d603e7SGreg Roach return false; 20115d603e7SGreg Roach } 20215d603e7SGreg Roach 20315d603e7SGreg Roach // Add the currently selected individual to the census 20415d603e7SGreg Roach function censusAssistantAdd () { 20515d603e7SGreg Roach var censusSelector = document.querySelector('#census-selector'); 20615d603e7SGreg Roach var census = censusSelector.options[censusSelector.selectedIndex].dataset.census; 20715d603e7SGreg Roach var indi_selector = document.querySelector('#census-assistant-individual'); 20815d603e7SGreg Roach var xref = indi_selector.options[indi_selector.selectedIndex].value; 20915d603e7SGreg Roach var headTd = document.querySelector('#census-assistant-table td'); 21015d603e7SGreg Roach var head = headTd === null ? xref : headTd.innerHTML; 21115d603e7SGreg Roach 21215d603e7SGreg Roach fetch('module.php?mod=GEDFact_assistant&mod_action=census-individual&census=' + census + '&xref=' + xref + '&head=' + head, {credentials: 'same-origin'}) 21315d603e7SGreg Roach .then(function (response) { 21415d603e7SGreg Roach return response.text(); 21515d603e7SGreg Roach }) 21615d603e7SGreg Roach .then(function (text) { 21715d603e7SGreg Roach document.querySelector('#census-assistant-table tbody').innerHTML += text; 21815d603e7SGreg Roach }); 21915d603e7SGreg Roach 22015d603e7SGreg Roach return false; 22115d603e7SGreg Roach } 22215d603e7SGreg Roach 22315d603e7SGreg Roach // Set the currently selected individual as the head of household 22415d603e7SGreg Roach function censusAssistantHead () { 22515d603e7SGreg Roach var censusSelector = document.querySelector('#census-selector'); 22615d603e7SGreg Roach var census = censusSelector.options[censusSelector.selectedIndex].dataset.census; 22715d603e7SGreg Roach var indi_selector = document.querySelector('#census-assistant-individual'); 22815d603e7SGreg Roach var xref = indi_selector.options[indi_selector.selectedIndex].value; 22915d603e7SGreg Roach 23015d603e7SGreg Roach fetch('module.php?mod=GEDFact_assistant&mod_action=census-individual&census=' + census + '&xref=' + xref + '&head=' + xref, {credentials: 'same-origin'}) 23115d603e7SGreg Roach .then(function (response) { 23215d603e7SGreg Roach return response.text(); 23315d603e7SGreg Roach }) 23415d603e7SGreg Roach .then(function (text) { 23515d603e7SGreg Roach document.querySelector('#census-assistant-table tbody').innerHTML = text; 23615d603e7SGreg Roach }); 23715d603e7SGreg Roach 23815d603e7SGreg Roach return false; 23915d603e7SGreg Roach } 24015d603e7SGreg Roach 24115d603e7SGreg Roach document.querySelector('#census-selector').addEventListener('change', censusAssistantSelect); 24215d603e7SGreg Roach document.querySelector('#census-assistant-link').addEventListener('click', censusAssistantLink); 24315d603e7SGreg Roach document.querySelector('#census-assistant-add').addEventListener('click', censusAssistantAdd); 24415d603e7SGreg Roach document.querySelector('#census-assistant-head').addEventListener('click', censusAssistantHead); 24515d603e7SGreg Roach </script> 24615d603e7SGreg Roach <?php 24715d603e7SGreg Roach } 24815d603e7SGreg Roach 24915d603e7SGreg Roach /** 25015d603e7SGreg Roach * @param Individual $individual 251*60bc3e3fSGreg Roach * @param string $fact_id 25215d603e7SGreg Roach * @param string $newged 253*60bc3e3fSGreg Roach * @param bool $keep_chan 25415d603e7SGreg Roach * 25515d603e7SGreg Roach * @return string 25615d603e7SGreg Roach */ 25715d603e7SGreg Roach public function updateCensusAssistant(Individual $individual, $fact_id, $newged, $keep_chan) { 25815d603e7SGreg Roach $ca_title = Filter::post('ca_title'); 25915d603e7SGreg Roach $ca_place = Filter::post('ca_place'); 26015d603e7SGreg Roach $ca_citation = Filter::post('ca_citation'); 26115d603e7SGreg Roach $ca_individuals = Filter::postArray('ca_individuals'); 26215d603e7SGreg Roach $ca_notes = Filter::post('ca_notes'); 26315d603e7SGreg Roach $ca_census = Filter::post('ca_census', 'Fisharebest\\\\Webtrees\\\\Census\\\\CensusOf[A-Za-z0-9]+'); 26415d603e7SGreg Roach 26515d603e7SGreg Roach if ($ca_census !== '' && !empty($ca_individuals)) { 26615d603e7SGreg Roach $census = new $ca_census; 26715d603e7SGreg Roach 26815d603e7SGreg Roach $note_text = $this->createNoteText($census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes); 26915d603e7SGreg Roach $note_gedcom = '0 @new@ NOTE ' . str_replace("\n", "\n1 CONT ", $note_text); 27015d603e7SGreg Roach $note = $individual->getTree()->createRecord($note_gedcom); 27115d603e7SGreg Roach 27215d603e7SGreg Roach $newged .= "\n2 NOTE @" . $note->getXref() . '@'; 27315d603e7SGreg Roach 27415d603e7SGreg Roach // Add the census fact to the rest of the household 27515d603e7SGreg Roach foreach (array_keys($ca_individuals) as $xref) { 27615d603e7SGreg Roach if ($xref !== $individual->getXref()) { 27715d603e7SGreg Roach Individual::getInstance($xref, $individual->getTree()) 27815d603e7SGreg Roach ->updateFact($fact_id, $newged, !$keep_chan); 27915d603e7SGreg Roach } 28015d603e7SGreg Roach } 28115d603e7SGreg Roach } 28215d603e7SGreg Roach 28315d603e7SGreg Roach return $newged; 28415d603e7SGreg Roach } 28515d603e7SGreg Roach 28615d603e7SGreg Roach /** 28715d603e7SGreg Roach * @param CensusInterface $census 28815d603e7SGreg Roach * @param string $ca_title 28915d603e7SGreg Roach * @param string $ca_place 29015d603e7SGreg Roach * @param string $ca_citation 29115d603e7SGreg Roach * @param string[][] $ca_individuals 29215d603e7SGreg Roach * @param string $ca_notes 29315d603e7SGreg Roach * 29415d603e7SGreg Roach * @return string 29515d603e7SGreg Roach */ 29615d603e7SGreg Roach private function createNoteText(CensusInterface $census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes) { 29715d603e7SGreg Roach $text = $ca_title . "\n" . $ca_citation . "\n" . $ca_place . "\n\n.start_formatted_area.\n\n"; 29815d603e7SGreg Roach 29915d603e7SGreg Roach foreach ($census->columns() as $n => $column) { 30015d603e7SGreg Roach if ($n > 0) { 30115d603e7SGreg Roach $text .= '|'; 30215d603e7SGreg Roach } 30315d603e7SGreg Roach $text .= '.b.' . $column->abbreviation(); 30415d603e7SGreg Roach } 30515d603e7SGreg Roach 30615d603e7SGreg Roach foreach ($ca_individuals as $xref => $columns) { 30715d603e7SGreg Roach $text .= "\n" . implode('|', $columns); 30815d603e7SGreg Roach } 30915d603e7SGreg Roach 31015d603e7SGreg Roach return $text . "\n.end_formatted_area.\n\n" . $ca_notes; 31140990b78SGreg Roach } 31240990b78SGreg Roach 31340990b78SGreg Roach /** 31476692c8bSGreg Roach * Find a media object. 31540990b78SGreg Roach */ 316764a01d9SGreg Roach private static function mediaFind() { 3178c2e8227SGreg Roach global $WT_TREE; 3188c2e8227SGreg Roach 3198c2e8227SGreg Roach $controller = new SimpleController; 3208c2e8227SGreg Roach $filter = Filter::get('filter'); 3218c2e8227SGreg Roach $multiple = Filter::getBool('multiple'); 3228c2e8227SGreg Roach 3238c2e8227SGreg Roach $controller 3248c2e8227SGreg Roach ->setPageTitle(I18N::translate('Find an individual')) 3258c2e8227SGreg Roach ->pageHeader(); 3268c2e8227SGreg Roach 3278c2e8227SGreg Roach ?> 32899f222b3SGreg Roach <script> 3298c2e8227SGreg Roach function pasterow (id, name, gend, yob, age, bpl) { 3308c2e8227SGreg Roach window.opener.opener.insertRowToTable(id, name, '', gend, '', yob, age, 'Y', '', bpl); 3318c2e8227SGreg Roach } 3328c2e8227SGreg Roach 3338c2e8227SGreg Roach function pasteid (id, name, thumb) { 3348c2e8227SGreg Roach if (thumb) { 3358c2e8227SGreg Roach window.opener.paste_id(id, name, thumb); 33615d603e7SGreg Roach <?php if (!$multiple) { 33715d603e7SGreg Roach echo 'window.close();'; 33815d603e7SGreg Roach } ?> 3398c2e8227SGreg Roach } else { 3408c2e8227SGreg Roach // GEDFact_assistant ======================== 3418c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 3428c2e8227SGreg Roach window.opener.insertRowToTable(id, name); 3438c2e8227SGreg Roach } 3448c2e8227SGreg Roach window.opener.paste_id(id); 3458c2e8227SGreg Roach if (window.opener.pastename) { 3468c2e8227SGreg Roach window.opener.pastename(name); 3478c2e8227SGreg Roach } 34815d603e7SGreg Roach <?php if (!$multiple) { 34915d603e7SGreg Roach echo 'window.close();'; 35015d603e7SGreg Roach } ?> 3518c2e8227SGreg Roach } 3528c2e8227SGreg Roach } 35315d603e7SGreg Roach 3548c2e8227SGreg Roach function checknames (frm) { 3558c2e8227SGreg Roach if (document.forms[0].subclick) { 3568c2e8227SGreg Roach button = document.forms[0].subclick.value; 3578c2e8227SGreg Roach } else { 35815d603e7SGreg Roach button = ''; 3598c2e8227SGreg Roach } 36015d603e7SGreg Roach if (frm.filter.value.length < 2 && button !== 'all') { 36115d603e7SGreg Roach alert('<?= I18N::translate('Please enter more than one character.') ?>'); 3628c2e8227SGreg Roach frm.filter.focus(); 3638c2e8227SGreg Roach return false; 3648c2e8227SGreg Roach } 36515d603e7SGreg Roach if (button == 'all') { 36615d603e7SGreg Roach frm.filter.value = ''; 3678c2e8227SGreg Roach } 3688c2e8227SGreg Roach return true; 3698c2e8227SGreg Roach } 37099f222b3SGreg Roach </script> 3718c2e8227SGreg Roach 37299f222b3SGreg Roach <?php 373a86dd8b1SGreg Roach echo '<div>'; 3744c621133SGreg Roach echo '<table class="list_table width90" border="0">'; 375a86dd8b1SGreg Roach echo '<tr><td style="padding: 10px;" class="facts_label03 width90">'; // start column for find text header 3768c2e8227SGreg Roach echo $controller->getPageTitle(); 3774c621133SGreg Roach echo '</td>'; 3784c621133SGreg Roach echo '</tr>'; 3794c621133SGreg Roach echo '</table>'; 3804c621133SGreg Roach echo '<br>'; 3818c2e8227SGreg Roach echo '<button onclick="window.close();">', I18N::translate('close'), '</button>'; 3824c621133SGreg Roach echo '<br>'; 3838c2e8227SGreg Roach 3848c2e8227SGreg Roach $filter = trim($filter); 3858c2e8227SGreg Roach $filter_array = explode(' ', preg_replace('/ {2,}/', ' ', $filter)); 3864c621133SGreg Roach echo '<table class="tabs_table width90"><tr>'; 38713abd6f3SGreg Roach $myindilist = FunctionsDb::searchIndividualNames($filter_array, [$WT_TREE]); 3888c2e8227SGreg Roach if ($myindilist) { 3894c621133SGreg Roach echo '<td class="list_value_wrap"><ul>'; 3900e62c4b8SGreg Roach usort($myindilist, '\Fisharebest\Webtrees\GedcomRecord::compare'); 3918c2e8227SGreg Roach foreach ($myindilist as $indi) { 3928c2e8227SGreg Roach $nam = Filter::escapeHtml($indi->getFullName()); 3938c2e8227SGreg Roach echo "<li><a href=\"#\" onclick=\"pasterow( 3948c2e8227SGreg Roach '" . $indi->getXref() . "' , 3958c2e8227SGreg Roach '" . $nam . "' , 3968c2e8227SGreg Roach '" . $indi->getSex() . "' , 3977820e4d7SGreg Roach '" . $indi->getBirthYear() . "' , 3987820e4d7SGreg Roach '" . (1901 - $indi->getBirthYear()) . "' , 3997820e4d7SGreg Roach '" . $indi->getBirthPlace() . "'); return false;\"> 4007a6ee1acSGreg Roach <b>" . $indi->getFullName() . '</b> '; 4018c2e8227SGreg Roach 402564ae2d7SGreg Roach $born = I18N::translate('Birth'); 4037a6ee1acSGreg Roach echo '</span><br><span class="list_item">', $born, ' ', $indi->getBirthYear(), ' ', $indi->getBirthPlace(), '</span></a></li>'; 4047a6ee1acSGreg Roach echo '<hr>'; 4058c2e8227SGreg Roach } 4068c2e8227SGreg Roach echo '</ul></td></tr><tr><td class="list_label">', I18N::translate('Total individuals: %s', count($myindilist)), '</tr></td>'; 4078c2e8227SGreg Roach } else { 4087a6ee1acSGreg Roach echo '<td class="list_value_wrap">'; 4098c2e8227SGreg Roach echo I18N::translate('No results found.'); 4107a6ee1acSGreg Roach echo '</td></tr>'; 4118c2e8227SGreg Roach } 4127a6ee1acSGreg Roach echo '</table>'; 4138c2e8227SGreg Roach echo '</div>'; 4148c2e8227SGreg Roach } 4158c2e8227SGreg Roach 4168c2e8227SGreg Roach /** 41776692c8bSGreg Roach * Search for a media object. 4188c2e8227SGreg Roach */ 419764a01d9SGreg Roach private static function mediaQuery() { 42024ec66ceSGreg Roach global $WT_TREE; 42124ec66ceSGreg Roach 4228c2e8227SGreg Roach $iid2 = Filter::get('iid', WT_REGEX_XREF); 4238c2e8227SGreg Roach 4248c2e8227SGreg Roach $controller = new SimpleController; 4258c2e8227SGreg Roach $controller 4268c2e8227SGreg Roach ->setPageTitle(I18N::translate('Link to an existing media object')) 4278c2e8227SGreg Roach ->pageHeader(); 4288c2e8227SGreg Roach 42924ec66ceSGreg Roach $record = GedcomRecord::getInstance($iid2, $WT_TREE); 4308c2e8227SGreg Roach if ($record) { 4318c2e8227SGreg Roach $headjs = ''; 4328c2e8227SGreg Roach if ($record instanceof Family) { 4338c2e8227SGreg Roach if ($record->getHusband()) { 4348c2e8227SGreg Roach $headjs = $record->getHusband()->getXref(); 4358c2e8227SGreg Roach } elseif ($record->getWife()) { 4368c2e8227SGreg Roach $headjs = $record->getWife()->getXref(); 4378c2e8227SGreg Roach } 4388c2e8227SGreg Roach } 4398c2e8227SGreg Roach ?> 4408c2e8227SGreg Roach <script> 4418c2e8227SGreg Roach function insertId () { 4428c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 4438c2e8227SGreg Roach // alert('Please move this alert window and examine the contents of the pop-up window, then click OK') 444564ae2d7SGreg Roach window.opener.insertRowToTable('<?= $record->getXref() ?>', '<?= htmlspecialchars($record->getFullName()) ?>', '<?= $headjs ?>'); 4458c2e8227SGreg Roach window.close(); 4468c2e8227SGreg Roach } 4478c2e8227SGreg Roach } 4488c2e8227SGreg Roach </script> 4498c2e8227SGreg Roach <?php 4508c2e8227SGreg Roach } else { 4518c2e8227SGreg Roach ?> 4528c2e8227SGreg Roach <script> 4538c2e8227SGreg Roach function insertId () { 454564ae2d7SGreg Roach window.opener.alert('<?= $iid2 ?> - <?= I18N::translate('Not a valid individual, family, or source ID') ?>'); 4558c2e8227SGreg Roach window.close(); 4568c2e8227SGreg Roach } 4578c2e8227SGreg Roach </script> 4588c2e8227SGreg Roach <?php 4598c2e8227SGreg Roach } 4608c2e8227SGreg Roach ?> 4618c2e8227SGreg Roach <script>window.onLoad = insertId();</script> 4628c2e8227SGreg Roach <?php 4638c2e8227SGreg Roach } 4648c2e8227SGreg Roach 4658c2e8227SGreg Roach /** 4668c2e8227SGreg Roach * Convert custom markup into HTML 4678c2e8227SGreg Roach * 4688c2e8227SGreg Roach * @param Note $note 4698c2e8227SGreg Roach * 4708c2e8227SGreg Roach * @return string 4718c2e8227SGreg Roach */ 4728c2e8227SGreg Roach public static function formatCensusNote(Note $note) { 47314c3d3fbSGreg Roach if (preg_match('/(.*)((?:\n.*)*)\n\.start_formatted_area\.\n(.+)\n(.+(?:\n.+)*)\n.end_formatted_area\.((?:\n.*)*)/', $note->getNote(), $match)) { 4748c2e8227SGreg Roach // This looks like a census-assistant shared note 4758c2e8227SGreg Roach $title = Filter::escapeHtml($match[1]); 4768c2e8227SGreg Roach $preamble = Filter::escapeHtml($match[2]); 4778c2e8227SGreg Roach $header = Filter::escapeHtml($match[3]); 4788c2e8227SGreg Roach $data = Filter::escapeHtml($match[4]); 4798c2e8227SGreg Roach $postamble = Filter::escapeHtml($match[5]); 4808c2e8227SGreg Roach 481dc46b574SDavid Drury // Get the column headers for the census to which this note refers 482dc46b574SDavid Drury // requires the fact place & date to match the specific census 483dc46b574SDavid Drury // censusPlace() (Soundex match) and censusDate() functions 48413abd6f3SGreg Roach $fmt_headers = []; 48515d603e7SGreg Roach /** @var GedcomRecord[] $linkedRecords */ 486dc46b574SDavid Drury $linkedRecords = array_merge($note->linkedIndividuals('NOTE'), $note->linkedFamilies('NOTE')); 487dc46b574SDavid Drury $firstRecord = array_shift($linkedRecords); 488dc46b574SDavid Drury if ($firstRecord) { 489dc46b574SDavid Drury $countryCode = ''; 490dc46b574SDavid Drury $date = ''; 491dc46b574SDavid Drury foreach ($firstRecord->getFacts('CENS') as $fact) { 492dc46b574SDavid Drury if (trim($fact->getAttribute('NOTE'), '@') === $note->getXref()) { 493dc46b574SDavid Drury $date = $fact->getAttribute('DATE'); 494dc46b574SDavid Drury $place = explode(',', strip_tags($fact->getPlace()->getFullName())); 495dc46b574SDavid Drury $countryCode = Soundex::daitchMokotoff(array_pop($place)); 496dc46b574SDavid Drury break; 497dc46b574SDavid Drury } 4988c2e8227SGreg Roach } 4998c2e8227SGreg Roach 500dc46b574SDavid Drury foreach (Census::allCensusPlaces() as $censusPlace) { 501dc46b574SDavid Drury if (Soundex::compare($countryCode, Soundex::daitchMokotoff($censusPlace->censusPlace()))) { 502dc46b574SDavid Drury foreach ($censusPlace->allCensusDates() as $census) { 503dc46b574SDavid Drury if ($census->censusDate() == $date) { 504dc46b574SDavid Drury foreach ($census->columns() as $column) { 505dc46b574SDavid Drury $abbrev = $column->abbreviation(); 506dc46b574SDavid Drury if ($abbrev) { 507dc46b574SDavid Drury $description = $column->title() ? $column->title() : I18N::translate('Description unavailable'); 508dc46b574SDavid Drury $fmt_headers[$abbrev] = '<span title="' . $description . '">' . $abbrev . '</span>'; 509dc46b574SDavid Drury } 510dc46b574SDavid Drury } 511dc46b574SDavid Drury break 2; 512dc46b574SDavid Drury } 513dc46b574SDavid Drury } 514dc46b574SDavid Drury } 515dc46b574SDavid Drury } 516dc46b574SDavid Drury } 517dc46b574SDavid Drury // Substitute header labels and format as HTML 5188c2e8227SGreg Roach $thead = '<tr><th>' . strtr(str_replace('|', '</th><th>', $header), $fmt_headers) . '</th></tr>'; 519ad51e0bbSGreg Roach $thead = str_replace('.b.', '', $thead); 5208c2e8227SGreg Roach 5218c2e8227SGreg Roach // Format data as HTML 5228c2e8227SGreg Roach $tbody = ''; 52314c3d3fbSGreg Roach foreach (explode("\n", $data) as $row) { 5248c2e8227SGreg Roach $tbody .= '<tr>'; 5258c2e8227SGreg Roach foreach (explode('|', $row) as $column) { 5268c2e8227SGreg Roach $tbody .= '<td>' . $column . '</td>'; 5278c2e8227SGreg Roach } 5288c2e8227SGreg Roach $tbody .= '</tr>'; 5298c2e8227SGreg Roach } 5308c2e8227SGreg Roach 5318c2e8227SGreg Roach return 5328c2e8227SGreg Roach $title . "\n" . // The newline allows the framework to expand the details and turn the first line into a link 533673157b0SGreg Roach '<div class="markdown">' . 5348c2e8227SGreg Roach '<p>' . $preamble . '</p>' . 535dc46b574SDavid Drury '<table>' . 5368c2e8227SGreg Roach '<thead>' . $thead . '</thead>' . 5378c2e8227SGreg Roach '<tbody>' . $tbody . '</tbody>' . 5388c2e8227SGreg Roach '</table>' . 539dc46b574SDavid Drury '<p>' . $postamble . '</p>' . 540dc46b574SDavid Drury '</div>'; 5418c2e8227SGreg Roach } else { 5428c2e8227SGreg Roach // Not a census-assistant shared note - apply default formatting 54315d603e7SGreg Roach return Filter::formatText($note->getNote(), $note->getTree()); 5448c2e8227SGreg Roach } 5458c2e8227SGreg Roach } 54699f222b3SGreg Roach 54799f222b3SGreg Roach /** 548ad51e0bbSGreg Roach * Generate an HTML row of data for the census header 54952bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 55052bc9faeSGreg Roach * Add suffix cell (delete button) 55152bc9faeSGreg Roach * 552ad51e0bbSGreg Roach * @param CensusInterface $census 55399f222b3SGreg Roach * 554ad51e0bbSGreg Roach * @return string 55599f222b3SGreg Roach */ 556ad51e0bbSGreg Roach public static function censusTableHeader(CensusInterface $census) { 55752bc9faeSGreg Roach $html = ''; 558ad51e0bbSGreg Roach foreach ($census->columns() as $column) { 55915d603e7SGreg Roach $html .= '<th class="wt-census-assistant-field" title="' . $column->title() . '">' . $column->abbreviation() . '</th>'; 56099f222b3SGreg Roach } 56199f222b3SGreg Roach 56215d603e7SGreg Roach return '<tr class="wt-census-assistant-row"><th hidden></th>' . $html . '<th></th></tr>'; 563ad51e0bbSGreg Roach } 56499f222b3SGreg Roach 565ad51e0bbSGreg Roach /** 566ad51e0bbSGreg Roach * Generate an HTML row of data for the census 56752bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 56852bc9faeSGreg Roach * Add suffix cell (delete button) 56952bc9faeSGreg Roach * 570ad51e0bbSGreg Roach * @param CensusInterface $census 571ad51e0bbSGreg Roach * 572ad51e0bbSGreg Roach * @return string 573ad51e0bbSGreg Roach */ 574ad51e0bbSGreg Roach public static function censusTableEmptyRow(CensusInterface $census) { 57515d603e7SGreg Roach return '<tr class="wt-census-assistant-row"><td hidden></td>' . str_repeat('<td class="wt-census-assistant-field"><input type="text" class="form-control wt-census-assistant-form-control"></td>', count($census->columns())) . '<td><a class="icon-remove" href="#" title="' . I18N::translate('Remove') . '"></a></td></tr>'; 576ad51e0bbSGreg Roach } 57799f222b3SGreg Roach 578ad51e0bbSGreg Roach /** 579ad51e0bbSGreg Roach * Generate an HTML row of data for the census 58052bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 58152bc9faeSGreg Roach * Add suffix cell (delete button) 58252bc9faeSGreg Roach * 583ad51e0bbSGreg Roach * @param CensusInterface $census 584ad51e0bbSGreg Roach * @param Individual $individual 585ad51e0bbSGreg Roach * @param Individual $head 586ad51e0bbSGreg Roach * 587ad51e0bbSGreg Roach * @return string 588ad51e0bbSGreg Roach */ 58915d603e7SGreg Roach public static function censusTableRow(CensusInterface $census, Individual $individual, Individual $head) { 59015d603e7SGreg Roach $html = ''; 59115d603e7SGreg Roach foreach ($census->columns() as $column) { 59215d603e7SGreg Roach $html .= '<td class="wt-census-assistant-field"><input class="form-control wt-census-assistant-form-control" type="text" value="' . $column->generate($individual, $head) . '" name="ca_individuals[' . $individual->getXref() . '][]"></td>'; 59399f222b3SGreg Roach } 59499f222b3SGreg Roach 59515d603e7SGreg Roach return '<tr class="wt-census-assistant-row"><td class="wt-census-assistant-field" hidden>' . $individual->getXref() . '</td>' . $html . '<td class="wt-census-assistant-field"><a class="icon-remove" href="#" title="' . I18N::translate('Remove') . '"></a></td></tr>'; 59699f222b3SGreg Roach } 5978c2e8227SGreg Roach} 598