diff options
author | ctrlaltca@gmail.com <> | 2011-11-19 11:33:31 +0000 |
---|---|---|
committer | ctrlaltca@gmail.com <> | 2011-11-19 11:33:31 +0000 |
commit | 98dbe6f0d2edfff3a1f5785504504b4a6e5dd4eb (patch) | |
tree | 89f19120abb170cb37bb512c8c9535eb2b451da8 /buildscripts/PhpDocumentor/phpDocumentor/Classes.inc | |
parent | 1f09b786730956d01c48a82272617a0f8b2597f0 (diff) |
updating phpDocumentor, part 2: add new version
Diffstat (limited to 'buildscripts/PhpDocumentor/phpDocumentor/Classes.inc')
-rwxr-xr-x | buildscripts/PhpDocumentor/phpDocumentor/Classes.inc | 1356 |
1 files changed, 1356 insertions, 0 deletions
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Classes.inc b/buildscripts/PhpDocumentor/phpDocumentor/Classes.inc new file mode 100755 index 00000000..6de944a5 --- /dev/null +++ b/buildscripts/PhpDocumentor/phpDocumentor/Classes.inc @@ -0,0 +1,1356 @@ +<?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 package + if (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 array + if (isset($this->roots[$class])) { + foreach ($this->roots[$class] as $i => $files) { + // find the file key and unset + if ($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 591396 + if (!$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 trees + if ($x->docblock->package != $db->docblock->package) { + // debug("adding $child in $childfile 1"); + $this->roots[$child][] = $childfile; + } + } + } + } else { + // test 2, different file, same package + foreach ($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 parent + if (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 trees + if ($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 name + if (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 file + if (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 way + if (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 conflict + addWarning(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; + } +} +?> |