home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / PhpDocumentor / phpDocumentor / Classes.inc next >
Encoding:
Text File  |  2008-07-02  |  48.1 KB  |  1,357 lines

  1. <?php
  2. /**
  3.  * Intermediate class parsing structure.
  4.  *
  5.  * phpDocumentor :: automatic documentation generator
  6.  * 
  7.  * PHP versions 4 and 5
  8.  *
  9.  * Copyright (c) 2001-2007 Gregory Beaver
  10.  * 
  11.  * LICENSE:
  12.  * 
  13.  * This library is free software; you can redistribute it
  14.  * and/or modify it under the terms of the GNU Lesser General
  15.  * Public License as published by the Free Software Foundation;
  16.  * either version 2.1 of the License, or (at your option) any
  17.  * later version.
  18.  * 
  19.  * This library is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22.  * Lesser General Public License for more details.
  23.  * 
  24.  * You should have received a copy of the GNU Lesser General Public
  25.  * License along with this library; if not, write to the Free Software
  26.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27.  *
  28.  * @category  ToolsAndUtilities
  29.  * @package   phpDocumentor
  30.  * @author    Greg Beaver <cellog@php.net>
  31.  * @copyright 2001-2007 Gregory Beaver
  32.  * @license   http://www.opensource.org/licenses/lgpl-license.php LGPL
  33.  * @version   CVS: $Id: Classes.inc,v 1.11 2007/10/10 01:18:25 ashnazg Exp $
  34.  * @filesource
  35.  * @link      http://www.phpdoc.org
  36.  * @link      http://pear.php.net/PhpDocumentor
  37.  * @see       parserDocBlock, parserInclude, parserPage, parserClass
  38.  * @see       parserDefine, parserFunction, parserMethod, parserVar
  39.  * @since     1.0rc1
  40.  * @todo      CS cleanup - change package to PhpDocumentor
  41.  */
  42. /**
  43.  * Intermediate class parsing structure.
  44.  *
  45.  * The {@link phpDocumentor_IntermediateParser} class uses this class and its
  46.  * cousin, {@link ProceduralPages} to organize all parsed source code elements.
  47.  * Data is fed to each immediately after it is parsed, and at conversion time,
  48.  * everything is organized.
  49.  *
  50.  * The Classes class is responsible for all inheritance, including resolving
  51.  * name conflicts between classes, determining which classes extend other
  52.  * classes, and is responsible for all inheritance of documentation.
  53.  * {@internal
  54.  * This structure parses classes, vars and methods by file, and then iterates
  55.  * over the class tree to set up inheritance.  The {@link Inherit()}
  56.  * method is the meat of the class, and processes the class trees from root to
  57.  * branch, ensuring that parsing order is unimportant.}}
  58.  *
  59.  * @category  ToolsAndUtilities
  60.  * @package   phpDocumentor
  61.  * @author    Greg Beaver <cellog@php.net>
  62.  * @copyright 2001-2007 Gregory Beaver
  63.  * @license   http://www.opensource.org/licenses/lgpl-license.php LGPL
  64.  * @version   Release: 1.4.2
  65.  * @link      http://www.phpdoc.org
  66.  * @link      http://pear.php.net/PhpDocumentor
  67.  * @since     1.0rc1
  68.  * @todo      CS cleanup - change package to PhpDocumentor
  69.  */
  70. class Classes
  71. {
  72.     /**#@+
  73.      * @access private
  74.      */
  75.     /**
  76.      * file being parsed, used in every add function to match up elements with 
  77.      * the file that contains them
  78.      *
  79.      * This variable is used during parsing to associate class elements added
  80.      * to the data structures that contain them with the file they reside in
  81.      * @see addClass(), addMethod(), addVar(), nextFile()
  82.      * @var string
  83.      */
  84.     var $curfile;
  85.     /**
  86.      * class being parsed, used to match up methods and vars with their parent
  87.      * class
  88.      *
  89.      * This variable is used during parsing to associate class elements added
  90.      * to the data structures that contain them with the file they reside in
  91.      * @see addMethod(), addVar()
  92.      * @var string
  93.      */
  94.     var $curclass;
  95.     
  96.     /**
  97.      * Used when a definite match is made between a parent class and a child
  98.      * class
  99.      *
  100.      * This variable is used in post-parsing.
  101.      *
  102.      * Format:<pre>
  103.      * array(
  104.      *     parent => array(
  105.      *         parentfile => array(
  106.      *             child => childfile
  107.      *         )
  108.      *     )
  109.      * )</pre>
  110.      * @var array
  111.      */
  112.     var $definitechild;
  113.     /**
  114.      * array of parsed classes organized by the name of the file that contains
  115.      * the class.
  116.      *
  117.      * Format:<pre>
  118.      * array(
  119.      *     filename => array(
  120.      *         classname => {@link parserClass}
  121.      *     )
  122.      * )</pre>
  123.      * @var array
  124.      */
  125.     var $classesbyfile = array();
  126.     /**
  127.      * array of file names organized by classes that are in the file.
  128.      *
  129.      * This structure is designed to handle name conflicts.  Two files can
  130.      * contain classes with the same name, and this array will record both
  131.      * filenames to help control linking and inheritance errors
  132.      *
  133.      * Format:<pre>
  134.      * array(
  135.      *     classname => array(
  136.      *         name of file containing classname,
  137.      *         name of file 2 containing classname,
  138.      *         ...
  139.      *     )
  140.      * )</pre>
  141.      * @var array
  142.      */
  143.     var $classesbynamefile = array();
  144.     /**
  145.      * array of parsed methods organized by the file that contains them.
  146.      *
  147.      * Format:<pre>
  148.      * array(
  149.      *     filename => array(
  150.      *         classname => array(
  151.      *             {@link parserMethod} 1, 
  152.      *             {@link parserMethod} 2,
  153.      *             ...
  154.      *         )
  155.      *     )
  156.      * )</pre>
  157.      * @var array
  158.      */
  159.     var $methodsbyfile = array();
  160.     /**
  161.      * array of parsed vars organized by the file that contains them.
  162.      *
  163.      * Format:<pre>
  164.      * array(
  165.      *     filename => array(
  166.      *         classname => array(
  167.      *             {@link parserVar} 1, 
  168.      *             {@link parserVar} 2,
  169.      *             ...
  170.      *         )
  171.      *     )
  172.      * )</pre>
  173.      * @var array
  174.      */
  175.     var $varsbyfile = array();
  176.     /**
  177.      * array of parsed class constants organized by the file that contains them.
  178.      *
  179.      * Format:<pre>
  180.      * array(
  181.      *     filename => array(
  182.      *         classname => array(
  183.      *             {@link parserConst} 1, 
  184.      *             {@link parserConst} 2,
  185.      *             ...
  186.      *         )
  187.      *     )
  188.      * )</pre>
  189.      * @var array
  190.      */
  191.     var $constsbyfile = array();
  192.     /**
  193.      * keeps track of extend declarations by file, used to find inheritance
  194.      *
  195.      * Format:<pre>
  196.      * array(
  197.      *     filename => array(
  198.      *         classname => parentclassname
  199.      *     )
  200.      * )</pre>
  201.      * @var array
  202.      */
  203.     var $extendsbyfile = array();
  204.     /**
  205.      * Keeps track of child classes by file.
  206.      * Since phpDocumentor can document collections of files that contain name
  207.      * conflicts (PHP would give a fatal error), it
  208.      * is impossible to assume a class that declares "extends foo" necessarily
  209.      * extends the class foo in file X.  It could be an
  210.      * extended class of class foo in file Y.  Because of this, phpDocumentor
  211.      * relies on packaging to resolve the name conflict
  212.      * This array keeps track of the packages of a child class
  213.      *
  214.      * Format:<pre>
  215.      * array(
  216.      *     parentclassname => array(
  217.      *         filename => array(
  218.      *             childclassname => array(
  219.      *                 packagename, 
  220.      *                 packagename
  221.      *             )
  222.      *         )
  223.      *     )
  224.      * )</pre>
  225.      * @var array
  226.      */
  227.     var $classchildrenbyfile = array();
  228.     /**
  229.      * Keeps track of class packages found in a file.
  230.      * This is used in {@link getParentClass()} to determine the number of
  231.      * packages in a file, in order to resolve inheritance issues
  232.      * Format:<pre>
  233.      * array(
  234.      *     filename => array(
  235.      *         packagename1, 
  236.      *         packagename2,
  237.      *         ...
  238.      *     )
  239.      * )</pre>
  240.      * @var array
  241.      */
  242.     var $classpackagebyfile = array();
  243.     /**
  244.      * a tree of class inheritance by name.
  245.      *
  246.      * Format:<pre>
  247.      * array(
  248.      *     childname => parentname,
  249.      *     childname1 => parentname1,
  250.      *     rootname => 0, 
  251.      *     ...
  252.      * )</pre>
  253.      * @var array
  254.      * @see Converter::generateSortedClassTreeFromClass()
  255.      */
  256.     var $classparents = array();
  257.     /**
  258.      * Keeps track of package and subpackage for each class name, organized
  259.      * by package
  260.      *
  261.      * Format:<pre>
  262.      * array(
  263.      *     classname => array(
  264.      *         path => array(
  265.      *             package,
  266.      *             subpackage
  267.      *         ),
  268.      *         path2 => array(
  269.      *             package,
  270.      *             subpackage
  271.      *         ),
  272.      *         ...
  273.      *     )
  274.      * )</pre>
  275.      * @var array
  276.      */
  277.     var $classpathpackages = array();
  278.     /**
  279.      * used to delete duplicates in the same package to avoid documentation errors
  280.      *
  281.      * Specifically used in {@link Converter::checkKillClass()}
  282.      */
  283.     var $killclass = array();
  284.     /**
  285.      * array of methods by package and class
  286.      *
  287.      * format:<pre>
  288.      * array(packagename =>
  289.      *         array(classname =>
  290.      *               array(methodname1 => {@link parserMethod} class,
  291.      *                     methodname2 => {@link parserMethod} class,...)
  292.      *                      )
  293.      *              )
  294.      *      )</pre>
  295.      * @var array
  296.      * @see Converter
  297.      */
  298.     var $methods = array();
  299.     
  300.     /**
  301.      * array of class variables by package and class
  302.      *
  303.      * format:<pre>
  304.      * array(packagename =>
  305.      *         array(classname =>
  306.      *                array(variablename1 => {@link parserVar} class,
  307.      *                      variablename2 => {@link parserVar} class,...
  308.      *                     )
  309.      *              )
  310.      *      )</pre>
  311.      * @var array
  312.      * @see Converter
  313.      */
  314.     var $vars = array();
  315.     
  316.     /**
  317.      * array of class variables by package and class
  318.      *
  319.      * format:<pre>
  320.      * array(packagename =>
  321.      *         array(classname =>
  322.      *                array(constname1 => {@link parserConst} class,
  323.      *                      constname2 => {@link parserConst} class,...
  324.      *                     )
  325.      *              )
  326.      *      )</pre>
  327.      * @var array
  328.      * @see Converter
  329.      */
  330.     var $consts = array();
  331.     /**
  332.      * Reverse class_packages_by_file, used to prevent duplicates
  333.      * @var array Format: array(packagename => 1)
  334.      */
  335.     var $revcpbf = array();
  336.     /**
  337.      * All classes with no parents (no extends clause) are tracked in this array
  338.      * by the file that contains them.
  339.      *
  340.      * Format:<pre>
  341.      * array(
  342.      *     classname => array(
  343.      *         name of file1 that contains root classname,
  344.      *         name of file2 that contains root classname,
  345.      *         ...
  346.      *     )
  347.      * )</pre>
  348.      * @var array
  349.      */
  350.     var $roots = array();
  351.     /**
  352.      * All classes with a parent that was not parsed are included in this array
  353.      *
  354.      * Format:<pre>
  355.      * array(
  356.      *     classname => array(
  357.      *         name of file1 that contains root classname,
  358.      *         name of file2 that contains root classname,
  359.      *         ...
  360.      *     )
  361.      * )</pre>
  362.      * @var array
  363.      */
  364.     var $specialRoots = array();
  365.     
  366.     /**
  367.      * array of all files that contain classes with the same name
  368.      * @var array Format: (classname => array(path1, path2,...))
  369.      */
  370.     var $potentialclassconflicts = array();
  371.     
  372.     /**
  373.      * array of all inter-package name conflicts of classes
  374.      *
  375.      * This array allows documentation of PHP namespace conflicts that would
  376.      * occur should a user try to include these files in the same file
  377.      * @var array Format: (classname => array(path1, path2,...))
  378.      */
  379.     var $classconflicts = array();
  380.     /**#@-*/
  381.     /**
  382.      * While parsing, add a class to the list of parsed classes
  383.      *
  384.      * sets up the {@link $classesbyfile, $classesbynamefile, $extendsbyfile},
  385.      * {@link $classchildrenbyfile, $roots} arrays, and sets {@link $curclass}
  386.      *
  387.      * @param parserClass &$element element is a {@link parserClass}
  388.      *
  389.      * @return void
  390.      * @uses addPackageToFile() marks the current class's package as being
  391.      *                          present in a file
  392.      */
  393.     function addClass(&$element)
  394.     {
  395.         $this->curclass   = $element->getName();
  396.         $element->curfile = $this->curfile;
  397.         if (isset($this->classesbyfile[$this->curfile][$this->curclass])) {
  398.             addWarning(PDERROR_ELEMENT_IGNORED, 
  399.                 'class', $this->curclass, $this->curfile);
  400.             $this->curclass = false;
  401.             return;
  402.         }
  403.         $this->
  404.             classesbyfile
  405.                 [$this->curfile][$this->curclass]
  406.             = $element;
  407.         $this->
  408.             classesbynamefile[$this->curclass][]
  409.             = $this->curfile;
  410.         $this->
  411.             extendsbyfile[$this->curfile][$this->curclass]
  412.             = $element->getExtends();
  413.         $this->
  414.             classchildrenbyfile[$element->getExtends()]
  415.                 [$this->curfile][$this->curclass][] 
  416.             = $element->docblock->package;
  417.         if ($element->docblock->getExplicitPackage())
  418.         $this->addPackageToFile($element->docblock->package);
  419.         if (!$element->getExtends()) {
  420.             $this->roots[$this->curclass][] = $this->curfile;
  421.         }
  422.     }
  423.     
  424.     /**
  425.      * While parsing, add a method to the list of parsed methods
  426.      *
  427.      * sets up the {@link $methodsbyfile} array using {@link $curfile} and
  428.      * {@link $curclass}
  429.      *
  430.      * @param parserMethod &$element element is a {@link parserMethod}
  431.      *
  432.      * @return void
  433.      */
  434.     function addMethod(&$element)
  435.     {
  436.         if (!$this->curclass) return;
  437.         $this->methodsbyfile[$this->curfile][$this->curclass][] = $element;
  438.     }
  439.     
  440.     /**
  441.      * While parsing, add a variable to the list of parsed variables
  442.      *
  443.      * sets up the {@link $varsbyfile} array using {@link $curfile} 
  444.      * and {@link $curclass}
  445.      *
  446.      * @param parserVar &$element element is a {@link parserVar}
  447.      *
  448.      * @return void
  449.      */
  450.     function addVar(&$element)
  451.     {
  452.         if (!$this->curclass) return;
  453.         $this->varsbyfile[$this->curfile][$this->curclass][] = $element;
  454.     }
  455.     
  456.     /**
  457.      * While parsing, add a variable to the list of parsed variables
  458.      *
  459.      * sets up the {@link $constsbyfile} array using {@link $curfile} 
  460.      * and {@link $curclass}
  461.      *
  462.      * @param parserConst &$element element is a {@link parserConst}
  463.      *
  464.      * @return void
  465.      */
  466.     function addConst(&$element)
  467.     {
  468.         if (!$this->curclass) return;
  469.         $this->constsbyfile[$this->curfile][$this->curclass][] = $element;
  470.     }
  471.     
  472.     /**
  473.      * Prepare to parse a new file
  474.      *
  475.      * sets {@link $curfile} to $file and {@link $curclass} 
  476.      * to false (no class being parsed)
  477.      *
  478.      * @param string $file file currently being parsed
  479.      *
  480.      * @return void
  481.      */
  482.     function nextFile($file)
  483.     {
  484.         $this->curfile  = $file;
  485.         $this->curclass = false;
  486.     }
  487.     
  488.     /**
  489.      * Mark a package as being used in a class
  490.      *
  491.      * {@source}
  492.      *
  493.      * @param string $package package name
  494.      *
  495.      * @return void
  496.      */
  497.     function addPackageToFile($package)
  498.     {
  499.         if (!isset($this->revcpbf[$this->curfile][$package]))
  500.         $this->classpackagebyfile[$this->curfile][] = $package;
  501.         $this->revcpbf[$this->curfile][$package]    = 1;
  502.     }
  503.     
  504.     /**
  505.      * Find the parent class of $class, and set up structures to note this fact
  506.      *
  507.      * Modifies the {@link parserClass} element in {@link $classesbyfile} to use
  508.      * the parent's package, and inherit methods/vars
  509.      *
  510.      * @param string $class child class to find parent class
  511.      * @param string $file  file child class is located in
  512.      *
  513.      * @return void
  514.      * @uses $definitechild if a match is made between a parent class and parameter
  515.      *                      $class in file $file, then definitechild is set here
  516.      * @uses getParentClass() to find the parent class
  517.      */
  518.     function setClassParent($class,$file)
  519.     {
  520.         if (is_array($par = $this->getParentClass($class, $file))) {
  521.             // (for debugging)
  522.             // phpDocumentor_out("$file class $class extends "
  523.             //    . $par[1] ." file ". $par[0] . "\n");
  524.  
  525.             $this->classesbyfile[$file][$class]->setParent($par[1], $par[0], $this);
  526.             $this->definitechild[$par[1]][$par[0]][$class] = $file;
  527.         } else {
  528.             $this->classesbyfile[$file][$class]->setParentNoClass($par);
  529.         }
  530.     }
  531.     
  532.     /**
  533.      * Main processing engine for setting up class inheritance.
  534.      *
  535.      * This function uses {@link $roots} to traverse the inheritance tree via
  536.      * {@link processChild()} and returns the data structures
  537.      * phpDocumentor_IntermediateParser needs to convert parsed data
  538.      * to output using {@link phpDocumentor_IntermediateParser::Convert()}
  539.      *
  540.      * @param phpDocumentor_IntermediateParser &$render the renderer object
  541.      *
  542.      * @return void
  543.      * @uses processChild() set up inheritance
  544.      * @todo CS Cleanup - rename to "inherit" for CamelCaps naming standard
  545.      */
  546.     function Inherit(&$render)
  547.     {
  548.         phpDocumentor_out("\nProcessing Class Inheritance\n\n");
  549.         flush();
  550.         phpDocumentor_out("\nProcessing Root Trees\n\n");
  551.         flush();
  552.         foreach ($this->roots as $class => $files) {
  553.             for ($i=0; $i<count($files); $i++) {
  554.                 $this->processChild($render, $class, $files[$i]);
  555.             }
  556.         }
  557.         if (0)
  558.         foreach ($this->classesbyfile as $i => $j) {
  559.             foreach ($j as $k => $m) {
  560.                 var_dump($i, $k);
  561.                 if ($i == 'iConverter') {
  562.                     var_dump($j);
  563.                 }
  564.             }
  565.         }
  566.         phpDocumentor_out("\nProcessing leftover classes "
  567.             . "(classes that extend root classes not found in the same package)\n");
  568.         flush();
  569.         foreach ($this->classesbyfile as $i => $j) {
  570.             foreach ($j as $k => $m) {
  571.                 $this->processChild($render, $k, $i, true);
  572.             }
  573.         }
  574.         phpDocumentor_out("done processing leftover classes\n");
  575.         flush();
  576.         $this->setupClassConflicts();
  577.     }
  578.     
  579.     /**
  580.      * Transfers actual conflicts from {@link $potentialClassconflicts} to
  581.      * {@link $classconflicts}
  582.      *
  583.      * @return void
  584.      * @access private
  585.      * @uses $potentialclassconflicts transfers values to {@link $classconflicts}
  586.      */
  587.     function setupClassConflicts()
  588.     {
  589.         foreach ($this->potentialclassconflicts as $class => $paths) {
  590.             if (count($paths) - 1) { //conflict
  591.                 $package = array();
  592.                 foreach ($paths as $path) {
  593.                     // create a list of conflicting classes in each package
  594.                     if (isset($this->classpathpackages[$class][$path]))
  595.                     $package[$this->classpathpackages[$class][$path][0]][] = $path;
  596.                 }
  597.                 foreach ($package as $pathpackages) {
  598.                     /*
  599.                      * if at least 2 functions exist in the same package, 
  600.                      * delete all but the first one and add warnings
  601.                      */
  602.                     if (count($pathpackages) - 1) {
  603.                         for ($i=1; $i < count($pathpackages); $i++) {
  604.                             if (isset($this->classesbyfile[$pathpackages[$i]])) {
  605.                                 addWarning(PDERROR_ELEMENT_IGNORED, 
  606.                                     'class', $class, $pathpackages[$i]);
  607.                                 $this->killClass($class, $pathpackages[$i]);
  608.                                 $oth = array_flip($paths);
  609.                                 unset($paths[$oth[$pathpackages[$i]]]);
  610.                             }
  611.                         }
  612.                     }
  613.                 }
  614.                 $this->classconflicts[$class] = $paths;
  615.             }
  616.         }
  617.     }
  618.     
  619.     /**
  620.      * If a package contains two classes with the same name, this function finds
  621.      * that conflict
  622.      *
  623.      * Returns the {@link $classconflicts} entry for class $class, minus its own path
  624.      *
  625.      * @param mixed $class the class name to search for
  626.      *
  627.      * @return mixed returns false if no conflicts, 
  628.      *               or an array of paths containing conflicts
  629.      */
  630.     function getConflicts($class)
  631.     {
  632.         if (!isset($this->classconflicts[$class])) return false;
  633.         $a = array();
  634.         foreach ($this->classconflicts[$class] as $conflict) {
  635.             $a[$this->classesbyfile[$conflict][$class]->docblock->package] 
  636.                 = $this->classesbyfile[$conflict][$class];
  637.         }
  638.         return $a;
  639.     }
  640.     
  641.     /**
  642.      * sets up {@link $killclass} for use by Converter::checkKillClass()
  643.      *
  644.      * @param mixed $class the class
  645.      * @param mixed $path  the path
  646.      *
  647.      * @return void
  648.      * @access private
  649.      */
  650.     function killClass($class,$path)
  651.     {
  652.         $this->killclass[$class][$path] = true;
  653.     }
  654.     
  655.     /**
  656.      * This function recursively climbs up the class tree, setting inherited
  657.      * information like package and adds the elements to 
  658.      * {@link phpDocumentor_IntermediateParser}.
  659.      *
  660.      * Using structures defined in {@link Classes}, 
  661.      * the function first sets package information,
  662.      * and then seeks out child classes.
  663.      * It uses 3 tests to determine whether a class is a child class.
  664.      * <ol>
  665.      *    <li>child class is in the same file as the parent class 
  666.      *        and extends parent class
  667.      *    </li>
  668.      *    <li>child class is in a different file and specifies 
  669.      *        the parent's @package in its docblock
  670.      *    </li>
  671.      *    <li>child class is in a different file and is in a 
  672.      *        different @package, with one possible parent class
  673.      *    </li>
  674.      * </ol>
  675.      *
  676.      * @param phpDocumentor_IntermediateParser &$render the renderer object
  677.      * @param string                           $class   class to process
  678.      * @param string                           $file    name of file $class 
  679.      *                                                  is located in
  680.      * @param boolean                          $furb    flag used privately
  681.      *                                                  to control informational
  682.      *                                                  output while parsing
  683.      *                                                  (used when processing 
  684.      *                                                  leftover classes in 
  685.      *                                                  {@link Inherit()}
  686.      *
  687.      * @return void
  688.      * @global string default package, usually "default"
  689.      */
  690.     function processChild(&$render,$class,$file,$furb = false)
  691.     {
  692.         global $phpDocumentor_DefaultPackageName;
  693.         if (isset($this->classesbyfile[$file][$class]->processed))
  694.             return;
  695.         $this->potentialclassconflicts[$class][] = $file;
  696.         if ($furb)
  697.             phpDocumentor_out("Processing $class in file $file\n");
  698.         flush();
  699.         $this->classesbyfile[$file][$class]->processed = true;
  700.  
  701.         $db = $this->classesbyfile[$file][$class];
  702.         $render->addUses($db, $file);
  703.         if (!$render->parsePrivate) {
  704.             /*
  705.              * if this class has an @access private, 
  706.              * and parse private is disabled, remove it
  707.              */
  708.             if ($db->docblock->hasaccess) {
  709.                 $aaa = $db->docblock->getKeyword('access');
  710.                 if (is_object($aaa) && $aaa->getString() == 'private') {
  711.                     if (isset($this->varsbyfile[$file]) 
  712.                         && isset($this->varsbyfile[$file][$class])) {
  713.                         unset($this->varsbyfile[$file][$class]);
  714.                     }
  715.                     if (isset($this->methodsbyfile[$file]) 
  716.                         && isset($this->methodsbyfile[$file][$class])) {
  717.                         unset($this->methodsbyfile[$file][$class]);
  718.                     }
  719.                     if (isset($this->constsbyfile[$file]) 
  720.                         && isset($this->constsbyfile[$file][$class])) {
  721.                         unset($this->constsbyfile[$file][$class]);
  722.                     }
  723.                     $this->classesbyfile[$file][$class]->ignore = true;
  724.                     // if this is a root class, remove it from the roots array
  725.                     if (isset($this->roots[$class])) {
  726.                         foreach ($this->roots[$class] as $i => $files) {
  727.                             // find the file key and unset
  728.                             if ($files == $file) 
  729.                                 unset($this->roots[$class][$i]);
  730.                         }
  731.                     }
  732.                     /*
  733.                      * if this is a child, remove it from the list 
  734.                      * of child classes of its parent
  735.                      */
  736.                     if ($db->getExtends()) 
  737.                         unset($this->classchildrenbyfile[$db->getExtends()][$file]);
  738.                     return;
  739.                 }
  740.             }
  741.         }
  742.         if ($render->packageoutput) {
  743.             if (!in_array($db->docblock->package, $render->packageoutput)) {
  744.                 if (isset($this->varsbyfile[$file]) 
  745.                     && isset($this->varsbyfile[$file][$class])) {
  746.                     unset($this->varsbyfile[$file][$class]);
  747.                 }
  748.                 if (isset($this->methodsbyfile[$file]) 
  749.                     && isset($this->methodsbyfile[$file][$class])) {
  750.                     unset($this->methodsbyfile[$file][$class]);
  751.                 }
  752.                 if (isset($this->constsbyfile[$file]) 
  753.                     && isset($this->constsbyfile[$file][$class])) {
  754.                     unset($this->constsbyfile[$file][$class]);
  755.                 }
  756.                 $this->classesbyfile[$file][$class]->ignore = true;
  757.                 if (isset($this->roots[$class])) {
  758.                     foreach ($this->roots[$class] as $i => $files) {
  759.                         if ($files == $file) unset($this->roots[$class][$i]);
  760.                     }
  761.                 }
  762.                 if ($db->getExtends()) 
  763.                     unset($this->classchildrenbyfile[$db->getExtends()][$file]);
  764.                 return;
  765.             }
  766.         }
  767.         $this->setClassParent($class, $file);
  768.         $db = $this->classesbyfile[$file][$class];
  769.         if ($furb && !is_array($db->parent)) {
  770.             // debug("furb adding $class $file to roots");
  771.             $this->specialRoots[$db->parent][] = array($class, $file);
  772.         }
  773.         // fix for 591396
  774.         if (!$db->docblock->getExplicitPackage()) {
  775.             $a = $render->proceduralpages->pagepackages[$file];
  776.             if ($a[0] != $phpDocumentor_DefaultPackageName) {
  777.                 // inherit page package
  778.                 $this->classesbyfile[$file][$class]->docblock->package = $a[0];
  779.             }
  780.         }
  781.         if ($this->classesbyfile[$file][$class]->docblock->package 
  782.             == $render->proceduralpages->pagepackages[$file][0]) {
  783.             if ($this->classesbyfile[$file][$class]->docblock->subpackage == '') {
  784.                 $this->classesbyfile[$file][$class]->docblock->subpackage 
  785.                     = $render->proceduralpages->pagepackages[$file][1];
  786.             }
  787.         }
  788.         $db = $this->classesbyfile[$file][$class];
  789.         $render->addPackageParent($db);
  790.         $render->addPageIfNecessary($file, $db);
  791.         if ($access = $db->docblock->getKeyword('access')) {
  792.             if (!is_string($access) && is_object($access)) 
  793.                 $access = $access->getString();
  794.             if (!is_string($access)) 
  795.                 $access = 'public';
  796.             if (($access == 'private') && (!$render->parsePrivate)) {
  797.                 if (isset($this->varsbyfile[$file]) 
  798.                     && isset($this->varsbyfile[$file][$class])) {
  799.                     foreach ($this->varsbyfile[$file][$class] as $i => $vr) {
  800.                         $vr->docblock->addKeyword('access', 'private');
  801.                         $this->varsbyfile[$file][$class][$i] = $vr;
  802.                     }
  803.                 }
  804.                 if (isset($this->methodsbyfile[$file]) 
  805.                     && isset($this->methodsbyfile[$file][$class])) {
  806.                     foreach ($this->methodsbyfile[$file][$class] as $i => $vr) {
  807.                         $vr->docblock->addKeyword('access', 'private');
  808.                         $this->methodsbyfile[$file][$class][$i] = $vr;
  809.                     }
  810.                 }
  811.                 if (isset($this->constsbyfile[$file]) 
  812.                     && isset($this->constsbyfile[$file][$class])) {
  813.                     foreach ($this->constsbyfile[$file][$class] as $i => $vr) {
  814.                         $vr->docblock->addKeyword('access', 'private');
  815.                         $this->constsbyfile[$file][$class][$i] = $vr;
  816.                     }
  817.                 }
  818.             }
  819.         }
  820.         $this->classpathpackages[$class][$file] 
  821.             = array($db->docblock->package,$db->docblock->subpackage);
  822.         if ($db->docblock->getExplicitPackage()) {
  823.             $render->proceduralpages->
  824.                 addClassPackageToFile($file, 
  825.                     $db->docblock->package, $db->docblock->subpackage);
  826.         }
  827.         $render->addElementToPage($db, $file);
  828.         if (isset($this->varsbyfile[$file]) 
  829.             && isset($this->varsbyfile[$file][$class])) {
  830.             foreach ($this->varsbyfile[$file][$class] as $i => $vr) {
  831.                 $vr->docblock->package    = $db->docblock->package;
  832.                 $vr->docblock->subpackage = $db->docblock->subpackage;
  833.                 $render->addElementToPage($vr, $file);
  834.                 $render->addUses($vr, $file);
  835.                 $this->varsbyfile[$file][$class][$i]                        = $vr;
  836.                 $this->vars[$db->docblock->package][$class][$vr->getName()] = $vr;
  837.             }
  838.         }
  839.         if (isset($this->methodsbyfile[$file]) 
  840.             && isset($this->methodsbyfile[$file][$class])) {
  841.             foreach ($this->methodsbyfile[$file][$class] as $i => $vr) {
  842.                 $vr->docblock->package    = $db->docblock->package;
  843.                 $vr->docblock->subpackage = $db->docblock->subpackage;
  844.                 $render->addElementToPage($vr, $file);
  845.                 $render->addUses($vr, $file);
  846.                 $this->methodsbyfile[$file][$class][$i]                        = $vr;
  847.                 $this->methods[$db->docblock->package][$class][$vr->getName()] = $vr;
  848.             }
  849.         }
  850.         if (isset($this->constsbyfile[$file]) 
  851.             && isset($this->constsbyfile[$file][$class])) {
  852.             foreach ($this->constsbyfile[$file][$class] as $i => $vr) {
  853.                 $vr->docblock->package    = $db->docblock->package;
  854.                 $vr->docblock->subpackage = $db->docblock->subpackage;
  855.                 $render->addElementToPage($vr, $file);
  856.                 $render->addUses($vr, $file);
  857.                 $this->constsbyfile[$file][$class][$i]                         = $vr;
  858.                 $this->methods[$db->docblock->package][$class][$vr->getName()] = $vr;
  859.             }
  860.         }
  861.         $this->classpackages[$class][] 
  862.             = array($db->docblock->package,$db->docblock->subpackage);
  863.         if (is_array($db->parent))
  864.             $this->classparents[$db->docblock->package][$class] = $db->parent[1];
  865.         else
  866.             $this->classparents[$db->docblock->package][$class] = $db->getExtends();
  867.         if (is_array($db->parent)) {
  868.             $z = $this->getClass($db->parent[1], $db->parent[0]);
  869.  
  870.             $this->classchildren[$z->docblock->package][$db->parent[1]][] = $db;
  871.         }
  872.         if (isset($this->classchildrenbyfile[$class])) {
  873.             foreach ($this->classchildrenbyfile[$class] as $childfile => $other) {
  874.                 // test 1, inherits in same file (must be same package)
  875.                 if ($childfile == $file) {
  876.                     foreach ($other as $child => $packages) {
  877.                         // debug("parent $class same file $child");
  878.                         $this->processChild($render, $child, $childfile);
  879.                         $x = $this->getClass($child, $childfile);
  880.                         if ($x->docblock->package 
  881.                             != $GLOBALS['phpDocumentor_DefaultPackageName']) {
  882.                             // child package need root for class trees
  883.                             if ($x->docblock->package != $db->docblock->package) {
  884.                                 // debug("adding $child in $childfile 1");
  885.                                 $this->roots[$child][] = $childfile;
  886.                             }
  887.                         }
  888.                     }
  889.                 } else {
  890.                     // test 2, different file, same package
  891.                     foreach ($other as $child => $packages) {
  892.                         for ($j=0; $j<count($packages); $j++) {
  893.                             if ($this->classesbyfile[$file][$class]->
  894.                                     docblock->package == $packages[$j]) {
  895.                                 $this->processChild($render, $child, $childfile);
  896.                                 // debug("$childfile diff file $child, parent $class,
  897.                                 //     same package ".$packages[$j]);
  898.                             } else {
  899.                                 /*
  900.                                  * test 3, different file, different package, 
  901.                                  * only 1 parent is possible
  902.                                  */
  903.                                 if (isset($this->classesbynamefile[$child])) {
  904.                                     // 1 possible parent
  905.                                     if (count($this->classesbynamefile[$class]) 
  906.                                         == 1) {
  907.                                         // debug("$childfile diff file $child, 
  908.                                         //        diff package, 
  909.                                         //        1 possible parent root $class");
  910.                                         $this->processChild($render, 
  911.                                             $child, $childfile);
  912.                                         $x = $this->getClass($child, $childfile);
  913.                                         if ($x->docblock->package 
  914.                                           != $GLOBALS
  915.                                           ['phpDocumentor_DefaultPackageName']) {
  916.                                             // child package need root 
  917.                                             //for class trees
  918.                                             if ($x->docblock->package 
  919.                                                 != $db->docblock->package) {
  920.                                                 // debug("adding roots 
  921.                                                 // $child in $childfile 2");
  922.                                                 $this->roots[$child][] = $childfile;
  923.                                             }
  924.                                         }
  925.                                     }
  926.                                 }
  927.                             }
  928.                         }
  929.                     }
  930.                 }
  931.             }
  932.         }
  933.     }
  934.     
  935.     /**
  936.      * Get the parserClass representation of a class from its name and file
  937.      *
  938.      * @param string $class classname
  939.      * @param string $file  file classname is located in
  940.      *
  941.      * @return parserClass
  942.      */
  943.     function &getClass($class, $file)
  944.     {
  945.         // debug("getClass called with class $class file $file");
  946.         return $this->classesbyfile[$file][$class];
  947.     }
  948.     
  949.     /**
  950.      * Used by {@link parserData::getClasses()} 
  951.      * to retrieve classes defined in file $path
  952.      *
  953.      * retrieves the array entry from {@link $classesbyfile} for $path
  954.      *
  955.      * @param string $path full path to filename
  956.      *
  957.      * @return mixed returns false if no classes defined in the file, 
  958.      *               otherwise returns an array of {@link parserClass}es
  959.      */
  960.     function getClassesInPath($path)
  961.     {
  962.         if (!isset($this->classesbyfile[$path])) return false;
  963.         return $this->classesbyfile[$path];
  964.     }
  965.     
  966.     /**
  967.      * called by {@link parserClass::hasMethods()}.  Should not be directly called
  968.      *
  969.      * @param string $file  file classname is located in
  970.      * @param string $class classname
  971.      *
  972.      * @return bool
  973.      * @access private
  974.      */
  975.     function hasMethods($file, $class)
  976.     {
  977.         return isset($this->methodsbyfile[$file][$class]);
  978.     }
  979.     
  980.     /**
  981.      * called by {@link parserClass::hasConsts()}.  
  982.      * Should not be directly called
  983.      *
  984.      * @param string $file  file classname is located in
  985.      * @param string $class classname
  986.      *
  987.      * @return bool
  988.      * @access private
  989.      */
  990.     function hasConsts($file,$class)
  991.     {
  992.         return isset($this->constsbyfile[$file][$class]);
  993.     }
  994.     
  995.     /**
  996.      * called by {@link parserClass::hasVars()}.  Should not be directly called
  997.      *
  998.      * @param string $file  file classname is located in
  999.      * @param string $class classname
  1000.      *
  1001.      * @return bool
  1002.      * @access private
  1003.      */
  1004.     function hasVars($file, $class)
  1005.     {
  1006.         return isset($this->varsbyfile[$file][$class]);
  1007.     }
  1008.     
  1009.     /**
  1010.      * called by {@link parserClass::hasMethod()}.  Should not be directly called
  1011.      *
  1012.      * @param string $class classname
  1013.      * @param string $file  file classname is located in
  1014.      * @param string $name  method name
  1015.      *
  1016.      * @return bool
  1017.      * @access private
  1018.      */
  1019.     function hasMethod($class, $file, $name)
  1020.     {
  1021.         if (!$this->hasMethods($file, $class)) return false;
  1022.         for ($i=0; $i<count($this->methodsbyfile[$file][$class]); $i++) {
  1023.             if ($this->methodsbyfile[$file][$class][$i]->getName() == $name) 
  1024.                return true;
  1025.         }
  1026.         return false;
  1027.     }
  1028.     
  1029.     /**
  1030.      * called by {@link parserClass::hasVar()}.  Should not be directly called
  1031.      *
  1032.      * @param string $class classname
  1033.      * @param string $file  file classname is located in
  1034.      * @param string $name  var name
  1035.      *
  1036.      * @return bool
  1037.      * @access private
  1038.      */
  1039.     function hasVar($class, $file, $name)
  1040.     {
  1041.         if (!$this->hasVars($file, $class)) return false;
  1042.         for ($i=0; $i<count($this->varsbyfile[$file][$class]); $i++) {
  1043.             if ($this->varsbyfile[$file][$class][$i]->getName() == $name) 
  1044.                 return true;
  1045.         }
  1046.         return false;
  1047.     }
  1048.     
  1049.     /**
  1050.      * called by {@link parserClass::hasConst()}.  Should not be directly called
  1051.      *
  1052.      * @param string $class classname
  1053.      * @param string $file  file classname is located in
  1054.      * @param string $name  constant name
  1055.      *
  1056.      * @return bool
  1057.      * @access private
  1058.      */
  1059.     function hasConst($class, $file, $name)
  1060.     {
  1061.         if (!$this->hasConsts($file, $class)) return false;
  1062.         for ($i=0; $i<count($this->constsbyfile[$file][$class]); $i++) {
  1063.             if ($this->constsbyfile[$file][$class][$i]->getName() == $name) 
  1064.                 return true;
  1065.         }
  1066.         return false;
  1067.     }
  1068.     
  1069.     /**
  1070.      * called by {@link parserClass::getMethods()}.  Should not be directly called
  1071.      *
  1072.      * @param string $class classname
  1073.      * @param string $file  file classname is located in
  1074.      *
  1075.      * @return mixed
  1076.      * @access private
  1077.      */
  1078.     function &getMethods($class, $file)
  1079.     {
  1080.         if (!isset($this->methodsbyfile[$file][$class])) {
  1081.             $flag = false;
  1082.             return $flag;
  1083.         }
  1084.         return $this->methodsbyfile[$file][$class];
  1085.     }
  1086.     
  1087.     /**
  1088.      * called by {@link parserClass::getVars()}.  Should not be directly called
  1089.      *
  1090.      * @param string $class classname
  1091.      * @param string $file  file classname is located in
  1092.      *
  1093.      * @return mixed
  1094.      * @access private
  1095.      */
  1096.     function &getVars($class, $file)
  1097.     {
  1098.         if (!isset($this->varsbyfile[$file][$class])) {
  1099.             $flag = false;
  1100.             return $flag;
  1101.         }
  1102.         return $this->varsbyfile[$file][$class];
  1103.     }
  1104.     
  1105.     /**
  1106.      * called by {@link parserClass::getConsts()}.  Should not be directly called
  1107.      *
  1108.      * @param string $class classname
  1109.      * @param string $file  file classname is located in
  1110.      *
  1111.      * @return mixed
  1112.      * @access private
  1113.      */
  1114.     function &getConsts($class, $file)
  1115.     {
  1116.         if (!isset($this->constsbyfile[$file][$class])) {
  1117.             $flag = false;
  1118.             return $flag;
  1119.         }
  1120.         return $this->constsbyfile[$file][$class];
  1121.     }
  1122.     
  1123.     /**
  1124.      * called by {@link parserClass::getMethod()}.  Should not be directly called
  1125.      *
  1126.      * @param string $class classname
  1127.      * @param string $file  file classname is located in
  1128.      * @param string $name  method name
  1129.      *
  1130.      * @return mixed
  1131.      * @access private
  1132.      */
  1133.     function getMethod($class, $file, $name)
  1134.     {
  1135.         if (!$this->hasMethod($class, $file, $name)) return false;
  1136.         for ($i=0; $i<count($this->methodsbyfile[$file][$class]); $i++) {
  1137.             if ($this->methodsbyfile[$file][$class][$i]->getName() == $name) 
  1138.                 return $this->methodsbyfile[$file][$class][$i];
  1139.         }
  1140.     }
  1141.     
  1142.     /**
  1143.      * called by {@link parserClass::getVar()}.  Should not be directly called
  1144.      *
  1145.      * @param string $class classname
  1146.      * @param string $file  file classname is located in
  1147.      * @param string $name  var name
  1148.      *
  1149.      * @return mixed
  1150.      * @access private
  1151.      */
  1152.     function getVar($class, $file, $name)
  1153.     {
  1154.         if (!$this->hasVar($class, $file, $name)) return false;
  1155.         for ($i=0; $i<count($this->varsbyfile[$file][$class]); $i++) {
  1156.             if ($this->varsbyfile[$file][$class][$i]->getName() == $name) 
  1157.                 return $this->varsbyfile[$file][$class][$i];
  1158.         }
  1159.     }
  1160.     
  1161.     /**
  1162.      * called by {@link parserClass::getConst()}.  Should not be directly called
  1163.      *
  1164.      * @param string $class classname
  1165.      * @param string $file  file classname is located in
  1166.      * @param string $name  const name
  1167.      *
  1168.      * @return mixed
  1169.      * @access private
  1170.      */
  1171.     function getConst($class, $file, $name)
  1172.     {
  1173.         if (!$this->hasConst($class, $file, $name)) return false;
  1174.         for ($i=0; $i<count($this->constsbyfile[$file][$class]); $i++) {
  1175.             if ($this->constsbyfile[$file][$class][$i]->getName() == $name) 
  1176.                 return $this->constsbyfile[$file][$class][$i];
  1177.         }
  1178.     }
  1179.     
  1180.     /**
  1181.      * Search for a class in a package
  1182.      *
  1183.      * @param string $class   classname
  1184.      * @param string $package package classname is in
  1185.      *
  1186.      * @return mixed returns false if no class in $package, 
  1187.      *               otherwise returns a {@link parserClass}
  1188.      */
  1189.     function &getClassByPackage($class, $package)
  1190.     {
  1191.         if (!isset($this->classesbynamefile[$class])) {
  1192.             // removed, too many warnings, not very useful
  1193.             // addWarning(PDERROR_CLASS_NOT_IN_PACKAGE,$class,$package); 
  1194.  
  1195.             $flag = false;
  1196.             return $flag;
  1197.         }
  1198.         for ($i=0; $i < count($this->classesbynamefile[$class]); $i++) {
  1199.             $cls = 
  1200.                 $this->classesbyfile[$this->classesbynamefile[$class][$i]][$class];
  1201.             $pkg = $cls->getPackage();
  1202.             if ($pkg == $package)
  1203.                 return $cls;
  1204.         }
  1205.         // addWarning(PDERROR_CLASS_NOT_IN_PACKAGE,$class,$package);
  1206.  
  1207.         $flag = false;
  1208.         return $flag;
  1209.     }
  1210.     
  1211.     /**
  1212.      * Find the parent class of a class in file $file
  1213.      * uses 3 tests to find the parent classname:
  1214.      * <ol>
  1215.      *    <li>only one class with the parent classname</li>
  1216.      *    <li>more than one class, but only one in the same file as the child</li>
  1217.      *    <li>only one parent class in the same package as the child</li>
  1218.      * </ol>
  1219.      *
  1220.      * @param string $class classname
  1221.      * @param string $file  file classname is located in
  1222.      *
  1223.      * @return mixed false if no parent class, 
  1224.      *               a string if no parent class found by that name,
  1225.      *               and an array(file parentclass is in, parentclassname)
  1226.      */
  1227.     function getParentClass($class,$file)
  1228.     {
  1229.         if (!isset($this->classesbyfile[$file][$class])) {
  1230.             return false;
  1231.         }
  1232.         $element = $this->classesbyfile[$file][$class];
  1233.         if (!($ex = $element->getExtends())) return false;
  1234.         // first check to see if there is one and only one 
  1235.         // class with the parent class's name
  1236.         if (isset($this->classesbynamefile[$ex])) {
  1237.             if (count($this->classesbynamefile[$ex]) == 1) {
  1238.                 if ($this->classesbyfile
  1239.                     [$this->classesbynamefile[$ex][0]][$ex]->ignore) {
  1240.                     return $ex;
  1241.                 }
  1242.                 return array($this->classesbynamefile[$ex][0],$ex);
  1243.             } else {
  1244.                 // next check to see if there is a parent class in the same file
  1245.                 if (isset($this->classesbyfile[$file][$ex])) {
  1246.                     if ($this->classesbyfile[$file][$ex]->ignore) {
  1247.                         return $ex;
  1248.                     }
  1249.                     return array($file,$ex);
  1250.                 }
  1251.                 // next check to see if there is only one package 
  1252.                 // used in the file, try to resolve it that way
  1253.                 if (isset($this->classpackagebyfile[$file])) {
  1254.                     if (count($this->classpackagebyfile[$file]) == 1) {
  1255.                         for ($i=0;$i<count($this->classesbynamefile[$ex]);$i++) {
  1256.                             if ($this->classesbyfile
  1257.                               [$this->classesbynamefile[$ex][$i]][$ex]->getPackage() 
  1258.                                == $this->classpackagebyfile[$file][0]) {
  1259.                                 if ($this->classesbyfile
  1260.                                    [$this->classesbynamefile[$ex][$i]][$ex]->ignore) 
  1261.                                     return $ex;
  1262.                                 return array($this->classesbynamefile[$ex][$i],$ex);
  1263.                             }
  1264.                         }
  1265.                     }
  1266.                 }
  1267.                 // name conflict
  1268.                 addWarning(PDERROR_INHERITANCE_CONFLICT, $class, $file, $ex);
  1269.                 return $ex;
  1270.             }
  1271.         } else {
  1272.             if (class_exists('ReflectionClass') && class_exists($ex)) {
  1273.                 $r = new ReflectionClass($ex);
  1274.                 if ($r->isInternal()) {
  1275.                     return $ex; // no warning
  1276.                 }
  1277.             }
  1278.             addWarning(PDERROR_PARENT_NOT_FOUND, $class, $ex);
  1279.             return $ex;
  1280.         }
  1281.     }
  1282.     
  1283.     /**
  1284.      * Get a list of all root classes indexed by package.  Used to generate
  1285.      * class trees by {@link Converter}
  1286.      *
  1287.      * @param boolean $all [since phpDocumentor 1.3.0RC6] determines whether to
  1288.      *                     return class trees that extend non-parsed classes
  1289.      *
  1290.      * @return array array(package => array(rootclassname, rootclassname,...),...)
  1291.      */
  1292.     function getRoots($all = false)
  1293.     {
  1294.         $roots     = array();
  1295.         $temproots = $this->roots;
  1296.         if (!$all) {
  1297.             foreach ($this->specialRoots as $package => $root) {
  1298.                 foreach ($root as $parent => $info) {
  1299.                     $temproots[$info[0]][] = $info[1];
  1300.                 }
  1301.             }
  1302.         }
  1303.         foreach ($temproots as $class => $files) {
  1304.             if (count($files)) {
  1305.                 foreach ($files as $i => $boofou) {
  1306.                     $x = $this->getClass($class, $files[$i]);
  1307.  
  1308.                     $roots[$x->getPackage()][] = $class;
  1309.                 }
  1310.             }
  1311.         }
  1312.         foreach ($roots as $package => $root) {
  1313.             usort($roots[$package], "strnatcasecmp");
  1314.         }
  1315.         if ($all) {
  1316.             $specialRoots = array();
  1317.             foreach ($this->specialRoots as $parent => $classinfo) {
  1318.                 if (count($classinfo)) {
  1319.                     foreach ($classinfo as $i => $info) {
  1320.                         $x = $this->getClass($info[0], $info[1]);
  1321.  
  1322.                         $specialRoots[$x->getPackage()][$parent][] = $info[0];
  1323.                     }
  1324.                 }
  1325.             }
  1326.             foreach ($specialRoots as $package => $root) {
  1327.                 uksort($specialRoots[$package], "strnatcasecmp");
  1328.                 foreach ($specialRoots[$package] as $parent => $classes) {
  1329.                     usort($specialRoots[$package][$parent], 'strnatcasecmp');
  1330.                 }
  1331.             }
  1332.             return array('special' => $specialRoots, 'normal' => $roots);
  1333.         }
  1334.         return $roots;
  1335.     }
  1336.     
  1337.     /**
  1338.      * Get all classes confirmed in parsing 
  1339.      * to be descended class $parclass in file $file
  1340.      *
  1341.      * @param string $parclass name of parent class
  1342.      * @param string $file     file parent class is found in
  1343.      *
  1344.      * @return mixed either false if no children, or array of format
  1345.      *         array(childname => childfile,childname2 => childfile2,...)
  1346.      * @see parserClass::getChildClassList()
  1347.      * @uses $definitechild
  1348.      */
  1349.     function getDefiniteChildren($parclass, $file)
  1350.     {
  1351.         if (isset($this->definitechild[$parclass][$file])) 
  1352.             return $this->definitechild[$parclass][$file];
  1353.         return false;
  1354.     }
  1355. }
  1356. ?>
  1357.