1<?php 2namespace Fisharebest\Webtrees; 3 4/** 5 * webtrees: online genealogy 6 * Copyright (C) 2015 webtrees development team 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19/** 20 * Class RelativesTabModule 21 */ 22class RelativesTabModule extends AbstractModule implements ModuleTabInterface { 23 /** {@inheritdoc} */ 24 public function getTitle() { 25 return /* I18N: Name of a module */ I18N::translate('Families'); 26 } 27 28 /** {@inheritdoc} */ 29 public function getDescription() { 30 return /* I18N: Description of the “Families” module */ I18N::translate('A tab showing the close relatives of an individual.'); 31 } 32 33 /** {@inheritdoc} */ 34 public function defaultTabOrder() { 35 return 20; 36 } 37 38 /** 39 * @param Date $prev 40 * @param Date $next 41 * @param integer $child_number 42 * 43 * @return string 44 */ 45 static function ageDifference(Date $prev, Date $next, $child_number = 0) { 46 if ($prev->isOK() && $next->isOK()) { 47 $days = $next->maximumJulianDay() - $prev->minimumJulianDay(); 48 if ($days < 0) { 49 // Show warning triangle if dates in reverse order 50 $diff = '<i class="icon-warning"></i> '; 51 } elseif ($child_number > 1 && $days > 1 && $days < 240) { 52 // Show warning triangle if children born too close together 53 $diff = '<i class="icon-warning"></i> '; 54 } else { 55 $diff = ''; 56 } 57 58 $months = round($days * 12 / 365.25); // Approximate - we do not know the calendar 59 if (abs($months) == 12 || abs($months) >= 24) { 60 $diff .= I18N::plural('%s year', '%s years', round($months / 12), I18N::number(round($months / 12))); 61 } elseif ($months != 0) { 62 $diff .= I18N::plural('%s month', '%s months', $months, I18N::number($months)); 63 } 64 65 return '<div class="elderdate age">' . $diff . '</div>'; 66 } else { 67 return ''; 68 } 69 } 70 71 /** 72 * @param Family $family 73 * @param string $type 74 * @param string $label 75 */ 76 function printFamily(Family $family, $type, $label) { 77 global $controller; 78 79 if ($family->getTree()->getPreference('SHOW_PRIVATE_RELATIONSHIPS')) { 80 $access_level = Auth::PRIV_HIDE; 81 } else { 82 $access_level = Auth::accessLevel($family->getTree()); 83 } 84 85 ?> 86 <table> 87 <tr> 88 <td> 89 <i class="icon-cfamily"></i> 90 </td> 91 <td> 92 <span class="subheaders"> <?php echo $label; ?> </span> - 93 <a href="<?php echo $family->getHtmlUrl(); ?>"><?php echo I18N::translate('View family'); ?></a> 94 </td> 95 </tr> 96 </table> 97 <table class="facts_table"> 98 <?php 99 100 ///// HUSB ///// 101 $found = false; 102 foreach ($family->getFacts('HUSB', false, $access_level) as $fact) { 103 $found |= !$fact->isPendingDeletion(); 104 $person = $fact->getTarget(); 105 if ($person instanceof Individual) { 106 if ($fact->isPendingAddition()) { 107 $class = 'facts_label new'; 108 } elseif ($fact->isPendingDeletion()) { 109 $class = 'facts_label old'; 110 } else { 111 $class = 'facts_label'; 112 } 113 ?> 114 <tr> 115 <td class="<?php echo $class; ?>"> 116 <?php echo get_close_relationship_name($controller->record, $person); ?> 117 </td> 118 <td class="<?php echo $controller->getPersonStyle($person); ?>"> 119 <?php echo Theme::theme()->individualBoxLarge($person); ?> 120 </td> 121 </tr> 122 <?php 123 } 124 } 125 if (!$found && $family->canEdit()) { 126 ?> 127 <tr> 128 <td class="facts_label"></td> 129 <td class="facts_value"><a href="#" onclick="return add_spouse_to_family('<?php echo $family->getXref(); ?>', 'HUSB');"><?php echo I18N::translate('Add a husband to this family'); ?></a></td> 130 </tr> 131 <?php 132 } 133 134 ///// WIFE ///// 135 $found = false; 136 foreach ($family->getFacts('WIFE', false, $access_level) as $fact) { 137 $person = $fact->getTarget(); 138 if ($person instanceof Individual) { 139 $found |= !$fact->isPendingDeletion(); 140 if ($fact->isPendingAddition()) { 141 $class = 'facts_label new'; 142 } elseif ($fact->isPendingDeletion()) { 143 $class = 'facts_label old'; 144 } else { 145 $class = 'facts_label'; 146 } 147 ?> 148 <tr> 149 <td class="<?php echo $class; ?>"> 150 <?php echo get_close_relationship_name($controller->record, $person); ?> 151 </td> 152 <td class="<?php echo $controller->getPersonStyle($person); ?>"> 153 <?php echo Theme::theme()->individualBoxLarge($person); ?> 154 </td> 155 </tr> 156 <?php 157 } 158 } 159 if (!$found && $family->canEdit()) { 160 ?> 161 <tr> 162 <td class="facts_label"></td> 163 <td class="facts_value"><a href="#" onclick="return add_spouse_to_family('<?php echo $family->getXref(); ?>', 'WIFE');"><?php echo I18N::translate('Add a wife to this family'); ?></a></td> 164 </tr> 165 <?php 166 } 167 168 ///// MARR ///// 169 $found = false; 170 $prev = new Date(''); 171 foreach ($family->getFacts(WT_EVENTS_MARR) as $fact) { 172 $found |= !$fact->isPendingDeletion(); 173 if ($fact->isPendingAddition()) { 174 $class = ' new'; 175 } elseif ($fact->isPendingDeletion()) { 176 $class = ' old'; 177 } else { 178 $class = ''; 179 } 180 ?> 181 <tr> 182 <td class="facts_label"> 183 184 </td> 185 <td class="facts_value<?php echo $class; ?>"> 186 <?php echo GedcomTag::getLabelValue($fact->getTag(), $fact->getDate()->display() . ' — ' . $fact->getPlace()->getFullName()); ?> 187 </td> 188 </tr> 189 <?php 190 if (!$prev->isOK() && $fact->getDate()->isOK()) { 191 $prev = $fact->getDate(); 192 } 193 } 194 if (!$found && $family->canShow() && $family->canEdit()) { 195 // Add a new marriage 196 ?> 197 <tr> 198 <td class="facts_label"> 199 200 </td> 201 <td class="facts_value"> 202 <a href="#" onclick="return add_new_record('<?php echo $family->getXref(); ?>', 'MARR');"> 203 <?php echo I18N::translate('Add marriage details'); ?> 204 </a> 205 </td> 206 </tr> 207 <?php 208 } 209 210 ///// CHIL ///// 211 $child_number = 0; 212 foreach ($family->getFacts('CHIL', false, $access_level) as $fact) { 213 $person = $fact->getTarget(); 214 if ($person instanceof Individual) { 215 if ($fact->isPendingAddition()) { 216 $child_number++; 217 $class = 'facts_label new'; 218 } elseif ($fact->isPendingDeletion()) { 219 $class = 'facts_label old'; 220 } else { 221 $child_number++; 222 $class = 'facts_label'; 223 } 224 $next = new Date(''); 225 foreach ($person->getFacts(WT_EVENTS_BIRT) as $bfact) { 226 if ($bfact->getDate()->isOK()) { 227 $next = $bfact->getDate(); 228 break; 229 } 230 } 231 ?> 232 <tr> 233 <td class="<?php echo $class; ?>"> 234 <?php echo self::ageDifference($prev, $next, $child_number); ?> 235 <?php echo get_close_relationship_name($controller->record, $person); ?> 236 </td> 237 <td class="<?php echo $controller->getPersonStyle($person); ?>"> 238 <?php echo Theme::theme()->individualBoxLarge($person); ?> 239 </td> 240 </tr> 241 <?php 242 $prev = $next; 243 } 244 } 245 // Re-order children / add a new child 246 if ($family->canEdit()) { 247 if ($type == 'FAMS') { 248 $add_child_text = I18N::translate('Add a new son or daughter'); 249 } else { 250 $add_child_text = I18N::translate('Add a new brother or sister'); 251 } 252 ?> 253 <tr> 254 <td class="facts_label"> 255 <?php if (count($family->getChildren()) > 1) { ?> 256 <a href="#" onclick="reorder_children('<?php echo $family->getXref(); ?>');tabswitch(5);"><i class="icon-media-shuffle"></i> <?php echo I18N::translate('Re-order children'); ?></a> 257 <?php } ?> 258 </td> 259 <td class="facts_value"> 260 <a href="#" onclick="return add_child_to_family('<?php echo $family->getXref(); ?>');"><?php echo $add_child_text; ?></a> 261 <span style='white-space:nowrap;'> 262 <a href="#" class="icon-sex_m_15x15" onclick="return add_child_to_family('<?php echo $family->getXref(); ?>','M');"></a> 263 <a href="#" class="icon-sex_f_15x15" onclick="return add_child_to_family('<?php echo $family->getXref(); ?>','F');"></a> 264 </span> 265 </td> 266 </tr> 267 <?php 268 } 269 270 echo '</table>'; 271 272 return; 273 } 274 275 /** {@inheritdoc} */ 276 public function getTabContent() { 277 global $WT_TREE, $show_full, $controller; 278 279 if (isset($show_full)) { 280 $saved_show_full = $show_full; 281 } 282 // We always want to see full details here 283 $show_full = 1; 284 285 ob_start(); 286 ?> 287 <table class="facts_table"><tr><td class="descriptionbox rela"> 288 <input id="checkbox_elder" type="checkbox" onclick="jQuery('div.elderdate').toggle();" <?php echo $WT_TREE->getPreference('SHOW_AGE_DIFF') ? 'checked' : ''; ?>> 289 <label for="checkbox_elder"><?php echo I18N::translate('Show date differences'); ?></label> 290 </td></tr></table> 291 <?php 292 $families = $controller->record->getChildFamilies(); 293 if (!$families && $controller->record->canEdit()) { 294 ?> 295 <table class="facts_table"> 296 <tr> 297 <td class="facts_value"><a href="#" onclick="return add_parent_to_individual('<?php echo $controller->record->getXref(); ?>', 'M');"><?php echo I18N::translate('Add a new father'); ?></td> 298 </tr> 299 <tr> 300 <td class="facts_value"><a href="#" onclick="return add_parent_to_individual('<?php echo $controller->record->getXref(); ?>', 'F');"><?php echo I18N::translate('Add a new mother'); ?></a></td> 301 </tr> 302 </table> 303 <?php 304 } 305 306 // parents 307 foreach ($families as $family) { 308 $this->printFamily($family, 'FAMC', $controller->record->getChildFamilyLabel($family)); 309 } 310 311 // step-parents 312 foreach ($controller->record->getChildStepFamilies() as $family) { 313 $this->printFamily($family, 'FAMC', $controller->record->getStepFamilyLabel($family)); 314 } 315 316 // spouses 317 $families = $controller->record->getSpouseFamilies(); 318 foreach ($families as $family) { 319 $this->printFamily($family, 'FAMS', $controller->record->getSpouseFamilyLabel($family)); 320 } 321 322 // step-children 323 foreach ($controller->record->getSpouseStepFamilies() as $family) { 324 $this->printFamily($family, 'FAMS', $family->getFullName()); 325 } 326 327 if (!$WT_TREE->getPreference('SHOW_AGE_DIFF')) { 328 echo '<script>jQuery("DIV.elderdate").toggle();</script>'; 329 } 330 331 if ($controller->record->canEdit()) { 332 ?> 333 <br><table class="facts_table"> 334 <?php 335 if (count($families) > 1) { ?> 336 <tr> 337 <td class="facts_value"> 338 <a href="#" onclick="return reorder_families('<?php echo $controller->record->getXref(); ?>');"><?php echo I18N::translate('Re-order families'); ?></a> 339 </td> 340 </tr> 341 <?php } ?> 342 <tr> 343 <td class="facts_value"> 344 <a href="#" onclick="return add_famc('<?php echo $controller->record->getXref(); ?>');"><?php echo I18N::translate('Link this individual to an existing family as a child'); ?></a> 345 </td> 346 </tr> 347 <?php if ($controller->record->getSex() != "F") { ?> 348 <tr> 349 <td class="facts_value"> 350 <a href="#" onclick="return add_spouse_to_individual('<?php echo $controller->record->getXref(); ?>','WIFE');"><?php echo I18N::translate('Add a new wife'); ?></a> 351 </td> 352 </tr> 353 <tr> 354 <td class="facts_value"> 355 <a href="#" onclick="return linkspouse('<?php echo $controller->record->getXref(); ?>','WIFE');"><?php echo I18N::translate('Add a wife using an existing individual'); ?></a> 356 </td> 357 </tr> 358 <?php } 359 if ($controller->record->getSex() != "M") { ?> 360 <tr> 361 <td class="facts_value"> 362 <a href="#" onclick="return add_spouse_to_individual('<?php echo $controller->record->getXref(); ?>','HUSB');"><?php echo I18N::translate('Add a new husband'); ?></a> 363 </td> 364 </tr> 365 <tr> 366 <td class="facts_value"> 367 <a href="#" onclick="return linkspouse('<?php echo $controller->record->getXref(); ?>','HUSB');"><?php echo I18N::translate('Add a husband using an existing individual'); ?></a> 368 </td> 369 </tr> 370 <?php } ?> 371 <tr> 372 <td class="facts_value"> 373 <a href="#" onclick="return add_child_to_individual('<?php echo $controller->record->getXref(); ?>','U');"><?php echo I18N::translate('Add a child to create a one-parent family'); ?></a> 374 </td> 375 </tr> 376 </table> 377 <?php } ?> 378 <br> 379 <?php 380 381 unset($show_full); 382 if (isset($saved_show_full)) { 383 $show_full = $saved_show_full; 384 } 385 386 return '<div id="' . $this->getName() . '_content">' . ob_get_clean() . '</div>'; 387 } 388 389 /** {@inheritdoc} */ 390 public function hasTabContent() { 391 return true; 392 } 393 /** {@inheritdoc} */ 394 public function isGrayedOut() { 395 return false; 396 } 397 /** {@inheritdoc} */ 398 public function canLoadAjax() { 399 return !Auth::isSearchEngine(); // Search engines cannot use AJAX 400 } 401 402 /** {@inheritdoc} */ 403 public function getPreLoadContent() { 404 return ''; 405 } 406} 407