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