Source for file Converter.inc

Documentation is available at Converter.inc

  1. <?php
  2. /**
  3.  * Base class for all Converters
  4.  *
  5.  * phpDocumentor :: automatic documentation generator
  6.  * 
  7.  * PHP versions 4 and 5
  8.  *
  9.  * Copyright (c) 2001-2006 Gregory Beaver
  10.  * 
  11.  * LICENSE:
  12.  * 
  13.  * This library is free software; you can redistribute it
  14.  * and/or modify it under the terms of the GNU Lesser General
  15.  * Public License as published by the Free Software Foundation;
  16.  * either version 2.1 of the License, or (at your option) any
  17.  * later version.
  18.  * 
  19.  * This library is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22.  * Lesser General Public License for more details.
  23.  * 
  24.  * You should have received a copy of the GNU Lesser General Public
  25.  * License along with this library; if not, write to the Free Software
  26.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27.  *
  28.  * @package    Converters
  29.  * @author     Greg Beaver <[email protected]>
  30.  * @copyright  2001-2006 Gregory Beaver
  31.  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
  32.  * @version    CVS: $Id: Converter.inc 291278 2009-11-24 17:43:20Z ashnazg $
  33.  * @filesource
  34.  * @link       http://www.phpdoc.org
  35.  * @link       http://pear.php.net/PhpDocumentor
  36.  * @see        parserDocBlock, parserInclude, parserPage, parserClass
  37.  * @see        parserDefine, parserFunction, parserMethod, parserVar
  38.  * @since      1.0rc1
  39.  */
  40. /**
  41.  * Smarty template files
  42.  */
  43. include_once("phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php");
  44. /**
  45.  * Base class for all output converters.
  46.  *
  47.  * The Converter marks the final stage in phpDocumentor.  phpDocumentor works
  48.  * in this order:
  49.  *
  50.  * <pre>Parsing => Intermediate Parsing organization => Conversion to output</pre>
  51.  *
  52.  * A Converter takes output from the {@link phpDocumentor_IntermediateParser} and
  53.  * converts it to output.  With version 1.2, phpDocumentor includes a variety
  54.  * of output converters:
  55.  * <ul>
  56.  *  <li>{@link HTMLframesConverter}</li>
  57.  *  <li>{@link HTMLSmartyConverter}</li>
  58.  *  <li>{@link PDFdefaultConverter}</li>
  59.  *  <li>{@link CHMdefaultConverter}</li>
  60.  *  <li>{@link CSVdia2codeConverter}</li>
  61.  *  <li>{@link XMLDocBookConverter}</li>
  62.  * </ul>
  63.  * {@internal 
  64.  * The converter takes output directly from {@link phpDocumentor_IntermediateParser}
  65.  * and using {@link walk()} or {@link walk_everything} (depending on the value of
  66.  * {@link $sort_absolutely_everything}) it "walks" over an array of phpDocumentor elements.}}}
  67.  *
  68.  * @package Converters
  69.  * @abstract
  70.  * @author Greg Beaver <[email protected]>
  71.  * @since 1.0rc1
  72.  * @version $Id: Converter.inc 291278 2009-11-24 17:43:20Z ashnazg $
  73.  */
  74. class Converter
  75. {
  76.     /**
  77.      * This converter knows about the new root tree processing
  78.      * In order to fix PEAR Bug #6389
  79.      * @var boolean 
  80.      */
  81.     var $processSpecialRoots = false;
  82.     /**
  83.      * output format of this converter
  84.      *
  85.      * in Child converters, this will match the first part of the -o command-line
  86.      * as in -o HTML:frames:default "HTML"
  87.      * @tutorial phpDocumentor.howto.pkg#using.command-line.output
  88.      * @var string 
  89.      */
  90.     var $outputformat = 'Generic';
  91.     /**
  92.      * package name currently being converted
  93.      * @var string 
  94.      */
  95.     var $package = 'default';
  96.     /**
  97.      * subpackage name currently being converted
  98.      * @var string 
  99.      */
  100.     var $subpackage = '';
  101.     /**
  102.      * set to a classname if currently parsing a class, false if not
  103.      * @var string|false
  104.      */
  105.     var $class = false;
  106.     /**#@+
  107.      * @access private
  108.      */
  109.     /**
  110.      * the workhorse of linking.
  111.      *
  112.      * This array is an array of link objects of format:
  113.      * [package][subpackage][eltype][elname] = descendant of {@link abstractLink}
  114.      * eltype can be page|function|define|class|method|var
  115.      * if eltype is method or var, the array format is:
  116.      * [package][subpackage][eltype][class][elname]
  117.      * @var array 
  118.      * @see functionLink, pageLink, classLink, defineLink, methodLink, varLink, globalLink
  119.      */
  120.     var $links array();
  121.  
  122.     /**
  123.      * the workhorse of linking, with allowance for support of multiple
  124.      * elements in different files.
  125.      *
  126.      * This array is an array of link objects of format:
  127.      * [package][subpackage][eltype][file][elname] = descendant of {@link abstractLink}
  128.      * eltype can be function|define|class|method|var
  129.      * if eltype is method or var, the array format is:
  130.      * [package][subpackage][eltype][file][class][elname]
  131.      * @var array 
  132.      * @see functionLink, pageLink, classLink, defineLink, methodLink, varLink, globalLink
  133.     */
  134.     var $linkswithfile array();
  135.     /**#@-*/
  136.     /**
  137.      * set to value of -po commandline
  138.      * @tutorial phpDocumentor.howto.pkg#using.command-line.packageoutput
  139.      * @var mixed 
  140.      */
  141.     var $package_output;
  142.  
  143.     /**
  144.      * name of current page being converted
  145.      * @var string 
  146.      */
  147.     var $page;
  148.  
  149.     /**
  150.      * path of current page being converted
  151.      * @var string 
  152.      */
  153.     var $path;
  154.  
  155.     /**
  156.      * template for the procedural page currently being processed
  157.      * @var Smarty 
  158.      */
  159.     var $page_data;
  160.  
  161.     /**
  162.      * template for the class currently being processed
  163.      * @var Smarty 
  164.      */
  165.     var $class_data;
  166.  
  167.     /**
  168.      * current procedural page being processed
  169.      * @var parserPage 
  170.      */
  171.     var $curpage;
  172.     /**
  173.      * alphabetical index of all elements sorted by package, subpackage, page,
  174.      * and class.
  175.      * @var array Format: array(package => array(subpackage => array('page'|'class' => array(path|classname => array(element, element,...)))))
  176.      * @uses $sort_absolutely_everything if true, then $package_elements is used,
  177.      *        otherwise, the {@link ParserData::$classelements} and
  178.      *        {@link ParserData::$pageelements} variables are used
  179.      */
  180.     var $package_elements = array();
  181.     /**
  182.      * alphabetical index of all elements
  183.      *
  184.      * @var array Format: array(first letter of element name => array({@link parserElement} or {@link parserPage},...))
  185.      * @see formatIndex(), HTMLframesConverter::formatIndex()
  186.      */
  187.     var $elements = array();
  188.     /**
  189.      * alphabetized index of procedural pages by package
  190.      *
  191.      * @see $leftindex
  192.      * @var array Format: array(package => array(subpackage => array({@link pageLink} 1,{@link pageLink} 2,...)
  193.      */
  194.     var $page_elements = array();
  195.     /**
  196.      * alphabetized index of defines by package
  197.      *
  198.      * @see $leftindex
  199.      * @var array Format: array(package => array(subpackage => array({@link defineLink} 1,{@link defineLink} 2,...)
  200.      */
  201.     var $define_elements = array();
  202.     /**
  203.      * alphabetized index of classes by package
  204.      *
  205.      * @see $leftindex
  206.      * @var array Format: array(package => array(subpackage => array({@link classLink} 1,{@link classLink} 2,...)
  207.      */
  208.     var $class_elements = array();
  209.     /**
  210.      * alphabetized index of global variables by package
  211.      *
  212.      * @see $leftindex
  213.      * @var array Format: array(package => array(subpackage => array({@link globalLink} 1,{@link globalLink} 2,...)
  214.      */
  215.     var $global_elements = array();
  216.     /**
  217.      * alphabetized index of functions by package
  218.      *
  219.      * @see $leftindex
  220.      * @var array Format: array(package => array(subpackage => array({@link functionLink} 1,{@link functionLink} 2,...)
  221.      */
  222.     var $function_elements = array();
  223.     /**
  224.      * alphabetical index of all elements, indexed by package/subpackage
  225.      *
  226.      * @var array Format: array(first letter of element name => array({@link parserElement} or {@link parserPage},...))
  227.      * @see formatPkgIndex(), HTMLframesConverter::formatPkgIndex()
  228.      */
  229.     var $pkg_elements = array();
  230.  
  231.     /**
  232.      * alphabetical index of all elements on a page by package/subpackage
  233.      *
  234.      * The page itself has a link under ###main
  235.      * @var array Format: array(package => array(subpackage => array(path => array({@link abstractLink} descendant 1, ...)))
  236.      * @see formatLeftIndex()
  237.      */
  238.     var $page_contents = array();
  239.  
  240.     /**
  241.      * This determines whether the {@link $page_contents} array should be sorted by element type as well as alphabetically by name
  242.      * @see sortPageContentsByElementType()
  243.      * @var boolean 
  244.      */
  245.     var $sort_page_contents_by_type = false;
  246.     /**
  247.      * This is used if the content must be passed in the order it should be read, i.e. by package, procedural then classes
  248.      *
  249.      * This fixes bug 637921, and is used by {@link PDFdefaultConverter}
  250.      */
  251.     var $sort_absolutely_everything = false;
  252.     /**
  253.      * alphabetical index of all methods and vars in a class by package/subpackage
  254.      *
  255.      * The class itself has a link under ###main
  256.      * @var array 
  257.      *  Format:<pre>
  258.      *  array(package =>
  259.      *        array(subpackage =>
  260.      *              array(path =>
  261.      *                    array(class =>
  262.      *                          array({@link abstractLink} descendant 1, ...
  263.      *                         )
  264.      *                   )
  265.      *             )
  266.      *       )</pre>
  267.      * @see formatLeftIndex()
  268.      */
  269.     var $class_contents = array();
  270.     /**
  271.      * controls processing of elements marked private with @access private
  272.      *
  273.      * defaults to false.  Set with command-line --parseprivate or -pp
  274.      * @var bool 
  275.      */
  276.     var $parseprivate;
  277.     /**
  278.      * controls display of progress information while parsing.
  279.      *
  280.      * defaults to false.  Set to true for cron jobs or other situations where no visual output is necessary
  281.      * @var bool 
  282.      */
  283.     var $quietmode;
  284.  
  285.     /**
  286.      * directory that output is sent to. -t command-line sets this.
  287.      * @tutorial phpDocumentor.howto.pkg#using.command-line.target
  288.      */
  289.     var $targetDir = '';
  290.  
  291.     /**
  292.      * Directory that the template is in, relative to phpDocumentor root directory
  293.      * @var string 
  294.      */
  295.     var $templateDir = '';
  296.  
  297.     /**
  298.      * Directory that the smarty templates are in
  299.      * @var string 
  300.      */
  301.     var $smarty_dir = '';
  302.  
  303.     /**
  304.      * Name of the template, from last part of -o
  305.      * @tutorial phpDocumentor.howto.pkg#using.command-line.output
  306.      * @var string 
  307.      */
  308.     var $templateName = '';
  309.  
  310.     /**
  311.      * full path of the current file being converted
  312.      */
  313.     var $curfile;
  314.  
  315.     /**
  316.      * All class information, organized by path, and by package
  317.      * @var Classes 
  318.      */
  319.     var $classes;
  320.  
  321.     /**
  322.      * Flag used to help converters determine whether to do special source highlighting
  323.      * @var boolean 
  324.      */
  325.     var $highlightingSource = false;
  326.  
  327.     /**
  328.      * Hierarchy of packages
  329.      *
  330.      * Every package that contains classes may have parent or child classes
  331.      * in other packages.  In other words, this code is legal:
  332.      *
  333.      * <code>
  334.      * /**
  335.      *  * @package one
  336.      *  * /
  337.      * class one {}
  338.      *
  339.      * /**
  340.      *  * @package two
  341.      *  * /
  342.      * class two extends one {}
  343.      * </code>
  344.      *
  345.      * In this case, package one is a parent of package two
  346.      * @var array 
  347.      * @see phpDocumentor_IntermediateParser::$package_parents
  348.      */
  349.     var $package_parents;
  350.  
  351.     /**
  352.      * Packages associated with categories
  353.      *
  354.      * Used by the XML:DocBook/peardoc2 converter, and available to others, to
  355.      * group many packages into categories
  356.      * @see phpDocumentor_IntermediateParser::$packagecategories
  357.      * @var array 
  358.      */
  359.     var $packagecategories;
  360.  
  361.     /**
  362.      * All packages encountered in parsing
  363.      * @var array 
  364.      * @see phpDocumentor_IntermediateParser::$all_packages
  365.      */
  366.     var $all_packages;
  367.  
  368.     /**
  369.      * A list of files that have had source code generated
  370.      * @var array 
  371.      */
  372.     var $sourcePaths = array();
  373.  
  374.     /**
  375.      * Controls which of the one-element-only indexes are generated.
  376.      *
  377.      * Generation of these indexes for large packages is time-consuming.  This is an optimization feature.  An
  378.      * example of how to use this is in {@link HTMLframesConverter::$leftindex}, and in {@link HTMLframesConverter::formatLeftIndex()}.
  379.      * These indexes are intended for use as navigational aids through documentation, but can be used for anything by converters.
  380.      * @see $class_elements, $page_elements, $function_elements, $define_elements, $global_elements
  381.      * @see formatLeftIndex()
  382.      * @var array 
  383.      */
  384.     var $leftindex = array('classes' => true'pages' => true'functions' => true'defines' => true'globals' => true);
  385.  
  386.     /** @access private */
  387.     var $killclass false;
  388.     /**
  389.      * @var string 
  390.      * @see phpDocumentor_IntermediateParser::$title
  391.      */
  392.     var $title = 'Generated Documentation';
  393.  
  394.     /**
  395.      * Options for each template, parsed from the options.ini file in the template base directory
  396.      * @tutorial phpDocumentor/tutorials.pkg#conversion.ppage
  397.      * @var array 
  398.      */
  399.     var $template_options;
  400.  
  401.     /**
  402.      * Tutorials and Extended Documentation parsed from a tutorials/package[/subpackage] directory
  403.      * @tutorial tutorials.pkg
  404.      * @access private
  405.      */
  406.     var $tutorials array();
  407.  
  408.     /**
  409.      * tree-format structure of tutorials and their child tutorials, if any
  410.      * @var array 
  411.      * @access private
  412.      */
  413.     var $tutorial_tree false;
  414.  
  415.     /**
  416.      * list of tutorials that have already been processed. Used by @link _setupTutorialTree()
  417.      * @var array 
  418.      * @access private
  419.      */
  420.     var $processed_tutorials;
  421.  
  422.     /**
  423.      * List of all @todo tags and a link to the element with the @todo
  424.      *
  425.      * Format: array(package => array(link to element, array(todo {@link parserTag},...)),...)
  426.      * @tutorial tags.todo.pkg
  427.      * @var array 
  428.      */
  429.     var $todoList = array();
  430.  
  431.     /**
  432.      * Directory where compiled templates go - will be deleted on exit
  433.      *
  434.      * @var string 
  435.      * @access private
  436.      */
  437.      var $_compiledDir array();
  438.  
  439.     /**
  440.      * Initialize Converter data structures
  441.      * @param array {@link $all_packages} value
  442.      * @param array {@link $package_parents} value
  443.      * @param Classes {@link $classes} value
  444.      * @param ProceduralPages {@link $proceduralpages} value
  445.      * @param array {@link $package_output} value
  446.      * @param boolean {@link $parseprivate} value
  447.      * @param boolean {@link $quietmode} value
  448.      * @param string {@link $targetDir} value
  449.      * @param string {@link $templateDir} value
  450.      * @param string (@link $title} value
  451.      */
  452.     function Converter(&$allp&$packp&$classes&$procpages$po$pp$qm$targetDir$template$title)
  453.     {
  454.         $this->all_packages = $allp;
  455.         $this->package_parents = $packp;
  456.         $this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
  457.         $this->proceduralpages &$procpages;
  458.         $this->package_output = $po;
  459.         if (is_array($po))
  460.         {
  461.             $a $po[0];
  462.             $this->all_packages = array_flip($po);
  463.             $this->all_packages[$a1;
  464.         }
  465.         $this->parseprivate = $pp;
  466.         $this->quietmode = $qm;
  467.         $this->classes = &$classes;
  468.         $this->roots $classes->getRoots($this->processSpecialRoots);
  469.         $this->title = $title;
  470.         $this->setTemplateDir($template);
  471.         $this->setTargetdir($targetDir);
  472.     }
  473.  
  474.     /**
  475.      * Called by IntermediateParser after creation
  476.      * @access private
  477.      */
  478.     function setTutorials($tutorials)
  479.     {
  480.         $this->tutorials $tutorials;
  481.     }
  482.  
  483.     /**
  484.      * @param pkg|cls|procthe tutorial type to search for
  485.      * @param tutorial name
  486.      * @param string package name
  487.      * @param string subpackage name, if any
  488.      * @return false|parserTutorialif the tutorial exists, return it
  489.      */
  490.     function hasTutorial($type$name$package$subpackage '')
  491.     {
  492.         if (isset($this->tutorials[$package][$subpackage][$type][$name '.' $type]))
  493.             return $this->tutorials[$package][$subpackage][$type][$name '.' $type];
  494.         return false;
  495.     }
  496.  
  497.     /**
  498.      * Called by {@link walk()} while converting, when the last class element
  499.      * has been parsed.
  500.      *
  501.      * A Converter can use this method in any way it pleases. HTMLframesConverter
  502.      * uses it to complete the template for the class and to output its
  503.      * documentation
  504.      * @see HTMLframesConverter::endClass()
  505.      * @abstract
  506.      */
  507.     function endClass()
  508.     {
  509.     }
  510.  
  511.     /**
  512.     * Called by {@link walk()} while converting, when the last procedural page
  513.     * element has been parsed.
  514.     *
  515.     * A Converter can use this method in any way it pleases. HTMLframesConverter
  516.     * uses it to complete the template for the procedural page and to output its
  517.     * documentation
  518.     * @see HTMLframesConverter::endClass()
  519.     * @abstract
  520.     */
  521.     function endPage()
  522.     {
  523.     }
  524.  
  525.     /**
  526.     * Called by {@link walk()} while converting.
  527.     *
  528.     * This method is intended to be the place that {@link $pkg_elements} is
  529.     * formatted for output.
  530.     * @see HTMLframesConverter::formatPkgIndex()
  531.     * @abstract
  532.     */
  533.     function formatPkgIndex()
  534.     {
  535.     }
  536.  
  537.     /**
  538.     * Called by {@link walk()} while converting.
  539.     *
  540.     * This method is intended to be the place that {@link $elements} is
  541.     * formatted for output.
  542.     * @see HTMLframesConverter::formatIndex()
  543.     * @abstract
  544.     */
  545.     function formatIndex()
  546.     {
  547.     }
  548.  
  549.     /**
  550.     * Called by {@link walk()} while converting.
  551.     *
  552.     * This method is intended to be the place that any of
  553.     * {@link $class_elements, $function_elements, $page_elements},
  554.     * {@link $define_elements}, and {@link $global_elements} is formatted for
  555.     * output, depending on the value of {@link $leftindex}
  556.     * @see HTMLframesConverter::formatLeftIndex()
  557.     * @abstract
  558.     */
  559.     function formatLeftIndex()
  560.     {
  561.     }
  562.  
  563.     /**
  564.      * Called by {@link parserSourceInlineTag::stringConvert()} to allow
  565.      * converters to format the source code the way they'd like.
  566.      *
  567.      * default returns it unchanged (html with xhtml tags)
  568.      * @param string output from highlight_string() - use this function to
  569.      *  reformat the returned data for Converter-specific output
  570.      * @return string 
  571.      * @deprecated in favor of tokenizer-based highlighting.  This will be
  572.      *              removed for 2.0
  573.      */
  574.     function unmangle($sourcecode)
  575.     {
  576.         return $sourcecode;
  577.     }
  578.  
  579.     /**
  580.      * Initialize highlight caching
  581.      */
  582.     function startHighlight()
  583.     {
  584.         $this->_highlightCache array(falsefalse);
  585.         $this->_appendHighlight '';
  586.     }
  587.  
  588.     function getHighlightState()
  589.     {
  590.         return $this->_highlightCache;
  591.     }
  592.  
  593.     function _setHighlightCache($type$token)
  594.     {
  595.         $test ($this->_highlightCache[0=== $type && $this->_highlightCache[1== $token);
  596.         if (!$test{
  597.             $this->_appendHighlight $this->flushHighlightCache();
  598.         else {
  599.             $this->_appendHighlight '';
  600.         }
  601.         $this->_highlightCache array($type$token);
  602.         return $test;
  603.     }
  604.  
  605.     /**
  606.      * Return the close text for the current token
  607.      * @return string 
  608.      */
  609.     function flushHighlightCache()
  610.     {
  611.         $hc $this->_highlightCache;
  612.         $this->_highlightCache array(falsefalse);
  613.         if ($hc[0]{
  614.             if (!isset($this->template_options[$hc[0]]['/'.$hc[1]])) {
  615.                 return '';
  616.             }
  617.             return $this->template_options[$hc[0]]['/'.$hc[1]];
  618.         }
  619.         return '';
  620.     }
  621.  
  622.     /**
  623.      * Used to allow converters to format the source code the way they'd like.
  624.      *
  625.      * default returns it unchanged.  Mainly used by the {@link HighlightParser}
  626.      * {@internal 
  627.      * The method takes information from options.ini, the template options
  628.      * file, specifically the [highlightSourceTokens] and [highlightSource]
  629.      * sections, and uses them to enclose tokens.
  630.      *
  631.      * {@source } }
  632.      * @param integer token value from {@link PHP_MANUAL#tokenizer tokenizer constants}
  633.      * @param string contents of token
  634.      * @param boolean whether the contents are preformatted or need modification
  635.      * @return string 
  636.      */
  637.     function highlightSource($token$word$preformatted false)
  638.     {
  639.         if ($token !== false)
  640.         {
  641.             if (!$preformatted$word $this->postProcess($word);
  642.             if (isset($this->template_options['highlightSourceTokens'][token_name($token)]))
  643.             {
  644.                 if ($this->_setHighlightCache('highlightSourceTokens'token_name($token))) {
  645.                     return $word;
  646.                 }
  647.                 $e $this->_appendHighlight;
  648.                 return $e $this->template_options['highlightSourceTokens'][token_name($token)$word;
  649.             else
  650.             {
  651.                 $this->_setHighlightCache(falsefalse);
  652.                 $e $this->_appendHighlight;
  653.                 return $e $word;
  654.             }
  655.         else
  656.         {
  657.             if (isset($this->template_options['highlightSource'][$word]))
  658.             {
  659.                 $newword ($preformatted $word $this->postProcess($word));
  660.                 if ($this->_setHighlightCache('highlightSource'$word)) {
  661.                     return $newword;
  662.                 }
  663.                 $e $this->_appendHighlight;
  664.                 return $e $this->template_options['highlightSource'][$word$newword;
  665.             else
  666.             {
  667.                 $this->_setHighlightCache(falsefalse);
  668.                 $e $this->_appendHighlight;
  669.                 return $e ($preformatted $word $this->postProcess($word));
  670.             }
  671.         }
  672.     }
  673.  
  674.     /**
  675.      * Used to allow converters to format the source code of DocBlocks the way
  676.      * they'd like.
  677.      *
  678.      * default returns it unchanged.  Mainly used by the {@link HighlightParser}
  679.      * {@internal 
  680.      * The method takes information from options.ini, the template options
  681.      * file, specifically the [highlightDocBlockSourceTokens] section, and uses
  682.      * it to enclose tokens.
  683.      *
  684.      * {@source } }
  685.      * @param string name of docblock token type
  686.      * @param string contents of token
  687.      * @param boolean whether the contents are preformatted or need modification
  688.      * @return string 
  689.      */
  690.     function highlightDocBlockSource($token$word$preformatted false)
  691.     {
  692.         if (empty($word)) {
  693.             $this->_setHighlightCache(falsefalse);
  694.             $e $this->_appendHighlight;
  695.             return $e $word;
  696.         }
  697.         if (isset($this->template_options['highlightDocBlockSourceTokens'][$token]))
  698.         {
  699.             if (!$preformatted$word $this->postProcess($word);
  700.             if ($this->_setHighlightCache('highlightDocBlockSourceTokens'$token)) {
  701.                 return $word;
  702.             }
  703.             $e $this->_appendHighlight;
  704.             return $e $this->template_options['highlightDocBlockSourceTokens'][$token$word;
  705.         else {
  706.             $this->_setHighlightCache(falsefalse);
  707.             $e $this->_appendHighlight;
  708.             return $e ($preformatted $word $this->postProcess($word));
  709.         }
  710.     }
  711.  
  712.     /**
  713.      * Used to allow converters to format the source code of Tutorial XML the way
  714.      * they'd like.
  715.      *
  716.      * default returns it unchanged.  Mainly used by the {@link HighlightParser}
  717.      * {@internal 
  718.      * The method takes information from options.ini, the template options
  719.      * file, specifically the [highlightDocBlockSourceTokens] section, and uses
  720.      * it to enclose tokens.
  721.      *
  722.      * {@source } }
  723.      * @param string name of docblock token type
  724.      * @param string contents of token
  725.      * @param boolean whether the contents are preformatted or need modification
  726.      * @return string 
  727.      */
  728.     function highlightTutorialSource($token$word$preformatted false)
  729.     {
  730.         if (empty($word)) {
  731.             $this->_setHighlightCache(falsefalse);
  732.             $e $this->_appendHighlight;
  733.             return $e $word;
  734.         }
  735.         if (isset($this->template_options['highlightTutorialSourceTokens'][$token]))
  736.         {
  737.             if (!$preformatted$word $this->postProcess($word);
  738.             if ($this->_setHighlightCache('highlightTutorialSourceTokens'$token)) {
  739.                 return $word;
  740.             }
  741.             $e $this->_appendHighlight;
  742.             return $e $this->template_options['highlightTutorialSourceTokens'][$token$word;
  743.         else {
  744.             $this->_setHighlightCache(falsefalse);
  745.             $e $this->_appendHighlight;
  746.             return $e ($preformatted $word $this->postProcess($word));
  747.         }
  748.     }
  749.  
  750.     /**
  751.      * Called by {@link parserReturnTag::Convert()} to allow converters to
  752.      * change type names to desired formatting
  753.      *
  754.      * Used by {@link XMLDocBookConverter::type_adjust()} to change true and
  755.      * false to the peardoc2 values
  756.      * @param string 
  757.      * @return string 
  758.      */
  759.     function type_adjust($typename)
  760.     {
  761.         return $typename;
  762.     }
  763.  
  764.     /**
  765.      * Used to convert the {@}example} inline tag in a docblock.
  766.      *
  767.      * By default, this just wraps ProgramExample
  768.      * @see XMLDocBookpeardoc2Converter::exampleProgramExample
  769.      * @param string 
  770.      * @param boolean true if this is to highlight a tutorial <programlisting>
  771.      * @return string 
  772.      */
  773.     function exampleProgramExample($example$tutorial false$inlinesourceparse null/*false*/,
  774.                             $class null/*false*/$linenum null/*false*/$filesourcepath null/*false*/)
  775.     {
  776.         return $this->ProgramExample($example$tutorial$inlinesourceparse$class$linenum$filesourcepath);
  777.     }
  778.  
  779.     /**
  780.      * Used to convert the <<code>> tag in a docblock
  781.      * @param string 
  782.      * @param boolean true if this is to highlight a tutorial <programlisting>
  783.      * @return string 
  784.      */
  785.     function ProgramExample($example$tutorial false$inlinesourceparse null/*false*/,
  786.                             $class null/*false*/$linenum null/*false*/$filesourcepath null/*false*/)
  787.     {
  788.         $this->highlightingSource = true;
  789.         if (tokenizer_ext)
  790.         {
  791.             $e $example;
  792.             if (!is_array($example))
  793.             {
  794.                 $obj new phpDocumentorTWordParser;
  795.                 $obj->setup($example);
  796.                 $e $obj->getFileSource();
  797.                 $bOpenTagFound false;
  798.                 foreach ($e as $ke => $ee)
  799.                 {
  800.                     foreach ($ee as $kee => $eee)
  801.                     {
  802.                         if ((int) $e[$ke][$kee][0== T_OPEN_TAG)
  803.                         {
  804.                             $bOpenTagFound true;
  805.                         }
  806.                     }
  807.                 }
  808.                 if (!$bOpenTagFound{
  809.                     $example "<?php\n".$example;
  810.                     $obj->setup($example);
  811.                     $e $obj->getFileSource();
  812.                     unset($e[0]);
  813.                     $e array_values($e);
  814.                 }
  815.                 unset($obj);
  816.             }
  817.             $saveclass $this->class;
  818.             $parser new phpDocumentor_HighlightParser;
  819.             if (!isset($inlinesourceparse))
  820.             {
  821.                 $example $parser->parse($e$thistrue)// force php mode
  822.             else
  823.             {
  824.                 if (isset($filesourcepath))
  825.                 {
  826.                     $example $parser->parse($e$this$inlinesourceparse$class$linenum$filesourcepath);
  827.                 elseif (isset($linenum))
  828.                 {
  829.                     $example $parser->parse($e$this$inlinesourceparse$class$linenum);
  830.                 elseif (isset($class))
  831.                 {
  832.                     $example $parser->parse($e$this$inlinesourceparse$class);
  833.                 else
  834.                 {
  835.                     $example $parser->parse($e$this$inlinesourceparse);
  836.                 }
  837.             }
  838.             $this->class = $saveclass;
  839.         else
  840.         {
  841.             $example $this->postProcess($example);
  842.         }
  843.         $this->highlightingSource = false;
  844.  
  845.         if ($tutorial)
  846.         {
  847.             return $example;
  848.         }
  849.  
  850.         if (!isset($this->template_options['desctranslate'])) return $example;
  851.         if (!isset($this->template_options['desctranslate']['code'])) return $example;
  852.         $example $this->template_options['desctranslate']['code'$example;
  853.         if (!isset($this->template_options['desctranslate']['/code'])) return $example;
  854.         return $example $this->template_options['desctranslate']['/code'];
  855.     }
  856.  
  857.     /**
  858.      * @param string 
  859.      */
  860.     function TutorialExample($example)
  861.     {
  862.         $this->highlightingSource = true;
  863.         $parse new phpDocumentor_TutorialHighlightParser;
  864.         $x $parse->parse($example$this);
  865.         $this->highlightingSource = false;
  866.         return $x;
  867.     }
  868.  
  869.     /**
  870.      * Used to convert the contents of <<li>> in a docblock
  871.      * @param string 
  872.      * @return string 
  873.      */
  874.     function ListItem($item)
  875.     {
  876.         if (!isset($this->template_options['desctranslate'])) return $item;
  877.         if (!isset($this->template_options['desctranslate']['li'])) return $item;
  878.         $item $this->template_options['desctranslate']['li'$item;
  879.         if (!isset($this->template_options['desctranslate']['/li'])) return $item;
  880.         return $item $this->template_options['desctranslate']['/li'];
  881.     }
  882.  
  883.     /**
  884.      * Used to convert the contents of <<ol>> or <<ul>> in a docblock
  885.      * @param string 
  886.      * @return string 
  887.      */
  888.     function EncloseList($list,$ordered)
  889.     {
  890.         $listname ($ordered 'ol' 'ul');
  891.         if (!isset($this->template_options['desctranslate'])) return $list;
  892.         if (!isset($this->template_options['desctranslate'][$listname])) return $list;
  893.         $list $this->template_options['desctranslate'][$listname$list;
  894.         if (!isset($this->template_options['desctranslate']['/'.$listname])) return $list;
  895.         return $list $this->template_options['desctranslate']['/'.$listname];
  896.     }
  897.  
  898.     /**
  899.      * Used to convert the contents of <<pre>> in a docblock
  900.      * @param string 
  901.      * @return string 
  902.      */
  903.     function PreserveWhiteSpace($string)
  904.     {
  905.         if (!isset($this->template_options['desctranslate'])) return $string;
  906.         if (!isset($this->template_options['desctranslate']['pre'])) return $string;
  907.         $string $this->template_options['desctranslate']['pre'$string;
  908.         if (!isset($this->template_options['desctranslate']['/pre'])) return $string;
  909.         return $string $this->template_options['desctranslate']['/pre'];
  910.     }
  911.  
  912.     /**
  913.      * Used to enclose a paragraph in a docblock
  914.      * @param string 
  915.      * @return string 
  916.      */
  917.     function EncloseParagraph($para)
  918.     {
  919.         if (!isset($this->template_options['desctranslate'])) return $para;
  920.         if (!isset($this->template_options['desctranslate']['p'])) return $para;
  921.         $para $this->template_options['desctranslate']['p'$para;
  922.         if (!isset($this->template_options['desctranslate']['/p'])) return $para;
  923.         return $para $this->template_options['desctranslate']['/p'];
  924.     }
  925.  
  926.     /**
  927.      * Used to convert the contents of <<b>> in a docblock
  928.      * @param string 
  929.      * @return string 
  930.      */
  931.     function Bolden($para)
  932.     {
  933.         if (!isset($this->template_options['desctranslate'])) return $para;
  934.         if (!isset($this->template_options['desctranslate']['b'])) return $para;
  935.         $para $this->template_options['desctranslate']['b'$para;
  936.         if (!isset($this->template_options['desctranslate']['/b'])) return $para;
  937.         return $para $this->template_options['desctranslate']['/b'];
  938.     }
  939.  
  940.     /**
  941.      * Used to convert the contents of <<i>> in a docblock
  942.      * @param string 
  943.      * @return string 
  944.      */
  945.     function Italicize($para)
  946.     {
  947.         if (!isset($this->template_options['desctranslate'])) return $para;
  948.         if (!isset($this->template_options['desctranslate']['i'])) return $para;
  949.         $para $this->template_options['desctranslate']['i'$para;
  950.         if (!isset($this->template_options['desctranslate']['/i'])) return $para;
  951.         return $para $this->template_options['desctranslate']['/i'];
  952.     }
  953.  
  954.     /**
  955.      * Used to convert the contents of <<var>> in a docblock
  956.      * @param string 
  957.      * @return string 
  958.      */
  959.     function Varize($para)
  960.     {
  961.         if (!isset($this->template_options['desctranslate'])) return $para;
  962.         if (!isset($this->template_options['desctranslate']['var'])) return $para;
  963.         $para $this->template_options['desctranslate']['var'$para;
  964.         if (!isset($this->template_options['desctranslate']['/var'])) return $para;
  965.         return $para $this->template_options['desctranslate']['/var'];
  966.     }
  967.  
  968.     /**
  969.      * Used to convert the contents of <<kbd>> in a docblock
  970.      * @param string 
  971.      * @return string 
  972.      */
  973.     function Kbdize($para)
  974.     {
  975.         if (!isset($this->template_options['desctranslate'])) return $para;
  976.         if (!isset($this->template_options['desctranslate']['kbd'])) return $para;
  977.         $para $this->template_options['desctranslate']['kbd'$para;
  978.         if (!isset($this->template_options['desctranslate']['/kbd'])) return $para;
  979.         return $para $this->template_options['desctranslate']['/kbd'];
  980.     }
  981.  
  982.     /**
  983.      * Used to convert the contents of <<samp>> in a docblock
  984.      * @param string 
  985.      * @return string 
  986.      */
  987.     function Sampize($para)
  988.     {
  989.         if (!isset($this->template_options['desctranslate'])) return $para;
  990.         if (!isset($this->template_options['desctranslate']['samp'])) return $para;
  991.         $para $this->template_options['desctranslate']['samp'$para;
  992.         if (!isset($this->template_options['desctranslate']['/samp'])) return $para;
  993.         return $para $this->template_options['desctranslate']['/samp'];
  994.     }
  995.  
  996.     /**
  997.      * Used to convert <<br>> in a docblock
  998.      * @param string 
  999.      * @return string 
  1000.      */
  1001.     function Br($para)
  1002.     {
  1003.         if (!isset($this->template_options['desctranslate'])) return $para;
  1004.         if (!isset($this->template_options['desctranslate']['br'])) return $para;
  1005.         $para $this->template_options['desctranslate']['br'$para;
  1006.         return $para;
  1007.     }
  1008.  
  1009.     /**
  1010.      * This version does nothing
  1011.      *
  1012.      * Perform necessary post-processing of string data.  For example, the HTML
  1013.      * Converters should escape < and > to become &lt; and &gt;
  1014.      * @return string 
  1015.      */
  1016.     function postProcess($text)
  1017.     {
  1018.         return $text;
  1019.     }
  1020.  
  1021.     /**
  1022.      * Creates a table of contents for a {@}toc} inline tag in a tutorial
  1023.      *
  1024.      * This function should return a formatted table of contents.  By default, it
  1025.      * does nothing, it is up to the converter to format the TOC
  1026.      * @abstract
  1027.      * @return string table of contents formatted for use in the current output format
  1028.      * @param array format: array(array('tagname' => section, 'link' => returnsee link, 'id' => anchor name, 'title' => from title tag),...)
  1029.      */
  1030.     function formatTutorialTOC($toc)
  1031.     {
  1032.         return '';
  1033.     }
  1034.  
  1035.     /**
  1036.      * Write out the formatted source code for a php file
  1037.      *
  1038.      * This function provides the primary functionality for the
  1039.      * {@tutorial tags.filesource.pkg} tag.
  1040.      * @param string full path to the file
  1041.      * @param string fully highlighted/linked source code of the file
  1042.      * @abstract
  1043.      */
  1044.     function writeSource($filepath$source)
  1045.     {
  1046.         debug($source);
  1047.         return;
  1048.     }
  1049.  
  1050.     /**
  1051.      * Write out the formatted source code for an example php file
  1052.      *
  1053.      * This function provides the primary functionality for the
  1054.      * {@tutorial tags.example.pkg} tag.
  1055.      * @param string example title
  1056.      * @param string example filename (no path)
  1057.      * @param string fully highlighted/linked source code of the file
  1058.      * @abstract
  1059.      */
  1060.     function writeExample($title$path$source)
  1061.     {
  1062.         return;
  1063.     }
  1064.  
  1065.     /** Translate the path info into a unique file name for the highlighted
  1066.      * source code.
  1067.      * @param string $pathinfo 
  1068.      * @return string 
  1069.      */
  1070.     function getFileSourceName($path)
  1071.     {
  1072.         global $_phpDocumentor_options;
  1073.         $pathinfo $this->proceduralpages->getPathInfo($path$this);
  1074.         $pathinfo['source_loc'str_replace($_phpDocumentor_options['Program_Root'].'/','',$pathinfo['source_loc']);
  1075.         $pathinfo['source_loc'str_replace('/','_',$pathinfo['source_loc']);
  1076.         return "fsource_{$pathinfo['package']}_{$pathinfo['subpackage']}_{$pathinfo['source_loc']}";
  1077.     }
  1078.  
  1079.     /** Return the fixed path to the source-code file folder.
  1080.      * @param string $base Path is relative to this folder
  1081.      * @return string 
  1082.      */
  1083.     function getFileSourcePath($base)
  1084.     {
  1085.         if (substr($basestrlen($base1!= PATH_DELIMITER{
  1086.             $base .= PATH_DELIMITER;
  1087.         }
  1088.         return $base '__filesource';
  1089.     }
  1090.  
  1091.     /** Return the path to the current
  1092.      * @param string $pathinfo 
  1093.      * @return string 
  1094.      */
  1095.     function getCurrentPageURL()
  1096.     {
  1097.         return '{$srcdir}' PATH_DELIMITER $this->page_dir;
  1098.     }
  1099.  
  1100.     /**
  1101.      * @return string an output-format dependent link to phpxref-style highlighted
  1102.      *  source code
  1103.      * @abstract
  1104.      */
  1105.     function getSourceLink($path)
  1106.     {
  1107.         return '';
  1108.     }
  1109.  
  1110.     /**
  1111.      * @return string Link to the current page being parsed.
  1112.      *  Should return {@link $curname} and a converter-specific extension.
  1113.      * @abstract
  1114.      */
  1115.     function getCurrentPageLink()
  1116.     {
  1117.     }
  1118.  
  1119.     /**
  1120.      * Return a line of highlighted source code with formatted line number
  1121.      *
  1122.      * If the $path is a full path, then an anchor to the line number will be
  1123.      * added as well
  1124.      * @param integer line number
  1125.      * @param string highlighted source code line
  1126.      * @param false|stringfull path to @filesource file this line is a part of,
  1127.      *         if this is a single line from a complete file.
  1128.      * @return string formatted source code line with line number
  1129.      */
  1130.     function sourceLine($linenumber$line$path false)
  1131.     {
  1132.         if ($path)
  1133.         {
  1134.             return $this->getSourceAnchor($path$linenumber.
  1135.                    $this->Br(sprintf('%-6u',$linenumber).str_replace("\n",'',$line));
  1136.         else
  1137.         {
  1138.             return $this->Br(sprintf('%-6u',$linenumber).str_replace("\n",'',$line));
  1139.         }
  1140.     }
  1141.  
  1142.     /**
  1143.      * Determine whether an element's file has generated source code, used for
  1144.      * linking to line numbers of source.
  1145.      *
  1146.      * Wrapper for {@link $sourcePaths} in this version
  1147.      * 
  1148.      * {@internal since file paths get stored with most/all slashes
  1149.      * set to forward slash '/', we need to doublecheck that
  1150.      * we're not given a backslashed path to search for...
  1151.      * if we are, it's likely that it was originally stored
  1152.      * with a forward slash.  Further, I'm not convinced it's safe
  1153.      * to just check the {@link PHPDOCUMENTOR_WINDOWS} flag, so I'm checking
  1154.      * specifically for backslashes intead.}}}
  1155.      * 
  1156.      * @param string full path to the source code file
  1157.      * @return boolean 
  1158.      */
  1159.     function hasSourceCode($path)
  1160.     {
  1161.         return isset($this->sourcePaths[$path]);
  1162.         if (strpos($path'\\'> -1{
  1163.             $modifiedPath str_replace('\\''/'$path);
  1164.             return isset($this->sourcePaths[$modifiedPath]);
  1165.         else {
  1166.             return isset($this->sourcePaths[$path]);
  1167.         }
  1168.     }
  1169.  
  1170.     /**
  1171.      * Mark a file as having had source code highlighted
  1172.      * @param string full path of source file
  1173.      */
  1174.     function setSourcePaths($path)
  1175.     {
  1176.         $this->sourcePaths[$pathtrue;
  1177.     }
  1178.  
  1179.     /**
  1180.      * Used to translate an XML DocBook entity like &rdquo; from a tutorial by
  1181.      * reading the options.ini file for the template.
  1182.      * @param string entity name
  1183.      */
  1184.     function TranslateEntity($name)
  1185.     {
  1186.         if (!isset($this->template_options['ppage']))
  1187.         {
  1188.             if (!$this->template_options['preservedocbooktags'])
  1189.             return '';
  1190.             else
  1191.             return '&'.$name.';';
  1192.         }
  1193.         if (isset($this->template_options['ppage']['&'.$name.';']))
  1194.         {
  1195.             return $this->template_options['ppage']['&'.$name.';'];
  1196.         else
  1197.         {
  1198.             if (!$this->template_options['preservedocbooktags'])
  1199.             return '';
  1200.             else
  1201.             return '&'.$name.';';
  1202.         }
  1203.     }
  1204.  
  1205.     /**
  1206.      * Used to translate an XML DocBook tag from a tutorial by reading the
  1207.      * options.ini file for the template.
  1208.      * @param string tag name
  1209.      * @param string any attributes Format: array(name => value)
  1210.      * @param string the tag contents, if any
  1211.      * @param string the tag contents, if any, unpost-processed
  1212.      * @return string 
  1213.      */
  1214.     function TranslateTag($name,$attr,$cdata,$unconvertedcdata)
  1215.     {
  1216.         if (!isset($this->template_options['ppage']))
  1217.         {
  1218.             if (!$this->template_options['preservedocbooktags'])
  1219.             return $cdata;
  1220.             else
  1221.             return '<'.$name.$this->AttrToString($name,$attr,true).'>'.$cdata.'</'.$name.'>'."\n";
  1222.         }
  1223.         // make sure this template transforms the tag into something
  1224.         if (isset($this->template_options['ppage'][$name]))
  1225.         {
  1226.             // test for global attribute transforms like $attr$role = class, changing
  1227.             // all role="*" attributes to class="*" in html, for example
  1228.             foreach($attr as $att => $val)
  1229.             {
  1230.                 if (isset($this->template_options['$attr$'.$att]))
  1231.                 {
  1232.                     $new '';
  1233.                     if (!isset($this->template_options['$attr$'.$att]['close']))
  1234.                     {
  1235.                         $new .= '<'.$this->template_options['$attr$'.$att]['open'];
  1236.                         if (isset($this->template_options['$attr$'.$att]['cdata!']))
  1237.                         {
  1238.                             if (isset($this->template_options['$attr$'.$att]['separateall']))
  1239.                             $new .= $this->template_options['$attr$'.$att]['separator'];
  1240.                             else
  1241.                             $new .= ' ';
  1242.                             $new .= $this->template_options['$attr$'.$att]['$'.$att];
  1243.                             $new .= $this->template_options['$attr$'.$att]['separator'];
  1244.                             if ($this->template_options['$attr$'.$att]['quotevalues']$val '"'.$val.'"';
  1245.                             $new .= $val.'>';
  1246.                         else
  1247.                         {
  1248.                             $new .= '>'.$val;
  1249.                         }
  1250.                         $new .= '</'.$this->template_options['$attr$'.$att]['open'].'>';
  1251.                     else
  1252.                     {
  1253.                         $new .= $this->template_options['$attr$'.$att]['open'$val $this->template_options['$attr$'.$att]['close'];
  1254.                     }
  1255.                     unset($attr[$att]);
  1256.                     $cdata $new $cdata;
  1257.                 }
  1258.             }
  1259.  
  1260.             if (!isset($this->template_options['ppage']['/'.$name]))
  1261.             {// if the close tag isn't specified, we put opening and closing tags around it, with translated attributes
  1262.                 if (isset($this->template_options['ppage'][$name.'/']))
  1263.                 $cdata '<'.$this->template_options['ppage'][$name].$this->AttrToString($name,$attr).'/>' $cdata;
  1264.                 else
  1265.                 $cdata '<'.$this->template_options['ppage'][$name].$this->AttrToString($name,$attr).'>' $cdata .
  1266.                          '</'.$this->template_options['ppage'][$name].'>';
  1267.             else
  1268.             // if close tag is specified, use the open and close as literal
  1269.                 if ($name == 'programlisting' && isset($attr['role']&&
  1270.                       ($attr['role'== 'php' || $attr['role'== 'tutorial' || $attr['role'== 'html'))
  1271.                 // highlight PHP source
  1272. //                    var_dump($unconvertedcdata, $cdata);exit;
  1273.                     if ($attr['role'== 'php'{
  1274.                         $cdata $this->ProgramExample($unconvertedcdatatrue);
  1275.                     elseif ($attr['role'== 'tutorial'{
  1276.                         $cdata $this->TutorialExample($unconvertedcdata);
  1277.                     elseif ($attr['role'== 'html'{
  1278.                         $cdata $unconvertedcdata;
  1279.                     }
  1280.                 else
  1281.                 {// normal case below
  1282.                     $cdata $this->template_options['ppage'][$name].$this->AttrToString($name,$attr)$cdata .$this->template_options['ppage']['/'.$name];
  1283.                 }
  1284.             }
  1285.             return $cdata;
  1286.         else
  1287.         {
  1288.             if ($this->template_options['preservedocbooktags'])
  1289.             {
  1290.                 return '<'.$name.$this->AttrToString($name,$attr,true).'>' $cdata .
  1291.                          '</'.$name.'>'."\n";
  1292.             else
  1293.             {
  1294.                 return $cdata;
  1295.             }
  1296.         }
  1297.     }
  1298.  
  1299.     /**
  1300.      * Convert the attribute of a Tutorial docbook tag's attribute list
  1301.      * to a string based on the template options.ini
  1302.      * @param string tag name
  1303.      * @param attribute array
  1304.      * @param boolean if true, returns attrname="value"...
  1305.      * @return string 
  1306.      */
  1307.     function AttrToString($tag,$attr,$unmodified false)
  1308.     {
  1309.         $ret '';
  1310.         if ($unmodified)
  1311.         {
  1312.             $ret ' ';
  1313.             foreach($attr as $n => $v)
  1314.             {
  1315.                 $ret .= $n.' = "'.$v.'"';
  1316.             }
  1317.             return $ret;
  1318.         }
  1319.         // no_attr tells us to ignore all attributes
  1320.         if (isset($this->template_options['no_attr'])) return $ret;
  1321.         // tagname! tells us to ignore all attributes for this tag
  1322.         if (isset($this->template_options['ppage'][$tag.'!'])) return $ret;
  1323.         if (count($attr)) $ret ' ';
  1324.         // pass 1, check to see if any attributes add together
  1325.         $same array();
  1326.         foreach($attr as $n => $v)
  1327.         {
  1328.             if (isset($this->template_options['ppage'][$tag.'->'.$n]))
  1329.             {
  1330.                 $same[$this->template_options['ppage'][$tag.'->'.$n]][$n;
  1331.             }
  1332.         }
  1333.         foreach($attr as $n => $v)
  1334.         {
  1335.             if (isset($this->template_options['ppage'][$tag.'->'.$n]))
  1336.             {
  1337.                 if (count($same[$this->template_options['ppage'][$tag.'->'.$n]]== 1)
  1338.                 // only 1 attribute translated for this one
  1339.                     // this is useful for equivalent value names
  1340.                     if (isset($this->template_options['ppage'][$tag.'->'.$n.'+'.$v])) $v $this->template_options['ppage'][$tag.'->'.$n.'+'.$v];
  1341.                 else
  1342.                 // more than 1 attribute combines to make the new attribute
  1343.                     $teststrtemp array();
  1344.                     foreach($same[$this->template_options['ppage'][$tag.'->'.$n]] as $oldattr)
  1345.                     {
  1346.                         $teststrtemp[$oldattr.'+'.$attr[$oldattr];
  1347.                     }
  1348.                     $teststrs array();
  1349.                     $num count($same[$this->template_options['ppage'][$tag.'->'.$n]]);
  1350.                     for($i=0;$i<$num;$i++)
  1351.                     {
  1352.                         $started false;
  1353.                         $a '';
  1354.                         for($j=$i;!$started || $j != $i;$j ($j $i$num)
  1355.                         {
  1356.                             if (!empty($a)) $a .= '|';
  1357.                             $a .= $teststrtemp[$j];
  1358.                         }
  1359.                         $teststrs[$i$a;
  1360.                     }
  1361.                     $done false;
  1362.                     foreach($teststrs as $test)
  1363.                     {
  1364.                         if ($donebreak;
  1365.                         if (isset($this->template_options['ppage'][$tag.'->'.$test]))
  1366.                         {
  1367.                             $done true;
  1368.                             $v $this->template_options['ppage'][$tag.'->'.$test];
  1369.                         }
  1370.                     }
  1371.                 }
  1372.                 $ret .= $this->template_options['ppage'][$tag.'->'.$n].' = "'.$v.'"';
  1373.             else
  1374.             {
  1375.                 if (!isset($this->template_options['ppage'][$tag.'!'.$n]))
  1376.                 {
  1377.                     if (isset($this->template_options['ppage']['$attr$'.$n]))
  1378.                     $ret .= $this->template_options['ppage']['$attr$'.$n].' = "'.$v.'"';
  1379.                     else
  1380.                     $ret .= $n.' = "'.$v.'"';
  1381.                 }
  1382.             }
  1383.         }
  1384.         return $ret;
  1385.     }
  1386.  
  1387.     /**
  1388.      * Convert the title of a Tutorial docbook tag section
  1389.      * to a string based on the template options.ini
  1390.      * @param string tag name
  1391.      * @param array 
  1392.      * @param string title text
  1393.      * @param string 
  1394.      * @return string 
  1395.      */
  1396.     function ConvertTitle($tag,$attr,$title,$cdata)
  1397.     {
  1398.         if (!isset($this->template_options[$tag.'_title'])) return array($attr,$cdata);
  1399.         if (isset($this->template_options[$tag.'_title']['tag_attr']))
  1400.         {
  1401.             $attr[$this->template_options[$tag.'_title']['tag_attr']] urlencode($cdata);
  1402.             $cdata '';
  1403.         elseif(isset($this->template_options[$tag.'_title']['cdata_start']))
  1404.         {
  1405.             $cdata $this->template_options[$tag.'_title']['open'$title .
  1406.                      $this->template_options[$tag.'_title']['close'$cdata;
  1407.         else $cdata $title.$cdata;
  1408.         return array($attr,$cdata);
  1409.     }
  1410.  
  1411.     /**
  1412.      * Return a converter-specific id to distinguish tutorials and their
  1413.      * sections
  1414.      *
  1415.      * Used by {@}id}
  1416.      * @return string 
  1417.      */
  1418.     function getTutorialId($package,$subpackage,$tutorial,$id)
  1419.     {
  1420.         return $package.$subpackage.$tutorial.$id;
  1421.     }
  1422.  
  1423.     /**
  1424.      * Create the {@link $elements, $pkg_elements} and {@link $links} arrays
  1425.      * @access private
  1426.      * @todo version 2.0 - faulty package_output logic should be removed
  1427.      *
  1428.      *        in this version, if the parent file isn't in the package, all
  1429.      *        the procedural elements are simply shunted to another package!
  1430.      */
  1431.     function _createPkgElements(&$pages)
  1432.     {
  1433.         if (empty($this->elements))
  1434.         {
  1435.             $this->elements = array();
  1436.             $this->pkg_elements = array();
  1437.             $this->links array();
  1438.             phpDocumentor_out('Building indexes...');
  1439.             flush();
  1440.             foreach($pages as $j => $flub)
  1441.             {
  1442.                 $this->package = $pages[$j]->parent->package;
  1443.                 $this->subpackage = $pages[$j]->parent->subpackage;
  1444.                 $this->class = false;
  1445.                 $this->curfile = $pages[$j]->parent->getFile();
  1446.                 $this->curname $this->getPageName($pages[$j]->parent);
  1447.                 $this->curpath $pages[$j]->parent->getPath();
  1448.                 $use true;
  1449.                 if ($this->package_output)
  1450.                 {
  1451.                     if (in_array($this->package,$this->package_output))
  1452.                     {
  1453.                         $this->addElement($pages[$j]->parent,$pages[$j]);
  1454.                     else
  1455.                     {
  1456.                         if (count($pages[$j]->classelements))
  1457.                         {
  1458.                             list(,$pages[$j]->parent->packageeach($this->package_output);
  1459.                             reset($this->package_output);
  1460.                             $pages[$j]->parent->subpackage '';
  1461.                             $this->addElement($pages[$j]->parent,$pages[$j]);
  1462.                         else
  1463.                         {
  1464.                             unset($pages[$j]);
  1465.                             continue;
  1466.                         }
  1467.                     }
  1468.                 else
  1469.                 {
  1470.                     $this->addElement($pages[$j]->parent,$pages[$j]);
  1471.                 }
  1472.                 if ($use)
  1473.                 for($i=0$i<count($pages[$j]->elements)$i++)
  1474.                 {
  1475.                     $pages[$j]->elements[$i]->docblock->package $this->package;
  1476.                     $pages[$j]->elements[$i]->docblock->subpackage $this->subpackage;
  1477.                     $this->proceduralpages->replaceElement($pages[$j]->elements[$i]);
  1478.                     $this->addElement($pages[$j]->elements[$i]);
  1479.                 }
  1480.                 for($i=0$i<count($pages[$j]->classelements)$i++)
  1481.                 {
  1482.                     if ($this->class)
  1483.                     {
  1484.                         if ($pages[$j]->classelements[$i]->type == 'class')
  1485.                         {
  1486.                             if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
  1487.                             $this->package = $pages[$j]->classelements[$i]->docblock->package;
  1488.                             if ($this->package_outputif (!in_array($this->package,$this->package_output)) continue;
  1489.                             $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
  1490.                             $this->class = $pages[$j]->classelements[$i]->name;
  1491.                         else
  1492.                         {
  1493.                             if ($this->killclasscontinue;
  1494.                             // force all contained elements to have parent package/subpackage
  1495.                             $pages[$j]->classelements[$i]->docblock->package $this->package;
  1496.                             $pages[$j]->classelements[$i]->docblock->subpackage $this->subpackage;
  1497.                         }
  1498.                     }
  1499.                     if ($pages[$j]->classelements[$i]->type == 'class')
  1500.                     {
  1501.                         if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
  1502.                         $this->package = $pages[$j]->classelements[$i]->docblock->package;
  1503.                         if ($this->package_outputif (!in_array($this->package,$this->package_output)) continue;
  1504.                         $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
  1505.                         $this->class = $pages[$j]->classelements[$i]->name;
  1506.                     }
  1507.                     if (!$this->killclass$this->addElement($pages[$j]->classelements[$i]);
  1508.                 }
  1509.             }
  1510.             phpDocumentor_out("done\n");
  1511.             flush();
  1512.         }
  1513.         $this->sortIndexes();
  1514.         $this->sortTodos();
  1515.         if ($this->sort_page_contents_by_type$this->sortPageContentsByElementType($pages);
  1516.     }
  1517.  
  1518.     /**
  1519.      * Process the {@link $tutorials} array
  1520.      *
  1521.      * Using the tutorialname.ext.ini files, this method sets up tutorial
  1522.      * hierarchy.  There is some minimal error checking to make sure that no
  1523.      * tutorial links to itself, even two levels deep as in tute->next->tute.
  1524.      *
  1525.      * If all tests pass, it creates the hierarchy
  1526.      * @uses generateTutorialOrder()
  1527.      * @uses _setupTutorialTree()
  1528.      * @access private
  1529.      */
  1530.     function _processTutorials()
  1531.     {
  1532.         $parents $all array();
  1533.         foreach($this->tutorials as $package => $els)
  1534.         {
  1535.             if ($this->package_output)
  1536.             {
  1537.                 if (!in_array($package,$this->package_output))
  1538.                 {
  1539.                     unset($this->tutorials[$package]);
  1540.                     continue;
  1541.                 }
  1542.             }
  1543.             if (!isset($this->pkg_elements[$package]))
  1544.             {
  1545.                 unset($this->tutorials[$package]);
  1546.                 continue;
  1547.             }
  1548.             foreach($els as $subpackage => $els2)
  1549.             {
  1550.                 foreach($els2 as $type => $tutorials)
  1551.                 {
  1552.                     foreach($tutorials as $tutorial)
  1553.                     {
  1554.                         if ($tutorial->ini)
  1555.                         {
  1556.                             if (isset($tutorial->ini['Linked Tutorials']))
  1557.                             {
  1558.                                 foreach($tutorial->ini['Linked Tutorials'as $child)
  1559.                                 {
  1560.                                     $sub (empty($tutorial->subpackage'' $tutorial->subpackage '/');
  1561.                                     $kid $tutorial->package '/' $sub $child '.' $tutorial->tutorial_type;
  1562.                                     // parent includes self as a linked tutorial?
  1563.                                     $kidlink $this->getTutorialLink($kid,false,false,array($tutorial->package));
  1564.                                     if (is_object($kidlink&& $this->returnSee($kidlink== $tutorial->getLink($this))
  1565.                                     // bad!
  1566.                                         addErrorDie(PDERROR_TUTORIAL_IS_OWN_CHILD,$tutorial->name,$tutorial->name.'.ini');
  1567.                                     }
  1568.                                 }
  1569.                                 $parents[$tutorial;
  1570.                             }
  1571.                         }
  1572.                         $all[$package][$subpackage][$type][$tutorial;
  1573.                     }
  1574.                 }
  1575.             }
  1576.         }
  1577.         // loop error-checking, use this to eliminate possibility of accidentally linking to a parent as a child
  1578.         $testlinks array();
  1579.         foreach($parents as $parent)
  1580.         {
  1581.             $testlinks[$parent->name]['links'][$parent->getLink($this);
  1582.             $testlinks[$parent->name]['name'][$parent->getLink($this)$parent->name;
  1583.         }
  1584.         // generate the order of tutorials, and link them together
  1585.         foreach($parents as $parent)
  1586.         {
  1587.             foreach($parent->ini['Linked Tutorials'as $child)
  1588.             {
  1589.                 $sub (empty($parent->subpackage'' $parent->subpackage '/');
  1590.                 $kid $parent->package '/' $sub $child '.' $parent->tutorial_type;
  1591.                 // child tutorials must be in the same package AND subpackage
  1592.                 // AND have the same extension as the parent, makes things clearer for both ends
  1593.                 if (in_array($this->returnSee($this->getTutorialLink($kid,false,false,array($parent->package))),$testlinks[$parent->name]['links']))
  1594.                     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');
  1595.                 if ($this->returnSee($this->getTutorialLink($kid,false,false,array($parent->package))) == $kid)
  1596.                 {
  1597.                     addWarning(PDERROR_CHILD_TUTORIAL_NOT_FOUND$child '.' $parent->tutorial_type$parent->name .'.ini',$parent->package$parent->subpackage);
  1598.                 }
  1599.             }
  1600.         }
  1601.         $new $tree $roots array();
  1602.         // build a list of all 'root' tutorials (tutorials without parents).
  1603.         foreach($parents as $i => $parent)
  1604.         {
  1605.             if ($parent->isChildOf($parents)) {
  1606.                 $roots[$parent;
  1607.             }
  1608.         }
  1609.         $parents $roots;
  1610.         // add the parents and all child tutorials in order to the list of tutorials to process
  1611.         foreach($parents as $parent)
  1612.         {
  1613.             $this->generateTutorialOrder($parent,$all,$new);
  1614.         }
  1615.         if (count($all))
  1616.         {
  1617.             // add the leftover tutorials
  1618.             foreach($all as $package => $els)
  1619.             {
  1620.                 foreach($els as $subpackage => $els2)
  1621.                 {
  1622.                     foreach($els2 as $type => $tutorials)
  1623.                     {
  1624.                         foreach($tutorials as $tutorial)
  1625.                         {
  1626.                             $new[$package][$subpackage][$type][$tutorial;
  1627.                         }
  1628.                     }
  1629.                 }
  1630.             }
  1631.         }
  1632.         // remove the old, unprocessed tutorials, and set it up with the next code
  1633.         $this->tutorials array();
  1634.         // reset integrity of the tutorial list
  1635.         $prev false;
  1636.         uksort($new'tutorialcmp');
  1637. //        debug($this->vardump_tree($new));exit;
  1638.         foreach($new as $package => $els)
  1639.         {
  1640.             foreach($els as $subpackage => $els2)
  1641.             {
  1642.                 foreach($els2 as $type => $tutorials)
  1643.                 {
  1644.                     foreach($tutorials as $tutorial)
  1645.                     {
  1646.                         if ($prev)
  1647.                         {
  1648.                             $this->tutorials[$prevpackage][$prevsubpackage][$prevtype][$prevname]->setNext($tutorial,$this);
  1649.                             $tutorial->setPrev($prev,$this);
  1650.                         }
  1651.                         $this->tutorials[$package][$subpackage][$type][$tutorial->name$tutorial;
  1652.                         $prev $tutorial->getLink($this,true);
  1653.                         $prevpackage $package;
  1654.                         $prevsubpackage $subpackage;
  1655.                         $prevtype $type;
  1656.                         $prevname $tutorial->name;
  1657.                     }
  1658.                 }
  1659.             }
  1660.         }
  1661.         $this->tutorial_tree $this->_setupTutorialTree();
  1662.         return $new;
  1663.     }
  1664.  
  1665.     /**
  1666.     * called by {@link phpDocumentor_IntermediateParser::Convert()} to traverse
  1667.     * the array of pages and their elements, converting them to the output format
  1668.     *
  1669.     * The walk() method should be flexible enough such that it never needs
  1670.     * modification.  walk() sets up all of the indexes, and sorts everything in
  1671.     * logical alphabetical order.  It then passes each element individually to
  1672.     * {@link Convert()}, which then passes to the Convert*() methods.  A child
  1673.     * Converter need not override any of these unless special functionality must
  1674.     * be added. see {@tutorial Converters/template.vars.cls} for details.
  1675.     * {@internal 
  1676.     * walk() first creates all of the indexes {@link $elements, $pkg_elements}
  1677.     * and the left indexes specified by {@link $leftindexes},
  1678.     * and then sorts them by calling {@link sortIndexes()}.
  1679.     *
  1680.     * Next, it converts all README/CHANGELOG/INSTALL-style files, using
  1681.     * {@link Convert_RIC}.
  1682.     *
  1683.     * After this, it
  1684.     * passes all package-level docs to Convert().  Then, it calls the index
  1685.     * sorting functions {@link formatPkgIndex(), formatIndex()} and
  1686.     * {@link formatLeftIndex()}.
  1687.     *
  1688.     * Finally, it converts each procedural page in alphabetical order.  This
  1689.     * stage passes elements from the physical file to Convert() in alphabetical
  1690.     * order.  First, procedural page elements {@link parserDefine, parserInclude}
  1691.     * {@link parserGlobal}, and {@link parserFunction} are passed to Convert().
  1692.     *
  1693.     * Then, class elements are passed in this order: {@link parserClass}, then
  1694.     * all of the {@link parserVar}s in the class and all of the
  1695.     * {@link parserMethod}s in the class.  Classes are in alphabetical order,
  1696.     * and both vars and methods are in alphabetical order.
  1697.     *
  1698.     * Finally, {@link ConvertErrorLog()} is called and the data walk is complete.}}}
  1699.     * @param array Format: array(fullpath => {@link parserData} structure with full {@link parserData::$elements}
  1700.     *                                          and {@link parserData::$class_elements}.
  1701.     * @param array Format: array({@link parserPackagePage} 1, {@link parserPackagePage} 2,...)
  1702.     * @uses Converter::_createPkgElements() sets up {@link $elements} and
  1703.     *        {@link $pkg_elements} array, as well as {@link $links}
  1704.     */
  1705.     function walk(&$pages,&$package_pages)
  1706.     {
  1707.         if (empty($pages))
  1708.         {
  1709.             die("<b>ERROR</b>: nothing parsed");
  1710.         }
  1711.         $this->_createPkgElements($pages);
  1712.         if (count($this->ric))
  1713.         {
  1714.             phpDocumentor_out("Converting README/INSTALL/CHANGELOG contents...\n");
  1715.             flush();
  1716.             foreach($this->ric as $name => $contents)
  1717.             {
  1718.                 phpDocumentor_out("$name...");
  1719.                 flush();
  1720.                 $this->Convert_RIC($name,$contents);
  1721.             }
  1722.             phpDocumentor_out("\ndone\n");
  1723.             flush();
  1724.         }
  1725.         foreach($package_pages as $i => $perp)
  1726.         {
  1727.             if ($this->package_output)
  1728.             {
  1729.                 if (!in_array($package_pages[$i]->package,$this->package_output)) continue;
  1730.             }
  1731.             phpDocumentor_out('Converting package page for package '.$package_pages[$i]->package.'... ');
  1732.             flush();
  1733.             $this->package = $package_pages[$i]->package;
  1734.             $this->subpackage = '';
  1735.             $this->class = false;
  1736.             $this->Convert($package_pages[$i]);
  1737.             phpDocumentor_out("done\n");
  1738.             flush();
  1739.         }
  1740.         phpDocumentor_out("Converting tutorials/extended docs\n");
  1741.         flush();
  1742.         // get tutorials into the order they will display, and set next/prev links
  1743.         $new $this->_processTutorials();
  1744.         foreach($this->tutorials as $package => $els)
  1745.         {
  1746.             foreach($els as $subpackage => $els2)
  1747.             {
  1748.                 foreach($els2 as $type => $tutorials)
  1749.                 {
  1750.                     foreach($tutorials as $tutorial)
  1751.                     {
  1752.                         switch ($type)
  1753.                         {
  1754.                             case 'pkg' :
  1755.                                 $a '';
  1756.                                 if ($tutorial->ini)
  1757.                                 $a .= 'Top-level ';
  1758.                                 if (!empty($tutorial->subpackage))
  1759.                                 $a .= 'Sub-';
  1760.                                 $ptext "Converting ${a}Package-level tutorial ".$tutorial->name.'...';
  1761.                             break;
  1762.                             case 'cls' :
  1763.                                 $a '';
  1764.                                 if ($tutorial->ini)
  1765.                                 $a .= 'Top-level ';
  1766.                                 $ptext "Converting ${a}Class-level tutorial $tutorial->name ." and associating...";
  1767.                                 $link Converter::getClassLink(str_replace('.cls','',$tutorial->name)$tutorial->package);
  1768.                                 if (is_object($link))
  1769.                                 {
  1770.                                     if ($this->sort_absolutely_everything)
  1771.                                     {
  1772.                                         $addend 'unsuccessful ';
  1773.                                         if (isset($this->package_elements[$tutorial->package][$tutorial->subpackage]['class'][$link->name]))
  1774.                                         {
  1775.                                             $this->package_elements[$tutorial->package][$tutorial->subpackage]['class'][$link->name][0]->addTutorial($tutorial,$this);
  1776.                                             $addend 'success ';
  1777.                                         }
  1778.                                     else
  1779.                                     {
  1780.                                         $addend 'unsuccessful ';
  1781.                                         if (!isset($this->classes->killclass[str_replace('.cls','',$tutorial->name)]&& !isset($this->classes->killclass[str_replace('.cls','',$tutorial->name)][$tutorial->path]))
  1782.                                         {
  1783.                                             foreach($pages as $j => $inf)
  1784.                                             {
  1785.                                                 foreach($inf->classelements as $i => $class)
  1786.                                                 {
  1787.                                                     if ($class->type == 'class' && $class->name == str_replace('.cls','',$tutorial->name&& $class->path == $link->path)
  1788.                                                     {
  1789.                                                         $pages[$j]->classelements[$i]->addTutorial($tutorial,$this);
  1790.                                                         $addend 'success ';
  1791.                                                     }
  1792.                                                 }
  1793.                                             }
  1794.                                         }
  1795.                                     }
  1796.                                     $ptext .= $addend;
  1797.                                 else $ptext .= "unsuccessful ";
  1798.                             break;
  1799.                             case 'proc' :
  1800.                                 $a '';
  1801.                                 if ($tutorial->ini)
  1802.                                 $a .= 'Top-level ';
  1803.                                 $ptext "Converting ${a}Procedural-level tutorial ".$tutorial->name." and associating...";
  1804.                                 $link Converter::getPageLink(str_replace('.proc','',$tutorial->name)$tutorial->package);
  1805.                                 if (is_object($link))
  1806.                                 {
  1807.                                     $addend 'unsuccessful ';
  1808.                                     if ($this->sort_absolutely_everything)
  1809.                                     {
  1810.                                         if (isset($this->package_elements[$tutorial->package][$tutorial->subpackage]['page'][$link->path]))
  1811.                                         {
  1812.                                             $this->package_elements[$tutorial->package][$tutorial->subpackage]['page'][$link->path][0]->addTutorial($tutorial,$this);
  1813.                                             $addend "success ";
  1814.                                         }
  1815.                                     else
  1816.                                     {
  1817.                                         foreach($pages as $j => $info)
  1818.                                         {
  1819.                                             if ($j == $link->path)
  1820.                                             {
  1821.                                                 $pages[$j]->addTutorial($tutorial,$this);
  1822.                                                 $addend "success ";
  1823.                                             }
  1824.                                         }
  1825.                                     }
  1826.                                     $ptext .= $addend;
  1827.                                 else $ptext .= "unsuccessful ";
  1828.                             break;
  1829.                         }
  1830.                         phpDocumentor_out($ptext);
  1831.                         flush();
  1832.                         $this->package = $tutorial->package;
  1833.                         $this->subpackage = $tutorial->subpackage;
  1834.                         $this->Convert($tutorial);
  1835.                         phpDocumentor_out("done\n");
  1836.                         flush();
  1837.                     }
  1838.                 }
  1839.             }
  1840.         }
  1841.         phpDocumentor_out("Formatting Package Indexes...");
  1842.         flush();
  1843.         $this->formatPkgIndex();
  1844.         phpDocumentor_out("done\n");
  1845.         flush();
  1846.         phpDocumentor_out("Formatting Index...");
  1847.         flush();
  1848.         $this->formatIndex();
  1849.         phpDocumentor_out("done\n\n");
  1850.         flush();
  1851.         phpDocumentor_out("Formatting Left Quick Index...");
  1852.         flush();
  1853.         $this->formatLeftIndex();
  1854.         phpDocumentor_out("done\n\n");
  1855.         flush();
  1856.         if ($this->sort_absolutely_everythingreturn $this->walk_everything();
  1857.         foreach($pages as $j => $flub)
  1858.         {
  1859.             phpDocumentor_out('Converting '.$pages[$j]->parent->getPath());
  1860.             flush();
  1861.             $this->package = $pages[$j]->parent->package;
  1862.             $this->subpackage = $pages[$j]->parent->subpackage;
  1863.             $this->class = false;
  1864.             $this->curfile = $pages[$j]->parent->getFile();
  1865.             $this->curname $this->getPageName($pages[$j]->parent);
  1866.             $this->curpath $pages[$j]->parent->getPath();
  1867.             $use true;
  1868.             if ($this->package_output)
  1869.             {
  1870.                 if (in_array($this->package,$this->package_output))
  1871.                 {
  1872.                     $this->Convert($pages[$j]);
  1873.                 else
  1874.                 {
  1875.                     $use false;
  1876.                 }
  1877.             else
  1878.             {
  1879.                 $this->Convert($pages[$j]);
  1880.             }
  1881.             phpDocumentor_out(" Procedural Page Elements...");
  1882.             flush();
  1883.             if ($use)
  1884.             for($i=0$i<count($pages[$j]->elements)$i++)
  1885.             {
  1886.                 $a $pages[$j]->elements[$i]->docblock->getKeyword('access');
  1887.                 if (is_object($a)) $a $a->getString();
  1888.                 if (!$this->parseprivate && ($a == 'private'))
  1889.                     continue;
  1890. //                phpDocumentor_out("    ".$pages[$j]->elements[$i]->name."\n");
  1891.                 $pages[$j]->elements[$i]->docblock->package $this->package;
  1892.                 $pages[$j]->elements[$i]->docblock->subpackage $this->subpackage;
  1893.                 $this->Convert($pages[$j]->elements[$i]);
  1894.             }
  1895.             phpDocumentor_out(" Classes...");
  1896.             $this->class = false;
  1897.             flush();
  1898.             for($i=0$i<count($pages[$j]->classelements)$i++)
  1899.             {
  1900.                 if ($this->class)
  1901.                 {
  1902.                     if ($pages[$j]->classelements[$i]->type == 'class')
  1903.                     {
  1904.                         if (!$this->killclass$this->endClass();
  1905.                         $this->killclass false;
  1906.                         if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
  1907.                         $this->package = $pages[$j]->classelements[$i]->docblock->package;
  1908.                         if ($this->package_outputif (!in_array($this->package,$this->package_output)) continue;
  1909.                         $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
  1910.                         $this->class = $pages[$j]->classelements[$i]->name;
  1911.                     else
  1912.                     {
  1913.                         $a $pages[$j]->classelements[$i]->docblock->getKeyword('access');
  1914.                         if (is_object($a)) $a $a->getString();
  1915.                         if (!$this->parseprivate && ($a == 'private'))
  1916.                             continue;
  1917.                         if ($this->killclasscontinue;
  1918.                         // force all contained elements to have parent package/subpackage
  1919.                         $pages[$j]->classelements[$i]->docblock->package $this->package;
  1920.                         $pages[$j]->classelements[$i]->docblock->subpackage $this->subpackage;
  1921.                     }
  1922.                 }
  1923.                 if ($pages[$j]->classelements[$i]->type == 'class')
  1924.                 {
  1925.                     $this->killclass false;
  1926.                     if ($this->checkKillClass($pages[$j]->classelements[$i]->getName(),$pages[$j]->classelements[$i]->getPath())) continue;
  1927.                     $this->package = $pages[$j]->classelements[$i]->docblock->package;
  1928.                     if ($this->package_outputif (!in_array($this->package,$this->package_output)) continue;
  1929.                     $this->subpackage = $pages[$j]->classelements[$i]->docblock->subpackage;
  1930.                     $this->class = $pages[$j]->classelements[$i]->name;
  1931.                 }
  1932.                 if ($this->killclasscontinue;
  1933. //                phpDocumentor_out("    ".$pages[$j]->classelements[$i]->name."\n");
  1934.                 $this->Convert($pages[$j]->classelements[$i]);
  1935.             }
  1936.             if (count($pages[$j]->classelements&& !$this->killclass$this->endClass();
  1937.             phpDocumentor_out(" done\n");
  1938.             flush();
  1939.             $this->endPage();
  1940.         }
  1941.         phpDocumentor_out("\nConverting @todo List...");
  1942.         flush();
  1943.         if (count($this->todoList))
  1944.         {
  1945.             $this->ConvertTodoList();
  1946.         }
  1947.         phpDocumentor_out("done\n");
  1948.         flush();
  1949.         phpDocumentor_out("\nConverting Error Log...");
  1950.         flush();
  1951.         $this->ConvertErrorLog();
  1952.         phpDocumentor_out("done\n");
  1953.         flush();
  1954.     }
  1955.  
  1956.  
  1957.     /**
  1958.      * Get a tree structure representing the hierarchy of tutorials
  1959.      *
  1960.      * Returns an array in format:
  1961.      * <pre>
  1962.      * array('tutorial' => {@link parserTutorial},
  1963.      *       'kids' => array( // child tutorials
  1964.      *                   array('tutorial' => child {@link parserTutorial},
  1965.      *                         'kids' => array(...)
  1966.      *                        )
  1967.      *                      )
  1968.      *      )
  1969.      * </pre>
  1970.      * @param parserTutorial|array
  1971.      * @tutorial tutorials.pkg
  1972.      * @return array 
  1973.      */
  1974.     function getTutorialTree($tutorial)
  1975.     {
  1976.         if (is_object($tutorial))
  1977.         {
  1978.             $path $this->_tutorial_path($tutorial,$tutorial,$tutorial);
  1979.             if (isset($this->tutorial_tree[$path])) {
  1980.                 $tutorial $this->tutorial_tree[$path];
  1981.             else {
  1982.                 return false;
  1983.             }
  1984.         }
  1985.         $tree array();
  1986.         if (isset($tutorial['tutorial']))
  1987.         {
  1988.             $tree['tutorial'$tutorial['tutorial'];
  1989.             if (isset($tutorial['child']))
  1990.             {
  1991.                 foreach($tutorial['child'as $a => $b)
  1992.                 {
  1993.                     $btut $b['tutorial'];
  1994.                     $res array(
  1995.                         'tutorial' => $this->tutorials
  1996.                             [$btut->package][$btut->subpackage]
  1997.                             [$btut->tutorial_type][$btut->name]
  1998.                     );
  1999.                     if (isset($b['child']))
  2000.                     {
  2001.                          $tempres Converter::getTutorialTree($b);
  2002.                          $res['kids'$tempres['kids'];
  2003.                     }
  2004.                     $tree['kids'][$res;
  2005.                 }
  2006.             }
  2007.         }
  2008.         return $tree;
  2009.     }
  2010.  
  2011.     /**
  2012.      * Remove tutorials one by one from $all, and transfer them into $new in the
  2013.      * order they should be parsed
  2014.      * @param parserTutorial 
  2015.      * @param array 
  2016.      * @param array 
  2017.      * @access private
  2018.      */
  2019.     function generateTutorialOrder($parent,&$all,&$new)
  2020.     {
  2021.         // remove from the list of tutorials to process
  2022.         foreach($all[$parent->package][$parent->subpackage][$parent->tutorial_typeas $ind => $t)
  2023.         {
  2024.             if ($t->name == $parent->name{
  2025.                 unset($all[$parent->package][$parent->subpackage][$parent->tutorial_type][$ind]);
  2026.             }
  2027.         }
  2028.         // add to the new ordered list of tutorials
  2029.         $x &$new[$parent->package][$parent->subpackage][$parent->tutorial_type];
  2030.         if (!is_object($x[count($x1]|| $x[count($x1]->name != $parent->name)
  2031.         // only add if the parent isn't also a child
  2032.             $new[$parent->package][$parent->subpackage][$parent->tutorial_type][$parent;
  2033.             // add a new branch to the tree
  2034.         }
  2035.         // process all child tutorials, and insert them in order
  2036. //        debug("processing parent ".$parent->name);
  2037.         if ($parent->ini)
  2038.         {
  2039.             foreach($parent->ini['Linked Tutorials'as $child)
  2040.             {
  2041.                 $sub (empty($parent->subpackage'' $parent->subpackage '/');
  2042.                 $kid $parent->package '/' $sub $child '.' $parent->tutorial_type;
  2043.                 $_klink $this->getTutorialLink($kid,false,false,array($parent->package));
  2044.                 if (is_object($_klink)) {
  2045.                     $klink $this->returnSee($_klink);
  2046.                 else {
  2047.                     $klink false;
  2048.                 }
  2049.                 // remove the child from the list of remaining tutorials
  2050.                 foreach($all[$parent->package][$parent->subpackage][$parent->tutorial_typeas $ind => $tute)
  2051.                 {
  2052.                     if ($klink && $tute->getLink($this== $klink)
  2053.                     {
  2054.                         // set up parent, next and prev links
  2055.                         $tute->setParent($parent$this);
  2056.                         // remove the child from the list of tutorials to process
  2057.                         foreach($all[$parent->package][$parent->subpackage][$parent->tutorial_typeas $ind => $t)
  2058.                         {
  2059.                             if ($t->name == $tute->name)
  2060.                             unset($all[$parent->package][$parent->subpackage][$parent->tutorial_type][$ind]);
  2061.                         }
  2062.                         // add to the new ordered list of tutorials
  2063.                         $new[$parent->package][$parent->subpackage][$parent->tutorial_type][$tute;
  2064.                         if ($tute->ini)
  2065.                         {
  2066.                             // add all the child's child tutorials to the list
  2067.                             $this->generateTutorialOrder($tute,$all,$new);
  2068.                         }
  2069.                     }
  2070.                 }
  2071.             }
  2072.         }
  2073.         return;
  2074.     }
  2075.  
  2076.         /** Returns the path to this tutorial as a string
  2077.          * @param parserTutorial $pkg 
  2078.          * @param parserTutorial $subpkg 
  2079.          * @param parserTutorial $namepkg 
  2080.          * @return string */
  2081.         function _tutorial_path($pkg$subpkg 0$namepkg 0)
  2082.         {
  2083.             if (!$subpkg{
  2084.                 $subpkg $pkg;
  2085.             }
  2086.             if (!$namepkg{
  2087.                 $namepkg $pkg;
  2088.             }
  2089.             $subpackagename ($subpkg->subpackage '/' $subpkg->subpackage '');
  2090.             return $pkg->package $subpackagename '/' $namepkg->name;
  2091.         }
  2092.  
  2093.  
  2094.     /**
  2095.      * Creates a tree structure of tutorials
  2096.      *
  2097.      * Format:
  2098.      * <pre>
  2099.      * array('package/subpackage/tutorial1.ext' =>
  2100.      *          array('tutorial' => {@link parserTutorial},
  2101.      *                'child'    =>
  2102.      *                    array('package/subpackage/child1tutorial.ext' => ...,
  2103.      *                          'package/subpackage/child2tutorial.ext' => ...,
  2104.      *                          ...
  2105.      *                         )
  2106.      *       'package/subpackage/tutorial2.ext' => ...,
  2107.      *       ...
  2108.      *       )
  2109.      * </pre>
  2110.      * @return array the tutorial tree
  2111.      * @access private
  2112.      */
  2113.     function _setupTutorialTree($parent false)
  2114.     {
  2115.         if (isset($this->processed_tutorials)) {
  2116.             $this->processed_tutorials array();
  2117.         }
  2118.         $tree array();
  2119.         if (!$parent)
  2120.         {
  2121.             foreach($this->tutorials as $package => $s)
  2122.             {
  2123.                 foreach($s as $subpackage => $t)
  2124.                 {
  2125.                     foreach($t as $type => $n)
  2126.                     {
  2127.                         foreach($n as $name => $tutorial)
  2128.                         {
  2129.                             if ($tutorial->parent{
  2130.                                 continue;
  2131.                             }
  2132.                             
  2133.                             $child_path $this->_tutorial_path($tutorial,$tutorial,$tutorial);
  2134.                             if (isset($this->processed_tutorials[$child_path])) {
  2135.                                 continue;
  2136.                             }
  2137.                             $this->processed_tutorials[$child_path$tutorial;
  2138.                             //debug("parent ".$tutorial->name);
  2139.                             $ret $this->_setupTutorialTree($tutorial);
  2140.                             if (!count($tree)) {
  2141.                                 $tree $ret;
  2142.                             else {
  2143.                                 $tree array_merge($tree,$ret);
  2144.                             }
  2145.                         }
  2146.                     }
  2147.                 }
  2148.             }
  2149.             return $tree;
  2150.         }
  2151.         $parent_path $this->_tutorial_path($parent);
  2152.         $tree[$parent_path]['tutorial'$parent;
  2153.         // process all child tutorials, and insert them in order
  2154.         if ($parent->ini)
  2155.         {
  2156.             foreach($parent->ini['Linked Tutorials'as $child)
  2157.             {
  2158.                 if (isset($this->tutorials[$parent->package][$parent->subpackage]
  2159.                                           [$parent->tutorial_type][$child '.' .
  2160.                                            $parent->tutorial_type])) {
  2161.                     // remove the child from the list of remaining tutorials
  2162.                     $tute $this->tutorials[$parent->package][$parent->subpackage]
  2163.                                             [$parent->tutorial_type][$child '.' .
  2164.                                              $parent->tutorial_type];
  2165.                 else {
  2166.                     $tute false;
  2167.                 }
  2168.  
  2169.                 if (!$tute{
  2170.                     continue;
  2171.                 }
  2172.                 $child_path $this->_tutorial_path($parent,$parent,$tute);
  2173.                 if (isset($this->processed_tutorials[$child_path])) {
  2174.                     continue;
  2175.                 }
  2176.                 $this->processed_tutorials[$child_path$tute;
  2177.                 if ($tute->name != $child '.' $parent->tutorial_type{
  2178.                     continue;
  2179.                 }
  2180.                 //echo "Adding [$child_path] to [$parent_path]<br>";
  2181.                 $tree[$parent_path]['child'][$this->_tutorial_path($parent,$parent,$tute)]['tutorial']
  2182.                     = $tute;
  2183.                 if (!$tute->ini{
  2184.                     continue;
  2185.                 }
  2186.                 // add all the child's child tutorials to the list
  2187.                 if (!isset($tree[$parent_path]['child'])) {
  2188.                     $tree[$parent_path]['child'$this->_setupTutorialTree($tute);
  2189.                 else {
  2190.                     $tree[$parent_path]['child'array_merge($tree[$parent_path]['child'],
  2191.                         $this->_setupTutorialTree($tute));
  2192.                 }
  2193.             }
  2194.         }
  2195.         return $tree;
  2196.     }
  2197.  
  2198.     /**
  2199.      * Debugging function for dumping {@link $tutorial_tree}
  2200.      * @return string 
  2201.      */
  2202.     function vardump_tree($tree,$indent='')
  2203.     {
  2204.         if (phpDocumentor_get_class($tree== 'parsertutorial'return $tree->name.' extends '.($tree->parent$tree->parent->name 'nothing');
  2205.         $a '';
  2206.         foreach($tree as $ind => $stuff)
  2207.         {
  2208.             $x $this->vardump_tree($stuff,"$indent   ");
  2209.             $a .= $indent.'['.$ind." => \n   ".$indent.$x."]\n";
  2210.         }
  2211.         return substr($a,0,strlen($a1);
  2212.     }
  2213.  
  2214.     /**
  2215.      * @access private
  2216.      */
  2217.     function sort_package_elements($a,$b)
  2218.     {
  2219.         if (($a->type == $b->type&& (isset($a->isConstructor&& $a->isConstructor)) return -1;
  2220.         if (($a->type == $b->type&& (isset($b->isConstructor&& $b->isConstructor)) return 1;
  2221.         if ($a->type == $b->typereturn strnatcasecmp($a->name,$b->name);
  2222.         if ($a->type == 'class'return -1;
  2223.         if ($b->type == 'class'return 1;
  2224.         if ($a->type == 'const'return -1;
  2225.         if ($b->type == 'const'return 1;
  2226.         if ($a->type == 'var'return -1;
  2227.         if ($b->type == 'var'return 1;
  2228.         if ($a->type == 'page'return -1;
  2229.         if ($b->type == 'page'return 1;
  2230.         if ($a->type == 'include'return -1;
  2231.         if ($b->type == 'include'return 1;
  2232.         if ($a->type == 'define'return -1;
  2233.         if ($b->type == 'define'return 1;
  2234.         if ($a->type == 'global'return -1;
  2235.         if ($b->type == 'global'return 1;
  2236.         if ($a->type == 'function'return -1;
  2237.         if ($b->type == 'function'return 1;
  2238.     }
  2239.  
  2240.     /**
  2241.      * @access private
  2242.      */
  2243.     function defpackagesort($a,$b)
  2244.     {
  2245.         if ($a == $GLOBALS['phpDocumentor_DefaultPackageName']return -1;
  2246.         if ($b == $GLOBALS['phpDocumentor_DefaultPackageName']return 0;
  2247.         return strnatcasecmp($a,$b);
  2248.     }
  2249.  
  2250.     /**
  2251.      * @access private
  2252.      */
  2253.     function Pc_sort($a,$b)
  2254.     {
  2255.         return strnatcasecmp(key($a),key($b));
  2256.     }
  2257.  
  2258.     /**
  2259.      * walk over elements by package rather than page
  2260.      *
  2261.      * This method is designed for converters like the PDF converter that need
  2262.      * everything passed in alphabetical order by package/subpackage and by
  2263.      * procedural and then class information
  2264.      * @see PDFdefaultConverter
  2265.      * @see walk()
  2266.      */
  2267.     function walk_everything()
  2268.     {
  2269.         global $hooser;
  2270.         $hooser false;
  2271.         uksort($this->package_elements,array($this,'defpackagesort'));
  2272.         foreach($this->package_elements as $package => $r)
  2273.         {
  2274.             if ($this->package_output)
  2275.             {
  2276.                 if (!in_array($this->package,$this->package_output))
  2277.                 {
  2278.                     unset($this->package_elements[$package]);
  2279.                     continue;
  2280.                 }
  2281.             }
  2282.             uksort($this->package_elements[$package],'strnatcasecmp');
  2283.         }
  2284.         foreach($this->package_elements as $package => $r)
  2285.         {
  2286.             foreach($this->package_elements[$packageas $subpackage => $r)
  2287.             {
  2288.                 if (isset($r['page']))
  2289.                 {
  2290.                     uksort($r['page'],'strnatcasecmp');
  2291.                     foreach($r['page'as $page => $oo)
  2292.                     {
  2293.                         usort($this->package_elements[$package][$subpackage]['page'][$page],array($this,'sort_package_elements'));
  2294.                     }
  2295.                 }
  2296.                 if (isset($r['class']))
  2297.                 {
  2298.                     uksort($r['class'],'strnatcasecmp');
  2299.                     foreach($r['class'as $page => $oo)
  2300.                     {
  2301.                         usort($r['class'][$page],array($this,'sort_package_elements'));
  2302.                     }
  2303.                 }
  2304.                 $this->package_elements[$package][$subpackage$r;
  2305.             }
  2306.         }
  2307.         foreach($this->package_elements as $package => $s)
  2308.         {
  2309.             $notyet false;
  2310.             foreach($s as $subpackage => $r)
  2311.             {
  2312.                 $this->package = $package;
  2313.                 $this->subpackage = $subpackage;
  2314.                 if (isset($r['page']))
  2315.                 {
  2316.                     $this->class = false;
  2317.                     foreach($r['page'as $page => $elements)
  2318.                     {
  2319.                         if (is_array($elements))
  2320.                         {
  2321.                             foreach($elements as $element)
  2322.                             {
  2323.                                 if ($element->type == 'page')
  2324.                                 {
  2325.                                     phpDocumentor_out('Converting '.$element->parent->getPath());
  2326.                                     flush();
  2327.                                     $this->curfile = $element->parent->getFile();
  2328.                                     $this->curname $this->getPageName($element->parent);
  2329.                                     $this->curpath $element->parent->getPath();
  2330.                                     $notyet true;
  2331.                                 else
  2332.                                 {
  2333.                                     // force all contained elements to have parent package/subpackage
  2334.                                     $element->docblock->package $this->package;
  2335.                                     $element->docblock->subpackage $this->subpackage;
  2336.                                     $a $element->docblock->getKeyword('access');
  2337.                                     if (is_object($a)) $a $a->getString();
  2338.                                     if (!$this->parseprivate && ($a == 'private'))
  2339.                                         continue;
  2340.                                 }
  2341.                                 if ($notyet)
  2342.                                 {
  2343.                                     phpDocumentor_out(" Procedural Page Elements...");
  2344.                                     flush();
  2345.                                     $notyet false;
  2346.                                 }
  2347.                                 $this->Convert($element);
  2348.                             }
  2349.                         }
  2350.                         $this->endPage();
  2351.                         phpDocumentor_out("done\n");
  2352.                         flush();
  2353.                     }
  2354.                 }
  2355.                 $start_classes true;
  2356.                 if (isset($r['class']))
  2357.                 {
  2358.                     foreach($r['class'as $class => $elements)
  2359.                     {
  2360.                         foreach($elements as $element)
  2361.                         {
  2362.                             if ($element->type == 'class')
  2363.                             {
  2364.                                 if (!$start_classes)
  2365.                                 {
  2366.                                     if (count($elements&& !$this->killclass$this->endClass();
  2367.                                     phpDocumentor_out("done\n");
  2368.                                     flush();
  2369.                                 }
  2370.                                 $start_classes false;
  2371.                                 $this->class = $element->getName();
  2372.                                 $this->killclass false;
  2373.                                 if ($this->checkKillClass($element->getName(),$element->getPath())) continue;
  2374.                                 if (!$this->killclass)
  2375.                                 {
  2376.                                     phpDocumentor_out('Converting '.$this->class."...");
  2377.                                     flush();
  2378.                                     $notyet true;
  2379.                                 }
  2380.                             else
  2381.                             {
  2382.                                 if ($notyet)
  2383.                                 {
  2384.                                     phpDocumentor_out("Variables/methods/Class constants...\n");
  2385.                                     flush();
  2386.                                     $notyet false;
  2387.                                 }
  2388.                                 $a $element->docblock->getKeyword('access');
  2389.                                 if (is_object($a)) $a $a->getString();
  2390.                                 if (!$this->parseprivate && ($a == 'private'))
  2391.                                     continue;
  2392.                                 if ($this->killclasscontinue;
  2393.                                 // force all contained elements to have parent package/subpackage
  2394.                                 $element->docblock->package $this->package;
  2395.                                 $element->docblock->subpackage $this->subpackage;
  2396.                             }
  2397.                             if ($this->killclasscontinue;
  2398.                             $this->Convert($element);
  2399.                         }
  2400.                     }
  2401.                     if (count($elements&& !$this->killclass$this->endClass();
  2402.                     phpDocumentor_out("done\n");
  2403.                     flush();
  2404.                 // if isset($r['class'])
  2405.             // foreach($s
  2406.         // foreach($this->package_elements)
  2407.         phpDocumentor_out("\nConverting @todo List...");
  2408.         flush();
  2409.         if (count($this->todoList))
  2410.         {
  2411.             $this->ConvertTodoList();
  2412.         }
  2413.         phpDocumentor_out("done\n");
  2414.         flush();
  2415.         phpDocumentor_out("\nConverting Error Log...");
  2416.         flush();
  2417.         $this->ConvertErrorLog();
  2418.         phpDocumentor_out("done\n");
  2419.         flush();
  2420.     }
  2421.  
  2422.     /**
  2423.      * Convert the phpDocumentor parsing/conversion error log
  2424.      * @abstract
  2425.      */
  2426.     function ConvertErrorLog()
  2427.     {
  2428.     }
  2429.  
  2430.     /**
  2431.      * Convert the list of all @todo tags
  2432.      * @abstract
  2433.      */
  2434.     function ConvertTodoList()
  2435.     {
  2436.     }
  2437.  
  2438.     /**
  2439.      * Sorts the @todo list - do not override or modify this function
  2440.      * @access private
  2441.      * @uses _sortTodos passed to {@link usort()} to sort the todo list
  2442.      */
  2443.     function sortTodos()
  2444.     {
  2445.         phpDocumentor_out("\nSorting @todo list...");
  2446.         flush();
  2447.         foreach($this->todoList as $package => $r{
  2448.             usort($this->todoList[$package]array('Converter''_sortTodoPackage'));
  2449.             foreach ($r as $a => $sub{
  2450.                 if (is_array($this->todoList[$package][$a][1])) {
  2451.                     usort($this->todoList[$package][$a][1],array('Converter''_sortTodos'));
  2452.                 }
  2453.             }
  2454.         }
  2455.         phpDocumentor_out("done\n");
  2456.     }
  2457.  
  2458.     /** @access private */
  2459.     function _sortTodoPackage($a$b)
  2460.     {
  2461.         return strnatcasecmp($a[0]->name$b[0]->name);
  2462.     }
  2463.  
  2464.     /** @access private */
  2465.     function _sortTodos($a$b)
  2466.     {
  2467.         if (!is_object($a)) {
  2468.             var_dump($a);
  2469.         }
  2470.         return strnatcasecmp($a->getString()$b->getString());
  2471.     }
  2472.  
  2473.     /**
  2474.      * Sorts all indexes - do not override or modify this function
  2475.      * @uses $leftindex based on the value of leftindex, sorts link arrays
  2476.      * @uses $class_elements sorts with {@link compareLink}
  2477.      * @uses $page_elements sorts with {@link compareLink}
  2478.      * @uses $define_elements sorts with {@link compareLink}
  2479.      * @uses $global_elements sorts with {@link compareLink}
  2480.      * @uses $function_elements sorts with {@link compareLink}
  2481.      * @uses $elements sorts with {@link elementCmp}
  2482.      * @uses $pkg_elements sorts with {@link elementCmp} after sorting by
  2483.      *                      package/subpackage alphabetically
  2484.      * @access private
  2485.      */
  2486.     function sortIndexes()
  2487.     {
  2488.         phpDocumentor_out("\nSorting Indexes...");
  2489.         flush();
  2490.         uksort($this->elements,'strnatcasecmp');
  2491.         if ($this->leftindex['classes'])
  2492.         {
  2493.             foreach($this->class_elements as $package => $o1)
  2494.             {
  2495.                 foreach($o1 as $subpackage => $links)
  2496.                 {
  2497.                     usort($this->class_elements[$package][$subpackage],array($this,'compareLink'));
  2498.                 }
  2499.             }
  2500.         }
  2501.         if ($this->leftindex['pages'])
  2502.         {
  2503.             foreach($this->page_elements as $package => $o1)
  2504.             {
  2505.                 uksort($this->page_elements[$package],'strnatcasecmp');
  2506.                 foreach($o1 as $subpackage => $links)
  2507.                 {
  2508.                     usort($this->page_elements[$package][$subpackage],array($this,'compareLink'));
  2509.                 }
  2510.             }
  2511.         }
  2512.         if ($this->leftindex['defines'])
  2513.         {
  2514.             foreach($this->define_elements as $package => $o1)
  2515.             {
  2516.                 uksort($this->define_elements[$package],'strnatcasecmp');
  2517.                 foreach($o1 as $subpackage => $links)
  2518.                 {
  2519.                     usort($this->define_elements[$package][$subpackage],array($this,'compareLink'));
  2520.                 }
  2521.             }
  2522.         }
  2523.         if ($this->leftindex['globals'])
  2524.         {
  2525.             foreach($this->global_elements as $package => $o1)
  2526.             {
  2527.                 uksort($this->global_elements[$package],'strnatcasecmp');
  2528.                 foreach($o1 as $subpackage => $links)
  2529.                 {
  2530.                     usort($this->global_elements[$package][$subpackage],array($this,'compareLink'));
  2531.                 }
  2532.             }
  2533.         }
  2534.         if ($this->leftindex['functions'])
  2535.         {
  2536.             foreach($this->function_elements as $package => $o1)
  2537.             {
  2538.                 uksort($this->function_elements[$package],'strnatcasecmp');
  2539.                 foreach($o1 as $subpackage => $links)
  2540.                 {
  2541.                     usort($this->function_elements[$package][$subpackage],array($this,'compareLink'));
  2542.                 }
  2543.             }
  2544.         }
  2545.         foreach($this->elements as $letter => $nothuing)
  2546.         {
  2547.             uasort($this->elements[$letter],array($this,"elementCmp"));
  2548.         }
  2549.         foreach($this->pkg_elements as $package => $els)
  2550.         {
  2551.             uksort($this->pkg_elements[$package],'strnatcasecmp');
  2552.             foreach($this->pkg_elements[$packageas $subpackage => $els)
  2553.             {
  2554.                 if (empty($els)) continue;
  2555.                 uksort($this->pkg_elements[$package][$subpackage],'strnatcasecmp');
  2556.                 foreach($els as $letter => $yuh)
  2557.                 {
  2558.                     usort($this->pkg_elements[$package][$subpackage][$letter],array($this,"elementCmp"));
  2559.                 }
  2560.             }
  2561.         }
  2562.         phpDocumentor_out("done\n");
  2563.         flush();
  2564.     }
  2565.  
  2566.     /**
  2567.      * sorts {@link $page_contents} by element type as well as alphabetically
  2568.      * @see $sort_page_contents_by_element_type
  2569.      */
  2570.     function sortPageContentsByElementType(&$pages)
  2571.     {
  2572.         foreach($this->page_contents as $package => $els)
  2573.         {
  2574.             foreach($this->page_contents[$packageas $subpackage => $els)
  2575.             {
  2576.                 if (empty($els)) continue;
  2577.                 foreach($this->page_contents[$package][$subpackageas $path => $stuff)
  2578.                 {
  2579.                     if (!count($pages[$path]->elements)) continue;
  2580.                     usort($pages[$path]->elements,array($this,'eltypecmp'));
  2581.                     usort($this->page_contents[$package][$subpackage][$path],array($this,'eltypecmp'));
  2582.                     if (isset($this->page_contents[$package][$subpackage][$path][0]))
  2583.                     $this->page_contents[$package][$subpackage][$path]['###main'$this->page_contents[$package][$subpackage][$path][0];
  2584.                     unset($this->page_contents[$package][$subpackage][$path][0]);
  2585.                 }
  2586.             }
  2587.         }
  2588.     }
  2589.  
  2590.     /**
  2591.      * @access private
  2592.      * @see Converter::sortIndexes()
  2593.      */
  2594.     function compareLink($a$b)
  2595.     {
  2596.          return strnatcasecmp($a->name,$b->name);
  2597.     }
  2598.  
  2599.     /**
  2600.      * @access private
  2601.      * @see Converter::sortPageContentsByElementType()
  2602.      */
  2603.     function eltypecmp($a$b)
  2604.     {
  2605.         if ($a->type == 'page'return -1;
  2606.         if ($b->type == 'page'return 1;
  2607.          return strnatcasecmp($a->type.$a->name,$b->type.$b->name);
  2608.     }
  2609.  
  2610.     /**
  2611.      * does a nat case sort on the specified second level value of the array
  2612.      *
  2613.      * @param    mixed    $a 
  2614.      * @param    mixed    $b 
  2615.      * @return    int 
  2616.      * @access private
  2617.      */
  2618.     function elementCmp ($a$b)
  2619.     {
  2620.         return strnatcasecmp($a->getName()$b->getName());
  2621.     }
  2622.  
  2623.     /**
  2624.      * Used to stop conversion of @ignored or private @access classes
  2625.      * @uses $killclass sets killclass based on the value of {@link Classes::$killclass}
  2626.      *        and {@link $package_output}
  2627.      * @access private
  2628.      */
  2629.     function checkKillClass($class$path)
  2630.     {
  2631.         $this->killclass false;
  2632.         if (isset($this->classes->killclass[$class]&& isset($this->classes->killclass[$class][$path])) $this->killclass true;
  2633.         if ($this->package_output)
  2634.         {
  2635.             $a $this->classes->getClass($class$path);
  2636.             if (!in_array($a->docblock->package,$this->package_output)) $this->killclass true;
  2637.         }
  2638.         if (PHPDOCUMENTOR_DEBUG && $this->killclassdebug("$class $path killed");
  2639.         return $this->killclass;
  2640.     }
  2641.  
  2642.     /**
  2643.      * @param abstractLink descendant of abstractLink
  2644.      * @param array|parserTaglist of @todos|@todo tag
  2645.      * @access private
  2646.      */
  2647.     function addTodoLink($link$todos)
  2648.     {
  2649.         $this->todoList[$link->package][array($link$todos);
  2650.     }
  2651.  
  2652.     /**
  2653.      * Adds all elements to the {@link $elements, $pkg_elements, $links},
  2654.      * {@link $linkswithfile} and left indexes - Do not modify or override
  2655.      * @access private
  2656.      * @param parserBase any documentable element descendant of parserBase
  2657.      *                    except parserTutorial
  2658.      * @param false|parserPageonly used to add a {@link parserPage} if the
  2659.      *                          $element passed is a parserPage
  2660.      * @staticvar string path of current page, used for {@link $page_contents} setup
  2661.      */
  2662.     function addElement(&$element,$pageel=false)
  2663.     {
  2664.         static $curpath '';
  2665.         if ($this->package_output)
  2666.         {
  2667.             if (!in_array($this->package$this->package_output)) return;
  2668.         }
  2669.         if ($pageel && phpDocumentor_get_class($pageel== 'parserdata')
  2670.         {
  2671.             if (isset($pageel->docblock&& phpDocumentor_get_class($pageel->docblock== 'parserdocblock')
  2672.             {
  2673.                 $a $pageel->docblock->getKeyword('todo');
  2674.                 if ($a && !empty($a->value[0]))
  2675.                 {
  2676.                     $this->addTodoLink($this->addLink($element),$a);
  2677.                 }
  2678.             }
  2679.         }
  2680.         if (isset($element->docblock))
  2681.         {
  2682.             $a $element->docblock->getKeyword('access');
  2683.             if (is_object($a)) $a $a->getString();
  2684.             if (!$this->parseprivate && ($a == 'private'))
  2685.                 return;
  2686.             $a $element->docblock->getKeyword('todo');
  2687.             if ($a && !empty($a->value[0]))
  2688.             {
  2689.                 if ($element->type != 'include'{
  2690.                     $this->addTodoLink($this->addLink($element),$a);
  2691.                 else {
  2692.                     addWarning(PDERROR_NOTODO_INCLUDE$element->getLineNumber(),
  2693.                         $element->getPath());
  2694.                 }
  2695.             }
  2696.         }
  2697.         $startPositionOfElementName 0;    // which character of the element name actually starts its textual name
  2698.         switch($element->type)
  2699.         {
  2700.             case 'page' :
  2701.                 if ($this->sort_absolutely_everything)
  2702.                 {
  2703.                     $this->package_elements[$element->package][$element->subpackage]['page'][$element->getPath()][$pageel;
  2704.                 }
  2705.                 $link $this->addLink($element);
  2706.                 $curpath $element->getPath();
  2707.                 if ($this->leftindex['pages'])
  2708.                 $this->page_elements[$element->package][$element->subpackage][$link;
  2709.                 $this->page_contents[$element->package][$element->subpackage][$curpath]['###main'$link;
  2710.             break;
  2711.             case 'class' :
  2712.                 if ($this->sort_absolutely_everything)
  2713.                 {
  2714.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][$element;
  2715.                 }
  2716.                 $link $this->addLink($element);
  2717.                 if ($this->leftindex['classes'])
  2718.                 $this->class_elements[$element->docblock->package][$element->docblock->subpackage][$link;
  2719.                 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class]['###main'$link;
  2720.             break;
  2721.             case 'include' :
  2722.                 if ($this->sort_absolutely_everything)
  2723.                 {
  2724.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][$element;
  2725.                 }
  2726.                 $link $this->addLink($element);
  2727.             break;
  2728.             case 'define' :
  2729.                 if ($this->sort_absolutely_everything)
  2730.                 {
  2731.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][$element;
  2732.                 }
  2733.                 $link $this->addLink($element);
  2734.                 if ($this->leftindex['defines'])
  2735.                 $this->define_elements[$element->docblock->package][$element->docblock->subpackage][$link;
  2736.                 $this->page_contents[$element->docblock->package][$element->docblock->subpackage][$curpath][$link;
  2737.             break;
  2738.             case 'global' :
  2739.                 if ($this->sort_absolutely_everything)
  2740.                 {
  2741.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][$element;
  2742.                 }
  2743.                 $link $this->addLink($element);
  2744.                 $startPositionOfElementName 1;    // lose the leading "$" character
  2745.                 if ($this->leftindex['globals'])
  2746.                 $this->global_elements[$element->docblock->package][$element->docblock->subpackage][$link;
  2747.                 $this->page_contents[$element->docblock->package][$element->docblock->subpackage][$curpath][$link;
  2748.             break;
  2749.             case 'var' :
  2750.                 if ($this->sort_absolutely_everything)
  2751.                 {
  2752.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][$element;
  2753.                 }
  2754.                 $link $this->addLink($element);
  2755.                 $startPositionOfElementName 1;    // lose the leading "$" character
  2756.                 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class][$link;
  2757.             break;
  2758.             case 'const' :
  2759.                 if ($this->sort_absolutely_everything)
  2760.                 {
  2761.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][$element;
  2762.                 }
  2763.                 $link $this->addLink($element);
  2764.                 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class][$link;
  2765.             break;
  2766.             case 'method' :
  2767.                 if ($this->sort_absolutely_everything)
  2768.                 {
  2769.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['class'][$this->class][$element;
  2770.                 }
  2771.                 $link $this->addLink($element);
  2772.                 $this->class_contents[$element->docblock->package][$element->docblock->subpackage][$this->class][$link;
  2773.             break;
  2774.             case 'function' :
  2775.                 if ($this->sort_absolutely_everything)
  2776.                 {
  2777.                     $this->package_elements[$element->docblock->package][$element->docblock->subpackage]['page'][$curpath][$element;
  2778.                 }
  2779.                 $link $this->addLink($element);
  2780.                 if ($this->leftindex['functions'])
  2781.                 $this->function_elements[$element->docblock->package][$element->docblock->subpackage][$link;
  2782.                 $this->page_contents[$element->docblock->package][$element->docblock->subpackage][$curpath][$link;
  2783.             break;
  2784.             default :
  2785.             break;
  2786.         }
  2787.         if ($element->getType(!= 'include')
  2788.         {
  2789.             if ($element->getType(== 'var' || $element->getType(== 'method'|| $element->getType(== 'const')
  2790.             {
  2791.                 $this->links[$this->package][$this->subpackage][$element->getType()][$element->class][$element->getName()$link;
  2792.                 $this->linkswithfile[$this->package][$this->subpackage][$element->getType()][$element->getPath()][$element->class][$element->getName()$link;
  2793.             else
  2794.             {
  2795.                 if ($element->type == 'page')
  2796.                 {
  2797.                     $this->links[$this->package][$this->subpackage][$element->getType()][$element->getFile()$link;
  2798.                     $this->linkswithfile[$this->package][$this->subpackage][$element->getType()][$element->getPath()][$element->getFile()$link;
  2799.                 else
  2800.                 {
  2801.                     $this->links[$this->package][$this->subpackage][$element->getType()][$element->getName()$link;
  2802.                     $this->linkswithfile[$this->package][$this->subpackage][$element->getType()][$element->getPath()][$element->getName()$link;
  2803.                 }
  2804.             }
  2805.         }
  2806.         if ($element->type == 'page')
  2807.         {
  2808.             $this->elements[substr(strtolower($element->getFile()),$startPositionOfElementName,1)][$element;
  2809.             $this->pkg_elements[$this->package][$this->subpackage][substr(strtolower($element->getFile()),$startPositionOfElementName,1)][$element;
  2810.         else
  2811.         {
  2812.             $this->elements[substr(strtolower($element->getName()),$startPositionOfElementName,1)][$element;
  2813.             $this->pkg_elements[$this->package][$this->subpackage][substr(strtolower($element->getName()),$startPositionOfElementName,1)][$element;
  2814.         }
  2815.     }
  2816.  
  2817.     /**
  2818.      * returns an abstract link to element.  Do not modify or override
  2819.      *
  2820.      * This method should only be called in process of Conversion, unless
  2821.      * $element is a parserPage, or $page is set to true, and $element is
  2822.      * not a parserPage
  2823.      * @return abstractLink abstractLink descendant
  2824.      * @access private
  2825.      * @param parserElement element to add a new link (descended from
  2826.      *                       {@link abstractLink})to the {@link $links} array
  2827.      * @param string classname for elements that are class-based (this may be
  2828.      *                deprecated in the future, as the classname
  2829.      *                should be contained within the element.  if $element is a
  2830.      *                page, this parameter is a package name
  2831.      * @param string subpackage name for page elements
  2832.      */
  2833.     function addLink(&$element,$page false)
  2834.     {
  2835.         if ($page)
  2836.         {
  2837.             // create a fake parserPage to extract the fileAlias for this link
  2838.             $fakepage new parserPage;
  2839.             $fakepage->setPath($element->getPath());
  2840.             $fakepage->setFile(basename($element->getPath()));
  2841.             $this->curname $this->getPageName($fakepage);
  2842.         }
  2843.         switch($element->type)
  2844.         {
  2845.             case 'function':
  2846.                 $x new functionLink;
  2847.                 $x->addLink($element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2848.                 return $x;
  2849.             break;
  2850.             case 'define':
  2851.                 $x new defineLink;
  2852.                 $x->addLink($element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2853.                 return $x;
  2854.             break;
  2855.             case 'global':
  2856.                 $x new globalLink;
  2857.                 $x->addLink($element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2858.                 return $x;
  2859.             break;
  2860.             case 'class':
  2861.                 $x new classLink;
  2862.                 $x->addLink($element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2863.                 return $x;
  2864.             break;
  2865.             case 'method':
  2866.                 $x new methodLink;
  2867.                 $x->addLink($this->class$element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2868.                 return $x;
  2869.             break;
  2870.             case 'var':
  2871.                 $x new varLink;
  2872.                 $x->addLink($this->class$element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2873.                 return $x;
  2874.             break;
  2875.             case 'const':
  2876.                 $x new constLink;
  2877.                 $x->addLink($this->class$element->getPath()$this->curname$element->name$element->docblock->package$element->docblock->subpackage$element->docblock->category);
  2878.                 return $x;
  2879.             break;
  2880.             case 'page':
  2881.                 $x new pageLink;
  2882.                 $x->addLink($element->getPath(),$this->getPageName($element),$element->file,$element->package$element->subpackage$element->category);
  2883.                 return $x;
  2884.             break;
  2885.         }
  2886.     }
  2887.  
  2888.     /**
  2889.      * Return a tree of all classes that extend this class
  2890.      *
  2891.      * The data structure returned is designed for a non-recursive algorithm,
  2892.      * and is somewhat complex.
  2893.      * In most cases, the array returned is:
  2894.      *
  2895.      * <pre>
  2896.      * array('#root' =>
  2897.      *         array('link' => {@link classLink} to $class,
  2898.      *               'parent' => false,
  2899.      *               'children' => array(array('class' => 'childclass1',
  2900.      *                                         'package' => 'child1package'),
  2901.      *                                    array('class' => 'childclass2',
  2902.      *                                         'package' => 'child2package'),...
  2903.      *                                  )
  2904.      *               ),
  2905.      *       'child1package#childclass1' =>
  2906.      *         array('link' => {@link classLink} to childclass1,
  2907.      *               'parent' => '#root',
  2908.      *               'children' => array(array('class' => 'kidclass',
  2909.      *                                         'package' => 'kidpackage'),...
  2910.      *                                  )
  2911.      *              ),
  2912.      *       'kidpackage#kidclass' =>
  2913.      *         array('link' => {@link classLink} to kidclass,
  2914.      *               'parent' => 'child1package#childclass1',
  2915.      *               'children' => array() // no children
  2916.      *              ),
  2917.      *      ....
  2918.      *      )
  2919.      *</pre>
  2920.      *
  2921.      * To describe this format using language, every class in the tree has an
  2922.      * entry in the first level of the array.  The index for all child
  2923.      * classes that extend the root class is childpackage#childclassname.
  2924.      * Each entry in the array has 3 elements: link, parent, and children.
  2925.      * <ul>
  2926.      *  <li>link - a {@link classLink} to the current class</li>
  2927.      *  <li>parent - a {@link classLink} to the class's parent, or false (except for one special case described below)</li>
  2928.      *  <li>children - an array of arrays, each entry has a 'class' and 'package' index to the child class,
  2929.      * used to find the entry in the big array</li>
  2930.      * </ul>
  2931.      *
  2932.      * special cases are when the #root class has a parent in another package,
  2933.      * or when the #root class extends a class not found
  2934.      * by phpDocumentor.  In the first case, parent will be a
  2935.      * classLink to the parent class.  In the second, parent will be the
  2936.      * extends clause, as in:
  2937.      * <code>
  2938.      * class X extends Y
  2939.      * {
  2940.      * ...
  2941.      * }
  2942.      * </code>
  2943.      * in this case, the #root entry will be array('link' => classLink to X, 'parent' => 'Y', children => array(...))
  2944.      *
  2945.      * The fastest way to design a method to process the array returned
  2946.      * is to copy HTMLframesConverter::getRootTree() into
  2947.      * your converter and to modify the html to whatever output format you are going to use
  2948.      * @see HTMLframesConverter::getRootTree()
  2949.      * @param string class name
  2950.      * @param string 
  2951.      * @param string 
  2952.      * @return array Format: see docs
  2953.      */
  2954.     function getSortedClassTreeFromClass($class,$package,$subpackage)
  2955.     {
  2956.         $my_tree array();
  2957.         $root $this->classes->getClassByPackage($class,$package);
  2958.         if (!$rootreturn false;
  2959.         $class_children $this->classes->getDefiniteChildren($class,$root->curfile);
  2960.         if (!$class_children)
  2961.         {
  2962.             // special case: parent class is found, but is not part of this package, class has no children
  2963.             if (is_array($root->parent))
  2964.             {
  2965.                 $x $root->getParent($this);
  2966.                 if ($x->docblock->package != $package)
  2967.                 {
  2968.                     $v Converter::getClassLink($root->getName(),$package,$root->getPath());
  2969.                     return array('#root' => array('link' => $v,'parent' => Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath())'children' => array()));
  2970.                 }
  2971.             else
  2972.             // class has normal situation, no children
  2973.                 if (is_string($root->getParent($this)))
  2974.                 return array('#root' => array('link' => Converter::getClassLink($root->getName(),$package,$root->getPath())'parent' => $root->getExtends(),'children' => array()));
  2975.                 else
  2976.                 return array('#root' => array('link' => Converter::getClassLink($root->getName(),$package,$root->getPath())'parent' => false'children' => array()));
  2977.             }
  2978.         }
  2979.         // special case: parent class is found, but is not part of this package, class has children
  2980.         if (is_array($root->parent))
  2981.         {
  2982.             $x $root->getParent($this);
  2983.             if ($x->docblock->package != $package)
  2984.             {
  2985.                 $v Converter::getClassLink($root->getName(),$package,$root->getPath());
  2986.                 $my_tree array('#root' => array('link' => $v'parent' => Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath())'children' => array()));
  2987.             else
  2988.             {
  2989.             }
  2990.         else
  2991.         $my_tree array('#root' => array('link' => Converter::getClassLink($root->getName(),$package,$root->getPath())'parent' => false'children' => array()));
  2992.         // location of tree walker
  2993.         $cur '#root';
  2994.         $lastcur array(array(false,0));
  2995.         $childpos 0;
  2996.         if (isset($class_children))
  2997.         {
  2998.             do
  2999.             {
  3000.                 if (!$class_children)
  3001.                 {
  3002.                     list($cur$childposarray_pop($lastcur);
  3003.                     if (isset($my_tree[$cur]['children'][$childpos 1]))
  3004.                     {
  3005.                         array_push($lastcurarray($cur$childpos 1));
  3006.                         $par $cur;
  3007.                         $cur $my_tree[$cur]['children'][$childpos 1];
  3008.                         $x $this->classes->getClassByPackage($cur['class'],$cur['package']);
  3009.                         $childpos 0;
  3010.                         $cur $cur['package''#' $cur['class'];
  3011.                         $my_tree[$cur]['link'Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath());
  3012.                         $my_tree[$cur]['parent'$par;
  3013.                         $my_tree[$cur]['children'array();
  3014.                         $class_children $this->classes->getDefiniteChildren($x->getName()$x->curfile);
  3015.                         continue;
  3016.                     else
  3017.                     {
  3018.                         $class_children false;
  3019.                         continue;
  3020.                     }
  3021.                 }
  3022.                 foreach($class_children as $chileclass => $chilefile)
  3023.                 {
  3024.                     $ch $this->classes->getClass($chileclass,$chilefile);
  3025.                     $my_tree[$cur]['children'][array('class' => $ch->getName()'package' => $ch->docblock->package);
  3026.                 }
  3027.                 usort($my_tree[$cur]['children'],'rootcmp');
  3028.                 if (isset($my_tree[$cur]['children'][$childpos]))
  3029.                 {
  3030.                     array_push($lastcurarray($cur$childpos));
  3031.                     $par $cur;
  3032.                     $cur $my_tree[$cur]['children'][$childpos];
  3033.                     $x $this->classes->getClassByPackage($cur['class'],$cur['package']);
  3034.                     $cur $cur['package''#' $cur['class'];
  3035.                     $my_tree[$cur]['link'Converter::getClassLink($x->getName(),$x->docblock->package,$x->getPath());
  3036.                     $my_tree[$cur]['parent'$par;
  3037.                     $my_tree[$cur]['children'array();
  3038.                     $childpos 0;
  3039.                     $class_children $this->classes->getDefiniteChildren($x->getName()$x->curfile);
  3040.                 else
  3041.                 {
  3042.                     list($cur$childposarray_pop($lastcur);
  3043.                 }
  3044.             while ($cur);
  3045.         }
  3046.         return $my_tree;
  3047.     }
  3048.  
  3049.     /**
  3050.      * do not override
  3051.      * @return bool true if a link to this class exists in package $package and subpackage $subpackage
  3052.      * @param string $expr class name
  3053.      * @param string $package package to search in
  3054.      * @param string $subpackage subpackage to search in
  3055.      * @access private
  3056.      */
  3057.     function isLinkedClass($expr,$package,$subpackage,$file=false)
  3058.     {
  3059.         if ($file)
  3060.         return isset($this->linkswithfile[$package][$subpackage]['class'][$file][$expr]);
  3061.         return isset($this->links[$package][$subpackage]['class'][$expr]);
  3062.     }
  3063.  
  3064.     /**
  3065.      * do not override
  3066.      * @return bool true if a link to this function exists in package $package and subpackage $subpackage
  3067.      * @param string $expr function name
  3068.      * @param string $package package to search in
  3069.      * @param string $subpackage subpackage to search in
  3070.      * @access private
  3071.      */
  3072.     function isLinkedFunction($expr,$package,$subpackage,$file=false)
  3073.     {
  3074.         if ($file)
  3075.         return isset($this->linkswithfile[$package][$subpackage]['function'][$file][$expr]);
  3076.         return isset($this->links[$package][$subpackage]['function'][$expr]);
  3077.     }
  3078.  
  3079.     /**
  3080.      * do not override
  3081.      * @return bool true if a link to this define exists in package $package and subpackage $subpackage
  3082.      * @param string $expr define name
  3083.      * @param string $package package to search in
  3084.      * @param string $subpackage subpackage to search in
  3085.      * @access private
  3086.      */
  3087.     function isLinkedDefine($expr,$package,$subpackage,$file=false)
  3088.     {
  3089.         if ($file)
  3090.         return isset($this->linkswithfile[$package][$subpackage]['define'][$file][$expr]);
  3091.         return isset($this->links[$package][$subpackage]['define'][$expr]);
  3092.     }
  3093.  
  3094.     /**
  3095.      * do not override
  3096.      * @return bool true if a link to this define exists in package $package and subpackage $subpackage
  3097.      * @param string $expr define name
  3098.      * @param string $package package to search in
  3099.      * @param string $subpackage subpackage to search in
  3100.      * @access private
  3101.      */
  3102.     function isLinkedGlobal($expr,$package,$subpackage,$file=false)
  3103.     {
  3104.         if ($file)
  3105.         return isset($this->linkswithfile[$package][$subpackage]['global'][$file][$expr]);
  3106.         return isset($this->links[$package][$subpackage]['global'][$expr]);
  3107.     }
  3108.  
  3109.     /**
  3110.      * do not override
  3111.      * @return bool true if a link to this procedural page exists in package $package and subpackage $subpackage
  3112.      * @param string $expr procedural page name
  3113.      * @param string $package package to search in
  3114.      * @param string $subpackage subpackage to search in
  3115.      * @access private
  3116.      */
  3117.     function isLinkedPage($expr,$package,$subpackage,$path=false)
  3118.     {
  3119.         if ($path)
  3120.         return isset($this->linkswithfile[$package][$subpackage]['page'][$path][$expr]);
  3121.         return isset($this->links[$package][$subpackage]['page'][$expr]);
  3122.     }
  3123.  
  3124.     /**
  3125.      * do not override
  3126.      * @return bool true if a link to this method exists in package $package, subpackage $subpackage and class $class
  3127.      * @param string $expr method name
  3128.      * @param string $class class name
  3129.      * @param string $package package to search in
  3130.      * @param string $subpackage subpackage to search in
  3131.      * @access private
  3132.      */
  3133.     function isLinkedMethod($expr,$package,$subpackage,$class,$file=false)
  3134.     {
  3135.         if ($file)
  3136.         return isset($this->linkswithfile[$package][$subpackage]['method'][$file][$class][$expr]);
  3137.         return isset($this->links[$package][$subpackage]['method'][$class][$expr]);
  3138.     }
  3139.  
  3140.     /**
  3141.      * do not override
  3142.      * @return bool true if a link to this method exists in package $package, subpackage $subpackage and class $class
  3143.      * @param string $expr var name
  3144.      * @param string $class class name
  3145.      * @param string $package package to search in
  3146.      * @param string $subpackage subpackage to search in
  3147.      * @access private
  3148.      */
  3149.     function isLinkedVar($expr,$package,$subpackage,$class,$file=false)
  3150.     {
  3151.         if ($file)
  3152.         return isset($this->linkswithfile[$package][$subpackage]['var'][$file][$class][$expr]);
  3153.         return isset($this->links[$package][$subpackage]['var'][$class][$expr]);
  3154.     }
  3155.  
  3156.     /**
  3157.      * do not override
  3158.      * @return bool true if a link to this method exists in package $package, subpackage $subpackage and class $class
  3159.      * @param string $expr constant name
  3160.      * @param string $class class name
  3161.      * @param string $package package to search in
  3162.      * @param string $subpackage subpackage to search in
  3163.      * @access private
  3164.      */
  3165.     function isLinkedConst($expr,$package,$subpackage,$class,$file=false)
  3166.     {
  3167.         if ($file)
  3168.         return isset($this->linkswithfile[$package][$subpackage]['const'][$file][$class][$expr]);
  3169.         return isset($this->links[$package][$subpackage]['const'][$class][$expr]);
  3170.     }
  3171.  
  3172.     /**
  3173.      * return false or a {@link classLink} to $expr
  3174.      * @param string $expr class name
  3175.      * @param string $package package name
  3176.      * @return mixed returns a {@link classLink} or false if the element is not found in package $package
  3177.      * @see classLink
  3178.      */
  3179.     function getClassLink($expr,$package,$file=false$text false)
  3180.     {
  3181.         if (!isset($this->links[$package])) return false;
  3182.         foreach($this->links[$packageas $subpackage => $notused)
  3183.         {
  3184.             if ($this->isLinkedClass($expr,$package,$subpackage,$file))
  3185.             {
  3186.                 if ($file)
  3187.                 {
  3188.                     return $this->linkswithfile[$package][$subpackage]['class'][$file][$expr];
  3189.                 }
  3190.                 return $this->links[$package][$subpackage]['class'][$expr];
  3191.             }
  3192.         }
  3193.         return false;
  3194.     }
  3195.  
  3196.     /**
  3197.      * return false or a {@link functionLink} to $expr
  3198.      * @param string $expr function name
  3199.      * @param string $package package name
  3200.      * @return mixed returns a {@link functionLink} or false if the element is not found in package $package
  3201.      * @see functionLink
  3202.      */
  3203.     function getFunctionLink($expr,$package,$file=false$text false)
  3204.     {
  3205.         if (!isset($this->links[$package])) return false;
  3206.         foreach($this->links[$packageas $subpackage => $notused)
  3207.         {
  3208.             if ($this->isLinkedFunction($expr,$package,$subpackage,$file))
  3209.             {
  3210.                 if ($file)
  3211.                 {
  3212.                     return $this->linkswithfile[$package][$subpackage]['function'][$file][$expr];
  3213.                 }
  3214.                 return $this->links[$package][$subpackage]['function'][$expr];
  3215.             }
  3216.         }
  3217.         return false;
  3218.     }
  3219.  
  3220.     /**
  3221.      * return false or a {@link defineLink} to $expr
  3222.      * @param string $expr constant name
  3223.      * @param string $package package name
  3224.      * @return mixed returns a {@link defineLink} or false if the element is not found in package $package
  3225.      * @see defineLink
  3226.      */
  3227.     function getDefineLink($expr,$package,$file=false$text false)
  3228.     {
  3229.         if (!isset($this->links[$package])) return false;
  3230.         foreach($this->links[$packageas $subpackage => $notused)
  3231.         {
  3232.             if ($this->isLinkedDefine($expr,$package,$subpackage,$file))
  3233.             {
  3234.                 if ($file)
  3235.                 {
  3236.                     return $this->linkswithfile[$package][$subpackage]['define'][$file][$expr];
  3237.                 }
  3238.                 return $this->links[$package][$subpackage]['define'][$expr];
  3239.             }
  3240.         }
  3241.         return false;
  3242.     }
  3243.  
  3244.     /**
  3245.      * return false or a {@link globalLink} to $expr
  3246.      * @param string $expr global variable name (with leading $)
  3247.      * @param string $package package name
  3248.      * @return mixed returns a {@link defineLink} or false if the element is not found in package $package
  3249.      * @see defineLink
  3250.      */
  3251.     function getGlobalLink($expr,$package,$file=false$text false)
  3252.     {
  3253.         if (!isset($this->links[$package])) return false;
  3254.         foreach($this->links[$packageas $subpackage => $notused)
  3255.         {
  3256.             if ($this->isLinkedGlobal($expr,$package,$subpackage,$file))
  3257.             {
  3258.                 if ($file)
  3259.                 {
  3260.                     return $this->linkswithfile[$package][$subpackage]['global'][$file][$expr];
  3261.                 }
  3262.                 return $this->links[$package][$subpackage]['global'][$expr];
  3263.             }
  3264.         }
  3265.         return false;
  3266.     }
  3267.  
  3268.     /**
  3269.      * return false or a {@link pageLink} to $expr
  3270.      * @param string $expr procedural page name
  3271.      * @param string $package package name
  3272.      * @return mixed returns a {@link pageLink} or false if the element is not found in package $package
  3273.      * @see pageLink
  3274.      */
  3275.     function getPageLink($expr,$package,$path false$text false$packages false)
  3276.     {
  3277.         if (!isset($this->links[$package])) return false;
  3278.         foreach($this->links[$packageas $subpackage => $notused)
  3279.         {
  3280.             if ($this->isLinkedPage($expr,$package,$subpackage,$path))
  3281.             {
  3282.                 if ($path)
  3283.                 {
  3284.                     return $this->linkswithfile[$package][$subpackage]['page'][$path][$expr];
  3285.                 }
  3286.                 return $this->links[$package][$subpackage]['page'][$expr];
  3287.             }
  3288.         }
  3289.         return false;
  3290.     }
  3291.  
  3292.     /**
  3293.      * return false or a {@link methodLink} to $expr in $class
  3294.      * @param string $expr method name
  3295.      * @param string $class class name
  3296.      * @param string $package package name
  3297.      * @return mixed returns a {@link methodLink} or false if the element is not found in package $package, class $class
  3298.      * @see methodLink
  3299.      */
  3300.     function getMethodLink($expr,$class,$package,$file=false$text false)
  3301.     {
  3302.         $expr trim($expr);
  3303.         $class trim($class);
  3304.         if (!isset($this->links[$package])) return false;
  3305.         foreach($this->links[$packageas $subpackage => $notused)
  3306.         {
  3307.             if ($this->isLinkedMethod($expr,$package,$subpackage,$class,$file))
  3308.             {
  3309.                 if ($file)
  3310.                 {
  3311.                     return $this->linkswithfile[$package][$subpackage]['method'][$file][$class][$expr];
  3312.                 }
  3313.                 return $this->links[$package][$subpackage]['method'][$class][$expr];
  3314.             }
  3315.         }
  3316.         return false;
  3317.     }
  3318.  
  3319.     /**
  3320.      * return false or a {@link varLink} to $expr in $class
  3321.      * @param string $expr var name
  3322.      * @param string $class class name
  3323.      * @param string $package package name
  3324.      * @return mixed returns a {@link varLink} or false if the element is not found in package $package, class $class
  3325.      * @see varLink
  3326.      */
  3327.     function getVarLink($expr,$class,$package,$file=false$text false)
  3328.     {
  3329.         $expr trim($expr);
  3330.         $class trim($class);
  3331.         if (!isset($this->links[$package])) return false;
  3332.         foreach($this->links[$packageas $subpackage => $notused)
  3333.         {
  3334.             if ($this->isLinkedVar($expr,$package,$subpackage,$class,$file))
  3335.             {
  3336.                 if ($file)
  3337.                 {
  3338.                     return $this->linkswithfile[$package][$subpackage]['var'][$file][$class][$expr];
  3339.                 }
  3340.                 return $this->links[$package][$subpackage]['var'][$class][$expr];
  3341.             }
  3342.         }
  3343.         return false;
  3344.     }
  3345.  
  3346.     /**
  3347.      * return false or a {@link constLink} to $expr in $class
  3348.      * @param string $expr constant name
  3349.      * @param string $class class name
  3350.      * @param string $package package name
  3351.      * @return mixed returns a {@link varLink} or false if the element is not found in package $package, class $class
  3352.      * @see constLink
  3353.      */
  3354.     function getConstLink($expr,$class,$package,$file=false$text false)
  3355.     {
  3356.         $expr trim($expr);
  3357.         $class trim($class);
  3358.         if (!isset($this->links[$package])) return false;
  3359.         foreach($this->links[$packageas $subpackage => $notused)
  3360.         {
  3361.             if ($this->isLinkedConst($expr,$package,$subpackage,$class,$file))
  3362.             {
  3363.                 if ($file)
  3364.                 {
  3365.                     return $this->linkswithfile[$package][$subpackage]['const'][$file][$class][$expr];
  3366.                 }
  3367.                 return $this->links[$package][$subpackage]['const'][$class][$expr];
  3368.             }
  3369.         }
  3370.         return false;
  3371.     }
  3372.  
  3373.     /**
  3374.      * The meat of the @tutorial tag and inline {@}tutorial} tag
  3375.      *
  3376.      * Take a string and return an abstract link to the tutorial it represents.
  3377.      * Since tutorial naming literally works like the underlying filesystem, the
  3378.      * way to reference the tutorial is similar.  Tutorials are located in a
  3379.      * subdirectory of any directory parsed, which is named 'tutorials/' (we
  3380.      * try to make things simple when we can :).  They are further organized by
  3381.      * package and subpackage as:
  3382.      *
  3383.      * tutorials/package/subpackage
  3384.      *
  3385.      * and the files are named *.cls, *.pkg, or *.proc, and so a link to a tutorial
  3386.      * named file.cls can be referenced (depending on context) as any of:
  3387.      *
  3388.      * <code>
  3389.      * * @tutorial package/subpackage/file.cls
  3390.      * * @tutorial package/file.cls
  3391.      * * @tutorial file.cls
  3392.      * </code>
  3393.      *
  3394.      * The first case will only be needed if file.cls exists in both the current
  3395.      * package, in anotherpackage/file.cls and in anotherpackage/subpackage/file.cls
  3396.      * and you wish to reference the one in anotherpackage/subpackage.
  3397.      * The second case is only needed if you wish to reference file.cls in another
  3398.      * package and it is unique in that package. the third will link to the first
  3399.      * file.cls it finds using this search method:
  3400.      *
  3401.      * <ol>
  3402.      *    <li>current package/subpackage</li>
  3403.      *    <li>all other subpackages of current package</li>
  3404.      *    <li>parent package, if this package has classes that extend classes in
  3405.      *    another package</li>
  3406.      *    <li>all other packages</li>
  3407.      * </ol>
  3408.      * @return tutorialLink|stringreturns either a link, or the original text, if not found
  3409.      * @param string the original expression
  3410.      * @param string package to look in first
  3411.      * @param string subpackage to look in first
  3412.      * @param array array of package names to search in if not found in parent packages.
  3413.      *               This is used to limit the search, phpDocumentor automatically searches
  3414.      *               all packages
  3415.      * @since 1.2
  3416.      */
  3417.     function getTutorialLink($expr$package false$subpackage false$packages false)
  3418.     {
  3419.         // is $expr a comma-delimited list?
  3420.         if (strpos($expr,','))
  3421.         {
  3422.             $a explode(',',$expr);
  3423.             $b array();
  3424.             for($i=0;$i<count($a);$i++)
  3425.             {
  3426.                 // if so return each component with a link
  3427.                 $b[Converter::getTutorialLink(trim($a[$i]));
  3428.             }
  3429.             return $b;
  3430.         }
  3431.         $subsection '';
  3432.         if (strpos($expr,'#'))
  3433.         {
  3434.             $a explode('#',$expr);
  3435.             $org $expr;
  3436.             $expr $a[0];
  3437.             $subsection $a[1];
  3438.         }
  3439.         if (strpos($expr,'/'))
  3440.         {
  3441.             $a explode('/',$expr);
  3442.             if (count($a== 3)
  3443.             {
  3444.                 return Converter::getTutorialLink($a[2],$a[0],$a[1],array());
  3445.             }
  3446.             if (count($a== 2)
  3447.             {
  3448.                 return Converter::getTutorialLink($a[1],$a[0],false,array());
  3449.             }
  3450.         }
  3451.         if (!$package$package $this->package;
  3452.         if (!$subpackage$subpackage $this->subpackage;
  3453.         if (!isset($this->all_packages[$package])) return $expr;
  3454.         elseif (isset($packages[$package])) unset($packages[$package]);
  3455.         $ext pathinfo($exprPATHINFO_EXTENSION);
  3456.         if (isset($this->tutorials[$package][$subpackage][$ext][$expr]))
  3457.         {
  3458.             $a $this->tutorials[$package][$subpackage][$ext][$expr];
  3459.             $link new tutorialLink;
  3460.             $link->addLink($subsection,$a->path,$a->name,$a->package,$a->subpackage,$a->getTitle($this,$subsection));
  3461.             return $link;
  3462.         }
  3463.         do
  3464.         {
  3465.             if (!is_array($packages))
  3466.             {
  3467.                 $packages $this->all_packages;
  3468.                 if (isset($packages[$package])) unset($packages[$package]);
  3469.             }
  3470.             if (isset($this->tutorials[$package]))
  3471.             {
  3472.                 if (isset($this->tutorials[$package][$subpackage][$ext][$expr]))
  3473.                 {
  3474.                     $a $this->tutorials[$package][$subpackage][$ext][$expr];
  3475.                     $link new tutorialLink;
  3476.                     $link->addLink($subsection,$a->path,$a->name,$a->package,$a->subpackage,$a->getTitle($this));
  3477.                     return $link;
  3478.                 else
  3479.                 {
  3480.                     foreach($this->tutorials[$packageas $subpackage => $stuff)
  3481.                     {
  3482.                         if (isset($stuff[$ext][$expr]))
  3483.                         {
  3484.                             $a $stuff[$ext][$expr];
  3485.                             $link new tutorialLink;
  3486.                             $link->addLink($subsection,$a->path,$a->name,$a->package,$a->subpackage,$a->getTitle($this));
  3487.                             return $link;
  3488.                         }
  3489.                     }
  3490.                 }
  3491.             }
  3492.             // try other packages
  3493.             // look in parent package first, if found
  3494.             if (isset($this->package_parents[$package]))
  3495.             {
  3496.                 $p1 $package;
  3497.                 $package $this->package_parents[$package];
  3498.             else
  3499.             {
  3500.                 // no parent package, so start with the first one that's left
  3501.                 list($package,@each($packages);
  3502.             }
  3503.             if ($package)
  3504.             {
  3505.                 if (isset($packages[$package])) unset($packages[$package]);
  3506.             }
  3507.         while (count($packages|| $package);
  3508.         addWarning(PDERROR_TUTORIAL_NOT_FOUND,$expr);
  3509.         return $expr;
  3510.     }
  3511.  
  3512.     /**
  3513.      * The meat of the @see tag and inline {@}link} tag
  3514.      *
  3515.      * $expr is a string with many allowable formats:
  3516.      * <ol>
  3517.      *  <li>proceduralpagename.ext</li>
  3518.      *  <li>constant_name</li>
  3519.      *  <li>classname::function()</li>
  3520.      *  <li>classname::constantname</li> (new 1.2.4)
  3521.      *  <li>classname::$variablename</li>
  3522.      *  <li>classname</li>
  3523.      *  <li>object classname</li>
  3524.      *  <li>function functionname()</li>
  3525.      *  <li>global $globalvarname</li>
  3526.      *  <li>packagename#expr where expr is any of the above</li>
  3527.      * </ol>
  3528.      *
  3529.      * New in version 1.1, you can explicitly specify a package to link to that
  3530.      * is different from the current package.  Use the # operator
  3531.      * to specify a new package, as in tests#bug-540368.php (which should appear
  3532.      * as a link like: "{@link tests#bug-540368.php}").  This
  3533.      * example links to the procedural page bug-540368.php in package
  3534.      * tests.  Also, the "function" operator is now used to specifically
  3535.      * link to a function instead of a method in the current class.
  3536.      *
  3537.      * <code>
  3538.      * class myclass
  3539.      * {
  3540.      *  // from inside the class definition, use "function conflict()" to refer to procedural function "conflict()"
  3541.      *    function conflict()
  3542.      *    {
  3543.      *    }
  3544.      * }
  3545.      *
  3546.      * function conflict()
  3547.      * {
  3548.      * }
  3549.      * </code>
  3550.      *
  3551.      * If classname:: is not present, and the see tag is in a documentation
  3552.      * block within a class, then the function uses the classname to
  3553.      * search for $expr as a function or variable within classname, or any of its parent classes.
  3554.      * given an $expr without '$', '::' or '()' getLink first searches for
  3555.      * classes, procedural pages, constants, global variables, and then searches for
  3556.      * methods and variables within the default class, and finally for any function
  3557.      *
  3558.      * @param string $expr expression to search for a link
  3559.      * @param string $package package to start searching in
  3560.      * @param array $packages list of all packages to search in
  3561.      * @return mixed getLink returns a descendant of {@link abstractLink} if it finds a link, otherwise it returns a string
  3562.      * @see getPageLink(), getDefineLink(), getVarLink(), getFunctionLink(), getClassLink()
  3563.      * @see pageLink, functionLink, defineLink, classLink, methodLink, varLink
  3564.      */
  3565.     function &getLink($expr$package false$packages false)
  3566.     {
  3567.         // is $expr a comma-delimited list?
  3568.         if (strpos($expr,','))
  3569.         {
  3570.             $a explode(',',$expr);
  3571.             $b array();
  3572.             for($i=0;$i<count($a);$i++)
  3573.             {
  3574.                 // if so return each component with a link
  3575.                 $b[Converter::getLink(trim($a[$i]));
  3576.             }
  3577.             return $b;
  3578.         }
  3579.         if (strpos($expr,'#'))
  3580.         {
  3581.             $a explode('#',$expr);
  3582.             if (count($a== 2)
  3583.             // can have exactly 1 package override, otherwise it's ignored
  3584.                 // feature 564991, link to php manual
  3585.                 if ($a[0== 'PHP_MANUAL'{
  3586.                     $s 'http://www.php.net/'.$a[1];
  3587.                     return $s;
  3588.                 }
  3589.                 $s &Converter::getLink($a[1],$a[0],array());
  3590.                 return $s;
  3591.             }
  3592.         }
  3593.         $a &$this->_getLink($expr$package$packages);
  3594.         return $a;
  3595.     }
  3596.  
  3597.     /**
  3598.      * @access private
  3599.      */
  3600.     function &_getLink($expr$package false$packages false)
  3601.     {
  3602.         if (!$package$package $this->package;
  3603.         //
  3604.         if (!isset($this->all_packages[$package])) return $expr;
  3605.         elseif (isset($packages[$package])) unset($packages[$package]);
  3606.         $links &$this->links;
  3607.         $class $this->class;
  3608.         if (strpos($expr,'function '=== 0)
  3609.         // asking for a function, not a method
  3610.             if ($test Converter::getFunctionLink(str_replace('function ','',str_replace('()','',$expr))$package)) return $test;
  3611.             else return $expr;
  3612.         }
  3613.         if (strpos($expr,'global '=== 0)
  3614.         // asking for a global variable
  3615.             if ($test Converter::getGlobalLink(str_replace('global ','',$expr)$package)) return $test;
  3616.             else return $expr;
  3617.         }
  3618.         if (strpos($expr,'object '=== 0)
  3619.         // asking for a class
  3620.             if ($test Converter::getClassLink(str_replace('object ','',$expr)$package)) return $test;
  3621.             else return $expr;
  3622.         }
  3623.         if (strpos($expr,'constant '=== 0)
  3624.         // asking for a class
  3625.             if ($test Converter::getDefineLink(str_replace('constant ','',$expr)$package)) return $test;
  3626.             else return $expr;
  3627.         }
  3628.         // are we in a class?
  3629.         if ($class)
  3630.         {
  3631.             // is $expr simply a word? see if it is the class
  3632.             if (trim($expr== $class)
  3633.             {
  3634.                 if ($test Converter::getClassLink(trim(str_replace('object ','',$expr)),$package)) return $test;
  3635.             }
  3636.             // if not, check to see if it is a method or variable of this class tree
  3637.             if (!strpos($expr,'::'))
  3638.             {
  3639.                 // if get is neither get() nor $get, assume get is a function, add () to make get()
  3640.                 if (strpos($expr,'$'!== && !strpos($expr,'()')) //$get = $get.'()';
  3641.                 {
  3642.                     if ($a $this->getLinkMethod($expr,$class,$package)) return $a;
  3643.                     if ($a $this->getLinkConst($expr,$class,$package)) return $a;
  3644.                     if ($a $this->getLinkVar('$'.$expr,$class,$package)) return $a;
  3645.                 }
  3646.                 if (strpos($expr,'()')) if ($a $this->getLinkMethod($expr,$class,$package)) return $a;
  3647.                 if (is_numeric(strpos($expr,'$'))) if ($a $this->getLinkVar($expr,$class,$package)) return $a;
  3648.             }
  3649.         }
  3650.         if ($test Converter::getClassLink(trim(str_replace('object ','',$expr)),$package)) return $test;
  3651.         if ($test Converter::getPageLink(trim($expr),$package)) return $test;
  3652.         if ($test Converter::getDefineLink(trim($expr),$package)) return $test;
  3653.         if ($test Converter::getGlobalLink(trim($expr),$package)) return $test;
  3654. //        if (strpos($expr,'.'))
  3655.         // package specified
  3656.  
  3657.         if (!is_array($packages))
  3658.         {
  3659.             $packages $this->all_packages;
  3660.         }
  3661.         do
  3662.         {
  3663.             if (isset($packages[$package])) unset($packages[$package]);
  3664.             if ($test Converter::getClassLink(str_replace('object ','',$expr),$package)) return $test;
  3665.             if ($test Converter::getPageLink($expr,$package)) return $test;
  3666.             if ($test Converter::getDefineLink($expr,$package)) return $test;
  3667.             if ($test Converter::getGlobalLink($expr,$package)) return $test;
  3668.             // is $expr in class::method() or class::$variable format?
  3669.             if (strpos($expr,'function '=== 0)
  3670.             // asking for a function, not a method
  3671.                 if ($test Converter::getFunctionLink(str_replace('function','',str_replace('()','',$expr))$package)) return $test;
  3672.                 else return $expr;
  3673.             }
  3674.             $test $this->_getDoubleColon($expr$package$packages$class$links);
  3675.             if (!is_string($test)) return $test;
  3676.             if (strpos($test'parent::'=== 0return $test;
  3677.             // $expr does not have ::
  3678.             if (is_numeric(@strpos('$',$expr)))
  3679.             {
  3680.                 // default to current class, whose name is contained in $this->render->parent
  3681.                 if ($test Converter::getVarLink($expr$class$package)) return $test;
  3682.             }
  3683.             // $expr is a function? (non-method)
  3684.             if (@strpos($expr,'()'))
  3685.             {
  3686.                 // otherwise, see if it is a method
  3687.                 if ($class)
  3688.                 {
  3689.                     if ($test Converter::getMethodLink(str_replace('()','',$expr)$class$package)) return $test;
  3690.                 }
  3691.                 // extract the function name, use it to retrieve the file that the function is in
  3692.     //            $page = $this->func_page[str_replace('function ','',str_replace('()','',$expr))];
  3693.                 // return the link
  3694.                 if ($test Converter::getFunctionLink(str_replace('function ','',str_replace('()','',$expr))$package)) return $test;
  3695.             }
  3696.             // $expr is just a word.  First, test to see if it is a function of the current package
  3697.             if ($test Converter::getFunctionLink(str_replace('function ','',str_replace('()','',$expr))$package)) return $test;
  3698.             // try other packages
  3699.             // look in parent package first, if found
  3700.             if (isset($this->package_parents[$package]&& in_array($this->package_parents[$package]$packages))
  3701.             {
  3702.                 $p1 $package;
  3703.                 $package $this->package_parents[$package];
  3704.                 if ($package)
  3705.                 {
  3706.                     if (isset($packages[$package])) unset($packages[$package]);
  3707.                 }
  3708.                 continue;
  3709.             }
  3710.             // no parent package, so start with the first one that's left
  3711.             $package @array_shift(@array_keys($packages));
  3712.             if ($package && isset($packages[$package]))
  3713.             {
  3714.                 unset($packages[$package]);
  3715.             }
  3716.         while (count($packages|| $package);
  3717.         $funcs get_defined_functions();
  3718.         // feature 564991, link to php manual
  3719.         if (in_array(str_replace(array('(',')'),array('',''),$expr),$funcs['internal']))
  3720.         {
  3721.             $return 'http://www.php.net/'.str_replace(array('(',')'),array('',''),$expr);
  3722.             return $return;
  3723.         }
  3724.         // no links found
  3725.         return $expr;
  3726.     }
  3727.  
  3728.     /**
  3729.      * Split up getLink to make it easier to debug
  3730.      * @access private
  3731.      */
  3732.     function _getDoubleColon(&$expr&$package&$packages$class$links)
  3733.     {
  3734.         if (@strpos($expr,'::'))
  3735.         {
  3736.             $class_method explode('::',$expr);
  3737.             if ($class_method[0== 'parent')
  3738.             {
  3739.                 // can only have parent in the same package as the class!  subtle bug
  3740.                 $package $this->package;
  3741.                 $packages array();
  3742.                 $cl $this->classes->getClassByPackage($class,$package);
  3743.                 if (!$cl)
  3744.                 // this is possible if an example file has parent::method()
  3745.                     return $expr;
  3746.                 }
  3747.                 $par $cl->getParent($this);
  3748.                 $phpparent false;
  3749.                 if (is_object($par))
  3750.                 {
  3751.                     $package $par->docblock->package;
  3752.                     $phpparent $par->getName();
  3753.                 else
  3754.                 {
  3755.                     addWarning(PDERROR_CLASS_PARENT_NOT_FOUND,$class,$package,$class_method[1]);
  3756.                     return $expr;
  3757.                 }
  3758.                 if ($phpparent$class_method[0$phpparent;
  3759.             }
  3760.             if (strpos($class_method[1],'()'))
  3761.             {
  3762.                 // strip everything but the function name, return a link
  3763.                 if ($test Converter::getMethodLink(str_replace('()','',$class_method[1])$class_method[0]$package)) return $test;
  3764.             }
  3765.             if ($test Converter::getVarLink($class_method[1]$class_method[0]$package)) return $test;
  3766.             if ($test Converter::getConstLink($class_method[1]$class_method[0]$package)) return $test;
  3767.         }
  3768.         return $expr;
  3769.     }
  3770.  
  3771.     /**
  3772.      * cycle through parent classes to retrieve a link to a method
  3773.      * do not use or override, used by getLink
  3774.      * @access private
  3775.      */
  3776.     function &getLinkMethod($expr$class$package)
  3777.     {
  3778.         $links &$this->links;
  3779.         do
  3780.         {
  3781.             // is $expr in class::method() or class::$variable format?
  3782.             if (@strpos($expr,'::'))
  3783.             {
  3784.                 $class_method explode('::',$expr);
  3785.                 if ($class_method[0== 'parent')
  3786.                 {
  3787.                     $cl $this->classes->getClassByPackage($class,$package);
  3788.                     $par $cl->getParent($this);
  3789.                     $phpparent false;
  3790.                     if (is_object($par))
  3791.                     {
  3792.                         $package $par->docblock->package;
  3793.                         $phpparent $par->getName();
  3794.                     else addWarning(PDERROR_CLASSPARENT_NOTFOUND,$class,$package,$class_method[1]);
  3795.                     if ($phpparent$class_method[0$phpparent;
  3796.                 else
  3797.                 {
  3798.                     $cl $this->classes->getClassByPackage($class,$package);
  3799.                 }
  3800.                 if (strpos($class_method[1],'()'))
  3801.                 {
  3802.                     // strip everything but the function name, return a link
  3803.                     if ($test Converter::getMethodLink(str_replace('function ','',str_replace('()','',$class_method[1]))$class_method[0]$package)) return $test;
  3804.                 }
  3805.             }
  3806.             if ($test Converter::getMethodLink(str_replace('()','',$expr)$class$package)) return $test;
  3807.             $cl $this->classes->getClassByPackage($class,$package);
  3808.             if ($cl)
  3809.             {
  3810.                 $par $cl->getParent($this);
  3811.                 if (is_object($par))
  3812.                 {
  3813.                     $package $par->docblock->package;
  3814.                     $class $par->getName();
  3815.                 else $class $par;
  3816.             else $class false;
  3817.         while ($class);
  3818.         // no links found
  3819.         $flag false;
  3820.         return $flag;
  3821.     }
  3822.  
  3823.     /**
  3824.      * cycle through parent classes to retrieve a link to a var
  3825.      * do not use or override, used by getLink
  3826.      * @access private
  3827.      */
  3828.     function &getLinkVar($expr$class$package)
  3829.     {
  3830.         $links &$this->links;
  3831.         do
  3832.         {
  3833.             // is $expr in class::method() or class::$variable format?
  3834.             if (@strpos($expr,'::'))
  3835.             {
  3836.                 $class_method explode('::',$expr);
  3837.                 if ($class_method[0== 'parent')
  3838.                 {
  3839.                     $cl $this->classes->getClassByPackage($class,$package);
  3840.                     $phpparent false;
  3841.                     $par $cl->getParent($this);
  3842.                     if (is_object($par))
  3843.                     {
  3844.                         $package $par->docblock->package;
  3845.                         $phpparent $par->getName();
  3846.                     else addWarning(PDERROR_CLASSPARENT_NOTFOUND,$class,$package,$class_method[1]);
  3847.                     if ($phpparent$class_method[0$phpparent;
  3848.                 else
  3849.                 {
  3850.                     $cl $this->classes->getClassByPackage($class,$package);
  3851.                 }
  3852.                 if ($test Converter::getVarLink($class_method[1]$class_method[0]$package)) return $test;
  3853.                 if ($test Converter::getVarLink('$'.$class_method[1]$class_method[0]$package)) return $test;
  3854.             }
  3855.             if ($test Converter::getVarLink($expr$class$package)) return $test;
  3856.             if ($test Converter::getVarLink('$'.$expr$class$package)) return $test;
  3857.             $cl $this->classes->getClassByPackage($class,$package);
  3858.             if ($cl)
  3859.             {
  3860.                 $par $cl->getParent($this);
  3861.                 if (is_object($par))
  3862.                 {
  3863.                     $package $par->docblock->package;
  3864.                     $class $par->getName();
  3865.                 else $class $par;
  3866.             else $class false;
  3867.         while ($class);
  3868.         // no links found
  3869.         $class false;
  3870.         return $class;
  3871.     }
  3872.  
  3873.     /**
  3874.      * cycle through parent classes to retrieve a link to a class constant
  3875.      * do not use or override, used by getLink
  3876.      * @access private
  3877.      * @since 1.2.4
  3878.      */
  3879.     function &getLinkConst($expr$class$package)
  3880.     {
  3881.         $links &$this->links;
  3882.         do
  3883.         {
  3884.             // is $expr in class::method() or class::$variable format?
  3885.             if (@strpos($expr,'::'))
  3886.             {
  3887.                 $class_method explode('::',$expr);
  3888.                 if ($class_method[0== 'parent')
  3889.                 {
  3890.                     $cl $this->classes->getClassByPackage($class,$package);
  3891.                     $phpparent false;
  3892.                     $par $cl->getParent($this);
  3893.                     if (is_object($par))
  3894.                     {
  3895.                         $package $par->docblock->package;
  3896.                         $phpparent $par->getName();
  3897.                     else addWarning(PDERROR_CLASSPARENT_NOTFOUND,$class,$package,$class_method[1]);
  3898.                     if ($phpparent$class_method[0$phpparent;
  3899.                 else
  3900.                 {
  3901.                     $cl $this->classes->getClassByPackage($class,$package);
  3902.                 }
  3903.                 if ($test Converter::getConstLink($class_method[1]$class_method[0]$package)) return $test;
  3904.             }
  3905.             if ($test Converter::getConstLink($expr$class$package)) return $test;
  3906.             $cl $this->classes->getClassByPackage($class,$package);
  3907.             if ($cl)
  3908.             {
  3909.                 $par $cl->getParent($this);
  3910.                 if (is_object($par))
  3911.                 {
  3912.                     $package $par->docblock->package;
  3913.                     $class $par->getName();
  3914.                 else $class $par;
  3915.             else $class false;
  3916.         while ($class);
  3917.         // no links found
  3918.         $flag false;
  3919.         return $flag;
  3920.     }
  3921.  
  3922.     /**
  3923.      * take URL $link and text $text and return a link in the format needed for the Converter
  3924.      * @param string URL
  3925.      * @param string text to display
  3926.      * @return string link to $link
  3927.      * @abstract
  3928.      */
  3929.     function returnLink($link,$text)
  3930.     {
  3931.     }
  3932.  
  3933.     /**
  3934.      * take {@link abstractLink} descendant and text $eltext and return a link
  3935.      * in the format needed for the Converter
  3936.      * @param abstractLink 
  3937.      * @param string 
  3938.      * @return string link to $element
  3939.      * @abstract
  3940.      */
  3941.     function returnSee(&$link$eltext false)
  3942.     {
  3943.     }
  3944.  
  3945.     /**
  3946.      * take {@link abstractLink} descendant and text $eltext and return a
  3947.      * unique ID in the format needed for the Converter
  3948.      * @param abstractLink 
  3949.      * @return string unique identifier of $element
  3950.      * @abstract
  3951.      */
  3952.     function getId(&$link)
  3953.     {
  3954.     }
  3955.  
  3956.     /**
  3957.      * Convert README/INSTALL/CHANGELOG file contents to output format
  3958.      * @param README|INSTALL|CHANGELOG
  3959.      * @param string contents of the file
  3960.      * @abstract
  3961.      */
  3962.     function Convert_RIC($name$contents)
  3963.     {
  3964.     }
  3965.  
  3966.     /**
  3967.      * Convert all elements to output format
  3968.      *
  3969.      * This will call ConvertXxx where Xxx is {@link ucfirst}($element->type).
  3970.      * It is expected that a child converter defines a handler for every
  3971.      * element type, even if that handler does nothing.  phpDocumentor will
  3972.      * terminate with an error if a handler doesn't exist.
  3973.      * {@internal 
  3974.      * Since 1.2.0 beta 3, this function has been moved from child converters
  3975.      * to the parent, because it doesn't really make sense to put it in the
  3976.      * child converter, and we can add error handling.
  3977.      *
  3978.      * {@source } }
  3979.      * @throws {@link PDERROR_NO_CONVERT_HANDLER}
  3980.      * @param mixed {@link parserElement} descendant or {@link parserPackagePage} or {@link parserData}
  3981.      */
  3982.     function Convert(&$element)
  3983.     {
  3984.         $handler 'convert'.ucfirst($element->type);
  3985.         if (method_exists($this,$handler))
  3986.         {
  3987.             $this->$handler($element);
  3988.         else
  3989.         {
  3990.             addErrorDie(PDERROR_NO_CONVERTER_HANDLER,$element->type,$handler,phpDocumentor_get_class($this));
  3991.         }
  3992.     }
  3993.     /**#@+
  3994.      * Conversion Handlers
  3995.      *
  3996.      * All of the convert* handlers set up template variables for the Smarty
  3997.      * template.{@internal  In addition, the {@link newSmarty()} method is
  3998.      * called to retrieve the global Smarty template}}
  3999.      */
  4000.     /**
  4001.      * Default Tutorial Handler
  4002.      *
  4003.      * Sets up the tutorial template, and its prev/next/parent links
  4004.      * {@internal 
  4005.      * Retrieves the title using {@link parserTutorial::getTitle()} and uses the
  4006.      * {@link parserTutorial::prev, parserTutorial::next, parserTutorial::parent}
  4007.      * links to set up those links.}}}
  4008.      * @param parserTutorial 
  4009.      */
  4010.     function &convertTutorial(&$element)
  4011.     {
  4012.         $this->package $element->package;
  4013.         $this->subpackage $element->subpackage;
  4014.         $x $element->Convert($this);
  4015.         $template &$this->newSmarty();
  4016.         $template->assign('contents',$x);
  4017.         $template->assign('title',$element->getTitle($this));
  4018.         $template->assign('nav',$element->parent || $element->prev || $element->next);
  4019.         if ($element->parent)
  4020.         {
  4021.             $template->assign('up',$this->getId($element->parent));
  4022.             $template->assign('uptitle',$element->parent->title);
  4023.         }
  4024.         if ($element->prev)
  4025.         {
  4026.             $template->assign('prev',$this->getId($element->prev));
  4027.             $template->assign('prevtitle',$element->prev->title);
  4028.         }
  4029.         if ($element->next)
  4030.         {
  4031.             $template->assign('next',$this->getId($element->next));
  4032.             $template->assign('nexttitle',$element->next->title);
  4033.         }
  4034.         return $template;
  4035.     }
  4036.     /**
  4037.      * Default Class Handler
  4038.      *
  4039.      * Sets up the class template.
  4040.      * {@internal special methods
  4041.      * {@link generateChildClassList(), generateFormattedClassTree()},
  4042.      * {@link getFormattedConflicts, getFormattedInheritedMethods},
  4043.      * and {@link getFormattedInheritedVars} are called to complete vital
  4044.      * template setup.}}}
  4045.      */
  4046.     function convertClass(&$element)
  4047.     {
  4048.         $this->class $element->getName();
  4049.         $this->class_data &$this->newSmarty();
  4050.         $this->class_data->assign("class_name",$element->getName());
  4051.         $this->class_data->assign("vars",array());
  4052.         $this->class_data->assign("methods",array());
  4053.         $this->class_data->assign("consts",array());
  4054.         $this->class_data->assign("is_interface"$element->isInterface());
  4055.         $this->class_data->assign("implements"$this->getFormattedImplements($element));
  4056.         $this->class_data->assign("package",$element->docblock->package);
  4057.         $this->class_data->assign("line_number",$element->getLineNumber());
  4058.         $this->class_data->assign("source_location",$element->getSourceLocation($this));
  4059.                 $this->class_data->assign("page_link",$this->getCurrentPageLink());
  4060.         $docblock $this->prepareDocBlock($elementfalse);
  4061.         $this->class_data->assign("sdesc",$docblock['sdesc']);
  4062.         $this->class_data->assign("desc",$docblock['desc']);
  4063.                 $this->class_data->assign("access"$docblock['access']);
  4064.                 $this->class_data->assign("abstract"$docblock['abstract']);
  4065.         $this->class_data->assign("tags",$docblock['tags']);
  4066.         $this->class_data->assign("api_tags",$docblock['api_tags']);
  4067.         $this->class_data->assign("info_tags",$docblock['info_tags']);
  4068.         $this->class_data->assign("utags",$docblock['utags']);
  4069.         $this->class_data->assign"prop_tags"$docblock['property_tags');
  4070.         if ($this->hasSourceCode($element->getPath())) {
  4071.         $this->class_data->assign("class_slink",$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true));
  4072.         }
  4073.  
  4074.         else
  4075.         $this->class_data->assign("class_slink",false);
  4076.         $this->class_data->assign("children"$this->generateChildClassList($element));
  4077.         $this->class_data->assign("class_tree"$this->generateFormattedClassTree($element));
  4078.         $this->class_data->assign("conflicts"$this->getFormattedConflicts($element,"classes"));
  4079.         $inherited_methods $this->getFormattedInheritedMethods($element);
  4080.         if (!empty($inherited_methods))
  4081.         {
  4082.             $this->class_data->assign("imethods",$inherited_methods);
  4083.         else
  4084.         {
  4085.             $this->class_data->assign("imethods",false);
  4086.         }
  4087.         $inherited_vars $this->getFormattedInheritedVars($element);
  4088.         if (!empty($inherited_vars))
  4089.         {
  4090.             $this->class_data->assign("ivars",$inherited_vars);
  4091.         else
  4092.         {
  4093.             $this->class_data->assign("ivars",false);
  4094.         }
  4095.         $inherited_consts $this->getFormattedInheritedConsts($element);
  4096.         if (!empty($inherited_consts))
  4097.         {
  4098.             $this->class_data->assign("iconsts",$inherited_consts);
  4099.         else
  4100.         {
  4101.             $this->class_data->assign("iconsts",false);
  4102.         }
  4103.     }
  4104.  
  4105.  
  4106.     /**
  4107.      * Converts method for template output
  4108.      *
  4109.      * This function must be called by a child converter with any extra
  4110.      * template variables needed in the parameter $addition
  4111.      * @param parserMethod 
  4112.      */
  4113.     function convertMethod(&$element$additions array())
  4114.     {
  4115.         $fname $element->getName();
  4116.         $docblock $this->prepareDocBlock($element);
  4117.         $returntype 'void';
  4118.         if ($element->isConstructor$returntype $element->class;
  4119.         if ($element->docblock->return)
  4120.         {
  4121.             $a $element->docblock->return->Convert($this);
  4122.             $returntype $element->docblock->return->converted_returnType;
  4123.         }
  4124.         $params $param_i array();
  4125.         if (count($element->docblock->params))
  4126.         foreach($element->docblock->params as $param => $val)
  4127.         {
  4128.             $a $val->Convert($this);
  4129.             $params[$param_i[$paramarray("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
  4130.         }
  4131.  
  4132.         if ($element->docblock->hasaccess{
  4133.             $acc $docblock['access'];
  4134.         else {
  4135.             $acc 'public';
  4136.         }
  4137.  
  4138.         if ($this->hasSourceCode($element->getPath()))
  4139.         $additions["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4140.         if (isset($this->class_data)) {
  4141.             $this->class_data->append(
  4142.                 'methods',
  4143.                 array_merge(
  4144.                     array(
  4145.                         'sdesc' => $docblock['sdesc'],
  4146.                         'desc' => $docblock['desc'],
  4147.                         'static' => $docblock['static'],
  4148.                         'abstract' => $docblock['abstract'],
  4149.                         'tags' => $docblock['tags'],
  4150.                         'api_tags' => $docblock['api_tags'],
  4151.                         'see_tags' => $docblock['see_tags'],
  4152.                         'info_tags_sorted' => $docblock['info_tags_sorted'],
  4153.                         'info_tags' => $docblock['info_tags'],
  4154.                         'utags' => $docblock['utags'],
  4155.                         'constructor' => $element->isConstructor,
  4156.                         'access' => $acc,
  4157.                         'function_name'     => $fname,
  4158.                         'function_return'    => $returntype,
  4159.                         'function_call'     => $element->getFunctionCall(),
  4160.                         'ifunction_call'     => $element->getIntricateFunctionCall($this$param_i),
  4161.                         'descmethod'    => $this->getFormattedDescMethods($element),
  4162.                         'method_overrides'    => $this->getFormattedOverrides($element),
  4163.                         'method_implements'    => $this->getFormattedMethodImplements($element),
  4164.                         'line_number' => $element->getLineNumber(),
  4165.                         'id' => $this->getId($element),
  4166.                         'params' => $params
  4167.                     ),
  4168.                     $additions
  4169.                 )
  4170.             );
  4171.         }
  4172.     }
  4173.  
  4174.     /**
  4175.      * Converts class variables for template output.
  4176.      *
  4177.      * This function must be called by a child converter with any extra
  4178.      * template variables needed in the parameter $addition
  4179.      * @param parserVar 
  4180.      */
  4181.     function convertVar(&$element$additions array())
  4182.     {
  4183.         $docblock $this->prepareDocBlock($element);
  4184.         $b 'mixed';
  4185.  
  4186.         if ($element->docblock->hasaccess)
  4187.             $acc $element->docblock->tags['access'][0]->value;
  4188.         else
  4189.             $acc 'public';
  4190.  
  4191.         if ($element->docblock->var)
  4192.         {
  4193.             $b $element->docblock->var->converted_returnType;
  4194.         }
  4195.         if ($this->hasSourceCode($element->getPath()))
  4196.         $additions["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4197.         if (isset($this->class_data)) {
  4198.             $this->class_data->append(
  4199.                 'vars',
  4200.                 array_merge(
  4201.                     array(
  4202.                         'sdesc' => $docblock['sdesc'],
  4203.                         'desc' => $docblock['desc'],
  4204.                         'static' => $docblock['static'],
  4205.                         'abstract' => $docblock['abstract'],
  4206.                         'utags' => $docblock['utags'],
  4207.                         'tags' => $docblock['tags'],
  4208.                         'api_tags' => $docblock['api_tags'],
  4209.                         'info_tags' => $docblock['info_tags'],
  4210.                         'var_name' => $element->getName(),
  4211.                         'has_default' => strlen($element->getValue()),
  4212.                         'var_default' => $this->postProcess($element->getValue()),
  4213.                         'var_type' => $b,
  4214.                         'access' => $acc,
  4215.                         'line_number' => $element->getLineNumber(),
  4216.                         'descvar'    => $this->getFormattedDescVars($element),
  4217.                         'var_overrides' => $this->getFormattedOverrides($element),
  4218.                         'id' => $this->getId($element)
  4219.                     ),
  4220.                     $additions
  4221.                 )
  4222.             );
  4223.         }
  4224.     }
  4225.  
  4226.     /**
  4227.      * Converts class constants for template output.
  4228.      *
  4229.      * This function must be called by a child converter with any extra
  4230.      * template variables needed in the parameter $addition
  4231.      * @param parserConst 
  4232.      */
  4233.     function convertConst(&$element$additions array())
  4234.     {
  4235.         $docblock $this->prepareDocBlock($element);
  4236.  
  4237.         if ($element->docblock->hasaccess)
  4238.             $acc $element->docblock->tags['access'][0]->value;
  4239.         else
  4240.             $acc 'public';
  4241.  
  4242.         if ($this->hasSourceCode($element->getPath()))
  4243.         $additions["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4244.         if (isset($this->class_data)) {
  4245.             $this->class_data->append(
  4246.                 'consts',
  4247.                  array_merge(
  4248.                     array(
  4249.                         'sdesc' => $docblock['sdesc'],
  4250.                         'desc' => $docblock['desc'],
  4251.                         'access' => $docblock['access'],
  4252.                         'abstract' => $docblock['abstract'],
  4253.                         'utags' => $docblock['utags'],
  4254.                         'tags' => $docblock['tags'],
  4255.                         'api_tags' => $docblock['api_tags'],
  4256.                         'info_tags' => $docblock['info_tags'],
  4257.                         'const_name' => $element->getName(),
  4258.                         'const_value' => $this->postProcess($element->getValue()),
  4259.                         'access' => $acc,
  4260.                         'line_number' => $element->getLineNumber(),
  4261.                         'id' => $this->getId($element)
  4262.                     ),
  4263.                     $additions
  4264.                 )
  4265.             );
  4266.         }
  4267.     }
  4268.  
  4269.     /**
  4270.      * Default Page Handler
  4271.      *
  4272.      * {@internal In addition to setting up the smarty template with {@link newSmarty()},
  4273.      * this class uses {@link getSourceLocation()} and {@link getClassesOnPage()}
  4274.      * to set template variables.  Also used is {@link getPageName()}, to get
  4275.      * a Converter-specific name for the page.}}}
  4276.      * @param parserPage 
  4277.      */
  4278.     function convertPage(&$element)
  4279.     {
  4280.         $this->page_data &$this->newSmarty(true);
  4281.         $this->page $this->getPageName($element->parent);
  4282.         $this->path $element->parent->getPath();
  4283.         $this->curpage &$element->parent;
  4284.         $this->page_data->assign("source_location",$element->parent->getSourceLocation($this));
  4285.         $this->page_data->assign("functions",array());
  4286.         $this->page_data->assign("includes",array());
  4287.         $this->page_data->assign("defines",array());
  4288.         $this->page_data->assign("globals",array());
  4289.         $this->page_data->assign("classes",$this->getClassesOnPage($element));
  4290.         $this->page_data->assign("hasclasses",$element->hasClasses());
  4291.         $this->page_data->assign("hasinterfaces",$element->hasInterfaces());
  4292.         $this->page_data->assign("name"$element->parent->getFile());
  4293.         if ($t $element->getTutorial())
  4294.         {
  4295.             $this->page_data->assign("tutorial",$this->returnSee($t));
  4296.         else
  4297.         {
  4298.             $this->page_data->assign("tutorial",false);
  4299.         }
  4300.         if ($element->docblock)
  4301.         {
  4302.             $docblock $this->prepareDocBlock($elementfalse);
  4303.             $this->page_data->assign("sdesc",$docblock['sdesc']);
  4304.             $this->page_data->assign("desc",$docblock['desc']);
  4305.             $this->page_data->assign("tags",$docblock['tags']);
  4306.             $this->page_data->assign("api_tags",$docblock['api_tags']);
  4307.             $this->page_data->assign("info_tags",$docblock['info_tags']);
  4308.             $this->page_data->assign("utags",$docblock['utags']);
  4309.         }
  4310.     }
  4311.  
  4312.     /**
  4313.      * Converts global variables for template output
  4314.      *
  4315.      * This function must be called by a child converter with any extra
  4316.      * template variables needed in the parameter $addition
  4317.      * {@internal 
  4318.      * In addition to using {@link prepareDocBlock()}, this method also
  4319.      * uses utility functions {@link getGlobalValue(), getFormattedConflicts()}}}}
  4320.      * @param parserGlobal 
  4321.      * @uses postProcess() on global_value template value, makes it displayable
  4322.      * @param array any additional template variables should be in this array
  4323.      */
  4324.     function convertGlobal(&$element$addition array())
  4325.     {
  4326.         $docblock $this->prepareDocBlock($element);
  4327.         $value $this->getGlobalValue($element->getValue());
  4328.         if ($this->hasSourceCode($element->getPath()))
  4329.         $addition["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4330.         $this->page_data->append('globals',array_merge(
  4331.                                             array('sdesc' => $docblock['sdesc'],
  4332.                                                   'desc' => $docblock['desc'],
  4333.                                                   'tags' => $docblock['tags'],
  4334.                                                   'api_tags' => $docblock['api_tags'],
  4335.                                                   'info_tags' => $docblock['info_tags'],
  4336.                                                   'utags' => $docblock['utags'],
  4337.                                                   'global_name'     => $element->getName(),
  4338.                                                   'global_type' => $element->getDataType($this),
  4339.                                                   'global_value'    => $value,
  4340.                                                   'line_number' => $element->getLineNumber(),
  4341.                                                   'global_conflicts'    => $this->getFormattedConflicts($element,"global variables"),
  4342.                                                   'id' => $this->getId($element)),
  4343.                                             $addition));
  4344.     }
  4345.  
  4346.     /**
  4347.      * Converts defines for template output
  4348.      *
  4349.      * This function must be called by a child converter with any extra
  4350.      * template variables needed in the parameter $addition
  4351.      * {@internal 
  4352.      * In addition to using {@link prepareDocBlock()}, this method also
  4353.      * uses utility functions {@link getGlobalValue(), getFormattedConflicts()}}}}
  4354.      * @param parserDefine 
  4355.      * @uses postProcess() on define_value template value, makes it displayable
  4356.      * @param array any additional template variables should be in this array
  4357.      */
  4358.     function convertDefine(&$element$addition array())
  4359.     {
  4360.         $docblock $this->prepareDocBlock($element);
  4361.         if ($this->hasSourceCode($element->getPath()))
  4362.         $addition["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4363.         $this->page_data->append('defines',array_merge(
  4364.                                             array('sdesc' => $docblock['sdesc'],
  4365.                                                   'desc' => $docblock['desc'],
  4366.                                                   'tags' => $docblock['tags'],
  4367.                                                   'api_tags' => $docblock['api_tags'],
  4368.                                                   'info_tags' => $docblock['info_tags'],
  4369.                                                   'utags' => $docblock['utags'],
  4370.                                                   'define_name'     => $element->getName(),
  4371.                                                   'line_number' => $element->getLineNumber(),
  4372.                                                   'define_value'    => $this->postProcess($element->getValue()),
  4373.                                                   'define_conflicts'    => $this->getFormattedConflicts($element,"defines"),
  4374.                                                   'id' => $this->getId($element)),
  4375.                                             $addition));
  4376.     }
  4377.  
  4378.  
  4379.     /**
  4380.      * Converts includes for template output
  4381.      *
  4382.      * This function must be called by a child converter with any extra
  4383.      * template variables needed in the parameter $addition
  4384.      * @see prepareDocBlock()
  4385.      * @param parserInclude 
  4386.      */
  4387.     function convertInclude(&$element$addition array())
  4388.     {
  4389.         $docblock $this->prepareDocBlock($element);
  4390.         $per $this->getIncludeValue($element->getValue()$element->getPath());
  4391.  
  4392.         if ($this->hasSourceCode($element->getPath()))
  4393.         $addition["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4394.         $this->page_data->append('includes',array_merge(
  4395.                                              array('sdesc' => $docblock['sdesc'],
  4396.                                                    'desc' => $docblock['desc'],
  4397.                                                    'tags' => $docblock['tags'],
  4398.                                                    'api_tags' => $docblock['api_tags'],
  4399.                                                    'info_tags' => $docblock['info_tags'],
  4400.                                                    'utags' => $docblock['utags'],
  4401.                                                    'include_name'     => $element->getName(),
  4402.                                                    'line_number' => $element->getLineNumber(),
  4403.                                                    'include_value'    => $per),
  4404.                                              $addition));
  4405.     }
  4406.  
  4407.     /**
  4408.      * Converts function for template output
  4409.      *
  4410.      * This function must be called by a child converter with any extra
  4411.      * template variables needed in the parameter $addition
  4412.      * @see prepareDocBlock()
  4413.      * @param parserFunction 
  4414.      */
  4415.     function convertFunction(&$element$addition array())
  4416.     {
  4417.         $docblock $this->prepareDocBlock($element);
  4418.         $fname $element->getName();
  4419.         $params $param_i array();
  4420.         if (count($element->docblock->params))
  4421.         foreach($element->docblock->params as $param => $val)
  4422.         {
  4423.             $a $val->Convert($this);
  4424.             $params[$param_i[$paramarray("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
  4425.         }
  4426.         $returntype 'void';
  4427.         if ($element->docblock->return)
  4428.         {
  4429.             $a $element->docblock->return->Convert($this);
  4430.             $returntype $element->docblock->return->converted_returnType;
  4431.         }
  4432.  
  4433.         if ($this->hasSourceCode($element->getPath()))
  4434.         $addition["slink"$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
  4435.         $this->page_data->append('functions',array_merge(
  4436.                                               array('sdesc' => $docblock['sdesc'],
  4437.                                                     'desc' => $docblock['desc'],
  4438.                                                     'tags' => $docblock['tags'],
  4439.                                                     'api_tags' => $docblock['api_tags'],
  4440.                                                     'info_tags' => $docblock['info_tags'],
  4441.                                                     'utags' => $docblock['utags'],
  4442.                                                     'function_name'     => $fname,
  4443.                                                     'function_return'    => $returntype,
  4444.                                                     'function_conflicts'    => $this->getFormattedConflicts($element,"functions"),
  4445.                                                     'ifunction_call'     => $element->getIntricateFunctionCall($this$param_i),
  4446.                                                     'function_call'     => $element->getFunctionCall(),
  4447.                                                     'line_number' => $element->getLineNumber(),
  4448.                                                     'id' => $this->getId($element),
  4449.                                                     'params' => $params),
  4450.                                               $addition));
  4451.     }
  4452.     /**#@-*/
  4453.  
  4454.     /**
  4455.      * convert the element's DocBlock for output
  4456.      *
  4457.      * This function converts all tags and descriptions for output
  4458.      * @param mixed any descendant of {@link parserElement}, or {@link parserData}
  4459.      * @param array used to translate tagnames into other tags
  4460.      * @param boolean set to false for pages and classes, the only elements allowed to specify @package
  4461.      * @return array 
  4462.      *
  4463.      *  Format:
  4464.      *  <pre>
  4465.      *  array('sdesc' => DocBlock summary
  4466.      *        'desc' => DocBlock detailed description
  4467.      *        'tags' => array('keyword' => tagname, 'data' => tag description)
  4468.      *                  known tags
  4469.      *        'api_tags' => array('keyword' => tagname, 'data' => tag description)
  4470.      *                  known api documentation tags
  4471.      *        'info_tags' => array('keyword' => tagname, 'data' => tag description)
  4472.      *                  known informational tags
  4473.      *      [ 'utags' => array('keyword' => tagname, 'data' => tag description
  4474.      *                  unknown tags ]
  4475.      *      [ 'vartype' => type from @var/@return tag ]
  4476.      *      [ 'var_descrip' => description from @var/@return tag ]
  4477.      *       )
  4478.      *  </pre>
  4479.      */
  4480.     function prepareDocBlock(&$element$names array(),$nopackage true)
  4481.     {
  4482.         $tagses $element->docblock->listTags();
  4483.         $tags $ret $api_tags $info_tags array();
  4484.         $api_tags_arr array("abstract""access""deprecated""example""filesource",
  4485.                              "global""internal""name""return""see",
  4486.                              "property""property-read""property-write""method",
  4487.                              "staticvar""usedby""uses""var");
  4488.         if (!$nopackage)
  4489.         {
  4490.             $tags[array('keyword' => 'package','data' => $element->docblock->package);
  4491.             if (!empty($element->docblock->subpackage)) $tags[array('keyword' => 'subpackage','data' => $element->docblock->subpackage);
  4492.         }
  4493.         if ($element->docblock->var)
  4494.         {
  4495.             $a $element->docblock->var->Convert($this);
  4496.             $ret['vartype'$element->docblock->var->converted_returnType;
  4497.             if (!empty($a))
  4498.             {
  4499.                 $tags[array('keyword' => 'var''data' => $a);
  4500.                 $ret["var_descrip"$a;
  4501.             }
  4502.         }
  4503.         if ($element->docblock->return)
  4504.         {
  4505.             $a $element->docblock->return->Convert($this);
  4506.             $ret['vartype'$element->docblock->return->converted_returnType;
  4507.             if (!empty($a))
  4508.             {
  4509.                 $tags[$api_tags[array('keyword' => 'return''data' => $a);
  4510.                 $ret["var_descrip"$a;
  4511.             }
  4512.         }
  4513.         if ($element->docblock->funcglobals)
  4514.         foreach($element->docblock->funcglobals as $global => $val)
  4515.         {
  4516.             if ($a $this->getGlobalLink($global,$element->docblock->package))
  4517.             {
  4518.                 $global $a;
  4519.             }
  4520.             $b Converter::getLink($val[0]);
  4521.             if (is_object($b&& phpDocumentor_get_class($b== 'classlink')
  4522.             {
  4523.                 $val[0$this->returnSee($b);
  4524.             }
  4525.             $tags[$api_tags[array('keyword' => 'global','data' => $val[0].' '.$global.': '.$val[1]->Convert($this));
  4526.         }
  4527.         if ($element->docblock->statics)
  4528.         foreach($element->docblock->statics as $static => $val)
  4529.         {
  4530.             $a $val->Convert($this);
  4531.             $tags[$api_tags[array('keyword' => 'staticvar','data' => $val->converted_returnType.' '.$static.': '.$a);
  4532.         }
  4533.         $property_tags array();
  4534.         foreach $element->docblock->properties as $prop_name => $val )
  4535.         {
  4536.             $a $val->Convert$this );
  4537.             if !empty$a ) )
  4538.             {
  4539.                 $tags[$api_tags[array'keyword' => $val->keyword ,
  4540.                                                'data' => $val->converted_returnType  ' ' $prop_name ': ' $a );
  4541.                 $prop['prop_name'$prop_name;
  4542.                 $prop['access'$val->keyword == 'property-read' 'read' :
  4543.                                     $val->keyword == 'property-write' 'write' 'read/write' );
  4544.                 $prop['prop_type'$val->converted_returnType;
  4545.                 $prop['sdesc'$a;
  4546.                 $property_tags$prop_name $prop;
  4547.             }
  4548.         }
  4549.         ksort$property_tagsSORT_STRING );
  4550.         $property_tags array_values$property_tags );
  4551.         $info_tags_sorted array();
  4552.         $ret['static'false;
  4553.         foreach($tagses as $tag)
  4554.         {
  4555.             if (isset($names[$tag->keyword])) $tag->keyword $names[$tag->keyword];
  4556.             if ($tag->keyword == 'static'{
  4557.                 $ret['static'true;
  4558.                 continue;
  4559.             }
  4560.             if ($tag->keyword)
  4561.                 $tags[array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
  4562.             if (in_array($tag->keyword$api_tags_arr)) {
  4563.                 $api_tags[array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
  4564.             else {
  4565.                 $info_tags[array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
  4566.                 @list$className$desc explode" "$tag->Convert($this));
  4567.                 $info_tags_sorted$tag->keyword ][array'keyword' => $className'data' => $desc );
  4568.             }
  4569.         }
  4570.         $utags array();
  4571.         foreach($element->docblock->unknown_tags as $keyword => $tag)
  4572.         {
  4573.             foreach($tag as $t)
  4574.             $utags[array('keyword' => $keyword'data' => $t->Convert($this));
  4575.         }
  4576.         $ret['abstract'false;
  4577.         $ret['access''public';
  4578.         $see_tags array();
  4579.         foreach($tags as $tag)
  4580.         {
  4581.             if ($tag['keyword'== 'access'{
  4582.                 $ret['access'$tag['data'];
  4583.             }
  4584.             if ($tag['keyword'== 'abstract'{
  4585.                 $ret['abstract'true;
  4586.             }
  4587.             if ($tag['keyword'== 'see' || $tag['keyword'== 'uses' ||
  4588.                   $tag['keyword'== 'usedby'{
  4589.                 $see_tags[$tag['data'];
  4590.             }
  4591.         }
  4592.         $ret['sdesc'$element->docblock->getSDesc($this);
  4593.         $ret['desc'$element->docblock->getDesc($this);
  4594.         $ret['tags'$tags;
  4595.         $ret['see_tags'$see_tags;
  4596.         $ret['info_tags_sorted'$info_tags_sorted;
  4597.         $ret['api_tags'$api_tags;
  4598.         $ret['info_tags'$info_tags;
  4599.         $ret['utags'$utags;
  4600.         $ret['property_tags'$property_tags;
  4601.         return $ret;
  4602.     }
  4603.  
  4604.     /**
  4605.      * gets a list of all classes declared on a procedural page represented by
  4606.      * $element, a {@link parserData} class
  4607.      * @param parserData &$element 
  4608.      * @return array links to each classes documentation
  4609.      *
  4610.      *  Format:
  4611.      *  <pre>
  4612.      *  array('name' => class name,
  4613.      *        'sdesc' => summary of the class
  4614.      *        'link' => link to the class's documentation)
  4615.      *  </pre>
  4616.      */
  4617.     function getClassesOnPage(&$element)
  4618.     {
  4619.         global $_phpDocumentor_setting;
  4620.         $a $element->getClasses($this);
  4621.         $classes array();
  4622.         foreach($a as $package => $clas)
  4623.         {
  4624.             if (!empty($_phpDocumentor_setting['packageoutput']))
  4625.             {
  4626.                 $packages explode(',',$_phpDocumentor_setting['packageoutput']);
  4627.                 if (!in_array($package$packages)) continue;
  4628.             }
  4629.             for($i=0$i<count($clas)$i++)
  4630.             {
  4631.                 if ($this->parseprivate || ($clas[$i]->docblock && $clas[$i]->docblock->hasaccess && $clas[$i]->docblock->tags['access'][0]->value == 'private'))
  4632.                 {
  4633.                     $sdesc '';
  4634.                     $r array();
  4635.                     $sdesc $clas[$i]->docblock->getSDesc($this);
  4636.                     if ($clas[$i]->docblock->hasaccess)
  4637.                                             $r['access'$clas[$i]->docblock->tags['access'][0]->value;
  4638.                     else
  4639.                                             $r['access''public';
  4640.                                         if (isset ($clas[$i]->docblock->tags['abstract']))
  4641.                                             $r['abstract'TRUE;
  4642.                                         else
  4643.                                             $r['abstract'FALSE;
  4644.                     $r['name'$clas[$i]->getName();
  4645.                     $r['sdesc'$sdesc;
  4646.                     $r['link'$this->getClassLink($clas[$i]->getName(),$package,$clas[$i]->getPath());
  4647.                     $classes[$r;
  4648.                 }
  4649.             }
  4650.         }
  4651.         return $classes;
  4652.     }
  4653.  
  4654.     /**
  4655.      * returns an array containing the class inheritance tree from the root
  4656.      * object to the class.
  4657.      *
  4658.      * This method must be overridden, or phpDocumentor will halt with a fatal
  4659.      * error
  4660.      * @return string Converter-specific class tree for an individual class
  4661.      * @param parserClass    class variable
  4662.      * @abstract
  4663.      */
  4664.  
  4665.     function generateFormattedClassTree($class)
  4666.     {
  4667.     }
  4668.  
  4669.     /**
  4670.      * returns an array containing the class inheritance tree from the root
  4671.      * object to the class.
  4672.      *
  4673.      * This method must be overridden, or phpDocumentor will halt with a fatal
  4674.      * error
  4675.      * @return string Converter-specific class tree for an individual class
  4676.      * @param parserClass    class variable
  4677.      * @abstract
  4678.      */
  4679.  
  4680.     function getFormattedImplements($el)
  4681.     {
  4682.         $ret array();
  4683.         foreach ($el->getImplements(as $interface)
  4684.         {
  4685.             $link $this->getLink($interface);
  4686.             if ($link && is_object($link)) {
  4687.                 $ret[$this->returnSee($link);
  4688.             else {
  4689.                 if (class_exists('ReflectionClass')) {
  4690.                     if (interface_exists($interface)) {
  4691.                         $inter new ReflectionClass($interface);
  4692.                         if ($inter->isInternal()) {
  4693.                             $ret[$interface ' (internal interface)';
  4694.                         else {
  4695.                             $ret[$interface;
  4696.                         }
  4697.                     }
  4698.                 else {
  4699.                     $ret[$interface;
  4700.                 }
  4701.             }
  4702.         }
  4703.         return $ret;
  4704.     }
  4705.  
  4706.     /**
  4707.      * @param mixed {@link parserClass, parserFunction, parserDefine} or
  4708.      *  {@link parserGlobal}
  4709.      * @param string type to display.  either 'class','function','define'
  4710.      *                or 'global variable'
  4711.      * @return array links to conflicting elements, or empty array
  4712.      * @uses parserClass::getConflicts()
  4713.      * @uses parserFunction::getConflicts()
  4714.      * @uses parserDefine::getConflicts()
  4715.      * @uses parserGlobal::getConflicts()
  4716.      */
  4717.     function getFormattedConflicts(&$element,$type)
  4718.     {
  4719.         $conflicts $element->getConflicts($this);
  4720.         $r array();
  4721.         if (!$conflictsreturn false;
  4722.         foreach($conflicts as $package => $class)
  4723.         {
  4724.             $r[$class->getLink($this,$class->docblock->package);
  4725.         }
  4726.         if (!empty($r)) $r array('conflicttype' => $type'conflicts' => $r);
  4727.         return $r;
  4728.     }
  4729.  
  4730.     /**
  4731.      * Get a list of methods in child classes that override this method
  4732.      * @return array empty array or array(array('link'=>link to method,
  4733.      *  'sdesc'=>short description of the method),...)
  4734.      * @uses parserMethod::getOverridingMethods()
  4735.      * @param parserMethod 
  4736.      */
  4737.     function getFormattedDescMethods(&$element)
  4738.     {
  4739.         $meths $element->getOverridingMethods($this);
  4740.         $r array();
  4741.         for($i=0$i<count($meths)$i++)
  4742.         {
  4743.             $ms array();
  4744.             $ms['link'$meths[$i]->getLink($this);
  4745.             $ms['sdesc'$meths[$i]->docblock->getSDesc($this);
  4746.             $r[$ms;
  4747.         }
  4748.         return $r;
  4749.     }
  4750.  
  4751.     /**
  4752.      * Get a list of vars in child classes that override this var
  4753.      * @return array empty array or array('link'=>link to var,
  4754.      *  'sdesc'=>short description of the method
  4755.      * @uses parserVar::getOverridingVars()
  4756.      * @param parserVar 
  4757.      */
  4758.     function getFormattedDescVars(&$element)
  4759.     {
  4760.         $vars $element->getOverridingVars($this);
  4761.         $r array();
  4762.         for($i=0$i<count($vars)$i++)
  4763.         {
  4764.             $vs array();
  4765.             $vs['link'$vars[$i]->getLink($this);
  4766.             $vs['sdesc'$vars[$i]->docblock->getSDesc($this);
  4767.             $r[$vs;
  4768.         }
  4769.         return $r;
  4770.     }
  4771.  
  4772.     /**
  4773.      * Get the method this method overrides, if any
  4774.      * @return array|falsearray('link'=>link to overridden method,
  4775.      *  'sdesc'=>short description
  4776.      * @see parserMethod::getOverrides()
  4777.      * @param parserMethod 
  4778.      */
  4779.     function getFormattedOverrides(&$element)
  4780.     {
  4781.         $ovr $element->getOverrides($this);
  4782.         if (!$ovrreturn false;
  4783.         $sdesc $ovr->docblock->getSDesc($this);
  4784.         $name method_exists($ovr'getFunctionCall'$ovr->getFunctionCall($ovr->getName();
  4785.         $link ($link $ovr->getLink($this)) $link $ovr->getClass('::' $name;
  4786.         return array('link' => $link,'sdesc' => $sdesc);
  4787.     }
  4788.  
  4789.     /**
  4790.      * Get the method this method(s) implemented from an interface, if any
  4791.      * @return array|falsearray('link'=>link to implemented method,
  4792.      *  'sdesc'=>short description
  4793.      * @uses parserMethod::getImplements()
  4794.      * @param parserMethod 
  4795.      */
  4796.     function getFormattedMethodImplements(&$element)
  4797.     {
  4798.         $ovr $element->getImplements($this);
  4799.         if (!$ovrreturn false;
  4800.         $ret array();
  4801.         foreach ($ovr as $impl{
  4802.             $sdesc $impl->docblock->getSDesc($this);
  4803.             $name $impl->getName();
  4804.             $link ($link $impl->getLink($this)) $link $impl->getClass('::' $name;
  4805.             $ret[array('link' => $link,'sdesc' => $sdesc);
  4806.         }
  4807.         return $ret;
  4808.     }
  4809.  
  4810.     /**
  4811.      * returns a list of child classes
  4812.      *
  4813.      * @param parserClass class variable
  4814.      * @uses parserClass::getChildClassList()
  4815.      */
  4816.  
  4817.     function generateChildClassList($class)
  4818.     {
  4819.         $kids $class->getChildClassList($this);
  4820.         $list array();
  4821.         if (count($kids))
  4822.         {
  4823.             for($i=0$i<count($kids)$i++)
  4824.             {
  4825.                 $lt['link'$kids[$i]->getLink($this);
  4826.                 $lt['sdesc'$kids[$i]->docblock->getSDesc($this);
  4827.  
  4828.                                 if ($kids[$i]->docblock->hasaccess)
  4829.                                     $lt['access'$kids[$i]->docblock->tags['access'][0]->value;
  4830.                                 else
  4831.                                     $lt['access''public';
  4832.  
  4833.                                 $lt['abstract'= isset ($kids[$i]->docblock->tags['abstract'][0]);
  4834.  
  4835.                 $list[$lt;
  4836.             }
  4837.         else return false;
  4838.         return $list;
  4839.     }
  4840.  
  4841.     /**
  4842.      * Return template-enabled list of inherited variables
  4843.      *
  4844.      * uses parserVar helper function getInheritedVars and generates a
  4845.      * template-enabled list using getClassLink()
  4846.      * @param parserVar $child class var
  4847.      * @see getClassLink(), parserVar::getInheritedVars()
  4848.      * @return array Format:
  4849.      *  <pre>
  4850.      *  array(
  4851.      *    array('parent_class' => link to parent class's documentation,
  4852.      *          'ivars' =>
  4853.      *             array(
  4854.      *               array('name' => inherited variable name,
  4855.      *                     'link' => link to inherited variable's documentation,
  4856.      *                     'default' => default value of inherited variable,
  4857.      *                     'sdesc' => summary of inherited variable),
  4858.      *               ...),
  4859.      *    ...)
  4860.      *  </pre>
  4861.      */
  4862.  
  4863.     function getFormattedInheritedVars($child)
  4864.     {
  4865.         $package $child->docblock->package;
  4866.         $subpackage $child->docblock->subpackage;
  4867.         $ivars $child->getInheritedVars($this);
  4868.         $results array();
  4869.         if (!count($ivars)) return $results;
  4870.         foreach($ivars as $parent => $vars)
  4871.         {
  4872.             $file $vars['file'];
  4873.             $vars $vars['vars'];
  4874.             $par $this->classes->getClass($parent,$file);
  4875.             if ($par{
  4876.                 $package $par->docblock->package;
  4877.             }
  4878.             usort($vars,array($this,"sortVar"));
  4879.             $result['parent_class'$this->getClassLink($parent$package);
  4880.             if (!$result['parent_class']{
  4881.                 $result['parent_class'$parent ' (Internal Class)';
  4882.             }
  4883.             foreach($vars as $var)
  4884.             {
  4885.                 $info array();
  4886.  
  4887.                 if ($var->docblock->hasaccess{
  4888.                     $info['access'$var->docblock->tags['access'][0]->value;
  4889.                 else {
  4890.                     $info['access''public';
  4891.                 }
  4892.  
  4893.                 $info['abstract'= isset ($var->docblock->tags['abstract'][0]);
  4894.  
  4895.                 $info['name'$var->getName();
  4896.                 $info['link'$var->getLink($this);
  4897.                 if (!$info['link']{
  4898.                     $info['link'$info['name'];
  4899.                 }
  4900.                 $info['default'$this->postProcess($var->getValue());
  4901.                 if ($var->docblock)
  4902.                 $info['sdesc'$var->docblock->getSDesc($this);
  4903.                 $result["ivars"][$info;
  4904.             }
  4905.             $results[$result;
  4906.             $result array();
  4907.         }
  4908.         return $results;
  4909.     }
  4910.  
  4911.     /**
  4912.      * Return template-enabled list of inherited methods
  4913.      *
  4914.      * uses parserMethod helper function getInheritedMethods and generates a
  4915.      * template-enabled list using getClassLink()
  4916.      * @param parserMethod $child class method
  4917.      * @see getClassLink(), parserMethod::getInheritedMethods()
  4918.      * @return array Format:
  4919.      *  <pre>
  4920.      *  array(
  4921.      *    array('parent_class' => link to parent class's documentation,
  4922.      *          'ivars' =>
  4923.      *             array(
  4924.      *               array('name' => inherited variable name,
  4925.      *                     'link' => link to inherited variable's documentation,
  4926.      *                     'function_call' => {@link parserMethod::getIntricateFunctionCall()}
  4927.      *                                        returned array,
  4928.      *                     'sdesc' => summary of inherited variable),
  4929.      *               ...),
  4930.      *    ...)
  4931.      *  </pre>
  4932.      */
  4933.  
  4934.     function getFormattedInheritedMethods($child)
  4935.     {
  4936.         $package $child->docblock->package;
  4937.         $subpackage $child->docblock->subpackage;
  4938.         $imethods $child->getInheritedMethods($this);
  4939.         $results array();
  4940.         if (!count($imethods)) return $results;
  4941.         foreach($imethods as $parent => $methods)
  4942.         {
  4943.             $file $methods['file'];
  4944.             $methods $methods['methods'];
  4945.             $par $this->classes->getClass($parent,$file);
  4946.             if ($par{
  4947.                 $package $par->docblock->package;
  4948.             }
  4949.             usort($methods,array($this,"sortMethod"));
  4950.             $result['parent_class'$this->getClassLink($parent,$package);
  4951.             if (!$result['parent_class']{
  4952.                 $result['parent_class'$parent ' (Internal Class)';
  4953.             }
  4954.             foreach($methods as $method)
  4955.             {
  4956.                 $info array();
  4957.  
  4958.                 if ($method->docblock->hasaccess{
  4959.                     $info['access'$method->docblock->tags['access'][0]->value;
  4960.                 else {
  4961.                     $info['access''public';
  4962.                 }
  4963.                 $info['abstract'= isset ($method->docblock->tags['abstract'][0]);
  4964.  
  4965.                 if ($method->isConstructor$info['constructor'1;
  4966.                 $returntype 'void';
  4967.                 if ($method->isConstructor{
  4968.                     $returntype $method->getClass();
  4969.                 }
  4970.                 if ($method->docblock->return{
  4971.                     $a $method->docblock->return->Convert($this);
  4972.                     $returntype $method->docblock->return->converted_returnType;
  4973.                 }
  4974.                 $info['function_return'$returntype;
  4975.                 $info['static'= isset ($method->docblock->tags['static'][0]);
  4976.                 $info['link'$method->getLink($this);
  4977.                 if (!$info['link']{
  4978.                     $info['link'$method->getFunctionCall();
  4979.                 }
  4980.                 $info['name'$method->getName();
  4981.                 if ($method->docblock)
  4982.                 $info['sdesc'$method->docblock->getSDesc($this);
  4983.                 $params array();
  4984.                 if (count($method->docblock->params))
  4985.                 foreach($method->docblock->params as $param => $val)
  4986.                 {
  4987.                     $a $val->Convert($this);
  4988.                     $params[$paramarray("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
  4989.                 }
  4990.  
  4991.                 $info['function_call'$method->getIntricateFunctionCall($this,$params);
  4992.                 $result["imethods"][$info;
  4993.             }
  4994.             $results[$result;
  4995.             $result array();
  4996.         }
  4997.         return $results;
  4998.     }
  4999.  
  5000.     /**
  5001.      * Return template-enabled list of inherited class constants
  5002.      *
  5003.      * uses parserConst helper function getInheritedConsts and generates a
  5004.      * template-enabled list using getClassLink()
  5005.      * @param parserConst $child class constant
  5006.      * @see getClassLink(), parserMethod::getInheritedConsts()
  5007.      * @return array Format:
  5008.      *  <pre>
  5009.      *  array(
  5010.      *    array('parent_class' => link to parent class's documentation,
  5011.      *          'ivars' =>
  5012.      *             array(
  5013.      *               array('name' => inherited constant name,
  5014.      *                     'link' => link to inherited constant's documentation,
  5015.      *                     'value' => constant value,
  5016.      *                     'sdesc' => summary of inherited constant),
  5017.      *               ...),
  5018.      *    ...)
  5019.      *  </pre>
  5020.      */
  5021.  
  5022.     function getFormattedInheritedConsts($child)
  5023.     {
  5024.         $package $child->docblock->package;
  5025.         $subpackage $child->docblock->subpackage;
  5026.         $ivars $child->getInheritedConsts($this);
  5027.         $results array();
  5028.         if (!count($ivars)) return $results;
  5029.         foreach($ivars as $parent => $vars)
  5030.         {
  5031.             $file $vars['file'];
  5032.             $vars $vars['consts'];
  5033.             $par $this->classes->getClass($parent,$file);
  5034.             if ($par{
  5035.                 $package $par->docblock->package;
  5036.             }
  5037.             usort($vars,array($this,"sortVar"));
  5038.             $result['parent_class'$this->getClassLink($parent,$package);
  5039.             if (!$result['parent_class']{
  5040.                 $result['parent_class'$parent ' (Internal Class)';
  5041.             }
  5042.             foreach($vars as $var)
  5043.             {
  5044.                 $info array();
  5045.  
  5046.                 if ($var->docblock->hasaccess{
  5047.                     $info['access'$var->docblock->tags['access'][0]->value;
  5048.                 else {
  5049.                     $info['access''public';
  5050.                 }
  5051.                 $info['name'$var->getName();
  5052.                 $info['link'$var->getLink($this);
  5053.                 if (!$info['link']{
  5054.                     $info['link'$info['name'' = ' $var->getValue();
  5055.                 }
  5056.                 $info['value'$this->postProcess($var->getValue());
  5057.                 if ($var->docblock)
  5058.                 $info['sdesc'$var->docblock->getSDesc($this);
  5059.                 $result["iconsts"][$info;
  5060.             }
  5061.             $results[$result;
  5062.             $result array();
  5063.         }
  5064.         return $results;
  5065.     }
  5066.  
  5067.     /**
  5068.      * Return a Smarty template object to operate with
  5069.      *
  5070.      * This returns a Smarty template with pre-initialized variables for use.
  5071.      * If the method "SmartyInit()" exists, it is called.
  5072.      * @return Smarty 
  5073.      */
  5074.     function &newSmarty()
  5075.     {
  5076.         $templ new Smarty;
  5077.         $templ->use_sub_dirs false;
  5078.         $templ->template_dir realpath($this->smarty_dir PATH_DELIMITER 'templates');
  5079.         $templatename get_class($this$this->templateName;
  5080.         if (!file_exists($this->targetDir DIRECTORY_SEPARATOR md5($templatename))) {
  5081.             // we'll delete this on finishing conversion
  5082.             $this->_compiledDir[$this->targetDir DIRECTORY_SEPARATOR md5($templatename)1;
  5083.             mkdir($this->targetDir DIRECTORY_SEPARATOR md5($templatename),0775);
  5084.         }
  5085.         $templ->compile_dir realpath($this->targetDir PATH_DELIMITER md5($templatename));
  5086.         $templ->config_dir realpath($this->smarty_dir PATH_DELIMITER 'configs');
  5087.         $templ->assign("date",date("r",time()));
  5088.         $templ->assign("maintitle",$this->title);
  5089.         $templ->assign('default_package',$GLOBALS['phpDocumentor_DefaultPackageName']);
  5090.         $templ->assign("package",$this->package);
  5091.         $templ->assign("phpdocversion",PHPDOCUMENTOR_VER);
  5092.         $templ->assign("phpdocwebsite",PHPDOCUMENTOR_WEBSITE);
  5093.         $templ->assign("subpackage",$this->subpackage);
  5094.         if (method_exists($this,'SmartyInit')) return $this->SmartyInit($templ);
  5095.         return $templ;
  5096.     }
  5097.  
  5098.     /**
  5099.      * Finish up parsing/cleanup directories
  5100.      */
  5101.     function cleanup()
  5102.     {
  5103.         foreach ($this->_compiledDir as $dir => $one{
  5104.             $this->_rmdir($dir);
  5105.         }
  5106.     }
  5107.  
  5108.     /**
  5109.      * Completely remove a directory and its contents
  5110.      *
  5111.      * @param string $directory 
  5112.      */
  5113.     function _rmdir($directory)
  5114.     {
  5115.         $handle @opendir($directory);
  5116.         if ($handle{
  5117.             while (false !== ($file readdir($handle))) {
  5118.                 if ($file == '.' || $file == '..'{
  5119.                     continue;
  5120.                 }
  5121.                 if (is_dir($directory DIRECTORY_SEPARATOR $file)) {
  5122.                     $this->_rmdir($directory DIRECTORY_SEPARATOR $file);
  5123.                 }
  5124.                 @unlink($directory DIRECTORY_SEPARATOR $file);
  5125.             }
  5126.             closedir($handle);
  5127.             @rmdir($directory);
  5128.         }
  5129.     }
  5130.  
  5131.     /**
  5132.      * do all necessary output
  5133.      * @see Converter
  5134.      * @abstract
  5135.      */
  5136.     function Output($title)
  5137.     {
  5138.         phpDocumentor_out("WARNING: Generic Converter::Output was used, no output will be generated");
  5139.     }
  5140.  
  5141.     /**
  5142.      * Set the template directory with a different template base directory
  5143.      * @tutorial phpDocumentor.howto.pkg#using.command-line.templatebase
  5144.      * @param string template base directory
  5145.      * @param string template name
  5146.      */
  5147.     function setTemplateBase($base$dir)
  5148.     {
  5149.         // remove trailing /'s from the base path, if any
  5150.         $base str_replace('\\','/',$base);
  5151.         while ($base{strlen($base1== '/'$base substr($base,0,strlen($base1);
  5152.         $this->templateName substr($dir,0,strlen($dir1);
  5153.         $this->templateDir =  $base "/Converters/" $this->outputformat "/" $this->name "/templates/" $dir;
  5154.         if (!is_dir($this->templateDir))
  5155.         {
  5156.             addErrorDie(PDERROR_TEMPLATEDIR_DOESNT_EXIST$this->templateDir);
  5157.         }
  5158.  
  5159.         $this->smarty_dir $this->templateDir;
  5160.         if (file_exists($this->templateDir PATH_DELIMITER 'options.ini'))
  5161.         {
  5162.             // retrieve template options, allow array creation
  5163.             $this->template_options phpDocumentor_parse_ini_file($this->templateDir PATH_DELIMITER 'options.ini',true);
  5164.         }
  5165.     }
  5166.  
  5167.     /**
  5168.      * sets the template directory based on the {@link $outputformat} and {@link $name}
  5169.      * Also sets {@link $templateName} to the $dir parameter
  5170.      * @param string subdirectory
  5171.      */
  5172.     function setTemplateDir($dir)
  5173.     {
  5174.         if (isset($GLOBALS['_phpDocumentor_template_base'])) {
  5175.             $templateBase str_replace('\\''/'$GLOBALS['_phpDocumentor_template_base']);
  5176.         else if ('@DATA-DIR@' != '@'.'DATA-DIR@'{
  5177.             $templateBase str_replace('\\''/''@DATA-DIR@/PhpDocumentor/phpDocumentor');
  5178.         else {
  5179.             $templateBase str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']'/phpDocumentor';
  5180.         }
  5181.         $this->setTemplateBase($templateBase$dir);
  5182.     }
  5183.  
  5184.     /**
  5185.      * Get the absolute path to the converter's base directory
  5186.      * @return string 
  5187.      */
  5188.     function getConverterDir()
  5189.     {
  5190.         if ('@DATA-DIR@' != '@' 'DATA-DIR@'{
  5191.             return str_replace('\\''/'"@DATA-DIR@/PhpDocumentor/phpDocumentor/Converters/"$this->outputformat "/" $this->name;
  5192.         else {
  5193.             return str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']."/phpDocumentor/Converters/" $this->outputformat "/" $this->name;
  5194.         }
  5195.     }
  5196.  
  5197.     /**
  5198.      * Parse a global variable's default value for class initialization.
  5199.      *
  5200.      * If a global variable's default value is "new class" as in:
  5201.      * <code>
  5202.      * $globalvar = new Parser
  5203.      * </code>
  5204.      * This method will document it not as "new Parser" but instead as
  5205.      * "new {@link Parser}".    For examples, see {@link phpdoc.inc}.
  5206.      * Many global variables are classes, and phpDocumentor links to their
  5207.      * documentation
  5208.      * @return string default global variable value with link to class if
  5209.      *                 it's "new Class"
  5210.      * @param string default value of a global variable.
  5211.      */
  5212.     function getGlobalValue($value)
  5213.     {
  5214.         if (strpos($value,'new'=== 0)
  5215.         {
  5216.             preg_match('/new([^(]*)((?:.|\r|\n)*)/',$value,$newval);
  5217.             if (isset($newval[1]))
  5218.             {
  5219.                 $a Converter::getLink(trim($newval[1]));
  5220.                 if (!isset($newval[2])) $newval[2'';
  5221.                 if ($a && phpDocumentor_get_class($a== 'classlink'$value 'new '.$this->returnSee($a.
  5222.                     $this->postProcess($newval[2]);
  5223.             }
  5224.             return $value;
  5225.         }
  5226.         return $this->postProcess($value);
  5227.     }
  5228.  
  5229.     /**
  5230.      * Parse an include's file to see if it is a file documented in this project
  5231.      *
  5232.      * Although not very smart yet, this method will try to look for the
  5233.      * included file file.ext:
  5234.      *
  5235.      * <code>
  5236.      * include ("file.ext");
  5237.      * </code>
  5238.      *
  5239.      * If it finds it, it will return a link to the file's documentation.  As of
  5240.      * 1.2.0rc1, phpDocumentor is smarty enough to find these cases:
  5241.      * <ul>
  5242.      *  <li>absolute path to file</li>
  5243.      *  <li>./file.ext or ../file.ext</li>
  5244.      *  <li>relpath/to/file.ext if relpath is a subdirectory of the base parse
  5245.      *      directory</li>
  5246.      * </ul>
  5247.      * For examples, see {@link Setup.inc.php} includes.
  5248.      * Every include auto-links to the documentation for the file that is included
  5249.      * @return string included file with link to docs for file, if found
  5250.      * @param string file included by include statement.
  5251.      * @param string path of file that has the include statement
  5252.      */
  5253.     function getIncludeValue($value$ipath)
  5254.     {
  5255.         preg_match('/"([^"\']*\.[^"\']*)"/',$value,$match);
  5256.         if (!isset($match[1]))
  5257.         preg_match('/\'([^"\']*\.[^"\']*)\'/',$value,$match);
  5258.         if (isset($match[1]))
  5259.         {
  5260.             $fancy_per $this->proceduralpages->pathMatchesParsedFile($match[1],$ipath);
  5261.             if ($fancy_per)
  5262.             {
  5263.                 $link $this->addLink($fancy_per);
  5264.                 if (is_object($link&& phpDocumentor_get_class($link== 'pagelink' &&
  5265.                     isset($this->all_packages[$link->package]))
  5266.                 {
  5267.                     $value $this->returnSee($link,$value);
  5268.                 }
  5269.             else
  5270.             {
  5271.                 $per Converter::getLink($match[1]);
  5272.                 if (is_object($per&& phpDocumentor_get_class($per== 'pagelink')
  5273.                 $value $this->returnSee($per);
  5274.             }
  5275.         }
  5276.         return $value;
  5277.     }
  5278.  
  5279.     /**
  5280.      * Recursively creates all subdirectories that don't exist in the $dir path
  5281.      * @param string $dir 
  5282.      */
  5283.     function createParentDir($dir)
  5284.     {
  5285.         if (empty($dir)) return;
  5286.         $tmp explode(SMART_PATH_DELIMITER,$dir);
  5287.         array_pop($tmp);
  5288.         $parent implode(SMART_PATH_DELIMITER,$tmp);
  5289.         if ($parent != '' && !file_exists($parent))
  5290.         {
  5291.             $test @mkdir($parent,0775);
  5292.             if (!$test)
  5293.             {
  5294.                 $this->createParentDir($parent);
  5295.                 $test @mkdir($parent,0775);
  5296.                 phpDocumentor_out("Creating Parent Directory $parent\n");
  5297.             else
  5298.             {
  5299.                 phpDocumentor_out("Creating Parent Directory $parent\n");
  5300.             }
  5301.         }
  5302.     }
  5303.  
  5304.     /**
  5305.      * Sets the output directory for generated documentation
  5306.      * 
  5307.      * As of 1.3.0RC6, this also sets the compiled templates directory inside
  5308.      * the target directory
  5309.      * @param string $dir the output directory
  5310.      */
  5311.     function setTargetDir($dir)
  5312.     {
  5313.         if (strlen($dir0)
  5314.         {
  5315.             $this->targetDir $dir;
  5316.             // if directory does exist create it, this should have more error checking in the future
  5317.             if (!file_exists($dir))
  5318.             {
  5319.                 $tmp str_replace(array("/","\\"),SMART_PATH_DELIMITER,$dir);
  5320.                 if (substr($tmp,-1== SMART_PATH_DELIMITER)
  5321.                 {
  5322.                     $tmp substr($tmp,0,(strlen($tmp)-1));
  5323.                 }
  5324.                 $this->createParentDir($tmp);
  5325.                 phpDocumentor_out("Creating Directory $dir\n");
  5326.                 mkdir($dir,0775);
  5327.             elseif (!is_dir($dir))
  5328.             {
  5329.                 echo "Output path: '$dir' is not a directory\n";
  5330.                 die();
  5331.             }
  5332.         else {
  5333.             echo "a target directory must be specified\n try phpdoc -h\n";
  5334.             die();
  5335.         }
  5336.     }
  5337.  
  5338.     /**
  5339.      * Writes a file to target dir
  5340.      * @param string 
  5341.      * @param string 
  5342.      * @param boolean true if the data is binary and not text
  5343.      */
  5344.     function writeFile($file,$data,$binary false)
  5345.     {
  5346.         if (!file_exists($this->targetDir))
  5347.         {
  5348.             mkdir($this->targetDir,0775);
  5349.         }
  5350.         $string '';
  5351.         if ($binary$string 'binary file ';
  5352.         phpDocumentor_out("    Writing $string".$this->targetDir PATH_DELIMITER $file "\n");
  5353.         flush();
  5354.         $write 'w';
  5355.         if ($binary$write 'wb';
  5356.         $fp fopen($this->targetDir PATH_DELIMITER $file,$write);
  5357.         set_file_buffer$fp);
  5358.         fwrite($fp,$data,strlen($data));
  5359.         fclose($fp);
  5360.     }
  5361.  
  5362.     /**
  5363.      * Copies a file from the template directory to the target directory
  5364.      * thanks to Robert Hoffmann for this fix
  5365.      * @param string 
  5366.      */
  5367.     function copyFile($file$subdir '')
  5368.     {
  5369.         if (!file_exists($this->targetDir))
  5370.         {
  5371.             mkdir($this->targetDir,0775);
  5372.         }
  5373.         copy($this->templateDir $subdir  PATH_DELIMITER $file$this->targetDir PATH_DELIMITER $file);
  5374.     }
  5375.  
  5376.     /**
  5377.      * Return parserStringWithInlineTags::Convert() cache state
  5378.      * @see parserStringWithInlineTags::Convert()
  5379.      * @abstract
  5380.      */
  5381.     function getState()
  5382.     {
  5383.         return true;
  5384.     }
  5385.  
  5386.     /**
  5387.      * Compare parserStringWithInlineTags::Convert() cache state to $state
  5388.      * @param mixed 
  5389.      * @see parserStringWithInlineTags::Convert()
  5390.      * @abstract
  5391.      */
  5392.     function checkState($state)
  5393.     {
  5394.         return true;
  5395.     }
  5396.  
  5397. }
  5398.  
  5399. /**
  5400.  * @access private
  5401.  * @see Converter::getSortedClassTreeFromClass()
  5402.  */
  5403. function rootcmp($a$b)
  5404. {
  5405.     return strnatcasecmp($a['class'],$b['class']);
  5406. }
  5407.  
  5408. /**
  5409.  * @access private
  5410.  * @global string used to make the first tutorials converted the default package tutorials
  5411.  */
  5412. function tutorialcmp($a$b)
  5413. {
  5414.     global $phpDocumentor_DefaultPackageName;
  5415.     if ($a == $phpDocumentor_DefaultPackageNamereturn -1;
  5416.     if ($b == $phpDocumentor_DefaultPackageNamereturn 1;
  5417.     return strnatcasecmp($a$b);
  5418. }
  5419.  
  5420. /**
  5421.  * smart htmlentities, doesn't entity the allowed tags list
  5422.  * Since version 1.1, this function uses htmlspecialchars instead of
  5423.  * htmlentities, for international support
  5424.  * This function has been replaced by functionality in {@link ParserDescCleanup.inc}
  5425.  * @param string $s 
  5426.  * @return string browser-displayable page
  5427.  * @deprecated As of v1.2, No longer needed, as valid tags are parsed out of the source,
  5428.  *    and everything else is {@link Converter::postProcess()} handled
  5429.  */
  5430. function adv_htmlentities($s)
  5431. {
  5432.     return;
  5433.     global $phpDocumentor___html,$_phpDocumentor_html_allowed;
  5434.     $result htmlspecialchars($s);
  5435.     $entities array_flip(get_html_translation_table(HTML_SPECIALCHARS));
  5436.     $result strtr($result,$phpDocumentor___html);
  5437.     $matches array();
  5438.     preg_match_all('/(&lt;img.*&gt;)/U',$result,$matches);
  5439.     for($i=0;$i<count($matches[1]);$i++)
  5440.     {
  5441.         $result str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
  5442.     }
  5443.     preg_match_all('/(&lt;font.*&gt;)/U',$result,$matches);
  5444.     for($i=0;$i<count($matches[1]);$i++)
  5445.     {
  5446.         $result str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
  5447.     }
  5448.     preg_match_all('/(&lt;ol.*&gt;)/U',$result,$matches);
  5449.     for($i=0;$i<count($matches[1]);$i++)
  5450.     {
  5451.         $result str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
  5452.     }
  5453.     preg_match_all('/(&lt;ul.*&gt;)/U',$result,$matches);
  5454.     for($i=0;$i<count($matches[1]);$i++)
  5455.     {
  5456.         $result str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
  5457.     }
  5458.     preg_match_all('/(&lt;li.*&gt;)/U',$result,$matches);
  5459.     for($i=0;$i<count($matches[1]);$i++)
  5460.     {
  5461.         $result str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
  5462.     }
  5463.     preg_match_all('/(&lt;a .*&gt;)/U',$result,$matches);
  5464.     for($i=0;$i<count($matches[1]);$i++)
  5465.     {
  5466.         $result str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
  5467.     }
  5468.     return $result;
  5469. }
  5470.  
  5471. /**
  5472.  * Used solely for setting up the @uses list
  5473.  * @package ignore
  5474.  * @ignore
  5475.  */
  5476. class __dummyConverter extends Converter
  5477. {
  5478.     function setTemplateDir(){}
  5479.     function setTargetDir(){}
  5480.     function getPageName(&$element)
  5481.     {
  5482.         if (phpDocumentor_get_class($element== 'parserpage'return '_'.$element->getName();
  5483.         return '_'.$element->parent->getName();
  5484.     }
  5485. }
  5486. ?>

Documentation generated on Mon, 05 Dec 2011 21:14:50 -0600 by phpDocumentor 1.4.4