1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2018 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\Controller\PageController; 20use Fisharebest\Webtrees\Family; 21use Fisharebest\Webtrees\Filter; 22use Fisharebest\Webtrees\GedcomRecord; 23use Fisharebest\Webtrees\Html; 24use Fisharebest\Webtrees\I18N; 25use Fisharebest\Webtrees\Individual; 26use Fisharebest\Webtrees\Menu; 27use Fisharebest\Webtrees\Module; 28use Fisharebest\Webtrees\Module\ClippingsCart\ClippingsCartController; 29use Fisharebest\Webtrees\Session; 30use Fisharebest\Webtrees\Tree; 31 32/** 33 * Class ClippingsCartModule 34 */ 35class ClippingsCartModule extends AbstractModule implements ModuleMenuInterface, ModuleSidebarInterface { 36 /** {@inheritdoc} */ 37 public function getTitle() { 38 return /* I18N: Name of a module */ 39 I18N::translate('Clippings cart'); 40 } 41 42 /** {@inheritdoc} */ 43 public function getDescription() { 44 return /* I18N: Description of the “Clippings cart” module */ 45 I18N::translate('Select records from your family tree and save them as a GEDCOM file.'); 46 } 47 48 /** 49 * What is the default access level for this module? 50 * 51 * Some modules are aimed at admins or managers, and are not generally shown to users. 52 * 53 * @return int 54 */ 55 public function defaultAccessLevel() { 56 return Auth::PRIV_USER; 57 } 58 59 /** 60 * This is a general purpose hook, allowing modules to respond to routes 61 * of the form module.php?mod=FOO&mod_action=BAR 62 * 63 * @param string $mod_action 64 */ 65 public function modAction($mod_action) { 66 global $WT_TREE; 67 68 // Only allow access if either the menu or sidebar is enabled. 69 if ( 70 !array_key_exists($this->getName(), Module::getActiveSidebars($WT_TREE)) && 71 !array_key_exists($this->getName(), Module::getActiveMenus($WT_TREE)) 72 ) { 73 http_response_code(404); 74 75 return; 76 } 77 78 switch ($mod_action) { 79 case 'ajax': 80 $html = $this->getSidebarAjaxContent(); 81 header('Content-Type: text/html; charset=UTF-8'); 82 echo $html; 83 break; 84 case 'index': 85 global $controller, $WT_TREE; 86 87 $MAX_PEDIGREE_GENERATIONS = $WT_TREE->getPreference('MAX_PEDIGREE_GENERATIONS'); 88 89 $clip_ctrl = new ClippingsCartController; 90 $cart = Session::get('cart'); 91 92 $controller = new PageController; 93 $controller 94 ->setPageTitle($this->getTitle()) 95 ->pageHeader(); 96 97 echo '<script>'; 98 echo 'function radAncestors(elementid) {var radFamilies=document.getElementById(elementid);radFamilies.checked=true;}'; 99 echo '</script>'; 100 echo '<div class="clipping-cart">'; 101 102 if (!$cart[$WT_TREE->getTreeId()]) { 103 echo '<h2>', I18N::translate('Family tree clippings cart'), '</h2>'; 104 } 105 106 if ($clip_ctrl->action == 'add') { 107 $record = GedcomRecord::getInstance($clip_ctrl->id, $WT_TREE); 108 if ($clip_ctrl->type === 'FAM') { ?> 109 <form class="wt-page-options wt-page-options-clipping-cart hidden-print" action="module.php"> 110 <input type="hidden" name="mod" value="clippings"> 111 <input type="hidden" name="mod_action" value="index"> 112 <input type="hidden" name="id" value="<?= $clip_ctrl->id ?>"> 113 <input type="hidden" name="type" value="<?= $clip_ctrl->type ?>"> 114 <input type="hidden" name="action" value="add1"> 115 <table class="add-to center"> 116 <thead> 117 <tr> 118 <td class="topbottombar"> 119 <?= I18N::translate('Add to the clippings cart') ?> 120 </td> 121 </tr> 122 </thead> 123 <tbody> 124 <tr> 125 <td class="optionbox"> 126 <input type="radio" name="others" value="parents"> 127 <?= $record->getFullName() ?> 128 </td> 129 </tr> 130 <tr> 131 <td class="optionbox"> 132 <input type="radio" name="others" value="members" checked> 133 <?= /* I18N: %s is a family (husband + wife) */ 134 I18N::translate('%s and their children', $record->getFullName()) ?> 135 </td> 136 </tr> 137 <tr> 138 <td class="optionbox"> 139 <input type="radio" name="others" value="descendants"> 140 <?= /* I18N: %s is a family (husband + wife) */ 141 I18N::translate('%s and their descendants', $record->getFullName()) ?> 142 </td> 143 </tr> 144 </tbody> 145 <tfoot> 146 <tr> 147 <td class="topbottombar"><input type="submit" value="<?= I18N::translate('continue') ?>"> 148 </td> 149 </tr> 150 </tfoot> 151 </table> 152 </form> 153 </div> 154 <?php } elseif ($clip_ctrl->type === 'INDI') { ?> 155 <form class="wt-page-options wt-page-options-clipping-cart hidden-print" action="module.php"> 156 <input type="hidden" name="mod" value="clippings"> 157 <input type="hidden" name="mod_action" value="index"> 158 <input type="hidden" name="id" value="<?= $clip_ctrl->id ?>"> 159 <input type="hidden" name="type" value="<?= $clip_ctrl->type ?>"> 160 <input type="hidden" name="action" value="add1"> 161 <table class="add-to center"> 162 <thead> 163 <tr> 164 <td class="topbottombar"> 165 <?= I18N::translate('Add to the clippings cart') ?> 166 </td> 167 </tr> 168 </thead> 169 <tbody> 170 <tr> 171 <td class="optionbox"> 172 <label> 173 <input type="radio" name="others" checked value="none"> 174 <?= $record->getFullName() ?> 175 </label> 176 </td> 177 </tr> 178 <tr> 179 <td class="optionbox"> 180 <label> 181 <input type="radio" name="others" value="parents"> 182 <?php 183 if ($record->getSex() === 'F') { 184 echo /* I18N: %s is a woman's name */ 185 I18N::translate('%s, her parents and siblings', $record->getFullName()); 186 } else { 187 echo /* I18N: %s is a man's name */ 188 I18N::translate('%s, his parents and siblings', $record->getFullName()); 189 } 190 ?> 191 </label> 192 </td> 193 </tr> 194 <tr> 195 <td class="optionbox"> 196 <label> 197 <input type="radio" name="others" value="members"> 198 <?php 199 if ($record->getSex() === 'F') { 200 echo /* I18N: %s is a woman's name */ 201 I18N::translate('%s, her spouses and children', $record->getFullName()); 202 } else { 203 echo /* I18N: %s is a man's name */ 204 I18N::translate('%s, his spouses and children', $record->getFullName()); 205 } 206 ?> 207 </label> 208 </td> 209 </tr> 210 <tr> 211 <td class="optionbox"> 212 <label> 213 <input type="radio" name="others" value="ancestors" id="ancestors"> 214 <?php 215 if ($record->getSex() === 'F') { 216 echo /* I18N: %s is a woman's name */ 217 I18N::translate('%s and her ancestors', $record->getFullName()); 218 } else { 219 echo /* I18N: %s is a man's name */ 220 I18N::translate('%s and his ancestors', $record->getFullName()); 221 } 222 ?> 223 </label> 224 <br> 225 <?= I18N::translate('Number of generations') ?> 226 <input type="text" size="5" name="level1" value="<?= $MAX_PEDIGREE_GENERATIONS ?>" onfocus="radAncestors('ancestors');"> 227 </td> 228 </tr> 229 <tr> 230 <td class="optionbox"> 231 <label> 232 <input type="radio" name="others" value="ancestorsfamilies" id="ancestorsfamilies"> 233 <?php 234 if ($record->getSex() === 'F') { 235 echo /* I18N: %s is a woman's name */ 236 I18N::translate('%s, her ancestors and their families', $record->getFullName()); 237 } else { 238 echo /* I18N: %s is a man's name */ 239 I18N::translate('%s, his ancestors and their families', $record->getFullName()); 240 } 241 ?> 242 </label> 243 <br> 244 <?= I18N::translate('Number of generations') ?> 245 <input type="text" size="5" name="level2" value="<?= $MAX_PEDIGREE_GENERATIONS ?>" onfocus="radAncestors('ancestorsfamilies');"> 246 </td> 247 </tr> 248 <tr> 249 <td class="optionbox"> 250 <label> 251 <input type="radio" name="others" value="descendants" id="descendants"> 252 <?php 253 if ($record->getSex() === 'F') { 254 echo /* I18N: %s is a woman's name */ 255 I18N::translate('%s, her spouses and descendants', $record->getFullName()); 256 } else { 257 echo /* I18N: %s is a man's name */ 258 I18N::translate('%s, his spouses and descendants', $record->getFullName()); 259 } 260 ?> 261 </label> 262 <br> 263 <?= I18N::translate('Number of generations') ?> 264 <input type="text" size="5" name="level3" value="<?= $MAX_PEDIGREE_GENERATIONS ?>" onfocus="radAncestors('descendants');"> 265 </td> 266 </tr> 267 </tbody> 268 <tfoot> 269 <tr> 270 <td class="topbottombar"> 271 <input type="submit" value="<?= I18N::translate('continue') ?>"> 272 </td> 273 </tr> 274 </tfoot> 275 </table> 276 </form> 277 </div> 278 <?php } elseif ($clip_ctrl->type === 'SOUR') { ?> 279 <form class="wt-page-options wt-page-options-clipping-cart hidden-print" action="module.php"> 280 <input type="hidden" name="mod" value="clippings"> 281 <input type="hidden" name="mod_action" value="index"> 282 <input type="hidden" name="id" value="<?= $clip_ctrl->id ?>"> 283 <input type="hidden" name="type" value="<?= $clip_ctrl->type ?>"> 284 <input type="hidden" name="action" value="add1"> 285 <table class="add-to center"> 286 <thead> 287 <tr> 288 <td class="topbottombar"> 289 <?= I18N::translate('Add to the clippings cart') ?> 290 </td> 291 </tr> 292 </thead> 293 <tbody> 294 <tr> 295 <td class="optionbox"> 296 <label> 297 <input type="radio" name="others" checked value="none"> 298 <?= $record->getFullName() ?> 299 </label> 300 </td> 301 </tr> 302 <tr> 303 <td class="optionbox"> 304 <label> 305 <input type="radio" name="others" value="linked"> 306 <?= /* I18N: %s is the name of a source */ 307 I18N::translate('%s and the individuals that reference it.', $record->getFullName()) ?> 308 </label> 309 </td> 310 </tr> 311 </tbody> 312 <tfoot> 313 <tr> 314 <td class="topbottombar"> 315 <input type="submit" value="<?= I18N::translate('continue') ?>"> 316 </td> 317 </tr> 318 </tfoot> 319 </table> 320 </form> 321 </div> 322 <?php } 323 } 324 325 if (!$cart[$WT_TREE->getTreeId()]) { 326 if ($clip_ctrl->action != 'add') { 327 echo '<div class="center">'; 328 echo I18N::translate('The clippings cart allows you to take extracts from this family tree and download them as a GEDCOM file.'); 329 echo '</div>'; 330 ?> 331 <form class="wt-page-options wt-page-options-clipping-cart hidden-print" name="addin" action="module.php"> 332 <input type="hidden" name="mod" value="clippings"> 333 <input type="hidden" name="mod_action" value="index"> 334 <table class="add-to center"> 335 <thead> 336 <tr> 337 <td colspan="2" class="topbottombar"> 338 <?= I18N::translate('Add to the clippings cart') ?> 339 </td> 340 </tr> 341 </thead> 342 <tbody> 343 <tr> 344 <td class="optionbox"> 345 <input type="hidden" name="action" value="add"> 346 <input type="text" data-autocomplete-type="IFSRO" name="id" id="cart_item_id" size="5"> 347 </td> 348 <td class="optionbox"> 349 <input type="submit" value="<?= /* I18N: A button label. */ I18N::translate('add') ?>"> 350 </td> 351 </tr> 352 </tbody> 353 </table> 354 </form> 355 </div> 356 <?php 357 } 358 echo '<div class="center">'; 359 // -- end new lines 360 echo I18N::translate('Your clippings cart is empty.'); 361 echo '</div>'; 362 } else { 363 // Keep track of the INDI from the parent page, otherwise it will 364 // get lost after ajax updates 365 $pid = Filter::get('pid', WT_REGEX_XREF); 366 367 if ($clip_ctrl->action !== 'download' && $clip_ctrl->action !== 'add') { ?> 368 <form class="wt-page-options wt-page-options-clipping-cart hidden-print" action="module.php"> 369 <input type="hidden" name="mod" value="clippings"> 370 <input type="hidden" name="mod_action" value="index"> 371 <input type="hidden" name="action" value="download"> 372 <input type="hidden" name="pid" value="<?= $pid ?>"> 373 <table class="add-to center"> 374 <tr> 375 <td colspan="2" class="topbottombar"> 376 <h2><?= I18N::translate('Download') ?></h2> 377 </td> 378 </tr> 379 <?php if (Auth::isManager($WT_TREE)) { ?> 380 <tr> 381 <td class="descriptionbox width50 wrap"> 382 <?= I18N::translate('Apply privacy settings') ?> 383 </td> 384 <td class="optionbox"> 385 <input type="radio" name="privatize_export" value="none" checked> 386 <?= I18N::translate('None') ?> 387 <br> 388 <input type="radio" name="privatize_export" value="gedadmin"> 389 <?= I18N::translate('Manager') ?> 390 <br> 391 <input type="radio" name="privatize_export" value="user"> 392 <?= I18N::translate('Member') ?> 393 <br> 394 <input type="radio" name="privatize_export" value="visitor"> 395 <?= I18N::translate('Visitor') ?> 396 </td> 397 </tr> 398 <?php } elseif (Auth::isMember($WT_TREE)) { ?> 399 <tr> 400 <td class="descriptionbox width50 wrap"> 401 <?= I18N::translate('Apply privacy settings') ?> 402 </td> 403 <td class="optionbox"> 404 <input type="radio" name="privatize_export" value="user" checked> <?= I18N::translate('Member') ?><br> 405 <input type="radio" name="privatize_export" value="visitor"> <?= I18N::translate('Visitor') ?> 406 </td> 407 </tr> 408 <?php } ?> 409 410 <tr> 411 <td class="descriptionbox width50 wrap"> 412 <?= I18N::translate('Convert from UTF-8 to ISO-8859-1') ?> 413 </td> 414 <td class="optionbox"> 415 <input type="checkbox" name="convert" value="yes"> 416 </td> 417 </tr> 418 419 <tr> 420 <td class="topbottombar" colspan="2"> 421 <input type="submit" value="<?= /* I18N: A button label. */ I18N::translate('download') ?>"> 422 </td> 423 </tr> 424 </table> 425 </form> 426 </div> 427 <br> 428 429 <form class="wt-page-options wt-page-options-clipping-cart hidden-print" name="addin" action="module.php"> 430 <input type="hidden" name="mod" value="clippings"> 431 <input type="hidden" name="mod_action" value="index"> 432 <table class="add-to center"> 433 <thead> 434 <tr> 435 <td colspan="2" class="topbottombar" style="text-align:center; "> 436 <?= I18N::translate('Add to the clippings cart') ?> 437 </td> 438 </tr> 439 </thead> 440 <tbody> 441 <tr> 442 <td class="optionbox"> 443 <input type="hidden" name="action" value="add"> 444 <input type="text" data-autocomplete-type="IFSRO" name="id" id="cart_item_id" size="8"> 445 </td> 446 <td class="optionbox"> 447 <input type="submit" value="<?= /* I18N: A button label. */ I18N::translate('add') ?>"> 448 </td> 449 </tr> 450 </tbody> 451 <tfoot> 452 <tr> 453 <th colspan="2"> 454 <a href="module.php?mod=clippings&mod_action=index&action=empty"> 455 <?= I18N::translate('Empty the clippings cart') ?> 456 </a> 457 </th> 458 </tr> 459 </tfoot> 460 </table> 461 </form> 462 </div> 463 <?php } ?> 464 <div class="clipping-cart"> 465 <h2> 466 <?= I18N::translate('Family tree clippings cart') ?> 467 </h2> 468 <table id="mycart" class="sortable list_table width50"> 469 <thead> 470 <tr> 471 <th class="list_label"><?= I18N::translate('Record') ?></th> 472 <th class="list_label"><?= I18N::translate('Remove') ?></th> 473 </tr> 474 </thead> 475 <tbody> 476 <?php 477 foreach (array_keys($cart[$WT_TREE->getTreeId()]) as $xref) { 478 $record = GedcomRecord::getInstance($xref, $WT_TREE); 479 if ($record) { 480 switch ($record::RECORD_TYPE) { 481 case 'INDI': 482 $icon = 'icon-indis'; 483 break; 484 case 'FAM': 485 $icon = 'icon-sfamily'; 486 break; 487 case 'SOUR': 488 $icon = 'icon-source'; 489 break; 490 case 'REPO': 491 $icon = 'icon-repository'; 492 break; 493 case 'NOTE': 494 $icon = 'icon-note'; 495 break; 496 case 'OBJE': 497 $icon = 'icon-media'; 498 break; 499 default: 500 $icon = 'icon-clippings'; 501 break; 502 } 503 ?> 504 <tr> 505 <td class="list_value"> 506 <i class="<?= $icon ?>"></i> 507 <?php 508 echo '<a href="', e($record->url()), '">', $record->getFullName(), '</a>'; 509 ?> 510 </td> 511 <td class="list_value center vmiddle"><a href="module.php?mod=clippings&mod_action=index&action=remove&id=<?= $xref ?>" class="icon-remove" title="<?= I18N::translate('Remove') ?>"></a></td> 512 </tr> 513 <?php 514 } 515 } 516 ?> 517 </table> 518 </div> 519 <?php 520 } 521 break; 522 default: 523 http_response_code(404); 524 break; 525 } 526 } 527 528 /** 529 * The user can re-order menus. Until they do, they are shown in this order. 530 * 531 * @return int 532 */ 533 public function defaultMenuOrder() { 534 return 20; 535 } 536 537 /** 538 * A menu, to be added to the main application menu. 539 * 540 * @param Tree $tree 541 * 542 * @return Menu|null 543 */ 544 public function getMenu(Tree $tree) { 545 global $controller; 546 547 $submenus = []; 548 if (isset($controller->record)) { 549 $submenus[] = new Menu($this->getTitle(), 'module.php?mod=clippings&mod_action=index&ged=' . $tree->getNameUrl(), 'menu-clippings-cart', ['rel' => 'nofollow']); 550 } 551 if (!empty($controller->record) && $controller->record->canShow()) { 552 $submenus[] = new Menu(I18N::translate('Add to the clippings cart'), 'module.php?mod=clippings&mod_action=index&action=add&id=' . $controller->record->getXref(), 'menu-clippings-add', ['rel' => 'nofollow']); 553 } 554 555 if ($submenus) { 556 return new Menu($this->getTitle(), '#', 'menu-clippings', ['rel' => 'nofollow'], $submenus); 557 } else { 558 return new Menu($this->getTitle(), 'module.php?mod=clippings&mod_action=index&ged=' . $tree->getNameUrl(), 'menu-clippings', ['rel' => 'nofollow']); 559 } 560 } 561 562 /** {@inheritdoc} */ 563 public function defaultSidebarOrder() { 564 return 60; 565 } 566 567 /** {@inheritdoc} */ 568 public function hasSidebarContent(Individual $individual) { 569 // Creating a controller has the side effect of initialising the cart 570 new ClippingsCartController; 571 572 return true; 573 } 574 575 /** 576 * Load this sidebar synchronously. 577 * 578 * @param Individual $individual 579 * 580 * @return string 581 */ 582 public function getSidebarContent(Individual $individual) { 583 global $controller; 584 585 $controller->addInlineJavascript(' 586 $("#sb_clippings_content").on("click", ".add_cart, .remove_cart", function() { 587 $("#sb_clippings_content").load(this.href); 588 return false; 589 }); 590 '); 591 592 return '<div id="sb_clippings_content">' . $this->getCartList() . '</div>'; 593 } 594 595 /** {@inheritdoc} */ 596 public function getSidebarAjaxContent() { 597 global $WT_TREE; 598 599 $cart = Session::get('cart'); 600 601 $clip_ctrl = new ClippingsCartController; 602 $add = Filter::get('add', WT_REGEX_XREF); 603 $add1 = Filter::get('add1', WT_REGEX_XREF); 604 $remove = Filter::get('remove', WT_REGEX_XREF); 605 $others = Filter::get('others'); 606 $clip_ctrl->level1 = Filter::getInteger('level1'); 607 $clip_ctrl->level2 = Filter::getInteger('level2'); 608 $clip_ctrl->level3 = Filter::getInteger('level3'); 609 if ($add) { 610 $record = GedcomRecord::getInstance($add, $WT_TREE); 611 if ($record) { 612 $clip_ctrl->id = $record->getXref(); 613 $clip_ctrl->type = $record::RECORD_TYPE; 614 $clip_ctrl->addClipping($record); 615 } 616 } elseif ($add1) { 617 $record = Individual::getInstance($add1, $WT_TREE); 618 if ($record) { 619 $clip_ctrl->id = $record->getXref(); 620 $clip_ctrl->type = $record::RECORD_TYPE; 621 if ($others == 'parents') { 622 foreach ($record->getChildFamilies() as $family) { 623 $clip_ctrl->addClipping($family); 624 $clip_ctrl->addFamilyMembers($family); 625 } 626 } elseif ($others == 'ancestors') { 627 $clip_ctrl->addAncestorsToCart($record, $clip_ctrl->level1); 628 } elseif ($others == 'ancestorsfamilies') { 629 $clip_ctrl->addAncestorsToCartFamilies($record, $clip_ctrl->level2); 630 } elseif ($others == 'members') { 631 foreach ($record->getSpouseFamilies() as $family) { 632 $clip_ctrl->addClipping($family); 633 $clip_ctrl->addFamilyMembers($family); 634 } 635 } elseif ($others == 'descendants') { 636 foreach ($record->getSpouseFamilies() as $family) { 637 $clip_ctrl->addClipping($family); 638 $clip_ctrl->addFamilyDescendancy($family, $clip_ctrl->level3); 639 } 640 } 641 } 642 } elseif ($remove) { 643 unset($cart[$WT_TREE->getTreeId()][$remove]); 644 Session::put('cart', $cart); 645 } elseif (isset($_REQUEST['empty'])) { 646 $cart[$WT_TREE->getTreeId()] = []; 647 Session::put('cart', $cart); 648 } elseif (isset($_REQUEST['download'])) { 649 return $this->downloadForm(); 650 } 651 652 return $this->getCartList(); 653 } 654 655 /** 656 * A list for the side bar. 657 * 658 * @return string 659 */ 660 public function getCartList() { 661 global $WT_TREE; 662 663 $cart = Session::get('cart', []); 664 if (!array_key_exists($WT_TREE->getTreeId(), $cart)) { 665 $cart[$WT_TREE->getTreeId()] = []; 666 } 667 $pid = Filter::get('pid', WT_REGEX_XREF); 668 669 if (!$cart[$WT_TREE->getTreeId()]) { 670 $out = I18N::translate('Your clippings cart is empty.'); 671 } else { 672 $out = ''; 673 if (!empty($cart[$WT_TREE->getTreeId()])) { 674 $out .= 675 '<a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&empty=true&pid=' . $pid . '" class="remove_cart">' . 676 I18N::translate('Empty the clippings cart') . 677 '</a>' . 678 '<br>' . 679 '<a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&download=true&pid=' . $pid . '" class="add_cart">' . 680 I18N::translate('Download') . 681 '</a><br><br>'; 682 } 683 $out .= '<ul>'; 684 foreach (array_keys($cart[$WT_TREE->getTreeId()]) as $xref) { 685 $record = GedcomRecord::getInstance($xref, $WT_TREE); 686 if ($record instanceof Individual || $record instanceof Family) { 687 switch ($record::RECORD_TYPE) { 688 case 'INDI': 689 $icon = 'icon-indis'; 690 break; 691 case 'FAM': 692 $icon = 'icon-sfamily'; 693 break; 694 } 695 $out .= '<li>'; 696 if (!empty($icon)) { 697 $out .= '<i class="' . $icon . '"></i>'; 698 } 699 $out .= '<a href="' . e($record->url()) . '">'; 700 if ($record instanceof Individual) { 701 $out .= $record->getSexImage(); 702 } 703 $out .= ' ' . $record->getFullName() . ' '; 704 if ($record instanceof Individual && $record->canShow()) { 705 $out .= ' (' . $record->getLifeSpan() . ')'; 706 } 707 $out .= '</a>'; 708 $out .= '<a class="icon-remove remove_cart" href="module.php?mod=' . $this->getName() . '&mod_action=ajax&remove=' . $xref . '&pid=' . $pid . '" title="' . I18N::translate('Remove') . '"></a>'; 709 $out .= '</li>'; 710 } 711 } 712 $out .= '</ul>'; 713 } 714 715 $record = Individual::getInstance($pid, $WT_TREE); 716 if ($record && !array_key_exists($record->getXref(), $cart[$WT_TREE->getTreeId()])) { 717 $out .= '<br><a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&action=add1&type=INDI&id=' . $pid . '&pid=' . $pid . '" class="add_cart"><i class="icon-clippings"></i> ' . I18N::translate('Add %s to the clippings cart', $record->getFullName()) . '</a>'; 718 } 719 720 return $out; 721 } 722 723 /** 724 * A form to choose the download options. 725 * 726 * @return string 727 */ 728 public function downloadForm() { 729 global $WT_TREE; 730 731 $pid = Filter::get('pid', WT_REGEX_XREF); 732 733 $out = '<script>'; 734 $out .= 'function cancelDownload() { 735 var link = "module.php?mod=' . $this->getName() . '&mod_action=ajax&pid=' . $pid . '"; 736 $("#sb_clippings_content").load(link); 737 }'; 738 $out .= '</script>'; 739 $out .= '<form class="wt-page-options wt-page-options-clipping-cart hidden-print" action="module.php"> 740 <input type="hidden" name="mod" value="clippings"> 741 <input type="hidden" name="mod_action" value="index"> 742 <input type="hidden" name="pid" value="' . $pid . '"> 743 <input type="hidden" name="action" value="download"> 744 <table> 745 <tr><td colspan="2" class="topbottombar"><h2>' . I18N::translate('Download') . '</h2></td></tr> 746 '; 747 748 if (Auth::isManager($WT_TREE)) { 749 $out .= 750 '<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Apply privacy settings') . '</td>' . 751 '<td class="optionbox">' . 752 '<input type="radio" name="privatize_export" value="none" checked> ' . I18N::translate('None') . '<br>' . 753 '<input type="radio" name="privatize_export" value="gedadmin"> ' . I18N::translate('Manager') . '<br>' . 754 '<input type="radio" name="privatize_export" value="user"> ' . I18N::translate('Member') . '<br>' . 755 '<input type="radio" name="privatize_export" value="visitor"> ' . I18N::translate('Visitor') . 756 '</td></tr>'; 757 } elseif (Auth::isMember($WT_TREE)) { 758 $out .= 759 '<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Apply privacy settings') . '</td>' . 760 '<td class="list_value">' . 761 '<input type="radio" name="privatize_export" value="user" checked> ' . I18N::translate('Member') . '<br>' . 762 '<input type="radio" name="privatize_export" value="visitor"> ' . I18N::translate('Visitor') . 763 '</td></tr>'; 764 } 765 766 $out .= ' 767 <tr><td class="descriptionbox width50 wrap">' . I18N::translate('Convert from UTF-8 to ISO-8859-1') . '</td> 768 <td class="optionbox"><input type="checkbox" name="convert" value="yes"></td></tr> 769 770 <tr><td class="topbottombar" colspan="2"> 771 <input type="button" class="btn btn-secondary" value="' . /* I18N: A button label. */ I18N::translate('cancel') . '" onclick="cancelDownload();"> 772 <input type="submit" class="btn btn-primary" value="' . /* I18N: A button label. */ I18N::translate('download') . '"> 773 </form>'; 774 775 return $out; 776 } 777} 778