xref: /webtrees/app/Module/ResearchTaskModule.php (revision 9797fe2e6d6eb3d34559dcf546f47c58bc50777b)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2016 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 = array()) {
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 (array('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					/* 0-DATE */     null,
95					/* 1-Date */     { dataSort: 0 },
96					/* 2-Record */   null,
97					/* 3-Username */ null,
98					/* 4-Text */     null
99				]
100			});
101			jQuery("#' . $table_id . '").css("visibility", "visible");
102			jQuery(".loading-image").css("display", "none");
103		');
104
105		$content = '';
106		$content .= '<div class="loading-image">&nbsp;</div>';
107		$content .= '<table id="' . $table_id . '" style="visibility:hidden;">';
108		$content .= '<thead><tr>';
109		$content .= '<th hidden>DATE</th>';
110		$content .= '<th>' . GedcomTag::getLabel('DATE') . '</th>';
111		$content .= '<th>' . I18N::translate('Record') . '</th>';
112		$content .= '<th>' . I18N::translate('Username') . '</th>';
113		$content .= '<th>' . GedcomTag::getLabel('TEXT') . '</th>';
114		$content .= '</tr></thead><tbody>';
115
116		$found  = false;
117		$end_jd = $show_future ? 99999999 : WT_CLIENT_JD;
118
119		$xrefs = Database::prepare(
120			"SELECT DISTINCT d_gid FROM `##dates`" .
121			" WHERE d_file = :tree_id AND d_fact = '_TODO' AND d_julianday1 < :jd"
122		)->execute(array(
123			'tree_id' => $WT_TREE->getTreeId(),
124			'jd'      => $end_jd,
125		))->fetchOneColumn();
126
127		$facts = array();
128		foreach ($xrefs as $xref) {
129			$record = GedcomRecord::getInstance($xref, $WT_TREE);
130			if ($record->canShow()) {
131				foreach ($record->getFacts('_TODO') as $fact) {
132					$facts[] = $fact;
133				}
134			}
135		}
136
137		foreach ($facts as $fact) {
138			$record    = $fact->getParent();
139			$user_name = $fact->getAttribute('_WT_USER');
140			if ($user_name === Auth::user()->getUserName() || !$user_name && $show_unassigned || $user_name && $show_other) {
141				$content .= '<tr>';
142				$content .= '<td hidden>' . $fact->getDate()->julianDay() . '</td>';
143				$content .= '<td class="wrap">' . $fact->getDate()->display() . '</td>';
144				$content .= '<td class="wrap"><a href="' . $record->getHtmlUrl() . '">' . $record->getFullName() . '</a></td>';
145				$content .= '<td class="wrap">' . $user_name . '</td>';
146				$content .= '<td class="wrap" dir="auto">' . $fact->getValue() . '</td>';
147				$content .= '</tr>';
148				$found = true;
149			}
150		}
151
152		$content .= '</tbody></table>';
153		if (!$found) {
154			$content .= '<p>' . I18N::translate('There are no research tasks in this family tree.') . '</p>';
155		}
156
157		if ($template) {
158			if ($block) {
159				$class .= ' small_inner_block';
160			}
161
162			return Theme::theme()->formatBlock($id, $title, $class, $content);
163		} else {
164			return $content;
165		}
166	}
167
168	/** {@inheritdoc} */
169	public function loadAjax() {
170		return false;
171	}
172
173	/** {@inheritdoc} */
174	public function isUserBlock() {
175		return true;
176	}
177
178	/** {@inheritdoc} */
179	public function isGedcomBlock() {
180		return true;
181	}
182
183	/**
184	 * An HTML form to edit block settings
185	 *
186	 * @param int $block_id
187	 */
188	public function configureBlock($block_id) {
189		if (Filter::postBool('save') && Filter::checkCsrf()) {
190			$this->setBlockSetting($block_id, 'show_other', Filter::postBool('show_other'));
191			$this->setBlockSetting($block_id, 'show_unassigned', Filter::postBool('show_unassigned'));
192			$this->setBlockSetting($block_id, 'show_future', Filter::postBool('show_future'));
193			$this->setBlockSetting($block_id, 'block', Filter::postBool('block'));
194		}
195
196		$show_other      = $this->getBlockSetting($block_id, 'show_other', self::DEFAULT_SHOW_OTHER);
197		$show_unassigned = $this->getBlockSetting($block_id, 'show_unassigned', self::DEFAULT_SHOW_UNASSIGNED);
198		$show_future     = $this->getBlockSetting($block_id, 'show_future', self::DEFAULT_SHOW_FUTURE);
199		$block           = $this->getBlockSetting($block_id, 'block', self::DEFAULT_BLOCK);
200
201		?>
202		<tr>
203			<td colspan="2">
204				<?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.'); ?>
205				<?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.'); ?>
206				<?php echo I18N::translate('Research tasks are stored using the custom GEDCOM tag “_TODO”. Other genealogy applications may not recognize this tag.'); ?>
207			</td>
208		</tr>
209		<?php
210
211		echo '<tr><td class="descriptionbox wrap width33">';
212		echo I18N::translate('Show research tasks that are assigned to other users');
213		echo '</td><td class="optionbox">';
214		echo FunctionsEdit::editFieldYesNo('show_other', $show_other);
215		echo '</td></tr>';
216
217		echo '<tr><td class="descriptionbox wrap width33">';
218		echo I18N::translate('Show research tasks that are not assigned to any user');
219		echo '</td><td class="optionbox">';
220		echo FunctionsEdit::editFieldYesNo('show_unassigned', $show_unassigned);
221		echo '</td></tr>';
222
223		echo '<tr><td class="descriptionbox wrap width33">';
224		echo I18N::translate('Show research tasks that have a date in the future');
225		echo '</td><td class="optionbox">';
226		echo FunctionsEdit::editFieldYesNo('show_future', $show_future);
227		echo '</td></tr>';
228
229		echo '<tr><td class="descriptionbox wrap width33">';
230		echo /* I18N: label for a yes/no option */ I18N::translate('Add a scrollbar when block contents grow');
231		echo '</td><td class="optionbox">';
232		echo FunctionsEdit::editFieldYesNo('block', $block);
233		echo '</td></tr>';
234	}
235}
236