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

Source for file Classes.inc

Documentation is available at Classes.inc

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

Documentation generated on Tue, 24 Oct 2006 09:21:14 -0500 by phpDocumentor 1.3.1