xref: /webtrees/app/Module/ResearchTaskModule.php (revision 6bdf767435631ad1dc27ec1ffd855d43dbdce907)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2017 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16namespace Fisharebest\Webtrees\Module;
17
18use Fisharebest\Webtrees\Auth;
19use Fisharebest\Webtrees\Database;
20use Fisharebest\Webtrees\Filter;
21use Fisharebest\Webtrees\Functions\FunctionsEdit;
22use Fisharebest\Webtrees\GedcomRecord;
23use Fisharebest\Webtrees\GedcomTag;
24use Fisharebest\Webtrees\I18N;
25use Fisharebest\Webtrees\Theme;
26use Rhumsaa\Uuid\Uuid;
27
28/**
29 * Class ResearchTaskModule
30 */
31class ResearchTaskModule extends AbstractModule implements ModuleBlockInterface {
32	const DEFAULT_SHOW_OTHER      = '1';
33	const DEFAULT_SHOW_UNASSIGNED = '1';
34	const DEFAULT_SHOW_FUTURE     = '1';
35	const DEFAULT_BLOCK           = '1';
36
37	/** {@inheritdoc} */
38	public function getTitle() {
39		return /* I18N: Name of a module. Tasks that need further research. */ I18N::translate('Research tasks');
40	}
41
42	/** {@inheritdoc} */
43	public function getDescription() {
44		return /* I18N: Description of “Research tasks” module */ I18N::translate('A list of tasks and activities that are linked to the family tree.');
45	}
46
47	/**
48	 * Generate the HTML content of this block.
49	 *
50	 * @param int      $block_id
51	 * @param bool     $template
52	 * @param string[] $cfg
53	 *
54	 * @return string
55	 */
56	public function getBlock($block_id, $template = true, $cfg = []) {
57		global $ctype, $controller, $WT_TREE;
58
59		$show_other      = $this->getBlockSetting($block_id, 'show_other', self::DEFAULT_SHOW_OTHER);
60		$show_unassigned = $this->getBlockSetting($block_id, 'show_unassigned', self::DEFAULT_SHOW_UNASSIGNED);
61		$show_future     = $this->getBlockSetting($block_id, 'show_future', self::DEFAULT_SHOW_FUTURE);
62		$block           = $this->getBlockSetting($block_id, 'block', self::DEFAULT_BLOCK);
63
64		foreach (['show_unassigned', 'show_other', 'show_future', 'block'] as $name) {
65			if (array_key_exists($name, $cfg)) {
66				$$name = $cfg[$name];
67			}
68		}
69
70		$id    = $this->getName() . $block_id;
71		$class = $this->getName() . '_block';
72		if ($ctype === 'gedcom' && Auth::isManager($WT_TREE) || $ctype === 'user' && Auth::check()) {
73			$title = '<a class="icon-admin" title="' . I18N::translate('Preferences') . '" href="block_edit.php?block_id=' . $block_id . '&amp;ged=' . $WT_TREE->getNameHtml() . '&amp;ctype=' . $ctype . '"></a>';
74		} else {
75			$title = '';
76		}
77		$title .= $this->getTitle();
78
79		$table_id = Uuid::uuid4(); // create a unique ID
80
81		$controller
82			->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)
83			->addInlineJavascript('
84			jQuery("#' . $table_id . '").dataTable({
85				dom: \'t\',
86				' . I18N::datatablesI18N() . ',
87				autoWidth: false,
88				paginate: false,
89				lengthChange: false,
90				filter: false,
91				info: true,
92				jQueryUI: true,
93				columns: [
94					null,
95					null,
96					null,
97					null
98				]
99			});
100			jQuery("#' . $table_id . '").css("visibility", "visible");
101			jQuery(".loading-image").css("display", "none");
102		');
103
104		$content = '';
105		$content .= '<div class="loading-image">&nbsp;</div>';
106		$content .= '<table id="' . $table_id . '" style="visibility:hidden;">';
107		$content .= '<thead><tr>';
108		$content .= '<th>' . GedcomTag::getLabel('DATE') . '</th>';
109		$content .= '<th>' . I18N::translate('Record') . '</th>';
110		$content .= '<th>' . I18N::translate('Username') . '</th>';
111		$content .= '<th>' . GedcomTag::getLabel('TEXT') . '</th>';
112		$content .= '</tr></thead><tbody>';
113
114		$found  = false;
115		$end_jd = $show_future ? 99999999 : WT_CLIENT_JD;
116
117		$xrefs = Database::prepare(
118			"SELECT DISTINCT d_gid FROM `##dates`" .
119			" WHERE d_file = :tree_id AND d_fact = '_TODO' AND d_julianday1 < :jd"
120		)->execute([
121			'tree_id' => $WT_TREE->getTreeId(),
122			'jd'      => $end_jd,
123		])->fetchOneColumn();
124
125		$facts = [];
126		foreach ($xrefs as $xref) {
127			$record = GedcomRecord::getInstance($xref, $WT_TREE);
128			if ($record->canShow()) {
129				foreach ($record->getFacts('_TODO') as $fact) {
130					$facts[] = $fact;
131				}
132			}
133		}
134
135		foreach ($facts as $fact) {
136			$record    = $fact->getParent();
137			$user_name = $fact->getAttribute('_WT_USER');
138			if ($user_name === Auth::user()->getUserName() || !$user_name && $show_unassigned || $user_name && $show_other) {
139				$content .= '<tr>';
140				$content .= '<td data-sort="' . $fact->getDate()->julianDay() . '">' . $fact->getDate()->display() . '</td>';
141				$content .= '<td data-sort="' . Filter::escapeHtml($record->getSortName()) . '"><a href="' . $record->getHtmlUrl() . '">' . $record->getFullName() . '</a></td>';
142				$content .= '<td>' . $user_name . '</td>';
143				$content .= '<td dir="auto">' . $fact->getValue() . '</td>';
144				$content .= '</tr>';
145				$found = true;
146			}
147		}
148
149		$content .= '</tbody></table>';
150		if (!$found) {
151			$content .= '<p>' . I18N::translate('There are no research tasks in this family tree.') . '</p>';
152		}
153
154		if ($template) {
155			if ($block === '1') {
156				$class .= ' small_inner_block';
157			}
158
159			return Theme::theme()->formatBlock($id, $title, $class, $content);
160		} else {
161			return $content;
162		}
163	}
164
165	/** {@inheritdoc} */
166	public function loadAjax() {
167		return false;
168	}
169
170	/** {@inheritdoc} */
171	public function isUserBlock() {
172		return true;
173	}
174
175	/** {@inheritdoc} */
176	public function isGedcomBlock() {
177		return true;
178	}
179
180	/**
181	 * An HTML form to edit block settings
182	 *
183	 * @param int $block_id
184	 */
185	public function configureBlock($block_id) {
186		if (Filter::postBool('save') && Filter::checkCsrf()) {
187			$this->setBlockSetting($block_id, 'show_other', Filter::postBool('show_other'));
188			$this->setBlockSetting($block_id, 'show_unassigned', Filter::postBool('show_unassigned'));
189			$this->setBlockSetting($block_id, 'show_future', Filter::postBool('show_future'));
190			$this->setBlockSetting($block_id, 'block', Filter::postBool('block'));
191		}
192
193		$show_other      = $this->getBlockSetting($block_id, 'show_other', self::DEFAULT_SHOW_OTHER);
194		$show_unassigned = $this->getBlockSetting($block_id, 'show_unassigned', self::DEFAULT_SHOW_UNASSIGNED);
195		$show_future     = $this->getBlockSetting($block_id, 'show_future', self::DEFAULT_SHOW_FUTURE);
196		$block           = $this->getBlockSetting($block_id, 'block', self::DEFAULT_BLOCK);
197
198		?>
199		<tr>
200			<td colspan="2">
201				<?php echo I18N::translate('Research tasks are special events, added to individuals in your family tree, which identify the need for further research. You can use them as a reminder to check facts against more reliable sources, to obtain documents or photographs, to resolve conflicting information, etc.'); ?>
202				<?php echo I18N::translate('To create new research tasks, you must first add “research task” to the list of facts and events in the family tree’s preferences.'); ?>
203				<?php echo I18N::translate('Research tasks are stored using the custom GEDCOM tag “_TODO”. Other genealogy applications may not recognize this tag.'); ?>
204			</td>
205		</tr>
206		<?php
207
208		echo '<tr><td class="descriptionbox wrap width33">';
209		echo I18N::translate('Show research tasks that are assigned to other users');
210		echo '</td><td class="optionbox">';
211		echo FunctionsEdit::editFieldYesNo('show_other', $show_other);
212		echo '</td></tr>';
213
214		echo '<tr><td class="descriptionbox wrap width33">';
215		echo I18N::translate('Show research tasks that are not assigned to any user');
216		echo '</td><td class="optionbox">';
217		echo FunctionsEdit::editFieldYesNo('show_unassigned', $show_unassigned);
218		echo '</td></tr>';
219
220		echo '<tr><td class="descriptionbox wrap width33">';
221		echo I18N::translate('Show research tasks that have a date in the future');
222		echo '</td><td class="optionbox">';
223		echo FunctionsEdit::editFieldYesNo('show_future', $show_future);
224		echo '</td></tr>';
225
226		echo '<tr><td class="descriptionbox wrap width33">';
227		echo /* I18N: label for a yes/no option */ I18N::translate('Add a scrollbar when block contents grow');
228		echo '</td><td class="optionbox">';
229		echo FunctionsEdit::editFieldYesNo('block', $block);
230		echo '</td></tr>';
231	}
232}
233