18c2e8227SGreg Roach<?php 28c2e8227SGreg Roach/** 38c2e8227SGreg Roach * webtrees: online genealogy 41062a142SGreg 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; 233d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsDb; 240e62c4b8SGreg Roachuse Fisharebest\Webtrees\GedcomRecord; 250e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 2699f222b3SGreg Roachuse Fisharebest\Webtrees\Individual; 27*9001c0b3SGreg Roachuse Fisharebest\Webtrees\Tree; 28*9001c0b3SGreg Roachuse Symfony\Component\HttpFoundation\Request; 29*9001c0b3SGreg Roachuse Symfony\Component\HttpFoundation\Response; 308c2e8227SGreg Roach 318c2e8227SGreg Roach/** 328c2e8227SGreg Roach * Class CensusAssistantModule 338c2e8227SGreg Roach */ 3415834aaeSGreg Roachclass CensusAssistantModule extends AbstractModule { 358c2e8227SGreg Roach /** {@inheritdoc} */ 368c2e8227SGreg Roach public function getTitle() { 3715d603e7SGreg Roach return /* I18N: Name of a module */ 3815d603e7SGreg Roach I18N::translate('Census assistant'); 398c2e8227SGreg Roach } 408c2e8227SGreg Roach 418c2e8227SGreg Roach /** {@inheritdoc} */ 428c2e8227SGreg Roach public function getDescription() { 4315d603e7SGreg Roach return /* I18N: Description of the “Census assistant” module */ 4415d603e7SGreg Roach I18N::translate('An alternative way to enter census transcripts and link them to individuals.'); 458c2e8227SGreg Roach } 468c2e8227SGreg Roach 4776692c8bSGreg Roach /** 48*9001c0b3SGreg Roach * @param Request $request 49*9001c0b3SGreg Roach * 50*9001c0b3SGreg Roach * @return Response 51*9001c0b3SGreg Roach */ 52*9001c0b3SGreg Roach public function getCensusHeaderAction(Request $request): Response { 53*9001c0b3SGreg Roach $census = $request->get('census'); 54*9001c0b3SGreg Roach 55*9001c0b3SGreg Roach $html = $this->censusTableHeader(new $census); 56*9001c0b3SGreg Roach 57*9001c0b3SGreg Roach return new Response($html); 58*9001c0b3SGreg Roach } 59*9001c0b3SGreg Roach 60*9001c0b3SGreg Roach /** 61*9001c0b3SGreg Roach * @param Request $request 62*9001c0b3SGreg Roach * 63*9001c0b3SGreg Roach * @return Response 64*9001c0b3SGreg Roach */ 65*9001c0b3SGreg Roach public function getCensusIndividualAction(Request $request): Response { 66*9001c0b3SGreg Roach /** @var Tree $tree */ 67*9001c0b3SGreg Roach $tree = $request->attributes->get('tree'); 68*9001c0b3SGreg Roach 69*9001c0b3SGreg Roach $census = $request->get('census'); 70*9001c0b3SGreg Roach 71*9001c0b3SGreg Roach $individual = Individual::getInstance($request->get('xref'), $tree); 72*9001c0b3SGreg Roach $head = Individual::getInstance($request->get('head'), $tree); 73*9001c0b3SGreg Roach $html = $this->censusTableRow(new $census, $individual, $head); 74*9001c0b3SGreg Roach 75*9001c0b3SGreg Roach return new Response($html); 76*9001c0b3SGreg Roach } 77*9001c0b3SGreg Roach 78*9001c0b3SGreg Roach /** 7976692c8bSGreg Roach * This is a general purpose hook, allowing modules to respond to routes 8076692c8bSGreg Roach * of the form module.php?mod=FOO&mod_action=BAR 8176692c8bSGreg Roach * 8276692c8bSGreg Roach * @param string $mod_action 8376692c8bSGreg Roach */ 848c2e8227SGreg Roach public function modAction($mod_action) { 858c2e8227SGreg Roach switch ($mod_action) { 8640990b78SGreg Roach case 'media_find': 87764a01d9SGreg Roach self::mediaFind(); 888c2e8227SGreg Roach break; 898c2e8227SGreg Roach case 'media_query_3a': 90764a01d9SGreg Roach self::mediaQuery(); 918c2e8227SGreg Roach break; 928c2e8227SGreg Roach default: 938c2e8227SGreg Roach http_response_code(404); 948c2e8227SGreg Roach } 958c2e8227SGreg Roach } 968c2e8227SGreg Roach 978c2e8227SGreg Roach /** 9815d603e7SGreg Roach * @param Individual $individual 99*9001c0b3SGreg Roach * 100*9001c0b3SGreg Roach * @return string 1018c2e8227SGreg Roach */ 10215d603e7SGreg Roach public function createCensusAssistant(Individual $individual) { 103225e381fSGreg Roach return view('modules/census-assistant', [ 10434cd602eSGreg Roach 'individual' => $individual, 10534cd602eSGreg Roach ]); 10615d603e7SGreg Roach } 10715d603e7SGreg Roach 10815d603e7SGreg Roach /** 10915d603e7SGreg Roach * @param Individual $individual 11060bc3e3fSGreg Roach * @param string $fact_id 11115d603e7SGreg Roach * @param string $newged 11260bc3e3fSGreg Roach * @param bool $keep_chan 11315d603e7SGreg Roach * 11415d603e7SGreg Roach * @return string 11515d603e7SGreg Roach */ 11615d603e7SGreg Roach public function updateCensusAssistant(Individual $individual, $fact_id, $newged, $keep_chan) { 11715d603e7SGreg Roach $ca_title = Filter::post('ca_title'); 11815d603e7SGreg Roach $ca_place = Filter::post('ca_place'); 11915d603e7SGreg Roach $ca_citation = Filter::post('ca_citation'); 12015d603e7SGreg Roach $ca_individuals = Filter::postArray('ca_individuals'); 12115d603e7SGreg Roach $ca_notes = Filter::post('ca_notes'); 12215d603e7SGreg Roach $ca_census = Filter::post('ca_census', 'Fisharebest\\\\Webtrees\\\\Census\\\\CensusOf[A-Za-z0-9]+'); 12315d603e7SGreg Roach 12415d603e7SGreg Roach if ($ca_census !== '' && !empty($ca_individuals)) { 12515d603e7SGreg Roach $census = new $ca_census; 12615d603e7SGreg Roach 12715d603e7SGreg Roach $note_text = $this->createNoteText($census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes); 12815d603e7SGreg Roach $note_gedcom = '0 @new@ NOTE ' . str_replace("\n", "\n1 CONT ", $note_text); 12915d603e7SGreg Roach $note = $individual->getTree()->createRecord($note_gedcom); 13015d603e7SGreg Roach 13115d603e7SGreg Roach $newged .= "\n2 NOTE @" . $note->getXref() . '@'; 13215d603e7SGreg Roach 13315d603e7SGreg Roach // Add the census fact to the rest of the household 13415d603e7SGreg Roach foreach (array_keys($ca_individuals) as $xref) { 13515d603e7SGreg Roach if ($xref !== $individual->getXref()) { 13615d603e7SGreg Roach Individual::getInstance($xref, $individual->getTree()) 13715d603e7SGreg Roach ->updateFact($fact_id, $newged, !$keep_chan); 13815d603e7SGreg Roach } 13915d603e7SGreg Roach } 14015d603e7SGreg Roach } 14115d603e7SGreg Roach 14215d603e7SGreg Roach return $newged; 14315d603e7SGreg Roach } 14415d603e7SGreg Roach 14515d603e7SGreg Roach /** 14615d603e7SGreg Roach * @param CensusInterface $census 14715d603e7SGreg Roach * @param string $ca_title 14815d603e7SGreg Roach * @param string $ca_place 14915d603e7SGreg Roach * @param string $ca_citation 15015d603e7SGreg Roach * @param string[][] $ca_individuals 15115d603e7SGreg Roach * @param string $ca_notes 15215d603e7SGreg Roach * 15315d603e7SGreg Roach * @return string 15415d603e7SGreg Roach */ 15515d603e7SGreg Roach private function createNoteText(CensusInterface $census, $ca_title, $ca_place, $ca_citation, $ca_individuals, $ca_notes) { 1560d46ec71SGreg Roach $text = $ca_title . "\n" . $ca_citation . "\n" . $ca_place . "\n\n"; 15715d603e7SGreg Roach 15815d603e7SGreg Roach foreach ($census->columns() as $n => $column) { 1590d46ec71SGreg Roach if ($n === 0) { 1600d46ec71SGreg Roach $text .= "\n"; 1610d46ec71SGreg Roach } else { 16215d603e7SGreg Roach $text .= ' | '; 16315d603e7SGreg Roach } 1640d46ec71SGreg Roach $text .= $column->abbreviation(); 1650d46ec71SGreg Roach } 1660d46ec71SGreg Roach 1670d46ec71SGreg Roach foreach ($census->columns() as $n => $column) { 1680d46ec71SGreg Roach if ($n === 0) { 1690d46ec71SGreg Roach $text .= "\n"; 1700d46ec71SGreg Roach } else { 1710d46ec71SGreg Roach $text .= ' | '; 1720d46ec71SGreg Roach } 1730d46ec71SGreg Roach $text .= '-----'; 17415d603e7SGreg Roach } 17515d603e7SGreg Roach 17615d603e7SGreg Roach foreach ($ca_individuals as $xref => $columns) { 17715d603e7SGreg Roach $text .= "\n" . implode(' | ', $columns); 17815d603e7SGreg Roach } 17915d603e7SGreg Roach 1800d46ec71SGreg Roach return $text . "\n\n" . $ca_notes; 18140990b78SGreg Roach } 18240990b78SGreg Roach 18340990b78SGreg Roach /** 18476692c8bSGreg Roach * Find a media object. 18540990b78SGreg Roach */ 186764a01d9SGreg Roach private static function mediaFind() { 1878c2e8227SGreg Roach global $WT_TREE; 1888c2e8227SGreg Roach 1898c2e8227SGreg Roach $controller = new SimpleController; 1908c2e8227SGreg Roach $filter = Filter::get('filter'); 1918c2e8227SGreg Roach $multiple = Filter::getBool('multiple'); 1928c2e8227SGreg Roach 1938c2e8227SGreg Roach $controller 1948c2e8227SGreg Roach ->setPageTitle(I18N::translate('Find an individual')) 1958c2e8227SGreg Roach ->pageHeader(); 1968c2e8227SGreg Roach 1978c2e8227SGreg Roach ?> 19899f222b3SGreg Roach <script> 1998c2e8227SGreg Roach function pasterow(id, name, gend, yob, age, bpl) { 200*9001c0b3SGreg Roach window.opener.opener.insertRowToTable(id, name, "", gend, "", yob, age, "Y", "", bpl); 2018c2e8227SGreg Roach } 2028c2e8227SGreg Roach 2038c2e8227SGreg Roach function pasteid(id, name, thumb) { 2048c2e8227SGreg Roach if (thumb) { 2058c2e8227SGreg Roach window.opener.paste_id(id, name, thumb); 20615d603e7SGreg Roach <?php if (!$multiple) { 20715d603e7SGreg Roach echo 'window.close();'; 20815d603e7SGreg Roach } ?> 2098c2e8227SGreg Roach } else { 2108c2e8227SGreg Roach // GEDFact_assistant ======================== 211*9001c0b3SGreg Roach if (window.opener.document.getElementById("addlinkQueue")) { 2128c2e8227SGreg Roach window.opener.insertRowToTable(id, name); 2138c2e8227SGreg Roach } 2148c2e8227SGreg Roach window.opener.paste_id(id); 2158c2e8227SGreg Roach if (window.opener.pastename) { 2168c2e8227SGreg Roach window.opener.pastename(name); 2178c2e8227SGreg Roach } 21815d603e7SGreg Roach <?php if (!$multiple) { 21915d603e7SGreg Roach echo 'window.close();'; 22015d603e7SGreg Roach } ?> 2218c2e8227SGreg Roach } 2228c2e8227SGreg Roach } 22315d603e7SGreg Roach 2248c2e8227SGreg Roach function checknames(frm) { 225*9001c0b3SGreg Roach var button = ""; 2268c2e8227SGreg Roach if (document.forms[0].subclick) { 2278c2e8227SGreg Roach button = document.forms[0].subclick.value; 2288c2e8227SGreg Roach } 229*9001c0b3SGreg Roach if (frm.filter.value.length < 2 && button !== "all") { 23015d603e7SGreg Roach alert('<?= I18N::translate('Please enter more than one character.') ?>'); 2318c2e8227SGreg Roach frm.filter.focus(); 2328c2e8227SGreg Roach return false; 2338c2e8227SGreg Roach } 234*9001c0b3SGreg Roach if (button === "all") { 235*9001c0b3SGreg Roach frm.filter.value = ""; 2368c2e8227SGreg Roach } 2378c2e8227SGreg Roach return true; 2388c2e8227SGreg Roach } 23999f222b3SGreg Roach </script> 2408c2e8227SGreg Roach 24199f222b3SGreg Roach <?php 242a86dd8b1SGreg Roach echo '<div>'; 2434c621133SGreg Roach echo '<table class="list_table width90" border="0">'; 244d20fc238SGreg Roach echo '<tr><td style="padding: 10px;" class="width90">'; // start column for find text header 2458c2e8227SGreg Roach echo $controller->getPageTitle(); 2464c621133SGreg Roach echo '</td>'; 2474c621133SGreg Roach echo '</tr>'; 2484c621133SGreg Roach echo '</table>'; 2494c621133SGreg Roach echo '<br>'; 2508c2e8227SGreg Roach echo '<button onclick="window.close();">', I18N::translate('close'), '</button>'; 2514c621133SGreg Roach echo '<br>'; 2528c2e8227SGreg Roach 2538c2e8227SGreg Roach $filter = trim($filter); 2548c2e8227SGreg Roach $filter_array = explode(' ', preg_replace('/ {2,}/', ' ', $filter)); 2554c621133SGreg Roach echo '<table class="tabs_table width90"><tr>'; 25613abd6f3SGreg Roach $myindilist = FunctionsDb::searchIndividualNames($filter_array, [$WT_TREE]); 2578c2e8227SGreg Roach if ($myindilist) { 2584c621133SGreg Roach echo '<td class="list_value_wrap"><ul>'; 2590e62c4b8SGreg Roach usort($myindilist, '\Fisharebest\Webtrees\GedcomRecord::compare'); 2608c2e8227SGreg Roach foreach ($myindilist as $indi) { 261d53324c9SGreg Roach $nam = e($indi->getFullName()); 2628c2e8227SGreg Roach echo "<li><a href=\"#\" onclick=\"pasterow( 2638c2e8227SGreg Roach '" . $indi->getXref() . "' , 2648c2e8227SGreg Roach '" . $nam . "' , 2658c2e8227SGreg Roach '" . $indi->getSex() . "' , 2667820e4d7SGreg Roach '" . $indi->getBirthYear() . "' , 2677820e4d7SGreg Roach '" . (1901 - $indi->getBirthYear()) . "' , 26816d0b7f7SRico Sonntag '" . $indi->getBirthPlace()->getGedcomName() . "'); return false;\"> 2697a6ee1acSGreg Roach <b>" . $indi->getFullName() . '</b> '; 2708c2e8227SGreg Roach 271564ae2d7SGreg Roach $born = I18N::translate('Birth'); 27216d0b7f7SRico Sonntag echo '</span><br><span class="list_item">', $born, ' ', $indi->getBirthYear(), ' ', $indi->getBirthPlace()->getGedcomName(), '</span></a></li>'; 2737a6ee1acSGreg Roach echo '<hr>'; 2748c2e8227SGreg Roach } 2758c2e8227SGreg Roach echo '</ul></td></tr><tr><td class="list_label">', I18N::translate('Total individuals: %s', count($myindilist)), '</tr></td>'; 2768c2e8227SGreg Roach } else { 2777a6ee1acSGreg Roach echo '<td class="list_value_wrap">'; 2788c2e8227SGreg Roach echo I18N::translate('No results found.'); 2797a6ee1acSGreg Roach echo '</td></tr>'; 2808c2e8227SGreg Roach } 2817a6ee1acSGreg Roach echo '</table>'; 2828c2e8227SGreg Roach echo '</div>'; 2838c2e8227SGreg Roach } 2848c2e8227SGreg Roach 2858c2e8227SGreg Roach /** 28676692c8bSGreg Roach * Search for a media object. 2878c2e8227SGreg Roach */ 288764a01d9SGreg Roach private static function mediaQuery() { 28924ec66ceSGreg Roach global $WT_TREE; 29024ec66ceSGreg Roach 2918c2e8227SGreg Roach $iid2 = Filter::get('iid', WT_REGEX_XREF); 2928c2e8227SGreg Roach 2938c2e8227SGreg Roach $controller = new SimpleController; 2948c2e8227SGreg Roach $controller 2958c2e8227SGreg Roach ->setPageTitle(I18N::translate('Link to an existing media object')) 2968c2e8227SGreg Roach ->pageHeader(); 2978c2e8227SGreg Roach 29824ec66ceSGreg Roach $record = GedcomRecord::getInstance($iid2, $WT_TREE); 2998c2e8227SGreg Roach if ($record) { 3008c2e8227SGreg Roach $headjs = ''; 3018c2e8227SGreg Roach if ($record instanceof Family) { 3028c2e8227SGreg Roach if ($record->getHusband()) { 3038c2e8227SGreg Roach $headjs = $record->getHusband()->getXref(); 3048c2e8227SGreg Roach } elseif ($record->getWife()) { 3058c2e8227SGreg Roach $headjs = $record->getWife()->getXref(); 3068c2e8227SGreg Roach } 3078c2e8227SGreg Roach } 3088c2e8227SGreg Roach ?> 3098c2e8227SGreg Roach <script> 3108c2e8227SGreg Roach function insertId() { 3118c2e8227SGreg Roach if (window.opener.document.getElementById('addlinkQueue')) { 3128c2e8227SGreg Roach // alert('Please move this alert window and examine the contents of the pop-up window, then click OK') 313564ae2d7SGreg Roach window.opener.insertRowToTable('<?= $record->getXref() ?>', '<?= htmlspecialchars($record->getFullName()) ?>', '<?= $headjs ?>'); 3148c2e8227SGreg Roach window.close(); 3158c2e8227SGreg Roach } 3168c2e8227SGreg Roach } 3178c2e8227SGreg Roach </script> 3188c2e8227SGreg Roach <?php 3198c2e8227SGreg Roach } else { 3208c2e8227SGreg Roach ?> 3218c2e8227SGreg Roach <script> 3228c2e8227SGreg Roach function insertId() { 323564ae2d7SGreg Roach window.opener.alert('<?= $iid2 ?> - <?= I18N::translate('Not a valid individual, family, or source ID') ?>'); 3248c2e8227SGreg Roach window.close(); 3258c2e8227SGreg Roach } 3268c2e8227SGreg Roach </script> 3278c2e8227SGreg Roach <?php 3288c2e8227SGreg Roach } 3298c2e8227SGreg Roach ?> 3308c2e8227SGreg Roach <script>window.onLoad = insertId();</script> 3318c2e8227SGreg Roach <?php 3328c2e8227SGreg Roach } 3338c2e8227SGreg Roach 3348c2e8227SGreg Roach /** 335ad51e0bbSGreg Roach * Generate an HTML row of data for the census header 33652bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 33752bc9faeSGreg Roach * Add suffix cell (delete button) 33852bc9faeSGreg Roach * 339ad51e0bbSGreg Roach * @param CensusInterface $census 34099f222b3SGreg Roach * 341ad51e0bbSGreg Roach * @return string 34299f222b3SGreg Roach */ 343ad51e0bbSGreg Roach public static function censusTableHeader(CensusInterface $census) { 34452bc9faeSGreg Roach $html = ''; 345ad51e0bbSGreg Roach foreach ($census->columns() as $column) { 34615d603e7SGreg Roach $html .= '<th class="wt-census-assistant-field" title="' . $column->title() . '">' . $column->abbreviation() . '</th>'; 34799f222b3SGreg Roach } 34899f222b3SGreg Roach 34915d603e7SGreg Roach return '<tr class="wt-census-assistant-row"><th hidden></th>' . $html . '<th></th></tr>'; 350ad51e0bbSGreg Roach } 35199f222b3SGreg Roach 352ad51e0bbSGreg Roach /** 353ad51e0bbSGreg Roach * Generate an HTML row of data for the census 35452bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 35552bc9faeSGreg Roach * Add suffix cell (delete button) 35652bc9faeSGreg Roach * 357ad51e0bbSGreg Roach * @param CensusInterface $census 358ad51e0bbSGreg Roach * 359ad51e0bbSGreg Roach * @return string 360ad51e0bbSGreg Roach */ 361ad51e0bbSGreg Roach public static function censusTableEmptyRow(CensusInterface $census) { 36215d603e7SGreg 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>'; 363ad51e0bbSGreg Roach } 36499f222b3SGreg Roach 365ad51e0bbSGreg Roach /** 366ad51e0bbSGreg Roach * Generate an HTML row of data for the census 36752bc9faeSGreg Roach * Add prefix cell (store XREF and drag/drop) 36852bc9faeSGreg Roach * Add suffix cell (delete button) 36952bc9faeSGreg Roach * 370ad51e0bbSGreg Roach * @param CensusInterface $census 371ad51e0bbSGreg Roach * @param Individual $individual 372ad51e0bbSGreg Roach * @param Individual $head 373ad51e0bbSGreg Roach * 374ad51e0bbSGreg Roach * @return string 375ad51e0bbSGreg Roach */ 37615d603e7SGreg Roach public static function censusTableRow(CensusInterface $census, Individual $individual, Individual $head) { 37715d603e7SGreg Roach $html = ''; 37815d603e7SGreg Roach foreach ($census->columns() as $column) { 37915d603e7SGreg 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>'; 38099f222b3SGreg Roach } 38199f222b3SGreg Roach 38215d603e7SGreg 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>'; 38399f222b3SGreg Roach } 3848c2e8227SGreg Roach} 385