18c2e8227SGreg Roach<?php 28c2e8227SGreg Roach/** 38c2e8227SGreg Roach * webtrees: online genealogy 4*1062a142SGreg Roach * Copyright (C) 2018 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; 27047f239bSGreg Roachuse Fisharebest\Webtrees\Html; 280e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 2999f222b3SGreg Roachuse Fisharebest\Webtrees\Individual; 300e62c4b8SGreg Roachuse Fisharebest\Webtrees\Note; 31dc46b574SDavid Druryuse Fisharebest\Webtrees\Soundex; 3234cd602eSGreg Roachuse Fisharebest\Webtrees\View; 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) { 8934cd602eSGreg Roach return View::make('modules/census-assistant', [ 9034cd602eSGreg Roach 'individual' => $individual, 9134cd602eSGreg Roach ]); 9215d603e7SGreg Roach } 9315d603e7SGreg Roach 9415d603e7SGreg Roach /** 9515d603e7SGreg Roach * @param Individual $individual 9660bc3e3fSGreg Roach * @param string $fact_id 9715d603e7SGreg Roach * @param string $newged 9860bc3e3fSGreg Roach * @param bool $keep_chan 9915d603e7SGreg Roach * 10015d603e7SGreg Roach * @return string 10115d603e7SGreg Roach */ 10215d603e7SGreg Roach public function updateCensusAssistant(Individual $individual, $fact_id, $newged, $keep_chan) { 10315d603e7SGreg Roach $ca_title = Filter::post('ca_title'); 10415d603e7SGreg Roach $ca_place = Filter::post('ca_place'); 10515d603e7SGreg Roach $ca_citation = Filter::post('ca_citation'); 10615d603e7SGreg Roach $ca_individuals = Filter::postArray('ca_individuals'); 10715d603e7SGreg Roach $ca_notes = Filter::post('ca_notes'); 10815d603e7SGreg Roach $ca_census = Filter::post('ca_census', 'Fisharebest\\\\Webtrees\\\\Census\\\\CensusOf[A-Za-z0-9]+'); 10915d603e7SGreg Roach 11015d603e7SGreg Roach if ($ca_census !== '' && !empty($ca_individuals)) { 11115d603e7SGreg Roach $census = new $ca_census; 11215d603e7SGreg Roach 11315d603e7SGreg Roach $note_text = $this->createNoteText($census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes); 11415d603e7SGreg Roach $note_gedcom = '0 @new@ NOTE ' . str_replace("\n", "\n1 CONT ", $note_text); 11515d603e7SGreg Roach $note = $individual->getTree()->createRecord($note_gedcom); 11615d603e7SGreg Roach 11715d603e7SGreg Roach $newged .= "\n2 NOTE @" . $note->getXref() . '@'; 11815d603e7SGreg Roach 11915d603e7SGreg Roach // Add the census fact to the rest of the household 12015d603e7SGreg Roach foreach (array_keys($ca_individuals) as $xref) { 12115d603e7SGreg Roach if ($xref !== $individual->getXref()) { 12215d603e7SGreg Roach Individual::getInstance($xref, $individual->getTree()) 12315d603e7SGreg Roach ->updateFact($fact_id, $newged, !$keep_chan); 12415d603e7SGreg Roach } 12515d603e7SGreg Roach } 12615d603e7SGreg Roach } 12715d603e7SGreg Roach 12815d603e7SGreg Roach return $newged; 12915d603e7SGreg Roach } 13015d603e7SGreg Roach 13115d603e7SGreg Roach /** 13215d603e7SGreg Roach * @param CensusInterface $census 13315d603e7SGreg Roach * @param string $ca_title 13415d603e7SGreg Roach * @param string $ca_place 13515d603e7SGreg Roach * @param string $ca_citation 13615d603e7SGreg Roach * @param string[][] $ca_individuals 13715d603e7SGreg Roach * @param string $ca_notes 13815d603e7SGreg Roach * 13915d603e7SGreg Roach * @return string 14015d603e7SGreg Roach */ 14115d603e7SGreg Roach private function createNoteText(CensusInterface $census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes) { 1420d46ec71SGreg Roach $text = $ca_title . "\n" . $ca_citation . "\n" . $ca_place . "\n\n"; 14315d603e7SGreg Roach 14415d603e7SGreg Roach foreach ($census->columns() as $n => $column) { 1450d46ec71SGreg Roach if ($n === 0) { 1460d46ec71SGreg Roach $text .= "\n"; 1470d46ec71SGreg Roach } else { 14815d603e7SGreg Roach $text .= ' | '; 14915d603e7SGreg Roach } 1500d46ec71SGreg Roach $text .= $column->abbreviation(); 1510d46ec71SGreg Roach } 1520d46ec71SGreg Roach 1530d46ec71SGreg Roach foreach ($census->columns() as $n => $column) { 1540d46ec71SGreg Roach if ($n === 0) { 1550d46ec71SGreg Roach $text .= "\n"; 1560d46ec71SGreg Roach } else { 1570d46ec71SGreg Roach $text .= ' | '; 1580d46ec71SGreg Roach } 1590d46ec71SGreg Roach $text .= '-----'; 16015d603e7SGreg Roach } 16115d603e7SGreg Roach 16215d603e7SGreg Roach foreach ($ca_individuals as $xref => $columns) { 16315d603e7SGreg Roach $text .= "\n" . implode(' | ', $columns); 16415d603e7SGreg Roach } 16515d603e7SGreg Roach 1660d46ec71SGreg Roach return $text . "\n\n" . $ca_notes; 16740990b78SGreg Roach } 16840990b78SGreg Roach 16940990b78SGreg Roach /** 17076692c8bSGreg Roach * Find a media object. 17140990b78SGreg Roach */ 172764a01d9SGreg Roach private static function mediaFind() { 1738c2e8227SGreg Roach global $WT_TREE; 1748c2e8227SGreg Roach 1758c2e8227SGreg Roach $controller = new SimpleController; 1768c2e8227SGreg Roach $filter = Filter::get('filter'); 1778c2e8227SGreg Roach $multiple = Filter::getBool('multiple'); 1788c2e8227SGreg Roach 1798c2e8227SGreg Roach $controller 1808c2e8227SGreg Roach ->setPageTitle(I18N::translate('Find an individual')) 1818c2e8227SGreg Roach ->pageHeader(); 1828c2e8227SGreg Roach 1838c2e8227SGreg Roach ?> 18499f222b3SGreg Roach <script> 1858c2e8227SGreg Roach function pasterow(id, name, gend, yob, age, bpl) { 1868c2e8227SGreg Roach window.opener.opener.insertRowToTable(id, name, '', gend, '', yob, age, 'Y', '', bpl); 1878c2e8227SGreg Roach } 1888c2e8227SGreg Roach 1898c2e8227SGreg Roach function pasteid(id, name, thumb) { 1908c2e8227SGreg Roach if (thumb) { 1918c2e8227SGreg Roach window.opener.paste_id(id, name, thumb); 19215d603e7SGreg Roach <?php if (!$multiple) { 19315d603e7SGreg Roach echo 'window.close();'; 19415d603e7SGreg Roach } ?> 1958c2e8227SGreg Roach } else { 1968c2e8227SGreg Roach // GEDFact_assistant ======================== 1978c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 1988c2e8227SGreg Roach window.opener.insertRowToTable(id, name); 1998c2e8227SGreg Roach } 2008c2e8227SGreg Roach window.opener.paste_id(id); 2018c2e8227SGreg Roach if (window.opener.pastename) { 2028c2e8227SGreg Roach window.opener.pastename(name); 2038c2e8227SGreg Roach } 20415d603e7SGreg Roach <?php if (!$multiple) { 20515d603e7SGreg Roach echo 'window.close();'; 20615d603e7SGreg Roach } ?> 2078c2e8227SGreg Roach } 2088c2e8227SGreg Roach } 20915d603e7SGreg Roach 2108c2e8227SGreg Roach function checknames(frm) { 2116fde90caSGreg Roach var button = ''; 2128c2e8227SGreg Roach if (document.forms[0].subclick) { 2138c2e8227SGreg Roach button = document.forms[0].subclick.value; 2148c2e8227SGreg Roach } 21515d603e7SGreg Roach if (frm.filter.value.length < 2 && button !== 'all') { 21615d603e7SGreg Roach alert('<?= I18N::translate('Please enter more than one character.') ?>'); 2178c2e8227SGreg Roach frm.filter.focus(); 2188c2e8227SGreg Roach return false; 2198c2e8227SGreg Roach } 2206fde90caSGreg Roach if (button === 'all') { 22115d603e7SGreg Roach frm.filter.value = ''; 2228c2e8227SGreg Roach } 2238c2e8227SGreg Roach return true; 2248c2e8227SGreg Roach } 22599f222b3SGreg Roach </script> 2268c2e8227SGreg Roach 22799f222b3SGreg Roach <?php 228a86dd8b1SGreg Roach echo '<div>'; 2294c621133SGreg Roach echo '<table class="list_table width90" border="0">'; 230d20fc238SGreg Roach echo '<tr><td style="padding: 10px;" class="width90">'; // start column for find text header 2318c2e8227SGreg Roach echo $controller->getPageTitle(); 2324c621133SGreg Roach echo '</td>'; 2334c621133SGreg Roach echo '</tr>'; 2344c621133SGreg Roach echo '</table>'; 2354c621133SGreg Roach echo '<br>'; 2368c2e8227SGreg Roach echo '<button onclick="window.close();">', I18N::translate('close'), '</button>'; 2374c621133SGreg Roach echo '<br>'; 2388c2e8227SGreg Roach 2398c2e8227SGreg Roach $filter = trim($filter); 2408c2e8227SGreg Roach $filter_array = explode(' ', preg_replace('/ {2,}/', ' ', $filter)); 2414c621133SGreg Roach echo '<table class="tabs_table width90"><tr>'; 24213abd6f3SGreg Roach $myindilist = FunctionsDb::searchIndividualNames($filter_array, [$WT_TREE]); 2438c2e8227SGreg Roach if ($myindilist) { 2444c621133SGreg Roach echo '<td class="list_value_wrap"><ul>'; 2450e62c4b8SGreg Roach usort($myindilist, '\Fisharebest\Webtrees\GedcomRecord::compare'); 2468c2e8227SGreg Roach foreach ($myindilist as $indi) { 247d53324c9SGreg Roach $nam = e($indi->getFullName()); 2488c2e8227SGreg Roach echo "<li><a href=\"#\" onclick=\"pasterow( 2498c2e8227SGreg Roach '" . $indi->getXref() . "' , 2508c2e8227SGreg Roach '" . $nam . "' , 2518c2e8227SGreg Roach '" . $indi->getSex() . "' , 2527820e4d7SGreg Roach '" . $indi->getBirthYear() . "' , 2537820e4d7SGreg Roach '" . (1901 - $indi->getBirthYear()) . "' , 25416d0b7f7SRico Sonntag '" . $indi->getBirthPlace()->getGedcomName() . "'); return false;\"> 2557a6ee1acSGreg Roach <b>" . $indi->getFullName() . '</b> '; 2568c2e8227SGreg Roach 257564ae2d7SGreg Roach $born = I18N::translate('Birth'); 25816d0b7f7SRico Sonntag echo '</span><br><span class="list_item">', $born, ' ', $indi->getBirthYear(), ' ', $indi->getBirthPlace()->getGedcomName(), '</span></a></li>'; 2597a6ee1acSGreg Roach echo '<hr>'; 2608c2e8227SGreg Roach } 2618c2e8227SGreg Roach echo '</ul></td></tr><tr><td class="list_label">', I18N::translate('Total individuals: %s', count($myindilist)), '</tr></td>'; 2628c2e8227SGreg Roach } else { 2637a6ee1acSGreg Roach echo '<td class="list_value_wrap">'; 2648c2e8227SGreg Roach echo I18N::translate('No results found.'); 2657a6ee1acSGreg Roach echo '</td></tr>'; 2668c2e8227SGreg Roach } 2677a6ee1acSGreg Roach echo '</table>'; 2688c2e8227SGreg Roach echo '</div>'; 2698c2e8227SGreg Roach } 2708c2e8227SGreg Roach 2718c2e8227SGreg Roach /** 27276692c8bSGreg Roach * Search for a media object. 2738c2e8227SGreg Roach */ 274764a01d9SGreg Roach private static function mediaQuery() { 27524ec66ceSGreg Roach global $WT_TREE; 27624ec66ceSGreg Roach 2778c2e8227SGreg Roach $iid2 = Filter::get('iid', WT_REGEX_XREF); 2788c2e8227SGreg Roach 2798c2e8227SGreg Roach $controller = new SimpleController; 2808c2e8227SGreg Roach $controller 2818c2e8227SGreg Roach ->setPageTitle(I18N::translate('Link to an existing media object')) 2828c2e8227SGreg Roach ->pageHeader(); 2838c2e8227SGreg Roach 28424ec66ceSGreg Roach $record = GedcomRecord::getInstance($iid2, $WT_TREE); 2858c2e8227SGreg Roach if ($record) { 2868c2e8227SGreg Roach $headjs = ''; 2878c2e8227SGreg Roach if ($record instanceof Family) { 2888c2e8227SGreg Roach if ($record->getHusband()) { 2898c2e8227SGreg Roach $headjs = $record->getHusband()->getXref(); 2908c2e8227SGreg Roach } elseif ($record->getWife()) { 2918c2e8227SGreg Roach $headjs = $record->getWife()->getXref(); 2928c2e8227SGreg Roach } 2938c2e8227SGreg Roach } 2948c2e8227SGreg Roach ?> 2958c2e8227SGreg Roach <script> 2968c2e8227SGreg Roach function insertId() { 2978c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 2988c2e8227SGreg Roach // alert('Please move this alert window and examine the contents of the pop-up window, then click OK') 299564ae2d7SGreg Roach window.opener.insertRowToTable('<?= $record->getXref() ?>', '<?= htmlspecialchars($record->getFullName()) ?>', '<?= $headjs ?>'); 3008c2e8227SGreg Roach window.close(); 3018c2e8227SGreg Roach } 3028c2e8227SGreg Roach } 3038c2e8227SGreg Roach </script> 3048c2e8227SGreg Roach <?php 3058c2e8227SGreg Roach } else { 3068c2e8227SGreg Roach ?> 3078c2e8227SGreg Roach <script> 3088c2e8227SGreg Roach function insertId() { 309564ae2d7SGreg Roach window.opener.alert('<?= $iid2 ?> - <?= I18N::translate('Not a valid individual, family, or source ID') ?>'); 3108c2e8227SGreg Roach window.close(); 3118c2e8227SGreg Roach } 3128c2e8227SGreg Roach </script> 3138c2e8227SGreg Roach <?php 3148c2e8227SGreg Roach } 3158c2e8227SGreg Roach ?> 3168c2e8227SGreg Roach <script>window.onLoad = insertId();</script> 3178c2e8227SGreg Roach <?php 3188c2e8227SGreg Roach } 3198c2e8227SGreg Roach 3208c2e8227SGreg Roach /** 321ad51e0bbSGreg Roach * Generate an HTML row of data for the census header 32252bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 32352bc9faeSGreg Roach * Add suffix cell (delete button) 32452bc9faeSGreg Roach * 325ad51e0bbSGreg Roach * @param CensusInterface $census 32699f222b3SGreg Roach * 327ad51e0bbSGreg Roach * @return string 32899f222b3SGreg Roach */ 329ad51e0bbSGreg Roach public static function censusTableHeader(CensusInterface $census) { 33052bc9faeSGreg Roach $html = ''; 331ad51e0bbSGreg Roach foreach ($census->columns() as $column) { 33215d603e7SGreg Roach $html .= '<th class="wt-census-assistant-field" title="' . $column->title() . '">' . $column->abbreviation() . '</th>'; 33399f222b3SGreg Roach } 33499f222b3SGreg Roach 33515d603e7SGreg Roach return '<tr class="wt-census-assistant-row"><th hidden></th>' . $html . '<th></th></tr>'; 336ad51e0bbSGreg Roach } 33799f222b3SGreg Roach 338ad51e0bbSGreg Roach /** 339ad51e0bbSGreg Roach * Generate an HTML row of data for the census 34052bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 34152bc9faeSGreg Roach * Add suffix cell (delete button) 34252bc9faeSGreg Roach * 343ad51e0bbSGreg Roach * @param CensusInterface $census 344ad51e0bbSGreg Roach * 345ad51e0bbSGreg Roach * @return string 346ad51e0bbSGreg Roach */ 347ad51e0bbSGreg Roach public static function censusTableEmptyRow(CensusInterface $census) { 34815d603e7SGreg 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>'; 349ad51e0bbSGreg Roach } 35099f222b3SGreg Roach 351ad51e0bbSGreg Roach /** 352ad51e0bbSGreg Roach * Generate an HTML row of data for the census 35352bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 35452bc9faeSGreg Roach * Add suffix cell (delete button) 35552bc9faeSGreg Roach * 356ad51e0bbSGreg Roach * @param CensusInterface $census 357ad51e0bbSGreg Roach * @param Individual $individual 358ad51e0bbSGreg Roach * @param Individual $head 359ad51e0bbSGreg Roach * 360ad51e0bbSGreg Roach * @return string 361ad51e0bbSGreg Roach */ 36215d603e7SGreg Roach public static function censusTableRow(CensusInterface $census, Individual $individual, Individual $head) { 36315d603e7SGreg Roach $html = ''; 36415d603e7SGreg Roach foreach ($census->columns() as $column) { 36515d603e7SGreg 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>'; 36699f222b3SGreg Roach } 36799f222b3SGreg Roach 36815d603e7SGreg 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>'; 36999f222b3SGreg Roach } 3708c2e8227SGreg Roach} 371