1<?php 2 3/** 4 * Plugin RefNotes: Renderer 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Mykola Ostrovskyy <dwpforge@gmail.com> 8 */ 9 10//////////////////////////////////////////////////////////////////////////////////////////////////// 11class refnotes_renderer_mock { 12 13 /** 14 * 15 */ 16 public function renderReference($reference) { 17 return ''; 18 } 19} 20 21//////////////////////////////////////////////////////////////////////////////////////////////////// 22abstract class refnotes_renderer_base { 23 24 protected $namespace; 25 26 /** 27 * Constructor 28 */ 29 public function __construct($namespace) { 30 $this->namespace = $namespace; 31 } 32 33 /** 34 * 35 */ 36 protected function getStyle($name) { 37 return $this->namespace->getStyle($name); 38 } 39 40 /** 41 * Returns an array of keys for data that is shared between references and notes. 42 */ 43 abstract public function getReferenceSharedDataSet(); 44 45 /** 46 * Returns an array of keys for data that is specific to references. 47 */ 48 abstract public function getReferencePrivateDataSet(); 49 50 /** 51 * 52 */ 53 abstract public function renderReference($mode, $reference); 54 55 /** 56 * 57 */ 58 abstract public function renderNoteText($note); 59 60 /** 61 * 62 */ 63 abstract public function renderNote($mode, $note, $reference); 64} 65 66//////////////////////////////////////////////////////////////////////////////////////////////////// 67class refnotes_renderer extends refnotes_renderer_base { 68 69 private $referenceRenderer; 70 private $noteRenderer; 71 72 /** 73 * Constructor 74 */ 75 public function __construct($namespace) { 76 parent::__construct($namespace); 77 78 $this->referenceRenderer = $this->createRenderer($this->getStyle('reference-render')); 79 $this->noteRenderer = $this->createRenderer($this->getStyle('note-render')); 80 } 81 82 /** 83 * 84 */ 85 private function createRenderer($style) { 86 switch ($style) { 87 case 'harvard': 88 $renderer = new refnotes_harvard_renderer($this->namespace); 89 break; 90 91 default: 92 $renderer = new refnotes_basic_renderer($this->namespace); 93 break; 94 } 95 96 return $renderer; 97 } 98 99 /** 100 * 101 */ 102 public function getReferenceSharedDataSet() { 103 return $this->referenceRenderer->getReferenceSharedDataSet(); 104 } 105 106 /** 107 * 108 */ 109 public function getReferencePrivateDataSet() { 110 return $this->referenceRenderer->getReferencePrivateDataSet(); 111 } 112 113 /** 114 * 115 */ 116 public function renderReference($mode, $reference) { 117 return $this->referenceRenderer->renderReference($mode, $reference); 118 } 119 120 /** 121 * 122 */ 123 public function renderNotesSeparator() { 124 $html = ''; 125 $style = $this->getStyle('notes-separator'); 126 if ($style != 'none') { 127 if (!empty($style)) { 128 $style = ' style="width: '. $style . '"'; 129 } 130 $html = '<hr' . $style . '>' . DOKU_LF; 131 } 132 133 return $html; 134 } 135 136 /** 137 * 138 */ 139 public function renderNoteText($note) { 140 return $this->noteRenderer->renderNoteText($note); 141 } 142 143 /** 144 * 145 */ 146 public function renderNote($mode, $note, $reference) { 147 return $this->noteRenderer->renderNote($mode, $note, $reference); 148 } 149} 150 151//////////////////////////////////////////////////////////////////////////////////////////////////// 152class refnotes_renderer_data { 153 154 private $data; 155 156 /** 157 * Constructor 158 */ 159 public function __construct($data) { 160 $this->data = $data; 161 } 162 163 /** 164 * 165 */ 166 public function has($key) { 167 if (func_num_args() > 1) { 168 $result = false; 169 170 foreach (func_get_args() as $key) { 171 if (array_key_exists($key, $this->data)) { 172 $result = true; 173 break; 174 } 175 } 176 177 return $result; 178 } 179 else { 180 return array_key_exists($key, $this->data); 181 } 182 } 183 184 /** 185 * 186 */ 187 public function get($key) { 188 if (func_num_args() > 1) { 189 $result = ''; 190 191 foreach (func_get_args() as $key) { 192 if (array_key_exists($key, $this->data)) { 193 $result = $this->data[$key]; 194 break; 195 } 196 } 197 198 return $result; 199 } 200 else { 201 return array_key_exists($key, $this->data) ? $this->data[$key] : ''; 202 } 203 } 204 205 /** 206 * 207 */ 208 public function getLongest() { 209 $result = ''; 210 211 if (func_num_args() > 0) { 212 foreach (func_get_args() as $key) { 213 if (array_key_exists($key, $this->data) && (strlen($result) < strlen($this->data[$key]))) { 214 $result = $this->data[$key]; 215 } 216 } 217 } 218 else { 219 foreach ($this->data as $value) { 220 if (strlen($result) < strlen($value)) { 221 $result = $value; 222 } 223 } 224 } 225 226 return $result; 227 } 228 229 /** 230 * 231 */ 232 public function isPositive($key) 233 { 234 static $lookup = array('y', 'yes', 'on', 'true', '1'); 235 236 return in_array(strtolower($this->get($key)), $lookup); 237 } 238} 239 240//////////////////////////////////////////////////////////////////////////////////////////////////// 241class refnotes_basic_renderer extends refnotes_renderer_base { 242 243 protected $renderedNoteId = array(); 244 245 /** 246 * 247 */ 248 public function getReferenceSharedDataSet() { 249 return array(); 250 } 251 252 /** 253 * 254 */ 255 public function getReferencePrivateDataSet() { 256 return array(); 257 } 258 259 /** 260 * 261 */ 262 public function renderReference($mode, $reference) { 263 if ($reference->isInline()) { 264 $doc = $this->renderInlineReference($reference); 265 } 266 else { 267 $doc = $this->renderRegularReference($mode, $reference); 268 } 269 270 return $doc; 271 } 272 273 /** 274 * 275 */ 276 public function renderNoteText($note) { 277 $data = new refnotes_renderer_data($note->getData()); 278 279 $text = $data->get('note-text', 'title'); 280 281 if (empty($text)) { 282 $text = $data->getLongest(); 283 } 284 285 if ($url = $data->get('url')) { 286 $text = '[[' . $url . '|' . $text . ']]'; 287 } 288 289 return $text; 290 } 291 292 /** 293 * 294 */ 295 public function renderNote($mode, $note, $reference) { 296 $doc = ''; 297 298 switch ($mode) { 299 case 'xhtml': 300 $doc = $this->renderNoteXhtml($note, $reference); 301 break; 302 303 case 'odt': 304 $doc = $this->renderNoteOdt($note, $reference); 305 break; 306 } 307 308 return $doc; 309 } 310 311 /** 312 * 313 */ 314 protected function renderNoteXhtml($note, $reference) { 315 $html = '<div class="' . $this->renderNoteClass() . '">' . DOKU_LF; 316 $html .= $this->renderBackReferences($note, $reference); 317 $html .= '<span id="' . $note->getAnchorName() . ':text">' . DOKU_LF; 318 $html .= $note->getText() . DOKU_LF; 319 $html .= '</span></div>' . DOKU_LF; 320 321 $this->rendered = true; 322 323 return $html; 324 } 325 326 /** 327 * 328 */ 329 protected function renderNoteOdt($note, $reference) { 330 $this->rendered = true; 331 332 return ''; 333 } 334 335 /** 336 * 337 */ 338 protected function getInlineReferenceStyle($reference, $name, $default) { 339 return ($reference->getAttribute('use-' . $name) === false) ? $default : $this->getStyle($name); 340 } 341 342 /** 343 * 344 */ 345 protected function renderInlineReference($reference) { 346 $baseStyle = $this->getInlineReferenceStyle($reference, 'reference-base', 'text'); 347 $fontWeightStyle = $this->getInlineReferenceStyle($reference, 'reference-font-weight', 'normal'); 348 $fontStyle = $this->getInlineReferenceStyle($reference, 'reference-font-style', 'normal'); 349 $formatStyle = $this->getInlineReferenceStyle($reference, 'reference-format', 'none'); 350 351 list($baseOpen, $baseClose) = $this->renderBase($baseStyle); 352 list($fontOpen, $fontClose) = $this->renderFont($fontWeightStyle, 'normal', $fontStyle); 353 list($formatOpen, $formatClose) = $this->renderFormat($formatStyle); 354 355 $html = $baseOpen . $fontOpen . $formatOpen; 356 $html .= $reference->getNote()->getText(); 357 $html .= $formatClose . $fontClose . $baseClose; 358 359 return $html; 360 } 361 362 /** 363 * 364 */ 365 protected function renderRegularReference($mode, $reference) { 366 $doc = ''; 367 368 switch ($mode) { 369 case 'xhtml': 370 $doc = $this->renderRegularReferenceXhtml($reference); 371 break; 372 373 case 'odt': 374 $doc = $this->renderRegularReferenceOdt($reference); 375 break; 376 } 377 378 return $doc; 379 } 380 381 /** 382 * 383 */ 384 protected function renderRegularReferenceXhtml($reference) { 385 $noteName = $reference->getNote()->getAnchorName(); 386 $referenceName = $reference->getAnchorName(); 387 $class = $this->renderReferenceClass(); 388 389 list($baseOpen, $baseClose) = $this->renderReferenceBase(); 390 list($fontOpen, $fontClose) = $this->renderReferenceFont(); 391 list($formatOpen, $formatClose) = $this->renderReferenceFormat($reference); 392 393 $html = $baseOpen . $fontOpen; 394 $html .= '<a href="#' . $noteName . '" name="' . $referenceName . '" class="' . $class . '">'; 395 $html .= $formatOpen . $this->renderReferenceId($reference) . $formatClose; 396 $html .= '</a>'; 397 $html .= $fontClose . $baseClose; 398 399 return $html; 400 } 401 402 /** 403 * 404 */ 405 protected function renderRegularReferenceOdt($reference) { 406 $xmlOdt = ''; 407 $note = $reference->getNote(); 408 $noteId = $note->getId(); 409 $refId = $reference->getId(); 410 411 // Check to see if this note has been seen before 412 413 if (array_search($noteId, $this->renderedNoteId) === false) { 414 // new note, add it to the $renderedNoteId array 415 $this->renderedNoteId[] = $noteId; 416 417 $xmlOdt .= '<text:note text:id="refnote' . $refId . '" text:note-class="footnote">'; 418 $xmlOdt .= '<text:note-citation text:label="' . $refId . '">' . $refId . '</text:note-citation>'; 419 $xmlOdt .= '<text:note-body>'; 420 $xmlOdt .= '<text:p>' . $note->getText(); 421 $xmlOdt .= '</text:p>'; 422 $xmlOdt .= '</text:note-body>'; 423 $xmlOdt .= '</text:note>'; 424 } 425 else { 426 // Seen this one before - just reference it FIXME: style isn't correct 427 $xmlOdt = '<text:note-ref text:note-class="footnote" text:ref-name="refnote' . $noteId . '">'; 428 $xmlOdt .= $refId; 429 $xmlOdt .= '</text:note-ref>'; 430 } 431 432 return $xmlOdt; 433 } 434 435 /** 436 * 437 */ 438 protected function renderBackReferences($note, $reference) { 439 $references = count($reference); 440 $singleReference = ($references == 1); 441 $nameAttribute = ' name="' . $note->getAnchorName() .'"'; 442 $backRefFormat = $this->getStyle('back-ref-format'); 443 $backRefCaret = ''; 444 $html = ''; 445 446 list($formatOpen, $formatClose) = $this->renderNoteIdFormat(); 447 448 if (($backRefFormat != 'note') && !empty($backRefFormat)) { 449 list($baseOpen, $baseClose) = $this->renderNoteIdBase(); 450 list($fontOpen, $fontClose) = $this->renderNoteIdFont(); 451 452 $html .= $baseOpen . $fontOpen; 453 $html .= '<a' . $nameAttribute .' class="nolink">'; 454 $html .= $formatOpen . $this->renderNoteId($note) . $formatClose; 455 $html .= '</a>'; 456 $html .= $fontClose . $baseClose . DOKU_LF; 457 458 $nameAttribute = ''; 459 $formatOpen = ''; 460 $formatClose = ''; 461 $backRefCaret = $this->renderBackRefCaret($singleReference); 462 } 463 464 if ($backRefFormat != 'none') { 465 $separator = $this->renderBackRefSeparator(); 466 467 list($baseOpen, $baseClose) = $this->renderBackRefBase(); 468 list($fontOpen, $fontClose) = $this->renderBackRefFont(); 469 470 $html .= $baseOpen . $backRefCaret; 471 472 for ($r = 0; $r < $references; $r++) { 473 $referenceName = $reference[$r]->getAnchorName(); 474 475 if ($r > 0) { 476 $html .= $separator . DOKU_LF; 477 } 478 479 $html .= $fontOpen; 480 $html .= '<a href="#' . $referenceName . '"' . $nameAttribute .' class="backref">'; 481 $html .= $formatOpen . $this->renderBackRefId($reference[$r], $r, $singleReference) . $formatClose; 482 $html .= '</a>'; 483 $html .= $fontClose; 484 485 $nameAttribute = ''; 486 } 487 488 $html .= $baseClose . DOKU_LF; 489 } 490 491 return $html; 492 } 493 494 /** 495 * 496 */ 497 protected function renderReferenceClass() { 498 switch ($this->getStyle('note-preview')) { 499 case 'tooltip': 500 $result = 'refnotes-ref note-tooltip'; 501 break; 502 503 case 'none': 504 $result = 'refnotes-ref'; 505 break; 506 507 default: 508 $result = 'refnotes-ref note-popup'; 509 break; 510 } 511 512 return $result; 513 } 514 515 /** 516 * 517 */ 518 protected function renderReferenceBase() { 519 return $this->renderBase($this->getStyle('reference-base')); 520 } 521 522 /** 523 * 524 */ 525 protected function renderReferenceFont() { 526 return $this->renderFont('reference-font-weight', 'normal', 'reference-font-style'); 527 } 528 529 /** 530 * 531 */ 532 protected function renderReferenceFormat($reference) { 533 $result = $this->renderFormat($this->getStyle('reference-format')); 534 535 if ($this->getReferenceGrouping($reference)) { 536 switch ($reference->getAttribute('group')) { 537 case 'open': 538 $result = array($result[0], $this->renderReferenceGroupSeparator()); 539 break; 540 541 case 'hold': 542 $result = array('', $this->renderReferenceGroupSeparator()); 543 break; 544 545 case 'close': 546 $result = array('', $result[1]); 547 break; 548 } 549 } 550 551 return $result; 552 } 553 554 /** 555 * 556 */ 557 protected function getReferenceGrouping($reference) { 558 $group = $reference->getAttribute('group'); 559 return !empty($group) && in_array($group, array('open', 'hold', 'close')) && 560 in_array($this->getStyle('reference-group'), array(',', 's')); 561 } 562 563 /** 564 * 565 */ 566 protected function renderReferenceGroupSeparator() { 567 $style = $this->getStyle('reference-group'); 568 switch ($style) { 569 case ',': 570 $result = ','; 571 break; 572 573 case 's': 574 $result = ';'; 575 break; 576 577 default: 578 $result = ''; 579 break; 580 } 581 582 return $result; 583 } 584 585 /** 586 * 587 */ 588 protected function renderReferenceId($reference) { 589 $idStyle = $this->getStyle('refnote-id'); 590 if ($idStyle == 'name') { 591 $html = $reference->getNote()->getName(); 592 } 593 else { 594 switch ($this->getStyle('multi-ref-id')) { 595 case 'note': 596 $id = $reference->getNote()->getId(); 597 break; 598 599 default: 600 $id = $reference->getId(); 601 break; 602 } 603 604 $html = $this->convertToStyle($id, $idStyle); 605 } 606 607 return $html; 608 } 609 610 /** 611 * 612 */ 613 protected function renderNoteClass() { 614 $result = 'note'; 615 616 switch ($this->getStyle('note-font-size')) { 617 case 'normal': 618 break; 619 620 case 'small': 621 $result .= ' small'; 622 break; 623 624 default: 625 $result .= ' reduced'; 626 break; 627 } 628 629 switch ($this->getStyle('note-text-align')) { 630 case 'left': 631 $result .= ' left'; 632 break; 633 634 default: 635 $result .= ' justify'; 636 break; 637 } 638 639 return $result; 640 } 641 642 /** 643 * 644 */ 645 protected function renderNoteIdBase() { 646 return $this->renderBase($this->getStyle('note-id-base')); 647 } 648 649 /** 650 * 651 */ 652 protected function renderNoteIdFont() { 653 return $this->renderFont('note-id-font-weight', 'normal', 'note-id-font-style'); 654 } 655 656 /** 657 * 658 */ 659 protected function renderNoteIdFormat() { 660 $style = $this->getStyle('note-id-format'); 661 switch ($style) { 662 case '.': 663 $result = array('', '.'); 664 break; 665 666 default: 667 $result = $this->renderFormat($style); 668 break; 669 } 670 671 return $result; 672 } 673 674 /** 675 * 676 */ 677 protected function renderNoteId($note) { 678 $idStyle = $this->getStyle('refnote-id'); 679 if ($idStyle == 'name') { 680 $html = $note->getName(); 681 } 682 else { 683 $html = $this->convertToStyle($note->getId(), $idStyle); 684 } 685 686 return $html; 687 } 688 689 /** 690 * 691 */ 692 protected function renderBackRefCaret($singleReference) { 693 switch ($this->getStyle('back-ref-caret')) { 694 case 'prefix': 695 $result = '^ '; 696 break; 697 698 case 'merge': 699 $result = $singleReference ? '' : '^ '; 700 break; 701 702 default: 703 $result = ''; 704 break; 705 } 706 707 return $result; 708 } 709 710 /** 711 * 712 */ 713 protected function renderBackRefBase() { 714 return $this->renderBase($this->getStyle('back-ref-base')); 715 } 716 717 /** 718 * 719 */ 720 protected function renderBackRefFont() { 721 return $this->renderFont('back-ref-font-weight', 'bold', 'back-ref-font-style'); 722 } 723 724 /** 725 * 726 */ 727 protected function renderBackRefSeparator() { 728 static $html = array('' => ',', 'none' => ''); 729 730 $style = $this->getStyle('back-ref-separator'); 731 if (!array_key_exists($style, $html)) { 732 $style = ''; 733 } 734 735 return $html[$style]; 736 } 737 738 /** 739 * 740 */ 741 protected function renderBackRefId($reference, $index, $singleReference) { 742 $style = $this->getStyle('back-ref-format'); 743 switch ($style) { 744 case 'a': 745 $result = $this->convertToLatin($index + 1, $style); 746 break; 747 748 case '1': 749 $result = $index + 1; 750 break; 751 752 case 'caret': 753 $result = '^'; 754 break; 755 756 case 'arrow': 757 $result = '↑'; 758 break; 759 760 default: 761 $result = $this->renderReferenceId($reference); 762 break; 763 } 764 765 if ($singleReference && ($this->getStyle('back-ref-caret') == 'merge')) { 766 $result = '^'; 767 } 768 769 return $result; 770 } 771 772 /** 773 * 774 */ 775 protected function renderBase($style) { 776 static $html = array( 777 '' => array('<sup>', '</sup>'), 778 'text' => array('', '') 779 ); 780 781 if (!array_key_exists($style, $html)) { 782 $style = ''; 783 } 784 785 return $html[$style]; 786 } 787 788 /** 789 * 790 */ 791 protected function renderFont($weight, $defaultWeight, $style) { 792 list($weightOpen, $weightClose) = $this->renderFontWeight($this->getStyle($weight), $defaultWeight); 793 list($styleOpen, $styleClose) = $this->renderFontStyle($this->getStyle($style)); 794 795 return array($weightOpen . $styleOpen, $styleClose . $weightClose); 796 } 797 798 /** 799 * 800 */ 801 protected function renderFontWeight($style, $default) { 802 static $html = array( 803 'normal' => array('', ''), 804 'bold' => array('<b>', '</b>') 805 ); 806 807 if (!array_key_exists($style, $html)) { 808 $style = $default; 809 } 810 811 return $html[$style]; 812 } 813 814 /** 815 * 816 */ 817 protected function renderFontStyle($style) { 818 static $html = array( 819 '' => array('', ''), 820 'italic' => array('<i>', '</i>') 821 ); 822 823 if (!array_key_exists($style, $html)) { 824 $style = ''; 825 } 826 827 return $html[$style]; 828 } 829 830 /** 831 * 832 */ 833 protected function renderFormat($style) { 834 static $html = array( 835 '' => array('', ')'), 836 '()' => array('(', ')'), 837 ']' => array('', ']'), 838 '[]' => array('[', ']'), 839 'none' => array('', '') 840 ); 841 842 if (!array_key_exists($style, $html)) { 843 $style = ''; 844 } 845 846 return $html[$style]; 847 } 848 849 /** 850 * 851 */ 852 protected function convertToStyle($id, $style) { 853 switch ($style) { 854 case 'a': 855 case 'A': 856 $result = $this->convertToLatin($id, $style); 857 break; 858 859 case 'i': 860 case 'I': 861 $result = $this->convertToRoman($id, $style); 862 break; 863 864 case '*': 865 $result = str_repeat('*', $id); 866 break; 867 868 default: 869 $result = $id; 870 break; 871 } 872 873 return $result; 874 } 875 876 /** 877 * 878 */ 879 protected function convertToLatin($number, $case) { 880 static $alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 881 882 $result = ''; 883 884 while ($number > 0) { 885 --$number; 886 $digit = $number % 26; 887 $result = $alpha[$digit] . $result; 888 $number = intval($number / 26); 889 } 890 891 if ($case == 'a') { 892 $result = strtolower($result); 893 } 894 895 return $result; 896 } 897 898 /** 899 * 900 */ 901 protected function convertToRoman($number, $case) { 902 static $lookup = array( 903 'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 904 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 905 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1 906 ); 907 908 $result = ''; 909 910 foreach ($lookup as $roman => $value) { 911 $matches = intval($number / $value); 912 913 if ($matches > 0) { 914 $result .= str_repeat($roman, $matches); 915 $number = $number % $value; 916 } 917 } 918 919 if ($case == 'i') { 920 $result = strtolower($result); 921 } 922 923 return $result; 924 } 925} 926 927//////////////////////////////////////////////////////////////////////////////////////////////////// 928class refnotes_harvard_renderer extends refnotes_basic_renderer { 929 930 /** 931 * Constructor 932 */ 933 public function __construct($namespace) { 934 parent::__construct($namespace); 935 } 936 937 /** 938 * 939 */ 940 public function getReferenceSharedDataSet() { 941 static $key = array('ref-authors', 'ref-author', 'authors', 'author', 'published', 'month', 'year'); 942 943 return $key; 944 } 945 946 /** 947 * 948 */ 949 public function getReferencePrivateDataSet() { 950 static $key = array('direct', 'pages', 'page'); 951 952 return $key; 953 } 954 955 /** 956 * 957 */ 958 public function renderNoteText($note) { 959 $data = new refnotes_renderer_data($note->getData()); 960 961 if (!$data->has('title')) { 962 return parent::renderNoteText($note); 963 } 964 965 // authors, published. //[[url|title.]]// edition. [format], publisher, pages, isbn. (accessed) 966 // authors, published. chapter In //[[url|title.]]// edition. [format], publisher, pages, isbn. (accessed) 967 // authors, published. [[url|title.]] //journal//, volume, [format], publisher, pages, issn. (accessed) 968 // authors, published. [[url|title.]] //booktitle//, [format], publisher, pages, issn. (accessed) 969 970 $title = $this->renderTitle($data); 971 972 // authors, published. //$title// edition. [format], publisher, pages, isbn. (accessed) 973 // authors, published. chapter In //$title// edition. [format], publisher, pages, isbn. (accessed) 974 // authors, published. $title //journal//, volume, [format], publisher, pages, issn. (accessed) 975 // authors, published. $title //booktitle//, [format], publisher, pages, issn. (accessed) 976 977 $authors = $this->renderAuthors($data); 978 979 // $authors? //$title// edition. [format], publisher, pages, isbn. (accessed) 980 // $authors? chapter In //$title// edition. [format], publisher, pages, isbn. (accessed) 981 // $authors? $title //journal//, volume, [format], publisher, pages, issn. (accessed) 982 // $authors? $title //booktitle//, [format], publisher, pages, issn. (accessed) 983 984 $publication = $this->renderPublication($data, !empty($authors)); 985 986 if ($data->has('journal')) { 987 // $authors? $title //journal//, volume, $publication? 988 989 $subtitle = $this->renderJournal($data); 990 } 991 elseif ($data->has('booktitle')) { 992 // $authors? $title //booktitle//, $publication? 993 994 $subtitle = $this->renderBookTitle($data); 995 } 996 997 if (!empty($subtitle)) { 998 // $authors? $title $subtitle?, $publication? 999 1000 $text = $title . ' ' . $subtitle; 1001 1002 // $authors? $text, $publication? 1003 1004 $text .= !empty($publication) ? ',' : '.'; 1005 } 1006 else { 1007 // $authors? //$title// edition. $publication? 1008 // $authors? chapter In //$title// edition. $publication? 1009 1010 $text = $this->renderBook($data, $title); 1011 } 1012 1013 // $authors? $text $publication? 1014 1015 if (!empty($authors)) { 1016 $text = $authors . ' ' . $text; 1017 } 1018 1019 if (!empty($publication)) { 1020 $text .= ' ' . $publication; 1021 } 1022 1023 return $text; 1024 } 1025 1026 /** 1027 * 1028 */ 1029 protected function renderTitle($data) { 1030 $text = $data->get('title') . '.'; 1031 1032 if ($url = $data->get('url')) { 1033 $text = '[[' . $url . '|' . $text . ']]'; 1034 } 1035 1036 return $text; 1037 } 1038 1039 /** 1040 * 1041 */ 1042 protected function renderAuthors($data) { 1043 $text = $data->get('authors', 'author'); 1044 1045 if (!empty($text)) { 1046 if ($published = $this->renderPublished($data)) { 1047 $text .= ', ' . $published; 1048 } 1049 1050 $text .= '.'; 1051 } 1052 1053 return $text; 1054 } 1055 1056 /** 1057 * 1058 */ 1059 protected function renderPublished($data, $useMonth = true) { 1060 $text = $data->get('published'); 1061 1062 if (empty($text)) { 1063 if ($text = $data->get('year')) { 1064 if ($useMonth && $month = $data->get('month')) { 1065 $text = $month . ' ' . $text; 1066 } 1067 } 1068 } 1069 1070 return $text; 1071 } 1072 1073 /** 1074 * 1075 */ 1076 protected function renderPublication($data, $authors) { 1077 $part = array(); 1078 1079 if ($format = $data->get('format')) { 1080 $part[] = '[' . $format . ']'; 1081 } 1082 1083 $address = $data->get('address'); 1084 $publisher = $data->get('publisher'); 1085 1086 if ($address && $publisher) { 1087 $part[] = $address . ': ' . $publisher; 1088 } 1089 else { 1090 if ($address || $publisher) { 1091 $part[] = $address . $publisher; 1092 } 1093 } 1094 1095 if (!$authors && ($published = $this->renderPublished($data))) { 1096 $part[] = $published; 1097 } 1098 1099 if ($pages = $this->renderPages($data, array('note-pages', 'note-page', 'pages', 'page'))) { 1100 $part[] = $pages; 1101 } 1102 1103 if ($isbn = $data->get('isbn')) { 1104 $part[] = 'ISBN ' . $isbn; 1105 } 1106 elseif ($issn = $data->get('issn')) { 1107 $part[] = 'ISSN ' . $issn; 1108 } 1109 1110 $text = implode(', ', $part); 1111 1112 if (!empty($text)) { 1113 $text = rtrim($text, '.') . '.'; 1114 } 1115 1116 if ($accessed = $data->get('accessed')) { 1117 $accessed = '(' . refnotes_localization::getInstance()->getLang('txt_accessed_cap') . ': ' . $accessed . ')'; 1118 1119 if (!empty($text)) { 1120 $text .= ' ' . $accessed; 1121 } 1122 else { 1123 $text = $accessed; 1124 } 1125 } 1126 1127 return $text; 1128 } 1129 1130 /** 1131 * 1132 */ 1133 protected function renderPages($data, $key) { 1134 $text = ''; 1135 1136 foreach ($key as $k) { 1137 if ($text = $data->get($k)) { 1138 if (preg_match("/^[0-9]/", $text)) { 1139 $abbr_key = (substr($k, -1) == 's') ? 'txt_pages_abbr' : 'txt_page_abbr'; 1140 $text = refnotes_localization::getInstance()->getLang($abbr_key) . $text; 1141 } 1142 break; 1143 } 1144 } 1145 1146 return $text; 1147 } 1148 1149 /** 1150 * 1151 */ 1152 protected function renderJournal($data) { 1153 $text = '//' . $data->get('journal') . '//'; 1154 1155 if ($volume = $data->get('volume')) { 1156 $text .= ', ' . $volume; 1157 } 1158 1159 return $text; 1160 } 1161 1162 /** 1163 * 1164 */ 1165 protected function renderBook($data, $title) { 1166 $text = '//' . $title . '//'; 1167 1168 if ($chapter = $data->get('chapter')) { 1169 $text = $chapter . '. ' . refnotes_localization::getInstance()->getLang('txt_in_cap') . ' ' . $text; 1170 } 1171 1172 if ($edition = $data->get('edition')) { 1173 $text .= ' ' . $edition . '.'; 1174 } 1175 1176 return $text; 1177 } 1178 1179 /** 1180 * 1181 */ 1182 protected function renderBookTitle($data) { 1183 return '//' . $data->get('booktitle') . '//'; 1184 } 1185 1186 /** 1187 * 1188 */ 1189 protected function renderReferenceId($reference) { 1190 $data = new refnotes_renderer_data($reference->getData()); 1191 1192 if (!$this->checkReferenceData($data)) { 1193 return $this->renderBasicReferenceId($reference); 1194 } 1195 1196 $authors = $data->get('ref-authors', 'ref-author'); 1197 1198 if (empty($authors)) { 1199 $authors = $data->get('authors', 'author'); 1200 $authorList = explode(',', $authors, 4); 1201 1202 if (count($authorList) > 3) { 1203 $authors = $authorList[0] . refnotes_localization::getInstance()->getLang('txt_et_al'); 1204 } 1205 } 1206 1207 $html = $this->renderReferenceExtra($data); 1208 1209 list($formatOpen, $formatClose) = $this->renderReferenceParentheses(); 1210 1211 if ($data->isPositive('direct')) { 1212 $html = $authors . ' ' . $formatOpen . $html . $formatClose; 1213 1214 if ($this->getReferenceGrouping($reference)) { 1215 switch ($reference->getAttribute('group')) { 1216 case 'open': 1217 case 'hold': 1218 $html .= $this->renderReferenceGroupSeparator(); 1219 break; 1220 } 1221 } 1222 } 1223 else { 1224 if ($this->getReferenceGrouping($reference)) { 1225 switch ($reference->getAttribute('group')) { 1226 case 'open': 1227 $formatClose = $this->renderReferenceGroupSeparator(); 1228 break; 1229 1230 case 'hold': 1231 $formatOpen = ''; 1232 $formatClose = $this->renderReferenceGroupSeparator(); 1233 break; 1234 1235 case 'close': 1236 $formatOpen = ''; 1237 break; 1238 } 1239 } 1240 1241 $html = $formatOpen . $authors . ', ' . $html . $formatClose; 1242 } 1243 1244 return htmlspecialchars($html); 1245 } 1246 1247 /** 1248 * 1249 */ 1250 protected function renderBasicReferenceId($reference) { 1251 list($formatOpen, $formatClose) = parent::renderReferenceFormat($reference); 1252 1253 return $formatOpen . parent::renderReferenceId($reference) . $formatClose; 1254 } 1255 1256 /** 1257 * 1258 */ 1259 protected function renderReferenceExtra($data) { 1260 $html = ''; 1261 1262 if ($published = $this->renderPublished($data, false)) { 1263 $html .= $published; 1264 } 1265 1266 if ($pages = $this->renderPages($data, array('page', 'pages'))) { 1267 if (!empty($html)) { 1268 $html .= ', '; 1269 } 1270 1271 $html .= $pages; 1272 } 1273 1274 return $html; 1275 } 1276 1277 /** 1278 * 1279 */ 1280 protected function renderReferenceParentheses() { 1281 $style = $this->getStyle('reference-format'); 1282 $style = (($style == '[]') || ($style == ']')) ? '[]' : '()'; 1283 1284 return $this->renderFormat($style); 1285 } 1286 1287 /** 1288 * 1289 */ 1290 protected function renderReferenceFormat($reference) { 1291 return array('', ''); 1292 } 1293 1294 /** 1295 * 1296 */ 1297 protected function checkReferenceData($data) { 1298 $authors = $data->has('ref-authors', 'ref-author', 'authors', 'author'); 1299 $year = $data->has('published', 'year'); 1300 $page = $data->has('page', 'pages'); 1301 1302 return $authors && ($year || $page); 1303 } 1304} 1305