Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/*** Intermediate class parsing structure.** phpDocumentor :: automatic documentation generator** PHP versions 4 and 5** Copyright (c) 2001-2007 Gregory Beaver** LICENSE:** This library is free software; you can redistribute it* and/or modify it under the terms of the GNU Lesser General* Public License as published by the Free Software Foundation;* either version 2.1 of the License, or (at your option) any* later version.** This library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public* License along with this library; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA** @category ToolsAndUtilities* @package phpDocumentor* @author Greg Beaver <cellog@php.net>* @copyright 2001-2007 Gregory Beaver* @license http://www.opensource.org/licenses/lgpl-license.php LGPL* @version CVS: $Id: Classes.inc 243933 2007-10-10 01:18:25Z ashnazg $* @filesource* @link http://www.phpdoc.org* @link http://pear.php.net/PhpDocumentor* @see parserDocBlock, parserInclude, parserPage, parserClass* @see parserDefine, parserFunction, parserMethod, parserVar* @since 1.0rc1* @todo CS cleanup - change package to PhpDocumentor*//*** Intermediate class parsing structure.** The {@link phpDocumentor_IntermediateParser} class uses this class and its* cousin, {@link ProceduralPages} to organize all parsed source code elements.* Data is fed to each immediately after it is parsed, and at conversion time,* everything is organized.** The Classes class is responsible for all inheritance, including resolving* name conflicts between classes, determining which classes extend other* classes, and is responsible for all inheritance of documentation.* {@internal* This structure parses classes, vars and methods by file, and then iterates* over the class tree to set up inheritance. The {@link Inherit()}* method is the meat of the class, and processes the class trees from root to* branch, ensuring that parsing order is unimportant.}}** @category ToolsAndUtilities* @package phpDocumentor* @author Greg Beaver <cellog@php.net>* @copyright 2001-2007 Gregory Beaver* @license http://www.opensource.org/licenses/lgpl-license.php LGPL* @version Release: 1.4.3* @link http://www.phpdoc.org* @link http://pear.php.net/PhpDocumentor* @since 1.0rc1* @todo CS cleanup - change package to PhpDocumentor*/class Classes{/**#@+* @access private*//*** file being parsed, used in every add function to match up elements with* the file that contains them** This variable is used during parsing to associate class elements added* to the data structures that contain them with the file they reside in* @see addClass(), addMethod(), addVar(), nextFile()* @var string*/var $curfile;/*** class being parsed, used to match up methods and vars with their parent* class** This variable is used during parsing to associate class elements added* to the data structures that contain them with the file they reside in* @see addMethod(), addVar()* @var string*/var $curclass;/*** Used when a definite match is made between a parent class and a child* class** This variable is used in post-parsing.** Format:<pre>* array(* parent => array(* parentfile => array(* child => childfile* )* )* )</pre>* @var array*/var $definitechild;/*** array of parsed classes organized by the name of the file that contains* the class.** Format:<pre>* array(* filename => array(* classname => {@link parserClass}* )* )</pre>* @var array*/var $classesbyfile = array();/*** array of file names organized by classes that are in the file.** This structure is designed to handle name conflicts. Two files can* contain classes with the same name, and this array will record both* filenames to help control linking and inheritance errors** Format:<pre>* array(* classname => array(* name of file containing classname,* name of file 2 containing classname,* ...* )* )</pre>* @var array*/var $classesbynamefile = array();/*** array of parsed methods organized by the file that contains them.** Format:<pre>* array(* filename => array(* classname => array(* {@link parserMethod} 1,* {@link parserMethod} 2,* ...* )* )* )</pre>* @var array*/var $methodsbyfile = array();/*** array of parsed vars organized by the file that contains them.** Format:<pre>* array(* filename => array(* classname => array(* {@link parserVar} 1,* {@link parserVar} 2,* ...* )* )* )</pre>* @var array*/var $varsbyfile = array();/*** array of parsed class constants organized by the file that contains them.** Format:<pre>* array(* filename => array(* classname => array(* {@link parserConst} 1,* {@link parserConst} 2,* ...* )* )* )</pre>* @var array*/var $constsbyfile = array();/*** keeps track of extend declarations by file, used to find inheritance** Format:<pre>* array(* filename => array(* classname => parentclassname* )* )</pre>* @var array*/var $extendsbyfile = array();/*** Keeps track of child classes by file.* Since phpDocumentor can document collections of files that contain name* conflicts (PHP would give a fatal error), it* is impossible to assume a class that declares "extends foo" necessarily* extends the class foo in file X. It could be an* extended class of class foo in file Y. Because of this, phpDocumentor* relies on packaging to resolve the name conflict* This array keeps track of the packages of a child class** Format:<pre>* array(* parentclassname => array(* filename => array(* childclassname => array(* packagename,* packagename* )* )* )* )</pre>* @var array*/var $classchildrenbyfile = array();/*** Keeps track of class packages found in a file.* This is used in {@link getParentClass()} to determine the number of* packages in a file, in order to resolve inheritance issues* Format:<pre>* array(* filename => array(* packagename1,* packagename2,* ...* )* )</pre>* @var array*/var $classpackagebyfile = array();/*** a tree of class inheritance by name.** Format:<pre>* array(* childname => parentname,* childname1 => parentname1,* rootname => 0,* ...* )</pre>* @var array* @see Converter::generateSortedClassTreeFromClass()*/var $classparents = array();/*** Keeps track of package and subpackage for each class name, organized* by package** Format:<pre>* array(* classname => array(* path => array(* package,* subpackage* ),* path2 => array(* package,* subpackage* ),* ...* )* )</pre>* @var array*/var $classpathpackages = array();/*** used to delete duplicates in the same package to avoid documentation errors** Specifically used in {@link Converter::checkKillClass()}*/var $killclass = array();/*** array of methods by package and class** format:<pre>* array(packagename =>* array(classname =>* array(methodname1 => {@link parserMethod} class,* methodname2 => {@link parserMethod} class,...)* )* )* )</pre>* @var array* @see Converter*/var $methods = array();/*** array of class variables by package and class** format:<pre>* array(packagename =>* array(classname =>* array(variablename1 => {@link parserVar} class,* variablename2 => {@link parserVar} class,...* )* )* )</pre>* @var array* @see Converter*/var $vars = array();/*** array of class variables by package and class** format:<pre>* array(packagename =>* array(classname =>* array(constname1 => {@link parserConst} class,* constname2 => {@link parserConst} class,...* )* )* )</pre>* @var array* @see Converter*/var $consts = array();/*** Reverse class_packages_by_file, used to prevent duplicates* @var array Format: array(packagename => 1)*/var $revcpbf = array();/*** All classes with no parents (no extends clause) are tracked in this array* by the file that contains them.** Format:<pre>* array(* classname => array(* name of file1 that contains root classname,* name of file2 that contains root classname,* ...* )* )</pre>* @var array*/var $roots = array();/*** All classes with a parent that was not parsed are included in this array** Format:<pre>* array(* classname => array(* name of file1 that contains root classname,* name of file2 that contains root classname,* ...* )* )</pre>* @var array*/var $specialRoots = array();/*** array of all files that contain classes with the same name* @var array Format: (classname => array(path1, path2,...))*/var $potentialclassconflicts = array();/*** array of all inter-package name conflicts of classes** This array allows documentation of PHP namespace conflicts that would* occur should a user try to include these files in the same file* @var array Format: (classname => array(path1, path2,...))*/var $classconflicts = array();/**#@-*//*** While parsing, add a class to the list of parsed classes** sets up the {@link $classesbyfile, $classesbynamefile, $extendsbyfile},* {@link $classchildrenbyfile, $roots} arrays, and sets {@link $curclass}** @param parserClass &$element element is a {@link parserClass}** @return void* @uses addPackageToFile() marks the current class's package as being* present in a file*/function addClass(&$element){$this->curclass = $element->getName();$element->curfile = $this->curfile;if (isset($this->classesbyfile[$this->curfile][$this->curclass])) {addWarning(PDERROR_ELEMENT_IGNORED,'class', $this->curclass, $this->curfile);$this->curclass = false;return;}$this->classesbyfile[$this->curfile][$this->curclass]= $element;$this->classesbynamefile[$this->curclass][]= $this->curfile;$this->extendsbyfile[$this->curfile][$this->curclass]= $element->getExtends();$this->classchildrenbyfile[$element->getExtends()][$this->curfile][$this->curclass][]= $element->docblock->package;if ($element->docblock->getExplicitPackage())$this->addPackageToFile($element->docblock->package);if (!$element->getExtends()) {$this->roots[$this->curclass][] = $this->curfile;}}/*** While parsing, add a method to the list of parsed methods** sets up the {@link $methodsbyfile} array using {@link $curfile} and* {@link $curclass}** @param parserMethod &$element element is a {@link parserMethod}** @return void*/function addMethod(&$element){if (!$this->curclass) return;$this->methodsbyfile[$this->curfile][$this->curclass][] = $element;}/*** While parsing, add a variable to the list of parsed variables** sets up the {@link $varsbyfile} array using {@link $curfile}* and {@link $curclass}** @param parserVar &$element element is a {@link parserVar}** @return void*/function addVar(&$element){if (!$this->curclass) return;$this->varsbyfile[$this->curfile][$this->curclass][] = $element;}/*** While parsing, add a variable to the list of parsed variables** sets up the {@link $constsbyfile} array using {@link $curfile}* and {@link $curclass}** @param parserConst &$element element is a {@link parserConst}** @return void*/function addConst(&$element){if (!$this->curclass) return;$this->constsbyfile[$this->curfile][$this->curclass][] = $element;}/*** Prepare to parse a new file** sets {@link $curfile} to $file and {@link $curclass}* to false (no class being parsed)** @param string $file file currently being parsed** @return void*/function nextFile($file){$this->curfile = $file;$this->curclass = false;}/*** Mark a package as being used in a class** {@source}** @param string $package package name** @return void*/function addPackageToFile($package){if (!isset($this->revcpbf[$this->curfile][$package]))$this->classpackagebyfile[$this->curfile][] = $package;$this->revcpbf[$this->curfile][$package] = 1;}/*** Find the parent class of $class, and set up structures to note this fact** Modifies the {@link parserClass} element in {@link $classesbyfile} to use* the parent's package, and inherit methods/vars** @param string $class child class to find parent class* @param string $file file child class is located in** @return void* @uses $definitechild if a match is made between a parent class and parameter* $class in file $file, then definitechild is set here* @uses getParentClass() to find the parent class*/function setClassParent($class,$file){if (is_array($par = $this->getParentClass($class, $file))) {// (for debugging)// phpDocumentor_out("$file class $class extends "// . $par[1] ." file ". $par[0] . "\n");$this->classesbyfile[$file][$class]->setParent($par[1], $par[0], $this);$this->definitechild[$par[1]][$par[0]][$class] = $file;} else {$this->classesbyfile[$file][$class]->setParentNoClass($par);}}/*** Main processing engine for setting up class inheritance.** This function uses {@link $roots} to traverse the inheritance tree via* {@link processChild()} and returns the data structures* phpDocumentor_IntermediateParser needs to convert parsed data* to output using {@link phpDocumentor_IntermediateParser::Convert()}** @param phpDocumentor_IntermediateParser &$render the renderer object** @return void* @uses processChild() set up inheritance* @todo CS Cleanup - rename to "inherit" for CamelCaps naming standard*/function Inherit(&$render){phpDocumentor_out("\nProcessing Class Inheritance\n\n");flush();phpDocumentor_out("\nProcessing Root Trees\n\n");flush();foreach ($this->roots as $class => $files) {for ($i=0; $i<count($files); $i++) {$this->processChild($render, $class, $files[$i]);}}if (0)foreach ($this->classesbyfile as $i => $j) {foreach ($j as $k => $m) {var_dump($i, $k);if ($i == 'iConverter') {var_dump($j);}}}phpDocumentor_out("\nProcessing leftover classes ". "(classes that extend root classes not found in the same package)\n");flush();foreach ($this->classesbyfile as $i => $j) {foreach ($j as $k => $m) {$this->processChild($render, $k, $i, true);}}phpDocumentor_out("done processing leftover classes\n");flush();$this->setupClassConflicts();}/*** Transfers actual conflicts from {@link $potentialClassconflicts} to* {@link $classconflicts}** @return void* @access private* @uses $potentialclassconflicts transfers values to {@link $classconflicts}*/function setupClassConflicts(){foreach ($this->potentialclassconflicts as $class => $paths) {if (count($paths) - 1) { //conflict$package = array();foreach ($paths as $path) {// create a list of conflicting classes in each packageif (isset($this->classpathpackages[$class][$path]))$package[$this->classpathpackages[$class][$path][0]][] = $path;}foreach ($package as $pathpackages) {/** if at least 2 functions exist in the same package,* delete all but the first one and add warnings*/if (count($pathpackages) - 1) {for ($i=1; $i < count($pathpackages); $i++) {if (isset($this->classesbyfile[$pathpackages[$i]])) {addWarning(PDERROR_ELEMENT_IGNORED,'class', $class, $pathpackages[$i]);$this->killClass($class, $pathpackages[$i]);$oth = array_flip($paths);unset($paths[$oth[$pathpackages[$i]]]);}}}}$this->classconflicts[$class] = $paths;}}}/*** If a package contains two classes with the same name, this function finds* that conflict** Returns the {@link $classconflicts} entry for class $class, minus its own path** @param mixed $class the class name to search for** @return mixed returns false if no conflicts,* or an array of paths containing conflicts*/function getConflicts($class){if (!isset($this->classconflicts[$class])) return false;$a = array();foreach ($this->classconflicts[$class] as $conflict) {$a[$this->classesbyfile[$conflict][$class]->docblock->package]= $this->classesbyfile[$conflict][$class];}return $a;}/*** sets up {@link $killclass} for use by Converter::checkKillClass()** @param mixed $class the class* @param mixed $path the path** @return void* @access private*/function killClass($class,$path){$this->killclass[$class][$path] = true;}/*** This function recursively climbs up the class tree, setting inherited* information like package and adds the elements to* {@link phpDocumentor_IntermediateParser}.** Using structures defined in {@link Classes},* the function first sets package information,* and then seeks out child classes.* It uses 3 tests to determine whether a class is a child class.* <ol>* <li>child class is in the same file as the parent class* and extends parent class* </li>* <li>child class is in a different file and specifies* the parent's @package in its docblock* </li>* <li>child class is in a different file and is in a* different @package, with one possible parent class* </li>* </ol>** @param phpDocumentor_IntermediateParser &$render the renderer object* @param string $class class to process* @param string $file name of file $class* is located in* @param boolean $furb flag used privately* to control informational* output while parsing* (used when processing* leftover classes in* {@link Inherit()}** @return void* @global string default package, usually "default"*/function processChild(&$render,$class,$file,$furb = false){global $phpDocumentor_DefaultPackageName;if (isset($this->classesbyfile[$file][$class]->processed))return;$this->potentialclassconflicts[$class][] = $file;if ($furb)phpDocumentor_out("Processing $class in file $file\n");flush();$this->classesbyfile[$file][$class]->processed = true;$db = $this->classesbyfile[$file][$class];$render->addUses($db, $file);if (!$render->parsePrivate) {/** if this class has an @access private,* and parse private is disabled, remove it*/if ($db->docblock->hasaccess) {$aaa = $db->docblock->getKeyword('access');if (is_object($aaa) && $aaa->getString() == 'private') {if (isset($this->varsbyfile[$file])&& isset($this->varsbyfile[$file][$class])) {unset($this->varsbyfile[$file][$class]);}if (isset($this->methodsbyfile[$file])&& isset($this->methodsbyfile[$file][$class])) {unset($this->methodsbyfile[$file][$class]);}if (isset($this->constsbyfile[$file])&& isset($this->constsbyfile[$file][$class])) {unset($this->constsbyfile[$file][$class]);}$this->classesbyfile[$file][$class]->ignore = true;// if this is a root class, remove it from the roots arrayif (isset($this->roots[$class])) {foreach ($this->roots[$class] as $i => $files) {// find the file key and unsetif ($files == $file)unset($this->roots[$class][$i]);}}/** if this is a child, remove it from the list* of child classes of its parent*/if ($db->getExtends())unset($this->classchildrenbyfile[$db->getExtends()][$file]);return;}}}if ($render->packageoutput) {if (!in_array($db->docblock->package, $render->packageoutput)) {if (isset($this->varsbyfile[$file])&& isset($this->varsbyfile[$file][$class])) {unset($this->varsbyfile[$file][$class]);}if (isset($this->methodsbyfile[$file])&& isset($this->methodsbyfile[$file][$class])) {unset($this->methodsbyfile[$file][$class]);}if (isset($this->constsbyfile[$file])&& isset($this->constsbyfile[$file][$class])) {unset($this->constsbyfile[$file][$class]);}$this->classesbyfile[$file][$class]->ignore = true;if (isset($this->roots[$class])) {foreach ($this->roots[$class] as $i => $files) {if ($files == $file) unset($this->roots[$class][$i]);}}if ($db->getExtends())unset($this->classchildrenbyfile[$db->getExtends()][$file]);return;}}$this->setClassParent($class, $file);$db = $this->classesbyfile[$file][$class];if ($furb && !is_array($db->parent)) {// debug("furb adding $class $file to roots");$this->specialRoots[$db->parent][] = array($class, $file);}// fix for 591396if (!$db->docblock->getExplicitPackage()) {$a = $render->proceduralpages->pagepackages[$file];if ($a[0] != $phpDocumentor_DefaultPackageName) {// inherit page package$this->classesbyfile[$file][$class]->docblock->package = $a[0];}}if ($this->classesbyfile[$file][$class]->docblock->package== $render->proceduralpages->pagepackages[$file][0]) {if ($this->classesbyfile[$file][$class]->docblock->subpackage == '') {$this->classesbyfile[$file][$class]->docblock->subpackage= $render->proceduralpages->pagepackages[$file][1];}}$db = $this->classesbyfile[$file][$class];$render->addPackageParent($db);$render->addPageIfNecessary($file, $db);if ($access = $db->docblock->getKeyword('access')) {if (!is_string($access) && is_object($access))$access = $access->getString();if (!is_string($access))$access = 'public';if (($access == 'private') && (!$render->parsePrivate)) {if (isset($this->varsbyfile[$file])&& isset($this->varsbyfile[$file][$class])) {foreach ($this->varsbyfile[$file][$class] as $i => $vr) {$vr->docblock->addKeyword('access', 'private');$this->varsbyfile[$file][$class][$i] = $vr;}}if (isset($this->methodsbyfile[$file])&& isset($this->methodsbyfile[$file][$class])) {foreach ($this->methodsbyfile[$file][$class] as $i => $vr) {$vr->docblock->addKeyword('access', 'private');$this->methodsbyfile[$file][$class][$i] = $vr;}}if (isset($this->constsbyfile[$file])&& isset($this->constsbyfile[$file][$class])) {foreach ($this->constsbyfile[$file][$class] as $i => $vr) {$vr->docblock->addKeyword('access', 'private');$this->constsbyfile[$file][$class][$i] = $vr;}}}}$this->classpathpackages[$class][$file]= array($db->docblock->package,$db->docblock->subpackage);if ($db->docblock->getExplicitPackage()) {$render->proceduralpages->addClassPackageToFile($file,$db->docblock->package, $db->docblock->subpackage);}$render->addElementToPage($db, $file);if (isset($this->varsbyfile[$file])&& isset($this->varsbyfile[$file][$class])) {foreach ($this->varsbyfile[$file][$class] as $i => $vr) {$vr->docblock->package = $db->docblock->package;$vr->docblock->subpackage = $db->docblock->subpackage;$render->addElementToPage($vr, $file);$render->addUses($vr, $file);$this->varsbyfile[$file][$class][$i] = $vr;$this->vars[$db->docblock->package][$class][$vr->getName()] = $vr;}}if (isset($this->methodsbyfile[$file])&& isset($this->methodsbyfile[$file][$class])) {foreach ($this->methodsbyfile[$file][$class] as $i => $vr) {$vr->docblock->package = $db->docblock->package;$vr->docblock->subpackage = $db->docblock->subpackage;$render->addElementToPage($vr, $file);$render->addUses($vr, $file);$this->methodsbyfile[$file][$class][$i] = $vr;$this->methods[$db->docblock->package][$class][$vr->getName()] = $vr;}}if (isset($this->constsbyfile[$file])&& isset($this->constsbyfile[$file][$class])) {foreach ($this->constsbyfile[$file][$class] as $i => $vr) {$vr->docblock->package = $db->docblock->package;$vr->docblock->subpackage = $db->docblock->subpackage;$render->addElementToPage($vr, $file);$render->addUses($vr, $file);$this->constsbyfile[$file][$class][$i] = $vr;$this->methods[$db->docblock->package][$class][$vr->getName()] = $vr;}}$this->classpackages[$class][]= array($db->docblock->package,$db->docblock->subpackage);if (is_array($db->parent))$this->classparents[$db->docblock->package][$class] = $db->parent[1];else$this->classparents[$db->docblock->package][$class] = $db->getExtends();if (is_array($db->parent)) {$z = $this->getClass($db->parent[1], $db->parent[0]);$this->classchildren[$z->docblock->package][$db->parent[1]][] = $db;}if (isset($this->classchildrenbyfile[$class])) {foreach ($this->classchildrenbyfile[$class] as $childfile => $other) {// test 1, inherits in same file (must be same package)if ($childfile == $file) {foreach ($other as $child => $packages) {// debug("parent $class same file $child");$this->processChild($render, $child, $childfile);$x = $this->getClass($child, $childfile);if ($x->docblock->package!= $GLOBALS['phpDocumentor_DefaultPackageName']) {// child package need root for class treesif ($x->docblock->package != $db->docblock->package) {// debug("adding $child in $childfile 1");$this->roots[$child][] = $childfile;}}}} else {// test 2, different file, same packageforeach ($other as $child => $packages) {for ($j=0; $j<count($packages); $j++) {if ($this->classesbyfile[$file][$class]->docblock->package == $packages[$j]) {$this->processChild($render, $child, $childfile);// debug("$childfile diff file $child, parent $class,// same package ".$packages[$j]);} else {/** test 3, different file, different package,* only 1 parent is possible*/if (isset($this->classesbynamefile[$child])) {// 1 possible parentif (count($this->classesbynamefile[$class])== 1) {// debug("$childfile diff file $child,// diff package,// 1 possible parent root $class");$this->processChild($render,$child, $childfile);$x = $this->getClass($child, $childfile);if ($x->docblock->package!= $GLOBALS['phpDocumentor_DefaultPackageName']) {// child package need root//for class treesif ($x->docblock->package!= $db->docblock->package) {// debug("adding roots// $child in $childfile 2");$this->roots[$child][] = $childfile;}}}}}}}}}}}/*** Get the parserClass representation of a class from its name and file** @param string $class classname* @param string $file file classname is located in** @return parserClass*/function &getClass($class, $file){// debug("getClass called with class $class file $file");return $this->classesbyfile[$file][$class];}/*** Used by {@link parserData::getClasses()}* to retrieve classes defined in file $path** retrieves the array entry from {@link $classesbyfile} for $path** @param string $path full path to filename** @return mixed returns false if no classes defined in the file,* otherwise returns an array of {@link parserClass}es*/function getClassesInPath($path){if (!isset($this->classesbyfile[$path])) return false;return $this->classesbyfile[$path];}/*** called by {@link parserClass::hasMethods()}. Should not be directly called** @param string $file file classname is located in* @param string $class classname** @return bool* @access private*/function hasMethods($file, $class){return isset($this->methodsbyfile[$file][$class]);}/*** called by {@link parserClass::hasConsts()}.* Should not be directly called** @param string $file file classname is located in* @param string $class classname** @return bool* @access private*/function hasConsts($file,$class){return isset($this->constsbyfile[$file][$class]);}/*** called by {@link parserClass::hasVars()}. Should not be directly called** @param string $file file classname is located in* @param string $class classname** @return bool* @access private*/function hasVars($file, $class){return isset($this->varsbyfile[$file][$class]);}/*** called by {@link parserClass::hasMethod()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in* @param string $name method name** @return bool* @access private*/function hasMethod($class, $file, $name){if (!$this->hasMethods($file, $class)) return false;for ($i=0; $i<count($this->methodsbyfile[$file][$class]); $i++) {if ($this->methodsbyfile[$file][$class][$i]->getName() == $name)return true;}return false;}/*** called by {@link parserClass::hasVar()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in* @param string $name var name** @return bool* @access private*/function hasVar($class, $file, $name){if (!$this->hasVars($file, $class)) return false;for ($i=0; $i<count($this->varsbyfile[$file][$class]); $i++) {if ($this->varsbyfile[$file][$class][$i]->getName() == $name)return true;}return false;}/*** called by {@link parserClass::hasConst()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in* @param string $name constant name** @return bool* @access private*/function hasConst($class, $file, $name){if (!$this->hasConsts($file, $class)) return false;for ($i=0; $i<count($this->constsbyfile[$file][$class]); $i++) {if ($this->constsbyfile[$file][$class][$i]->getName() == $name)return true;}return false;}/*** called by {@link parserClass::getMethods()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in** @return mixed* @access private*/function &getMethods($class, $file){if (!isset($this->methodsbyfile[$file][$class])) {$flag = false;return $flag;}return $this->methodsbyfile[$file][$class];}/*** called by {@link parserClass::getVars()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in** @return mixed* @access private*/function &getVars($class, $file){if (!isset($this->varsbyfile[$file][$class])) {$flag = false;return $flag;}return $this->varsbyfile[$file][$class];}/*** called by {@link parserClass::getConsts()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in** @return mixed* @access private*/function &getConsts($class, $file){if (!isset($this->constsbyfile[$file][$class])) {$flag = false;return $flag;}return $this->constsbyfile[$file][$class];}/*** called by {@link parserClass::getMethod()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in* @param string $name method name** @return mixed* @access private*/function getMethod($class, $file, $name){if (!$this->hasMethod($class, $file, $name)) return false;for ($i=0; $i<count($this->methodsbyfile[$file][$class]); $i++) {if ($this->methodsbyfile[$file][$class][$i]->getName() == $name)return $this->methodsbyfile[$file][$class][$i];}}/*** called by {@link parserClass::getVar()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in* @param string $name var name** @return mixed* @access private*/function getVar($class, $file, $name){if (!$this->hasVar($class, $file, $name)) return false;for ($i=0; $i<count($this->varsbyfile[$file][$class]); $i++) {if ($this->varsbyfile[$file][$class][$i]->getName() == $name)return $this->varsbyfile[$file][$class][$i];}}/*** called by {@link parserClass::getConst()}. Should not be directly called** @param string $class classname* @param string $file file classname is located in* @param string $name const name** @return mixed* @access private*/function getConst($class, $file, $name){if (!$this->hasConst($class, $file, $name)) return false;for ($i=0; $i<count($this->constsbyfile[$file][$class]); $i++) {if ($this->constsbyfile[$file][$class][$i]->getName() == $name)return $this->constsbyfile[$file][$class][$i];}}/*** Search for a class in a package** @param string $class classname* @param string $package package classname is in** @return mixed returns false if no class in $package,* otherwise returns a {@link parserClass}*/function &getClassByPackage($class, $package){if (!isset($this->classesbynamefile[$class])) {// removed, too many warnings, not very useful// addWarning(PDERROR_CLASS_NOT_IN_PACKAGE,$class,$package);$flag = false;return $flag;}for ($i=0; $i < count($this->classesbynamefile[$class]); $i++) {$cls =$this->classesbyfile[$this->classesbynamefile[$class][$i]][$class];$pkg = $cls->getPackage();if ($pkg == $package)return $cls;}// addWarning(PDERROR_CLASS_NOT_IN_PACKAGE,$class,$package);$flag = false;return $flag;}/*** Find the parent class of a class in file $file* uses 3 tests to find the parent classname:* <ol>* <li>only one class with the parent classname</li>* <li>more than one class, but only one in the same file as the child</li>* <li>only one parent class in the same package as the child</li>* </ol>** @param string $class classname* @param string $file file classname is located in** @return mixed false if no parent class,* a string if no parent class found by that name,* and an array(file parentclass is in, parentclassname)*/function getParentClass($class,$file){if (!isset($this->classesbyfile[$file][$class])) {return false;}$element = $this->classesbyfile[$file][$class];if (!($ex = $element->getExtends())) return false;// first check to see if there is one and only one// class with the parent class's nameif (isset($this->classesbynamefile[$ex])) {if (count($this->classesbynamefile[$ex]) == 1) {if ($this->classesbyfile[$this->classesbynamefile[$ex][0]][$ex]->ignore) {return $ex;}return array($this->classesbynamefile[$ex][0],$ex);} else {// next check to see if there is a parent class in the same fileif (isset($this->classesbyfile[$file][$ex])) {if ($this->classesbyfile[$file][$ex]->ignore) {return $ex;}return array($file,$ex);}// next check to see if there is only one package// used in the file, try to resolve it that wayif (isset($this->classpackagebyfile[$file])) {if (count($this->classpackagebyfile[$file]) == 1) {for ($i=0;$i<count($this->classesbynamefile[$ex]);$i++) {if ($this->classesbyfile[$this->classesbynamefile[$ex][$i]][$ex]->getPackage()== $this->classpackagebyfile[$file][0]) {if ($this->classesbyfile[$this->classesbynamefile[$ex][$i]][$ex]->ignore)return $ex;return array($this->classesbynamefile[$ex][$i],$ex);}}}}// name conflictaddWarning(PDERROR_INHERITANCE_CONFLICT, $class, $file, $ex);return $ex;}} else {if (class_exists('ReflectionClass') && class_exists($ex)) {$r = new ReflectionClass($ex);if ($r->isInternal()) {return $ex; // no warning}}addWarning(PDERROR_PARENT_NOT_FOUND, $class, $ex);return $ex;}}/*** Get a list of all root classes indexed by package. Used to generate* class trees by {@link Converter}** @param boolean $all [since phpDocumentor 1.3.0RC6] determines whether to* return class trees that extend non-parsed classes** @return array array(package => array(rootclassname, rootclassname,...),...)*/function getRoots($all = false){$roots = array();$temproots = $this->roots;if (!$all) {foreach ($this->specialRoots as $package => $root) {foreach ($root as $parent => $info) {$temproots[$info[0]][] = $info[1];}}}foreach ($temproots as $class => $files) {if (count($files)) {foreach ($files as $i => $boofou) {$x = $this->getClass($class, $files[$i]);$roots[$x->getPackage()][] = $class;}}}foreach ($roots as $package => $root) {usort($roots[$package], "strnatcasecmp");}if ($all) {$specialRoots = array();foreach ($this->specialRoots as $parent => $classinfo) {if (count($classinfo)) {foreach ($classinfo as $i => $info) {$x = $this->getClass($info[0], $info[1]);$specialRoots[$x->getPackage()][$parent][] = $info[0];}}}foreach ($specialRoots as $package => $root) {uksort($specialRoots[$package], "strnatcasecmp");foreach ($specialRoots[$package] as $parent => $classes) {usort($specialRoots[$package][$parent], 'strnatcasecmp');}}return array('special' => $specialRoots, 'normal' => $roots);}return $roots;}/*** Get all classes confirmed in parsing* to be descended class $parclass in file $file** @param string $parclass name of parent class* @param string $file file parent class is found in** @return mixed either false if no children, or array of format* array(childname => childfile,childname2 => childfile2,...)* @see parserClass::getChildClassList()* @uses $definitechild*/function getDefiniteChildren($parclass, $file){if (isset($this->definitechild[$parclass][$file]))return $this->definitechild[$parclass][$file];return false;}}?>