1<?php 2/** 3 * Outputs documentation in XML DocBook format, in the version expected by 4 * pear.php.net's documentation team 5 * 6 * phpDocumentor :: automatic documentation generator 7 * 8 * PHP versions 4 and 5 9 * 10 * Copyright (c) 2002-2006 Gregory Beaver 11 * 12 * LICENSE: 13 * 14 * This library is free software; you can redistribute it 15 * and/or modify it under the terms of the GNU Lesser General 16 * Public License as published by the Free Software Foundation; 17 * either version 2.1 of the License, or (at your option) any 18 * later version. 19 * 20 * This library is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * Lesser General Public License for more details. 24 * 25 * You should have received a copy of the GNU Lesser General Public 26 * License along with this library; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28 * 29 * @package Converters 30 * @subpackage XMLDocBook 31 * @author Greg Beaver <cellog@php.net> 32 * @copyright 2002-2006 Gregory Beaver 33 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 34 * @version CVS: $Id: XMLDocBookpeardoc2Converter.inc 234423 2007-04-24 21:32:15Z ashnazg $ 35 * @filesource 36 * @link http://www.phpdoc.org 37 * @link http://pear.php.net/PhpDocumentor 38 * @since 1.2 39 */ 40/** 41 * XML DocBook converter. 42 * This Converter takes output from the {@link Parser} and converts it to DocBook 43 * output for PEAR documentation. 44 * 45 * This Converter differs from the parent DocBook Converter in that it does not 46 * recognize the possibility of procedural pages or of functions! All functions 47 * must be defined as static methods for namespace purposes. In addition, all 48 * constants and global variables for a package are grouped together as per 49 * peardoc2 requirements. Include statements are not documented. If you want 50 * to document a normal project, don't use the peardoc2 converter, use the 51 * DocBook converter. 52 * @package Converters 53 * @subpackage XMLDocBook 54 * @author Greg Beaver <cellog@php.net> 55 * @since 1.2 56 * @version $Id: XMLDocBookpeardoc2Converter.inc 234423 2007-04-24 21:32:15Z ashnazg $ 57 */ 58class XMLDocBookpeardoc2Converter extends Converter 59{ 60 /** 61 * This converter knows about the new root tree processing 62 * In order to fix PEAR Bug #6389 63 * @var boolean 64 */ 65 var $processSpecialRoots = true; 66 /** 67 * XMLDocBookConverter wants elements sorted by type as well as alphabetically 68 * @see Converter::$sort_page_contents_by_type 69 * @var boolean 70 */ 71 var $sort_page_contents_by_type = true; 72 /** @var string */ 73 var $outputformat = 'XML'; 74 /** @var string */ 75 var $name = 'DocBook/peardoc2'; 76 /** 77 * indexes of elements by package that need to be generated 78 * @var array 79 */ 80 var $leftindex = array('classes' => true, 'pages' => false, 'functions' => false, 'defines' => true, 'globals' => true); 81 /** 82 * whether a @see is going to be in the {@link $base_dir}, or in a package/subpackage subdirectory of $base_dir 83 * @var boolean 84 */ 85 var $local = true; 86 87 /** 88 * name of current page being converted 89 * @var string 90 */ 91 var $page; 92 93 /** 94 * path of current page being converted 95 * @var string 96 */ 97 var $path; 98 99 /** 100 * name of current class being converted 101 * @var string 102 */ 103 var $class; 104 105 /** 106 * template for the procedural page currently being processed 107 * @var Template 108 */ 109 var $page_data; 110 111 /** 112 * output directory for the current procedural page being processed 113 * @var string 114 */ 115 var $page_dir; 116 117 /** 118 * Constants, used for constants.tpl 119 * @var array 120 */ 121 var $_peardoc2_constants = false; 122 123 /** 124 * Global Variables, used for globals.tpl 125 * @var array 126 */ 127 var $_peardoc2_globals = false; 128 129 /** 130 * target directory passed on the command-line. 131 * {@link $targetDir} is malleable, always adding package/ and package/subpackage/ subdirectories onto it. 132 * @var string 133 */ 134 var $base_dir; 135 136 /** 137 * output directory for the current class being processed 138 * @var string 139 */ 140 var $class_dir; 141 142 /** 143 * template for the class currently being processed 144 * @var Template 145 */ 146 var $class_data; 147 148 /** 149 * array of converted package page names. 150 * Used to link to the package page in the left index 151 * @var array Format: array(package => 1) 152 */ 153 var $package_pages = array(); 154 155 /** 156 * Contents of the packagename.xml file are stored in this template variable 157 * @var Smarty 158 */ 159 var $packagexml; 160 /** 161 * controls formatting of parser informative output 162 * 163 * Converter prints: 164 * "Converting /path/to/file.php... Procedural Page Elements... Classes..." 165 * Since HTMLdefaultConverter outputs files while converting, it needs to send a \n to start a new line. However, if there 166 * is more than one class, output is messy, with multiple \n's just between class file output. This variable prevents that 167 * and is purely cosmetic 168 * @var boolean 169 */ 170 var $juststarted = false; 171 172 /** 173 * contains all of the template procedural page element loop data needed for the current template 174 * @var array 175 */ 176 var $current; 177 178 /** 179 * contains all of the template class element loop data needed for the current template 180 * @var array 181 */ 182 var $currentclass; 183 184 /** 185 * Pass elements by package, simplifies generation of package.xml/category.xml 186 */ 187 var $sort_absolutely_everything = true; 188 /** 189 * template options. Currently only 1 recognized option usepear 190 * 191 * usepear tells the getLink() function to return a package link to PEAR and PEAR_ERROR if possible, and to link directly 192 * to the fully-delimited link package#class.method or package#file.method in PEAR style, if possible, even if the 193 * package is not parsed. This will allow parsing of separate PEAR packages without parsing the entire thing at once! 194 * @var array 195 */ 196 var $template_options = array('usepear' => false); 197 198 var $function_data = array(); 199 var $method_data = array(); 200 var $_write_constants_xml = array(); 201 var $_write_globals_xml = array(); 202 var $sourceloc = ''; 203 /** 204 * peardoc2 Category 205 * @var string 206 */ 207 var $category; 208 /** 209 * Used to re-format output so that it's easy for translators to handle 210 * 211 * @var XML_Beautifier|false 212 * @access private 213 */ 214 var $_beautifier = false; 215 216 /** 217 * sets {@link $base_dir} to $targetDir 218 * @see Converter() 219 */ 220 function XMLDocBookpeardoc2Converter(&$allp, &$packp, &$classes, &$procpages, $po, $pp, $qm, $targetDir, $templateDir, $title) 221 { 222 if (!class_exists('XML_Beautifier')) { 223 @include_once 'XML/Beautifier.php'; 224 } 225 Converter::Converter($allp, $packp, $classes, $procpages,$po, $pp, $qm, $targetDir, $templateDir, $title); 226 if (class_exists('XML_Beautifier')) { 227 require_once 'phpDocumentor/Converters/XML/DocBook/peardoc2/Beautifier.php'; 228 $this->_beautifier = new phpDocumentor_peardoc2_XML_Beautifier; 229 $this->_beautifier->setOption('indent', ' '); 230 } 231 $this->base_dir = $targetDir; 232 } 233 234 /** 235 * do that stuff in $template_options 236 */ 237 function &getLink($expr, $package = false, $packages = false) 238 { 239 return Converter::getLink($expr, $package, $packages); 240 } 241 242 function unmangle($s,$sourcecode) 243 { 244 return '<programlisting role="php"><![CDATA[ 245'.$sourcecode.']]></programlisting>'; 246 } 247 248 /** 249 * Writes a file to target dir, beautify any .xml files first 250 * @param string filename 251 * @param string file contents 252 * @param boolean true if the data is binary and not text 253 */ 254 function writeFile($file,$data,$binary = false) 255 { 256 if ($this->_beautifier && substr($file, -4) == '.xml') { 257 $ret = $this->_beautifier->formatString($data); 258 if (PEAR::isError($ret)) { 259 addWarning(PDERROR_BEAUTIFYING_FAILED, $ret->getMessage()); 260 $ret = $data; 261 } 262 $data = $ret; 263 } 264 return parent::writeFile($file, $data, $binary); 265 } 266 267 /** 268 * Used to convert the {@}example} inline tag in a docblock. 269 * 270 * By default, this just wraps ProgramExample 271 * @see XMLDocBookpeardoc2Converter::exampleProgramExample 272 * @param string 273 * @param boolean true if this is to highlight a tutorial <programlisting> 274 * @return string 275 */ 276 function exampleProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/, 277 $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/) 278 { 279 return '<example><title>Example</title><programlisting role="php"><![CDATA[' . 280 $example . ']]></programlisting></example>'; 281 $this->ProgramExample($example, $tutorial, $inlinesourceparse, $class, $linenum, $filesourcepath) 282 . '</example>'; 283 } 284 285 function writeExample($title, $path, $source) 286 { 287 $this->_save_example = array($title, $source); 288 } 289 290 function getExampleLink($unused, $title) 291 { 292 $source = $this->_save_example[1]; 293 return '<para><example><title>' . $title . '</title>' . $source . '</example></para>'; 294 } 295 296 function type_adjust($typename) 297 { 298 if (isset($this->template_options['typechanging'][trim($typename)])) 299 return $this->template_options['typechanging'][trim($typename)]; 300 $a = $this->getLink($typename); 301 if (is_object($a)) 302 { 303 if (phpDocumentor_get_class($a) == 'classlink') 304 return '<classname>'.$typename.'</classname>'; 305 if (phpDocumentor_get_class($a) == 'functionlink' || phpDocumentor_get_class($a) == 'methodlink') 306 return '<function>'.$typename.'</function>'; 307 if (phpDocumentor_get_class($a) == 'definelink') 308 return '<constant>'.$typename.'</constant>'; 309 if (phpDocumentor_get_class($a) == 'varlink') 310 return '<varname>'.$typename.'</varname>'; 311 } 312 return $typename; 313 } 314 315 /** 316 * Writes out the template file of {@link $class_data} and unsets the template to save memory 317 * @see registerCurrentClass() 318 * @see parent::endClass() 319 * @todo move class summary into an array to be written out at the end 320 * of parsing each package 321 */ 322 function endClass() 323 { 324 $a = '../'; 325 if (!empty($this->subpackage)) $a .= '../'; 326 if ($this->juststarted) 327 { 328 $this->juststarted = false; 329 phpDocumentor_out("\n"); 330 flush(); 331 } 332 foreach($this->method_data as $func) 333 { 334 $func[0]->assign("phpdocversion",PHPDOCUMENTOR_VER); 335 $func[0]->assign("phpdocwebsite",PHPDOCUMENTOR_WEBSITE); 336 $this->setTargetDir($this->base_dir . PATH_DELIMITER . strtolower($this->category) . PATH_DELIMITER . strtolower($this->class_dir . PATH_DELIMITER . str_replace(array('_','.'),array('-','--'),$this->class))); 337 $this->writefile(strtolower($func[1] ). '.xml','<!-- $' . "Revision$ -->\n" . $func[0]->fetch('method.tpl')); 338 } 339 // code below is in packagename.xml handling, see Output() 340/* $this->setTargetDir($this->base_dir . PATH_DELIMITER . strtolower($this->category) . PATH_DELIMITER . strtolower($this->class_dir)); 341 $this->writefile(str_replace(array('_','.'),array('-','--'),strtolower($this->class)) . '.xml',$this->class_data->fetch('class.tpl'));*/ 342 unset($this->class_data); 343 } 344 345 function addSummaryToPackageXml($template_output) 346 { 347 $this->packagexml->append('ids',$template_output); 348 } 349 350 /** 351 * @param parserClass|false $element is false if this is the end of all conversion 352 */ 353 function flushPackageXml($element) 354 { 355 if (isset($this->packagexml)) 356 { 357 if (!$element || $element->docblock->package != $this->package) // finished with package 358 { 359 if (isset($this->_write_constants_xml[$this->category][$this->package]) && 360 $this->_write_constants_xml[$this->category][$this->package]) 361 { 362 $this->packagexml->append('ids', 363 '&package.' . 364 strtolower($this->category.'.' . 365 str_replace(array('_','.'),array('-','--'),$this->package).'.constants;')); 366 $this->_write_constants_xml[$this->category][$this->package] = false; 367 } 368 if (isset($this->_write_globals_xml[$this->category][$this->package]) && 369 $this->_write_globals_xml[$this->category][$this->package]) 370 { 371 $this->packagexml->append('ids', 372 '&package.'.strtolower($this->category.'.' . 373 str_replace(array('_','.'),array('-','--'),$this->package).'.globals;')); 374 $this->_write_globals_xml[$this->category][$this->package] = false; 375 } 376 $this->setTargetDir($this->base_dir . PATH_DELIMITER . strtolower($this->category)); 377 $this->writefile(str_replace('_','-',strtolower($this->package)).'.xml', 378 '<!-- $' . "Revision$ -->\n" . $this->packagexml->fetch('package.tpl')); 379 $this->packagexml->clear_all_assign(); 380 if ($element) { 381 $this->packagexml->assign('package',$element->docblock->package); 382 $this->packagexml->assign('ids',array()); 383 $this->packagexml->assign('id',$this->getId($element, true)); 384 } 385 } 386 } else 387 { 388 $this->packagexml = $this->newSmarty(); 389 $this->packagexml->assign('package',$element->docblock->package); 390 $this->packagexml->assign('ids',array()); 391 $this->packagexml->assign('id',$this->getId($element, true)); 392 } 393 } 394 395 /** 396 * @param string 397 * @param string 398 * @return string <ulink url="'.$link.'">'.$text.'</ulink> 399 */ 400 function returnLink($link,$text) 401 { 402 return '<ulink url="'.$link.'">'.$text.'</ulink>'; 403 } 404 405 function makeLeft() 406 { 407 } 408 409 /** 410 * Does nothing 411 */ 412 function formatPkgIndex() 413 { 414 } 415 416 /** 417 * Does nothing 418 */ 419 function formatIndex() 420 { 421 } 422 423 /** 424 * Does nothing 425 */ 426 function writeNewPPage($key) 427 { 428 } 429 430 /** 431 * Does nothing 432 */ 433 function writeSource() 434 { 435 } 436 437 /** 438 * Creates package/lang/categoryname/packagename.xml for each package 439 */ 440 function formatLeftIndex() 441 { 442 $this->makeLeft(); 443 } 444 445 /** 446 * This function takes an {@link abstractLink} descendant and returns an html link 447 * 448 * @param abstractLink a descendant of abstractlink should be passed, and never text 449 * @param string text to display in the link 450 * @param boolean this parameter is not used, and is deprecated 451 * @param boolean determines whether the returned text is enclosed in an <link> tag 452 */ 453 function returnSee(&$element, $eltext = false, $local = true, $with_a = true) 454 { 455 if (!$element) return false; 456 if (!$eltext) 457 { 458 $eltext = ''; 459 switch($element->type) 460 { 461 case 'tutorial' : 462 $eltext = $element->title; 463 break; 464 case 'class' : 465 $eltext = '<classname>'.$element->name.'</classname>'; 466 break; 467 case 'method' : 468 $eltext .= '<function>'; 469 case 'var' : 470 if ($element->type == 'var') $eltext .= '<varname>'; 471 $eltext .= $element->class.'::'; 472 case 'page' : 473 case 'define' : 474 if ($element->type == 'define') 475 $eltext .= '<constant>'; 476 case 'function' : 477 if ($element->type == 'function') 478 $eltext .= '<function>'; 479 case 'global' : 480 default : 481 $eltext .= $element->name; 482 if ($element->type == 'function' || $element->type == 'method') $eltext .= '</function>'; 483 if ($element->type == 'var') $eltext .= '</varname>'; 484 if ($element->type == 'define') $eltext .= '</constant>'; 485 break; 486 } 487 } elseif (!is_object($element)) { 488 return false; 489 } elseif ($element->type == 'method') 490 { 491 $eltext = str_replace($element->name . '()', $element->name, $eltext); 492 } 493 494 if ($element->type == 'page' || $element->type == 'function' || $element->type == 'var') 495 { // we ignore all procedural pages, instead, constant, function and 496 // global variable pages are output 497 return $eltext; 498 } 499 if ($element->type == 'class') 500 { 501 return '<link linkend="'.$this->getId($element).'-summary">'.$eltext.'</link>'; 502 } 503 return '<link linkend="'.$this->getId($element).'">'.$eltext.'</link>'; 504 } 505 506 /** 507 * Get the id value needed to allow linking 508 * @param mixed descendant of parserElement or parserData/parserPage 509 * @param boolean true to return the id for the package page 510 * @see parserElement, parserData, parserPage 511 * @return string the id value for this element type 512 */ 513 function getId(&$el, $returnpackage = false) 514 { 515 if (phpDocumentor_get_class($el) == 'parserdata') 516 { 517 $element = $this->addLink($el->parent); 518 $elp = $el->parent; 519 } elseif (!is_a($el,'abstractlink')) 520 { 521 $elp = $el; 522 $element = $this->addLink($el); 523 } else $element = $el; 524 $a = ''; 525 if (!empty($element->subpackage)) 526 { 527 $a = str_replace(array('_','.'),array('-','--'),$element->subpackage).'.'; 528 } 529 if ($returnpackage) return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package)); 530 switch ($element->type) 531 { 532 case 'page' : 533 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.$element->fileAlias); 534 break; 535 case 'define' : 536 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.constants.details.'.$element->fileAlias); 537 break; 538 case 'global' : 539 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.globals.details.'.$element->fileAlias); 540 break; 541 case 'class' : 542 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->name)); 543 break; 544 case 'function' : 545 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.$element->fileAlias.'.'.str_replace('_','-',$element->name)); 546 break; 547 case 'method' : 548 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->class).'.'.str_replace('_','-',$element->name)); 549 break; 550 case 'var' : 551 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->class).'-summary.vars.'.str_replace(array('$','_'),array('var--','-'),$element->name)); 552 break; 553 case 'tutorial' : 554 return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->name)).'-tutorial'; 555 break; 556 } 557 } 558 559 /** 560 * Create errors.html template file output 561 * 562 * This method takes all parsing errors and warnings and spits them out ordered by file and line number. 563 * @global ErrorTracker We'll be using it's output facility 564 */ 565 function ConvertErrorLog() 566 { 567 global $phpDocumentor_errors; 568 $allfiles = array(); 569 $files = array(); 570 $warnings = $phpDocumentor_errors->returnWarnings(); 571 $errors = $phpDocumentor_errors->returnErrors(); 572 $template = &$this->newSmarty(); 573 foreach($warnings as $warning) 574 { 575 $file = '##none'; 576 $linenum = 'Warning'; 577 if ($warning->file) 578 { 579 $file = $warning->file; 580 $allfiles[$file] = 1; 581 $linenum .= ' on line '.$warning->linenum; 582 } 583 $files[$file]['warnings'][] = array('name' => $linenum, 'listing' => $warning->data); 584 } 585 foreach($errors as $error) 586 { 587 $file = '##none'; 588 $linenum = 'Error'; 589 if ($error->file) 590 { 591 $file = $error->file; 592 $allfiles[$file] = 1; 593 $linenum .= ' on line '.$error->linenum; 594 } 595 $files[$file]['errors'][] = array('name' => $linenum, 'listing' => $error->data); 596 } 597 $i=1; 598 $af = array(); 599 foreach($allfiles as $file => $num) 600 { 601 $af[$i++] = $file; 602 } 603 $allfiles = $af; 604 usort($allfiles,'strnatcasecmp'); 605 $allfiles[0] = "Post-parsing"; 606 foreach($allfiles as $i => $a) 607 { 608 $allfiles[$i] = array('file' => $a); 609 } 610 $out = array(); 611 foreach($files as $file => $data) 612 { 613 if ($file == '##none') $file = 'Post-parsing'; 614 $out[$file] = $data; 615 } 616 $template->assign("files",$allfiles); 617 $template->assign("all",$out); 618 $template->assign("title","phpDocumentor Parser Errors and Warnings"); 619 $this->setTargetDir($this->base_dir); 620 $this->writefile("errors.html",$template->fetch('errors.tpl')); 621 unset($template); 622 phpDocumentor_out("\n\nTo view errors and warnings, look at ".$this->base_dir. PATH_DELIMITER . "errors.html\n"); 623 flush(); 624 } 625 626 function postProcess($text) 627 { 628 return str_replace("'", ''', htmlentities($text)); 629 } 630 631 function prepareDocBlock(&$element, $nopackage = true) 632 { 633 $a = new parserStringWithInlineTags; 634 $a->add('no exceptions thrown'); 635 if (!$element->docblock->getKeyword('throws')) $element->docblock->addKeyword('throws',$a); 636 $tags = parent::prepareDocBlock($element, 637 array('staticvar' => 'note','deprec' => 'deprecated', 638 'abstract' => 'abstract','TODO' => 'note', 'link' => 'see', 639 'uses' => 'see', 'usedby' => 'see', 'tutorial' => 'see', 640 'return' => 'returns', 'access' => false), $nopackage); 641 $ret = array(); 642 foreach($tags['tags'] as $tag) 643 { 644 if ($tag['keyword'] == 'return') 645 { 646 // hack because stupid Converter isn't doing its job 647 $tag['keyword'] = 'returns'; 648 } 649 $ret[$tag['keyword']][] = $tag; 650 } 651 $tags['tags'] = $ret; 652 $tags['sdesc'] = $this->wordwrap($tags['sdesc']); 653 return $tags; 654 } 655 656 function getTutorialId($package,$subpackage,$tutorial,$id,$category) 657 { 658 $subpackage = (empty($subpackage) ? '' : '.'.$subpackage); 659 $id = (empty($id) ? '' : '.'.$id); 660 return 'package.'.strtolower($category.'.'.$package.$subpackage.str_replace(array('_','.'),array('-','--'),$tutorial).$id); 661 } 662 663 664 /** 665 * Retrieve a Converter-specific anchor to a segment of a source code file 666 * parsed via a {@tutorial tags.filesource.pkg} tag. 667 * 668 * NOTE: unused 669 * @param string full path to source file 670 * @param string name of anchor 671 * @param string link text, if this is a link 672 * @param boolean returns either a link or a destination based on this 673 * parameter 674 * @return string link to an anchor, or the anchor 675 */ 676 function getSourceAnchor($sourcefile,$anchor,$text = '',$link = false) 677 { 678 return ''; 679 } 680 681 function Br($input) 682 { 683 return "$input\n"; 684 } 685 686 function getCData($value) 687 { 688 return '<![CDATA['.$value.']]>'; 689 } 690 691 function ProgramExample($listing, $tutorial = false, $inlinesourceparse = null/*false*/, 692 $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/, $origsource = null) 693 { 694 if ($origsource !== null) { 695 $listing = $origsource; 696 } 697 if (!tokenizer_ext) 698 { 699 $listing = $this->getCData($listing); 700 } 701 return '<programlisting role="php">' . $this->getCData($listing) . '</programlisting>'; 702 } 703 704 /** 705 * Does nothing - use tutorials for DocBook 706 * @param parserPackagePage 707 */ 708 function convertPackagePage(&$element) 709 { 710 } 711 712 /** 713 * Convert tutorials for output 714 * @param parserTutorial 715 */ 716 function convertTutorial(&$element) 717 { 718 $template = &parent::convertTutorial($element); 719 phpDocumentor_out("\n"); 720 flush(); 721 $x = $element->Convert($this,false); 722 if ($element->ini) 723 { // add child tutorial list to the tutorial through a slight hack :) 724 $subtutorials = ''; 725 $b = ''; 726 if (!empty($element->subpackage)) $b = '.'.$element->subpackage; 727 foreach($element->ini['Linked Tutorials'] as $child) 728 { 729 $subtutorials .= ' &'.$element->category.'.'.$element->package.$b.'.'.str_replace(array('_','.'),array('-','--'),$child).'-'.$element->tutorial_type."-tutorial;\n"; 730 } 731 $x = str_replace('</refsect1></refentry>','</refsect1> 732 <refsect1> 733 <title>Related Docs</title> 734 <para> 735'.$subtutorials. 736' </para> 737 </refsect1></refentry>',$x); 738 } 739 $template->assign('contents',$x); 740 $contents = $template->fetch('tutorial.tpl'); 741 $a = ''; 742 if ($element->subpackage) $a = PATH_DELIMITER . $element->subpackage; 743 phpDocumentor_out("\n"); 744 flush(); 745 $this->setTargetDir($this->base_dir . PATH_DELIMITER . str_replace(array('_','.'),array('-','--'),strtolower($element->category)) 746 . PATH_DELIMITER . strtolower(str_replace(array('_','.'),array('-','--'),$element->package) . $a)); 747 $this->writeFile(str_replace(array('_','.'),array('-','--'),strtolower($element->name)).'-tutorial.xml', 748 '<!-- $' . "Revision$ -->\n" . $contents); 749 } 750 751 /** 752 * Does nothing in this converter 753 * @param parserVar 754 */ 755 function convertVar(&$element) 756 { 757 return; 758 $docblock = $this->prepareDocBlock($element); 759 $b = 'mixed'; 760 if ($element->docblock->var) 761 { 762 $b = $element->docblock->var->converted_returnType; 763 } 764// var_dump($this->getFormattedOverrides($element)); 765 if (isset($this->template_options['separatepage']) && $this->template_options['separatepage']) 766 $this->class_summary->append('vars',array('sdesc' => $docblock['sdesc'], 767 'desc' => $docblock['desc'], 768 'tags' => $docblock['tags'], 769 'var_name' => $this->type_adjust($element->getName()), 770 'var_default' => htmlspecialchars($element->getValue()), 771 'var_type' => $b, 772 'var_overrides' => $this->getFormattedOverrides($element), 773 'line_number' => $element->getLineNumber(), 774 'id' => $this->getId($element))); 775 else 776 $this->class_data->append('vars',array('sdesc' => $docblock['sdesc'], 777 'desc' => $docblock['desc'], 778 'tags' => $docblock['tags'], 779 'var_name' => $this->type_adjust($element->getName()), 780 'var_default' => htmlspecialchars($element->getValue()), 781 'var_type' => $b, 782 'var_overrides' => $this->getFormattedOverrides($element), 783 'line_number' => $element->getLineNumber(), 784 'id' => $this->getId($element))); 785 } 786 787 /** 788 * Converts class for template output 789 * @param parserClass 790 * @uses flushPackageXml() creates packagename.xml file when all classes in 791 * a package have been converted 792 */ 793 function convertClass(&$element) 794 { 795 $this->flushPackageXml($element); 796 parent::convertClass($element); 797 $docblock = $this->prepareDocBlock($element); 798 $this->method_data = array(); 799 $this->class_dir = str_replace(array('_','.'),array('-','--'),$element->docblock->package); 800 $this->package = $element->docblock->package; 801 $this->category = strtolower($element->docblock->category); 802 if (!empty($element->docblock->subpackage)) $this->class_dir .= PATH_DELIMITER . $element->docblock->subpackage; 803 $docblock = $this->prepareDocBlock($element,false); 804 $this->class_data->assign("sdesc",$docblock['sdesc']); 805 $this->class_data->assign("desc",$docblock['desc']); 806 $this->class_data->assign("tags",$docblock['tags']); 807 808 $this->class_data->assign("source_location",$element->getSourceLocation($this,$this->template_options['usepear'])); 809 $this->class_data->assign("id",$this->getId($element)); 810 $this->class_data->assign("method_ids",array()); 811 $this->left[$this->package][] = array('link' => $this->getId($element).'-summary'); 812 if ($t = $element->getTutorial()) 813 { 814 $this->class_data->append("method_ids",$this->getId($t)); 815 } 816 817 if (isset($this->template_options['separatepage']) && $this->template_options['separatepage']) 818 { 819 $this->class_summary = &$this->newSmarty(true); 820 if ($t = $element->getTutorial()) 821 { 822 $this->class_summary->assign("tutorial",$this->returnSee($t)); 823 } 824 825 $this->class_summary->assign("class_name",$this->type_adjust($element->getName())); 826 $this->class_summary->assign("sdesc",$docblock['sdesc']); 827 $this->class_summary->assign("desc",$docblock['desc']); 828 $this->class_summary->assign("tags",$docblock['tags']); 829 $this->class_summary->assign("vars",array()); 830 $this->class_summary->assign("methods",array()); 831 $this->class_summary->assign("package",$element->docblock->package); 832 833 $this->class_summary->assign("children", $this->generateChildClassList($element)); 834 $this->class_summary->assign("class_tree", $this->generateFormattedClassTree($element)); 835 $this->class_summary->assign("conflicts", $this->getFormattedConflicts($element,"classes")); 836 837 $this->class_summary->assign("source_location",$element->getSourceLocation($this,$this->template_options['usepear'])); 838 $this->class_summary->assign("id",$this->getId($element).'-summary'); 839 $this->class_data->append("method_ids",$this->getId($element).'.'.strtolower(str_replace('_','-',$element->getName())).'-summary'); 840 $inherited_methods = $this->getFormattedInheritedMethods($element); 841 if (!empty($inherited_methods)) 842 { 843 $this->class_summary->assign("imethods",$inherited_methods); 844 } 845 $inherited_vars = $this->getFormattedInheritedVars($element); 846 // variables are irrelevant in peardoc2 847 if (false)//!empty($inherited_vars)) 848 { 849 $this->class_summary->assign("ivars",$inherited_vars); 850 } 851 $this->addSummaryToPackageXml($this->class_summary->fetch('class_summary.tpl')); 852 } 853 $this->sourceloc = $element->getSourceLocation($this,$this->template_options['usepear']); 854 } 855 856 /** 857 * Converts method for template output 858 * @see prepareDocBlock(), parserMethod::getFunctionCall(), getFormattedDescMethods(), getFormattedOverrides() 859 * @param parserMethod 860 */ 861 function convertMethod(&$element) 862 { 863 $docblock = $this->prepareDocBlock($element); 864 $returntype = 'void'; 865 if ($element->docblock->return) 866 { 867 $a = $element->docblock->return->Convert($this); 868 $returntype = $element->docblock->return->converted_returnType; 869 if ($returntype != $element->docblock->return->returnType) 870 { 871 $returntype = "<replaceable>$returntype</replaceable>"; 872 } 873 } 874 $params = array(); 875 if (count($element->docblock->params)) 876 foreach($element->docblock->params as $param => $val) 877 { 878 $a = $val->Convert($this); 879 $b = explode(' ',$a); 880 $c = ''; 881 foreach($b as $blah) { 882 if (!empty($c)) { 883 $c .= ' '; 884 } 885 $c .= str_replace(array('true', 'false', 'null'), array('&true;', '&false;', '&null;'), $blah); 886 } 887 $params[$param] = array("var" => $param,"datatype" => str_replace(array('true', 'false', 'null'), array('&true;', '&false;', '&null;'), 888 $val->returnType), "cdatatype" => $val->converted_returnType,"data" => $this->wordwrap($c)); 889 } 890 891 $call = $element->getIntricateFunctionCall($this, $params); 892 if (isset($call['params'])) 893 { 894 foreach($call['params'] as $i => $param) 895 { 896 if (!is_string($call['params'][$i]['default'])) 897 { 898 continue; 899 } 900 $call['params'][$i]['default'] = str_replace(array('true', 'false', 'null'), array('&true;', '&false;', '&null;'), $param['default']); 901 } 902 } 903 $this->packagexml->append('ids','&'.$this->getId($element).';'); 904 $this->class_data->append('method_ids',$this->getId($element)); 905 $this->class_summary->append('methods',array('id' => $this->getId($element), 906 'sdesc' => $docblock['sdesc'], 907 'desc' => $docblock['desc'], 908 'tags' => $docblock['tags'], 909 'is_constructor' => $element->isConstructor, 910 'function_name' => $element->getName(), 911 'function_return' => $returntype, 912 'function_call' => $call, 913 'descmethod' => $this->getFormattedDescMethods($element), 914 'method_overrides' => $this->getFormattedOverrides($element), 915 'line_number' => $element->getLineNumber(), 916 'params' => $params)); 917 $this->method_data[$i = count($this->method_data) - 1][0] = &$this->newSmarty(true); 918 $this->method_data[$i][1] = str_replace(array('_','.'),array('-','--'),$element->getName()); 919 $this->method_data[$i][0]->assign('class',$this->class); 920 $this->method_data[$i][0]->assign('source_location',$this->returnSee($this->getLink(basename($this->curpage->getFile())),$this->sourceloc)); 921 $this->method_data[$i][0]->assign('sdesc',$docblock['sdesc']); 922 $this->method_data[$i][0]->assign('desc',$docblock['desc']); 923 $this->method_data[$i][0]->assign('tags',$docblock['tags']); 924 $this->method_data[$i][0]->assign('function_name',$element->getName()); 925 $this->method_data[$i][0]->assign('function_return',$returntype); 926 $this->method_data[$i][0]->assign('function_call',$call); 927 $this->method_data[$i][0]->assign('descmethod',$this->getFormattedDescMethods($element)); 928 $this->method_data[$i][0]->assign('method_overrides',$this->getFormattedOverrides($element)); 929 $this->method_data[$i][0]->assign('params',$params); 930 $this->method_data[$i][0]->assign('id',$this->getId($element)); 931 } 932 933 /** 934 * Converts function for template output - does nothing in peardoc2! 935 * @param parserFunction 936 */ 937 function convertFunction(&$element) 938 { 939/* parent::convertFunction($element); 940 $docblock = $this->prepareDocBlock($element); 941 $fname = $element->getName(); 942 $params = array(); 943 if (count($element->docblock->params)) 944 foreach($element->docblock->params as $param => $val) 945 { 946 $a = $val->Convert($this); 947 $params[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a); 948 } 949 $returntype = 'void'; 950 if ($element->docblock->return) 951 { 952 $a = $element->docblock->return->Convert($this); 953 $returntype = $element->docblock->return->converted_returnType; 954 } 955 956 $this->page_data->append("function_ids",$this->getId($element)); 957 $this->page_summary->append("function_ids",$this->getId($element)); 958 $this->page_summary->append('functions',array('id' => $this->getId($element), 959 'sdesc' => $docblock['sdesc'], 960 'desc' => $docblock['desc'], 961 'tags' => $docblock['tags'], 962 'function_name' => $element->getName(), 963 'line_number' => $element->getLineNumber(), 964 'function_return' => $returntype, 965 'function_call' => $element->getIntricateFunctionCall($this,$params), 966 'function_conflicts' => $this->getFormattedConflicts($element,'functions'), 967 'params' => $params)); 968 $this->function_data[$i = count($this->function_data) - 1][0] = $this->newSmarty(true); 969 $this->function_data[$i][1] = $element->getName(); 970 $this->function_data[$i][0]->assign('sdesc',$docblock['sdesc']); 971 $this->function_data[$i][0]->assign('desc',$docblock['desc']); 972 $this->function_data[$i][0]->assign('tags',$docblock['tags']); 973 $this->function_data[$i][0]->assign('function_name',$fname); 974 $this->function_data[$i][0]->assign('line_number',$element->getLineNumber()); 975 $this->function_data[$i][0]->assign('function_return',$returntype); 976 $this->function_data[$i][0]->assign('function_call',$element->getIntricateFunctionCall($this,$params)); 977 $this->function_data[$i][0]->assign('function_conflicts',$this->getFormattedConflicts($element,"functions")); 978 $this->function_data[$i][0]->assign('params',$params); 979 $this->function_data[$i][0]->assign('source_location',$this->returnSee($this->getLink(basename($this->curpage->getFile())),$this->sourceloc)); 980 $this->function_data[$i][0]->assign('id',$this->getId($element));*/ 981 } 982 983 /** 984 * Converts include elements for template output 985 * 986 * Completely ignored by this converter 987 * @param parserInclude 988 */ 989 function convertInclude(&$element) 990 { 991/* parent::convertInclude($element, array('include_file' => '-'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '-')))); 992 $docblock = $this->prepareDocBlock($element); 993 $per = $this->getIncludeValue($element->getValue(), $element->getPath()); 994 $this->page_summary->append('includes',array('sdesc' => $docblock['sdesc'], 995 'desc' => $docblock['desc'], 996 'tags' => $docblock['tags'], 997 'utags' => $docblock['utags'], 998 'include_name' => $element->getName(), 999 'include_value' => $per, 1000 'line_number' => $element->getLineNumber(), 1001 'include_file' => '-'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '-'))));*/ 1002 } 1003 1004 /** 1005 * Converts defines for template output 1006 * @see prepareDocBlock(), getFormattedConflicts() 1007 * @param parserDefine 1008 */ 1009 function convertDefine(&$element) 1010 { 1011 $docblock = $this->prepareDocBlock($element); 1012 $this->_appendDefines(array('sdesc' => $docblock['sdesc'], 1013 'desc' => $docblock['desc'], 1014 'tags' => $docblock['tags'], 1015 'name' => $this->postProcess($element->getName()), 1016 'value' => $this->postProcess($element->getValue()), 1017 'conflicts' => $this->getFormattedConflicts($element,"defines"), 1018 'line_number' => $element->getLineNumber(), 1019 'id' => $this->getId($element))); 1020 } 1021 1022 /** 1023 * Append the constant information to the Smarty information 1024 * 1025 * Uses category, package, and current file to organize constants defined 1026 * in a package for the constants.xml output file 1027 * @param array 1028 * @uses $_peardoc2_constants appends $define to them 1029 * @access private 1030 */ 1031 function _appendDefines($define) 1032 { 1033 if (!isset($this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc])) 1034 { 1035 $this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]['name'] = 1036 $this->sourceloc; 1037 $this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]['page'] = 1038 $this->page; 1039 } 1040 $this->_write_constants_xml[$this->category][$this->package] = true; 1041 $this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]['defines'][] = $define; 1042 } 1043 1044 /** 1045 * Converts global variables for template output 1046 * @param parserGlobal 1047 * @see prepareDocBlock(), getFormattedConflicts() 1048 */ 1049 function convertGlobal(&$element) 1050 { 1051 $docblock = $this->prepareDocBlock($element); 1052 $value = $this->getGlobalValue($element->getValue()); 1053 if ($value == $element->getValue()) 1054 { 1055 $value = $this->ProgramExample($value); 1056 } else 1057 { 1058 $value = $this->getGlobalValue('<![CDATA[' .$element->getValue() . ']]>'); 1059 } 1060 $this->_appendGlobals(array('sdesc' => $docblock['sdesc'], 1061 'desc' => $docblock['desc'], 1062 'tags' => $docblock['tags'], 1063 'name' => $this->postProcess($element->getName()), 1064 'link' => $element->getName(), 1065 'value' => $value, 1066 'type' => $element->getDataType($this), 1067 'line_number' => $element->getLineNumber(), 1068 'conflicts' => $this->getFormattedConflicts($element,"global variables"), 1069 'id' => $this->getId($element))); 1070 } 1071 1072 /** 1073 * Append the global variable information to the Smarty information 1074 * 1075 * Uses category, package, and current file to organize globals defined 1076 * in a package for the globals.xml output file 1077 * @param array 1078 * @uses $_peardoc2_globals appends $global to them 1079 * @access private 1080 */ 1081 function _appendGlobals($global) 1082 { 1083 if (!isset($this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc])) 1084 { 1085 $this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]['name'] = 1086 $this->sourceloc; 1087 $this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]['page'] = 1088 $this->page; 1089 } 1090 $this->_write_globals_xml[$this->category][$this->package] = true; 1091 $this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]['globals'][] = $global; 1092 } 1093 1094 /** 1095 * converts procedural pages for template output 1096 * @see prepareDocBlock(), getClassesOnPage() 1097 * @param parserData 1098 */ 1099 function convertPage(&$element) 1100 { 1101 parent::convertPage($element); 1102 $this->juststarted = true; 1103 $this->page_dir = $element->parent->package; 1104 $this->page = $this->getPageName($element->parent); 1105 $this->category = strtolower($element->parent->category); 1106 $this->sourceloc = $element->parent->getSourceLocation($this,true); 1107 if (!empty($element->parent->subpackage)) $this->page_dir .= PATH_DELIMITER . $element->parent->subpackage; 1108 // registering stuff on the template 1109 } 1110 1111 function getPageName(&$element) 1112 { 1113 return str_replace(array('/','_','.'),array('-','-','---'),$element->getSourceLocation($this,true)); 1114 } 1115 1116 /** 1117 * returns an array containing the class inheritance tree from the root object to the class 1118 * 1119 * @param parserClass class variable 1120 * @return array Format: array(root,child,child,child,...,$class) 1121 * @uses parserClass::getParentClassTree() 1122 */ 1123 1124 function generateFormattedClassTree($class) 1125 { 1126 $tree = $class->getParentClassTree($this); 1127 $out = ''; 1128 if (count($tree) - 1) 1129 { 1130 $result = array($class->getName()); 1131 $parent = $tree[$class->getName()]; 1132 while ($parent) 1133 { 1134 if (is_string($parent)) { 1135 $result[] = $parent; 1136 break; 1137 } 1138 $subpackage = $parent->docblock->subpackage; 1139 $package = $parent->docblock->package; 1140 $x = $parent; 1141 if (is_object($parent)) 1142 $x = $parent->getLink($this); 1143 if (!$x) $x = $parent->getName(); 1144 $result[] = 1145 $x; 1146 if (is_object($parent)) 1147 $parent = $tree[$parent->getName()]; 1148 elseif (isset($tree[$parent])) 1149 $parent = $tree[$parent]; 1150 } 1151 return array_reverse($result); 1152 } else 1153 { 1154 return array($class->getName()); 1155 } 1156 } 1157 1158 /** 1159 * returns a list of child classes 1160 * 1161 * @param parserClass class variable 1162 * @uses parserClass::getChildClassList() 1163 */ 1164 1165 function generateChildClassList($class) 1166 { 1167 $kids = $class->getChildClassList($this); 1168 $list = array(); 1169 if (count($kids)) 1170 { 1171 for($i=0; $i<count($kids); $i++) 1172 { 1173 $lt['link'] = '<link linkend="'.$this->getId($kids[$i]) . '-summary">'. $kids[$i]->getName().'</link>'; 1174 $lt['sdesc'] = $kids[$i]->docblock->getSDesc($this); 1175 $list[] = $lt; 1176 } 1177 } else return false; 1178 return $list; 1179 } 1180 1181 /** @access private */ 1182 function sortVar($a, $b) 1183 { 1184 return strnatcasecmp($a->getName(),$b->getName()); 1185 } 1186 1187 /** @access private */ 1188 function sortMethod($a, $b) 1189 { 1190 if ($a->isConstructor) return -1; 1191 if ($b->isConstructor) return 1; 1192 return strnatcasecmp($a->getName(),$b->getName()); 1193 } 1194 1195 /** 1196 * returns a template-enabled array of class trees 1197 * 1198 * @param string $package package to generate a class tree for 1199 * @see $roots, HTMLConverter::getRootTree() 1200 */ 1201 function generateFormattedClassTrees($package) 1202 { 1203 if (!isset($this->roots['normal'][$package]) && 1204 !isset($this->roots['special'][$package])) { 1205 return array(); 1206 } 1207 $trees = array(); 1208 if (isset($this->roots['normal'][$package])) { 1209 $roots = $this->roots['normal'][$package]; 1210 for($i=0;$i<count($roots);$i++) 1211 { 1212 $root = $this->classes->getClassByPackage($roots[$i], $package); 1213 if ($root && $root->isInterface()) { 1214 continue; 1215 } 1216 $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n"); 1217 } 1218 } 1219 if (isset($this->roots['special'][$package])) { 1220 $roots = $this->roots['special'][$package]; 1221 foreach ($roots as $parent => $classes) { 1222 $thistree = ''; 1223 foreach ($classes as $classinfo) { 1224 $root = $this->classes->getClassByPackage($classinfo, $package); 1225 if ($root && $root->isInterface()) { 1226 continue; 1227 } 1228 $thistree .= 1229 $this->getRootTree( 1230 $this->getSortedClassTreeFromClass( 1231 $classinfo, 1232 $package, 1233 ''), 1234 $package, 1235 true); 1236 } 1237 if (!$thistree) { 1238 continue; 1239 } 1240 $trees[] = array( 1241 'class' => $parent, 1242 'class_tree' => "<ul>\n" . $thistree . "</ul>\n" 1243 ); 1244 } 1245 } 1246 return $trees; 1247 } 1248 1249 /** 1250 * returns a template-enabled array of interface inheritance trees 1251 * 1252 * @param string $package package to generate a class tree for 1253 * @see $roots, HTMLConverter::getRootTree() 1254 */ 1255 function generateFormattedInterfaceTrees($package) 1256 { 1257 if (!isset($this->roots['normal'][$package]) && 1258 !isset($this->roots['special'][$package])) { 1259 return array(); 1260 } 1261 $trees = array(); 1262 if (isset($this->roots['normal'][$package])) { 1263 $roots = $this->roots['normal'][$package]; 1264 for($i=0;$i<count($roots);$i++) 1265 { 1266 $root = $this->classes->getClassByPackage($roots[$i], $package); 1267 if ($root && !$root->isInterface()) { 1268 continue; 1269 } 1270 $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n"); 1271 } 1272 } 1273 if (isset($this->roots['special'][$package])) { 1274 $roots = $this->roots['special'][$package]; 1275 foreach ($roots as $parent => $classes) { 1276 $thistree = ''; 1277 foreach ($classes as $classinfo) { 1278 $root = $this->classes->getClassByPackage($classinfo, $package); 1279 if ($root && !$root->isInterface()) { 1280 continue; 1281 } 1282 $thistree .= 1283 $this->getRootTree( 1284 $this->getSortedClassTreeFromClass( 1285 $classinfo, 1286 $package, 1287 ''), 1288 $package, 1289 true); 1290 } 1291 if (!$thistree) { 1292 continue; 1293 } 1294 $trees[] = array( 1295 'class' => $parent, 1296 'class_tree' => "<ul>\n" . $thistree . "</ul>\n" 1297 ); 1298 } 1299 } 1300 return $trees; 1301 } 1302 1303 /** 1304 * return formatted class tree for the Class Trees page 1305 * 1306 * @param array $tree output from {@link getSortedClassTreeFromClass()} 1307 * @param string $package package 1308 * @param boolean $nounknownparent if true, an object's parent will not be checked 1309 * @see Classes::$definitechild, generateFormattedClassTrees() 1310 * @return string 1311 */ 1312 function getRootTree($tree, $package, $noparent = false) 1313 { 1314 if (!$tree) return ''; 1315 $my_tree = ''; 1316 $cur = '#root'; 1317 $lastcur = array(false); 1318 $kids = array(); 1319 $dopar = false; 1320 if (!$noparent && $tree[$cur]['parent']) 1321 { 1322 $dopar = true; 1323 if (!is_object($tree[$cur]['parent'])) 1324 { 1325// debug("parent ".$tree[$cur]['parent']." not found"); 1326 $my_tree .= '<listitem>' . $tree[$cur]['parent'] .'<itemizedlist>'; 1327 } 1328 else 1329 { 1330// debug("parent ".$this->returnSee($tree[$cur]['parent'], false, false)." in other package"); 1331 $my_tree .= '<listitem>' . $this->returnSee($tree[$cur]['parent'], false, false); 1332 if ($tree[$cur]['parent']->package != $package) $my_tree .= ' <emphasis>(Different package)</emphasis><itemizedlist>'; 1333 } 1334 } 1335 do 1336 { 1337// fancy_debug($cur,$lastcur,$kids); 1338 if (count($tree[$cur]['children'])) 1339 { 1340// debug("$cur has children"); 1341 if (!isset($kids[$cur])) 1342 { 1343// debug("set $cur kids"); 1344 $kids[$cur] = 1; 1345 $my_tree .= '<listitem>'.$this->returnSee($tree[$cur]['link'], false, false); 1346 $my_tree .= '<itemizedlist>'."\n"; 1347 } 1348 array_push($lastcur,$cur); 1349 list(,$cur) = each($tree[$cur]['children']); 1350// var_dump('listed',$cur); 1351 if ($cur) 1352 { 1353 $cur = $cur['package'] . '#' . $cur['class']; 1354// debug("set cur to child $cur"); 1355// $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link'], false, false); 1356 continue; 1357 } else 1358 { 1359// debug("end of children for $cur"); 1360 $cur = array_pop($lastcur); 1361 $cur = array_pop($lastcur); 1362 $my_tree .= '</itemizedlist></listitem>'."\n"; 1363 if ($dopar && ($cur == '#root' || !$cur)) $my_tree .= '</itemizedlist></listitem>'; 1364 } 1365 } else 1366 { 1367// debug("$cur has no children"); 1368 $my_tree .= '<listitem>'.$this->returnSee($tree[$cur]['link'], false, false)."</listitem>"; 1369 if ($dopar && $cur == '#root') $my_tree .= '</itemizedlist></listitem>'; 1370 $cur = array_pop($lastcur); 1371 } 1372 } while ($cur); 1373 return $my_tree; 1374 } 1375 /** 1376 * does nothing 1377 */ 1378 function generateElementIndex() 1379 { 1380 } 1381 1382 function setTemplateDir($dir) 1383 { 1384 Converter::setTemplateDir($dir); 1385 $this->smarty_dir = $this->templateDir; 1386 } 1387 1388 /** 1389 * Generate alphabetical index of all elements by package and subpackage 1390 * 1391 * @param string $package name of a package 1392 * @see $pkg_elements, walk(), generatePkgElementIndexes() 1393 */ 1394 function generatePkgElementIndex($package) 1395 { 1396 } 1397 1398 /** 1399 * 1400 * @see generatePkgElementIndex() 1401 */ 1402 function generatePkgElementIndexes() 1403 { 1404 } 1405 1406 /** 1407 * @param string name of class 1408 * @param string package name 1409 * @param string full path to look in (used in index generation) 1410 * @param boolean deprecated 1411 * @param boolean return just the URL, or enclose it in an html a tag 1412 * @return mixed false if not found, or an html a link to the class's documentation 1413 * @see parent::getClassLink() 1414 */ 1415 function getClassLink($expr,$package, $file = false,$text = false, $local = true, $with_a = true) 1416 { 1417 $a = Converter::getClassLink($expr,$package,$file); 1418 if (!$a) return false; 1419 return $this->returnSee($a, $text, $local, $with_a); 1420 } 1421 1422 /** 1423 * @param string name of function 1424 * @param string package name 1425 * @param string full path to look in (used in index generation) 1426 * @param boolean deprecated 1427 * @param boolean return just the URL, or enclose it in an html a tag 1428 * @return mixed false if not found, or an html a link to the function's documentation 1429 * @see parent::getFunctionLink() 1430 */ 1431 function getFunctionLink($expr,$package, $file = false,$text = false, $local = true) 1432 { 1433 $a = Converter::getFunctionLink($expr,$package,$file); 1434 if (!$a) return false; 1435 return $this->returnSee($a, $text, $local); 1436 } 1437 1438 /** 1439 * @param string name of define 1440 * @param string package name 1441 * @param string full path to look in (used in index generation) 1442 * @param boolean deprecated 1443 * @param boolean return just the URL, or enclose it in an html a tag 1444 * @return mixed false if not found, or an html a link to the define's documentation 1445 * @see parent::getDefineLink() 1446 */ 1447 function getDefineLink($expr,$package, $file = false,$text = false, $local = true) 1448 { 1449 $a = Converter::getDefineLink($expr,$package,$file); 1450 if (!$a) return false; 1451 return $this->returnSee($a, $text, $local); 1452 } 1453 1454 /** 1455 * @param string name of global variable 1456 * @param string package name 1457 * @param string full path to look in (used in index generation) 1458 * @param boolean deprecated 1459 * @param boolean return just the URL, or enclose it in an html a tag 1460 * @return mixed false if not found, or an html a link to the global variable's documentation 1461 * @see parent::getGlobalLink() 1462 */ 1463 function getGlobalLink($expr,$package, $file = false,$text = false, $local = true) 1464 { 1465 $a = Converter::getGlobalLink($expr,$package,$file); 1466 if (!$a) return false; 1467 return $this->returnSee($a, $text, $local); 1468 } 1469 1470 /** 1471 * @param string name of procedural page 1472 * @param string package name 1473 * @param string full path to look in (used in index generation) 1474 * @param boolean deprecated 1475 * @param boolean return just the URL, or enclose it in an html a tag 1476 * @return mixed false if not found, or an html a link to the procedural page's documentation 1477 * @see parent::getPageLink() 1478 */ 1479 function getPageLink($expr,$package, $path = false,$text = false, $local = true) 1480 { 1481 $a = Converter::getPageLink($expr,$package,$path); 1482 if (!$a) return false; 1483 return $this->returnSee($a, $text, $local); 1484 } 1485 1486 /** 1487 * @param string name of method 1488 * @param string class containing method 1489 * @param string package name 1490 * @param string full path to look in (used in index generation) 1491 * @param boolean deprecated 1492 * @param boolean return just the URL, or enclose it in an html a tag 1493 * @return mixed false if not found, or an html a link to the method's documentation 1494 * @see parent::getMethodLink() 1495 */ 1496 function getMethodLink($expr,$class,$package, $file = false,$text = false, $local = true) 1497 { 1498 $a = Converter::getMethodLink($expr,$class,$package,$file); 1499 if (!$a) return false; 1500 return $this->returnSee($a, $text, $local); 1501 } 1502 1503 /** 1504 * @param string name of var 1505 * @param string class containing var 1506 * @param string package name 1507 * @param string full path to look in (used in index generation) 1508 * @param boolean deprecated 1509 * @param boolean return just the URL, or enclose it in an html a tag 1510 * @return mixed false if not found, or an html a link to the var's documentation 1511 * @see parent::getVarLink() 1512 */ 1513 function getVarLink($expr,$class,$package, $file = false,$text = false, $local = true) 1514 { 1515 $a = Converter::getVarLink($expr,$class,$package,$file); 1516 if (!$a) return false; 1517 return $this->returnSee($a, $text, $local); 1518 } 1519 1520 /** 1521 * does a nat case sort on the specified second level value of the array 1522 * 1523 * @param mixed $a 1524 * @param mixed $b 1525 * @return int 1526 */ 1527 function rcNatCmp ($a, $b) 1528 { 1529 $aa = strtoupper($a[$this->rcnatcmpkey]); 1530 $bb = strtoupper($b[$this->rcnatcmpkey]); 1531 1532 return strnatcasecmp($aa, $bb); 1533 } 1534 1535 /** 1536 * does a nat case sort on the specified second level value of the array. 1537 * this one puts constructors first 1538 * 1539 * @param mixed $a 1540 * @param mixed $b 1541 * @return int 1542 */ 1543 function rcNatCmp1 ($a, $b) 1544 { 1545 $aa = strtoupper($a[$this->rcnatcmpkey]); 1546 $bb = strtoupper($b[$this->rcnatcmpkey]); 1547 1548 if (strpos($aa,'CONSTRUCTOR') === 0) 1549 { 1550 return -1; 1551 } 1552 if (strpos($bb,'CONSTRUCTOR') === 0) 1553 { 1554 return 1; 1555 } 1556 if (strpos($aa,strtoupper($this->class)) === 0) 1557 { 1558 return -1; 1559 } 1560 if (strpos($bb,strtoupper($this->class)) === 0) 1561 { 1562 return -1; 1563 } 1564 return strnatcasecmp($aa, $bb); 1565 } 1566 1567 function wordwrap($string) 1568 { 1569 return wordwrap($string); 1570 } 1571 1572 /** 1573 * Generate the constants.xml, packagename.xml, and globals.xml files 1574 */ 1575 function Output() 1576 { 1577 $this->flushPackageXml(false); 1578 $templ = &$this->newSmarty(); 1579 $categories = array(); 1580 $packages = array_flip($this->all_packages); 1581 foreach($this->packagecategories as $package => $category) 1582 { 1583 $categories[$category]['package.'.$category.'.'.str_replace('_','-',strtolower($package ))] = 1; 1584 if (isset($packages[$package])) unset($packages[$package]); 1585 } 1586 $category = $GLOBALS['phpDocumentor_DefaultCategoryName']; 1587 foreach($packages as $package) 1588 { 1589 $categories[$category]['package.'.$category.'.'.str_replace('_','-',strtolower($package ))] = 1; 1590 } 1591 foreach($categories as $category => $ids) 1592 { 1593 $templ->assign('id','package.'.$category); 1594 $templ->assign('ids',array()); 1595 $templ->assign('category',$category); 1596 $this->setTargetDir($this->base_dir); 1597 if (file_exists($this->base_dir . PATH_DELIMITER . strtolower($category ) . '.xml')) 1598 { 1599 $contents = @file($this->base_dir . PATH_DELIMITER . strtolower($category ) . '.xml'); 1600 if (is_array($contents)) 1601 { 1602 $found = false; 1603 foreach($contents as $i => $line) 1604 { 1605 $line = trim($line); 1606 if (strlen($line) && $line{0} == '&') 1607 { 1608 $found = $i; 1609 if (in_array(str_replace(array ('&', ';'), array ('', ''), trim($line )), array_keys($ids ))) 1610 { 1611 unset($ids[str_replace(array('&', ';'), array('', ''), trim($line))]); 1612 } 1613 } 1614 if ($found !== false && (!strlen($line) || $line{0} != '&')) 1615 { 1616 break; 1617 } 1618 } 1619 $newids = array(); 1620 foreach($ids as $id => $unll) 1621 { 1622 $newids[] = ' &' . $id . ";\n"; 1623 } 1624 $newcontents = array_merge(array_slice($contents, 0, $i), $newids); 1625 $newcontents = array_merge($newcontents, array_slice($contents, $i)); 1626 } 1627 $categorycontents = implode($newcontents, ''); 1628 } else 1629 { 1630 foreach($ids as $id => $unll) 1631 { 1632 if (!in_array($id, $templ->_tpl_vars['ids'])) 1633 { 1634 $templ->append('ids',$id); 1635 } 1636 } 1637 $categorycontents = '<!-- $' . "Revision$ -->\n" . $templ->fetch('category.tpl'); 1638 } 1639 $this->writefile(strtolower($category) . '.xml', 1640 $categorycontents); 1641 phpDocumentor_out("\n"); 1642 flush(); 1643 } 1644 $my = &$this->newSmarty(); 1645 if ($this->_peardoc2_constants) 1646 { 1647 foreach($this->_peardoc2_constants as $category => $r) 1648 { 1649 foreach($r as $package => $s) 1650 { 1651 $my->assign('id','package.'.strtolower($category.'.'.str_replace('_','-',strtolower($package ))).'.constants'); 1652 $my->assign('package',$package); 1653 $defines = array(); 1654 foreach($s as $file => $t) 1655 { 1656 $arr = array(); 1657 $arr['name'] = $file; 1658 $arr['page'] = strtolower($t['page']); 1659 $arr['defines'] = $t['defines']; 1660 $defines[] = $arr; 1661 } 1662 $my->assign('defines',$defines); 1663 $this->setTargetDir($this->base_dir . PATH_DELIMITER . $category 1664 . PATH_DELIMITER . strtolower(str_replace('_','-',strtolower($package )))); 1665 $this->writefile('constants.xml', 1666 '<!-- $' . "Revision$ -->\n" . $my->fetch('constants.tpl')); 1667 $my->clear_all_assign(); 1668 } 1669 } 1670 $this->_peardoc2_constants = false; 1671 } 1672 if ($this->_peardoc2_globals) 1673 { 1674 foreach($this->_peardoc2_globals as $category => $r) 1675 { 1676 foreach($r as $package => $s) 1677 { 1678 $my->assign('id','package.'.strtolower($category.'.'.str_replace('_','-',strtolower($package ))).'.globals'); 1679 $my->assign('package',$package); 1680 $defines = array(); 1681 foreach($s as $file => $t) 1682 { 1683 $arr = array(); 1684 $arr['name'] = $file; 1685 $arr['page'] = strtolower($t['page']); 1686 $arr['globals'] = $t['globals']; 1687 $defines[] = $arr; 1688 } 1689 $my->assign('globals',$defines); 1690 $this->setTargetDir($this->base_dir . PATH_DELIMITER . $category 1691 . PATH_DELIMITER . strtolower(str_replace('_','-',strtolower($package )))); 1692 $this->writefile('globals.xml', 1693 '<!-- $' . "Revision$ -->\n" . $my->fetch('globals.tpl')); 1694 $my->clear_all_assign(); 1695 } 1696 } 1697 $this->_peardoc2_globals = false; 1698 } 1699 } 1700} 1701?> 1702