3 * Base class for all Converters
\r
5 * phpDocumentor :: automatic documentation generator
\r
7 * PHP versions 4 and 5
\r
9 * Copyright (c) 2001-2006 Gregory Beaver
\r
13 * This library is free software; you can redistribute it
\r
14 * and/or modify it under the terms of the GNU Lesser General
\r
15 * Public License as published by the Free Software Foundation;
\r
16 * either version 2.1 of the License, or (at your option) any
\r
19 * This library is distributed in the hope that it will be useful,
\r
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
22 * Lesser General Public License for more details.
\r
24 * You should have received a copy of the GNU Lesser General Public
\r
25 * License along with this library; if not, write to the Free Software
\r
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
28 * @package Converters
\r
29 * @author Greg Beaver <cellog@php.net>
\r
30 * @copyright 2001-2006 Gregory Beaver
\r
31 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
\r
32 * @version CVS: $Id: Converter.inc,v 1.38 2007/04/25 19:02:42 ashnazg Exp $
\r
34 * @link http://www.phpdoc.org
\r
35 * @link http://pear.php.net/PhpDocumentor
\r
36 * @see parserDocBlock, parserInclude, parserPage, parserClass
\r
37 * @see parserDefine, parserFunction, parserMethod, parserVar
\r
41 * Smarty template files
\r
43 include_once("phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php");
\r
45 * Base class for all output converters.
\r
47 * The Converter marks the final stage in phpDocumentor. phpDocumentor works
\r
50 * <pre>Parsing => Intermediate Parsing organization => Conversion to output</pre>
\r
52 * A Converter takes output from the {@link phpDocumentor_IntermediateParser} and
\r
53 * converts it to output. With version 1.2, phpDocumentor includes a variety
\r
54 * of output converters:
\r
56 * <li>{@link HTMLframesConverter}</li>
\r
57 * <li>{@link HTMLSmartyConverter}</li>
\r
58 * <li>{@link PDFdefaultConverter}</li>
\r
59 * <li>{@link CHMdefaultConverter}</li>
\r
60 * <li>{@link CSVdia2codeConverter}</li>
\r
61 * <li>{@link XMLDocBookConverter}</li>
\r
64 * The converter takes output directly from {@link phpDocumentor_IntermediateParser}
\r
65 * and using {@link walk()} or {@link walk_everything} (depending on the value of
\r
66 * {@link $sort_absolutely_everything}) it "walks" over an array of phpDocumentor elements.}}
\r
68 * @package Converters
\r
70 * @author Greg Beaver <cellog@php.net>
\r
72 * @version $Id: Converter.inc,v 1.38 2007/04/25 19:02:42 ashnazg Exp $
\r
77 * This converter knows about the new root tree processing
\r
78 * In order to fix PEAR Bug #6389
\r
81 var $processSpecialRoots = false;
\r
83 * output format of this converter
\r
85 * in Child converters, this will match the first part of the -o command-line
\r
86 * as in -o HTML:frames:default "HTML"
\r
87 * @tutorial phpDocumentor.howto.pkg#using.command-line.output
\r
90 var $outputformat = 'Generic';
\r
92 * package name currently being converted
\r
95 var $package = 'default';
\r
97 * subpackage name currently being converted
\r
100 var $subpackage = '';
\r
102 * set to a classname if currently parsing a class, false if not
\r
103 * @var string|false
\r
105 var $class = false;
\r
110 * the workhorse of linking.
\r
112 * This array is an array of link objects of format:
\r
113 * [package][subpackage][eltype][elname] = descendant of {@link abstractLink}
\r
114 * eltype can be page|function|define|class|method|var
\r
115 * if eltype is method or var, the array format is:
\r
116 * [package][subpackage][eltype][class][elname]
\r
118 * @see functionLink, pageLink, classLink, defineLink, methodLink, varLink, globalLink
\r
120 var $links = array();
\r
123 * the workhorse of linking, with allowance for support of multiple
\r
124 * elements in different files.
\r
126 * This array is an array of link objects of format:
\r
127 * [package][subpackage][eltype][file][elname] = descendant of {@link abstractLink}
\r
128 * eltype can be function|define|class|method|var
\r
129 * if eltype is method or var, the array format is:
\r
130 * [package][subpackage][eltype][file][class][elname]
\r
132 * @see functionLink, pageLink, classLink, defineLink, methodLink, varLink, globalLink
\r
134 var $linkswithfile = array();
\r
137 * set to value of -po commandline
\r
138 * @tutorial phpDocumentor.howto.pkg#using.command-line.packageoutput
\r
141 var $package_output;
\r
144 * name of current page being converted
\r
150 * path of current page being converted
\r
156 * template for the procedural page currently being processed
\r
162 * template for the class currently being processed
\r
168 * current procedural page being processed
\r
173 * alphabetical index of all elements sorted by package, subpackage, page,
\r
175 * @var array Format: array(package => array(subpackage => array('page'|'class' => array(path|classname => array(element, element,...)))))
\r
176 * @uses $sort_absolutely_everything if true, then $package_elements is used,
\r
177 * otherwise, the {@link ParserData::$classelements} and
\r
178 * {@link ParserData::$pageelements} variables are used
\r
180 var $package_elements = array();
\r
182 * alphabetical index of all elements
\r
184 * @var array Format: array(first letter of element name => array({@link parserElement} or {@link parserPage},...))
\r
185 * @see formatIndex(), HTMLframesConverter::formatIndex()
\r
187 var $elements = array();
\r
189 * alphabetized index of procedural pages by package
\r
192 * @var array Format: array(package => array(subpackage => array({@link pageLink} 1,{@link pageLink} 2,...)
\r
194 var $page_elements = array();
\r
196 * alphabetized index of defines by package
\r
199 * @var array Format: array(package => array(subpackage => array({@link defineLink} 1,{@link defineLink} 2,...)
\r
201 var $define_elements = array();
\r
203 * alphabetized index of classes by package
\r
206 * @var array Format: array(package => array(subpackage => array({@link classLink} 1,{@link classLink} 2,...)
\r
208 var $class_elements = array();
\r
210 * alphabetized index of global variables by package
\r
213 * @var array Format: array(package => array(subpackage => array({@link globalLink} 1,{@link globalLink} 2,...)
\r
215 var $global_elements = array();
\r
217 * alphabetized index of functions by package
\r
220 * @var array Format: array(package => array(subpackage => array({@link functionLink} 1,{@link functionLink} 2,...)
\r
222 var $function_elements = array();
\r
224 * alphabetical index of all elements, indexed by package/subpackage
\r
226 * @var array Format: array(first letter of element name => array({@link parserElement} or {@link parserPage},...))
\r
227 * @see formatPkgIndex(), HTMLframesConverter::formatPkgIndex()
\r
229 var $pkg_elements = array();
\r
232 * alphabetical index of all elements on a page by package/subpackage
\r
234 * The page itself has a link under ###main
\r
235 * @var array Format: array(package => array(subpackage => array(path => array({@link abstractLink} descendant 1, ...)))
\r
236 * @see formatLeftIndex()
\r
238 var $page_contents = array();
\r
241 * This determines whether the {@link $page_contents} array should be sorted by element type as well as alphabetically by name
\r
242 * @see sortPageContentsByElementType()
\r
245 var $sort_page_contents_by_type = false;
\r
247 * This is used if the content must be passed in the order it should be read, i.e. by package, procedural then classes
\r
249 * This fixes bug 637921, and is used by {@link PDFdefaultConverter}
\r
251 var $sort_absolutely_everything = false;
\r
253 * alphabetical index of all methods and vars in a class by package/subpackage
\r
255 * The class itself has a link under ###main
\r
259 * array(subpackage =>
\r
262 * array({@link abstractLink} descendant 1, ...
\r
267 * @see formatLeftIndex()
\r
269 var $class_contents = array();
\r
271 * controls processing of elements marked private with @access private
\r
273 * defaults to false. Set with command-line --parseprivate or -pp
\r
278 * controls display of progress information while parsing.
\r
280 * defaults to false. Set to true for cron jobs or other situations where no visual output is necessary
\r
286 * directory that output is sent to. -t command-line sets this.
\r
287 * @tutorial phpDocumentor.howto.pkg#using.command-line.target
\r
289 var $targetDir = '';
\r
292 * Directory that the template is in, relative to phpDocumentor root directory
\r
295 var $templateDir = '';
\r
298 * Directory that the smarty templates are in
\r
301 var $smarty_dir = '';
\r
304 * Name of the template, from last part of -o
\r
305 * @tutorial phpDocumentor.howto.pkg#using.command-line.output
\r
308 var $templateName = '';
\r
311 * full path of the current file being converted
\r
316 * All class information, organized by path, and by package
\r
322 * Flag used to help converters determine whether to do special source highlighting
\r
325 var $highlightingSource = false;
\r
328 * Hierarchy of packages
\r
330 * Every package that contains classes may have parent or child classes
\r
331 * in other packages. In other words, this code is legal:
\r
342 * class two extends one {}
\r
345 * In this case, package one is a parent of package two
\r
347 * @see phpDocumentor_IntermediateParser::$package_parents
\r
349 var $package_parents;
\r
352 * Packages associated with categories
\r
354 * Used by the XML:DocBook/peardoc2 converter, and available to others, to
\r
355 * group many packages into categories
\r
356 * @see phpDocumentor_IntermediateParser::$packagecategories
\r
359 var $packagecategories;
\r
362 * All packages encountered in parsing
\r
364 * @see phpDocumentor_IntermediateParser::$all_packages
\r
369 * A list of files that have had source code generated
\r
372 var $sourcePaths = array();
\r
375 * Controls which of the one-element-only indexes are generated.
\r
377 * Generation of these indexes for large packages is time-consuming. This is an optimization feature. An
\r
378 * example of how to use this is in {@link HTMLframesConverter::$leftindex}, and in {@link HTMLframesConverter::formatLeftIndex()}.
\r
379 * These indexes are intended for use as navigational aids through documentation, but can be used for anything by converters.
\r
380 * @see $class_elements, $page_elements, $function_elements, $define_elements, $global_elements
\r
381 * @see formatLeftIndex()
\r
384 var $leftindex = array('classes' => true, 'pages' => true, 'functions' => true, 'defines' => true, 'globals' => true);
\r
386 /** @access private */
\r
387 var $killclass = false;
\r
390 * @see phpDocumentor_IntermediateParser::$title
\r
392 var $title = 'Generated Documentation';
\r
395 * Options for each template, parsed from the options.ini file in the template base directory
\r
396 * @tutorial phpDocumentor/tutorials.pkg#conversion.ppage
\r
399 var $template_options;
\r
402 * Tutorials and Extended Documentation parsed from a tutorials/package[/subpackage] directory
\r
403 * @tutorial tutorials.pkg
\r
406 var $tutorials = array();
\r
409 * tree-format structure of tutorials and their child tutorials, if any
\r
413 var $tutorial_tree = false;
\r
416 * list of tutorials that have already been processed. Used by @link _setupTutorialTree()
\r
420 var $processed_tutorials;
\r
423 * List of all @todo tags and a link to the element with the @todo
\r
425 * Format: array(package => array(link to element, array(todo {@link parserTag},...)),...)
\r
426 * @tutorial tags.todo.pkg
\r
429 var $todoList = array();
\r
432 * Directory where compiled templates go - will be deleted on exit
\r
437 var $_compiledDir = array();
\r
440 * Initialize Converter data structures
\r
441 * @param array {@link $all_packages} value
\r
442 * @param array {@link $package_parents} value
\r
443 * @param Classes {@link $classes} value
\r
444 * @param ProceduralPages {@link $proceduralpages} value
\r
445 * @param array {@link $package_output} value
\r
446 * @param boolean {@link $parseprivate} value
\r
447 * @param boolean {@link $quietmode} value
\r
448 * @param string {@link $targetDir} value
\r
449 * @param string {@link $templateDir} value
\r
450 * @param string (@link $title} value
\r
452 function Converter(&$allp, &$packp, &$classes, &$procpages, $po, $pp, $qm, $targetDir, $template, $title)
\r
454 $this->all_packages = $allp;
\r
455 $this->package_parents = $packp;
\r
456 $this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
\r
457 $this->proceduralpages = &$procpages;
\r
458 $this->package_output = $po;
\r
462 $this->all_packages = array_flip($po);
\r
463 $this->all_packages[$a] = 1;
\r
465 $this->parseprivate = $pp;
\r
466 $this->quietmode = $qm;
\r
467 $this->classes = &$classes;
\r
468 $this->roots = $classes->getRoots($this->processSpecialRoots);
\r
469 $this->title = $title;
\r
470 $this->setTemplateDir($template);
\r
471 $this->setTargetdir($targetDir);
\r
475 * Called by IntermediateParser after creation
\r
478 function setTutorials($tutorials)
\r
480 $this->tutorials = $tutorials;
\r
484 * @param pkg|cls|proc the tutorial type to search for
\r
485 * @param tutorial name
\r
486 * @param string package name
\r
487 * @param string subpackage name, if any
\r
488 * @return false|parserTutorial if the tutorial exists, return it
\r
490 function hasTutorial($type, $name, $package, $subpackage = '')
\r
492 if (isset($this->tutorials[$package][$subpackage][$type][$name . '.' . $type]))
\r
493 return $this->tutorials[$package][$subpackage][$type][$name . '.' . $type];
\r
498 * Called by {@link walk()} while converting, when the last class element
\r
501 * A Converter can use this method in any way it pleases. HTMLframesConverter
\r
502 * uses it to complete the template for the class and to output its
\r
504 * @see HTMLframesConverter::endClass()
\r
507 function endClass()
\r
512 * Called by {@link walk()} while converting, when the last procedural page
\r
513 * element has been parsed.
\r
515 * A Converter can use this method in any way it pleases. HTMLframesConverter
\r
516 * uses it to complete the template for the procedural page and to output its
\r
518 * @see HTMLframesConverter::endClass()
\r
526 * Called by {@link walk()} while converting.
\r
528 * This method is intended to be the place that {@link $pkg_elements} is
\r
529 * formatted for output.
\r
530 * @see HTMLframesConverter::formatPkgIndex()
\r
533 function formatPkgIndex()
\r
538 * Called by {@link walk()} while converting.
\r
540 * This method is intended to be the place that {@link $elements} is
\r
541 * formatted for output.
\r
542 * @see HTMLframesConverter::formatIndex()
\r
545 function formatIndex()
\r
550 * Called by {@link walk()} while converting.
\r
552 * This method is intended to be the place that any of
\r
553 * {@link $class_elements, $function_elements, $page_elements},
\r
554 * {@link $define_elements}, and {@link $global_elements} is formatted for
\r
555 * output, depending on the value of {@link $leftindex}
\r
556 * @see HTMLframesConverter::formatLeftIndex()
\r
559 function formatLeftIndex()
\r
564 * Called by {@link parserSourceInlineTag::stringConvert()} to allow
\r
565 * converters to format the source code the way they'd like.
\r
567 * default returns it unchanged (html with xhtml tags)
\r
568 * @param string output from highlight_string() - use this function to
\r
569 * reformat the returned data for Converter-specific output
\r
571 * @deprecated in favor of tokenizer-based highlighting. This will be
\r
574 function unmangle($sourcecode)
\r
576 return $sourcecode;
\r
580 * Initialize highlight caching
\r
582 function startHighlight()
\r
584 $this->_highlightCache = array(false, false);
\r
585 $this->_appendHighlight = '';
\r
588 function getHighlightState()
\r
590 return $this->_highlightCache;
\r
593 function _setHighlightCache($type, $token)
\r
595 $test = ($this->_highlightCache[0] === $type && $this->_highlightCache[1] == $token);
\r
597 $this->_appendHighlight = $this->flushHighlightCache();
\r
599 $this->_appendHighlight = '';
\r
601 $this->_highlightCache = array($type, $token);
\r
606 * Return the close text for the current token
\r
609 function flushHighlightCache()
\r
611 $hc = $this->_highlightCache;
\r
612 $this->_highlightCache = array(false, false);
\r
614 if (!isset($this->template_options[$hc[0]]['/'.$hc[1]])) {
\r
617 return $this->template_options[$hc[0]]['/'.$hc[1]];
\r
623 * Used to allow converters to format the source code the way they'd like.
\r
625 * default returns it unchanged. Mainly used by the {@link HighlightParser}
\r
627 * The method takes information from options.ini, the template options
\r
628 * file, specifically the [highlightSourceTokens] and [highlightSource]
\r
629 * sections, and uses them to enclose tokens.
\r
632 * @param integer token value from {@link PHP_MANUAL#tokenizer tokenizer constants}
\r
633 * @param string contents of token
\r
634 * @param boolean whether the contents are preformatted or need modification
\r
637 function highlightSource($token, $word, $preformatted = false)
\r
639 if ($token !== false)
\r
641 if (!$preformatted) $word = $this->postProcess($word);
\r
642 if (isset($this->template_options['highlightSourceTokens'][token_name($token)]))
\r
644 if ($this->_setHighlightCache('highlightSourceTokens', token_name($token))) {
\r
647 $e = $this->_appendHighlight;
\r
648 return $e . $this->template_options['highlightSourceTokens'][token_name($token)] . $word;
\r
651 $this->_setHighlightCache(false, false);
\r
652 $e = $this->_appendHighlight;
\r
657 if (isset($this->template_options['highlightSource'][$word]))
\r
659 $newword = ($preformatted ? $word : $this->postProcess($word));
\r
660 if ($this->_setHighlightCache('highlightSource', $word)) {
\r
663 $e = $this->_appendHighlight;
\r
664 return $e . $this->template_options['highlightSource'][$word] . $newword;
\r
667 $this->_setHighlightCache(false, false);
\r
668 $e = $this->_appendHighlight;
\r
669 return $e . ($preformatted ? $word : $this->postProcess($word));
\r
675 * Used to allow converters to format the source code of DocBlocks the way
\r
678 * default returns it unchanged. Mainly used by the {@link HighlightParser}
\r
680 * The method takes information from options.ini, the template options
\r
681 * file, specifically the [highlightDocBlockSourceTokens] section, and uses
\r
682 * it to enclose tokens.
\r
685 * @param string name of docblock token type
\r
686 * @param string contents of token
\r
687 * @param boolean whether the contents are preformatted or need modification
\r
690 function highlightDocBlockSource($token, $word, $preformatted = false)
\r
692 if (empty($word)) {
\r
693 $this->_setHighlightCache(false, false);
\r
694 $e = $this->_appendHighlight;
\r
697 if (isset($this->template_options['highlightDocBlockSourceTokens'][$token]))
\r
699 if (!$preformatted) $word = $this->postProcess($word);
\r
700 if ($this->_setHighlightCache('highlightDocBlockSourceTokens', $token)) {
\r
703 $e = $this->_appendHighlight;
\r
704 return $e . $this->template_options['highlightDocBlockSourceTokens'][$token] . $word;
\r
706 $this->_setHighlightCache(false, false);
\r
707 $e = $this->_appendHighlight;
\r
708 return $e . ($preformatted ? $word : $this->postProcess($word));
\r
713 * Used to allow converters to format the source code of Tutorial XML the way
\r
716 * default returns it unchanged. Mainly used by the {@link HighlightParser}
\r
718 * The method takes information from options.ini, the template options
\r
719 * file, specifically the [highlightDocBlockSourceTokens] section, and uses
\r
720 * it to enclose tokens.
\r
723 * @param string name of docblock token type
\r
724 * @param string contents of token
\r
725 * @param boolean whether the contents are preformatted or need modification
\r
728 function highlightTutorialSource($token, $word, $preformatted = false)
\r
730 if (empty($word)) {
\r
731 $this->_setHighlightCache(false, false);
\r
732 $e = $this->_appendHighlight;
\r
735 if (isset($this->template_options['highlightTutorialSourceTokens'][$token]))
\r
737 if (!$preformatted) $word = $this->postProcess($word);
\r
738 if ($this->_setHighlightCache('highlightTutorialSourceTokens', $token)) {
\r
741 $e = $this->_appendHighlight;
\r
742 return $e . $this->template_options['highlightTutorialSourceTokens'][$token] . $word;
\r
744 $this->_setHighlightCache(false, false);
\r
745 $e = $this->_appendHighlight;
\r
746 return $e . ($preformatted ? $word : $this->postProcess($word));
\r
751 * Called by {@link parserReturnTag::Convert()} to allow converters to
\r
752 * change type names to desired formatting
\r
754 * Used by {@link XMLDocBookConverter::type_adjust()} to change true and
\r
755 * false to the peardoc2 values
\r
759 function type_adjust($typename)
\r
765 * Used to convert the {@}example} inline tag in a docblock.
\r
767 * By default, this just wraps ProgramExample
\r
768 * @see XMLDocBookpeardoc2Converter::exampleProgramExample
\r
770 * @param boolean true if this is to highlight a tutorial <programlisting>
\r
773 function exampleProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/,
\r
774 $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/)
\r
776 return $this->ProgramExample($example, $tutorial, $inlinesourceparse, $class, $linenum, $filesourcepath);
\r
780 * Used to convert the <<code>> tag in a docblock
\r
782 * @param boolean true if this is to highlight a tutorial <programlisting>
\r
785 function ProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/,
\r
786 $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/)
\r
788 $this->highlightingSource = true;
\r
792 if (!is_array($example))
\r
794 $obj = new phpDocumentorTWordParser;
\r
795 $obj->setup($example);
\r
796 $e = $obj->getFileSource();
\r
797 $bOpenTagFound = false;
\r
798 foreach ($e as $ke => $ee)
\r
800 foreach ($ee as $kee => $eee)
\r
802 if ((int) $e[$ke][$kee][0] == T_OPEN_TAG)
\r
804 $bOpenTagFound = true;
\r
808 if (!$bOpenTagFound) {
\r
809 $example = "<?php\n".$example;
\r
810 $obj->setup($example);
\r
811 $e = $obj->getFileSource();
\r
813 $e = array_values($e);
\r
817 $saveclass = $this->class;
\r
818 $parser = new phpDocumentor_HighlightParser;
\r
819 if (!isset($inlinesourceparse))
\r
821 $example = $parser->parse($e, $this, true); // force php mode
\r
824 if (isset($filesourcepath))
\r
826 $example = $parser->parse($e, $this, $inlinesourceparse, $class, $linenum, $filesourcepath);
\r
827 } elseif (isset($linenum))
\r
829 $example = $parser->parse($e, $this, $inlinesourceparse, $class, $linenum);
\r
830 } elseif (isset($class))
\r
832 $example = $parser->parse($e, $this, $inlinesourceparse, $class);
\r
835 $example = $parser->parse($e, $this, $inlinesourceparse);
\r
838 $this->class = $saveclass;
\r
841 $example = $this->postProcess($example);
\r
843 $this->highlightingSource = false;
\r
850 if (!isset($this->template_options['desctranslate'])) return $example;
\r
851 if (!isset($this->template_options['desctranslate']['code'])) return $example;
\r
852 $example = $this->template_options['desctranslate']['code'] . $example;
\r
853 if (!isset($this->template_options['desctranslate']['/code'])) return $example;
\r
854 return $example . $this->template_options['desctranslate']['/code'];
\r
860 function TutorialExample($example)
\r
862 $this->highlightingSource = true;
\r
863 $parse = new phpDocumentor_TutorialHighlightParser;
\r
864 $x = $parse->parse($example, $this);
\r
865 $this->highlightingSource = false;
\r
870 * Used to convert the contents of <<li>> in a docblock
\r
874 function ListItem($item)
\r
876 if (!isset($this->template_options['desctranslate'])) return $item;
\r
877 if (!isset($this->template_options['desctranslate']['li'])) return $item;
\r
878 $item = $this->template_options['desctranslate']['li'] . $item;
\r
879 if (!isset($this->template_options['desctranslate']['/li'])) return $item;
\r
880 return $item . $this->template_options['desctranslate']['/li'];
\r
884 * Used to convert the contents of <<ol>> or <<ul>> in a docblock
\r
888 function EncloseList($list,$ordered)
\r
890 $listname = ($ordered ? 'ol' : 'ul');
\r
891 if (!isset($this->template_options['desctranslate'])) return $list;
\r
892 if (!isset($this->template_options['desctranslate'][$listname])) return $list;
\r
893 $list = $this->template_options['desctranslate'][$listname] . $list;
\r
894 if (!isset($this->template_options['desctranslate']['/'.$listname])) return $list;
\r
895 return $list . $this->template_options['desctranslate']['/'.$listname];
\r
899 * Used to convert the contents of <<pre>> in a docblock
\r
903 function PreserveWhiteSpace($string)
\r
905 if (!isset($this->template_options['desctranslate'])) return $string;
\r
906 if (!isset($this->template_options['desctranslate']['pre'])) return $string;
\r
907 $string = $this->template_options['desctranslate']['pre'] . $string;
\r
908 if (!isset($this->template_options['desctranslate']['/pre'])) return $string;
\r
909 return $string . $this->template_options['desctranslate']['/pre'];
\r
913 * Used to enclose a paragraph in a docblock
\r
917 function EncloseParagraph($para)
\r
919 if (!isset($this->template_options['desctranslate'])) return $para;
\r
920 if (!isset($this->template_options['desctranslate']['p'])) return $para;
\r
921 $para = $this->template_options['desctranslate']['p'] . $para;
\r
922 if (!isset($this->template_options['desctranslate']['/p'])) return $para;
\r
923 return $para . $this->template_options['desctranslate']['/p'];
\r
927 * Used to convert the contents of <<b>> in a docblock
\r
931 function Bolden($para)
\r
933 if (!isset($this->template_options['desctranslate'])) return $para;
\r
934 if (!isset($this->template_options['desctranslate']['b'])) return $para;
\r
935 $para = $this->template_options['desctranslate']['b'] . $para;
\r
936 if (!isset($this->template_options['desctranslate']['/b'])) return $para;
\r
937 return $para . $this->template_options['desctranslate']['/b'];
\r
941 * Used to convert the contents of <<i>> in a docblock
\r
945 function Italicize($para)
\r
947 if (!isset($this->template_options['desctranslate'])) return $para;
\r
948 if (!isset($this->template_options['desctranslate']['i'])) return $para;
\r
949 $para = $this->template_options['desctranslate']['i'] . $para;
\r
950 if (!isset($this->template_options['desctranslate']['/i'])) return $para;
\r
951 return $para . $this->template_options['desctranslate']['/i'];
\r
955 * Used to convert the contents of <<var>> in a docblock
\r
959 function Varize($para)
\r
961 if (!isset($this->template_options['desctranslate'])) return $para;
\r
962 if (!isset($this->template_options['desctranslate']['var'])) return $para;
\r
963 $para = $this->template_options['desctranslate']['var'] . $para;
\r
964 if (!isset($this->template_options['desctranslate']['/var'])) return $para;
\r
965 return $para . $this->template_options['desctranslate']['/var'];
\r
969 * Used to convert the contents of <<kbd>> in a docblock
\r
973 function Kbdize($para)
\r
975 if (!isset($this->template_options['desctranslate'])) return $para;
\r
976 if (!isset($this->template_options['desctranslate']['kbd'])) return $para;
\r
977 $para = $this->template_options['desctranslate']['kbd'] . $para;
\r
978 if (!isset($this->template_options['desctranslate']['/kbd'])) return $para;
\r
979 return $para . $this->template_options['desctranslate']['/kbd'];
\r
983 * Used to convert the contents of <<samp>> in a docblock
\r
987 function Sampize($para)
\r
989 if (!isset($this->template_options['desctranslate'])) return $para;
\r
990 if (!isset($this->template_options['desctranslate']['samp'])) return $para;
\r
991 $para = $this->template_options['desctranslate']['samp'] . $para;
\r
992 if (!isset($this->template_options['desctranslate']['/samp'])) return $para;
\r
993 return $para . $this->template_options['desctranslate']['/samp'];
\r
997 * Used to convert <<br>> in a docblock
\r
1001 function Br($para)
\r
1003 if (!isset($this->template_options['desctranslate'])) return $para;
\r
1004 if (!isset($this->template_options['desctranslate']['br'])) return $para;
\r
1005 $para = $this->template_options['desctranslate']['br'] . $para;
\r
1010 * This version does nothing
\r
1012 * Perform necessary post-processing of string data. For example, the HTML
\r
1013 * Converters should escape < and > to become < and >
\r
1016 function postProcess($text)
\r
1022 * Creates a table of contents for a {@}toc} inline tag in a tutorial
\r
1024 * This function should return a formatted table of contents. By default, it
\r
1025 * does nothing, it is up to the converter to format the TOC
\r
1027 * @return string table of contents formatted for use in the current output format
\r
1028 * @param array format: array(array('tagname' => section, 'link' => returnsee link, 'id' => anchor name, 'title' => from title tag),...)
\r
1030 function formatTutorialTOC($toc)
\r
1036 * Write out the formatted source code for a php file
\r
1038 * This function provides the primary functionality for the
\r
1039 * {@tutorial tags.filesource.pkg} tag.
\r
1040 * @param string full path to the file
\r
1041 * @param string fully highlighted/linked source code of the file
\r
1044 function writeSource($filepath, $source)
\r
1051 * Write out the formatted source code for an example php file
\r
1053 * This function provides the primary functionality for the
\r
1054 * {@tutorial tags.example.pkg} tag.
\r
1055 * @param string example title
\r
1056 * @param string example filename (no path)
\r
1057 * @param string fully highlighted/linked source code of the file
\r
1060 function writeExample($title, $path, $source)
\r
1065 /** Translate the path info into a unique file name for the highlighted
\r
1067 * @param string $pathinfo
\r
1070 function getFileSourceName($path)
\r
1072 global $_phpDocumentor_options;
\r
1073 $pathinfo = $this->proceduralpages->getPathInfo($path, $this);
\r
1074 $pathinfo['source_loc'] = str_replace($_phpDocumentor_options['Program_Root'].'/','',$pathinfo['source_loc']);
\r
1075 $pathinfo['source_loc'] = str_replace('/','_',$pathinfo['source_loc']);
\r
1076 return "fsource_{$pathinfo['package']}_{$pathinfo['subpackage']}_{$pathinfo['source_loc']}";
\r
1079 /** Return the fixed path to the source-code file folder.
\r
1080 * @param string $base Path is relative to this folder
\r
1083 function getFileSourcePath($base)
\r
1085 if (substr($base, strlen($base) - 1) != PATH_DELIMITER) {
\r
1086 $base .= PATH_DELIMITER;
\r
1088 return $base . '__filesource';
\r
1091 /** Return the path to the current
\r
1092 * @param string $pathinfo
\r
1095 function getCurrentPageURL()
\r
1097 return '{$srcdir}' . PATH_DELIMITER . $this->page_dir;
\r
1101 * @return string an output-format dependent link to phpxref-style highlighted
\r
1105 function getSourceLink($path)
\r
1111 * @return string Link to the current page being parsed.
\r
1112 * Should return {@link $curname} and a converter-specific extension.
\r
1115 function getCurrentPageLink()
\r
1120 * Return a line of highlighted source code with formatted line number
\r
1122 * If the $path is a full path, then an anchor to the line number will be
\r
1124 * @param integer line number
\r
1125 * @param string highlighted source code line
\r
1126 * @param false|string full path to @filesource file this line is a part of,
\r
1127 * if this is a single line from a complete file.
\r
1128 * @return string formatted source code line with line number
\r
1130 function sourceLine($linenumber, $line, $path = false)
\r
1134 return $this->getSourceAnchor($path, $linenumber) .
\r
1135 $this->Br(sprintf('%-6u',$linenumber).str_replace("\n",'',$line));
\r
1138 return $this->Br(sprintf('%-6u',$linenumber).str_replace("\n",'',$line));
\r
1143 * Determine whether an element's file has generated source code, used for
\r
1144 * linking to line numbers of source.
\r
1146 * Wrapper for {@link $sourcePaths} in this version
\r
1147 * @param string full path to the source code file
\r
1150 function hasSourceCode($path)
\r
1152 return isset($this->sourcePaths[$path]);
\r
1156 * Mark a file as having had source code highlighted
\r
1157 * @param string full path of source file
\r
1159 function setSourcePaths($path)
\r
1161 $this->sourcePaths[$path] = true;
\r
1165 * Used to translate an XML DocBook entity like ” from a tutorial by
\r
1166 * reading the options.ini file for the template.
\r
1167 * @param string entity name
\r
1169 function TranslateEntity($name)
\r
1171 if (!isset($this->template_options['ppage']))
\r
1173 if (!$this->template_options['preservedocbooktags'])
\r
1176 return '&'.$name.';';
\r
1178 if (isset($this->template_options['ppage']['&'.$name.';']))
\r
1180 return $this->template_options['ppage']['&'.$name.';'];
\r
1183 if (!$this->template_options['preservedocbooktags'])
\r
1186 return '&'.$name.';';
\r
1191 * Used to translate an XML DocBook tag from a tutorial by reading the
\r
1192 * options.ini file for the template.
\r
1193 * @param string tag name
\r
1194 * @param string any attributes Format: array(name => value)
\r
1195 * @param string the tag contents, if any
\r
1196 * @param string the tag contents, if any, unpost-processed
\r
1199 function TranslateTag($name,$attr,$cdata,$unconvertedcdata)
\r
1201 if (!isset($this->template_options['ppage']))
\r
1203 if (!$this->template_options['preservedocbooktags'])
\r
1206 return '<'.$name.$this->AttrToString($name,$attr,true).'>'.$cdata.'</'.$name.'>'."\n";
\r
1208 // make sure this template transforms the tag into something
\r
1209 if (isset($this->template_options['ppage'][$name]))
\r
1211 // test for global attribute transforms like $attr$role = class, changing
\r
1212 // all role="*" attributes to class="*" in html, for example
\r
1213 foreach($attr as $att => $val)
\r
1215 if (isset($this->template_options['$attr$'.$att]))
\r
1218 if (!isset($this->template_options['$attr$'.$att]['close']))
\r
1220 $new .= '<'.$this->template_options['$attr$'.$att]['open'];
\r
1221 if (isset($this->template_options['$attr$'.$att]['cdata!']))
\r
1223 if (isset($this->template_options['$attr$'.$att]['separateall']))
\r
1224 $new .= $this->template_options['$attr$'.$att]['separator'];
\r
1227 $new .= $this->template_options['$attr$'.$att]['$'.$att];
\r
1228 $new .= $this->template_options['$attr$'.$att]['separator'];
\r
1229 if ($this->template_options['$attr$'.$att]['quotevalues']) $val = '"'.$val.'"';
\r
1235 $new .= '</'.$this->template_options['$attr$'.$att]['open'].'>';
\r
1238 $new .= $this->template_options['$attr$'.$att]['open'] . $val . $this->template_options['$attr$'.$att]['close'];
\r
1240 unset($attr[$att]);
\r
1241 $cdata = $new . $cdata;
\r
1245 if (!isset($this->template_options['ppage']['/'.$name]))
\r
1246 {// if the close tag isn't specified, we put opening and closing tags around it, with translated attributes
\r
1247 if (isset($this->template_options['ppage'][$name.'/']))
\r
1248 $cdata = '<'.$this->template_options['ppage'][$name].$this->AttrToString($name,$attr).'/>' . $cdata;
\r
1250 $cdata = '<'.$this->template_options['ppage'][$name].$this->AttrToString($name,$attr).'>' . $cdata .
\r
1251 '</'.$this->template_options['ppage'][$name].'>';
\r
1253 { // if close tag is specified, use the open and close as literal
\r
1254 if ($name == 'programlisting' && isset($attr['role']) &&
\r
1255 ($attr['role'] == 'php' || $attr['role'] == 'tutorial' || $attr['role'] == 'html'))
\r
1256 { // highlight PHP source
\r
1257 // var_dump($unconvertedcdata, $cdata);exit;
\r
1258 if ($attr['role'] == 'php') {
\r
1259 $cdata = $this->ProgramExample($unconvertedcdata, true);
\r
1260 } elseif ($attr['role'] == 'tutorial') {
\r
1261 $cdata = $this->TutorialExample($unconvertedcdata);
\r
1262 } elseif ($attr['role'] == 'html') {
\r
1263 $cdata = $unconvertedcdata;
\r
1266 {// normal case below
\r
1267 $cdata = $this->template_options['ppage'][$name].$this->AttrToString($name,$attr). $cdata .$this->template_options['ppage']['/'.$name];
\r
1273 if ($this->template_options['preservedocbooktags'])
\r
1275 return '<'.$name.$this->AttrToString($name,$attr,true).'>' . $cdata .
\r
1276 '</'.$name.'>'."\n";
\r
1285 * Convert the attribute of a Tutorial docbook tag's attribute list
\r
1286 * to a string based on the template options.ini
\r
1287 * @param string tag name
\r
1288 * @param attribute array
\r
1289 * @param boolean if true, returns attrname="value"...
\r
1292 function AttrToString($tag,$attr,$unmodified = false)
\r
1298 foreach($attr as $n => $v)
\r
1300 $ret .= $n.' = "'.$v.'"';
\r
1304 // no_attr tells us to ignore all attributes
\r
1305 if (isset($this->template_options['no_attr'])) return $ret;
\r
1306 // tagname! tells us to ignore all attributes for this tag
\r
1307 if (isset($this->template_options['ppage'][$tag.'!'])) return $ret;
\r
1308 if (count($attr)) $ret = ' ';
\r
1309 // pass 1, check to see if any attributes add together
\r
1311 foreach($attr as $n => $v)
\r
1313 if (isset($this->template_options['ppage'][$tag.'->'.$n]))
\r
1315 $same[$this->template_options['ppage'][$tag.'->'.$n]][] = $n;
\r
1318 foreach($attr as $n => $v)
\r
1320 if (isset($this->template_options['ppage'][$tag.'->'.$n]))
\r
1322 if (count($same[$this->template_options['ppage'][$tag.'->'.$n]]) == 1)
\r
1323 { // only 1 attribute translated for this one
\r
1324 // this is useful for equivalent value names
\r
1325 if (isset($this->template_options['ppage'][$tag.'->'.$n.'+'.$v])) $v = $this->template_options['ppage'][$tag.'->'.$n.'+'.$v];
\r
1327 { // more than 1 attribute combines to make the new attribute
\r
1328 $teststrtemp = array();
\r
1329 foreach($same[$this->template_options['ppage'][$tag.'->'.$n]] as $oldattr)
\r
1331 $teststrtemp[] = $oldattr.'+'.$attr[$oldattr];
\r
1333 $teststrs = array();
\r
1334 $num = count($same[$this->template_options['ppage'][$tag.'->'.$n]]);
\r
1335 for($i=0;$i<$num;$i++)
\r
1339 for($j=$i;!$started || $j != $i;$j = ($j + $i) % $num)
\r
1341 if (!empty($a)) $a .= '|';
\r
1342 $a .= $teststrtemp[$j];
\r
1344 $teststrs[$i] = $a;
\r
1347 foreach($teststrs as $test)
\r
1350 if (isset($this->template_options['ppage'][$tag.'->'.$test]))
\r
1353 $v = $this->template_options['ppage'][$tag.'->'.$test];
\r
1357 $ret .= $this->template_options['ppage'][$tag.'->'.$n].' = "'.$v.'"';
\r
1360 if (!isset($this->template_options['ppage'][$tag.'!'.$n]))
\r
1362 if (isset($this->template_options['ppage']['$attr$'.$n]))
\r
1363 $ret .= $this->template_options['ppage']['$attr$'.$n].' = "'.$v.'"';
\r
1365 $ret .= $n.' = "'.$v.'"';
\r
1373 * Convert the title of a Tutorial docbook tag section
\r
1374 * to a string based on the template options.ini
\r
1375 * @param string tag name
\r
1377 * @param string title text
\r
1381 function ConvertTitle($tag,$attr,$title,$cdata)
\r
1383 if (!isset($this->template_options[$tag.'_title'])) return array($attr,$cdata);
\r
1384 if (isset($this->template_options[$tag.'_title']['tag_attr']))
\r
1386 $attr[$this->template_options[$tag.'_title']['tag_attr']] = urlencode($cdata);
\r
1388 } elseif(isset($this->template_options[$tag.'_title']['cdata_start']))
\r
1390 $cdata = $this->template_options[$tag.'_title']['open'] . $title .
\r
1391 $this->template_options[$tag.'_title']['close'] . $cdata;
\r
1392 } else $cdata = $title.$cdata;
\r
1393 return array($attr,$cdata);
\r
1397 * Return a converter-specific id to distinguish tutorials and their
\r
1403 function getTutorialId($package,$subpackage,$tutorial,$id)
\r
1405 return $package.$subpackage.$tutorial.$id;
\r
1409 * Create the {@link $elements, $pkg_elements} and {@link $links} arrays
\r
1411 * @todo version 2.0 - faulty package_output logic should be removed
\r
1413 * in this version, if the parent file isn't in the package, all
\r
1414 * the procedural elements are simply shunted to another package!
\r
1416 function _createPkgElements(&$pages)
\r
1418 if (empty($this->elements))
\r
1420 $this->elements = array();
\r
1421 $this->pkg_elements = array();
\r
1422 $this->links = array();
\r
1423 phpDocumentor_out('Building indexes...');
\r
1425 foreach($pages as $j => $flub)
\r
1427 $this->package = $pages[$j]->parent->package;
\r
1428 $this->subpackage = $pages[$j]->parent->subpackage;
\r
1429 $this->class = false;
\r
1430 $this->curfile = $pages[$j]->parent->getFile();
\r
1431 $this->curname = $this->getPageName($pages[$j]->parent);
\r
1432 $this->curpath = $pages[$j]->parent->getPath();
\r
1434 if ($this->package_output)
\r
1436 if (in_array($this->package,$this->package_output))
\r
1438 $this->addElement($pages[$j]->parent,$pages[$j]);
\r
1441 if (count($pages[$j]->classelements))
\r
1443 list(,$pages[$j]->parent->package) = each($this->package_output);
\r
1444 reset($this->package_output);
\r
1445 $pages[$j]->parent->subpackage = '';
\r
1446 $this->addElement($pages[$j]->parent,$pages[$j]);
\r
1449 unset($pages[$j]);
\r
1455 $this->addElement($pages[$j]->parent,$pages[$j]);
\r
1458 for($i=0; $i<count($pages[$j]->elements); $i++)
\r
1460 $pages[$j]->elements[$i]->docblock->package = $this->package;
\r
1461 $pages[$j]->elements[$i]->docblock->subpackage = $this->subpackage;
\r
1462 $this->proceduralpages->replaceElement($pages[$j]->elements[$i]);
\r
1463 $this->addElement($pages[$j]->elements[$i]);
\r
1465 for($i=0; $i<count($pages[$j]->classelements); $i++)
\r
1469 if ($pages[$j]->classelements[$i]->type == 'class')
\r
1471 if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
\r
1472 $this->package = $pages[$j]->classelements[$i]->docblock->package;
\r
1473 if ($this->package_output) if (!in_array($this->package,$this->package_output)) continue;
\r
1474 $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
\r
1475 $this->class = $pages[$j]->classelements[$i]->name;
\r
1478 if ($this->killclass) continue;
\r
1479 // force all contained elements to have parent package/subpackage
\r
1480 $pages[$j]->classelements[$i]->docblock->package = $this->package;
\r
1481 $pages[$j]->classelements[$i]->docblock->subpackage = $this->subpackage;
\r
1484 if ($pages[$j]->classelements[$i]->type == 'class')
\r
1486 if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
\r
1487 $this->package = $pages[$j]->classelements[$i]->docblock->package;
\r
1488 if ($this->package_output) if (!in_array($this->package,$this->package_output)) continue;
\r
1489 $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
\r
1490 $this->class = $pages[$j]->classelements[$i]->name;
\r
1492 if (!$this->killclass) $this->addElement($pages[$j]->classelements[$i]);
\r
1495 phpDocumentor_out("done\n");
\r
1498 $this->sortIndexes();
\r
1499 $this->sortTodos();
\r
1500 if ($this->sort_page_contents_by_type) $this->sortPageContentsByElementType($pages);
\r
1504 * Process the {@link $tutorials} array
\r
1506 * Using the tutorialname.ext.ini files, this method sets up tutorial
\r
1507 * hierarchy. There is some minimal error checking to make sure that no
\r
1508 * tutorial links to itself, even two levels deep as in tute->next->tute.
\r
1510 * If all tests pass, it creates the hierarchy
\r
1511 * @uses generateTutorialOrder()
\r
1512 * @uses _setupTutorialTree()
\r
1515 function _processTutorials()
\r
1517 $parents = $all = array();
\r
1518 foreach($this->tutorials as $package => $els)
\r
1520 if ($this->package_output)
\r
1522 if (!in_array($package,$this->package_output))
\r
1524 unset($this->tutorials[$package]);
\r
1528 if (!isset($this->pkg_elements[$package]))
\r
1530 unset($this->tutorials[$package]);
\r
1533 foreach($els as $subpackage => $els2)
\r
1535 foreach($els2 as $type => $tutorials)
\r
1537 foreach($tutorials as $tutorial)
\r
1539 if ($tutorial->ini)
\r
1541 if (isset($tutorial->ini['Linked Tutorials']))
\r
1543 foreach($tutorial->ini['Linked Tutorials'] as $child)
\r
1545 $sub = (empty($tutorial->subpackage) ? '' : $tutorial->subpackage . '/');
\r
1546 $kid = $tutorial->package . '/' . $sub . $child . '.' . $tutorial->tutorial_type;
\r
1547 // parent includes self as a linked tutorial?
\r
1548 $kidlink = $this->getTutorialLink($kid,false,false,array($tutorial->package));
\r
1549 if (is_object($kidlink) && $this->returnSee($kidlink) == $tutorial->getLink($this))
\r
1551 addErrorDie(PDERROR_TUTORIAL_IS_OWN_CHILD,$tutorial->name,$tutorial->name.'.ini');
\r
1554 $parents[] = $tutorial;
\r
1557 $all[$package][$subpackage][$type][] = $tutorial;
\r
1562 // loop error-checking, use this to eliminate possibility of accidentally linking to a parent as a child
\r
1563 $testlinks = array();
\r
1564 foreach($parents as $parent)
\r
1566 $testlinks[$parent->name]['links'][] = $parent->getLink($this);
\r
1567 $testlinks[$parent->name]['name'][$parent->getLink($this)] = $parent->name;
\r
1569 // generate the order of tutorials, and link them together
\r
1570 foreach($parents as $parent)
\r
1572 foreach($parent->ini['Linked Tutorials'] as $child)
\r
1574 $sub = (empty($parent->subpackage) ? '' : $parent->subpackage . '/');
\r
1575 $kid = $parent->package . '/' . $sub . $child . '.' . $parent->tutorial_type;
\r
1576 // child tutorials must be in the same package AND subpackage
\r
1577 // AND have the same extension as the parent, makes things clearer for both ends
\r
1578 if (in_array($this->returnSee($this->getTutorialLink($kid,false,false,array($parent->package))),$testlinks[$parent->name]['links']))
\r
1579 addErrorDie(PDERROR_TUTORIAL_IS_OWN_GRANDPA,$testlinks[$parent->name][$this->returnSee($this->getTutorialLink($kid,false,false,array($parent->package)))],$kid->name,$testlinks[$parent->name][$this->returnSee($this->getTutorialLink($kid,false,false,array($parent->package)))],$kid->name.'.ini');
\r
1580 if ($this->returnSee($this->getTutorialLink($kid,false,false,array($parent->package))) == $kid)
\r
1582 addWarning(PDERROR_CHILD_TUTORIAL_NOT_FOUND, $child . '.' . $parent->tutorial_type, $parent->name .'.ini',$parent->package, $parent->subpackage);
\r
1586 $new = $tree = $roots = array();
\r
1587 // build a list of all 'root' tutorials (tutorials without parents).
\r
1588 foreach($parents as $i => $parent)
\r
1590 if (! $parent->isChildOf($parents)) {
\r
1591 $roots[] = $parent;
\r
1594 $parents = $roots;
\r
1595 // add the parents and all child tutorials in order to the list of tutorials to process
\r
1596 foreach($parents as $parent)
\r
1598 $this->generateTutorialOrder($parent,$all,$new);
\r
1602 // add the leftover tutorials
\r
1603 foreach($all as $package => $els)
\r
1605 foreach($els as $subpackage => $els2)
\r
1607 foreach($els2 as $type => $tutorials)
\r
1609 foreach($tutorials as $tutorial)
\r
1611 $new[$package][$subpackage][$type][] = $tutorial;
\r
1617 // remove the old, unprocessed tutorials, and set it up with the next code
\r
1618 $this->tutorials = array();
\r
1619 // reset integrity of the tutorial list
\r
1621 uksort($new, 'tutorialcmp');
\r
1622 // debug($this->vardump_tree($new));exit;
\r
1623 foreach($new as $package => $els)
\r
1625 foreach($els as $subpackage => $els2)
\r
1627 foreach($els2 as $type => $tutorials)
\r
1629 foreach($tutorials as $tutorial)
\r
1633 $this->tutorials[$prevpackage][$prevsubpackage][$prevtype][$prevname]->setNext($tutorial,$this);
\r
1634 $tutorial->setPrev($prev,$this);
\r
1636 $this->tutorials[$package][$subpackage][$type][$tutorial->name] = $tutorial;
\r
1637 $prev = $tutorial->getLink($this,true);
\r
1638 $prevpackage = $package;
\r
1639 $prevsubpackage = $subpackage;
\r
1640 $prevtype = $type;
\r
1641 $prevname = $tutorial->name;
\r
1646 $this->tutorial_tree = $this->_setupTutorialTree();
\r
1651 * called by {@link phpDocumentor_IntermediateParser::Convert()} to traverse
\r
1652 * the array of pages and their elements, converting them to the output format
\r
1654 * The walk() method should be flexible enough such that it never needs
\r
1655 * modification. walk() sets up all of the indexes, and sorts everything in
\r
1656 * logical alphabetical order. It then passes each element individually to
\r
1657 * {@link Convert()}, which then passes to the Convert*() methods. A child
\r
1658 * Converter need not override any of these unless special functionality must
\r
1659 * be added. see {@tutorial Converters/template.vars.cls} for details.
\r
1661 * walk() first creates all of the indexes {@link $elements, $pkg_elements}
\r
1662 * and the left indexes specified by {@link $leftindexes},
\r
1663 * and then sorts them by calling {@link sortIndexes()}.
\r
1665 * Next, it converts all README/CHANGELOG/INSTALL-style files, using
\r
1666 * {@link Convert_RIC}.
\r
1669 * passes all package-level docs to Convert(). Then, it calls the index
\r
1670 * sorting functions {@link formatPkgIndex(), formatIndex()} and
\r
1671 * {@link formatLeftIndex()}.
\r
1673 * Finally, it converts each procedural page in alphabetical order. This
\r
1674 * stage passes elements from the physical file to Convert() in alphabetical
\r
1675 * order. First, procedural page elements {@link parserDefine, parserInclude}
\r
1676 * {@link parserGlobal}, and {@link parserFunction} are passed to Convert().
\r
1678 * Then, class elements are passed in this order: {@link parserClass}, then
\r
1679 * all of the {@link parserVar}s in the class and all of the
\r
1680 * {@link parserMethod}s in the class. Classes are in alphabetical order,
\r
1681 * and both vars and methods are in alphabetical order.
\r
1683 * Finally, {@link ConvertErrorLog()} is called and the data walk is complete.}}
\r
1684 * @param array Format: array(fullpath => {@link parserData} structure with full {@link parserData::$elements}
\r
1685 * and {@link parserData::$class_elements}.
\r
1686 * @param array Format: array({@link parserPackagePage} 1, {@link parserPackagePage} 2,...)
\r
1687 * @uses Converter::_createPkgElements() sets up {@link $elements} and
\r
1688 * {@link $pkg_elements} array, as well as {@link $links}
\r
1690 function walk(&$pages,&$package_pages)
\r
1692 if (empty($pages))
\r
1694 die("<b>ERROR</b>: nothing parsed");
\r
1696 $this->_createPkgElements($pages);
\r
1697 if (count($this->ric))
\r
1699 phpDocumentor_out("Converting README/INSTALL/CHANGELOG contents...\n");
\r
1701 foreach($this->ric as $name => $contents)
\r
1703 phpDocumentor_out("$name...");
\r
1705 $this->Convert_RIC($name,$contents);
\r
1707 phpDocumentor_out("\ndone\n");
\r
1710 foreach($package_pages as $i => $perp)
\r
1712 if ($this->package_output)
\r
1714 if (!in_array($package_pages[$i]->package,$this->package_output)) continue;
\r
1716 phpDocumentor_out('Converting package page for package '.$package_pages[$i]->package.'... ');
\r
1718 $this->package = $package_pages[$i]->package;
\r
1719 $this->subpackage = '';
\r
1720 $this->class = false;
\r
1721 $this->Convert($package_pages[$i]);
\r
1722 phpDocumentor_out("done\n");
\r
1725 phpDocumentor_out("Converting tutorials/extended docs\n");
\r
1727 // get tutorials into the order they will display, and set next/prev links
\r
1728 $new = $this->_processTutorials();
\r
1729 foreach($this->tutorials as $package => $els)
\r
1731 foreach($els as $subpackage => $els2)
\r
1733 foreach($els2 as $type => $tutorials)
\r
1735 foreach($tutorials as $tutorial)
\r
1741 if ($tutorial->ini)
\r
1742 $a .= 'Top-level ';
\r
1743 if (!empty($tutorial->subpackage))
\r
1745 $ptext = "Converting ${a}Package-level tutorial ".$tutorial->name.'...';
\r
1749 if ($tutorial->ini)
\r
1750 $a .= 'Top-level ';
\r
1751 $ptext = "Converting ${a}Class-level tutorial " . $tutorial->name ." and associating...";
\r
1752 $link = Converter::getClassLink(str_replace('.cls','',$tutorial->name), $tutorial->package);
\r
1753 if (is_object($link))
\r
1755 if ($this->sort_absolutely_everything)
\r
1757 $addend = 'unsuccessful ';
\r
1758 if (isset($this->package_elements[$tutorial->package][$tutorial->subpackage]['class'][$link->name]))
\r
1760 $this->package_elements[$tutorial->package][$tutorial->subpackage]['class'][$link->name][0]->addTutorial($tutorial,$this);
\r
1761 $addend = 'success ';
\r
1765 $addend = 'unsuccessful ';
\r
1766 if (!isset($this->classes->killclass[str_replace('.cls','',$tutorial->name)]) && !isset($this->classes->killclass[str_replace('.cls','',$tutorial->name)][$tutorial->path]))
\r
1768 foreach($pages as $j => $inf)
\r
1770 foreach($inf->classelements as $i => $class)
\r
1772 if ($class->type == 'class' && $class->name == str_replace('.cls','',$tutorial->name) && $class->path == $link->path)
\r
1774 $pages[$j]->classelements[$i]->addTutorial($tutorial,$this);
\r
1775 $addend = 'success ';
\r
1781 $ptext .= $addend;
\r
1782 } else $ptext .= "unsuccessful ";
\r
1786 if ($tutorial->ini)
\r
1787 $a .= 'Top-level ';
\r
1788 $ptext = "Converting ${a}Procedural-level tutorial ".$tutorial->name." and associating...";
\r
1789 $link = Converter::getPageLink(str_replace('.proc','',$tutorial->name), $tutorial->package);
\r
1790 if (is_object($link))
\r
1792 $addend = 'unsuccessful ';
\r
1793 if ($this->sort_absolutely_everything)
\r
1795 if (isset($this->package_elements[$tutorial->package][$tutorial->subpackage]['page'][$link->path]))
\r
1797 $this->package_elements[$tutorial->package][$tutorial->subpackage]['page'][$link->path][0]->addTutorial($tutorial,$this);
\r
1798 $addend = "success ";
\r
1802 foreach($pages as $j => $info)
\r
1804 if ($j == $link->path)
\r
1806 $pages[$j]->addTutorial($tutorial,$this);
\r
1807 $addend = "success ";
\r
1811 $ptext .= $addend;
\r
1812 } else $ptext .= "unsuccessful ";
\r
1815 phpDocumentor_out($ptext);
\r
1817 $this->package = $tutorial->package;
\r
1818 $this->subpackage = $tutorial->subpackage;
\r
1819 $this->Convert($tutorial);
\r
1820 phpDocumentor_out("done\n");
\r
1826 phpDocumentor_out("Formatting Package Indexes...");
\r
1828 $this->formatPkgIndex();
\r
1829 phpDocumentor_out("done\n");
\r
1831 phpDocumentor_out("Formatting Index...");
\r
1833 $this->formatIndex();
\r
1834 phpDocumentor_out("done\n\n");
\r
1836 phpDocumentor_out("Formatting Left Quick Index...");
\r
1838 $this->formatLeftIndex();
\r
1839 phpDocumentor_out("done\n\n");
\r
1841 if ($this->sort_absolutely_everything) return $this->walk_everything();
\r
1842 foreach($pages as $j => $flub)
\r
1844 phpDocumentor_out('Converting '.$pages[$j]->parent->getPath());
\r
1846 $this->package = $pages[$j]->parent->package;
\r
1847 $this->subpackage = $pages[$j]->parent->subpackage;
\r
1848 $this->class = false;
\r
1849 $this->curfile = $pages[$j]->parent->getFile();
\r
1850 $this->curname = $this->getPageName($pages[$j]->parent);
\r
1851 $this->curpath = $pages[$j]->parent->getPath();
\r
1853 if ($this->package_output)
\r
1855 if (in_array($this->package,$this->package_output))
\r
1857 $this->Convert($pages[$j]);
\r
1864 $this->Convert($pages[$j]);
\r
1866 phpDocumentor_out(" Procedural Page Elements...");
\r
1869 for($i=0; $i<count($pages[$j]->elements); $i++)
\r
1871 $a = $pages[$j]->elements[$i]->docblock->getKeyword('access');
\r
1872 if (is_object($a)) $a = $a->getString();
\r
1873 if (!$this->parseprivate && ($a == 'private'))
\r
1875 // phpDocumentor_out(" ".$pages[$j]->elements[$i]->name."\n");
\r
1876 $pages[$j]->elements[$i]->docblock->package = $this->package;
\r
1877 $pages[$j]->elements[$i]->docblock->subpackage = $this->subpackage;
\r
1878 $this->Convert($pages[$j]->elements[$i]);
\r
1880 phpDocumentor_out(" Classes...");
\r
1881 $this->class = false;
\r
1883 for($i=0; $i<count($pages[$j]->classelements); $i++)
\r
1887 if ($pages[$j]->classelements[$i]->type == 'class')
\r
1889 if (!$this->killclass) $this->endClass();
\r
1890 $this->killclass = false;
\r
1891 if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
\r
1892 $this->package = $pages[$j]->classelements[$i]->docblock->package;
\r
1893 if ($this->package_output) if (!in_array($this->package,$this->package_output)) continue;
\r
1894 $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
\r
1895 $this->class = $pages[$j]->classelements[$i]->name;
\r
1898 $a = $pages[$j]->classelements[$i]->docblock->getKeyword('access');
\r
1899 if (is_object($a)) $a = $a->getString();
\r
1900 if (!$this->parseprivate && ($a == 'private'))
\r
1902 if ($this->killclass) continue;
\r
1903 // force all contained elements to have parent package/subpackage
\r
1904 $pages[$j]->classelements[$i]->docblock->package = $this->package;
\r
1905 $pages[$j]->classelements[$i]->docblock->subpackage = $this->subpackage;
\r
1908 if ($pages[$j]->classelements[$i]->type == 'class')
\r
1910 $this->killclass = false;
\r
1911 if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
\r
1912 $this->package = $pages[$j]->classelements[$i]->docblock->package;
\r
1913 if ($this->package_output) if (!in_array($this->package,$this->package_output)) continue;
\r
1914 $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
\r
1915 $this->class = $pages[$j]->classelements[$i]->name;
\r
1917 if ($this->killclass) continue;
\r
1918 // phpDocumentor_out(" ".$pages[$j]->classelements[$i]->name."\n");
\r
1919 $this->Convert($pages[$j]->classelements[$i]);
\r
1921 if (count($pages[$j]->classelements) && !$this->killclass) $this->endClass();
\r
1922 phpDocumentor_out(" done\n");
\r
1926 phpDocumentor_out("\nConverting @todo List...");
\r
1928 if (count($this->todoList))
\r
1930 $this->ConvertTodoList();
\r
1932 phpDocumentor_out("done\n");
\r
1934 phpDocumentor_out("\nConverting Error Log...");
\r
1936 $this->ConvertErrorLog();
\r
1937 phpDocumentor_out("done\n");
\r
1943 * Get a tree structure representing the hierarchy of tutorials
\r
1945 * Returns an array in format:
\r
1947 * array('tutorial' => {@link parserTutorial},
\r
1948 * 'kids' => array( // child tutorials
\r
1949 * array('tutorial' => child {@link parserTutorial},
\r
1950 * 'kids' => array(...)
\r
1955 * @param parserTutorial|array
\r
1956 * @tutorial tutorials.pkg
\r
1959 function getTutorialTree($tutorial)
\r
1961 if (is_object($tutorial))
\r
1963 $path = $this->_tutorial_path($tutorial,$tutorial,$tutorial);
\r
1964 if (isset($this->tutorial_tree[$path])) {
\r
1965 $tutorial = $this->tutorial_tree[$path];
\r
1971 if (isset($tutorial['tutorial']))
\r
1973 $tree['tutorial'] = $tutorial['tutorial'];
\r
1974 if (isset($tutorial['child']))
\r
1976 foreach($tutorial['child'] as $a => $b)
\r
1978 $btut = $b['tutorial'];
\r
1979 $res['tutorial'] = $this->tutorials[$btut->package][$btut->subpackage][$btut->tutorial_type][$btut->name];
\r
1980 if (isset($b['child']))
\r
1982 $tempres = Converter::getTutorialTree($b);
\r
1983 $res['kids'] = $tempres['kids'];
\r
1985 $tree['kids'][] = $res;
\r
1993 * Remove tutorials one by one from $all, and transfer them into $new in the
\r
1994 * order they should be parsed
\r
1995 * @param parserTutorial
\r
2000 function generateTutorialOrder($parent,&$all,&$new)
\r
2002 // remove from the list of tutorials to process
\r
2003 foreach($all[$parent->package][$parent->subpackage][$parent->tutorial_type] as $ind => $t)
\r
2005 if ($t->name == $parent->name) {
\r
2006 unset($all[$parent->package][$parent->subpackage][$parent->tutorial_type][$ind]);
\r
2009 // add to the new ordered list of tutorials
\r
2010 $x = &$new[$parent->package][$parent->subpackage][$parent->tutorial_type];
\r
2011 if (!is_object($x[count($x) - 1]) || $x[count($x) - 1]->name != $parent->name)
\r
2012 { // only add if the parent isn't also a child
\r
2013 $new[$parent->package][$parent->subpackage][$parent->tutorial_type][] = $parent;
\r
2014 // add a new branch to the tree
\r
2016 // process all child tutorials, and insert them in order
\r
2017 // debug("processing parent ".$parent->name);
\r
2020 foreach($parent->ini['Linked Tutorials'] as $child)
\r
2022 $sub = (empty($parent->subpackage) ? '' : $parent->subpackage . '/');
\r
2023 $kid = $parent->package . '/' . $sub . $child . '.' . $parent->tutorial_type;
\r
2024 $_klink = $this->getTutorialLink($kid,false,false,array($parent->package));
\r
2025 if (is_object($_klink)) {
\r
2026 $klink = $this->returnSee($_klink);
\r
2030 // remove the child from the list of remaining tutorials
\r
2031 foreach($all[$parent->package][$parent->subpackage][$parent->tutorial_type] as $ind => $tute)
\r
2033 if ($klink && $tute->getLink($this) == $klink)
\r
2035 // set up parent, next and prev links
\r
2036 $tute->setParent($parent, $this);
\r
2037 // remove the child from the list of tutorials to process
\r
2038 foreach($all[$parent->package][$parent->subpackage][$parent->tutorial_type] as $ind => $t)
\r
2040 if ($t->name == $tute->name)
\r
2041 unset($all[$parent->package][$parent->subpackage][$parent->tutorial_type][$ind]);
\r
2043 // add to the new ordered list of tutorials
\r
2044 $new[$parent->package][$parent->subpackage][$parent->tutorial_type][] = $tute;
\r
2047 // add all the child's child tutorials to the list
\r
2048 $this->generateTutorialOrder($tute,$all,$new);
\r
2057 /** Returns the path to this tutorial as a string
\r
2058 * @param parserTutorial $pkg
\r
2059 * @param parserTutorial $subpkg
\r
2060 * @param parserTutorial $namepkg
\r
2061 * @return string */
\r
2062 function _tutorial_path($pkg, $subpkg = 0, $namepkg = 0)
\r
2070 $subpackagename = ($subpkg->subpackage ? '/' . $subpkg->subpackage : '');
\r
2071 return $pkg->package . $subpackagename . '/' . $namepkg->name;
\r
2076 * Creates a tree structure of tutorials
\r
2080 * array('package/subpackage/tutorial1.ext' =>
\r
2081 * array('tutorial' => {@link parserTutorial},
\r
2083 * array('package/subpackage/child1tutorial.ext' => ...,
\r
2084 * 'package/subpackage/child2tutorial.ext' => ...,
\r
2087 * 'package/subpackage/tutorial2.ext' => ...,
\r
2091 * @return array the tutorial tree
\r
2094 function _setupTutorialTree($parent = false)
\r
2096 if (! isset($this->processed_tutorials)) {
\r
2097 $this->processed_tutorials = array();
\r
2102 foreach($this->tutorials as $package => $s)
\r
2104 foreach($s as $subpackage => $t)
\r
2106 foreach($t as $type => $n)
\r
2108 foreach($n as $name => $tutorial)
\r
2110 if ($tutorial->parent) {
\r
2114 $child_path = $this->_tutorial_path($tutorial,$tutorial,$tutorial);
\r
2115 if (isset($this->processed_tutorials[$child_path])) {
\r
2118 $this->processed_tutorials[$child_path] = $tutorial;
\r
2119 //debug("parent ".$tutorial->name);
\r
2120 $ret = $this->_setupTutorialTree($tutorial);
\r
2121 if (!count($tree)) {
\r
2124 $tree = array_merge($tree,$ret);
\r
2132 $parent_path = $this->_tutorial_path($parent);
\r
2133 $tree[$parent_path]['tutorial'] = $parent;
\r
2134 // process all child tutorials, and insert them in order
\r
2137 foreach($parent->ini['Linked Tutorials'] as $child)
\r
2139 if (isset($this->tutorials[$parent->package][$parent->subpackage]
\r
2140 [$parent->tutorial_type][$child . '.' .
\r
2141 $parent->tutorial_type])) {
\r
2142 // remove the child from the list of remaining tutorials
\r
2143 $tute = $this->tutorials[$parent->package][$parent->subpackage]
\r
2144 [$parent->tutorial_type][$child . '.' .
\r
2145 $parent->tutorial_type];
\r
2153 $child_path = $this->_tutorial_path($parent,$parent,$tute);
\r
2154 if (isset($this->processed_tutorials[$child_path])) {
\r
2157 $this->processed_tutorials[$child_path] = $tute;
\r
2158 if ($tute->name != $child . '.' . $parent->tutorial_type) {
\r
2161 //echo "Adding [$child_path] to [$parent_path]<br>";
\r
2162 $tree[$parent_path]['child'][$this->_tutorial_path($parent,$parent,$tute)]['tutorial']
\r
2164 if (!$tute->ini) {
\r
2167 // add all the child's child tutorials to the list
\r
2168 if (!isset($tree[$parent_path]['child'])) {
\r
2169 $tree[$parent_path]['child'] = $this->_setupTutorialTree($tute);
\r
2171 $tree[$parent_path]['child'] = array_merge($tree[$parent_path]['child'],
\r
2172 $this->_setupTutorialTree($tute));
\r
2180 * Debugging function for dumping {@link $tutorial_tree}
\r
2183 function vardump_tree($tree,$indent='')
\r
2185 if (phpDocumentor_get_class($tree) == 'parsertutorial') return $tree->name.' extends '.($tree->parent? $tree->parent->name : 'nothing');
\r
2187 foreach($tree as $ind => $stuff)
\r
2189 $x = $this->vardump_tree($stuff,"$indent ");
\r
2190 $a .= $indent.'['.$ind." => \n ".$indent.$x."]\n";
\r
2192 return substr($a,0,strlen($a) - 1);
\r
2198 function sort_package_elements($a,$b)
\r
2200 if (($a->type == $b->type) && (isset($a->isConstructor) && $a->isConstructor)) return -1;
\r
2201 if (($a->type == $b->type) && (isset($b->isConstructor) && $b->isConstructor)) return 1;
\r
2202 if ($a->type == $b->type) return strnatcasecmp($a->name,$b->name);
\r
2203 if ($a->type == 'class') return -1;
\r
2204 if ($b->type == 'class') return 1;
\r
2205 if ($a->type == 'const') return -1;
\r
2206 if ($b->type == 'const') return 1;
\r
2207 if ($a->type == 'var') return -1;
\r
2208 if ($b->type == 'var') return 1;
\r
2209 if ($a->type == 'page') return -1;
\r
2210 if ($b->type == 'page') return 1;
\r
2211 if ($a->type == 'include') return -1;
\r
2212 if ($b->type == 'include') return 1;
\r
2213 if ($a->type == 'define') return -1;
\r
2214 if ($b->type == 'define') return 1;
\r
2215 if ($a->type == 'global') return -1;
\r
2216 if ($b->type == 'global') return 1;
\r
2217 if ($a->type == 'function') return -1;
\r
2218 if ($b->type == 'function') return 1;
\r
2224 function defpackagesort($a,$b)
\r
2226 if ($a == $GLOBALS['phpDocumentor_DefaultPackageName']) return -1;
\r
2227 if ($b == $GLOBALS['phpDocumentor_DefaultPackageName']) return 0;
\r
2228 return strnatcasecmp($a,$b);
\r
2234 function Pc_sort($a,$b)
\r
2236 return strnatcasecmp(key($a),key($b));
\r
2240 * walk over elements by package rather than page
\r
2242 * This method is designed for converters like the PDF converter that need
\r
2243 * everything passed in alphabetical order by package/subpackage and by
\r
2244 * procedural and then class information
\r
2245 * @see PDFdefaultConverter
\r
2248 function walk_everything()
\r
2252 uksort($this->package_elements,array($this,'defpackagesort'));
\r
2253 foreach($this->package_elements as $package => $r)
\r
2255 if ($this->package_output)
\r
2257 if (!in_array($this->package,$this->package_output))
\r
2259 unset($this->package_elements[$package]);
\r
2263 uksort($this->package_elements[$package],'strnatcasecmp');
\r
2265 foreach($this->package_elements as $package => $r)
\r
2267 foreach($this->package_elements[$package] as $subpackage => $r)
\r
2269 if (isset($r['page']))
\r
2271 uksort($r['page'],'strnatcasecmp');
\r
2272 foreach($r['page'] as $page => $oo)
\r
2274 usort($this->package_elements[$package][$subpackage]['page'][$page],array($this,'sort_package_elements'));
\r
2277 if (isset($r['class']))
\r
2279 uksort($r['class'],'strnatcasecmp');
\r
2280 foreach($r['class'] as $page => $oo)
\r
2282 usort($r['class'][$page],array($this,'sort_package_elements'));
\r
2285 $this->package_elements[$package][$subpackage] = $r;
\r
2288 foreach($this->package_elements as $package => $s)
\r
2291 foreach($s as $subpackage => $r)
\r
2293 $this->package = $package;
\r
2294 $this->subpackage = $subpackage;
\r
2295 if (isset($r['page']))
\r
2297 $this->class = false;
\r
2298 foreach($r['page'] as $page => $elements)
\r
2300 if (is_array($elements))
\r
2302 foreach($elements as $element)
\r
2304 if ($element->type == 'page')
\r
2306 phpDocumentor_out('Converting '.$element->parent->getPath());
\r
2308 $this->curfile = $element->parent->getFile();
\r
2309 $this->curname = $this->getPageName($element->parent);
\r
2310 $this->curpath = $element->parent->getPath();
\r
2314 // force all contained elements to have parent package/subpackage
\r
2315 $element->docblock->package = $this->package;
\r
2316 $element->docblock->subpackage = $this->subpackage;
\r
2317 $a = $element->docblock->getKeyword('access');
\r
2318 if (is_object($a)) $a = $a->getString();
\r
2319 if (!$this->parseprivate && ($a == 'private'))
\r
2324 phpDocumentor_out(" Procedural Page Elements...");
\r
2328 $this->Convert($element);
\r
2332 phpDocumentor_out("done\n");
\r
2336 $start_classes = true;
\r
2337 if (isset($r['class']))
\r
2339 foreach($r['class'] as $class => $elements)
\r
2341 foreach($elements as $element)
\r
2343 if ($element->type == 'class')
\r
2345 if (!$start_classes)
\r
2347 if (count($elements) && !$this->killclass) $this->endClass();
\r
2348 phpDocumentor_out("done\n");
\r
2351 $start_classes = false;
\r
2352 $this->class = $element->getName();
\r
2353 $this->killclass = false;
\r
2354 if ($this->checkKillClass($element->getName(),$element->getPath())) continue;
\r
2355 if (!$this->killclass)
\r
2357 phpDocumentor_out('Converting '.$this->class."...");
\r
2365 phpDocumentor_out("Variables/methods/Class constants...\n");
\r
2369 $a = $element->docblock->getKeyword('access');
\r
2370 if (is_object($a)) $a = $a->getString();
\r
2371 if (!$this->parseprivate && ($a == 'private'))
\r
2373 if ($this->killclass) continue;
\r
2374 // force all contained elements to have parent package/subpackage
\r
2375 $element->docblock->package = $this->package;
\r
2376 $element->docblock->subpackage = $this->subpackage;
\r
2378 if ($this->killclass) continue;
\r
2379 $this->Convert($element);
\r
2382 if (count($elements) && !$this->killclass) $this->endClass();
\r
2383 phpDocumentor_out("done\n");
\r
2385 } // if isset($r['class'])
\r
2387 } // foreach($this->package_elements)
\r
2388 phpDocumentor_out("\nConverting @todo List...");
\r
2390 if (count($this->todoList))
\r
2392 $this->ConvertTodoList();
\r
2394 phpDocumentor_out("done\n");
\r
2396 phpDocumentor_out("\nConverting Error Log...");
\r
2398 $this->ConvertErrorLog();
\r
2399 phpDocumentor_out("done\n");
\r
2404 * Convert the phpDocumentor parsing/conversion error log
\r
2407 function ConvertErrorLog()
\r
2412 * Convert the list of all @todo tags
\r
2415 function ConvertTodoList()
\r
2420 * Sorts the @todo list - do not override or modify this function
\r
2422 * @uses _sortTodos passed to {@link usort()} to sort the todo list
\r
2424 function sortTodos()
\r
2426 phpDocumentor_out("\nSorting @todo list...");
\r
2428 foreach($this->todoList as $package => $r) {
\r
2429 usort($this->todoList[$package], array('Converter', '_sortTodoPackage'));
\r
2430 foreach ($r as $a => $sub) {
\r
2431 if (is_array($this->todoList[$package][$a][1])) {
\r
2432 usort($this->todoList[$package][$a][1],array('Converter', '_sortTodos'));
\r
2436 phpDocumentor_out("done\n");
\r
2439 /** @access private */
\r
2440 function _sortTodoPackage($a, $b)
\r
2442 return strnatcasecmp($a[0]->name, $b[0]->name);
\r
2445 /** @access private */
\r
2446 function _sortTodos($a, $b)
\r
2448 if (!is_object($a)) {
\r
2451 return strnatcasecmp($a->getString(), $b->getString());
\r
2455 * Sorts all indexes - do not override or modify this function
\r
2456 * @uses $leftindex based on the value of leftindex, sorts link arrays
\r
2457 * @uses $class_elements sorts with {@link compareLink}
\r
2458 * @uses $page_elements sorts with {@link compareLink}
\r
2459 * @uses $define_elements sorts with {@link compareLink}
\r
2460 * @uses $global_elements sorts with {@link compareLink}
\r
2461 * @uses $function_elements sorts with {@link compareLink}
\r
2462 * @uses $elements sorts with {@link elementCmp}
\r
2463 * @uses $pkg_elements sorts with {@link elementCmp} after sorting by
\r
2464 * package/subpackage alphabetically
\r
2467 function sortIndexes()
\r
2469 phpDocumentor_out("\nSorting Indexes...");
\r
2471 uksort($this->elements,'strnatcasecmp');
\r
2472 if ($this->leftindex['classes'])
\r
2474 foreach($this->class_elements as $package => $o1)
\r
2476 foreach($o1 as $subpackage => $links)
\r
2478 usort($this->class_elements[$package][$subpackage],array($this,'compareLink'));
\r
2482 if ($this->leftindex['pages'])
\r
2484 foreach($this->page_elements as $package => $o1)
\r
2486 uksort($this->page_elements[$package],'strnatcasecmp');
\r
2487 foreach($o1 as $subpackage => $links)
\r
2489 usort($this->page_elements[$package][$subpackage],array($this,'compareLink'));
\r
2493 if ($this->leftindex['defines'])
\r
2495 foreach($this->define_elements as $package => $o1)
\r
2497 uksort($this->define_elements[$package],'strnatcasecmp');
\r
2498 foreach($o1 as $subpackage => $links)
\r
2500 usort($this->define_elements[$package][$subpackage],array($this,'compareLink'));
\r
2504 if ($this->leftindex['globals'])
\r
2506 foreach($this->global_elements as $package => $o1)
\r
2508 uksort($this->global_elements[$package],'strnatcasecmp');
\r
2509 foreach($o1 as $subpackage => $links)
\r
2511 usort($this->global_elements[$package][$subpackage],array($this,'compareLink'));
\r
2515 if ($this->leftindex['functions'])
\r
2517 foreach($this->function_elements as $package => $o1)
\r
2519 uksort($this->function_elements[$package],'strnatcasecmp');
\r
2520 foreach($o1 as $subpackage => $links)
\r
2522 usort($this->function_elements[$package][$subpackage],array($this,'compareLink'));
\r
2526 foreach($this->elements as $letter => $nothuing)
\r
2528 uasort($this->elements[$letter],array($this,"elementCmp"));
\r
2530 foreach($this->pkg_elements as $package => $els)
\r
2532 uksort($this->pkg_elements[$package],'strnatcasecmp');
\r
2533 foreach($this->pkg_elements[$package] as $subpackage => $els)
\r
2535 if (empty($els)) continue;
\r
2536 uksort($this->pkg_elements[$package][$subpackage],'strnatcasecmp');
\r
2537 foreach($els as $letter => $yuh)
\r
2539 usort($this->pkg_elements[$package][$subpackage][$letter],array($this,"elementCmp"));
\r
2543 phpDocumentor_out("done\n");
\r
2548 * sorts {@link $page_contents} by element type as well as alphabetically
\r
2549 * @see $sort_page_contents_by_element_type
\r
2551 function sortPageContentsByElementType(&$pages)
\r
2553 foreach($this->page_contents as $package => $els)
\r
2555 foreach($this->page_contents[$package] as $subpackage => $els)
\r
2557 if (empty($els)) continue;
\r
2558 foreach($this->page_contents[$package][$subpackage] as $path => $stuff)
\r
2560 if (!count($pages[$path]->elements)) continue;
\r
2561 usort($pages[$path]->elements,array($this,'eltypecmp'));
\r
2562 usort($this->page_contents[$package][$subpackage][$path],array($this,'eltypecmp'));
\r
2563 if (isset($this->page_contents[$package][$subpackage][$path][0]))
\r
2564 $this->page_contents[$package][$subpackage][$path]['###main'] = $this->page_contents[$package][$subpackage][$path][0];
\r
2565 unset($this->page_contents[$package][$subpackage][$path][0]);
\r
2573 * @see Converter::sortIndexes()
\r
2575 function compareLink($a, $b)
\r
2577 return strnatcasecmp($a->name,$b->name);
\r
2582 * @see Converter::sortPageContentsByElementType()
\r
2584 function eltypecmp($a, $b)
\r
2586 if ($a->type == 'page') return -1;
\r
2587 if ($b->type == 'page') return 1;
\r
2588 return strnatcasecmp($a->type.$a->name,$b->type.$b->name);
\r
2592 * does a nat case sort on the specified second level value of the array
\r
2599 function elementCmp ($a, $b)
\r
2601 return strnatcasecmp($a->getName(), $b->getName());
\r
2605 * Used to stop conversion of @ignored or private @access classes
\r
2606 * @uses $killclass sets killclass based on the value of {@link Classes::$killclass}
\r
2607 * and {@link $package_output}
\r
2610 function checkKillClass($class, $path)
\r
2612 $this->killclass = false;
\r
2613 if (isset($this->classes->killclass[$class]) && isset($this->classes->killclass[$class][$path])) $this->killclass = true;
\r
2614 if ($this->package_output)
\r
2616 $a = $this->classes->getClass($class, $path);
\r
2617 if (!in_array($a->docblock->package,$this->package_output)) $this->killclass = true;
\r
2619 if (PHPDOCUMENTOR_DEBUG && $this->killclass) debug("$class $path killed");
\r
2620 return $this->killclass;
\r
2624 * @param abstractLink descendant of abstractLink
\r
2625 * @param array|parserTag list of @todos|@todo tag
\r
2628 function addTodoLink($link, $todos)
\r
2630 $this->todoList[$link->package][] = array($link, $todos);
\r
2634 * Adds all elements to the {@link $elements, $pkg_elements, $links},
\r
2635 * {@link $linkswithfile} and left indexes - Do not modify or override
\r
2637 * @param parserBase any documentable element descendant of parserBase
\r
2638 * except parserTutorial
\r
2639 * @param false|parserPage only used to add a {@link parserPage} if the
\r
2640 * $element passed is a parserPage
\r
2641 * @staticvar string path of current page, used for {@link $page_contents} setup
\r
2643 function addElement(&$element,$pageel=false)
\r
2645 static $curpath = '';
\r
2646 if ($this->package_output)
\r
2648 if (!in_array($this->package, $this->package_output)) return;
\r
2650 if ($pageel && phpDocumentor_get_class($pageel) == 'parserdata')
\r
2652 if (isset($pageel->docblock) && phpDocumentor_get_class($pageel->docblock) == 'parserdocblock')
\r
2654 $a = $pageel->docblock->getKeyword('todo');
\r
2657 $this->addTodoLink($this->addLink($element),$a);
\r
2661 if (isset($element->docblock))
\r
2663 $a = $element->docblock->getKeyword('access');
\r
2664 if (is_object($a)) $a = $a->getString();
\r
2665 if (!$this->parseprivate && ($a == 'private'))
\r
2667 $a = $element->docblock->getKeyword('todo');
\r
2670 if ($element->type != 'include') {
\r
2671 $this->addTodoLink($this->addLink($element),$a);
\r
2673 addWarning(PDERROR_NOTODO_INCLUDE, $element->getLineNumber(),
\r
2674 $element->getPath());
\r
2678 $startPositionOfElementName = 0; // which character of the element name actually starts its textual name
\r
2679 switch($element->type)
\r
2682 if ($this->sort_absolutely_everything)
\r
2684 $this->package_elements[$element->package][$element->subpackage]['page'][$element->getPath()][] = $pageel;
\r
2686 $link = $this->addLink($element);
\r
2687 $curpath = $element->getPath();
\r
2688 if ($this->leftindex['pages'])
\r
2689 $this->page_elements[$element->package][$element->subpackage][] = $link;
\r
2690 $this->page_contents[$element->package][$element->subpackage][$curpath]['###main'] = $link;
\r
2693 if ($this->sort_absolutely_everything)
\r
2695 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][] = $element;
\r
2697 $link = $this->addLink($element);
\r
2698 if ($this->leftindex['classes'])
\r
2699 $this->class_elements[$element->docblock->package][$element->docblock->subpackage][] = $link;
\r
2700 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class]['###main'] = $link;
\r
2703 if ($this->sort_absolutely_everything)
\r
2705 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][] = $element;
\r
2707 $link = $this->addLink($element);
\r
2710 if ($this->sort_absolutely_everything)
\r
2712 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][] = $element;
\r
2714 $link = $this->addLink($element);
\r
2715 if ($this->leftindex['defines'])
\r
2716 $this->define_elements[$element->docblock->package][$element->docblock->subpackage][] = $link;
\r
2717 $this->page_contents[$element->docblock->package][$element->docblock->subpackage][$curpath][] = $link;
\r
2720 if ($this->sort_absolutely_everything)
\r
2722 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][] = $element;
\r
2724 $link = $this->addLink($element);
\r
2725 $startPositionOfElementName = 1; // lose the leading "$" character
\r
2726 if ($this->leftindex['globals'])
\r
2727 $this->global_elements[$element->docblock->package][$element->docblock->subpackage][] = $link;
\r
2728 $this->page_contents[$element->docblock->package][$element->docblock->subpackage][$curpath][] = $link;
\r
2731 if ($this->sort_absolutely_everything)
\r
2733 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][] = $element;
\r
2735 $link = $this->addLink($element);
\r
2736 $startPositionOfElementName = 1; // lose the leading "$" character
\r
2737 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class][] = $link;
\r
2740 if ($this->sort_absolutely_everything)
\r
2742 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][] = $element;
\r
2744 $link = $this->addLink($element);
\r
2745 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class][] = $link;
\r
2748 if ($this->sort_absolutely_everything)
\r
2750 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][] = $element;
\r
2752 $link = $this->addLink($element);
\r
2753 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class][] = $link;
\r
2756 if ($this->sort_absolutely_everything)
\r
2758 $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][] = $element;
\r
2760 $link = $this->addLink($element);
\r
2761 if ($this->leftindex['functions'])
\r
2762 $this->function_elements[$element->docblock->package][$element->docblock->subpackage][] = $link;
\r
2763 $this->page_contents[$element->docblock->package][$element->docblock->subpackage][$curpath][] = $link;
\r
2768 if ($element->getType() != 'include')
\r
2770 if ($element->getType() == 'var' || $element->getType() == 'method'|| $element->getType() == 'const')
\r
2772 $this->links[$this->package][$this->subpackage][$element->getType()][$element->class][$element->getName()] = $link;
\r
2773 $this->linkswithfile[$this->package][$this->subpackage][$element->getType()][$element->getPath()][$element->class][$element->getName()] = $link;
\r
2776 if ($element->type == 'page')
\r
2778 $this->links[$this->package][$this->subpackage][$element->getType()][$element->getFile()] = $link;
\r
2779 $this->linkswithfile[$this->package][$this->subpackage][$element->getType()][$element->getPath()][$element->getFile()] = $link;
\r
2782 $this->links[$this->package][$this->subpackage][$element->getType()][$element->getName()] = $link;
\r
2783 $this->linkswithfile[$this->package][$this->subpackage][$element->getType()][$element->getPath()][$element->getName()] = $link;
\r
2787 if ($element->type == 'page')
\r
2789 $this->elements[substr(strtolower($element->getFile()),$startPositionOfElementName,1)][] = $element;
\r
2790 $this->pkg_elements[$this->package][$this->subpackage][substr(strtolower($element->getFile()),$startPositionOfElementName,1)][] = $element;
\r
2793 $this->elements[substr(strtolower($element->getName()),$startPositionOfElementName,1)][] = $element;
\r
2794 $this->pkg_elements[$this->package][$this->subpackage][substr(strtolower($element->getName()),$startPositionOfElementName,1)][] = $element;
\r
2799 * returns an abstract link to element. Do not modify or override
\r
2801 * This method should only be called in process of Conversion, unless
\r
2802 * $element is a parserPage, or $page is set to true, and $element is
\r
2803 * not a parserPage
\r
2804 * @return abstractLink abstractLink descendant
\r
2806 * @param parserElement element to add a new link (descended from
\r
2807 * {@link abstractLink})to the {@link $links} array
\r
2808 * @param string classname for elements that are class-based (this may be
\r
2809 * deprecated in the future, as the classname
\r
2810 * should be contained within the element. if $element is a
\r
2811 * page, this parameter is a package name
\r
2812 * @param string subpackage name for page elements
\r
2814 function addLink(&$element,$page = false)
\r
2818 // create a fake parserPage to extract the fileAlias for this link
\r
2819 $fakepage = new parserPage;
\r
2820 $fakepage->setPath($element->getPath());
\r
2821 $fakepage->setFile(basename($element->getPath()));
\r
2822 $this->curname = $this->getPageName($fakepage);
\r
2824 switch($element->type)
\r
2827 $x = new functionLink;
\r
2828 $x->addLink($element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2832 $x = new defineLink;
\r
2833 $x->addLink($element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2837 $x = new globalLink;
\r
2838 $x->addLink($element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2842 $x = new classLink;
\r
2843 $x->addLink($element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2847 $x = new methodLink;
\r
2848 $x->addLink($this->class, $element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2853 $x->addLink($this->class, $element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2857 $x = new constLink;
\r
2858 $x->addLink($this->class, $element->getPath(), $this->curname, $element->name, $element->docblock->package, $element->docblock->subpackage, $element->docblock->category);
\r
2862 $x = new pageLink;
\r
2863 $x->addLink($element->getPath(),$this->getPageName($element),$element->file,$element->package, $element->subpackage, $element->category);
\r
2870 * Return a tree of all classes that extend this class
\r
2872 * The data structure returned is designed for a non-recursive algorithm,
\r
2873 * and is somewhat complex.
\r
2874 * In most cases, the array returned is:
\r
2877 * array('#root' =>
\r
2878 * array('link' => {@link classLink} to $class,
\r
2879 * 'parent' => false,
\r
2880 * 'children' => array(array('class' => 'childclass1',
\r
2881 * 'package' => 'child1package'),
\r
2882 * array('class' => 'childclass2',
\r
2883 * 'package' => 'child2package'),...
\r
2886 * 'child1package#childclass1' =>
\r
2887 * array('link' => {@link classLink} to childclass1,
\r
2888 * 'parent' => '#root',
\r
2889 * 'children' => array(array('class' => 'kidclass',
\r
2890 * 'package' => 'kidpackage'),...
\r
2893 * 'kidpackage#kidclass' =>
\r
2894 * array('link' => {@link classLink} to kidclass,
\r
2895 * 'parent' => 'child1package#childclass1',
\r
2896 * 'children' => array() // no children
\r
2902 * To describe this format using language, every class in the tree has an
\r
2903 * entry in the first level of the array. The index for all child
\r
2904 * classes that extend the root class is childpackage#childclassname.
\r
2905 * Each entry in the array has 3 elements: link, parent, and children.
\r
2907 * <li>link - a {@link classLink} to the current class</li>
\r
2908 * <li>parent - a {@link classLink} to the class's parent, or false (except for one special case described below)</li>
\r
2909 * <li>children - an array of arrays, each entry has a 'class' and 'package' index to the child class,
\r
2910 * used to find the entry in the big array</li>
\r
2913 * special cases are when the #root class has a parent in another package,
\r
2914 * or when the #root class extends a class not found
\r
2915 * by phpDocumentor. In the first case, parent will be a
\r
2916 * classLink to the parent class. In the second, parent will be the
\r
2917 * extends clause, as in:
\r
2919 * class X extends Y
\r
2924 * in this case, the #root entry will be array('link' => classLink to X, 'parent' => 'Y', children => array(...))
\r
2926 * The fastest way to design a method to process the array returned
\r
2927 * is to copy HTMLframesConverter::getRootTree() into
\r
2928 * your converter and to modify the html to whatever output format you are going to use
\r
2929 * @see HTMLframesConverter::getRootTree()
\r
2930 * @param string class name
\r
2933 * @return array Format: see docs
\r
2935 function getSortedClassTreeFromClass($class,$package,$subpackage)
\r
2937 $my_tree = array();
\r
2938 $root = $this->classes->getClassByPackage($class,$package);
\r
2939 if (!$root) return false;
\r
2940 $class_children = $this->classes->getDefiniteChildren($class,$root->curfile);
\r
2941 if (!$class_children)
\r
2943 // special case: parent class is found, but is not part of this package, class has no children
\r
2944 if (is_array($root->parent))
\r
2946 $x = $root->getParent($this);
\r
2947 if ($x->docblock->package != $package)
\r
2949 $v = Converter::getClassLink($root->getName(),$package,$root->getPath());
\r
2950 return array('#root' => array('link' => $v,'parent' => Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath()), 'children' => array()));
\r
2953 { // class has normal situation, no children
\r
2954 if (is_string($root->getParent($this)))
\r
2955 return array('#root' => array('link' => Converter::getClassLink($root->getName(),$package,$root->getPath()), 'parent' => $root->getExtends(),'children' => array()));
\r
2957 return array('#root' => array('link' => Converter::getClassLink($root->getName(),$package,$root->getPath()), 'parent' => false, 'children' => array()));
\r
2960 // special case: parent class is found, but is not part of this package, class has children
\r
2961 if (is_array($root->parent))
\r
2963 $x = $root->getParent($this);
\r
2964 if ($x->docblock->package != $package)
\r
2966 $v = Converter::getClassLink($root->getName(),$package,$root->getPath());
\r
2967 $my_tree = array('#root' => array('link' => $v, 'parent' => Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath()), 'children' => array()));
\r
2972 $my_tree = array('#root' => array('link' => Converter::getClassLink($root->getName(),$package,$root->getPath()), 'parent' => false, 'children' => array()));
\r
2973 // location of tree walker
\r
2975 $lastcur = array(array(false,0));
\r
2977 if (isset($class_children))
\r
2981 if (!$class_children)
\r
2983 list($cur, $childpos) = array_pop($lastcur);
\r
2984 if (isset($my_tree[$cur]['children'][$childpos + 1]))
\r
2986 array_push($lastcur, array($cur, $childpos + 1));
\r
2988 $cur = $my_tree[$cur]['children'][$childpos + 1];
\r
2989 $x = $this->classes->getClassByPackage($cur['class'],$cur['package']);
\r
2991 $cur = $cur['package'] . '#' . $cur['class'];
\r
2992 $my_tree[$cur]['link'] = Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath());
\r
2993 $my_tree[$cur]['parent'] = $par;
\r
2994 $my_tree[$cur]['children'] = array();
\r
2995 $class_children = $this->classes->getDefiniteChildren($x->getName(), $x->curfile);
\r
2999 $class_children = false;
\r
3003 foreach($class_children as $chileclass => $chilefile)
\r
3005 $ch = $this->classes->getClass($chileclass,$chilefile);
\r
3006 $my_tree[$cur]['children'][] = array('class' => $ch->getName(), 'package' => $ch->docblock->package);
\r
3008 usort($my_tree[$cur]['children'],'rootcmp');
\r
3009 if (isset($my_tree[$cur]['children'][$childpos]))
\r
3011 array_push($lastcur, array($cur, $childpos));
\r
3013 $cur = $my_tree[$cur]['children'][$childpos];
\r
3014 $x = $this->classes->getClassByPackage($cur['class'],$cur['package']);
\r
3015 $cur = $cur['package'] . '#' . $cur['class'];
\r
3016 $my_tree[$cur]['link'] = Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath());
\r
3017 $my_tree[$cur]['parent'] = $par;
\r
3018 $my_tree[$cur]['children'] = array();
\r
3020 $class_children = $this->classes->getDefiniteChildren($x->getName(), $x->curfile);
\r
3023 list($cur, $childpos) = array_pop($lastcur);
\r
3032 * @return bool true if a link to this class exists in package $package and subpackage $subpackage
\r
3033 * @param string $expr class name
\r
3034 * @param string $package package to search in
\r
3035 * @param string $subpackage subpackage to search in
\r
3038 function isLinkedClass($expr,$package,$subpackage,$file=false)
\r
3041 return isset($this->linkswithfile[$package][$subpackage]['class'][$file][$expr]);
\r
3042 return isset($this->links[$package][$subpackage]['class'][$expr]);
\r
3047 * @return bool true if a link to this function exists in package $package and subpackage $subpackage
\r
3048 * @param string $expr function name
\r
3049 * @param string $package package to search in
\r
3050 * @param string $subpackage subpackage to search in
\r
3053 function isLinkedFunction($expr,$package,$subpackage,$file=false)
\r
3056 return isset($this->linkswithfile[$package][$subpackage]['function'][$file][$expr]);
\r
3057 return isset($this->links[$package][$subpackage]['function'][$expr]);
\r
3062 * @return bool true if a link to this define exists in package $package and subpackage $subpackage
\r
3063 * @param string $expr define name
\r
3064 * @param string $package package to search in
\r
3065 * @param string $subpackage subpackage to search in
\r
3068 function isLinkedDefine($expr,$package,$subpackage,$file=false)
\r
3071 return isset($this->linkswithfile[$package][$subpackage]['define'][$file][$expr]);
\r
3072 return isset($this->links[$package][$subpackage]['define'][$expr]);
\r
3077 * @return bool true if a link to this define exists in package $package and subpackage $subpackage
\r
3078 * @param string $expr define name
\r
3079 * @param string $package package to search in
\r
3080 * @param string $subpackage subpackage to search in
\r
3083 function isLinkedGlobal($expr,$package,$subpackage,$file=false)
\r
3086 return isset($this->linkswithfile[$package][$subpackage]['global'][$file][$expr]);
\r
3087 return isset($this->links[$package][$subpackage]['global'][$expr]);
\r
3092 * @return bool true if a link to this procedural page exists in package $package and subpackage $subpackage
\r
3093 * @param string $expr procedural page name
\r
3094 * @param string $package package to search in
\r
3095 * @param string $subpackage subpackage to search in
\r
3098 function isLinkedPage($expr,$package,$subpackage,$path=false)
\r
3101 return isset($this->linkswithfile[$package][$subpackage]['page'][$path][$expr]);
\r
3102 return isset($this->links[$package][$subpackage]['page'][$expr]);
\r
3107 * @return bool true if a link to this method exists in package $package, subpackage $subpackage and class $class
\r
3108 * @param string $expr method name
\r
3109 * @param string $class class name
\r
3110 * @param string $package package to search in
\r
3111 * @param string $subpackage subpackage to search in
\r
3114 function isLinkedMethod($expr,$package,$subpackage,$class,$file=false)
\r
3117 return isset($this->linkswithfile[$package][$subpackage]['method'][$file][$class][$expr]);
\r
3118 return isset($this->links[$package][$subpackage]['method'][$class][$expr]);
\r
3123 * @return bool true if a link to this method exists in package $package, subpackage $subpackage and class $class
\r
3124 * @param string $expr var name
\r
3125 * @param string $class class name
\r
3126 * @param string $package package to search in
\r
3127 * @param string $subpackage subpackage to search in
\r
3130 function isLinkedVar($expr,$package,$subpackage,$class,$file=false)
\r
3133 return isset($this->linkswithfile[$package][$subpackage]['var'][$file][$class][$expr]);
\r
3134 return isset($this->links[$package][$subpackage]['var'][$class][$expr]);
\r
3139 * @return bool true if a link to this method exists in package $package, subpackage $subpackage and class $class
\r
3140 * @param string $expr constant name
\r
3141 * @param string $class class name
\r
3142 * @param string $package package to search in
\r
3143 * @param string $subpackage subpackage to search in
\r
3146 function isLinkedConst($expr,$package,$subpackage,$class,$file=false)
\r
3149 return isset($this->linkswithfile[$package][$subpackage]['const'][$file][$class][$expr]);
\r
3150 return isset($this->links[$package][$subpackage]['const'][$class][$expr]);
\r
3154 * return false or a {@link classLink} to $expr
\r
3155 * @param string $expr class name
\r
3156 * @param string $package package name
\r
3157 * @return mixed returns a {@link classLink} or false if the element is not found in package $package
\r
3160 function getClassLink($expr,$package,$file=false, $text = false)
\r
3162 if (!isset($this->links[$package])) return false;
\r
3163 foreach($this->links[$package] as $subpackage => $notused)
\r
3165 if ($this->isLinkedClass($expr,$package,$subpackage,$file))
\r
3169 return $this->linkswithfile[$package][$subpackage]['class'][$file][$expr];
\r
3171 return $this->links[$package][$subpackage]['class'][$expr];
\r
3178 * return false or a {@link functionLink} to $expr
\r
3179 * @param string $expr function name
\r
3180 * @param string $package package name
\r
3181 * @return mixed returns a {@link functionLink} or false if the element is not found in package $package
\r
3182 * @see functionLink
\r
3184 function getFunctionLink($expr,$package,$file=false, $text = false)
\r
3186 if (!isset($this->links[$package])) return false;
\r
3187 foreach($this->links[$package] as $subpackage => $notused)
\r
3189 if ($this->isLinkedFunction($expr,$package,$subpackage,$file))
\r
3193 return $this->linkswithfile[$package][$subpackage]['function'][$file][$expr];
\r
3195 return $this->links[$package][$subpackage]['function'][$expr];
\r
3202 * return false or a {@link defineLink} to $expr
\r
3203 * @param string $expr constant name
\r
3204 * @param string $package package name
\r
3205 * @return mixed returns a {@link defineLink} or false if the element is not found in package $package
\r
3208 function getDefineLink($expr,$package,$file=false, $text = false)
\r
3210 if (!isset($this->links[$package])) return false;
\r
3211 foreach($this->links[$package] as $subpackage => $notused)
\r
3213 if ($this->isLinkedDefine($expr,$package,$subpackage,$file))
\r
3217 return $this->linkswithfile[$package][$subpackage]['define'][$file][$expr];
\r
3219 return $this->links[$package][$subpackage]['define'][$expr];
\r
3226 * return false or a {@link globalLink} to $expr
\r
3227 * @param string $expr global variable name (with leading $)
\r
3228 * @param string $package package name
\r
3229 * @return mixed returns a {@link defineLink} or false if the element is not found in package $package
\r
3232 function getGlobalLink($expr,$package,$file=false, $text = false)
\r
3234 if (!isset($this->links[$package])) return false;
\r
3235 foreach($this->links[$package] as $subpackage => $notused)
\r
3237 if ($this->isLinkedGlobal($expr,$package,$subpackage,$file))
\r
3241 return $this->linkswithfile[$package][$subpackage]['global'][$file][$expr];
\r
3243 return $this->links[$package][$subpackage]['global'][$expr];
\r
3250 * return false or a {@link pageLink} to $expr
\r
3251 * @param string $expr procedural page name
\r
3252 * @param string $package package name
\r
3253 * @return mixed returns a {@link pageLink} or false if the element is not found in package $package
\r
3256 function getPageLink($expr,$package,$path = false, $text = false, $packages = false)
\r
3258 if (!isset($this->links[$package])) return false;
\r
3259 foreach($this->links[$package] as $subpackage => $notused)
\r
3261 if ($this->isLinkedPage($expr,$package,$subpackage,$path))
\r
3265 return $this->linkswithfile[$package][$subpackage]['page'][$path][$expr];
\r
3267 return $this->links[$package][$subpackage]['page'][$expr];
\r
3274 * return false or a {@link methodLink} to $expr in $class
\r
3275 * @param string $expr method name
\r
3276 * @param string $class class name
\r
3277 * @param string $package package name
\r
3278 * @return mixed returns a {@link methodLink} or false if the element is not found in package $package, class $class
\r
3281 function getMethodLink($expr,$class,$package,$file=false, $text = false)
\r
3283 $expr = trim($expr);
\r
3284 $class = trim($class);
\r
3285 if (!isset($this->links[$package])) return false;
\r
3286 foreach($this->links[$package] as $subpackage => $notused)
\r
3288 if ($this->isLinkedMethod($expr,$package,$subpackage,$class,$file))
\r
3292 return $this->linkswithfile[$package][$subpackage]['method'][$file][$class][$expr];
\r
3294 return $this->links[$package][$subpackage]['method'][$class][$expr];
\r
3301 * return false or a {@link varLink} to $expr in $class
\r
3302 * @param string $expr var name
\r
3303 * @param string $class class name
\r
3304 * @param string $package package name
\r
3305 * @return mixed returns a {@link varLink} or false if the element is not found in package $package, class $class
\r
3308 function getVarLink($expr,$class,$package,$file=false, $text = false)
\r
3310 $expr = trim($expr);
\r
3311 $class = trim($class);
\r
3312 if (!isset($this->links[$package])) return false;
\r
3313 foreach($this->links[$package] as $subpackage => $notused)
\r
3315 if ($this->isLinkedVar($expr,$package,$subpackage,$class,$file))
\r
3319 return $this->linkswithfile[$package][$subpackage]['var'][$file][$class][$expr];
\r
3321 return $this->links[$package][$subpackage]['var'][$class][$expr];
\r
3328 * return false or a {@link constLink} to $expr in $class
\r
3329 * @param string $expr constant name
\r
3330 * @param string $class class name
\r
3331 * @param string $package package name
\r
3332 * @return mixed returns a {@link varLink} or false if the element is not found in package $package, class $class
\r
3335 function getConstLink($expr,$class,$package,$file=false, $text = false)
\r
3337 $expr = trim($expr);
\r
3338 $class = trim($class);
\r
3339 if (!isset($this->links[$package])) return false;
\r
3340 foreach($this->links[$package] as $subpackage => $notused)
\r
3342 if ($this->isLinkedConst($expr,$package,$subpackage,$class,$file))
\r
3346 return $this->linkswithfile[$package][$subpackage]['const'][$file][$class][$expr];
\r
3348 return $this->links[$package][$subpackage]['const'][$class][$expr];
\r
3355 * The meat of the @tutorial tag and inline {@}tutorial} tag
\r
3357 * Take a string and return an abstract link to the tutorial it represents.
\r
3358 * Since tutorial naming literally works like the underlying filesystem, the
\r
3359 * way to reference the tutorial is similar. Tutorials are located in a
\r
3360 * subdirectory of any directory parsed, which is named 'tutorials/' (we
\r
3361 * try to make things simple when we can :). They are further organized by
\r
3362 * package and subpackage as:
\r
3364 * tutorials/package/subpackage
\r
3366 * and the files are named *.cls, *.pkg, or *.proc, and so a link to a tutorial
\r
3367 * named file.cls can be referenced (depending on context) as any of:
\r
3370 * * @tutorial package/subpackage/file.cls
\r
3371 * * @tutorial package/file.cls
\r
3372 * * @tutorial file.cls
\r
3375 * The first case will only be needed if file.cls exists in both the current
\r
3376 * package, in anotherpackage/file.cls and in anotherpackage/subpackage/file.cls
\r
3377 * and you wish to reference the one in anotherpackage/subpackage.
\r
3378 * The second case is only needed if you wish to reference file.cls in another
\r
3379 * package and it is unique in that package. the third will link to the first
\r
3380 * file.cls it finds using this search method:
\r
3383 * <li>current package/subpackage</li>
\r
3384 * <li>all other subpackages of current package</li>
\r
3385 * <li>parent package, if this package has classes that extend classes in
\r
3386 * another package</li>
\r
3387 * <li>all other packages</li>
\r
3389 * @return tutorialLink|string returns either a link, or the original text, if not found
\r
3390 * @param string the original expression
\r
3391 * @param string package to look in first
\r
3392 * @param string subpackage to look in first
\r
3393 * @param array array of package names to search in if not found in parent packages.
\r
3394 * This is used to limit the search, phpDocumentor automatically searches
\r
3398 function getTutorialLink($expr, $package = false, $subpackage = false, $packages = false)
\r
3400 // is $expr a comma-delimited list?
\r
3401 if (strpos($expr,','))
\r
3403 $a = explode(',',$expr);
\r
3405 for($i=0;$i<count($a);$i++)
\r
3407 // if so return each component with a link
\r
3408 $b[] = Converter::getTutorialLink(trim($a[$i]));
\r
3413 if (strpos($expr,'#'))
\r
3415 $a = explode('#',$expr);
\r
3418 $subsection = $a[1];
\r
3420 if (strpos($expr,'/'))
\r
3422 $a = explode('/',$expr);
\r
3423 if (count($a) == 3)
\r
3425 return Converter::getTutorialLink($a[2],$a[0],$a[1],array());
\r
3427 if (count($a) == 2)
\r
3429 return Converter::getTutorialLink($a[1],$a[0],false,array());
\r
3432 if (!$package) $package = $this->package;
\r
3433 if (!$subpackage) $subpackage = $this->subpackage;
\r
3434 if (!isset($this->all_packages[$package])) return $expr;
\r
3435 elseif (isset($packages[$package])) unset($packages[$package]);
\r
3436 $ext = pathinfo($expr, PATHINFO_EXTENSION);
\r
3437 if (isset($this->tutorials[$package][$subpackage][$ext][$expr]))
\r
3439 $a = $this->tutorials[$package][$subpackage][$ext][$expr];
\r
3440 $link = new tutorialLink;
\r
3441 $link->addLink($subsection,$a->path,$a->name,$a->package,$a->subpackage,$a->getTitle($this,$subsection));
\r
3446 if (!is_array($packages))
\r
3448 $packages = $this->all_packages;
\r
3449 if (isset($packages[$package])) unset($packages[$package]);
\r
3451 if (isset($this->tutorials[$package]))
\r
3453 if (isset($this->tutorials[$package][$subpackage][$ext][$expr]))
\r
3455 $a = $this->tutorials[$package][$subpackage][$ext][$expr];
\r
3456 $link = new tutorialLink;
\r
3457 $link->addLink($subsection,$a->path,$a->name,$a->package,$a->subpackage,$a->getTitle($this));
\r
3461 foreach($this->tutorials[$package] as $subpackage => $stuff)
\r
3463 if (isset($stuff[$ext][$expr]))
\r
3465 $a = $stuff[$ext][$expr];
\r
3466 $link = new tutorialLink;
\r
3467 $link->addLink($subsection,$a->path,$a->name,$a->package,$a->subpackage,$a->getTitle($this));
\r
3473 // try other packages
\r
3474 // look in parent package first, if found
\r
3475 if (isset($this->package_parents[$package]))
\r
3478 $package = $this->package_parents[$package];
\r
3481 // no parent package, so start with the first one that's left
\r
3482 list($package,) = @each($packages);
\r
3486 if (isset($packages[$package])) unset($packages[$package]);
\r
3488 } while (count($packages) || $package);
\r
3489 addWarning(PDERROR_TUTORIAL_NOT_FOUND,$expr);
\r
3494 * The meat of the @see tag and inline {@}link} tag
\r
3496 * $expr is a string with many allowable formats:
\r
3498 * <li>proceduralpagename.ext</li>
\r
3499 * <li>constant_name</li>
\r
3500 * <li>classname::function()</li>
\r
3501 * <li>classname::constantname</li> (new 1.2.4)
\r
3502 * <li>classname::$variablename</li>
\r
3503 * <li>classname</li>
\r
3504 * <li>object classname</li>
\r
3505 * <li>function functionname()</li>
\r
3506 * <li>global $globalvarname</li>
\r
3507 * <li>packagename#expr where expr is any of the above</li>
\r
3510 * New in version 1.1, you can explicitly specify a package to link to that
\r
3511 * is different from the current package. Use the # operator
\r
3512 * to specify a new package, as in tests#bug-540368.php (which should appear
\r
3513 * as a link like: "{@link tests#bug-540368.php}"). This
\r
3514 * example links to the procedural page bug-540368.php in package
\r
3515 * tests. Also, the "function" operator is now used to specifically
\r
3516 * link to a function instead of a method in the current class.
\r
3521 * // from inside the class definition, use "function conflict()" to refer to procedural function "conflict()"
\r
3522 * function conflict()
\r
3527 * function conflict()
\r
3532 * If classname:: is not present, and the see tag is in a documentation
\r
3533 * block within a class, then the function uses the classname to
\r
3534 * search for $expr as a function or variable within classname, or any of its parent classes.
\r
3535 * given an $expr without '$', '::' or '()' getLink first searches for
\r
3536 * classes, procedural pages, constants, global variables, and then searches for
\r
3537 * methods and variables within the default class, and finally for any function
\r
3539 * @param string $expr expression to search for a link
\r
3540 * @param string $package package to start searching in
\r
3541 * @param array $packages list of all packages to search in
\r
3542 * @return mixed getLink returns a descendant of {@link abstractLink} if it finds a link, otherwise it returns a string
\r
3543 * @see getPageLink(), getDefineLink(), getVarLink(), getFunctionLink(), getClassLink()
\r
3544 * @see pageLink, functionLink, defineLink, classLink, methodLink, varLink
\r
3546 function &getLink($expr, $package = false, $packages = false)
\r
3548 // is $expr a comma-delimited list?
\r
3549 if (strpos($expr,','))
\r
3551 $a = explode(',',$expr);
\r
3553 for($i=0;$i<count($a);$i++)
\r
3555 // if so return each component with a link
\r
3556 $b[] = Converter::getLink(trim($a[$i]));
\r
3560 if (strpos($expr,'#'))
\r
3562 $a = explode('#',$expr);
\r
3563 if (count($a) == 2)
\r
3564 { // can have exactly 1 package override, otherwise it's ignored
\r
3565 // feature 564991, link to php manual
\r
3566 if ($a[0] == 'PHP_MANUAL') {
\r
3567 $s = 'http://www.php.net/'.$a[1];
\r
3570 $s = &Converter::getLink($a[1],$a[0],array());
\r
3574 $a = &$this->_getLink($expr, $package, $packages);
\r
3581 function &_getLink($expr, $package = false, $packages = false)
\r
3583 if (!$package) $package = $this->package;
\r
3585 if (!isset($this->all_packages[$package])) return $expr;
\r
3586 elseif (isset($packages[$package])) unset($packages[$package]);
\r
3587 $links = &$this->links;
\r
3588 $class = $this->class;
\r
3589 if (strpos($expr,'function ') === 0)
\r
3590 { // asking for a function, not a method
\r
3591 if ($test = Converter::getFunctionLink(str_replace('function ','',str_replace('()','',$expr)), $package)) return $test;
\r
3592 else return $expr;
\r
3594 if (strpos($expr,'global ') === 0)
\r
3595 { // asking for a global variable
\r
3596 if ($test = Converter::getGlobalLink(str_replace('global ','',$expr), $package)) return $test;
\r
3597 else return $expr;
\r
3599 if (strpos($expr,'object ') === 0)
\r
3600 { // asking for a class
\r
3601 if ($test = Converter::getClassLink(str_replace('object ','',$expr), $package)) return $test;
\r
3602 else return $expr;
\r
3604 if (strpos($expr,'constant ') === 0)
\r
3605 { // asking for a class
\r
3606 if ($test = Converter::getDefineLink(str_replace('constant ','',$expr), $package)) return $test;
\r
3607 else return $expr;
\r
3609 // are we in a class?
\r
3612 // is $expr simply a word? see if it is the class
\r
3613 if (trim($expr) == $class)
\r
3615 if ($test = Converter::getClassLink(trim(str_replace('object ','',$expr)),$package)) return $test;
\r
3617 // if not, check to see if it is a method or variable of this class tree
\r
3618 if (!strpos($expr,'::'))
\r
3620 // if get is neither get() nor $get, assume get is a function, add () to make get()
\r
3621 if (strpos($expr,'$') !== 0 && !strpos($expr,'()')) //$get = $get.'()';
\r
3623 if ($a = $this->getLinkMethod($expr,$class,$package)) return $a;
\r
3624 if ($a = $this->getLinkConst($expr,$class,$package)) return $a;
\r
3625 if ($a = $this->getLinkVar('$'.$expr,$class,$package)) return $a;
\r
3627 if (strpos($expr,'()')) if ($a = $this->getLinkMethod($expr,$class,$package)) return $a;
\r
3628 if (is_numeric(strpos($expr,'$'))) if ($a = $this->getLinkVar($expr,$class,$package)) return $a;
\r
3631 if ($test = Converter::getClassLink(trim(str_replace('object ','',$expr)),$package)) return $test;
\r
3632 if ($test = Converter::getPageLink(trim($expr),$package)) return $test;
\r
3633 if ($test = Converter::getDefineLink(trim($expr),$package)) return $test;
\r
3634 if ($test = Converter::getGlobalLink(trim($expr),$package)) return $test;
\r
3635 // if (strpos($expr,'.'))
\r
3636 // package specified
\r
3638 if (!is_array($packages))
\r
3640 $packages = $this->all_packages;
\r
3644 if (isset($packages[$package])) unset($packages[$package]);
\r
3645 if ($test = Converter::getClassLink(str_replace('object ','',$expr),$package)) return $test;
\r
3646 if ($test = Converter::getPageLink($expr,$package)) return $test;
\r
3647 if ($test = Converter::getDefineLink($expr,$package)) return $test;
\r
3648 if ($test = Converter::getGlobalLink($expr,$package)) return $test;
\r
3649 // is $expr in class::method() or class::$variable format?
\r
3650 if (strpos($expr,'function ') === 0)
\r
3651 { // asking for a function, not a method
\r
3652 if ($test = Converter::getFunctionLink(str_replace('function','',str_replace('()','',$expr)), $package)) return $test;
\r
3653 else return $expr;
\r
3655 $test = $this->_getDoubleColon($expr, $package, $packages, $class, $links);
\r
3656 if (!is_string($test)) return $test;
\r
3657 if (strpos($test, 'parent::') === 0) return $test;
\r
3658 // $expr does not have ::
\r
3659 if (is_numeric(@strpos('$',$expr)))
\r
3661 // default to current class, whose name is contained in $this->render->parent
\r
3662 if ($test = Converter::getVarLink($expr, $class, $package)) return $test;
\r
3664 // $expr is a function? (non-method)
\r
3665 if (@strpos($expr,'()'))
\r
3667 // otherwise, see if it is a method
\r
3670 if ($test = Converter::getMethodLink(str_replace('()','',$expr), $class, $package)) return $test;
\r
3672 // extract the function name, use it to retrieve the file that the function is in
\r
3673 // $page = $this->func_page[str_replace('function ','',str_replace('()','',$expr))];
\r
3674 // return the link
\r
3675 if ($test = Converter::getFunctionLink(str_replace('function ','',str_replace('()','',$expr)), $package)) return $test;
\r
3677 // $expr is just a word. First, test to see if it is a function of the current package
\r
3678 if ($test = Converter::getFunctionLink(str_replace('function ','',str_replace('()','',$expr)), $package)) return $test;
\r
3679 // try other packages
\r
3680 // look in parent package first, if found
\r
3681 if (isset($this->package_parents[$package]) && in_array($this->package_parents[$package], $packages))
\r
3684 $package = $this->package_parents[$package];
\r
3687 if (isset($packages[$package])) unset($packages[$package]);
\r
3691 // no parent package, so start with the first one that's left
\r
3692 $package = @array_shift(@array_keys($packages));
\r
3693 if ($package && isset($packages[$package]))
\r
3695 unset($packages[$package]);
\r
3697 } while (count($packages) || $package);
\r
3698 $funcs = get_defined_functions();
\r
3699 // feature 564991, link to php manual
\r
3700 if (in_array(str_replace(array('(',')'),array('',''),$expr),$funcs['internal']))
\r
3702 $return = 'http://www.php.net/'.str_replace(array('(',')'),array('',''),$expr);
\r
3710 * Split up getLink to make it easier to debug
\r
3713 function _getDoubleColon(&$expr, &$package, &$packages, $class, $links)
\r
3715 if (@strpos($expr,'::'))
\r
3717 $class_method = explode('::',$expr);
\r
3718 if ($class_method[0] == 'parent')
\r
3720 // can only have parent in the same package as the class! subtle bug
\r
3721 $package = $this->package;
\r
3722 $packages = array();
\r
3723 $cl = $this->classes->getClassByPackage($class,$package);
\r
3725 { // this is possible if an example file has parent::method()
\r
3728 $par = $cl->getParent($this);
\r
3729 $phpparent = false;
\r
3730 if (is_object($par))
\r
3732 $package = $par->docblock->package;
\r
3733 $phpparent = $par->getName();
\r
3736 addWarning(PDERROR_CLASS_PARENT_NOT_FOUND,$class,$package,$class_method[1]);
\r
3739 if ($phpparent) $class_method[0] = $phpparent;
\r
3741 if (strpos($class_method[1],'()'))
\r
3743 // strip everything but the function name, return a link
\r
3744 if ($test = Converter::getMethodLink(str_replace('()','',$class_method[1]), $class_method[0], $package)) return $test;
\r
3746 if ($test = Converter::getVarLink($class_method[1], $class_method[0], $package)) return $test;
\r
3747 if ($test = Converter::getConstLink($class_method[1], $class_method[0], $package)) return $test;
\r
3753 * cycle through parent classes to retrieve a link to a method
\r
3754 * do not use or override, used by getLink
\r
3757 function &getLinkMethod($expr, $class, $package)
\r
3759 $links = &$this->links;
\r
3762 // is $expr in class::method() or class::$variable format?
\r
3763 if (@strpos($expr,'::'))
\r
3765 $class_method = explode('::',$expr);
\r
3766 if ($class_method[0] == 'parent')
\r
3768 $cl = $this->classes->getClassByPackage($class,$package);
\r
3769 $par = $cl->getParent($this);
\r
3770 $phpparent = false;
\r
3771 if (is_object($par))
\r
3773 $package = $par->docblock->package;
\r
3774 $phpparent = $par->getName();
\r
3775 } else addWarning(PDERROR_CLASSPARENT_NOTFOUND,$class,$package,$class_method[1]);
\r
3776 if ($phpparent) $class_method[0] = $phpparent;
\r
3779 $cl = $this->classes->getClassByPackage($class,$package);
\r
3781 if (strpos($class_method[1],'()'))
\r
3783 // strip everything but the function name, return a link
\r
3784 if ($test = Converter::getMethodLink(str_replace('function ','',str_replace('()','',$class_method[1])), $class_method[0], $package)) return $test;
\r
3787 if ($test = Converter::getMethodLink(str_replace('()','',$expr), $class, $package)) return $test;
\r
3788 $cl = $this->classes->getClassByPackage($class,$package);
\r
3791 $par = $cl->getParent($this);
\r
3792 if (is_object($par))
\r
3794 $package = $par->docblock->package;
\r
3795 $class = $par->getName();
\r
3796 } else $class = $par;
\r
3797 } else $class = false;
\r
3805 * cycle through parent classes to retrieve a link to a var
\r
3806 * do not use or override, used by getLink
\r
3809 function &getLinkVar($expr, $class, $package)
\r
3811 $links = &$this->links;
\r
3814 // is $expr in class::method() or class::$variable format?
\r
3815 if (@strpos($expr,'::'))
\r
3817 $class_method = explode('::',$expr);
\r
3818 if ($class_method[0] == 'parent')
\r
3820 $cl = $this->classes->getClassByPackage($class,$package);
\r
3821 $phpparent = false;
\r
3822 $par = $cl->getParent($this);
\r
3823 if (is_object($par))
\r
3825 $package = $par->docblock->package;
\r
3826 $phpparent = $par->getName();
\r
3827 } else addWarning(PDERROR_CLASSPARENT_NOTFOUND,$class,$package,$class_method[1]);
\r
3828 if ($phpparent) $class_method[0] = $phpparent;
\r
3831 $cl = $this->classes->getClassByPackage($class,$package);
\r
3833 if ($test = Converter::getVarLink($class_method[1], $class_method[0], $package)) return $test;
\r
3834 if ($test = Converter::getVarLink('$'.$class_method[1], $class_method[0], $package)) return $test;
\r
3836 if ($test = Converter::getVarLink($expr, $class, $package)) return $test;
\r
3837 if ($test = Converter::getVarLink('$'.$expr, $class, $package)) return $test;
\r
3838 $cl = $this->classes->getClassByPackage($class,$package);
\r
3841 $par = $cl->getParent($this);
\r
3842 if (is_object($par))
\r
3844 $package = $par->docblock->package;
\r
3845 $class = $par->getName();
\r
3846 } else $class = $par;
\r
3847 } else $class = false;
\r
3855 * cycle through parent classes to retrieve a link to a class constant
\r
3856 * do not use or override, used by getLink
\r
3860 function &getLinkConst($expr, $class, $package)
\r
3862 $links = &$this->links;
\r
3865 // is $expr in class::method() or class::$variable format?
\r
3866 if (@strpos($expr,'::'))
\r
3868 $class_method = explode('::',$expr);
\r
3869 if ($class_method[0] == 'parent')
\r
3871 $cl = $this->classes->getClassByPackage($class,$package);
\r
3872 $phpparent = false;
\r
3873 $par = $cl->getParent($this);
\r
3874 if (is_object($par))
\r
3876 $package = $par->docblock->package;
\r
3877 $phpparent = $par->getName();
\r
3878 } else addWarning(PDERROR_CLASSPARENT_NOTFOUND,$class,$package,$class_method[1]);
\r
3879 if ($phpparent) $class_method[0] = $phpparent;
\r
3882 $cl = $this->classes->getClassByPackage($class,$package);
\r
3884 if ($test = Converter::getConstLink($class_method[1], $class_method[0], $package)) return $test;
\r
3886 if ($test = Converter::getConstLink($expr, $class, $package)) return $test;
\r
3887 $cl = $this->classes->getClassByPackage($class,$package);
\r
3890 $par = $cl->getParent($this);
\r
3891 if (is_object($par))
\r
3893 $package = $par->docblock->package;
\r
3894 $class = $par->getName();
\r
3895 } else $class = $par;
\r
3896 } else $class = false;
\r
3904 * take URL $link and text $text and return a link in the format needed for the Converter
\r
3905 * @param string URL
\r
3906 * @param string text to display
\r
3907 * @return string link to $link
\r
3910 function returnLink($link,$text)
\r
3915 * take {@link abstractLink} descendant and text $eltext and return a link
\r
3916 * in the format needed for the Converter
\r
3917 * @param abstractLink
\r
3919 * @return string link to $element
\r
3922 function returnSee(&$link, $eltext = false)
\r
3927 * take {@link abstractLink} descendant and text $eltext and return a
\r
3928 * unique ID in the format needed for the Converter
\r
3929 * @param abstractLink
\r
3930 * @return string unique identifier of $element
\r
3933 function getId(&$link)
\r
3938 * Convert README/INSTALL/CHANGELOG file contents to output format
\r
3939 * @param README|INSTALL|CHANGELOG
\r
3940 * @param string contents of the file
\r
3943 function Convert_RIC($name, $contents)
\r
3948 * Convert all elements to output format
\r
3950 * This will call ConvertXxx where Xxx is {@link ucfirst}($element->type).
\r
3951 * It is expected that a child converter defines a handler for every
\r
3952 * element type, even if that handler does nothing. phpDocumentor will
\r
3953 * terminate with an error if a handler doesn't exist.
\r
3955 * Since 1.2.0 beta 3, this function has been moved from child converters
\r
3956 * to the parent, because it doesn't really make sense to put it in the
\r
3957 * child converter, and we can add error handling.
\r
3960 * @throws {@link PDERROR_NO_CONVERT_HANDLER}
\r
3961 * @param mixed {@link parserElement} descendant or {@link parserPackagePage} or {@link parserData}
\r
3963 function Convert(&$element)
\r
3965 $handler = 'convert'.ucfirst($element->type);
\r
3966 if (method_exists($this,$handler))
\r
3968 $this->$handler($element);
\r
3971 addErrorDie(PDERROR_NO_CONVERTER_HANDLER,$element->type,$handler,phpDocumentor_get_class($this));
\r
3975 * Conversion Handlers
\r
3977 * All of the convert* handlers set up template variables for the Smarty
\r
3978 * template.{@internal In addition, the {@link newSmarty()} method is
\r
3979 * called to retrieve the global Smarty template}}
\r
3982 * Default Tutorial Handler
\r
3984 * Sets up the tutorial template, and its prev/next/parent links
\r
3986 * Retrieves the title using {@link parserTutorial::getTitle()} and uses the
\r
3987 * {@link parserTutorial::prev, parserTutorial::next, parserTutorial::parent}
\r
3988 * links to set up those links.}}
\r
3989 * @param parserTutorial
\r
3991 function &convertTutorial(&$element)
\r
3993 $this->package = $element->package;
\r
3994 $this->subpackage = $element->subpackage;
\r
3995 $x = $element->Convert($this);
\r
3996 $template = &$this->newSmarty();
\r
3997 $template->assign('contents',$x);
\r
3998 $template->assign('title',$element->getTitle($this));
\r
3999 $template->assign('nav',$element->parent || $element->prev || $element->next);
\r
4000 if ($element->parent)
\r
4002 $template->assign('up',$this->getId($element->parent));
\r
4003 $template->assign('uptitle',$element->parent->title);
\r
4005 if ($element->prev)
\r
4007 $template->assign('prev',$this->getId($element->prev));
\r
4008 $template->assign('prevtitle',$element->prev->title);
\r
4010 if ($element->next)
\r
4012 $template->assign('next',$this->getId($element->next));
\r
4013 $template->assign('nexttitle',$element->next->title);
\r
4018 * Default Class Handler
\r
4020 * Sets up the class template.
\r
4021 * {@internal special methods
\r
4022 * {@link generateChildClassList(), generateFormattedClassTree()},
\r
4023 * {@link getFormattedConflicts, getFormattedInheritedMethods},
\r
4024 * and {@link getFormattedInheritedVars} are called to complete vital
\r
4025 * template setup.}}
\r
4027 function convertClass(&$element)
\r
4029 $this->class = $element->getName();
\r
4030 $this->class_data = &$this->newSmarty();
\r
4031 $this->class_data->assign("class_name",$element->getName());
\r
4032 $this->class_data->assign("vars",array());
\r
4033 $this->class_data->assign("methods",array());
\r
4034 $this->class_data->assign("consts",array());
\r
4035 $this->class_data->assign("is_interface", $element->isInterface());
\r
4036 $this->class_data->assign("implements", $this->getFormattedImplements($element));
\r
4037 $this->class_data->assign("package",$element->docblock->package);
\r
4038 $this->class_data->assign("line_number",$element->getLineNumber());
\r
4039 $this->class_data->assign("source_location",$element->getSourceLocation($this));
\r
4040 $this->class_data->assign("page_link",$this->getCurrentPageLink());
\r
4041 $docblock = $this->prepareDocBlock($element, false);
\r
4042 $this->class_data->assign("sdesc",$docblock['sdesc']);
\r
4043 $this->class_data->assign("desc",$docblock['desc']);
\r
4044 $this->class_data->assign("access", $docblock['access']);
\r
4045 $this->class_data->assign("abstract", $docblock['abstract']);
\r
4046 $this->class_data->assign("tags",$docblock['tags']);
\r
4047 $this->class_data->assign("api_tags",$docblock['api_tags']);
\r
4048 $this->class_data->assign("info_tags",$docblock['info_tags']);
\r
4049 $this->class_data->assign("utags",$docblock['utags']);
\r
4050 $this->class_data->assign( "prop_tags", $docblock['property_tags'] );
\r
4051 if ($this->hasSourceCode($element->getPath())) {
\r
4052 $this->class_data->assign("class_slink",$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true));
\r
4056 $this->class_data->assign("class_slink",false);
\r
4057 $this->class_data->assign("children", $this->generateChildClassList($element));
\r
4058 $this->class_data->assign("class_tree", $this->generateFormattedClassTree($element));
\r
4059 $this->class_data->assign("conflicts", $this->getFormattedConflicts($element,"classes"));
\r
4060 $inherited_methods = $this->getFormattedInheritedMethods($element);
\r
4061 if (!empty($inherited_methods))
\r
4063 $this->class_data->assign("imethods",$inherited_methods);
\r
4066 $this->class_data->assign("imethods",false);
\r
4068 $inherited_vars = $this->getFormattedInheritedVars($element);
\r
4069 if (!empty($inherited_vars))
\r
4071 $this->class_data->assign("ivars",$inherited_vars);
\r
4074 $this->class_data->assign("ivars",false);
\r
4076 $inherited_consts = $this->getFormattedInheritedConsts($element);
\r
4077 if (!empty($inherited_consts))
\r
4079 $this->class_data->assign("iconsts",$inherited_consts);
\r
4082 $this->class_data->assign("iconsts",false);
\r
4088 * Converts method for template output
\r
4090 * This function must be called by a child converter with any extra
\r
4091 * template variables needed in the parameter $addition
\r
4092 * @param parserMethod
\r
4094 function convertMethod(&$element, $additions = array())
\r
4096 $fname = $element->getName();
\r
4097 $docblock = $this->prepareDocBlock($element);
\r
4098 $returntype = 'void';
\r
4099 if ($element->isConstructor) $returntype = $element->class;
\r
4100 if ($element->docblock->return)
\r
4102 $a = $element->docblock->return->Convert($this);
\r
4103 $returntype = $element->docblock->return->converted_returnType;
\r
4105 $params = $param_i = array();
\r
4106 if (count($element->docblock->params))
\r
4107 foreach($element->docblock->params as $param => $val)
\r
4109 $a = $val->Convert($this);
\r
4110 $params[] = $param_i[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
\r
4113 if ($element->docblock->hasaccess) {
\r
4114 $acc = $docblock['access'];
\r
4119 if ($this->hasSourceCode($element->getPath()))
\r
4120 $additions["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4121 $this->class_data->append('methods',array_merge(
\r
4122 array('sdesc' => $docblock['sdesc'],
\r
4123 'desc' => $docblock['desc'],
\r
4124 'static' => $docblock['static'],
\r
4125 'abstract' => $docblock['abstract'],
\r
4126 'tags' => $docblock['tags'],
\r
4127 'api_tags' => $docblock['api_tags'],
\r
4128 'see_tags' => $docblock['see_tags'],
\r
4129 'info_tags_sorted' => $docblock['info_tags_sorted'],
\r
4130 'info_tags' => $docblock['info_tags'],
\r
4131 'utags' => $docblock['utags'],
\r
4132 'constructor' => $element->isConstructor,
\r
4134 'function_name' => $fname,
\r
4135 'function_return' => $returntype,
\r
4136 'function_call' => $element->getFunctionCall(),
\r
4137 'ifunction_call' => $element->getIntricateFunctionCall($this, $param_i),
\r
4138 'descmethod' => $this->getFormattedDescMethods($element),
\r
4139 'method_overrides' => $this->getFormattedOverrides($element),
\r
4140 'method_implements' => $this->getFormattedMethodImplements($element),
\r
4141 'line_number' => $element->getLineNumber(),
\r
4142 'id' => $this->getId($element),
\r
4143 'params' => $params),
\r
4148 * Converts class variables for template output.
\r
4150 * This function must be called by a child converter with any extra
\r
4151 * template variables needed in the parameter $addition
\r
4152 * @param parserVar
\r
4154 function convertVar(&$element, $additions = array())
\r
4156 $docblock = $this->prepareDocBlock($element);
\r
4159 if ($element->docblock->hasaccess)
\r
4160 $acc = $element->docblock->tags['access'][0]->value;
\r
4164 if ($element->docblock->var)
\r
4166 $b = $element->docblock->var->converted_returnType;
\r
4168 if ($this->hasSourceCode($element->getPath()))
\r
4169 $additions["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4170 $this->class_data->append('vars',array_merge(
\r
4171 array('sdesc' => $docblock['sdesc'],
\r
4172 'desc' => $docblock['desc'],
\r
4173 'static' => $docblock['static'],
\r
4174 'abstract' => $docblock['abstract'],
\r
4175 'utags' => $docblock['utags'],
\r
4176 'tags' => $docblock['tags'],
\r
4177 'api_tags' => $docblock['api_tags'],
\r
4178 'info_tags' => $docblock['info_tags'],
\r
4179 'var_name' => $element->getName(),
\r
4180 'has_default' => strlen($element->getValue()),
\r
4181 'var_default' => $this->postProcess($element->getValue()),
\r
4184 'line_number' => $element->getLineNumber(),
\r
4185 'descvar' => $this->getFormattedDescVars($element),
\r
4186 'var_overrides' => $this->getFormattedOverrides($element),
\r
4187 'id' => $this->getId($element)),
\r
4192 * Converts class constants for template output.
\r
4194 * This function must be called by a child converter with any extra
\r
4195 * template variables needed in the parameter $addition
\r
4196 * @param parserConst
\r
4198 function convertConst(&$element, $additions = array())
\r
4200 $docblock = $this->prepareDocBlock($element);
\r
4202 if ($element->docblock->hasaccess)
\r
4203 $acc = $element->docblock->tags['access'][0]->value;
\r
4207 if ($this->hasSourceCode($element->getPath()))
\r
4208 $additions["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4209 $this->class_data->append('consts',array_merge(
\r
4210 array('sdesc' => $docblock['sdesc'],
\r
4211 'desc' => $docblock['desc'],
\r
4212 'access' => $docblock['access'],
\r
4213 'abstract' => $docblock['abstract'],
\r
4214 'utags' => $docblock['utags'],
\r
4215 'tags' => $docblock['tags'],
\r
4216 'api_tags' => $docblock['api_tags'],
\r
4217 'info_tags' => $docblock['info_tags'],
\r
4218 'const_name' => $element->getName(),
\r
4219 'const_value' => $this->postProcess($element->getValue()),
\r
4221 'line_number' => $element->getLineNumber(),
\r
4222 'id' => $this->getId($element)),
\r
4227 * Default Page Handler
\r
4229 * {@internal In addition to setting up the smarty template with {@link newSmarty()},
\r
4230 * this class uses {@link getSourceLocation()} and {@link getClassesOnPage()}
\r
4231 * to set template variables. Also used is {@link getPageName()}, to get
\r
4232 * a Converter-specific name for the page.}}
\r
4233 * @param parserPage
\r
4235 function convertPage(&$element)
\r
4237 $this->page_data = &$this->newSmarty(true);
\r
4238 $this->page = $this->getPageName($element->parent);
\r
4239 $this->path = $element->parent->getPath();
\r
4240 $this->curpage = &$element->parent;
\r
4241 $this->page_data->assign("source_location",$element->parent->getSourceLocation($this));
\r
4242 $this->page_data->assign("functions",array());
\r
4243 $this->page_data->assign("includes",array());
\r
4244 $this->page_data->assign("defines",array());
\r
4245 $this->page_data->assign("globals",array());
\r
4246 $this->page_data->assign("classes",$this->getClassesOnPage($element));
\r
4247 $this->page_data->assign("hasclasses",$element->hasClasses());
\r
4248 $this->page_data->assign("hasinterfaces",$element->hasInterfaces());
\r
4249 $this->page_data->assign("name", $element->parent->getFile());
\r
4250 if ($t = $element->getTutorial())
\r
4252 $this->page_data->assign("tutorial",$this->returnSee($t));
\r
4255 $this->page_data->assign("tutorial",false);
\r
4257 if ($element->docblock)
\r
4259 $docblock = $this->prepareDocBlock($element, false);
\r
4260 $this->page_data->assign("sdesc",$docblock['sdesc']);
\r
4261 $this->page_data->assign("desc",$docblock['desc']);
\r
4262 $this->page_data->assign("tags",$docblock['tags']);
\r
4263 $this->page_data->assign("api_tags",$docblock['api_tags']);
\r
4264 $this->page_data->assign("info_tags",$docblock['info_tags']);
\r
4265 $this->page_data->assign("utags",$docblock['utags']);
\r
4270 * Converts global variables for template output
\r
4272 * This function must be called by a child converter with any extra
\r
4273 * template variables needed in the parameter $addition
\r
4275 * In addition to using {@link prepareDocBlock()}, this method also
\r
4276 * uses utility functions {@link getGlobalValue(), getFormattedConflicts()}}}
\r
4277 * @param parserGlobal
\r
4278 * @uses postProcess() on global_value template value, makes it displayable
\r
4279 * @param array any additional template variables should be in this array
\r
4281 function convertGlobal(&$element, $addition = array())
\r
4283 $docblock = $this->prepareDocBlock($element);
\r
4284 $value = $this->getGlobalValue($element->getValue());
\r
4285 if ($this->hasSourceCode($element->getPath()))
\r
4286 $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4287 $this->page_data->append('globals',array_merge(
\r
4288 array('sdesc' => $docblock['sdesc'],
\r
4289 'desc' => $docblock['desc'],
\r
4290 'tags' => $docblock['tags'],
\r
4291 'api_tags' => $docblock['api_tags'],
\r
4292 'info_tags' => $docblock['info_tags'],
\r
4293 'utags' => $docblock['utags'],
\r
4294 'global_name' => $element->getName(),
\r
4295 'global_type' => $element->getDataType($this),
\r
4296 'global_value' => $value,
\r
4297 'line_number' => $element->getLineNumber(),
\r
4298 'global_conflicts' => $this->getFormattedConflicts($element,"global variables"),
\r
4299 'id' => $this->getId($element)),
\r
4304 * Converts defines for template output
\r
4306 * This function must be called by a child converter with any extra
\r
4307 * template variables needed in the parameter $addition
\r
4309 * In addition to using {@link prepareDocBlock()}, this method also
\r
4310 * uses utility functions {@link getGlobalValue(), getFormattedConflicts()}}}
\r
4311 * @param parserDefine
\r
4312 * @uses postProcess() on define_value template value, makes it displayable
\r
4313 * @param array any additional template variables should be in this array
\r
4315 function convertDefine(&$element, $addition = array())
\r
4317 $docblock = $this->prepareDocBlock($element);
\r
4318 if ($this->hasSourceCode($element->getPath()))
\r
4319 $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4320 $this->page_data->append('defines',array_merge(
\r
4321 array('sdesc' => $docblock['sdesc'],
\r
4322 'desc' => $docblock['desc'],
\r
4323 'tags' => $docblock['tags'],
\r
4324 'api_tags' => $docblock['api_tags'],
\r
4325 'info_tags' => $docblock['info_tags'],
\r
4326 'utags' => $docblock['utags'],
\r
4327 'define_name' => $element->getName(),
\r
4328 'line_number' => $element->getLineNumber(),
\r
4329 'define_value' => $this->postProcess($element->getValue()),
\r
4330 'define_conflicts' => $this->getFormattedConflicts($element,"defines"),
\r
4331 'id' => $this->getId($element)),
\r
4337 * Converts includes for template output
\r
4339 * This function must be called by a child converter with any extra
\r
4340 * template variables needed in the parameter $addition
\r
4341 * @see prepareDocBlock()
\r
4342 * @param parserInclude
\r
4344 function convertInclude(&$element, $addition = array())
\r
4346 $docblock = $this->prepareDocBlock($element);
\r
4347 $per = $this->getIncludeValue($element->getValue(), $element->getPath());
\r
4349 if ($this->hasSourceCode($element->getPath()))
\r
4350 $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4351 $this->page_data->append('includes',array_merge(
\r
4352 array('sdesc' => $docblock['sdesc'],
\r
4353 'desc' => $docblock['desc'],
\r
4354 'tags' => $docblock['tags'],
\r
4355 'api_tags' => $docblock['api_tags'],
\r
4356 'info_tags' => $docblock['info_tags'],
\r
4357 'utags' => $docblock['utags'],
\r
4358 'include_name' => $element->getName(),
\r
4359 'line_number' => $element->getLineNumber(),
\r
4360 'include_value' => $per),
\r
4365 * Converts function for template output
\r
4367 * This function must be called by a child converter with any extra
\r
4368 * template variables needed in the parameter $addition
\r
4369 * @see prepareDocBlock()
\r
4370 * @param parserFunction
\r
4372 function convertFunction(&$element, $addition = array())
\r
4374 $docblock = $this->prepareDocBlock($element);
\r
4375 $fname = $element->getName();
\r
4376 $params = $param_i = array();
\r
4377 if (count($element->docblock->params))
\r
4378 foreach($element->docblock->params as $param => $val)
\r
4380 $a = $val->Convert($this);
\r
4381 $params[] = $param_i[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
\r
4383 $returntype = 'void';
\r
4384 if ($element->docblock->return)
\r
4386 $a = $element->docblock->return->Convert($this);
\r
4387 $returntype = $element->docblock->return->converted_returnType;
\r
4390 if ($this->hasSourceCode($element->getPath()))
\r
4391 $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
\r
4392 $this->page_data->append('functions',array_merge(
\r
4393 array('sdesc' => $docblock['sdesc'],
\r
4394 'desc' => $docblock['desc'],
\r
4395 'tags' => $docblock['tags'],
\r
4396 'api_tags' => $docblock['api_tags'],
\r
4397 'info_tags' => $docblock['info_tags'],
\r
4398 'utags' => $docblock['utags'],
\r
4399 'function_name' => $fname,
\r
4400 'function_return' => $returntype,
\r
4401 'function_conflicts' => $this->getFormattedConflicts($element,"functions"),
\r
4402 'ifunction_call' => $element->getIntricateFunctionCall($this, $param_i),
\r
4403 'function_call' => $element->getFunctionCall(),
\r
4404 'line_number' => $element->getLineNumber(),
\r
4405 'id' => $this->getId($element),
\r
4406 'params' => $params),
\r
4412 * convert the element's DocBlock for output
\r
4414 * This function converts all tags and descriptions for output
\r
4415 * @param mixed any descendant of {@link parserElement}, or {@link parserData}
\r
4416 * @param array used to translate tagnames into other tags
\r
4417 * @param boolean set to false for pages and classes, the only elements allowed to specify @package
\r
4422 * array('sdesc' => DocBlock summary
\r
4423 * 'desc' => DocBlock detailed description
\r
4424 * 'tags' => array('keyword' => tagname, 'data' => tag description)
\r
4426 * 'api_tags' => array('keyword' => tagname, 'data' => tag description)
\r
4427 * known api documentation tags
\r
4428 * 'info_tags' => array('keyword' => tagname, 'data' => tag description)
\r
4429 * known informational tags
\r
4430 * [ 'utags' => array('keyword' => tagname, 'data' => tag description
\r
4432 * [ 'vartype' => type from @var/@return tag ]
\r
4433 * [ 'var_descrip' => description from @var/@return tag ]
\r
4437 function prepareDocBlock(&$element, $names = array(),$nopackage = true)
\r
4439 $tagses = $element->docblock->listTags();
\r
4440 $tags = $ret = $api_tags = $info_tags = array();
\r
4441 $api_tags_arr = array("abstract", "access", "deprecated", "example", "filesource",
\r
4442 "global", "internal", "name", "return", "see",
\r
4443 "property", "property-read", "property-write", "method",
\r
4444 "staticvar", "usedby", "uses", "var");
\r
4447 $tags[] = array('keyword' => 'package','data' => $element->docblock->package);
\r
4448 if (!empty($element->docblock->subpackage)) $tags[] = array('keyword' => 'subpackage','data' => $element->docblock->subpackage);
\r
4450 if ($element->docblock->var)
\r
4452 $a = $element->docblock->var->Convert($this);
\r
4453 $ret['vartype'] = $element->docblock->var->converted_returnType;
\r
4456 $tags[] = array('keyword' => 'var', 'data' => $a);
\r
4457 $ret["var_descrip"] = $a;
\r
4460 if ($element->docblock->return)
\r
4462 $a = $element->docblock->return->Convert($this);
\r
4463 $ret['vartype'] = $element->docblock->return->converted_returnType;
\r
4466 $tags[] = $api_tags[] = array('keyword' => 'return', 'data' => $a);
\r
4467 $ret["var_descrip"] = $a;
\r
4470 if ($element->docblock->funcglobals)
\r
4471 foreach($element->docblock->funcglobals as $global => $val)
\r
4473 if ($a = $this->getGlobalLink($global,$element->docblock->package))
\r
4477 $b = Converter::getLink($val[0]);
\r
4478 if (is_object($b) && phpDocumentor_get_class($b) == 'classlink')
\r
4480 $val[0] = $this->returnSee($b);
\r
4482 $tags[] = $api_tags[] = array('keyword' => 'global','data' => $val[0].' '.$global.': '.$val[1]->Convert($this));
\r
4484 if ($element->docblock->statics)
\r
4485 foreach($element->docblock->statics as $static => $val)
\r
4487 $a = $val->Convert($this);
\r
4488 $tags[] = $api_tags[] = array('keyword' => 'staticvar','data' => $val->converted_returnType.' '.$static.': '.$a);
\r
4490 $property_tags = array();
\r
4491 foreach ( $element->docblock->properties as $prop_name => $val )
\r
4493 $a = $val->Convert( $this );
\r
4494 if ( !empty( $a ) )
\r
4496 $tags[] = $api_tags[] = array( 'keyword' => $val->keyword ,
\r
4497 'data' => $val->converted_returnType . ' ' . $prop_name . ': ' . $a );
\r
4498 $prop['prop_name'] = $prop_name;
\r
4499 $prop['access'] = $val->keyword == 'property-read' ? 'read' :
\r
4500 ( $val->keyword == 'property-write' ? 'write' : 'read/write' );
\r
4501 $prop['prop_type'] = $val->converted_returnType;
\r
4502 $prop['sdesc'] = $a;
\r
4503 $property_tags[ $prop_name ] = $prop;
\r
4506 ksort( $property_tags, SORT_STRING );
\r
4507 $property_tags = array_values( $property_tags );
\r
4508 $info_tags_sorted = array();
\r
4509 $ret['static'] = false;
\r
4510 foreach($tagses as $tag)
\r
4512 if (isset($names[$tag->keyword])) $tag->keyword = $names[$tag->keyword];
\r
4513 if ($tag->keyword == 'static') {
\r
4514 $ret['static'] = true;
\r
4517 if ($tag->keyword)
\r
4518 $tags[] = array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
\r
4519 if (in_array($tag->keyword, $api_tags_arr)) {
\r
4520 $api_tags[] = array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
\r
4522 $info_tags[] = array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
\r
4523 @list( $className, $desc ) = explode( " ", $tag->Convert($this), 2 );
\r
4524 $info_tags_sorted[ $tag->keyword ][] = array( 'keyword' => $className, 'data' => $desc );
\r
4528 foreach($element->docblock->unknown_tags as $keyword => $tag)
\r
4530 foreach($tag as $t)
\r
4531 $utags[] = array('keyword' => $keyword, 'data' => $t->Convert($this));
\r
4533 $ret['abstract'] = false;
\r
4534 $ret['access'] = 'public';
\r
4535 $see_tags = array();
\r
4536 foreach($tags as $tag)
\r
4538 if ($tag['keyword'] == 'access') {
\r
4539 $ret['access'] = $tag['data'];
\r
4541 if ($tag['keyword'] == 'abstract') {
\r
4542 $ret['abstract'] = true;
\r
4544 if ($tag['keyword'] == 'see' || $tag['keyword'] == 'uses' ||
\r
4545 $tag['keyword'] == 'usedby') {
\r
4546 $see_tags[] = $tag['data'];
\r
4549 $ret['sdesc'] = $element->docblock->getSDesc($this);
\r
4550 $ret['desc'] = $element->docblock->getDesc($this);
\r
4551 $ret['tags'] = $tags;
\r
4552 $ret['see_tags'] = $see_tags;
\r
4553 $ret['info_tags_sorted'] = $info_tags_sorted;
\r
4554 $ret['api_tags'] = $api_tags;
\r
4555 $ret['info_tags'] = $info_tags;
\r
4556 $ret['utags'] = $utags;
\r
4557 $ret['property_tags'] = $property_tags;
\r
4562 * gets a list of all classes declared on a procedural page represented by
\r
4563 * $element, a {@link parserData} class
\r
4564 * @param parserData &$element
\r
4565 * @return array links to each classes documentation
\r
4569 * array('name' => class name,
\r
4570 * 'sdesc' => summary of the class
\r
4571 * 'link' => link to the class's documentation)
\r
4574 function getClassesOnPage(&$element)
\r
4576 global $_phpDocumentor_setting;
\r
4577 $a = $element->getClasses($this);
\r
4578 $classes = array();
\r
4579 foreach($a as $package => $clas)
\r
4581 if (!empty($_phpDocumentor_setting['packageoutput']))
\r
4583 $packages = explode(',',$_phpDocumentor_setting['packageoutput']);
\r
4584 if (!in_array($package, $packages)) continue;
\r
4586 for($i=0; $i<count($clas); $i++)
\r
4588 if ($this->parseprivate || ! ($clas[$i]->docblock && $clas[$i]->docblock->hasaccess && $clas[$i]->docblock->tags['access'][0]->value == 'private'))
\r
4592 $sdesc = $clas[$i]->docblock->getSDesc($this);
\r
4593 if ($clas[$i]->docblock->hasaccess)
\r
4594 $r['access'] = $clas[$i]->docblock->tags['access'][0]->value;
\r
4596 $r['access'] = 'public';
\r
4597 if (isset ($clas[$i]->docblock->tags['abstract']))
\r
4598 $r['abstract'] = TRUE;
\r
4600 $r['abstract'] = FALSE;
\r
4601 $r['name'] = $clas[$i]->getName();
\r
4602 $r['sdesc'] = $sdesc;
\r
4603 $r['link'] = $this->getClassLink($clas[$i]->getName(),$package,$clas[$i]->getPath());
\r
4612 * returns an array containing the class inheritance tree from the root
\r
4613 * object to the class.
\r
4615 * This method must be overridden, or phpDocumentor will halt with a fatal
\r
4617 * @return string Converter-specific class tree for an individual class
\r
4618 * @param parserClass class variable
\r
4622 function generateFormattedClassTree($class)
\r
4624 addErrorDie(PDERROR_CONVERTER_OVR_GFCT,phpDocumentor_get_class($this));
\r
4628 * returns an array containing the class inheritance tree from the root
\r
4629 * object to the class.
\r
4631 * This method must be overridden, or phpDocumentor will halt with a fatal
\r
4633 * @return string Converter-specific class tree for an individual class
\r
4634 * @param parserClass class variable
\r
4638 function getFormattedImplements($el)
\r
4641 foreach ($el->getImplements() as $interface)
\r
4643 $link = $this->getLink($interface);
\r
4644 if ($link && is_object($link)) {
\r
4645 $ret[] = $this->returnSee($link);
\r
4647 if (class_exists('ReflectionClass')) {
\r
4648 if (interface_exists($interface)) {
\r
4649 $inter = new ReflectionClass($interface);
\r
4650 if ($inter->isInternal()) {
\r
4651 $ret[] = $interface . ' (internal interface)';
\r
4653 $ret[] = $interface;
\r
4657 $ret[] = $interface;
\r
4665 * @param mixed {@link parserClass, parserFunction, parserDefine} or
\r
4666 * {@link parserGlobal}
\r
4667 * @param string type to display. either 'class','function','define'
\r
4668 * or 'global variable'
\r
4669 * @return array links to conflicting elements, or empty array
\r
4670 * @uses parserClass::getConflicts()
\r
4671 * @uses parserFunction::getConflicts()
\r
4672 * @uses parserDefine::getConflicts()
\r
4673 * @uses parserGlobal::getConflicts()
\r
4675 function getFormattedConflicts(&$element,$type)
\r
4677 $conflicts = $element->getConflicts($this);
\r
4679 if (!$conflicts) return false;
\r
4680 foreach($conflicts as $package => $class)
\r
4682 $r[] = $class->getLink($this,$class->docblock->package);
\r
4684 if (!empty($r)) $r = array('conflicttype' => $type, 'conflicts' => $r);
\r
4689 * Get a list of methods in child classes that override this method
\r
4690 * @return array empty array or array(array('link'=>link to method,
\r
4691 * 'sdesc'=>short description of the method),...)
\r
4692 * @uses parserMethod::getOverridingMethods()
\r
4693 * @param parserMethod
\r
4695 function getFormattedDescMethods(&$element)
\r
4697 $meths = $element->getOverridingMethods($this);
\r
4699 for($i=0; $i<count($meths); $i++)
\r
4702 $ms['link'] = $meths[$i]->getLink($this);
\r
4703 $ms['sdesc'] = $meths[$i]->docblock->getSDesc($this);
\r
4710 * Get a list of vars in child classes that override this var
\r
4711 * @return array empty array or array('link'=>link to var,
\r
4712 * 'sdesc'=>short description of the method
\r
4713 * @uses parserVar::getOverridingVars()
\r
4714 * @param parserVar
\r
4716 function getFormattedDescVars(&$element)
\r
4718 $vars = $element->getOverridingVars($this);
\r
4720 for($i=0; $i<count($vars); $i++)
\r
4723 $vs['link'] = $vars[$i]->getLink($this);
\r
4724 $vs['sdesc'] = $vars[$i]->docblock->getSDesc($this);
\r
4731 * Get the method this method overrides, if any
\r
4732 * @return array|false array('link'=>link to overridden method,
\r
4733 * 'sdesc'=>short description
\r
4734 * @see parserMethod::getOverrides()
\r
4735 * @param parserMethod
\r
4737 function getFormattedOverrides(&$element)
\r
4739 $ovr = $element->getOverrides($this);
\r
4740 if (!$ovr) return false;
\r
4741 $sdesc = $ovr->docblock->getSDesc($this);
\r
4742 $name = method_exists($ovr, 'getFunctionCall') ? $ovr->getFunctionCall() : $ovr->getName();
\r
4743 $link = ($link = $ovr->getLink($this)) ? $link : $ovr->getClass() . '::' . $name;
\r
4744 return array('link' => $link,'sdesc' => $sdesc);
\r
4748 * Get the method this method(s) implemented from an interface, if any
\r
4749 * @return array|false array('link'=>link to implemented method,
\r
4750 * 'sdesc'=>short description
\r
4751 * @uses parserMethod::getImplements()
\r
4752 * @param parserMethod
\r
4754 function getFormattedMethodImplements(&$element)
\r
4756 $ovr = $element->getImplements($this);
\r
4757 if (!$ovr) return false;
\r
4759 foreach ($ovr as $impl) {
\r
4760 $sdesc = $impl->docblock->getSDesc($this);
\r
4761 $name = $impl->getName();
\r
4762 $link = ($link = $impl->getLink($this)) ? $link : $impl->getClass() . '::' . $name;
\r
4763 $ret[] = array('link' => $link,'sdesc' => $sdesc);
\r
4769 * returns a list of child classes
\r
4771 * @param parserClass class variable
\r
4772 * @uses parserClass::getChildClassList()
\r
4775 function generateChildClassList($class)
\r
4777 $kids = $class->getChildClassList($this);
\r
4781 for($i=0; $i<count($kids); $i++)
\r
4783 $lt['link'] = $kids[$i]->getLink($this);
\r
4784 $lt['sdesc'] = $kids[$i]->docblock->getSDesc($this);
\r
4786 if ($kids[$i]->docblock->hasaccess)
\r
4787 $lt['access'] = $kids[$i]->docblock->tags['access'][0]->value;
\r
4789 $lt['access'] = 'public';
\r
4791 $lt['abstract'] = isset ($kids[$i]->docblock->tags['abstract'][0]);
\r
4795 } else return false;
\r
4800 * Return template-enabled list of inherited variables
\r
4802 * uses parserVar helper function getInheritedVars and generates a
\r
4803 * template-enabled list using getClassLink()
\r
4804 * @param parserVar $child class var
\r
4805 * @see getClassLink(), parserVar::getInheritedVars()
\r
4806 * @return array Format:
\r
4809 * array('parent_class' => link to parent class's documentation,
\r
4812 * array('name' => inherited variable name,
\r
4813 * 'link' => link to inherited variable's documentation,
\r
4814 * 'default' => default value of inherited variable,
\r
4815 * 'sdesc' => summary of inherited variable),
\r
4821 function getFormattedInheritedVars($child)
\r
4823 $package = $child->docblock->package;
\r
4824 $subpackage = $child->docblock->subpackage;
\r
4825 $ivars = $child->getInheritedVars($this);
\r
4826 $results = array();
\r
4827 if (!count($ivars)) return $results;
\r
4828 foreach($ivars as $parent => $vars)
\r
4830 $file = $vars['file'];
\r
4831 $vars = $vars['vars'];
\r
4832 $par = $this->classes->getClass($parent,$file);
\r
4834 $package = $par->docblock->package;
\r
4836 usort($vars,array($this,"sortVar"));
\r
4837 $result['parent_class'] = $this->getClassLink($parent, $package);
\r
4838 if (!$result['parent_class']) {
\r
4839 $result['parent_class'] = $parent . ' (Internal Class)';
\r
4841 foreach($vars as $var)
\r
4845 if ($var->docblock->hasaccess) {
\r
4846 $info['access'] = $var->docblock->tags['access'][0]->value;
\r
4848 $info['access'] = 'public';
\r
4851 $info['abstract'] = isset ($var->docblock->tags['abstract'][0]);
\r
4853 $info['name'] = $var->getName();
\r
4854 $info['link'] = $var->getLink($this);
\r
4855 if (!$info['link']) {
\r
4856 $info['link'] = $info['name'];
\r
4858 $info['default'] = $this->postProcess($var->getValue());
\r
4859 if ($var->docblock)
\r
4860 $info['sdesc'] = $var->docblock->getSDesc($this);
\r
4861 $result["ivars"][] = $info;
\r
4863 $results[] = $result;
\r
4864 $result = array();
\r
4870 * Return template-enabled list of inherited methods
\r
4872 * uses parserMethod helper function getInheritedMethods and generates a
\r
4873 * template-enabled list using getClassLink()
\r
4874 * @param parserMethod $child class method
\r
4875 * @see getClassLink(), parserMethod::getInheritedMethods()
\r
4876 * @return array Format:
\r
4879 * array('parent_class' => link to parent class's documentation,
\r
4882 * array('name' => inherited variable name,
\r
4883 * 'link' => link to inherited variable's documentation,
\r
4884 * 'function_call' => {@link parserMethod::getIntricateFunctionCall()}
\r
4886 * 'sdesc' => summary of inherited variable),
\r
4892 function getFormattedInheritedMethods($child)
\r
4894 $package = $child->docblock->package;
\r
4895 $subpackage = $child->docblock->subpackage;
\r
4896 $imethods = $child->getInheritedMethods($this);
\r
4897 $results = array();
\r
4898 if (!count($imethods)) return $results;
\r
4899 foreach($imethods as $parent => $methods)
\r
4901 $file = $methods['file'];
\r
4902 $methods = $methods['methods'];
\r
4903 $par = $this->classes->getClass($parent,$file);
\r
4905 $package = $par->docblock->package;
\r
4907 usort($methods,array($this,"sortMethod"));
\r
4908 $result['parent_class'] = $this->getClassLink($parent,$package);
\r
4909 if (!$result['parent_class']) {
\r
4910 $result['parent_class'] = $parent . ' (Internal Class)';
\r
4912 foreach($methods as $method)
\r
4916 if ($method->docblock->hasaccess) {
\r
4917 $info['access'] = $method->docblock->tags['access'][0]->value;
\r
4919 $info['access'] = 'public';
\r
4921 $info['abstract'] = isset ($method->docblock->tags['abstract'][0]);
\r
4923 if ($method->isConstructor) $info['constructor'] = 1;
\r
4924 $returntype = 'void';
\r
4925 if ($method->isConstructor) {
\r
4926 $returntype = $method->getClass();
\r
4928 if ($method->docblock->return) {
\r
4929 $a = $method->docblock->return->Convert($this);
\r
4930 $returntype = $method->docblock->return->converted_returnType;
\r
4932 $info['function_return'] = $returntype;
\r
4933 $info['static'] = isset ($method->docblock->tags['static'][0]);
\r
4934 $info['link'] = $method->getLink($this);
\r
4935 if (!$info['link']) {
\r
4936 $info['link'] = $method->getFunctionCall();
\r
4938 $info['name'] = $method->getName();
\r
4939 if ($method->docblock)
\r
4940 $info['sdesc'] = $method->docblock->getSDesc($this);
\r
4941 $params = array();
\r
4942 if (count($method->docblock->params))
\r
4943 foreach($method->docblock->params as $param => $val)
\r
4945 $a = $val->Convert($this);
\r
4946 $params[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
\r
4949 $info['function_call'] = $method->getIntricateFunctionCall($this,$params);
\r
4950 $result["imethods"][] = $info;
\r
4952 $results[] = $result;
\r
4953 $result = array();
\r
4959 * Return template-enabled list of inherited class constants
\r
4961 * uses parserConst helper function getInheritedConsts and generates a
\r
4962 * template-enabled list using getClassLink()
\r
4963 * @param parserConst $child class constant
\r
4964 * @see getClassLink(), parserMethod::getInheritedConsts()
\r
4965 * @return array Format:
\r
4968 * array('parent_class' => link to parent class's documentation,
\r
4971 * array('name' => inherited constant name,
\r
4972 * 'link' => link to inherited constant's documentation,
\r
4973 * 'value' => constant value,
\r
4974 * 'sdesc' => summary of inherited constant),
\r
4980 function getFormattedInheritedConsts($child)
\r
4982 $package = $child->docblock->package;
\r
4983 $subpackage = $child->docblock->subpackage;
\r
4984 $ivars = $child->getInheritedConsts($this);
\r
4985 $results = array();
\r
4986 if (!count($ivars)) return $results;
\r
4987 foreach($ivars as $parent => $vars)
\r
4989 $file = $vars['file'];
\r
4990 $vars = $vars['consts'];
\r
4991 $par = $this->classes->getClass($parent,$file);
\r
4993 $package = $par->docblock->package;
\r
4995 usort($vars,array($this,"sortVar"));
\r
4996 $result['parent_class'] = $this->getClassLink($parent,$package);
\r
4997 if (!$result['parent_class']) {
\r
4998 $result['parent_class'] = $parent . ' (Internal Class)';
\r
5000 foreach($vars as $var)
\r
5004 if ($var->docblock->hasaccess) {
\r
5005 $info['access'] = $var->docblock->tags['access'][0]->value;
\r
5007 $info['access'] = 'public';
\r
5009 $info['name'] = $var->getName();
\r
5010 $info['link'] = $var->getLink($this);
\r
5011 if (!$info['link']) {
\r
5012 $info['link'] = $info['name'] . ' = ' . $var->getValue();
\r
5014 $info['value'] = $this->postProcess($var->getValue());
\r
5015 if ($var->docblock)
\r
5016 $info['sdesc'] = $var->docblock->getSDesc($this);
\r
5017 $result["iconsts"][] = $info;
\r
5019 $results[] = $result;
\r
5020 $result = array();
\r
5026 * Return a Smarty template object to operate with
\r
5028 * This returns a Smarty template with pre-initialized variables for use.
\r
5029 * If the method "SmartyInit()" exists, it is called.
\r
5032 function &newSmarty()
\r
5034 $templ = new Smarty;
\r
5035 $templ->use_sub_dirs = false;
\r
5036 $templ->template_dir = realpath($this->smarty_dir . PATH_DELIMITER . 'templates');
\r
5037 $templatename = get_class($this) . $this->templateName;
\r
5038 if (!file_exists($this->targetDir . DIRECTORY_SEPARATOR . md5($templatename))) {
\r
5039 // we'll delete this on finishing conversion
\r
5040 $this->_compiledDir[$this->targetDir . DIRECTORY_SEPARATOR . md5($templatename)] = 1;
\r
5041 mkdir($this->targetDir . DIRECTORY_SEPARATOR . md5($templatename),0775);
\r
5043 $templ->compile_dir = realpath($this->targetDir . PATH_DELIMITER . md5($templatename));
\r
5044 $templ->config_dir = realpath($this->smarty_dir . PATH_DELIMITER . 'configs');
\r
5045 $templ->assign("date",date("r",time()));
\r
5046 $templ->assign("maintitle",$this->title);
\r
5047 $templ->assign("package",$this->package);
\r
5048 $templ->assign("phpdocversion",PHPDOCUMENTOR_VER);
\r
5049 $templ->assign("phpdocwebsite",PHPDOCUMENTOR_WEBSITE);
\r
5050 $templ->assign("subpackage",$this->subpackage);
\r
5051 if (method_exists($this,'SmartyInit')) return $this->SmartyInit($templ);
\r
5056 * Finish up parsing/cleanup directories
\r
5058 function cleanup()
\r
5060 foreach ($this->_compiledDir as $dir => $one) {
\r
5061 $this->_rmdir($dir);
\r
5066 * Completely remove a directory and its contents
\r
5068 * @param string $directory
\r
5070 function _rmdir($directory)
\r
5072 $handle = @opendir($directory);
\r
5074 while (false !== ($file = readdir($handle))) {
\r
5075 if ($file == '.' || $file == '..') {
\r
5078 if (is_dir($directory . DIRECTORY_SEPARATOR . $file)) {
\r
5079 $this->_rmdir($directory . DIRECTORY_SEPARATOR . $file);
\r
5081 @unlink($directory . DIRECTORY_SEPARATOR . $file);
\r
5083 closedir($handle);
\r
5084 @rmdir($directory);
\r
5089 * do all necessary output
\r
5093 function Output($title)
\r
5095 phpDocumentor_out("WARNING: Generic Converter::Output was used, no output will be generated");
\r
5099 * Set the template directory with a different template base directory
\r
5100 * @tutorial phpDocumentor.howto.pkg#using.command-line.templatebase
\r
5101 * @param string template base directory
\r
5102 * @param string template name
\r
5104 function setTemplateBase($base, $dir)
\r
5106 // remove trailing /'s from the base path, if any
\r
5107 $base = str_replace('\\','/',$base);
\r
5108 while ($base{strlen($base) - 1} == '/') $base = substr($base,0,strlen($base) - 1);
\r
5109 $this->templateName = substr($dir,0,strlen($dir) - 1);
\r
5110 $this->templateDir = $base . "/Converters/" . $this->outputformat . "/" . $this->name . "/templates/" . $dir;
\r
5111 if (!is_dir($this->templateDir))
\r
5113 addErrorDie(PDERROR_TEMPLATEDIR_DOESNT_EXIST, $this->templateDir);
\r
5116 $this->smarty_dir = $this->templateDir;
\r
5117 if (file_exists($this->templateDir . PATH_DELIMITER . 'options.ini'))
\r
5119 // retrieve template options, allow array creation
\r
5120 $this->template_options = phpDocumentor_parse_ini_file($this->templateDir . PATH_DELIMITER . 'options.ini',true);
\r
5125 * sets the template directory based on the {@link $outputformat} and {@link $name}
\r
5126 * Also sets {@link $templateName} to the $dir parameter
\r
5127 * @param string subdirectory
\r
5129 function setTemplateDir($dir)
\r
5131 if ('@DATA-DIR@' != '@'.'DATA-DIR@') {
\r
5132 $templateBase = str_replace('\\', '/', '@DATA-DIR@/PhpDocumentor/phpDocumentor');
\r
5134 $templateBase = str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) . '/phpDocumentor';
\r
5136 $this->setTemplateBase($templateBase, $dir);
\r
5140 * Get the absolute path to the converter's base directory
\r
5143 function getConverterDir()
\r
5145 if ('@DATA-DIR@' != '@' . 'DATA-DIR@') {
\r
5146 return str_replace('\\', '/', "@DATA-DIR@/PhpDocumentor/phpDocumentor/Converters/") . $this->outputformat . "/" . $this->name;
\r
5148 return str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) ."/phpDocumentor/Converters/" . $this->outputformat . "/" . $this->name;
\r
5153 * Parse a global variable's default value for class initialization.
\r
5155 * If a global variable's default value is "new class" as in:
\r
5157 * $globalvar = new Parser
\r
5159 * This method will document it not as "new Parser" but instead as
\r
5160 * "new {@link Parser}". For examples, see {@link phpdoc.inc}.
\r
5161 * Many global variables are classes, and phpDocumentor links to their
\r
5163 * @return string default global variable value with link to class if
\r
5164 * it's "new Class"
\r
5165 * @param string default value of a global variable.
\r
5167 function getGlobalValue($value)
\r
5169 if (strpos($value,'new') === 0)
\r
5171 preg_match('/new([^(]*)((?:.|\r|\n)*)/',$value,$newval);
\r
5172 if (isset($newval[1]))
\r
5174 $a = Converter::getLink(trim($newval[1]));
\r
5175 if (!isset($newval[2])) $newval[2] = '';
\r
5176 if ($a && phpDocumentor_get_class($a) == 'classlink') $value = 'new '.$this->returnSee($a) .
\r
5177 $this->postProcess($newval[2]);
\r
5181 return $this->postProcess($value);
\r
5185 * Parse an include's file to see if it is a file documented in this project
\r
5187 * Although not very smart yet, this method will try to look for the
\r
5188 * included file file.ext:
\r
5191 * include ("file.ext");
\r
5194 * If it finds it, it will return a link to the file's documentation. As of
\r
5195 * 1.2.0rc1, phpDocumentor is smarty enough to find these cases:
\r
5197 * <li>absolute path to file</li>
\r
5198 * <li>./file.ext or ../file.ext</li>
\r
5199 * <li>relpath/to/file.ext if relpath is a subdirectory of the base parse
\r
5202 * For examples, see {@link Setup.inc.php} includes.
\r
5203 * Every include auto-links to the documentation for the file that is included
\r
5204 * @return string included file with link to docs for file, if found
\r
5205 * @param string file included by include statement.
\r
5206 * @param string path of file that has the include statement
\r
5208 function getIncludeValue($value, $ipath)
\r
5210 preg_match('/"([^"\']*\.[^"\']*)"/',$value,$match);
\r
5211 if (!isset($match[1]))
\r
5212 preg_match('/\'([^"\']*\.[^"\']*)\'/',$value,$match);
\r
5213 if (isset($match[1]))
\r
5215 $fancy_per = $this->proceduralpages->pathMatchesParsedFile($match[1],$ipath);
\r
5218 $link = $this->addLink($fancy_per);
\r
5219 if (is_object($link) && phpDocumentor_get_class($link) == 'pagelink' &&
\r
5220 isset($this->all_packages[$link->package]))
\r
5222 $value = $this->returnSee($link,$value);
\r
5226 $per = Converter::getLink($match[1]);
\r
5227 if (is_object($per) && phpDocumentor_get_class($per) == 'pagelink')
\r
5228 $value = $this->returnSee($per);
\r
5235 * Recursively creates all subdirectories that don't exist in the $dir path
\r
5236 * @param string $dir
\r
5238 function createParentDir($dir)
\r
5240 if (empty($dir)) return;
\r
5241 $tmp = explode(SMART_PATH_DELIMITER,$dir);
\r
5243 $parent = implode(SMART_PATH_DELIMITER,$tmp);
\r
5244 if ($parent != '' && !file_exists($parent))
\r
5246 $test = @mkdir($parent,0775);
\r
5249 $this->createParentDir($parent);
\r
5250 $test = @mkdir($parent,0775);
\r
5251 phpDocumentor_out("Creating Parent Directory $parent\n");
\r
5254 phpDocumentor_out("Creating Parent Directory $parent\n");
\r
5260 * Sets the output directory for generated documentation
\r
5262 * As of 1.3.0RC6, this also sets the compiled templates directory inside
\r
5263 * the target directory
\r
5264 * @param string $dir the output directory
\r
5266 function setTargetDir($dir)
\r
5268 if (strlen($dir) > 0)
\r
5270 $this->targetDir = $dir;
\r
5271 // if directory does exist create it, this should have more error checking in the future
\r
5272 if (!file_exists($dir))
\r
5274 $tmp = str_replace(array("/","\\"),SMART_PATH_DELIMITER,$dir);
\r
5275 if (substr($tmp,-1) == SMART_PATH_DELIMITER)
\r
5277 $tmp = substr($tmp,0,(strlen($tmp)-1));
\r
5279 $this->createParentDir($tmp);
\r
5280 phpDocumentor_out("Creating Directory $dir\n");
\r
5282 } elseif (!is_dir($dir))
\r
5284 echo "Output path: '$dir' is not a directory\n";
\r
5288 echo "a target directory must be specified\n try phpdoc -h\n";
\r
5294 * Writes a file to target dir
\r
5297 * @param boolean true if the data is binary and not text
\r
5299 function writeFile($file,$data,$binary = false)
\r
5301 if (!file_exists($this->targetDir))
\r
5303 mkdir($this->targetDir,0775);
\r
5306 if ($binary) $string = 'binary file ';
\r
5307 phpDocumentor_out(" Writing $string".$this->targetDir . PATH_DELIMITER . $file . "\n");
\r
5310 if ($binary) $write = 'wb';
\r
5311 $fp = fopen($this->targetDir . PATH_DELIMITER . $file,$write);
\r
5312 set_file_buffer( $fp, 0 );
\r
5313 fwrite($fp,$data,strlen($data));
\r
5318 * Copies a file from the template directory to the target directory
\r
5319 * thanks to Robert Hoffmann for this fix
\r
5322 function copyFile($file, $subdir = '')
\r
5324 if (!file_exists($this->targetDir))
\r
5326 mkdir($this->targetDir,0775);
\r
5328 copy($this->templateDir . $subdir . PATH_DELIMITER . $file, $this->targetDir . PATH_DELIMITER . $file);
\r
5332 * Return parserStringWithInlineTags::Convert() cache state
\r
5333 * @see parserStringWithInlineTags::Convert()
\r
5336 function getState()
\r
5342 * Compare parserStringWithInlineTags::Convert() cache state to $state
\r
5344 * @see parserStringWithInlineTags::Convert()
\r
5347 function checkState($state)
\r
5356 * @see Converter::getSortedClassTreeFromClass()
\r
5358 function rootcmp($a, $b)
\r
5360 return strnatcasecmp($a['class'],$b['class']);
\r
5365 * @global string used to make the first tutorials converted the default package tutorials
\r
5367 function tutorialcmp($a, $b)
\r
5369 global $phpDocumentor_DefaultPackageName;
\r
5370 if ($a == $phpDocumentor_DefaultPackageName) return -1;
\r
5371 if ($b == $phpDocumentor_DefaultPackageName) return 1;
\r
5372 return strnatcasecmp($a, $b);
\r
5376 * smart htmlentities, doesn't entity the allowed tags list
\r
5377 * Since version 1.1, this function uses htmlspecialchars instead of
\r
5378 * htmlentities, for international support
\r
5379 * This function has been replaced by functionality in {@link ParserDescCleanup.inc}
\r
5380 * @param string $s
\r
5381 * @return string browser-displayable page
\r
5382 * @deprecated As of v1.2, No longer needed, as valid tags are parsed out of the source,
\r
5383 * and everything else is {@link Converter::postProcess()} handled
\r
5385 function adv_htmlentities($s)
\r
5388 global $phpDocumentor___html,$_phpDocumentor_html_allowed;
\r
5389 $result = htmlspecialchars($s);
\r
5390 $entities = array_flip(get_html_translation_table(HTML_SPECIALCHARS));
\r
5391 $result = strtr($result,$phpDocumentor___html);
\r
5392 $matches = array();
\r
5393 preg_match_all('/(<img.*>)/U',$result,$matches);
\r
5394 for($i=0;$i<count($matches[1]);$i++)
\r
5396 $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
\r
5398 preg_match_all('/(<font.*>)/U',$result,$matches);
\r
5399 for($i=0;$i<count($matches[1]);$i++)
\r
5401 $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
\r
5403 preg_match_all('/(<ol.*>)/U',$result,$matches);
\r
5404 for($i=0;$i<count($matches[1]);$i++)
\r
5406 $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
\r
5408 preg_match_all('/(<ul.*>)/U',$result,$matches);
\r
5409 for($i=0;$i<count($matches[1]);$i++)
\r
5411 $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
\r
5413 preg_match_all('/(<li.*>)/U',$result,$matches);
\r
5414 for($i=0;$i<count($matches[1]);$i++)
\r
5416 $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
\r
5418 preg_match_all('/(<a .*>)/U',$result,$matches);
\r
5419 for($i=0;$i<count($matches[1]);$i++)
\r
5421 $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
\r
5427 * Used solely for setting up the @uses list
\r
5431 class __dummyConverter extends Converter
\r
5433 function setTemplateDir(){}
\r
5434 function setTargetDir(){}
\r
5435 function getPageName(&$element)
\r
5437 if (phpDocumentor_get_class($element) == 'parserpage') return '_'.$element->getName();
\r
5438 return '_'.$element->parent->getName();
\r