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; 243d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsDb; 2515d603e7SGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsEdit; 260e62c4b8SGreg Roachuse Fisharebest\Webtrees\GedcomRecord; 270e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 2899f222b3SGreg Roachuse Fisharebest\Webtrees\Individual; 290e62c4b8SGreg Roachuse Fisharebest\Webtrees\Note; 30dc46b574SDavid Druryuse Fisharebest\Webtrees\Soundex; 318c2e8227SGreg Roach 328c2e8227SGreg Roach/** 338c2e8227SGreg Roach * Class CensusAssistantModule 348c2e8227SGreg Roach */ 3515834aaeSGreg Roachclass CensusAssistantModule extends AbstractModule { 368c2e8227SGreg Roach /** {@inheritdoc} */ 378c2e8227SGreg Roach public function getTitle() { 3815d603e7SGreg Roach return /* I18N: Name of a module */ 3915d603e7SGreg Roach I18N::translate('Census assistant'); 408c2e8227SGreg Roach } 418c2e8227SGreg Roach 428c2e8227SGreg Roach /** {@inheritdoc} */ 438c2e8227SGreg Roach public function getDescription() { 4415d603e7SGreg Roach return /* I18N: Description of the “Census assistant” module */ 4515d603e7SGreg Roach I18N::translate('An alternative way to enter census transcripts and link them to individuals.'); 468c2e8227SGreg Roach } 478c2e8227SGreg Roach 4876692c8bSGreg Roach /** 4976692c8bSGreg Roach * This is a general purpose hook, allowing modules to respond to routes 5076692c8bSGreg Roach * of the form module.php?mod=FOO&mod_action=BAR 5176692c8bSGreg Roach * 5276692c8bSGreg Roach * @param string $mod_action 5376692c8bSGreg Roach */ 548c2e8227SGreg Roach public function modAction($mod_action) { 5515d603e7SGreg Roach global $WT_TREE; 5615d603e7SGreg Roach 578c2e8227SGreg Roach switch ($mod_action) { 5815d603e7SGreg Roach case 'census-header': 5915d603e7SGreg Roach header('Content-Type: text/html; charset=utf8'); 6015d603e7SGreg Roach $census = Filter::get('census'); 6115d603e7SGreg Roach echo $this->censusTableHeader(new $census); 628c2e8227SGreg Roach break; 6315d603e7SGreg Roach 6415d603e7SGreg Roach case 'census-individual': 6515d603e7SGreg Roach header('Content-Type: text/html; charset=utf8'); 6615d603e7SGreg Roach $census = Filter::get('census'); 6715d603e7SGreg Roach $individual = Individual::getInstance(Filter::get('xref'), $WT_TREE); 6815d603e7SGreg Roach $head = Individual::getInstance(Filter::get('head'), $WT_TREE); 6915d603e7SGreg Roach echo $this->censusTableRow(new $census, $individual, $head); 7015d603e7SGreg Roach break; 7115d603e7SGreg Roach 7240990b78SGreg Roach case 'media_find': 73764a01d9SGreg Roach self::mediaFind(); 748c2e8227SGreg Roach break; 758c2e8227SGreg Roach case 'media_query_3a': 76764a01d9SGreg Roach self::mediaQuery(); 778c2e8227SGreg Roach break; 788c2e8227SGreg Roach default: 798c2e8227SGreg Roach http_response_code(404); 808c2e8227SGreg Roach } 818c2e8227SGreg Roach } 828c2e8227SGreg Roach 838c2e8227SGreg Roach /** 8415d603e7SGreg Roach * @param Individual $individual 858c2e8227SGreg Roach */ 8615d603e7SGreg Roach public function createCensusAssistant(Individual $individual) { 8715d603e7SGreg Roach ?> 8840990b78SGreg Roach 8915d603e7SGreg Roach <div id="census-assistant-link" hidden> 9015d603e7SGreg Roach <a href="#"> 9115d603e7SGreg Roach <?= I18N::translate('Create a shared note using the census assistant') ?> 9215d603e7SGreg Roach </a> 9315d603e7SGreg Roach </div> 9440990b78SGreg Roach 9515d603e7SGreg Roach <div id="census-assistant" hidden> 9615d603e7SGreg Roach <input type="hidden" name="ca_census" id="ca-census"> 9715d603e7SGreg Roach <div class="form-group"> 9815d603e7SGreg Roach <div class="input-group"> 9915d603e7SGreg Roach <label for="census-assistant-title" class="input-group-addon"> 10015d603e7SGreg Roach <?= I18N::translate('Title') ?> 10115d603e7SGreg Roach </label> 10215d603e7SGreg Roach <input class="form-control" id="ca-title" name="ca_title" value=""> 10315d603e7SGreg Roach </div> 10415d603e7SGreg Roach </div> 10540990b78SGreg Roach 10615d603e7SGreg Roach <div class="row"> 10715d603e7SGreg Roach <div class="form-group col-sm-6"> 10815d603e7SGreg Roach <div class="input-group"> 10915d603e7SGreg Roach <label for="census-assistant-citation" class="input-group-addon"> 11015d603e7SGreg Roach <?= I18N::translate('Citation') ?> 11115d603e7SGreg Roach </label> 11215d603e7SGreg Roach <input class="form-control" id="census-assistant-citation" name="ca_citation"> 11315d603e7SGreg Roach </div> 11415d603e7SGreg Roach </div> 11540990b78SGreg Roach 11615d603e7SGreg Roach <div class="form-group col-sm-6"> 11715d603e7SGreg Roach <div class="input-group"> 11815d603e7SGreg Roach <label for="census-assistant-place" class="input-group-addon"> 11915d603e7SGreg Roach <?= I18N::translate('Place') ?> 12015d603e7SGreg Roach </label> 12115d603e7SGreg Roach <input class="form-control" id="census-assistant-place" name="ca_place"> 12215d603e7SGreg Roach </div> 12315d603e7SGreg Roach </div> 12415d603e7SGreg Roach </div> 12540990b78SGreg Roach 12615d603e7SGreg Roach <div class="form-group"> 12715d603e7SGreg Roach <div class="input-group"> 12815d603e7SGreg Roach <span class="input-group-addon"><?= I18N::translate('Individuals') ?></span> 12915d603e7SGreg Roach <?= FunctionsEdit::formControlIndividual($individual, ['id' => 'census-assistant-individual', 'style' => 'width:100%']) ?> 13015d603e7SGreg Roach <span class="input-group-btn"> 13115d603e7SGreg Roach <button type="button" class="btn btn-primary" id="census-assistant-add"> 13215d603e7SGreg Roach <?= FontAwesome::semanticIcon('add', I18N::translate('Add')) ?> 13315d603e7SGreg Roach </button> 13415d603e7SGreg Roach </span> 13515d603e7SGreg Roach <span class="input-group-btn"> 13615d603e7SGreg Roach <button type="button" class="btn btn-primary" id="census-assistant-head" 13715d603e7SGreg Roach title="<?= I18N::translate('Head of household') ?>"> 13815d603e7SGreg Roach <?= FontAwesome::semanticIcon('individual', I18N::translate('Head of household')) ?> 13915d603e7SGreg Roach </button> 14015d603e7SGreg Roach </span> 14115d603e7SGreg Roach </div> 14215d603e7SGreg Roach </div> 14315d603e7SGreg Roach 14415d603e7SGreg Roach <table class="table table-bordered table-small table-responsive wt-census-assistant-table" 14515d603e7SGreg Roach id="census-assistant-table"> 14615d603e7SGreg Roach <thead class="wt-census-assistant-header"></thead> 14715d603e7SGreg Roach <tbody class="wt-census-assistant-body"></tbody> 14815d603e7SGreg Roach </table> 14915d603e7SGreg Roach 15015d603e7SGreg Roach <div class="form-group"> 15115d603e7SGreg Roach <div class="input-group"> 15215d603e7SGreg Roach <label for="census-assistant-notes" class="input-group-addon"> 15315d603e7SGreg Roach <?= I18N::translate('Notes') ?> 15415d603e7SGreg Roach </label> 15515d603e7SGreg Roach <input class="form-control" id="census-assistant-notes" name="ca_notes"> 15615d603e7SGreg Roach </div> 15715d603e7SGreg Roach </div> 15815d603e7SGreg Roach </div> 15915d603e7SGreg Roach 16015d603e7SGreg Roach <script> 16115d603e7SGreg Roach // When a census date/place is selected, activate the census-assistant 16215d603e7SGreg Roach function censusAssistantSelect() { 16315d603e7SGreg Roach var censusAssistantLink = document.querySelector('#census-assistant-link'); 16415d603e7SGreg Roach var censusAssistant = document.querySelector('#census-assistant'); 16515d603e7SGreg Roach var censusOption = this.options[this.selectedIndex]; 16615d603e7SGreg Roach var census = censusOption.dataset.census; 16715d603e7SGreg Roach var censusPlace = censusOption.dataset.place; 16815d603e7SGreg Roach var censusYear = censusOption.value.substr(-4); 16915d603e7SGreg Roach 17015d603e7SGreg Roach if (censusOption.value !== '') { 17115d603e7SGreg Roach censusAssistantLink.removeAttribute('hidden'); 17240990b78SGreg Roach } else { 17315d603e7SGreg Roach censusAssistantLink.setAttribute('hidden', ''); 17440990b78SGreg Roach } 17515d603e7SGreg Roach 17615d603e7SGreg Roach censusAssistant.setAttribute('hidden', ''); 17715d603e7SGreg Roach document.querySelector('#ca-census').value = census; 17815d603e7SGreg Roach document.querySelector('#ca-title').value = censusYear + ' ' + censusPlace + ' - <?= I18N::translate('Census transcript') ?> - <?= strip_tags($individual->getFullName()) ?> - <?= I18N::translate('Household') ?>'; 17915d603e7SGreg Roach 18015d603e7SGreg Roach fetch('module.php?mod=GEDFact_assistant&mod_action=census-header&census=' + census) 18115d603e7SGreg Roach .then(function (response) { 18215d603e7SGreg Roach return response.text(); 18315d603e7SGreg Roach }) 18415d603e7SGreg Roach .then(function (text) { 18515d603e7SGreg Roach document.querySelector('#census-assistant-table thead').innerHTML = text; 18615d603e7SGreg Roach document.querySelector('#census-assistant-table tbody').innerHTML = ''; 18715d603e7SGreg Roach }); 188ad51e0bbSGreg Roach } 18915d603e7SGreg Roach 19015d603e7SGreg Roach // When the census assistant is activated, show the input fields 19115d603e7SGreg Roach function censusAssistantLink() { 19215d603e7SGreg Roach document.querySelector('#census-selector').setAttribute('hidden', ''); 19315d603e7SGreg Roach this.setAttribute('hidden', ''); 19415d603e7SGreg Roach document.getElementById('census-assistant').removeAttribute('hidden'); 19515d603e7SGreg Roach // Set the current individual as the head of household. 19615d603e7SGreg Roach censusAssistantHead(); 19715d603e7SGreg Roach 19815d603e7SGreg Roach return false; 19915d603e7SGreg Roach } 20015d603e7SGreg Roach 20115d603e7SGreg Roach // Add the currently selected individual to the census 20215d603e7SGreg Roach function censusAssistantAdd() { 20315d603e7SGreg Roach var censusSelector = document.querySelector('#census-selector'); 20415d603e7SGreg Roach var census = censusSelector.options[censusSelector.selectedIndex].dataset.census; 20515d603e7SGreg Roach var indi_selector = document.querySelector('#census-assistant-individual'); 20615d603e7SGreg Roach var xref = indi_selector.options[indi_selector.selectedIndex].value; 20715d603e7SGreg Roach var headTd = document.querySelector('#census-assistant-table td'); 20815d603e7SGreg Roach var head = headTd === null ? xref : headTd.innerHTML; 20915d603e7SGreg Roach 21015d603e7SGreg Roach fetch('module.php?mod=GEDFact_assistant&mod_action=census-individual&census=' + census + '&xref=' + xref + '&head=' + head, {credentials: 'same-origin'}) 21115d603e7SGreg Roach .then(function (response) { 21215d603e7SGreg Roach return response.text(); 21315d603e7SGreg Roach }) 21415d603e7SGreg Roach .then(function (text) { 21515d603e7SGreg Roach document.querySelector('#census-assistant-table tbody').innerHTML += text; 21615d603e7SGreg Roach }); 21715d603e7SGreg Roach 21815d603e7SGreg Roach return false; 21915d603e7SGreg Roach } 22015d603e7SGreg Roach 22115d603e7SGreg Roach // Set the currently selected individual as the head of household 22215d603e7SGreg Roach function censusAssistantHead() { 22315d603e7SGreg Roach var censusSelector = document.querySelector('#census-selector'); 22415d603e7SGreg Roach var census = censusSelector.options[censusSelector.selectedIndex].dataset.census; 22515d603e7SGreg Roach var indi_selector = document.querySelector('#census-assistant-individual'); 22615d603e7SGreg Roach var xref = indi_selector.options[indi_selector.selectedIndex].value; 22715d603e7SGreg Roach 22815d603e7SGreg Roach fetch('module.php?mod=GEDFact_assistant&mod_action=census-individual&census=' + census + '&xref=' + xref + '&head=' + xref, {credentials: 'same-origin'}) 22915d603e7SGreg Roach .then(function (response) { 23015d603e7SGreg Roach return response.text(); 23115d603e7SGreg Roach }) 23215d603e7SGreg Roach .then(function (text) { 23315d603e7SGreg Roach document.querySelector('#census-assistant-table tbody').innerHTML = text; 23415d603e7SGreg Roach }); 23515d603e7SGreg Roach 23615d603e7SGreg Roach return false; 23715d603e7SGreg Roach } 23815d603e7SGreg Roach 23915d603e7SGreg Roach document.querySelector('#census-selector').addEventListener('change', censusAssistantSelect); 24015d603e7SGreg Roach document.querySelector('#census-assistant-link').addEventListener('click', censusAssistantLink); 24115d603e7SGreg Roach document.querySelector('#census-assistant-add').addEventListener('click', censusAssistantAdd); 24215d603e7SGreg Roach document.querySelector('#census-assistant-head').addEventListener('click', censusAssistantHead); 24315d603e7SGreg Roach </script> 24415d603e7SGreg Roach <?php 24515d603e7SGreg Roach } 24615d603e7SGreg Roach 24715d603e7SGreg Roach /** 24815d603e7SGreg Roach * @param Individual $individual 24960bc3e3fSGreg Roach * @param string $fact_id 25015d603e7SGreg Roach * @param string $newged 25160bc3e3fSGreg Roach * @param bool $keep_chan 25215d603e7SGreg Roach * 25315d603e7SGreg Roach * @return string 25415d603e7SGreg Roach */ 25515d603e7SGreg Roach public function updateCensusAssistant(Individual $individual, $fact_id, $newged, $keep_chan) { 25615d603e7SGreg Roach $ca_title = Filter::post('ca_title'); 25715d603e7SGreg Roach $ca_place = Filter::post('ca_place'); 25815d603e7SGreg Roach $ca_citation = Filter::post('ca_citation'); 25915d603e7SGreg Roach $ca_individuals = Filter::postArray('ca_individuals'); 26015d603e7SGreg Roach $ca_notes = Filter::post('ca_notes'); 26115d603e7SGreg Roach $ca_census = Filter::post('ca_census', 'Fisharebest\\\\Webtrees\\\\Census\\\\CensusOf[A-Za-z0-9]+'); 26215d603e7SGreg Roach 26315d603e7SGreg Roach if ($ca_census !== '' && !empty($ca_individuals)) { 26415d603e7SGreg Roach $census = new $ca_census; 26515d603e7SGreg Roach 26615d603e7SGreg Roach $note_text = $this->createNoteText($census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes); 26715d603e7SGreg Roach $note_gedcom = '0 @new@ NOTE ' . str_replace("\n", "\n1 CONT ", $note_text); 26815d603e7SGreg Roach $note = $individual->getTree()->createRecord($note_gedcom); 26915d603e7SGreg Roach 27015d603e7SGreg Roach $newged .= "\n2 NOTE @" . $note->getXref() . '@'; 27115d603e7SGreg Roach 27215d603e7SGreg Roach // Add the census fact to the rest of the household 27315d603e7SGreg Roach foreach (array_keys($ca_individuals) as $xref) { 27415d603e7SGreg Roach if ($xref !== $individual->getXref()) { 27515d603e7SGreg Roach Individual::getInstance($xref, $individual->getTree()) 27615d603e7SGreg Roach ->updateFact($fact_id, $newged, !$keep_chan); 27715d603e7SGreg Roach } 27815d603e7SGreg Roach } 27915d603e7SGreg Roach } 28015d603e7SGreg Roach 28115d603e7SGreg Roach return $newged; 28215d603e7SGreg Roach } 28315d603e7SGreg Roach 28415d603e7SGreg Roach /** 28515d603e7SGreg Roach * @param CensusInterface $census 28615d603e7SGreg Roach * @param string $ca_title 28715d603e7SGreg Roach * @param string $ca_place 28815d603e7SGreg Roach * @param string $ca_citation 28915d603e7SGreg Roach * @param string[][] $ca_individuals 29015d603e7SGreg Roach * @param string $ca_notes 29115d603e7SGreg Roach * 29215d603e7SGreg Roach * @return string 29315d603e7SGreg Roach */ 29415d603e7SGreg Roach private function createNoteText(CensusInterface $census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes) { 29515d603e7SGreg Roach $text = $ca_title . "\n" . $ca_citation . "\n" . $ca_place . "\n\n.start_formatted_area.\n\n"; 29615d603e7SGreg Roach 29715d603e7SGreg Roach foreach ($census->columns() as $n => $column) { 29815d603e7SGreg Roach if ($n > 0) { 29915d603e7SGreg Roach $text .= '|'; 30015d603e7SGreg Roach } 30115d603e7SGreg Roach $text .= '.b.' . $column->abbreviation(); 30215d603e7SGreg Roach } 30315d603e7SGreg Roach 30415d603e7SGreg Roach foreach ($ca_individuals as $xref => $columns) { 30515d603e7SGreg Roach $text .= "\n" . implode('|', $columns); 30615d603e7SGreg Roach } 30715d603e7SGreg Roach 30815d603e7SGreg Roach return $text . "\n.end_formatted_area.\n\n" . $ca_notes; 30940990b78SGreg Roach } 31040990b78SGreg Roach 31140990b78SGreg Roach /** 31276692c8bSGreg Roach * Find a media object. 31340990b78SGreg Roach */ 314764a01d9SGreg Roach private static function mediaFind() { 3158c2e8227SGreg Roach global $WT_TREE; 3168c2e8227SGreg Roach 3178c2e8227SGreg Roach $controller = new SimpleController; 3188c2e8227SGreg Roach $filter = Filter::get('filter'); 3198c2e8227SGreg Roach $multiple = Filter::getBool('multiple'); 3208c2e8227SGreg Roach 3218c2e8227SGreg Roach $controller 3228c2e8227SGreg Roach ->setPageTitle(I18N::translate('Find an individual')) 3238c2e8227SGreg Roach ->pageHeader(); 3248c2e8227SGreg Roach 3258c2e8227SGreg Roach ?> 32699f222b3SGreg Roach <script> 3278c2e8227SGreg Roach function pasterow(id, name, gend, yob, age, bpl) { 3288c2e8227SGreg Roach window.opener.opener.insertRowToTable(id, name, '', gend, '', yob, age, 'Y', '', bpl); 3298c2e8227SGreg Roach } 3308c2e8227SGreg Roach 3318c2e8227SGreg Roach function pasteid(id, name, thumb) { 3328c2e8227SGreg Roach if (thumb) { 3338c2e8227SGreg Roach window.opener.paste_id(id, name, thumb); 33415d603e7SGreg Roach <?php if (!$multiple) { 33515d603e7SGreg Roach echo 'window.close();'; 33615d603e7SGreg Roach } ?> 3378c2e8227SGreg Roach } else { 3388c2e8227SGreg Roach // GEDFact_assistant ======================== 3398c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 3408c2e8227SGreg Roach window.opener.insertRowToTable(id, name); 3418c2e8227SGreg Roach } 3428c2e8227SGreg Roach window.opener.paste_id(id); 3438c2e8227SGreg Roach if (window.opener.pastename) { 3448c2e8227SGreg Roach window.opener.pastename(name); 3458c2e8227SGreg Roach } 34615d603e7SGreg Roach <?php if (!$multiple) { 34715d603e7SGreg Roach echo 'window.close();'; 34815d603e7SGreg Roach } ?> 3498c2e8227SGreg Roach } 3508c2e8227SGreg Roach } 35115d603e7SGreg Roach 3528c2e8227SGreg Roach function checknames(frm) { 353*6fde90caSGreg Roach var button = ''; 3548c2e8227SGreg Roach if (document.forms[0].subclick) { 3558c2e8227SGreg Roach button = document.forms[0].subclick.value; 3568c2e8227SGreg Roach } 35715d603e7SGreg Roach if (frm.filter.value.length < 2 && button !== 'all') { 35815d603e7SGreg Roach alert('<?= I18N::translate('Please enter more than one character.') ?>'); 3598c2e8227SGreg Roach frm.filter.focus(); 3608c2e8227SGreg Roach return false; 3618c2e8227SGreg Roach } 362*6fde90caSGreg Roach if (button === 'all') { 36315d603e7SGreg Roach frm.filter.value = ''; 3648c2e8227SGreg Roach } 3658c2e8227SGreg Roach return true; 3668c2e8227SGreg Roach } 36799f222b3SGreg Roach </script> 3688c2e8227SGreg Roach 36999f222b3SGreg Roach <?php 370a86dd8b1SGreg Roach echo '<div>'; 3714c621133SGreg Roach echo '<table class="list_table width90" border="0">'; 372a86dd8b1SGreg Roach echo '<tr><td style="padding: 10px;" class="facts_label03 width90">'; // start column for find text header 3738c2e8227SGreg Roach echo $controller->getPageTitle(); 3744c621133SGreg Roach echo '</td>'; 3754c621133SGreg Roach echo '</tr>'; 3764c621133SGreg Roach echo '</table>'; 3774c621133SGreg Roach echo '<br>'; 3788c2e8227SGreg Roach echo '<button onclick="window.close();">', I18N::translate('close'), '</button>'; 3794c621133SGreg Roach echo '<br>'; 3808c2e8227SGreg Roach 3818c2e8227SGreg Roach $filter = trim($filter); 3828c2e8227SGreg Roach $filter_array = explode(' ', preg_replace('/ {2,}/', ' ', $filter)); 3834c621133SGreg Roach echo '<table class="tabs_table width90"><tr>'; 38413abd6f3SGreg Roach $myindilist = FunctionsDb::searchIndividualNames($filter_array, [$WT_TREE]); 3858c2e8227SGreg Roach if ($myindilist) { 3864c621133SGreg Roach echo '<td class="list_value_wrap"><ul>'; 3870e62c4b8SGreg Roach usort($myindilist, '\Fisharebest\Webtrees\GedcomRecord::compare'); 3888c2e8227SGreg Roach foreach ($myindilist as $indi) { 3898c2e8227SGreg Roach $nam = Filter::escapeHtml($indi->getFullName()); 3908c2e8227SGreg Roach echo "<li><a href=\"#\" onclick=\"pasterow( 3918c2e8227SGreg Roach '" . $indi->getXref() . "' , 3928c2e8227SGreg Roach '" . $nam . "' , 3938c2e8227SGreg Roach '" . $indi->getSex() . "' , 3947820e4d7SGreg Roach '" . $indi->getBirthYear() . "' , 3957820e4d7SGreg Roach '" . (1901 - $indi->getBirthYear()) . "' , 3967820e4d7SGreg Roach '" . $indi->getBirthPlace() . "'); return false;\"> 3977a6ee1acSGreg Roach <b>" . $indi->getFullName() . '</b> '; 3988c2e8227SGreg Roach 399564ae2d7SGreg Roach $born = I18N::translate('Birth'); 4007a6ee1acSGreg Roach echo '</span><br><span class="list_item">', $born, ' ', $indi->getBirthYear(), ' ', $indi->getBirthPlace(), '</span></a></li>'; 4017a6ee1acSGreg Roach echo '<hr>'; 4028c2e8227SGreg Roach } 4038c2e8227SGreg Roach echo '</ul></td></tr><tr><td class="list_label">', I18N::translate('Total individuals: %s', count($myindilist)), '</tr></td>'; 4048c2e8227SGreg Roach } else { 4057a6ee1acSGreg Roach echo '<td class="list_value_wrap">'; 4068c2e8227SGreg Roach echo I18N::translate('No results found.'); 4077a6ee1acSGreg Roach echo '</td></tr>'; 4088c2e8227SGreg Roach } 4097a6ee1acSGreg Roach echo '</table>'; 4108c2e8227SGreg Roach echo '</div>'; 4118c2e8227SGreg Roach } 4128c2e8227SGreg Roach 4138c2e8227SGreg Roach /** 41476692c8bSGreg Roach * Search for a media object. 4158c2e8227SGreg Roach */ 416764a01d9SGreg Roach private static function mediaQuery() { 41724ec66ceSGreg Roach global $WT_TREE; 41824ec66ceSGreg Roach 4198c2e8227SGreg Roach $iid2 = Filter::get('iid', WT_REGEX_XREF); 4208c2e8227SGreg Roach 4218c2e8227SGreg Roach $controller = new SimpleController; 4228c2e8227SGreg Roach $controller 4238c2e8227SGreg Roach ->setPageTitle(I18N::translate('Link to an existing media object')) 4248c2e8227SGreg Roach ->pageHeader(); 4258c2e8227SGreg Roach 42624ec66ceSGreg Roach $record = GedcomRecord::getInstance($iid2, $WT_TREE); 4278c2e8227SGreg Roach if ($record) { 4288c2e8227SGreg Roach $headjs = ''; 4298c2e8227SGreg Roach if ($record instanceof Family) { 4308c2e8227SGreg Roach if ($record->getHusband()) { 4318c2e8227SGreg Roach $headjs = $record->getHusband()->getXref(); 4328c2e8227SGreg Roach } elseif ($record->getWife()) { 4338c2e8227SGreg Roach $headjs = $record->getWife()->getXref(); 4348c2e8227SGreg Roach } 4358c2e8227SGreg Roach } 4368c2e8227SGreg Roach ?> 4378c2e8227SGreg Roach <script> 4388c2e8227SGreg Roach function insertId() { 4398c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 4408c2e8227SGreg Roach // alert('Please move this alert window and examine the contents of the pop-up window, then click OK') 441564ae2d7SGreg Roach window.opener.insertRowToTable('<?= $record->getXref() ?>', '<?= htmlspecialchars($record->getFullName()) ?>', '<?= $headjs ?>'); 4428c2e8227SGreg Roach window.close(); 4438c2e8227SGreg Roach } 4448c2e8227SGreg Roach } 4458c2e8227SGreg Roach </script> 4468c2e8227SGreg Roach <?php 4478c2e8227SGreg Roach } else { 4488c2e8227SGreg Roach ?> 4498c2e8227SGreg Roach <script> 4508c2e8227SGreg Roach function insertId() { 451564ae2d7SGreg Roach window.opener.alert('<?= $iid2 ?> - <?= I18N::translate('Not a valid individual, family, or source ID') ?>'); 4528c2e8227SGreg Roach window.close(); 4538c2e8227SGreg Roach } 4548c2e8227SGreg Roach </script> 4558c2e8227SGreg Roach <?php 4568c2e8227SGreg Roach } 4578c2e8227SGreg Roach ?> 4588c2e8227SGreg Roach <script>window.onLoad = insertId();</script> 4598c2e8227SGreg Roach <?php 4608c2e8227SGreg Roach } 4618c2e8227SGreg Roach 4628c2e8227SGreg Roach /** 4638c2e8227SGreg Roach * Convert custom markup into HTML 4648c2e8227SGreg Roach * 4658c2e8227SGreg Roach * @param Note $note 4668c2e8227SGreg Roach * 4678c2e8227SGreg Roach * @return string 4688c2e8227SGreg Roach */ 4698c2e8227SGreg Roach public static function formatCensusNote(Note $note) { 47014c3d3fbSGreg Roach if (preg_match('/(.*)((?:\n.*)*)\n\.start_formatted_area\.\n(.+)\n(.+(?:\n.+)*)\n.end_formatted_area\.((?:\n.*)*)/', $note->getNote(), $match)) { 4718c2e8227SGreg Roach // This looks like a census-assistant shared note 4728c2e8227SGreg Roach $title = Filter::escapeHtml($match[1]); 4738c2e8227SGreg Roach $preamble = Filter::escapeHtml($match[2]); 4748c2e8227SGreg Roach $header = Filter::escapeHtml($match[3]); 4758c2e8227SGreg Roach $data = Filter::escapeHtml($match[4]); 4768c2e8227SGreg Roach $postamble = Filter::escapeHtml($match[5]); 4778c2e8227SGreg Roach 478dc46b574SDavid Drury // Get the column headers for the census to which this note refers 479dc46b574SDavid Drury // requires the fact place & date to match the specific census 480dc46b574SDavid Drury // censusPlace() (Soundex match) and censusDate() functions 48113abd6f3SGreg Roach $fmt_headers = []; 48215d603e7SGreg Roach /** @var GedcomRecord[] $linkedRecords */ 483dc46b574SDavid Drury $linkedRecords = array_merge($note->linkedIndividuals('NOTE'), $note->linkedFamilies('NOTE')); 484dc46b574SDavid Drury $firstRecord = array_shift($linkedRecords); 485dc46b574SDavid Drury if ($firstRecord) { 486dc46b574SDavid Drury $countryCode = ''; 487dc46b574SDavid Drury $date = ''; 488dc46b574SDavid Drury foreach ($firstRecord->getFacts('CENS') as $fact) { 489dc46b574SDavid Drury if (trim($fact->getAttribute('NOTE'), '@') === $note->getXref()) { 490dc46b574SDavid Drury $date = $fact->getAttribute('DATE'); 491dc46b574SDavid Drury $place = explode(',', strip_tags($fact->getPlace()->getFullName())); 492dc46b574SDavid Drury $countryCode = Soundex::daitchMokotoff(array_pop($place)); 493dc46b574SDavid Drury break; 494dc46b574SDavid Drury } 4958c2e8227SGreg Roach } 4968c2e8227SGreg Roach 497dc46b574SDavid Drury foreach (Census::allCensusPlaces() as $censusPlace) { 498dc46b574SDavid Drury if (Soundex::compare($countryCode, Soundex::daitchMokotoff($censusPlace->censusPlace()))) { 499dc46b574SDavid Drury foreach ($censusPlace->allCensusDates() as $census) { 500dc46b574SDavid Drury if ($census->censusDate() == $date) { 501dc46b574SDavid Drury foreach ($census->columns() as $column) { 502dc46b574SDavid Drury $abbrev = $column->abbreviation(); 503dc46b574SDavid Drury if ($abbrev) { 504dc46b574SDavid Drury $description = $column->title() ? $column->title() : I18N::translate('Description unavailable'); 505dc46b574SDavid Drury $fmt_headers[$abbrev] = '<span title="' . $description . '">' . $abbrev . '</span>'; 506dc46b574SDavid Drury } 507dc46b574SDavid Drury } 508dc46b574SDavid Drury break 2; 509dc46b574SDavid Drury } 510dc46b574SDavid Drury } 511dc46b574SDavid Drury } 512dc46b574SDavid Drury } 513dc46b574SDavid Drury } 514dc46b574SDavid Drury // Substitute header labels and format as HTML 5158c2e8227SGreg Roach $thead = '<tr><th>' . strtr(str_replace('|', '</th><th>', $header), $fmt_headers) . '</th></tr>'; 516ad51e0bbSGreg Roach $thead = str_replace('.b.', '', $thead); 5178c2e8227SGreg Roach 5188c2e8227SGreg Roach // Format data as HTML 5198c2e8227SGreg Roach $tbody = ''; 52014c3d3fbSGreg Roach foreach (explode("\n", $data) as $row) { 5218c2e8227SGreg Roach $tbody .= '<tr>'; 5228c2e8227SGreg Roach foreach (explode('|', $row) as $column) { 5238c2e8227SGreg Roach $tbody .= '<td>' . $column . '</td>'; 5248c2e8227SGreg Roach } 5258c2e8227SGreg Roach $tbody .= '</tr>'; 5268c2e8227SGreg Roach } 5278c2e8227SGreg Roach 5288c2e8227SGreg Roach return 5298c2e8227SGreg Roach $title . "\n" . // The newline allows the framework to expand the details and turn the first line into a link 530673157b0SGreg Roach '<div class="markdown">' . 5318c2e8227SGreg Roach '<p>' . $preamble . '</p>' . 532dc46b574SDavid Drury '<table>' . 5338c2e8227SGreg Roach '<thead>' . $thead . '</thead>' . 5348c2e8227SGreg Roach '<tbody>' . $tbody . '</tbody>' . 5358c2e8227SGreg Roach '</table>' . 536dc46b574SDavid Drury '<p>' . $postamble . '</p>' . 537dc46b574SDavid Drury '</div>'; 5388c2e8227SGreg Roach } else { 5398c2e8227SGreg Roach // Not a census-assistant shared note - apply default formatting 54015d603e7SGreg Roach return Filter::formatText($note->getNote(), $note->getTree()); 5418c2e8227SGreg Roach } 5428c2e8227SGreg Roach } 54399f222b3SGreg Roach 54499f222b3SGreg Roach /** 545ad51e0bbSGreg Roach * Generate an HTML row of data for the census header 54652bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 54752bc9faeSGreg Roach * Add suffix cell (delete button) 54852bc9faeSGreg Roach * 549ad51e0bbSGreg Roach * @param CensusInterface $census 55099f222b3SGreg Roach * 551ad51e0bbSGreg Roach * @return string 55299f222b3SGreg Roach */ 553ad51e0bbSGreg Roach public static function censusTableHeader(CensusInterface $census) { 55452bc9faeSGreg Roach $html = ''; 555ad51e0bbSGreg Roach foreach ($census->columns() as $column) { 55615d603e7SGreg Roach $html .= '<th class="wt-census-assistant-field" title="' . $column->title() . '">' . $column->abbreviation() . '</th>'; 55799f222b3SGreg Roach } 55899f222b3SGreg Roach 55915d603e7SGreg Roach return '<tr class="wt-census-assistant-row"><th hidden></th>' . $html . '<th></th></tr>'; 560ad51e0bbSGreg Roach } 56199f222b3SGreg Roach 562ad51e0bbSGreg Roach /** 563ad51e0bbSGreg Roach * Generate an HTML row of data for the census 56452bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 56552bc9faeSGreg Roach * Add suffix cell (delete button) 56652bc9faeSGreg Roach * 567ad51e0bbSGreg Roach * @param CensusInterface $census 568ad51e0bbSGreg Roach * 569ad51e0bbSGreg Roach * @return string 570ad51e0bbSGreg Roach */ 571ad51e0bbSGreg Roach public static function censusTableEmptyRow(CensusInterface $census) { 57215d603e7SGreg 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>'; 573ad51e0bbSGreg Roach } 57499f222b3SGreg Roach 575ad51e0bbSGreg Roach /** 576ad51e0bbSGreg Roach * Generate an HTML row of data for the census 57752bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 57852bc9faeSGreg Roach * Add suffix cell (delete button) 57952bc9faeSGreg Roach * 580ad51e0bbSGreg Roach * @param CensusInterface $census 581ad51e0bbSGreg Roach * @param Individual $individual 582ad51e0bbSGreg Roach * @param Individual $head 583ad51e0bbSGreg Roach * 584ad51e0bbSGreg Roach * @return string 585ad51e0bbSGreg Roach */ 58615d603e7SGreg Roach public static function censusTableRow(CensusInterface $census, Individual $individual, Individual $head) { 58715d603e7SGreg Roach $html = ''; 58815d603e7SGreg Roach foreach ($census->columns() as $column) { 58915d603e7SGreg 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>'; 59099f222b3SGreg Roach } 59199f222b3SGreg Roach 59215d603e7SGreg 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>'; 59399f222b3SGreg Roach } 5948c2e8227SGreg Roach} 595