phpDocumentor
[ class tree: phpDocumentor ] [ index: phpDocumentor ] [ all elements ]

Source for file IntermediateParser.inc

Documentation is available at IntermediateParser.inc

  1. <?php
  2. /**
  3.  * The phpDocumentor_IntermediateParser Class
  4.  *
  5.  * The Intermediary Data Parser (intermediate between Parse and Converter)
  6.  *
  7.  * phpDocumentor :: automatic documentation generator
  8.  * 
  9.  * PHP versions 4 and 5
  10.  *
  11.  * Copyright (c) 2002-2006 Gregory Beaver
  12.  * 
  13.  * LICENSE:
  14.  * 
  15.  * This library is free software; you can redistribute it
  16.  * and/or modify it under the terms of the GNU Lesser General
  17.  * Public License as published by the Free Software Foundation;
  18.  * either version 2.1 of the License, or (at your option) any
  19.  * later version.
  20.  * 
  21.  * This library is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  24.  * Lesser General Public License for more details.
  25.  * 
  26.  * You should have received a copy of the GNU Lesser General Public
  27.  * License along with this library; if not, write to the Free Software
  28.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  29.  *
  30.  * @package    phpDocumentor
  31.  * @author     Gregory Beaver <cellog@php.net>
  32.  * @copyright  2002-2006 Gregory Beaver
  33.  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
  34.  * @version    CVS: $Id: IntermediateParser.inc,v 1.19.2.1 2007/03/29 18:51:11 ashnazg Exp $
  35.  * @filesource
  36.  * @link       http://www.phpdoc.org
  37.  * @link       http://pear.php.net/PhpDocumentor
  38.  * @since      1.1
  39.  */
  40. /** The phpDocumentor_IntermediateParser Class
  41.  *
  42.  * This class performs the work of organizing raw data from the parser in the
  43.  * format of descendants of the {@link parserElement} class.  This is also where
  44.  * processing of package pages occurs, in
  45.  * {@link phpDocumentor_IntermediateParser::handleClass()} for class-level
  46.  * packages and {@link phpDocumentor_IntermediateParser::handleDocBlock()} for
  47.  * page-level packages.
  48.  *
  49.  * Most of the work of this parser goes to matching up
  50.  * DocBlocks with the elements that they are documenting.  Since DocBlocks are
  51.  * passed before the element they document, the last DocBlock is stored in
  52.  * {@link phpDocumentor_IntermediateParser::$last} and then placed into the
  53.  * $docblock parameter of the parserElement
  54.  * descendant object.
  55.  *  @author Gregory Beaver
  56.  *  @version $Id: IntermediateParser.inc,v 1.19.2.1 2007/03/29 18:51:11 ashnazg Exp $
  57.  *  @copyright 2002 Gregory Beaver
  58.  *  @package     phpDocumentor
  59.  */
  60. {
  61.     /**
  62.      * @var parserDocBlock 
  63.      */
  64.     var $last;
  65.     
  66.     /**
  67.      * type of the last parser Element handled
  68.      *
  69.      * This is used in handleDocBlock to determine whether a DocBlock is a
  70.      * page-level DocBlock in conjunction with the {@link parserData::$clean}
  71.      * var.  A page-level DocBlock is alwaysthe first DocBlock in a file, and
  72.      * must be followed by another DocBlock.  The first test is handled by
  73.      * parserData::$clean, which is set to false on the first encounter of an
  74.      * element, and the second test is handled by this variable, which must be
  75.      * equal to "docblock"
  76.      * @see handleDocBlock()
  77.      * @var string 
  78.      */
  79.     var $lasttype = '';
  80.     
  81.     /**
  82.      * Name of the class currently being parsed.
  83.      * It is only used (and only valid) when phpDocumentor_IntermediateParser is
  84.      * parsing a class
  85.      * @var string 
  86.      */
  87.     var $cur_class = '';
  88.     
  89.     /**
  90.      * type of the current parser Element being handled
  91.      * 
  92.      * This is used by {@link HandleEvent()} to set the {@link $lasttype} var,
  93.      * which is used to detect page-level DocBlocks
  94.      * @var string 
  95.      */
  96.     var $type = '';
  97.     
  98.     /**
  99.      * set in {@link Setup.inc.php} to the value of the parseprivate commandline
  100.      * option.  If this option is true, elements with an @access private tag
  101.      * will be parsed and displayed
  102.      * @tutorial phpDocumentor.howto.pkg#using.command-line.parseprivate
  103.      * @var boolean 
  104.      */
  105.     var $parsePrivate = false;
  106.     
  107.     /**
  108.      * this variable is used to prevent parsing of elements with an @ignore tag
  109.      * @see $packageoutput
  110.      * @see $parsePrivate
  111.      */
  112.     var $private_class = false;
  113.     
  114.     /**
  115.      * used to set the output directory
  116.      * @see setTargetDir()
  117.      */
  118.     var $targetDir;
  119.     
  120.     /**
  121.      * used to set the template base directory
  122.      * @see setTemplateBase()
  123.      */
  124.     var $templateBase;
  125.     
  126.     /**
  127.      * array of parsed package pages
  128.      *
  129.      * used by {@link Convert()} to convert all package pages into output
  130.      * @var array 
  131.      */
  132.     var $package_pages = array();
  133.     
  134.     /**
  135.      * @var array array of all {@link parserData} containing page information
  136.      */
  137.     var $pages = array();
  138.     /**
  139.      * Put away a page that has been @ignored or @access private if
  140.      * !{@link $parsePrivate}
  141.      *
  142.      * When a page has @access private in its DocBlock, it is placed here
  143.      * instead of in {@link $pages}, to allow for proper Class parsing.  Since
  144.      * classes and pages are parsed as if they were separate, this array allows
  145.      * public classes on private pages to retrieve information needed about the
  146.      * page that holds the class and to {@link addPageIfNecessary()} to the
  147.      * $pages array
  148.      * @var array 
  149.      */
  150.     var $privatepages = array();
  151.     /**
  152.      * Keeps track of packages of classes that have parent classes in another
  153.      * package.  Used in automatic linking.
  154.      *
  155.      * This array is updated by {@link addPackageParent()}, which is called in
  156.      * {@link Classes::processChild()} to keep track of classes that descend
  157.      * from classes in different packages.  In other words, if class foo is in
  158.      * package one, and class bar is in package two, an entry
  159.      * $package_parents['two'] = 'one' will be made.
  160.      * @var array Format: packagename => parentpackagename
  161.      * @see Converter::getLink()
  162.      */
  163.     var $package_parents = array();
  164.     
  165.     /**
  166.      * Used to determine the category for tutorials.
  167.      *
  168.      * <b>WARNING:</b> If more than one category exists, the last category
  169.      * encountered will overwrite the previous and will raise a big warning
  170.      * @var array Format: packagename => categoryname
  171.      */
  172.     var $packagecategories = array();
  173.     
  174.     /**
  175.      * list of all packages encountered while documenting.  Used in automatic
  176.      * linking.
  177.      * 
  178.      * Converter::getLink() first checks if an ambiguous link is found in the
  179.      * current package.  If not, it then checks in parent packages, and if still
  180.      * not found, uses this array to check in the rest of the packages before
  181.      * giving up
  182.      * @var array Format: array(packagename => 1, packagename => 1,...)
  183.      * @see Converter::getLink()
  184.      */
  185.     var $all_packages = array();
  186.     
  187.     /**
  188.      * array of packages to parser and output documentation for, if not all
  189.      * packages should be documented
  190.      *
  191.      * Format:<br />
  192.      * array(package1,package2,...)<br />
  193.      * or false if not set
  194.      *
  195.      * Use this option to limit output similar to ignoring files.  If you have
  196.      * some temporary files that you don't want to specify by name but don't
  197.      * want included in output, set a package name for all the elements in your
  198.      * project, and set packageoutput to that name.  the default package will be
  199.      * ignored.  Parsing speed does not improve.  If you want to ignore files
  200.      * for speed reasons, use the ignore command-line option
  201.      * @tutorial phpDocumentor.howto.pkg#using.command-line.packageoutput
  202.      * @see Io
  203.      * @var false|array
  204.      */
  205.     var $packageoutput = false;
  206.     
  207.     /**
  208.      * the functions which handle output from the {@link Parser}
  209.      * @see handleEvent(), handleDocBlock(), handlePage(), handleClass()
  210.      * @see handleDefine(), handleFunction(), handleMethod(), handleVar()
  211.      * @see handlePackagePage(), handleInclude(), handleTutorial()
  212.      */
  213.     var $event_handlers = array(
  214.             'docblock' => 'handleDocBlock',
  215.             'page' => 'handlePage',
  216.             'class' => 'handleClass',
  217.             'define' => 'handleDefine',
  218.             'function' => 'handleFunction',
  219.             'method' => 'handleMethod',
  220.             'var' => 'handleVar',
  221.             'const' => 'handleConst',
  222.             'packagepage' => 'handlePackagePage',
  223.             'include' => 'handleInclude',
  224.             'global' => 'handleGlobal',
  225.             'tutorial' => 'handleTutorial',
  226.             );
  227.     
  228.     /**
  229.      * $data contains parsed structures for the current page being parsed
  230.      *
  231.      * In version 1.1+, $data is only used to store the current page information.
  232.      * All handling of documented elements is handled by the
  233.      * {@link ProceduralPages} and {@link Classes} classes.
  234.      * @var parserData 
  235.      */
  236.     var $data;
  237.     
  238.     /**
  239.      * set in {@link Setup.inc.php} to the value of the quitemode commandline
  240.      * option.
  241.      *
  242.      * If this option is true, informative output while parsing will not be
  243.      * displayed (documentation is unaffected)
  244.      * @var boolean 
  245.      * @tutorial phpDocumentor.howto.pkg#using.command-line.quiet
  246.      */
  247.     var $quietMode = false;
  248.         
  249.     /**
  250.      * used to keep track of inheritance at the smartest level possible for a
  251.      * dumb computer
  252.      * @var Classes 
  253.      */
  254.     var $classes = false;
  255.     
  256.     /**
  257.      * used to keep track of all elements in a procedural page.  Handles name
  258.      * conflicts with elegance
  259.      * @since 1.1
  260.      * @var ProceduralPages 
  261.      */
  262.     var $proceduralpages = false;
  263.     
  264.     /**
  265.      * an array of template names indexed by converter name
  266.      *
  267.      * For example, if the default HTMLframesConverter is using the DOM/l0l33t
  268.      * template, the array will be
  269.      * <code>$converters['frames'] = 'DOM/l0l33t'</code>
  270.      * @var array Format: array(Convertername1 => templatename)
  271.      * @see Converter
  272.      */
  273.     var $converters = false;
  274.     /** 
  275.      * @var string Title of generated documentation, passed to Converters
  276.      */
  277.     var $title = '';
  278.     
  279.     var $uses = array();
  280.  
  281.     var $db_template;
  282.     
  283.     /**
  284.      * Stores parsed CHANGELOG/INSTALL/README files
  285.      * @var array Format: array(CHANGELOG => contents,
  286.      *                           INSTALL => contents,
  287.      *                           README => contents)
  288.      */
  289.     var $ric = array();
  290.     
  291.     /**
  292.      * Flag used to determine whether the last docblock
  293.      * was a page-level docblock.
  294.      * @var boolean 
  295.      * @access private
  296.      */
  297.     var $_lastDocBlockWasPageLevel = false;
  298.     
  299.     /**
  300.      * Flag used to determine whether the Page-level
  301.      * DocBlock was declared in old or new style
  302.      * @var boolean 
  303.      * @access private
  304.      */
  305.     var $_oldPageLevel = false;
  306.  
  307.     /**
  308.      * sets up basic data structures
  309.      * @param string Title of generated documentation, passed to Converters
  310.      * @see $title, $data, $classes, $proceduralpages
  311.      */
  312.     function phpDocumentor_IntermediateParser($title='Generated Documentation')
  313.     {
  314.         $this->title = $title;
  315.         $this->data = new parserData;
  316.         $this->classes = new Classes;
  317.         $this->proceduralpages = new ProceduralPages;
  318.     }
  319.     
  320.     /**
  321.      * Retrieve the relative path.  If the path contains "pear/" it will
  322.      * be used as the base, otherwise the Program_Root string will be used.
  323.      * @global array uses 'Program_Root' option to replace it with '' for
  324.      *                retrieving the source location of a file
  325.      * @param string path to file
  326.      * @return string 
  327.      * @see $sourceLocation
  328.      * @access private
  329.      */
  330.     function _getSourceLocation($sl$sourceloc)
  331.     {
  332.         global $_phpDocumentor_options;
  333.         if (empty($sl)) return false;
  334.         $sl str_replace('\\','/',$sl);
  335.         if (strpos($sl,'pear/'))
  336.         {
  337.             $sl substr($sl,strpos($sl,'pear/'+ 5);
  338.             if (dirname($sl== '.')
  339.             {
  340.                 return 'PEAR';
  341.             }
  342.             return dirname($sl);
  343.         else
  344.         {
  345.             if (strpos(str_replace($_phpDocumentor_options['Program_Root'PATH_DELIMITER,'',$sourceloc),PATH_DELIMITER=== false)
  346.                 return '';
  347.             return dirname(str_replace($_phpDocumentor_options['Program_Root'PATH_DELIMITER,'',$sourceloc));
  348.         }
  349.     }
  350.     
  351.     /**
  352.      * Guess the package/subpackage based on subdirectory if the --pear option
  353.      *
  354.      * A file in pear/dir/file.php will be in package "dir."  A file in
  355.      * pear/dir/subdir/file.php will be in package "dir," subpackage "subdir."
  356.      * @param string full path of file
  357.      * @param template-ready source location Program_Root/dir/file.php
  358.      * @global array uses the 'pear' option to determine whether to guess based
  359.      *                on subdirectory
  360.      * @tutorial phpDocumentor.howto.pkg#using.command-line.pear
  361.      */
  362.     function _guessPackage($path$sourceloc)
  363.     {
  364.         global $_phpDocumentor_setting;
  365.         if ($_phpDocumentor_setting['pear'])
  366.         {
  367.             $subpath explode(PATH_DELIMITER$this->_getSourceLocation($path$sourceloc));
  368.             if (!empty($subpath[0]))
  369.             // can only have package and subpackage in this version
  370.                 $package $subpath[0];
  371.                 $subpackage '';
  372.                 if (isset($subpath[1])) $subpackage $subpath[1];
  373.                 return array($package,$subpackage);
  374.             else return array($this->package$this->subpackage);
  375.         else return array($this->package$this->subpackage);
  376.     }
  377.     
  378.     /**
  379.      * handles post-parsing of include/require/include_once/require_once
  380.      *
  381.      * This function sets {@link $data}->clean to false to tell the
  382.      * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
  383.      * found after this point on this page.  It then sets the package
  384.      * to be the same as the page, and adds itself to the
  385.      * {@link ProceduralPages} class
  386.      * @param integer $event Event number from {@link Parser.inc}
  387.      * @param parserInclude $data 
  388.      */
  389.     function handleInclude($event,$data)
  390.     {
  391.         if ($this->_lastDocBlockWasPageLevel)
  392.         {
  393.             addWarning(PDERROR_DOCBLOCK_CONFLICT$data->getName()$data->getValue());
  394.             if (!$this->_oldPageLevel)
  395.             {
  396.                 unset($this->last);
  397.             }
  398.         }
  399.         $this->_lastDocBlockWasPageLevel = false;
  400.         $this->data->clean = false;
  401.         // page was @ignored
  402.         if ($this->private_page)
  403.         {
  404.             unset($this->last);
  405.             return;
  406.         }
  407.         if (empty($this->last))
  408.         {
  409.             if (isset($this->db_template))
  410.             {
  411.                 // use the docblock template
  412.                 $this->last = phpDocumentor_clone($this->db_template);
  413.             }
  414.             else
  415.             {
  416.                 // we don't have a docblock, create an empty one to get rid of errors
  417.                 $this->last = new parserDocblock();
  418.             }
  419.         }
  420. //        $this->last->setLineNumber($data->getLineNumber());
  421.         if ($this->last->getKeyword('ignore'))
  422.         {
  423.             $this->last = false;
  424.             return;
  425. //            addWarning(PDERROR_IGNORE_TAG_IGNORED,'include',$data->getName().'('.$data->getValue().')');
  426.         }
  427.  
  428.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'include');
  429.         $data->setDocBlock($this->last);
  430.         $this->proceduralpages->addInclude($data);
  431.         $this->last = false;
  432.     }
  433.     
  434.     /**
  435.      * handles post-parsing of global variables
  436.      *
  437.      * This function sets {@link $data}->clean to false to tell the
  438.      * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
  439.      * found after this point on this page.  It then sets the package
  440.      * to be the same as the page, and adds itself to the
  441.      * {@link ProceduralPages} class
  442.      * @param integer $event Event number from {@link Parser.inc}
  443.      * @param parserGlobal $data 
  444.      */
  445.     function handleGlobal($event,$data)
  446.     {
  447.         if ($this->_lastDocBlockWasPageLevel)
  448.         {
  449.             addWarning(PDERROR_DOCBLOCK_CONFLICT'global variable'$data->getName());
  450.             if (!$this->_oldPageLevel)
  451.             {
  452.                 unset($this->last);
  453.             }
  454.         }
  455.         $this->_lastDocBlockWasPageLevel = false;
  456.         $this->data->clean = false;
  457.         if ($this->private_page)
  458.         {
  459.             unset($this->last);
  460.             return;
  461.         }
  462.         if (empty($this->last))
  463.         {
  464.             if (isset($this->db_template))
  465.             {
  466.                 // use the docblock template
  467.                 $this->last = phpDocumentor_clone($this->db_template);
  468.             }
  469.             else
  470.             {
  471.                 // we don't have a docblock, create an empty one to get rid of errors
  472.                 $this->last = new parserDocblock();
  473.             }
  474.         }
  475. //        $this->last->setLineNumber($data->getLineNumber());
  476.         if ($this->last->getKeyword('ignore'))
  477.         {
  478.             addWarning(PDERROR_IGNORE_TAG_IGNORED,'global variable - just don\'t document the',$data->getName());
  479.             $this->last = false;
  480.             return;
  481.         }
  482.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'global');
  483.         $data->setDocBlock($this->last);
  484.         if ($data->docblock->getKeyword('name'))
  485.         {
  486.             $a $data->docblock->getKeyword('name');
  487.             if (is_object($a)) $a $a->value;
  488.             $data->setName($a);
  489.         }
  490.         $this->proceduralpages->addGlobal($data);
  491.         $this->last = false;
  492.     }
  493.     
  494.     /**
  495.      * handles post-parsing of Package-level documentation pages.
  496.      *
  497.      * sets the {@link $package_pages}[$data->package] to $data
  498.      * @param integer $event Event number from {@link Parser.inc}
  499.      * @param parserPackagePage $data 
  500.      */
  501.     function handlePackagePage($event,$data)
  502.     {
  503.         $this->package_pages[$data->package&$data;
  504.         $this->last = false;
  505.     }
  506.     
  507.     /**
  508.      * handle post-parsing of Tutorials.
  509.      *
  510.      * This adds the parsed tutorial to the tutorial tree
  511.      * @uses $tutorials sets the value of tutorials to parameter $data
  512.      * @param integer $event Event Number
  513.      * @param parserTutorial $data 
  514.      * @since 1.2
  515.      */
  516.     function handleTutorial($event,$data)
  517.     {
  518.         if (isset($this->packagecategories[$data->package]))
  519.         {
  520.             $data->category = $this->packagecategories[$data->package];
  521.         else
  522.         {
  523.             $data->category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
  524.         }
  525.         $this->tutorials[$data->package][$data->subpackage][$data->tutorial_type][$data->name$data;
  526.     }
  527.     
  528.     /**
  529.      * handles post-parsing of class vars
  530.      *
  531.      * This function sets up a @var tag if none is found, and aligns $data's
  532.      * $path var and packages to match the parent object
  533.      * @param integer $event Event number from {@link Parser.inc}
  534.      * @param parserVar $data 
  535.      */
  536.     function handleVar($event,$data)
  537.     {
  538.         global $_phpDocumentor_setting;
  539.         if ($this->private_class)
  540.         {
  541.             unset($this->last);
  542.             return;
  543.         }
  544.         if (empty($this->last))
  545.         {
  546.             if (isset($this->db_template))
  547.             {
  548.                 // use the docblock template
  549.                 $this->last = phpDocumentor_clone($this->db_template);
  550.             
  551.             else 
  552.             {
  553.                 // we don't have a docblock, create an empty one to get rid of errors
  554.                 $this->last = new parserDocblock();
  555.             }
  556.         }
  557. //        $this->last->setLineNumber($data->getLineNumber());
  558.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'var');
  559.         $this->last->updateModifiers($data->getModifiers());
  560.  
  561.         if ($this->last->getKeyword('ignore'))
  562.         {
  563.             $this->last = false;
  564.             return;
  565. //            addWarning(PDERROR_IGNORE_TAG_IGNORED,'var',$this->cur_class.'::'.$data->getName());
  566.         }
  567.         if (!$this->last->var)
  568.         {
  569.             $this->last->addVar('mixed',new parserStringWithInlineTags);
  570.         }
  571.         
  572.         if ($_phpDocumentor_setting['pear'])
  573.         {
  574.             if (strpos($data->getName()'_'== 1 && !$this->last->getKeyword('access'))
  575.             {
  576.                 addWarning(PDERROR_PRIVATE_ASSUMED,'class variable',$data->class.'::'.$data->getName());
  577.                 $this->last->addKeyword('access','private');
  578.                 $data->setDocBlock($this->last);
  579.             }
  580.         }
  581.         $data->setDocBlock($this->last);
  582.         $data->path = $this->data->parent->path;
  583.         $this->classes->addVar($data);
  584.         $this->last = false;
  585.     }
  586.     
  587.     /**
  588.      * handles post-parsing of class constants
  589.      *
  590.      * This function aligns $data's
  591.      * $path var and packages to match the parent object
  592.      * @param integer $event Event number from {@link Parser.inc}
  593.      * @param parserVar $data 
  594.      */
  595.     function handleConst($event,$data)
  596.     {
  597.         global $_phpDocumentor_setting;
  598.         if ($this->private_class)
  599.         {
  600.             unset($this->last);
  601.             return;
  602.         }
  603.         if (empty($this->last))
  604.         {
  605.             if (isset($this->db_template))
  606.             {
  607.                 // use the docblock template
  608.                 $this->last = phpDocumentor_clone($this->db_template);
  609.             }
  610.             else
  611.             {
  612.                 // we don't have a docblock, create an empty one to get rid of errors
  613.                 $this->last = new parserDocblock();
  614.             }
  615.         }
  616. //        $this->last->setLineNumber($data->getLineNumber());
  617.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'const');
  618.  
  619.         if ($this->last->getKeyword('ignore'))
  620.         {
  621.             $this->last = false;
  622.             return;
  623. //            addWarning(PDERROR_IGNORE_TAG_IGNORED,'var',$this->cur_class.'::'.$data->getName());
  624.         }
  625.         $data->setDocBlock($this->last);
  626.         $data->path = $this->data->parent->path;
  627.         $this->classes->addConst($data);
  628.         $this->last = false;
  629.     }
  630.     
  631.     /**
  632.      * handles post-parsing of class methods
  633.      *
  634.      * This function first aligns $data's path and package to match the parent
  635.      * object, and also aligns the docblock's @param, @global, and @staticvar
  636.      * tags with the information parsed from the method source code.  It also
  637.      * checks to see if the method is a constructor and sets the $isConstructor
  638.      * flag.  If source code has been parsed by a {@}source} tag, the source is
  639.      * added to its docblock
  640.      *
  641.      * Finally, it adds the method to the {@link Classes} class.
  642.      * @param integer $event Event number from {@link Parser.inc}
  643.      * @param parserMethod $data 
  644.      */
  645.     function handleMethod($event,$data)
  646.     {
  647.         global $_phpDocumentor_setting;
  648.         if ($this->private_class)
  649.         {
  650.             unset($this->last);
  651.             return;
  652.         }
  653.  
  654.         if (empty($this->last))
  655.         {
  656.             if (isset($this->db_template))
  657.             {
  658.                 // use the docblock template
  659.                 $this->last = phpDocumentor_clone($this->db_template);
  660.             }
  661.             else
  662.             {
  663.                 // we don't have a docblock, create an empty one to get rid of errors
  664.                 $this->last = new parserDocblock();
  665.             }
  666.         }
  667. //        $this->last->setLineNumber($data->getLineNumber());
  668.         if ($this->last->getKeyword('ignore'))
  669.         {
  670.             $this->last = false;
  671.             return;
  672. //            addWarning(PDERROR_IGNORE_TAG_IGNORED,'method',$this->cur_class.'::'.$data->getName());
  673.         }
  674.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'method');
  675.         if ($data->hasSource())
  676.         {
  677.             $this->last->setSource($data->getSource()$data->getClass());
  678.         }
  679.         foreach($data->listParams(as $key => $param)
  680.         {
  681.             $update_params[$key$param;
  682.         }
  683.         foreach($data->listGlobals(as $param)
  684.         {
  685.             $update_globals[$param[1];
  686.         }
  687.         foreach($data->listStatics(as $param)
  688.         {
  689.             $update_statics[$param[0];
  690.         }
  691.         if (isset($update_params))
  692.         $this->last->updateParams($update_params);
  693.         if (isset($update_globals))
  694.         $this->last->updateGlobals($update_globals);
  695.         if (isset($update_statics))
  696.         $this->last->updateStatics($update_statics);
  697.         $this->last->updateModifiers($data->getModifiers());
  698.         unset($update_params);
  699.         unset($update_globals);
  700.         unset($update_statics);
  701.  
  702.         if ($data->getName(== $this->cur_class$data->setConstructor();
  703.         if ($data->getName(== '__construct'{
  704.             $data->setConstructor();
  705.         }
  706.         if ($data->getName(== '__destruct'{
  707.             $data->setDestructor();
  708.         }
  709.  
  710.         if ($_phpDocumentor_setting['pear'])
  711.         {
  712.             if (strpos($data->getName()'_'=== 0 && substr($data->getName()1== $data->class)
  713.             // is destructor
  714.                 $data->setDestructor();
  715.             elseif (strpos($data->getName()'_'=== 0 && !$this->last->getKeyword('access'))
  716.             {
  717.                 if (strpos($data->getName()'__'!== 0{
  718.                     addWarning(PDERROR_PRIVATE_ASSUMED,'method',$data->class.'::'.$data->getName().'()');
  719.                     $this->last->addKeyword('access','private');
  720.                     $data->setDocBlock($this->last);
  721.                 }
  722.             }
  723.         }
  724.         $data->setDocBlock($this->last);
  725.         $data->path = $this->data->parent->path;
  726.         $this->classes->addMethod($data);
  727.         $this->last = false;
  728.     }
  729.  
  730.     /**
  731.      * handles post-parsing of functions
  732.      *
  733.      * This function sets {@link $data}->clean to false to tell the
  734.      * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
  735.      * found after this point on this page.  It then sets the package to be the
  736.      * same as the page, aligns the docblock's @param, @global, and @staticvar
  737.      * tags with the information parsed from the function source code.
  738.      *
  739.      * If source code has been parsed by a {@}source} tag, the source is added
  740.      * to its docblock, and then the parserFunction adds itself to the
  741.      * {@link ProceduralPages} class
  742.      * @param integer $event Event number from {@link Parser.inc}
  743.      * @param parserFunction $data 
  744.      */
  745.     function handleFunction($event,$data)
  746.     {
  747.         if ($this->_lastDocBlockWasPageLevel)
  748.         {
  749.             addWarning(PDERROR_DOCBLOCK_CONFLICT'function'$data->getName());
  750.             if (!$this->_oldPageLevel)
  751.             {
  752.                 unset($this->last);
  753.             }
  754.         }
  755.         $this->_lastDocBlockWasPageLevel = false;
  756.         $this->data->clean = false;
  757.         if ($this->private_page)
  758.         {
  759.             unset($this->last);
  760.             return;
  761.         }
  762.  
  763.         if (empty($this->last))
  764.         {
  765.             if (isset($this->db_template))
  766.             {
  767.                 // use the docblock template
  768.                 $this->last = phpDocumentor_clone($this->db_template);
  769.             }
  770.             else
  771.             {
  772.                 // we don't have a docblock, create an empty one to get rid of errors
  773.                 $this->last = new parserDocblock();
  774.             }
  775.         }
  776. //        $this->last->setLineNumber($data->getLineNumber());
  777.         if ($this->last->getKeyword('ignore'))
  778.         {
  779.             unset($this->last);
  780.             return;
  781.         }
  782.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'function');
  783.  
  784.         foreach($data->listParams(as $key => $param)
  785.         {
  786.             $update_params[$key$param;
  787.         }
  788.         foreach($data->listGlobals(as $param)
  789.         {
  790.             $update_globals[$param[1];
  791.         }
  792.         foreach($data->listStatics(as $param)
  793.         {
  794.             $update_statics[$param[0];
  795.         }
  796.         if (isset($update_params))
  797.         $this->last->updateParams($update_params);
  798.         if (isset($update_globals))
  799.         $this->last->updateGlobals($update_globals);
  800.         if (isset($update_statics))
  801.         $this->last->updateStatics($update_statics);
  802.         unset($update_params);
  803.         unset($update_globals);
  804.         unset($update_statics);
  805.  
  806.         if ($data->hasSource())
  807.         {
  808.             $this->last->setSource($data->getSource());
  809.         }
  810.         if (count($this->last->params== 1 && !count($data->listParams()))
  811.         {
  812.             // if the function has no parameters, and 1 @param, add it to the list as optional, default value is description from @param
  813.             $pars $this->last->listParams();
  814.             $data->addParam($pars[0]['var'],$pars[0]['data']->getString());
  815.         }
  816.         $data->setDocBlock($this->last);
  817.         $this->proceduralpages->addFunction($data);
  818.         $this->last = false;
  819.     }
  820.     
  821.     /**
  822.      * handles post-parsing of defines
  823.      *
  824.      * This function sets {@link $data}->clean to false to tell the
  825.      * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
  826.      * found after this point on this page.  It then sets the package to be the
  827.      * same as the page and adds itself to the {@link ProceduralPages} class
  828.      * @param integer $event Event number from {@link Parser.inc}
  829.      * @param parserDefine $data 
  830.      */
  831.     function handleDefine($event,$data)
  832.     {
  833.         if ($this->_lastDocBlockWasPageLevel)
  834.         {
  835.             addWarning(PDERROR_DOCBLOCK_CONFLICT'define'$data->getName());
  836.             if (!$this->_oldPageLevel)
  837.             {
  838.                 unset($this->last);
  839.             }
  840.         }
  841.         $this->_lastDocBlockWasPageLevel = false;
  842.         $this->data->clean = false;
  843.         if ($this->private_page)
  844.         {
  845.             unset($this->last);
  846.             return;
  847.         }
  848.         if (empty($this->last))
  849.         {
  850.             if (isset($this->db_template))
  851.             {
  852.                 // use the docblock template
  853.                 $this->last = phpDocumentor_clone($this->db_template);
  854.             }
  855.             else
  856.             {
  857.                 // we don't have a docblock, create an empty one to get rid of errors
  858.                 $this->last = new parserDocblock();
  859.             }
  860.         }
  861. //        $this->last->setLineNumber($data->getLineNumber());
  862.         if ($this->last->getKeyword('ignore'))
  863.         {
  864.             unset($this->last);
  865.             return;
  866.         }
  867.  
  868.         $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'define');
  869.         $data->setDocBlock($this->last);
  870.         $this->proceduralpages->addDefine($data);
  871.         $this->last = false;
  872.     }
  873.     
  874.     /**
  875.      * handles post-parsing of classes
  876.      *
  877.      * This function sets {@link $data}->clean to false to tell the
  878.      * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
  879.      * found after this point on this page.  It sets {@link $cur_class} to its
  880.      * name, and if an @ignore tag is found in the DocBlock, it sets
  881.      * {@link $private_class} to true, to prevent post-parsing of any of the
  882.      * class's vars or methods.  Then it checks for the existence of a package
  883.      * page for the class's package
  884.      * @param integer $event Event number from {@link Parser.inc}
  885.      * @param parserClass $data 
  886.      */
  887.     function handleClass($event,$data)
  888.     {
  889.         global $_phpDocumentor_setting;
  890.         if ($data->isInterface()) 
  891.         {
  892.             $objectType 'interface';
  893.         }
  894.         else
  895.         {
  896.             $objectType 'class';
  897.         }
  898.         if ($this->_lastDocBlockWasPageLevel)
  899.         {
  900.             if (!$this->_oldPageLevel)
  901.             {
  902.                 addWarning(PDERROR_DOCBLOCK_GOES_CLASS$data->getName());
  903.                 $doc = new parserDocBlock;
  904.                 $doc->category = $this->category;
  905.                 $doc->package = $this->package;
  906.                 $doc->subpackage = $this->subpackage;
  907.                 if ($_phpDocumentor_setting['sourcecode']{
  908.                     $doc->canSource();
  909.                     $doc->addFileSource($this->data->parent->path$this->data->parent->source);
  910.                 }
  911.                 $this->data->setDocBlock($doc);
  912.                 unset($doc);
  913.                 if ($this->last{
  914.                     $this->last->cantSource();
  915.                 }
  916.             }
  917.         }
  918.         $this->_lastDocBlockWasPageLevel = false;
  919.         $this->data->clean = false;
  920.         if (empty($this->last))
  921.         {
  922.             if (isset($this->db_template))
  923.             {
  924.                 // use the docblock template
  925.                 $this->last = phpDocumentor_clone($this->db_template);
  926.             }
  927.             else
  928.             {
  929.                 // we don't have a docblock, create an empty one to get rid of errors
  930.                 $this->last = new parserDocblock();
  931.             }
  932.             list($this->last->package$this->last->subpackage$this->_guessPackage($this->data->parent->path$this->data->parent->getSourceLocation('dummy'));
  933.             addWarning(PDERROR_NO_PACKAGE_TAG,$objectType,$data->getName(),$this->last->package);
  934.         else
  935.         {
  936.             if (!$this->last->getExplicitPackage())
  937.             {
  938.                 list($this->last->package$this->last->subpackage$this->_guessPackage($this->data->parent->path$this->data->parent->getSourceLocation('dummy'));
  939.                 addWarning(PDERROR_NO_PACKAGE_TAG,$objectType,$data->getName(),$this->last->package);
  940.             else
  941.             {
  942.                 if (isset($this->packagecategories[$this->package])
  943.                     && $this->packagecategories[$this->package!= $this->category)
  944.                     addWarning(PDERROR_PACKAGECAT_SET,$this->package,
  945.                                 $this->packagecategories[$this->package],
  946.                                 $this->category);
  947.                 $this->packagecategories[$this->package$this->category;
  948.             }
  949.         }
  950.         $this->last->updateModifiers($data->getModifiers());
  951. //        $this->last->setLineNumber($data->getLineNumber());
  952.         $data->setDocBlock($this->last);
  953.         $this->cur_class = $name $data->getName();
  954.         if ($this->last->getKeyword('ignore'))
  955.         {
  956.             $this->private_class = true;
  957.             unset($this->last);
  958.             return;
  959.         }
  960.         $data->path = $this->data->parent->path;
  961.         $this->classes->addClass($data);
  962.         $this->private_class = false;
  963.         if ($this->last->package)
  964.         {
  965.             $this->parsePackagePage($this->last->package$this->data->parent->getPath());
  966.         }
  967.         $this->last = false;
  968.     }
  969.     
  970.     /**
  971.      * handles post-parsing of procedural pages
  972.      *
  973.      * this event is called at the start of a new page, before the Parser knows
  974.      * whether the page will contain any procedural pages or not
  975.      * @param integer $event Event number from {@link Parser.inc}
  976.      * @param parserPage $data 
  977.      */
  978.     function handlePage($event,$data)
  979.     {
  980.         $type 'page';
  981.         $this->private_page = false;
  982.         $this->data = new parserData;
  983.         $data->category = $this->category $GLOBALS['phpDocumentor_DefaultCategoryName'];
  984.         $this->package $GLOBALS['phpDocumentor_DefaultPackageName'];
  985.         $this->subpackage '';
  986.         $this->proceduralpages->addPage($data);
  987.         $this->data->setParent($data);
  988.         $this->pages[$data->getPath()$this->data;
  989.         $this->classes->nextFile($data->getPath());
  990.         $this->packageoutput = $data->getPackageOutput();
  991.     }
  992.     
  993.     /**
  994.      * handles post-parsing of DocBlocks
  995.      *
  996.      * This function sets {@link $last} to the DocBlock represented by $data, to
  997.      * allow the next documentable element passed to
  998.      * phpDocumentor_IntermediateParser to link the DocBlock into its $docblock
  999.      * property.  This function also checks for two special cases of DocBlocks:
  1000.      * <ol>
  1001.      *    <li>First DocBlock in the file contains a @package tag</li>
  1002.      *    <li>First DocBlock in the file is immediately followed by another
  1003.      *        DocBlock</li>
  1004.      * </ol>
  1005.      * In both cases, the function extracts this tag and uses it as the
  1006.      * page-level package.  If the @package tag is in the DocBlock of an
  1007.      * element (function, global variable, whatever) that isn't a page-level
  1008.      * DocBlock, a warning will be raised to notify the author that a @package
  1009.      * tag belongs in a page-level DocBlock.
  1010.      *
  1011.      * <b>New</b> in version 1.2.2, if the first DocBlock in a file contains
  1012.      * a @package tag, it is a page-level DocBlock.
  1013.      *
  1014.      * If the DocBlock is page-level, it is processed with
  1015.      * {@link _processPageLevelDocBlock}
  1016.      *
  1017.      * Finally, the function replaces the old parserPage in
  1018.      * {@link parserData::$data}->parent with the new one containing information
  1019.      * from the DocBlock by calling {@link addPage()}, and checks for
  1020.      * package-level docs.
  1021.      * @param integer $event Event number from {@link Parser.inc}
  1022.      * @param parserDocBlock $data 
  1023.      */
  1024.     function handleDocBlock($event,$data)
  1025.     {
  1026.         $type 'docblock';
  1027.         $data->postProcess();
  1028.         // Zend desc support
  1029.         if ($tdesc $data->getKeyword('desc'))
  1030.         {
  1031.             $data->setShortDesc($tdesc);
  1032.             unset($data->tags['desc']);
  1033.         }
  1034.         $this->_lastDocBlockWasPageLevel = false;
  1035.         // 1st docblock in file, check for @package
  1036.         if ($this->data->isClean(&& !isset($this->last))
  1037.         {
  1038.             if ($data->getExplicitPackage())
  1039.             {
  1040.                 // new with 1.2.2:
  1041.                 // if the first docblock in a file
  1042.                 // contains a @package tag, then it is
  1043.                 // a page-level docblock
  1044.                 $this->_processPageLevelDocBlock($data);
  1045.                 $this->_lastDocBlockWasPageLevel = true;
  1046.                 $this->all_packages[$data->package= 1;
  1047.                 $this->last = $data;
  1048.                 return;
  1049.             }
  1050.             $doc = new parserDocBlock;
  1051.             $doc->category = $this->category;
  1052.             $doc->package = $this->package;
  1053.             $doc->subpackage = $this->subpackage;
  1054.             $this->data->setDocBlock($doc);
  1055.             $this->proceduralpages->addPagePackage($this->data->parent->getPath(),$this->package,$this->subpackage);
  1056.             unset($doc);
  1057.         }
  1058.         // 2nd docblock in a row, and it's at the top of the file, page-level docblock
  1059.         if ($this->lasttype == "docblock" && $this->data->isClean())
  1060.         {
  1061.             $this->_processPageLevelDocBlock($this->last);
  1062.             $this->_oldPageLevel = true;
  1063.             $this->_lastDocBlockWasPageLevel = false;
  1064.         }
  1065.         $this->all_packages[$data->package= 1;
  1066.         $this->last = $data;
  1067.     }
  1068.     
  1069.     /**
  1070.      * Process a Page-level DocBlock
  1071.      *
  1072.      * First, it checks for an @ignore tag,
  1073.      * and if found, calls {@link ProceduralPages::ignorePage()}.  An @ignore
  1074.      * tag in a page-level DocBlock will ignore all functions, defines, global
  1075.      * variables, and includes.  It will not ignore classes!  The function next
  1076.      * checks for an @access private, and if --parseprivate is off, performs the
  1077.      * same actions as @ignore.
  1078.      * Next, it checks for the @name tag, which is used to rename the page.
  1079.      * This is also a PEAR compatibility issue, and may not be very useful in
  1080.      * the long run.  Documentation is best when it refers to real entities in
  1081.      * the package, and not to aliases.
  1082.      * @access private
  1083.      */
  1084.     function _processPageLevelDocBlock($data)
  1085.     {
  1086.         global $_phpDocumentor_setting;
  1087.         // can only have 1 package-level docblock, others are ignored
  1088.         if (!$this->data->isClean())
  1089.         {
  1090.             return;
  1091.         }
  1092.         $this->data->clean = false;
  1093.         $this->data->explicitDocBlock();
  1094.         $data->canSource();
  1095.         if ($_phpDocumentor_setting['sourcecode'])
  1096.         {
  1097.             $data->addFileSource($this->data->parent->path$this->data->parent->source);
  1098.         }
  1099.         if (!$data->getExplicitPackage())
  1100.         {
  1101.             list($data->package,$data->subpackage$this->_guessPackage($this->data->parent->getPath()$this->data->parent->getSourceLocation('dummy'));
  1102.             addWarning(PDERROR_NO_PACKAGE_TAG,'file',$this->data->parent->getPath(),$this->last->package);
  1103.         }
  1104.         if (isset($this->packagecategories[$this->package])
  1105.             && $this->packagecategories[$this->package!= $this->category)
  1106.             addWarning(PDERROR_PACKAGECAT_SET,$this->package,
  1107.                         $this->packagecategories[$this->package],
  1108.                         $data->category);
  1109.         $this->packagecategories[$this->package$data->category;
  1110.         $this->category $this->data->parent->category = $data->category;
  1111.         $this->packagecategories[$this->package$this->category;
  1112.         $this->subpackage $this->data->parent->subpackage = $data->subpackage;
  1113.         $this->data->setDocBlock($data);
  1114.         if ($data->getKeyword('ignore'))
  1115.         {
  1116.             $this->proceduralpages->ignorePage($this->data->parent);
  1117.             $this->private_page = true;
  1118.             unset($this->last);
  1119.             $this->privatepages[$this->data->parent->getPath()$this->data;
  1120.             unset($this->pages[$this->data->parent->getPath()]);
  1121.             return;
  1122.         }
  1123.         $this->package $this->data->parent->package = $data->package;
  1124.         $this->subpackage $this->data->parent->subpackage = $data->subpackage;
  1125.         $this->proceduralpages->addPagePackage($this->data->parent->getPath(),$this->package,$this->subpackage);
  1126.         if ($access $data->getKeyword('access'))
  1127.         {
  1128.             if (is_object($access&& ($access->getString(== 'private'&& (!$this->parsePrivate))
  1129.             {
  1130.                 $this->proceduralpages->ignorePage($this->data->parent);
  1131.                 $this->private_page = true;
  1132.                 unset($this->last);
  1133.                 $this->privatepages[$this->data->parent->getPath()$this->data;
  1134.                 unset($this->pages[$this->data->parent->getPath()]);
  1135.                 return;
  1136.             }
  1137.         }
  1138.         if ($data->getKeyword('name'))
  1139.         {
  1140.             $a $data->getKeyword('name');
  1141.             if (is_object($a)) $a $a->value;
  1142.             $this->data->parent->setFile($a);
  1143.             $this->proceduralpages->setName($a);
  1144.         }
  1145.         $this->addPage($this->data->parent$this->data->parent->getPath());
  1146.         if ($this->package)
  1147.         {
  1148.             $this->parsePackagePage($this->package$this->data->parent->getPath());
  1149.         }
  1150.     }
  1151.     
  1152.     /**
  1153.      * Backward-compatibility only, use the new tutorials for more power
  1154.      * @tutorial tutorials.pkg
  1155.      * @param string package name of package file to parse
  1156.      * @param string directory of file that contains package name
  1157.      */
  1158.     function parsePackagePage($package$path)
  1159.     {
  1160.         if (!isset($this->package_pages[$package]))
  1161.         {
  1162.             if (file_exists(dirname($pathSMART_PATH_DELIMITER . $package '.html'))
  1163.             {
  1164.                 if ($this->quietMode === false)
  1165.                 {
  1166.                     phpDocumentor_out("Reading package-level file ".$package '.html');
  1167.                           flush();
  1168.                 }
  1169.                 $fp fopen(dirname($pathSMART_PATH_DELIMITER . $package '.html',"r");
  1170.                 $ret fread($fp,filesize(dirname($pathSMART_PATH_DELIMITER . $package '.html'));
  1171.                 fclose($fp);
  1172.                 unset($fp);
  1173.                 if ($this->quietMode === false)
  1174.                 {
  1175.                     phpDocumentor_out(" -- Parsing File\n");
  1176.                           flush();
  1177.                 }
  1178.                 $pageParser = new ppageParser;
  1179.                 $tempp $this->package;
  1180.                 $lp $this->last;
  1181.                 $pageParser->subscribe('*',$this);
  1182.                 $pageParser->parse($ret,false,$package);
  1183.                 $this->package $tempp;
  1184.                 $this->last = $lp;
  1185.                 unset($tempp);
  1186.                 unset($pageParser);
  1187.             }
  1188.         }
  1189.     }
  1190.     
  1191.     /**
  1192.      * called via {@link Parser::parse()} and Parser's inherited method
  1193.      * {@link Publisher::publishEvent()}
  1194.      *
  1195.      * $event is one of the PHPDOC constants from Parser.inc.  If it is not
  1196.      * PHPDOCUMENTOR_EVENT_NEWSTATE, then a function name is retrieved from the
  1197.      * {@link $event_handlers} array and called to handle the $data
  1198.      * @param integer $event event number from {@link Parser.inc}
  1199.      * @param mixed $data if $event is {@link PHPDOCUMENTOR_EVENT_NEWSTATE}, $data is a {@link PHP_DOC_EVENT_END_PAGE} or {@link STATE_END_CLASS},
  1200.      *                     otherwise $data is either a {@link parserDocBlock}{@link parserPage} or descendant of {@link parserElement}
  1201.      * @global array we use 'sourcecode' to determine whether to highlight the source
  1202.      *                of the current file if it has no file-level docblock
  1203.      */
  1204.     function HandleEvent($event,$data)
  1205.     {
  1206.         global $_phpDocumentor_setting;
  1207.         if (empty($this->packagecategories))
  1208.         $this->packagecategories[$phpDocumentor_DefaultPackageName$phpDocumentor_DefaultCategoryName;
  1209.         if ($event == PHPDOCUMENTOR_EVENT_NEWSTATE)
  1210.         {
  1211.             if ($data == STATE_END_CLASS)
  1212.             {
  1213.             elseif ($data == PHPDOCUMENTOR_EVENT_END_PAGE)
  1214.             {
  1215.                 if (!$this->private_page)
  1216.                 {
  1217.                     $this->all_packages[$this->package= 1;
  1218.                     if (!$this->data->hasExplicitDocBlock())
  1219.                     {
  1220.                         $doc $this->data->docblock;
  1221.                         if (!$this->data->docblock)
  1222.                         {
  1223.                             $doc = new parserDocBlock;
  1224.                         }
  1225.                         if ($_phpDocumentor_setting['sourcecode'])
  1226.                         {
  1227.                             $doc->canSource();
  1228.                             $doc->addFileSource($this->data->parent->path$this->data->parent->source);
  1229.                         }
  1230.                         list($doc->package,$doc->subpackage$this->_guessPackage($this->data->parent->getPath()$this->data->parent->getSourceLocation('dummy'));
  1231.                         addWarning(PDERROR_NO_PAGE_LEVELDOCBLOCK,$this->data->parent->getPath());
  1232.                         $this->data->setDocBlock($doc);
  1233.                         $this->proceduralpages->addPage($this->data->parent,$doc->package,$doc->subpackage);
  1234.                     }
  1235.                     $this->pages[$this->data->parent->getPath()$this->data;
  1236.                 }
  1237.                 $this->private_page = false;
  1238.                 $this->private_class = false;
  1239.                 if (isset($this->db_template))
  1240.                 {
  1241.                     addWarning(PDERROR_DB_TEMPLATE_UNTERMINATED);
  1242.                 }
  1243.                 unset($this->db_template);
  1244.                 unset($this->last);
  1245.             elseif ($data == PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE)
  1246.             {
  1247.                 unset($this->db_template);
  1248.             }
  1249.             //echo $this->state_lookup[$data] . "\n";
  1250.             //echo $data."\n";
  1251.         
  1252.          else 
  1253.         {
  1254.             if ($event == PHPDOCUMENTOR_EVENT_README_INSTALL_CHANGELOG)
  1255.             {
  1256.                 $this->ric[$data[0]] $data[1];
  1257.                 return;
  1258.             }
  1259.             if ($event == PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE)
  1260.             {
  1261.                 $data->postProcess();
  1262.                 $this->db_template = $data;
  1263.                 $this->_lastDocBlockWasPageLevel = false;
  1264.                 // 2nd docblock in a row, and it's at the top of the file, page-level docblock
  1265.                 if ($this->type == "docblock" && $this->data->isClean())
  1266.                 {
  1267.                     // can only have 1 package-level docblock, others are ignored
  1268.                     $this->data->clean = false;
  1269.                     if ($this->last->getKeyword('ignore'))
  1270.                     {
  1271.                         $this->proceduralpages->ignorePage($this->data->parent);
  1272.                         $this->private_page = true;
  1273.                         unset($this->last);
  1274.                         $this->privatepages[$this->data->parent->getPath()$this->data;
  1275.                         unset($this->pages[$this->data->parent->getPath()]);
  1276.                         return;
  1277.                     }
  1278.                     $this->data->setDocBlock($this->last);
  1279.                     $this->package $this->data->parent->package = $this->last->package;
  1280.                     $this->subpackage $this->data->parent->subpackage = $this->last->subpackage;
  1281.                     $this->proceduralpages->addPagePackage($this->data->parent->getPath(),$this->package,$this->subpackage);
  1282.                     if ($access $this->last->getKeyword('access'))
  1283.                     {
  1284.                         if (is_object($access&& ($access->getString(== 'private'&& (!$this->parsePrivate))
  1285.                         {
  1286.                             addWarning(PDERROR_PARSEPRIVATE$this->data->parent->getPath());
  1287.                             $this->proceduralpages->ignorePage($this->data->parent);
  1288.                             $this->private_page = true;
  1289.                             unset($this->last);
  1290.                             $this->privatepages[$this->data->parent->getPath()$this->data;
  1291.                             unset($this->pages[$this->data->parent->getPath()]);
  1292.                             return;
  1293.                         }
  1294.                     }
  1295.                     if ($this->last->getKeyword('name'))
  1296.                     {
  1297.                         $a $this->last->getKeyword('name');
  1298.                         if (is_object($a)) $a $a->value;
  1299.                         $this->data->parent->setFile($a);
  1300.                         $this->proceduralpages->setName($a);
  1301.                     }
  1302.                     $this->addPage($this->data->parent$this->data->parent->getPath());
  1303.                     if ($this->package)
  1304.                     {
  1305.                         $this->parsePackagePage($this->package$this->data->parent->getPath());
  1306.                     }
  1307.                 }
  1308.                 unset($this->last);
  1309.             else
  1310.             {
  1311.                 $this->lasttype = $this->type;
  1312.                 $type $data->getType();
  1313. //                fancy_debug($type,$data);
  1314.                 if (($type != 'page'&& ($type != 'docblock'&& ($type != 'packagepage'&& ($type != 'tutorial'))
  1315.                 {
  1316.                     $data->setFile($this->data->parent->getFile());
  1317.                 }
  1318.                 $this->type = $type;
  1319.                 //echo $type . "\n";
  1320.                 
  1321.                 if (isset($this->event_handlers[$type]))
  1322.                 {
  1323.                     $handle $this->event_handlers[$type];
  1324.                     $this->$handle($event,$data);
  1325.                 }
  1326.             
  1327.         }
  1328.     }
  1329.     
  1330.     /**
  1331.      * Replaces the {@link parserPage} represented by $this->pages[$path] with
  1332.      * $page
  1333.      *
  1334.      * Called by {@link addPageIfNecessary(), handleDocBlock()} and
  1335.      * {@link ProceduralPages::setupPages()}, this method first checks to see if
  1336.      * the page has been added.  If not, it assumes that the page has either
  1337.      * been @ignored or set with @access private with --parseprivate off, and
  1338.      * returns {@link addPrivatePage()}.  Otherwise, it sets the pages[$path] to
  1339.      * be the parserPage $page and sets the package and subpackage to that of
  1340.      * $page
  1341.      * @see $pages
  1342.      * @param parserPage 
  1343.      * @param string full path to the file
  1344.      */
  1345.     function addPage($page$path)
  1346.     {
  1347.         if (!isset($this->pages[$path])) return $this->addPrivatePage($page$path);
  1348.         $this->pages[$path]->setParent($page);
  1349.         if ($page->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
  1350.         {
  1351.             if (!$this->pages[$path]->docblock)
  1352.             {
  1353.                 $docblock = new parserDocBlock;
  1354.                 $docblock->package = $page->package;
  1355.                 $docblock->subpackage = $page->subpackage;
  1356.                 $this->pages[$path]->docblock = $docblock;
  1357.             else
  1358.             {
  1359.                 $this->pages[$path]->docblock->package = $page->package;
  1360.                 $this->pages[$path]->docblock->subpackage = $page->subpackage;
  1361.             }
  1362.         }
  1363.     }
  1364.     
  1365.     /**
  1366.      * add a new {@link parserPage} to the $pages array if none is found
  1367.      *
  1368.      * This method is used when a page has been @ignored or marked with @access
  1369.      * private, and a public class is in the page (a class with no @access
  1370.      * private in its DocBlock).  The method first creates a new page in the
  1371.      * {@link $pages} array and then copies path information, and calls
  1372.      * {@link addPage()} to set up packages
  1373.      * @param string full path of page
  1374.      */
  1375.     function addPageIfNecessary($path&$class)
  1376.     {
  1377.         global $_phpDocumentor_setting;
  1378.         if (!$this->parsePrivate)
  1379.         {
  1380.             if (!isset($this->pages[$path]))
  1381.             {
  1382.                 $this->pages[$path= new parserData;
  1383.                 $this->pages[$path]->docblock = new parserDocBlock;
  1384.                 $this->pages[$path]->docblock->package = $this->privatepages[$path]->docblock->package;
  1385.                 $this->pages[$path]->docblock->subpackage = $this->privatepages[$path]->docblock->subpackage;
  1386.                 $par $this->privatepages[$path]->parent;
  1387.                 $this->pages[$path]->setParent($par);
  1388.                 $this->proceduralpages->addPage($par);
  1389.             }
  1390.         }
  1391.         if (!empty($_phpDocumentor_setting['packageoutput']))
  1392.             $packages explode(',',$_phpDocumentor_setting['packageoutput']);
  1393.         if (!empty($_phpDocumentor_setting['packageoutput']&&
  1394.             $this->pages[$path]->parent->package != $class->docblock->package &&
  1395.             !in_array($this->pages[$path]->parent->package,$packages))
  1396.         {
  1397.             $this->pages[$path]->parent->package = $class->docblock->package;
  1398.             $this->addPage($this->pages[$path]->parent$path);
  1399.             $this->proceduralpages->addPage($this->pages[$path]->parent);
  1400.         }
  1401.     }
  1402.     
  1403.     /**
  1404.      * Adds a {@link parserPage} element to the {@link parserData} element in
  1405.      * $this->privatepages[$path]
  1406.      *
  1407.      * Performs a similar function to addPage, but adds to the
  1408.      * {@link $privatePages} array
  1409.      * @param parserPage $page 
  1410.      * @param string $path full path to the page
  1411.      * @see addPage()
  1412.      */
  1413.     function addPrivatePage($page$path)
  1414.     {
  1415.         $this->privatepages[$path]->setParent($page);
  1416.         if ($page->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
  1417.         {
  1418.             if (!$this->privatepages[$path]->docblock)
  1419.             {
  1420.                 $docblock = new parserDocBlock;
  1421.                 $docblock->package = $page->package;
  1422.                 $docblock->subpackage = $page->subpackage;
  1423.                 $this->privatepages[$path]->docblock = $docblock;
  1424.             else
  1425.             {
  1426.                 $this->privatepages[$path]->docblock->package = $page->package;
  1427.                 $this->privatepages[$path]->docblock->subpackage = $page->subpackage;
  1428.             }
  1429.         }
  1430.     }
  1431.     
  1432.     /**
  1433.      * adds a processed descendant of {@link parserElement} to the {@link $pages}
  1434.      * array or {@link $privatepages} array
  1435.      *
  1436.      * This function expects the page to exist in either $pages or $privatepages.  It calls the
  1437.      * {@link parserData::addElement()} method to add $element to the page.
  1438.      * @param parserElement $element this will actually be a descendant of parserElement
  1439.      * @param string $path 
  1440.      */
  1441.     function addElementToPage($element$path)
  1442.     {
  1443.         if (isset($this->privatepages[$path]))
  1444.         {
  1445.             if (isset($this->pages[$path]))
  1446.             {
  1447.                 if ($element->type == 'class' || $element->type == 'method'
  1448.                     || $element->type == 'var' || $element->type == 'const')
  1449.                 {
  1450.                     $this->pages[$path]->addElement($element);
  1451.                 else
  1452.                 $this->privatepages[$path]->addElement($element);
  1453.             else
  1454.             $this->privatepages[$path]->addElement($element);
  1455.         else
  1456.         {
  1457.             if (isset($this->pages[$path]))
  1458.             {
  1459.                 $this->pages[$path]->addElement($element);
  1460.             }
  1461.         }
  1462.     }
  1463.     
  1464.     /**
  1465.      * Add all the @uses tags from $element to the $uses array so that @usedby
  1466.      * virtual tags can be added
  1467.      * @uses parserUsesTag::getSeeElement() used to initialize {@link $uses}
  1468.      * @uses parserUsesTag::getDescription() used to initialize {@link $uses}
  1469.      * @param parserElement descendant of parserElement
  1470.      * @param string full path to the file
  1471.      */
  1472.     function addUses($element$path)
  1473.     {
  1474.         if ($element->type == 'page')
  1475.         {
  1476.             $element $this->pages[$element->path];
  1477.         }
  1478.         if (!$this->parsePrivate && $element->docblock->hasaccess)
  1479.         {
  1480.             $a =  $element->docblock->getKeyword('access');
  1481.             if (is_object($a&& $a->getString(== 'private'return;
  1482.         }
  1483.         if (isset($this->privatepages[$path]))
  1484.         {
  1485.             if (isset($this->pages[$path]))
  1486.             {
  1487. //                if ($element->type == 'function' || $element->type == 'method')
  1488.                 {
  1489.                     $uses $element->docblock->getKeyword('uses');
  1490.                     if ($uses)
  1491.                     {
  1492.                         if (!is_array($uses)) $uses = array($uses);
  1493.                         foreach($uses as $use)
  1494.                         {
  1495.                             if (!is_object($use)) continue;
  1496.                             $el $use->getSeeElement();
  1497.                             $description $use->getDescription();
  1498.                             $this->uses[$el][= array($element$description);
  1499.                         }
  1500.                     }
  1501.                 }
  1502.             }
  1503.         else
  1504.         {
  1505.             if (isset($this->pages[$path]))
  1506.             {
  1507. //                if ($element->type == 'function' || $element->type == 'method')
  1508.                 {
  1509.                     $uses $element->docblock->getKeyword('uses');
  1510.                     if ($uses)
  1511.                     {
  1512.                         if (!is_array($uses)) $uses = array($uses);
  1513.                         foreach($uses as $use)
  1514.                         {
  1515.                             if (!is_object($use)) continue;
  1516.                             $el $use->getSeeElement();
  1517.                             $description $use->getDescription();
  1518.                             $this->uses[$el][= array($element$description);
  1519.                         }
  1520.                     }
  1521.                 }
  1522.             }
  1523.         }
  1524.     }
  1525.     
  1526.     /**
  1527.      * Add a {@link parserUsedByTag} link to every element referred to by @uses
  1528.      * @param Converter temporary converter used to retrieve abstract links
  1529.      * @uses phpDocumentor_IntermediateParser::addUses() indirectly, as
  1530.      *        addUses() sets up $uses, which is iterated over here
  1531.      * @uses $pages sets up all @usedby tags from here
  1532.      * @access private
  1533.      */
  1534.     function _setupUsesList(&$converter)
  1535.     {
  1536.         ob_start();
  1537.         $converter->_createPkgElements($this->pages);
  1538.         ob_end_clean();
  1539.         ksort($this->uses);
  1540.         foreach($this->uses as $link => $elements)
  1541.         {
  1542.             foreach($elements as $element)
  1543.             {
  1544.                 if ($element[0]->type == 'method' || $element[0]->type == 'var' ||
  1545.                     $element[0]->type == 'const')
  1546.                 {
  1547.                     $converter->class = $element[0]->getClass();
  1548.                 }
  1549.                 if ($element[0]->type == 'class')
  1550.                 {
  1551.                     $converter->class = $element[0]->getName();
  1552.                 }
  1553.                 $reallink $converter->getLink($link,$element[0]->docblock->package);
  1554.                 if (is_object($reallink))
  1555.                 {
  1556.                     // add a used by tag to the docblock of the destination
  1557.                     switch(phpDocumentor_get_class($reallink))
  1558.                     {
  1559.                         case 'pagelink' :
  1560.                             $this->pages[$reallink->path]->docblock->addUsedBy(
  1561.                                 $element[0]->getLink($converterfalsetrue),
  1562.                                 $element[1]);
  1563.                         break;
  1564.                         case 'functionlink' :
  1565.                         case 'definelink' :
  1566.                         case 'globallink' :
  1567.                         if (isset($this->pages[$reallink->path]))
  1568.                         {
  1569.                             for ($i=0;
  1570.                                  $i<count($this->pages[$reallink->path]->elements);
  1571.                                  $i++{
  1572.                                 if ($this->pages[$reallink->path]->elements[$i]->type ==
  1573.                                       str_replace('link''',
  1574.                                       phpDocumentor_get_class($reallink)) &&
  1575.                                       $this->pages[$reallink->path]->
  1576.                                       elements[$i]->getName(
  1577.                                       == $reallink->name{
  1578.                                     $this->pages[$reallink->path]->elements[$i]->
  1579.                                     docblock->addUsedBy(
  1580.                                         $element[0]->getLink($converter,false,true),
  1581.                                         $element[1]);
  1582. //                                   debug('added @usedby to '.str_replace('link','',phpDocumentor_get_class($reallink)).' '.$reallink->name);
  1583.                                 }
  1584.                             }
  1585.                         }
  1586.                         break;
  1587.                         case 'classlink' :
  1588.                         case 'methodlink' :
  1589.                         case 'varlink' :
  1590.                         case 'constlink' :
  1591.                         if (isset($this->pages[$reallink->path]))
  1592.                         {
  1593.                             for ($i=0;$i<count($this->pages[$reallink->path]->classelements);$i++)
  1594.                             {
  1595.                                 if ($this->pages[$reallink->path]->classelements[$i]->type ==
  1596.                                       str_replace('link','',phpDocumentor_get_class($reallink)) &&
  1597.                                       $this->pages[$reallink->path]->classelements[$i]->getName(== $reallink->name &&
  1598.                                       (!isset($reallink->class|| 
  1599.                                       $this->pages[$reallink->path]->classelements[$i]->getClass(== $reallink->class))
  1600.                                 {
  1601.                                     $this->pages[$reallink->path]->classelements[$i]->docblock->addUsedBy($element[0]->getLink($converter,false,true)$element[1]);
  1602. //                                   debug('added @usedby to '.str_replace('link','',phpDocumentor_get_class($reallink)).' '.$reallink->name);
  1603.                                 }
  1604.                             }
  1605.                         }
  1606.                         break;
  1607.                     }
  1608.                 }
  1609.             }
  1610.         }
  1611.     }
  1612.     
  1613.     /**
  1614.      * Interface to the Converter
  1615.      *
  1616.      * This function simply passes {@link $pages} and {@link package_pages} to
  1617.      * the walk() method, and then calls the Output() method.  Note that
  1618.      * Output() is not required to do anything, and in fact doesn't in
  1619.      * HTMLframesConverter.
  1620.      * @uses Converter::walk() passes {@link $pages} and {@link $package_pages}
  1621.      * @uses Converter::Output()
  1622.      */
  1623.     function Convert($title$converter)
  1624.     {
  1625.         $converter->walk($this->pages$this->package_pages);
  1626.         $converter->Output($title);
  1627.         $converter->cleanup();
  1628.     }
  1629.     
  1630.     /**
  1631.      * Clean up classes
  1632.      *
  1633.      * {@source } 
  1634.      * @access private
  1635.      * @uses Classes::Inherit() passes $this
  1636.      */
  1637.     function fixClasses()
  1638.     {
  1639.         $this->classes->Inherit($this);
  1640.     }
  1641.     
  1642.     /**
  1643.      * Clean up Procedural Pages
  1644.      * {@source } 
  1645.      * @access private
  1646.      * @uses ProceduralPages::setupPages() passes $this
  1647.      */
  1648.     function fixProcPages()
  1649.     {
  1650.         $this->proceduralpages->setupPages($this);
  1651.     }
  1652.     
  1653.     /**
  1654.      * If the parent class of $class is in a different package, adds it to the
  1655.      * {@link $package_parents} array
  1656.      * @param parserClass &$class 
  1657.      */
  1658.     function addPackageParent(&$class)
  1659.     {
  1660.         if (!is_array($class->parent)) return;
  1661.         $par $this->classes->getClass($class->parent[1]$class->parent[0]);
  1662.         if ($class->docblock->package == $par->docblock->packagereturn;
  1663.         $this->package_parents[$class->docblock->package$par->docblock->package;
  1664.         if (!isset($this->package_parents[$par->docblock->package]|| !$this->package_parents[$par->docblock->package]$this->package_parents[$par->docblock->package= false;
  1665.     }
  1666.     
  1667.     /**
  1668.      * Add a converter name to use to the list of converters
  1669.      *
  1670.      * Sets up the {@link $converters} array.
  1671.      * {@internal 
  1672.      * First, the Converter's file is included, and then, if successful,
  1673.      * the converter classname is tested for existance.  If all is good,
  1674.      * then the templates are added to the list of converters/templates to use}}}
  1675.      * @param string $output output format (HTML, PDF, XML).  Must be all caps
  1676.      * @param string $name Converter name (frames, for example, is the name of
  1677.      *                      HTMLframesConverter)
  1678.      * @param string $template template to use, should be a relative path to the
  1679.      *                          templates dir (like DOM/default)
  1680.      */
  1681.     function addConverter($output,$name,$template)
  1682.     {
  1683.         if ($this->templateBase{
  1684.             $templateBase str_replace('\\','/'$this->templateBase'/Converters';
  1685.         else {
  1686.             if ('@PEAR-DIR@' != '@'.'PEAR-DIR@'{
  1687.                 $templateBase 'PhpDocumentor/phpDocumentor/Converters';
  1688.             else {
  1689.                 $templateBase str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']'/phpDocumentor/Converters';
  1690.             }
  1691.         }
  1692.         if (strpos($name,PATH_DELIMITER))
  1693.         {
  1694.             // include the parent template
  1695.             $parent explode(PATH_DELIMITER,$name);
  1696.             $parent $parent[0];
  1697.             if (!class_exists($output $parent 'Converter')) {
  1698.                 $filename $templateBase '/' $output '/' $parent '/' $output
  1699.                     . $parent 'Converter.inc';
  1700.                 if (Io::isIncludeable($filename))
  1701.                 {
  1702.                     include_once($filename);
  1703.                 }
  1704.             }
  1705.             if (!class_exists($output $parent 'Converter'))
  1706.             {
  1707.                 addError(PDERROR_CONVERTER_NOT_FOUND,"parent Converter ".$output $parent "Converter of child Converter ".$output str_replace(PATH_DELIMITER,'',$name"Converter");
  1708.             }
  1709.         }
  1710.         $filename $templateBase .
  1711.              PATH_DELIMITER . $output PATH_DELIMITER . $name PATH_DELIMITER . $output .
  1712.              str_replace(PATH_DELIMITER''$name"Converter" ".inc";
  1713.         if (Io::isIncludeable($filename))
  1714.         {
  1715.             include_once($filename);
  1716.         }
  1717.         if (class_exists($output str_replace(PATH_DELIMITER,'',$name'Converter'))
  1718.         {
  1719.             $this->converters[$output][$output str_replace(PATH_DELIMITER,'',$name"Converter"][$template;
  1720.         else
  1721.         {
  1722.             addError(PDERROR_CONVERTER_NOT_FOUND,$output str_replace(PATH_DELIMITER,'',$name"Converter");
  1723.         }
  1724.     }
  1725.  
  1726.     /**
  1727.      * does a natural case sort on two {@link parserElement} descendants
  1728.      *
  1729.      * @param    mixed    $a 
  1730.      * @param    mixed    $b 
  1731.      * @return    int 
  1732.      * @see        generateElementIndex()
  1733.      */
  1734.     function elementCmp ($a$b)
  1735.     {
  1736.         return strnatcasecmp($a->getName()$b->getName());
  1737.     }
  1738.     
  1739.     /**
  1740.      * does a natural case sort on two class elements (either
  1741.      * {@link parserClass, parserMethod} or {@link parserVar}
  1742.      *
  1743.      * @param    mixed    $a 
  1744.      * @param    mixed    $b 
  1745.      * @return    int 
  1746.      * @see        generateElementIndex()
  1747.      */
  1748.     function ClasselementCmp ($a$b)
  1749.     {
  1750.         if (phpDocumentor_get_class($a== 'parserclass'$atest $a->name; else $atest $a->class;
  1751.         if (phpDocumentor_get_class($b== 'parserclass'$btest $b->name; else $btest $b->class;
  1752.         
  1753.         if(($c strnatcasecmp($atest$btest)) != 0return $c;
  1754.         if (phpDocumentor_get_class($a!= 'parserclass'$atest .= $a->name;
  1755.         if (phpDocumentor_get_class($b!= 'parserclass'$btest .= $b->name;
  1756.         if (phpDocumentor_get_class($a== 'parsermethod' && phpDocumentor_get_class($b== 'parsermethod')
  1757.         {
  1758.             if ($a->isConstructorreturn -1;
  1759.             if ($b->isConstructorreturn 1;
  1760.             if ($a->isDestructorreturn -1;
  1761.             if ($b->isDestructorreturn 1;
  1762.         }
  1763.         return strnatcasecmp($atest,$btest);
  1764.     }
  1765.     
  1766.     /**
  1767.      * call this method once parsing has completed.
  1768.      *
  1769.      * This method calls the private methods fixClasses and fixProcPages, both
  1770.      * of which adjust inheritance and package information based on complicated
  1771.      * post-parsing rules described in {@link ProceduralPages::setupPages()}
  1772.      * and {@link Classes::Inherit()}.  Then, it sorts elements of the $pages
  1773.      * array and calls Convert for each Converter in the $converters array
  1774.      * @see $converters
  1775.      * @see $pages
  1776.      * @see Convert()
  1777.      */
  1778.     function Output ($title "Generated Documentation")
  1779.     {
  1780.         $GLOBALS['phpDocumentor_errors']->curfile = false;
  1781.         $this->fixClasses();
  1782.         $this->fixProcPages();
  1783. //        var_dump($this->uses);
  1784. //        exit;
  1785.         phpDocumentor_out("\nSorting page elements...");
  1786.         flush();
  1787.         uasort($this->pages,'pagesort');
  1788.         foreach($this->pages as $i => $page)
  1789.         {
  1790.             usort($this->pages[$i]->elements,array($this,'elementCmp'));
  1791.             usort($this->pages[$i]->classelements,array($this,'ClasselementCmp'));
  1792.         }
  1793.         phpDocumentor_out("done\n");
  1794.         flush();
  1795.         $complicatedout = false;
  1796.         if (is_array($this->converters))
  1797.         {
  1798.             if (count($this->converters> 1)
  1799.             {
  1800.                 $complicatedout = true;
  1801.             }
  1802.             phpDocumentor_out("Formatting @uses list...");
  1803.             flush();
  1804.             $a = new __dummyConverter($this->all_packages$this->package_parents$this->classes$this->proceduralpages$this->packageoutput$this->parsePrivate$this->quietMode$this->targetDir ''$this->title);
  1805.             $this->_setupUsesList($a);
  1806.             unset($a);
  1807.             phpDocumentor_out("done\n\n");
  1808.             flush();
  1809.             foreach($this->converters as $converter => $blah)
  1810.             {
  1811.                 if (is_array($blah))
  1812.                 {
  1813.                     if (count($blah> 1)
  1814.                     {
  1815.                         $complicatedout = true;
  1816.                     }
  1817.                     foreach($blah as $converter => $templates)
  1818.                     {
  1819.                         foreach($templates as $template)
  1820.                         {
  1821.                             $extraout '';
  1822.                             if ($complicatedout)
  1823.                             {
  1824.                                 $extraout SMART_PATH_DELIMITER . $converter;
  1825.                             }
  1826.                             if (count($templates> 1)
  1827.                             {
  1828.                                 $extraout .= SMART_PATH_DELIMITER . str_replace(PATH_DELIMITERSMART_PATH_DELIMITERsubstr($template,0,strlen($template- 1));
  1829.                             }
  1830.                             $a = new $converter($this->all_packages$this->package_parents$this->classes$this->proceduralpages$this->packageoutput$this->parsePrivate$this->quietMode$this->targetDir . $extraout$template$this->title);
  1831.                             if (isset($this->templateBase))
  1832.                             {
  1833.                                 $a->setTemplateBase($this->templateBase$template);
  1834.                             }
  1835.                             $a->ric = $this->ric;
  1836.                             $a->packagecategories = $this->packagecategories;
  1837.                             if (isset($this->tutorials)) $a->setTutorials($this->tutorials);
  1838.                             $this->Convert($title$a);
  1839.                             unset($a);
  1840.                         }
  1841.                     }
  1842.                 }
  1843.             }
  1844.         else
  1845.         {
  1846.             addErrorDie(PDERROR_NO_CONVERTERS);
  1847.         }
  1848.     }
  1849.  
  1850.     /**
  1851.      * Sets the output directory
  1852.      *
  1853.      * @param string $dir the output directory
  1854.      */
  1855.     function setTargetDir($dir)
  1856.     {
  1857.         $this->targetDir = $dir;
  1858.     }
  1859.  
  1860.     /**
  1861.      * Sets the template base directory
  1862.      *
  1863.      * @param string $dir the template base directory
  1864.      * @tutorial phpDocumentor.howto.pkg#using.command-line.templatebase
  1865.      */
  1866.     function setTemplateBase($dir)
  1867.     {
  1868.         $this->templateBase = $dir;
  1869.     }
  1870.  
  1871.     /**
  1872.      * set parsing information output mode (quiet or verbose)
  1873.      *
  1874.      * If set to false, no parsing information (parsing /php/file/thisfile.php,
  1875.      * Converting etc.) will be displayed.
  1876.      * Useful for cron jobs
  1877.      * @param    bool $quietMode 
  1878.      */
  1879.     function setQuietMode($quietMode)
  1880.     {
  1881.         $this->quietMode = $quietMode;
  1882.     }
  1883.     
  1884.     /**
  1885.      * set display of elements marked with @access private
  1886.      *
  1887.      * If set to true, elements will be displayed
  1888.      * @param    bool $parse 
  1889.      */
  1890.     function setParsePrivate($parse)
  1891.     {
  1892.         $this->parsePrivate = $parse;
  1893.     }
  1894. }
  1895.  
  1896. /** @access private */
  1897. function pagesort($a$b)
  1898. {
  1899.     return strnatcasecmp($a->parent->file,$b->parent->file);
  1900. }
  1901. ?>

Documentation generated on Mon, 11 Mar 2019 14:58:51 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.