Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Move PHPDoc to pear/.

git-svn-id: http://svn.php.net/repository/pear/packages/PHPDoc/trunk@46850 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information...
commit 0ba4ceece8ffb89bf90c31497ea21fcc532a732b 1 parent a86617a
Sebastian Bergmann authored
Showing with 12,274 additions and 0 deletions.
  1. +22 −0 README
  2. +79 −0 accessor/PhpdocAccessor.php
  3. +246 −0 accessor/PhpdocClassAccessor.php
  4. +252 −0 accessor/PhpdocDocumentAccessor.php
  5. +360 −0 accessor/PhpdocIndexAccessor.php
  6. +38 −0 accessor/PhpdocModuleAccessor.php
  7. +93 −0 accessor/PhpdocWarningAccessor.php
  8. +361 −0 analyser/PhpdocAnalyser.php
  9. +553 −0 analyser/PhpdocClassAnalyser.php
  10. +370 −0 analyser/PhpdocModuleAnalyser.php
  11. +14 −0 apidoc/keep/empty.html
  12. +22 −0 apidoc/keep/index2.html
  13. +89 −0 apidoc/keep/phpdoc.css
  14. +146 −0 apidoc/keep/phpdoc.dtd
  15. +240 −0 core/Phpdoc.php
  16. +161 −0 core/PhpdocArgvHandler.php
  17. +189 −0 core/PhpdocObject.php
  18. +217 −0 core/PhpdocSetupHandler.php
  19. +134 −0 exceptions/PhpdocError.php
  20. +208 −0 filehandler/PhpdocFileHandler.php
  21. +101 −0 index.php
  22. +196 −0 indexer/PhpdocIndexer.php
  23. +128 −0 parser/PhpdocClassParser.php
  24. +109 −0 parser/PhpdocConstantParser.php
  25. +138 −0 parser/PhpdocFunctionParser.php
  26. +142 −0 parser/PhpdocModuleParser.php
  27. +450 −0 parser/PhpdocParser.php
  28. +662 −0 parser/PhpdocParserCore.php
  29. +492 −0 parser/PhpdocParserRegExp.php
  30. +736 −0 parser/PhpdocParserTags.php
  31. +78 −0 parser/PhpdocUseParser.php
  32. +129 −0 parser/PhpdocVariableParser.php
  33. +71 −0 prepend.php
  34. +22 −0 renderer/PhpdocRendererObject.php
  35. +389 −0 renderer/html/PhpdocHTMLClassRenderer.php
  36. +744 −0 renderer/html/PhpdocHTMLDocumentRenderer.php
  37. +459 −0 renderer/html/PhpdocHTMLIndexRenderer.php
  38. +95 −0 renderer/html/PhpdocHTMLModuleRenderer.php
  39. +80 −0 renderer/html/PhpdocHTMLRenderer.php
  40. +100 −0 renderer/html/PhpdocHTMLRendererManager.php
  41. +90 −0 renderer/html/PhpdocHTMLWarningRenderer.php
  42. +598 −0 renderer/html/templates/class.html
  43. +64 −0 renderer/html/templates/classtree.html
  44. +65 −0 renderer/html/templates/elementlist.html
  45. +47 −0 renderer/html/templates/frame_packageelementlist.html
  46. +23 −0 renderer/html/templates/frame_packagelist.html
  47. +445 −0 renderer/html/templates/module.html
  48. +64 −0 renderer/html/templates/modulegroup.html
  49. +106 −0 renderer/html/templates/packagelist.html
  50. +85 −0 renderer/html/templates/warnings.html
  51. +63 −0 renderer/html/templates/xmlfiles.html
  52. +69 −0 warning/PhpdocWarning.php
  53. +183 −0 xmlexporter/PhpdocXMLClassExporter.php
  54. +420 −0 xmlexporter/PhpdocXMLDocumentExporter.php
  55. +145 −0 xmlexporter/PhpdocXMLExporter.php
  56. +192 −0 xmlexporter/PhpdocXMLIndexExporter.php
  57. +51 −0 xmlexporter/PhpdocXMLModuleExporter.php
  58. +50 −0 xmlexporter/PhpdocXMLWarningExporter.php
  59. +225 −0 xmlreader/PhpdocXMLReader.php
  60. +174 −0 xmlwriter/PhpdocXMLWriter.php
View
22 README
@@ -0,0 +1,22 @@
+Welcome to PHPDoc!
+
+PHPDoc is an attemt to adopt Javadoc to the PHP world. This version
+is the first public beta version. I started coding a few monts ago but
+was not really satisfied with the code so it took some time up to this day.
+
+As said this is beta stuff. It's not perfect at all. Here's some known bugs:
+
+- needs PHP4.03dev+
+- variable warnings are thrown before information inheritance takes place
+- @todo and @exclude do not work
+
+This will change soon.
+
+PHPDoc is distributed under LGPL. That means you can use it even in
+commercial projects.
+
+Documentation will follow after the german php congress and after the weekend.
+
+Have fun with it!
+
+Ulf , ulf.wendel@phpdoc.de
View
79 accessor/PhpdocAccessor.php
@@ -0,0 +1,79 @@
+<?php
+/**
+* Provides an API to access PHPDoc XML files.
+*
+* It's up to you eigther to use this class to access
+* the phpdoc xml files or to write your own parser.
+*
+* @version $Id$
+*/
+class PhpdocAccessor extends PhpdocObject {
+
+ /**
+ * Instance of PhpdocXMLReader
+ * @var object PhpdocXMLReader $xmlreader
+ */
+ var $xmlreader;
+
+ /**
+ * Result of the PhpdocXMLReader
+ * @var array $xml
+ */
+ var $xml = array();
+
+ /**
+ * Free xml resources on calling a getXY() function?
+ *
+ * One of the design goals was to minimize the memory consumption of PHPdoc.
+ * So PHPdoc tries to save data as soon as possible to the disk, reuse objects
+ * and free resources of an object when they are no longer needed. The default
+ * value of true will cause the object to free the memory used by the
+ * xml data as soon as possible.
+ *
+ * @var boolean
+ */
+ var $freeOnGet = true;
+
+ /**
+ * Reformatted PhpdocXMLReader result array
+ * @var array
+ */
+ var $data = array();
+
+ /**
+ * Loads the specified xml file.
+ *
+ * @param string Name of the xml file
+ * @return boolean False if the given xml file was not
+ * found or is empty otherwise true.
+ * @access public
+ * @see init()
+ */
+ function loadXMLFile($filename) {
+
+ $this->xmlreader = new PhpdocXMLReader;
+
+ $this->xml = $this->xmlreader->parse($filename);
+ $this->xml = $this->xml["phpdoc"];
+ $ok = (!is_array($this->xml) || 0 == count($this->xml)) ? false : true;
+
+ $this->init();
+
+ return $ok;
+ } // end func loadXMLFile
+
+ /**
+ * Reformats the xml result array from the PhpdocXMLReader.
+ *
+ * Every derived class must override this function to call the functions
+ * it needs to reorganize the data from the PhpdocXMLReader in a
+ * way that it needs.
+ *
+ * @abstract
+ * @see $xml, $data
+ */
+ function init() {
+ } // end func init
+
+} // end class PhpdocAccessor
+?>
View
246 accessor/PhpdocClassAccessor.php
@@ -0,0 +1,246 @@
+<?php
+/**
+* Provides functions to access phpdoc xml documents that contain classes.
+*
+* @author Ulf Wendel <ulf.wendel@phpdoc.de>
+* @version $Id$
+*/
+class PhpdocClassAccessor extends PhpdocDocumentAccessor {
+
+ /**
+ * TODO: add documentation
+ */
+ var $xmlkey = "class";
+
+ /**
+ * Array of inherited elements
+ *
+ * @var array $inherited
+ */
+ var $inherited = array();
+
+ /**
+ * Returns an array with the data of a class (no functions etc, just the class docs).
+ *
+ * @return array $class
+ * @access public
+ */
+ function getClassdata() {
+
+ $class = $this->xml["class"];
+
+ unset($class["variable"]);
+ unset($class["function"]);
+ unset($class["uses"]);
+ unset($class["constant"]);
+ unset($class["inherited"]);
+ unset($class["overriden"]);
+ unset($class["path"]);
+
+ return $class;
+ } // end func getClassdata
+
+ /**
+ * Returns an array of inherited functions.
+ *
+ * @return array
+ * @access public
+ * @see getInheritedVariables(), getInheritedUses(), getInheritedConstants()
+ */
+ function getInheritedFunctions() {
+ return $this->inherited["functions"];
+ } // end func getInheritedFunctions
+
+ /**
+ * Returns an array of inherited variables.
+ *
+ * @return array
+ * @access public
+ * @see getInheritedFunctions(), getInheritedUses(), getInheritedConstants()
+ */
+ function getInheritedVariables() {
+ return $this->inherited["variables"];
+ } // end func getInheritedVariables
+
+ /**
+ * Returns an array of inherited included files.
+ *
+ * @return array
+ * @access public
+ * @see getInheritedFunctions(), getInheritedUses(), getInheritedConstants()
+ */
+ function getInheritedUses() {
+ return $this->inherited["uses"];
+ } // end func getInheritedUses()
+
+ /**
+ * Returns an array of inherited constants.
+ *
+ * @return array
+ * @access public
+ * @see getInheritedFunctions(), getInheritedVariables(), getInheritedUses()
+ */
+ function getInheritedConstants() {
+ return $this->inherited["constants"];
+ } // end func getInheritedConstants
+
+ /**
+ * Returns an array with the "path" of a class.
+ *
+ * @return array $path
+ * @access public
+ * @see getSubclasses()
+ */
+ function getClasstree() {
+
+ if (isset($this->xml["class"]["path"]))
+ return $this->convertPath($this->xml["class"]["path"]);
+ else
+ return array();
+
+ } // end func getClasstree
+
+ /**
+ * Returns an array with all subclasses of a class.
+ *
+ * @return array
+ * @access public
+ * @see getClasstree()
+ */
+ function getSubclasses() {
+ return $this->data["subclasses"];
+ } // end func getSubclasses
+
+
+ /**
+ * Converts a xml path array to a path that can be passed to the user.
+ *
+ * The path is an array like path[0..n] = classname where path[0] is the
+ * directs parent (extends path[0]) and path[n] is the baseclass.
+ *
+ * @param array $xmlpath
+ * @return array $path
+ */
+ function convertPath($xmlpath) {
+
+ $path = array();
+
+ if (!isset($xmlpath["parent"][0])) {
+
+ $path[0] = $xmlpath["parent"]["value"];
+
+ } else {
+
+ reset($xmlpath["parent"]);
+ while (list($k, $parent) = each($xmlpath["parent"]))
+ $path[] = $parent["value"];
+
+ }
+
+ return $path;
+ } // end func convertPath
+
+ /**
+ * Builds a list of inherited elements.
+ *
+ * @see $inherited
+ */
+ function buildInheritedlist() {
+
+ $this->inherited = array(
+ "functions" => array(),
+ "variables" => array(),
+ "constants" => array(),
+ "uses" => array()
+ );
+
+ if (isset($this->xml["class"]["inherited"])) {
+
+ if (isset($this->xml["class"]["inherited"][0])) {
+
+ reset($this->xml["class"]["inherited"]);
+ while (list($k, $inherited) = each($this->xml["class"]["inherited"])) {
+
+ $type = $inherited["type"];
+ $src = $inherited["src"];
+
+ if (isset($inherited["element"][0])) {
+
+ reset($inherited["element"]);
+ while (list($k2, $element) = each($inherited["element"]))
+ $this->inherited[$type][$src][] = $element["value"];
+
+ } else {
+
+ $this->inherited[$type][$src][] = $inherited["element"]["value"];
+
+ }
+
+ }
+
+ } else {
+
+ $inherited = $this->xml["class"]["inherited"];
+ $type = $inherited["type"];
+ $src = $inherited["src"];
+
+ if (isset($inherited["element"][0])) {
+
+ reset($inherited["element"]);
+ while (list($k, $element) = each($inherited["element"]))
+ $this->inherited[$type][$src][] = $element["value"];
+
+ } else {
+
+ $this->inherited[$type][$src][] = $inherited["element"]["value"];
+
+ }
+
+ }
+
+ unset($this->xml["class"]["inherited"]);
+
+ }
+
+ } // end func buildInheritedlist
+
+ /**
+ * Builds a list of subclasses
+ */
+ function buildSubclasslist() {
+
+ $this->data["subclasses"] = array();
+
+ if (isset($this->xml["class"]["subclasses"])) {
+
+ if (isset($this->xml["class"]["subclasses"]["subclass"][0])) {
+
+ reset($this->xml["class"]["subclasses"]["subclass"]);
+ while (list($k, $subclass) = each($this->xml["class"]["subclasses"]["subclass"]))
+ $this->data["subclasses"][] = $subclass["value"];
+
+ } else {
+
+ $this->data["subclasses"][] = $this->xml["class"]["subclasses"]["subclass"]["value"];
+
+ }
+
+ }
+
+ } // end func buildSubclasslist
+
+ function init() {
+
+ $this->buildInheritedlist();
+ $this->buildSubclasslist();
+
+ list($this->data["functions"], $this->data["functionsaccess"]) = $this->getElementlist("function");
+ list($this->data["variables"], $this->data["variablesaccess"]) = $this->getElementlist("variable");
+ list($this->data["constants"], $this->data["constantsaccess"]) = $this->getElementlist("constant");
+
+ $this->buildUseslist();
+
+ } // end func Init
+
+} // end class PhpdocClassAccessor
+?>
View
252 accessor/PhpdocDocumentAccessor.php
@@ -0,0 +1,252 @@
+<?php
+/**
+* Base of the class and module accessor.
+*
+* @version $Id$
+*/
+class PhpdocDocumentAccessor extends PhpdocAccessor {
+
+ /**
+ * Kind of top-level container in the xml document.
+ *
+ * Must be set by all derived classes.
+ *
+ * @var string
+ */
+ var $xmlkey = "";
+
+ /**
+ * Returns an array with all functions.
+ *
+ * @return array $functions
+ * @access public
+ * @see getFunctionsByAccess()
+ */
+ function getFunctions() {
+ return $this->getElements("functions", "functionsaccess");
+ } // end func getFunctions
+
+ /**
+ * Returns an array with all functions with a certain access (public, private) attribute.
+ *
+ * @param string Requested access attribute.
+ * @return array $functions
+ * @access public
+ * @see getFunctions()
+ */
+ function getFunctionsByAccess($access) {
+ return $this->getElementsByAccess($access, "functions", "functionsaccess");
+ } // end func getFunctionByAccess
+
+ /**
+ * Returns an array with all variables.
+ *
+ * @return array $variables
+ * @access public
+ * @see getVariablesByAccess()
+ */
+ function getVariables() {
+ return $this->getElements("variables", "variablesaccess");
+ } // end func getVariables
+
+ /**
+ * Returns an array with all variables with a certain access (public, private) attribute.
+ *
+ * @param string Requested access attribute.
+ * @return array $variables
+ * @access public
+ * @see getVariables()
+ */
+ function getVariablesByAccess($access) {
+ return $this->getElementsByAccess($access, "variables", "variablesaccess");
+ } // end func getVariablesByAccess
+
+ /**
+ * Returns an array of all constants.
+ *
+ * @return array $constants
+ * @access public
+ * @see getConstantsByAccess()
+ */
+ function getConstants() {
+ return $this->getElements("constants", "constantsaccess");
+ } // end func getConstants
+
+ /**
+ * Returns an array of all constants with a certain access (public, private) attribute.
+ *
+ * @param string Requested access attribute.
+ * @return array $constants
+ * @see getConstants()
+ * @access public
+ */
+ function getConstantsByAccess($access) {
+ return $this->getElementsByAccess($access, "constants", "constantsaccess");
+ } // end func getConstantsByAccess
+
+ /**
+ * Returns an array of all included files.
+ *
+ * @return array $uses
+ * @see getUsesByType()
+ * @access public
+ */
+ function getUses() {
+ return $this->getElements("uses", "usestype");
+ } // end func getUses
+
+ /**
+ * Returns an array of all included files with a certain type (include, require...) attribute.
+ *
+ * @param string Requested type: include, include_once, require, require_once
+ * @return array $uses
+ * @access public
+ */
+ function getUsesByType($type) {
+
+ $data = array();
+
+ if (!isset($this->data["usestype"][$type]))
+ return $data;
+
+ reset($this->data["usestype"][$type]);
+ while (list($k, $file) = each($this->data["usestype"][$type])) {
+
+ $data[$file] = $this->data["uses"][$file];
+ if ($this->freeOnGet)
+ unset($this->data["uses"][$file]);
+
+ }
+
+ if ($this->freeOnGet)
+ unset($this->data["usestype"][$type]);
+
+ return $data;
+ } // end func getUsesByType
+
+ /**
+ * Returns elements from the internal $data array.
+ *
+ * The object uses this function to extract functions, variables, uses and
+ * constants from an internal array. Note that this is not a public function,
+ * future version might access internal data structures different.
+ *
+ * @param string Name of the element you need: functions, variables,...
+ * @param string Name of internal element access table
+ * @see $data
+ */
+ function getElements($element, $elementaccess) {
+
+ if ($this->freeOnGet) {
+
+ $data = $this->data[$element];
+ unset($this->data[$element]);
+ unset($this->data[$elementaccess]);
+ return $data;
+
+ } else {
+
+ $this->data[$element];
+
+ }
+
+ } // end func getElements
+
+ /**
+ * Returns elements with a certain access type from the internal data.
+ *
+ * @param string Accesstype
+ * @param string element name
+ * @param string access type
+ * @brother getElements()
+ */
+ function getElementsByAccess($access, $element, $elementaccess) {
+
+ $data = array();
+
+ if (!isset($this->data[$elementaccess][$access]))
+ return $data;
+
+ reset($this->data[$elementaccess][$access]);
+ while (list($k, $name) = each($this->data[$elementaccess][$access])) {
+
+ $data[$name] = $this->data[$element][$name];
+ if ($this->freeOnGet)
+ unset($this->data[$element][$name]);
+
+ }
+
+ if ($this->freeOnGet)
+ unset($this->data[$elementaccess][$access]);
+
+ return $data;
+ } // end func getElementsByAccess
+
+ /**
+ * Adds a list of included files to the internal data array.
+ */
+ function buildUseslist() {
+
+ $this->data["uses"] = array();
+ $this->data["usestype"] = array();
+
+ if (isset($this->xml[$this->xmlkey]["uses"])) {
+
+ if (isset($this->xml[$this->xmlkey]["uses"][0])) {
+
+ reset($this->xml[$this->xmlkey]["uses"]);
+ while (list($k, $data) = each($this->xml[$this->xmlkey]["uses"])) {
+ $this->data["uses"][$data["file"]] = $data;
+ $this->data["usestype"][$data["type"]][] = $data["file"];
+ }
+
+ } else {
+
+ $data = $this->xml[$this->xmlkey]["uses"];
+ $this->data["uses"][$data["file"]] = $data;
+ $this->data["usestype"][$data["type"]][] = $data["file"];
+
+ }
+
+ unset($this->xml[$this->xmlkey]["uses"]);
+ }
+
+ } // end func buildUseslist
+
+ /**
+ * Adds a list of a certain element to the internal data array.
+ *
+ * @param string name of the element to add: function, variable, constant.
+ */
+ function getElementlist($element) {
+
+ $elements = array();
+ $elementaccess = array();
+
+ if (isset($this->xml[$this->xmlkey][$element])) {
+
+ if (isset($this->xml[$this->xmlkey][$element][0])) {
+
+ reset($this->xml[$this->xmlkey][$element]);
+ while (list($k, $data) = each($this->xml[$this->xmlkey][$element])) {
+ $elements[$data["name"]] = $data;
+ $elementaccess[$data["access"]][] = $data["name"];
+ }
+
+ } else {
+
+ $data = $this->xml[$this->xmlkey][$element];
+ $elements[$data["name"]] = $data;
+ $elementaccess[$data["access"]][] = $data["name"];
+
+ }
+
+ unset($this->xml[$this->xmlkey][$element]);
+
+ }
+
+ return array($elements, $elementaccess);
+ } // end func getElementlist
+
+} // end class PhpdocDocumentAccessor
+?>
View
360 accessor/PhpdocIndexAccessor.php
@@ -0,0 +1,360 @@
+<?php
+/**
+* Provides a API to access Index xml documents.
+*/
+class PhpdocIndexAccessor extends PhpdocAccessor {
+
+ /**
+ * Ordered list of all chapternames.
+ *
+ * @var array
+ */
+ var $chapternames = array();
+
+ /**
+ * Ordered list of all chapters.
+ *
+ * @var array
+ */
+ var $chapters = array();
+
+ /**
+ * List of all packages.
+ *
+ * @var array
+ */
+ var $packages = array();
+
+ /**
+ * Data of a classtree
+ *
+ * @var array
+ */
+ var $classtree = array();
+
+ /**
+ * Data of a modulegroup
+ *
+ * @var array
+ */
+ var $modulegroup = array();
+
+ /**
+ * Some container withing the packagelist.
+ *
+ * @var array
+ * @see buildPackagelist()
+ */
+ var $packageFields = array("class", "module");
+
+ /**
+ * Flag indicating that certain internal datafield have been filled.
+ *
+ * @var array
+ */
+ var $flagBuild = array(
+ "chapter" => false,
+ "package" => false
+ );
+
+
+ /**
+ * Returns a modulegroup
+ *
+ * @access public
+ */
+ function getModulegroup() {
+
+ $this->buildModulegroup();
+
+ if ($this->freeOnGet) {
+
+ $data = $this->modulegroup;
+ $this->modulegroup = array();
+ return $data;
+
+ } else {
+
+ return $this->modulegroup;
+ }
+
+ } // end func getModulegroup
+
+ /**
+ * Returns a classtree.
+ *
+ * @return array
+ * @access public
+ */
+ function getClasstree() {
+
+ $this->buildClasstree();
+
+ if ($this->freeOnGet) {
+
+ $data = $this->classtree;
+ $this->classtree = array();
+ return $data;
+
+ } else {
+
+ return $this->classtree;
+
+ }
+
+ } // end func getClasstree
+
+ /**
+ * Returns an ordered list of all chapternames.
+ *
+ * @return array
+ * @access public
+ * @see getChapters()
+ */
+ function getChapternames() {
+
+ $this->buildChapterlist();
+
+ if ($this->freeOnGet) {
+
+ $data = $this->chapternames;
+ $this->chapternames = array();
+ return $data;
+
+ } else {
+
+ return $this->chapternames;
+
+ }
+
+ } // end func getChapternames
+
+ /**
+ * Returns an ordered list of all chapters.
+ *
+ * @return array
+ * @access public
+ * @see getChapternames()
+ */
+ function getChapters() {
+
+ $this->buildChapterlist();
+
+ if ($this->freeOnGet) {
+
+ $data = $this->chapters;
+ $this->chapters = array();
+ return $data;
+
+ } else {
+
+ return $this->chapters;
+
+ }
+
+ } // end func getChapters
+
+ /**
+ * Returns a list of all packages
+ *
+ * @return array
+ * @access public
+ */
+ function getPackagelist() {
+
+ $this->buildPackagelist();
+
+ if ($this->freeOnGet) {
+
+ $data = $this->packages;
+ $this->packages = array();
+ return $data;
+
+ } else {
+
+ return $this->packages;
+
+ }
+
+ } // end func getPackagelist
+
+
+ /**
+ * Builds the internal packagelist.
+ */
+ function buildPackagelist() {
+
+ if ($this->flagBuild["package"])
+ return;
+
+ $data = $this->xml["packagelist"];
+ $this->xml = array();
+ $this->flagBuild["package"] = true;
+
+ $this->packages = array();
+
+ if (!isset($data["package"][0]))
+ $data["package"] = array($data["package"]);
+
+ reset($data["package"]);
+ while (list($k, $package) = each($data["package"])) {
+
+ $packagename = $package["name"];
+
+ reset($this->packageFields);
+ while (list($k, $field) = each($this->packageFields)) {
+
+ if (isset($package[$field][0])) {
+
+ reset($package[$field]);
+ while (list($k, $element)=each($package[$field]))
+ $this->packages[$packagename][$field][] = $element["name"];
+
+ } else if (isset($package[$field])) {
+
+ $this->packages[$packagename][$field][] = $package[$field]["name"];
+
+ }
+ }
+
+ }
+
+ } // end func buildPackagelist
+
+ /**
+ * Builds the internal chapterlists.
+ */
+ function buildChapterlist() {
+
+ if ($this->flagBuild["chapter"])
+ return;
+
+ $data = $this->xml["index"];
+ $this->xml = array();
+ $this->flagBuild["chapter"] = true;
+
+ $this->chapternames = array();
+ $this->chapters = array();
+
+ if (isset($data["chapter"][0])) {
+
+ $chapterlist = array();
+ reset($data["chapter"]);
+ while (list($k, $chapter) = each($data["chapter"]))
+ $chapterlist[strtoupper($chapter["char"])][$chapter["char"]] = $k;
+
+ ksort($chapterlist, SORT_STRING);
+
+ reset($chapterlist);
+ while (list($k, $chapters) = each($chapterlist)) {
+
+ reset($chapters);
+ while (list($chapter, $index)=each($chapters)) {
+ $this->chapternames[] = $chapter;
+ $this->chapters[$chapter] = $data["chapter"][$index];
+ }
+
+ }
+
+ } else {
+
+ $this->chapternames[] = $data["chapter"]["char"];
+ $this->chapters[$data["chapter"]["char"]] = $data["chapter"]["char"];
+
+ }
+
+ } // end func buildChapterlist
+
+ /**
+ * Extracts the modulegroup data of the xml file.
+ *
+ * @see getModulegroup()
+ */
+ function buildModulegroup() {
+
+ if ($this->flagBuild["modulegroup"])
+ return;
+
+ $this->flagBuild["modulegroup"] = true;
+ $data = $this->xml["modulegroup"];
+
+ $this->xml = "";
+ $this->modulegroup = array(
+ "group" => $data["name"],
+ "modules" => array()
+ );
+
+ if (!isset($data["module"][0]))
+ $data["module"] = array( $data["module"] );
+
+ reset($data["module"]);
+ while (list($k, $module) = each($data["module"]))
+ $this->modulegroup["modules"][] = $module["name"];
+
+ } // end func buildModulegroup
+
+ /**
+ * Extracts the classtree data of the xml file.
+ *
+ * @see getClasstree()
+ */
+ function buildClasstree() {
+
+ if ($this->flagBuild["classtree"])
+ return;
+
+ $this->flagBuild["classtree"] = true;
+ $data = $this->xml["classtree"];
+ $this->xml = "";
+
+ $this->classtree = array(
+ "baseclass" => $data["baseclass"],
+ "classes" => array()
+ );
+
+ if (!isset($data["class"][0]))
+ $data["class"] = array( $data["class"] );
+
+ reset($data["class"]);
+ while (list($k, $class)=each($data["class"])) {
+
+ if (!isset($class["subclass"])) {
+
+ $this->classtree["classes"][$class["name"]] = array();
+
+ } else {
+
+ if (!isset($class["subclass"][0])) {
+
+ $this->classtree["classes"][$class["name"]][] = $class["subclass"]["value"];
+
+ } else {
+
+ reset($class["subclass"]);
+ while (list($k, $subclass)=each($class["subclass"]))
+ $this->classtree["classes"][$class["name"]][] = $subclass["value"];
+
+ }
+
+ }
+
+ }
+
+ } // end func buildClasstree
+
+ /**
+ * Resets the build flags.
+ *
+ * @see $flagBuild
+ */
+ function init() {
+
+ reset($this->flagBuild);
+ while (list($k, $v) = each($this->flagBuild))
+ $this->flagBuild[$k] = false;
+
+ } // end func init
+
+
+} // end class PhpdocIndexAccessor
+?>
View
38 accessor/PhpdocModuleAccessor.php
@@ -0,0 +1,38 @@
+<?php
+/**
+* Provides functions to access phpdoc xml documents that contain modules.
+*
+* @version $Id$
+*/
+class PhpdocModuleAccessor extends PhpdocDocumentAccessor {
+
+ var $xmlkey = "module";
+
+ /**
+ * Returns an array with the data of a module (no functions etc, just the module docs).
+ *
+ * @return array $class
+ * @access public
+ */
+ function getModuledata() {
+
+ $module = $this->xml["module"];
+
+ unset($module["function"]);
+ unset($module["uses"]);
+ unset($module["constant"]);
+
+ return $module;
+ } // end func getModuledata
+
+ function init() {
+
+ list($this->data["functions"], $this->data["functionsaccess"]) = $this->getElementlist("function");
+ list($this->data["variables"], $this->data["variablesaccess"]) = $this->getElementlist("variable");
+ list($this->data["constants"], $this->data["constantsaccess"]) = $this->getElementlist("constant");
+ $this->buildUseslist();
+
+ } // end func Init
+
+} // end class PhpdocModuleAccessor
+?>
View
93 accessor/PhpdocWarningAccessor.php
@@ -0,0 +1,93 @@
+<?php
+/**
+* Extracts the warnings from PHPDoc warnings_* files.
+*
+* @version $Id$
+*/
+class PhpdocWarningAccessor extends PhpdocAccessor {
+
+ /**
+ * If set to true all get_xy() functions will free their resources.
+ *
+ * @var boolean
+ * @access public
+ */
+ var $freeOnGet = true;
+
+ /**
+ * Array of warnings.
+ *
+ * @var array
+ */
+ var $warnings = array();
+
+ /**
+ * Flag used to detect if get_xy() was called.
+ *
+ * @var boolean
+ */
+ var $flag_build = false;
+
+ /**
+ * Returns a hash of warnings in of the given XML file.
+ *
+ * @param string XML file
+ * @return array
+ * @access public
+ * @see $freeOnGet
+ */
+ function getWarnings($xmlfile) {
+
+ $this->buildWarnings($xmlfile);
+
+ if ($this->freeOnGet) {
+
+ $data = $this->warnings;
+ $this->warnings = array();
+ return $data;
+
+ } else {
+
+ return $this->warnings;
+
+ }
+
+ } // end func getWarnings
+
+ /**
+ * Build the internal list of warnings.
+ *
+ * @param string XML file to load
+ */
+ function buildWarnings($xmlfile) {
+
+ if ($this->flag_build)
+ return;
+
+ $this->flag_build = true;
+ $this->warnings = array();
+ $this->loadXMLFile($xmlfile);
+
+ if(!isset($this->xml["warnings"][0]))
+ $this->xml["warnings"] = array( $this->xml["warnings"] );
+
+ reset($this->xml["warnings"]);
+ while (list($k, $warnings) = each($this->xml["warnings"])) {
+
+ $file = $warnings["file"];
+ if (!isset($warnings["warning"][0]))
+ $warnings["warning"] = array($warnings["warning"]);
+ $this->warnings[$file] = $warnings["warning"];
+
+ }
+
+ $this->xml = "";
+
+ } // end func buildWarnings
+
+ function init() {
+ $this->flag_build = false;
+ } // end func init
+
+} // end class PhpdocWarningAccess
+?>
View
361 analyser/PhpdocAnalyser.php
@@ -0,0 +1,361 @@
+<?php
+/**
+* Analyses parsing data.
+*
+* Analyse means:
+* - update brother/sister
+* - update access/return
+* - inherit elements
+* - inherit information
+*
+* @version $Id$
+*/
+class PhpdocAnalyser extends PhpdocObject {
+
+ /**
+ * Flag indicating that getModule/getClass was called.
+ *
+ * @var boolean
+ */
+ var $flag_get = false;
+
+ /**
+ * List of all elements of a certain class/module.
+ *
+ * The array is used to look up see references
+ *
+ * @var array Format: elementlist[ eltype ][ elname ] = true
+ * @see buildElementlist()
+ */
+ var $elementlist = array();
+
+ /**
+ * Adds a suffix to the number like 1st, 2nd and 3th
+ *
+ * @param integer $nr number to format
+ * @return string
+ * @author Thomas Weinert <subjective@subjective.de>
+ */
+ function addNumberSuffix($nr) {
+
+ $last_nr = substr($nr, -1, 1);
+
+ switch ($last_nr) {
+ case 1:
+ return ($nr . "st");
+ break;
+
+ case 2:
+ return ($nr . "nd");
+ break;
+
+ default:
+ return ($nr . "th");
+ }
+
+ } // end func addNumberSuffix
+
+ /**
+ * Starts the analysing of the raw parsing data.
+ *
+ * @access public
+ * @abstract
+ */
+ function analyse() {
+ ;
+ } // end func analyse
+
+ /**
+ * Handles brother and sister.
+ *
+ * @abstract
+ * @see updateBrotherSisterElements()
+ */
+ function updateBrothersSisters() {
+ ;
+ } // end func updateBrothersSisters
+
+ /**
+ * Updates certain elements that use brother and sister.
+ *
+ * @return boolean $ok
+ */
+ function updateBrotherSisterElements() {
+ return false;
+ } // end func updateBrotherSisterElements
+
+ /**
+ * Copies fields from a brother or sister to the current element.
+ *
+ * @param array Data of the target element that has a brother/sister tag
+ * @param array Data of the element that is referenced by brother/sister
+ */
+ function copyBrotherSisterFields($target, $from) {
+
+ reset($from);
+ while (list($k, $v) = each($from))
+ if (!isset($target[$k]) || "" == $target[$k])
+ $target[$k] = $v;
+
+ return $target;
+ } // end func copyBrotherSisterFields
+
+ /**
+ * Updates the access and return tag values.
+ *
+ * @see updateAccessReturnElements(), updateAccessElements()
+ * @abstract
+ */
+ function updateAccessReturn() {
+ ;
+ } // end func updateAccessReturn
+
+ /**
+ * Updates access and return for certain elements.
+ *
+ * This function should only be used to update functions.
+ * Functions that have the same name as the class (constructors)
+ * get return void and access public. Functions without
+ * access get access public and functions without return get return void.
+ *
+ * @return boolean $ok
+ * @see updateAccessReturn()
+ * @abstract
+ */
+ function updateAccessReturnElements() {
+ ;
+ } // end func updateAccessReturnElements
+
+ /**
+ * Updates access tags.
+ *
+ * @see updateAccessReturnElements()
+ * @abstract
+ */
+ function updateAccessElements() {
+ ;
+ } // end func updateAccessElements
+
+ /**
+ * Compares the param tags with the function head found.
+ *
+ * @abstract
+ */
+ function checkFunctionArgs() {
+ ;
+ } // end func checkFunctionArgs
+
+ /**
+ * Looks for undocumented elements and adds a warning if neccessary.
+ *
+ * @abstract
+ */
+ function findUndocumented() {
+ ;
+ } // end func findUndocumented
+
+ /**
+ * Checks all see references in the given classes/modulegroup.
+ *
+ * @abstract
+ */
+ function checkSee() {
+ ;
+ } // end func checkSee
+
+ /**
+ * Checks see references in the given elementlist.
+ *
+ * @abstract
+ */
+ function checkSeeElement() {
+ ;
+ } // end func checkSeeElement
+
+ /**
+ * Build a list of all elemente (functions, variables,...) of a certain class/module
+ *
+ * @abstract
+ * @see $elementlist
+ */
+ function buildElementlist() {
+ ;
+ } // end func buildElementlist
+
+ /**
+ * Compares the argument list generated from the function head with the param tags found.
+ *
+ * PHPDoc is able to recognize these documentation mistakes:
+ * - too few or too many param tags
+ * - name does not match or is missing
+ * - type does not match or is missing
+ * - trouble with inherited elements
+ *
+ * @param array Function arguments found by the parser
+ * @param array Paramarray
+ * @param string Functionname
+ * @param string Filename
+ * @param boolean Param tags inherited?
+ * @return array $params Param array
+ */
+ function checkArgDocs($args, $params, $elname, $elfile, $inherited = false) {
+
+ // "param" contains the information from the @param tags.
+ $num_args = count($args);
+ $num_params = count($params);
+
+ // no args? return...
+ if (0 == $num_args && 0 == $num_params)
+ return array();
+
+ // no args but @param used
+ if (0 == $num_args && $num_params > 0) {
+
+ if (!$inherited) {
+
+ $msg = "Function head shows no parameters, remove all @param tags.";
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+
+ } else {
+
+ if ("void" != $params[0]["type"]) {
+
+ $msg = "The function inherited some parameter documentation from it's parentclass but PHPDoc could not find
+ arguments in the function head. Add @param void to the doc comment to avoid confusion.";
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+
+ }
+
+ }
+
+ return array();
+
+ }
+
+ // compare the informations from the parser with the @param tags
+ reset($args);
+ while (list($k, $arg) = each($args)) {
+
+ if (isset($params[$k])) {
+
+ if ($arg["optional"])
+ $params[$k]["default"] = $arg["default"];
+
+ if (!$inherited) {
+
+ if ("" != $arg["type"] && "" != $params[$k]["type"] && "mixed" != $params[$k]["type"] && strtolower($arg["type"]) != strtolower($params[$k]["type"])) {
+
+ $type = $arg["type"];
+ $msg = sprintf("%s parameter type '%s' does match the the documented type '%s', possible error consider an update to '@param %s %s %s' or '@param %s %s', the variable name is optional.",
+ $this->addNumberSuffix($k + 1),
+ $arg["name"],
+ $params[$k]["type"],
+ $type,
+ $arg["name"],
+ (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)",
+ $type,
+ (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)"
+ );
+
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+
+ } else if ("" != $params[$k]["type"]) {
+
+ $type = $params[$k]["type"];
+
+ } else {
+
+ $msg = sprintf('Type missing for the %s parameter, "mixed" assumed.', $this->addNumberSuffix($k));
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "missing");
+ $type = "mixed";
+
+ }
+
+ $params[$k]["type"] = $type;
+
+ } else {
+
+ if ("" != $params[$k]["type"] && strtolower($arg["type"]) != strtolower($params[$k]["type"])) {
+
+ $type = (""!=$args["type"]) ? $arg["type"] : $params[$k]["type"];
+ $msg = sprintf("Possible documentation error due to inherited information.
+ The type of the %s parameter '%s' does not match the documented type '%s'.
+ Override the inherited documentation if neccessary.",
+ $this->addNumberSuffix($k),
+ $arg["type"],
+ $params[$k]["type"]
+ );
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+
+ } else if ("" != $params[$k]["type"]) {
+
+ $type = $params[$k]["type"];
+
+ } else {
+
+ $type = "mixed";
+ $msg = sprintf('Type missing for the %d parameter, "mixed" assumed. Override the inherited documentation if neccessary.', $k);
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+
+ }
+
+ $params[$k]["type"] = $type;
+
+ }
+
+ if ("" != $params[$k]["name"] && $arg["name"] != $params[$k]["name"]) {
+
+ $msg = sprintf("%s parameter '%s' does not match the documented name '%s', update the tag to '@param %s %s %s' or '@param %s %s', the variable name is optional.",
+ $this->addNumberSuffix($k+1),
+ $arg["name"],
+ $params[$k]["name"],
+ $type,
+ $arg["name"],
+ (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)",
+ $type,
+ (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)"
+ );
+
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+ $params[$k]["name"] = $arg["name"];
+
+ } else if ("" == $params[$k]["name"]) {
+
+ $params[$k]["name"] = $arg["name"];
+
+ }
+
+ } else {
+
+ $msg = sprintf("%s parameter '%s' is not documented add '@param %s [description]' to the end of the @param[eter] list.",
+ $this->addNumberSuffix($k+1),
+ $arg["name"],
+ ("" == $arg["type"]) ? "(object objectname|type)" : $arg["type"]
+ );
+
+ $params[$k]["name"] = $arg["name"];
+ $params[$k]["undoc"] = true;
+
+ if ("" != $arg["type"])
+ $params[$k]["type"] = $arg["type"];
+
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "missing");
+ }
+
+ }
+
+ // more @params specified than variables where found in the function head, delete them
+ if ($num_params > $num_args) {
+
+ $msg = "The parser found '$num_args' parameter but '$num_params' @param[eter] tags. You should update the @param[eter] list.";
+ $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
+ for ($i = $k + 1; $i < $num_params; ++$i)
+ unset($params[$i]);
+
+ }
+
+ return $params;
+ } // end func checkArgDocs
+
+} // end func PhpdocAnalyser
+?>
View
553 analyser/PhpdocClassAnalyser.php
@@ -0,0 +1,553 @@
+<?php
+/**
+* Analyses a class.
+*
+* @version $Id$
+*/
+class PhpdocClassAnalyser extends PhpdocAnalyser {
+
+ /**
+ * Class data.
+ *
+ * @var array
+ */
+ var $classes = array();
+
+ /**
+ * Name of the baseclass of the given classes.
+ *
+ * @var string
+ */
+ var $baseclass = "";
+
+ /**
+ * Ordered list of all classes.
+ *
+ * @var array
+ */
+ var $classlist = array();
+
+ /**
+ * List of not inherited elements.
+ *
+ * @var array
+ */
+ var $notinherited = array(
+ "class" => array(
+ "name" => true,
+ "extends" => true,
+ "undoc" => true,
+ "variables" => true,
+ "functions" => true,
+ "consts" => true,
+ "uses" => true,
+ "filename" => true,
+ "subclasses" => true,
+ "path" => true,
+ "baseclass" => true,
+ "abstract" => true
+ ),
+
+ "functions" => array(
+ "name" => true,
+ "undoc" => true,
+ "inherited" => true,
+ "overrides" => true,
+ "abstract" => true
+ ),
+
+ "variables" => array(
+ "name" => true,
+ "undoc" => true,
+ "inherited" => true,
+ "overrides" => true,
+ "abstract" => true
+ ),
+
+ "uses" => array(
+ "name" => true,
+ "undoc" => true,
+ "inherited" => true,
+ "overrides" => true
+ ),
+
+ "consts" => array(
+ "name" => true,
+ "undoc" => true,
+ "inherited" => true,
+ "overrides" => true
+ )
+ );
+
+
+ /**
+ * Puuuh - findUndocumented() needs this.
+ *
+ * @var array
+ * @see findUndocumented()
+ */
+ var $undocumentedFields = array(
+ "functions" => "function",
+ "variables" => "variable",
+ "uses" => "included file",
+ "consts" => "constant"
+ );
+
+ /**
+ * Sets the class data and the name of the baseclass.
+ *
+ * @param array Raw class data from the parser
+ * @param string Name of the baseclass of the given classes
+ * @access public
+ */
+ function setClasses($classes, $baseclass) {
+
+ $this->classes = $classes;
+ $this->baseclass = $baseclass;
+
+ } // end func setClasses
+
+ function analyse() {
+
+ $this->flag_get = false;
+
+ $this->updateAccessReturn();
+ $this->updateBrothersSisters();
+ $this->checkSee();
+
+ $this->classlist = array();
+
+ $this->buildBottomUpClasslist($this->baseclass);
+
+ } // end func analyse
+
+ /**
+ * Returns an analysed class or false if there're no classes any more.
+ *
+ * @return mixed False if there no classes anymore, otherwise an array with
+ * the data of the class.
+ * @accesss public
+ */
+ function getClass() {
+
+ if (!$this->flag_get) {
+ reset($this->classlist);
+ $this->flag_get = true;
+ }
+ if (list($k, $classname) = each($this->classlist)) {
+
+ if (isset($this->classes[$classname]["path"]))
+ $this->inheritClassElements($classname);
+
+ $this->checkFunctionArgs($classname);
+ $this->findUndocumented($classname);
+
+ $class = $this->classes[$classname];
+ unset($this->classes[$classname]);
+ return $class;
+
+ } else {
+
+ return false;
+
+ }
+ } // end func getClass
+
+ /**
+ * Looks for undocumented elements in a certain class
+ *
+ * @param string Classname
+ */
+ function findUndocumented($classname) {
+
+ $file = $this->classes["filename"];
+ if ($this->classes["undoc"])
+ $this->warn->addDocWarning($file, "class", $name, "The class is not documented.", "missing");
+
+ reset($this->undocumentedFields);
+ while (list($index, $eltype) = each($this->undocumentedFields)) {
+ if (!isset($this->classes[$index]))
+ continue;
+
+ reset($this->classes[$index]);
+ while (list($elname, $data) = each($this->classes[$index]))
+ if (isset($data["undoc"]) && $data["undoc"])
+ $this->warn->addDocWarning($file, $eltype, $elname, "Undocumented element.", "missing");
+
+ }
+
+ } // end func findUndocumented
+
+ /**
+ * Checks the function documentation of a certain class.
+ *
+ * @param string Classname
+ */
+ function checkFunctionArgs($classname) {
+
+ if (!isset($this->classes[$classname]["functions"]))
+ return;
+
+ $file = $this->classes[$classname]["filename"];
+
+ reset($this->classes[$classname]["functions"]);
+ while (list($fname, $function) = each($this->classes[$classname]["functions"])) {
+
+ $inherited = isset($function["paraminherited"]);
+ $this->classes[$classname]["functions"][$fname]["params"] = $this->checkArgDocs($function["args"], $function["params"], $fname, $file, $inherited);
+ unset($this->classes[$classname]["functions"][$fname]["args"]);
+
+ if ($inherited)
+ unset($this->classes[$classname]["functions"][$fname]["paraminherited"]);
+
+ }
+ } // end func checkFunctionArgs
+
+ /**
+ * Builds an internal list of all classes.
+ *
+ * The analyser needs an ordered list of all classes
+ * to inherit information effective.
+ *
+ * @param string Name of the class that starts the recursive build process.
+ * @see $classlist
+ */
+ function buildBottomUpClasslist($classname) {
+
+ if (isset($this->classes[$classname]["subclasses"])) {
+
+ reset($this->classes[$classname]["subclasses"]);
+ while (list($subclass, $v) = each($this->classes[$classname]["subclasses"]))
+ $this->buildBottomUpClasslist($subclass);
+
+ $this->classlist[] = $classname;
+
+ } else {
+
+ $this->classlist[] = $classname;
+
+ }
+ } // end func buildBottomUpClasslist
+
+ /**
+ * Adds inherited elements to a class.
+ *
+ * @param string Classname
+ * @return boolean $ok
+ * @see $classes, $notinherited, addInheritedElements()
+ */
+ function inheritClassElements($classname) {
+
+ if (!isset($this->classes[$classname]["path"]))
+ return false;
+
+ $undoc = $this->classes[$classname]["undoc"];
+
+ $path = $this->classes[$classname]["path"];
+ reset($path);
+ while (list($k, $parentclass) = each($path)) {
+
+ $this->addInheritedElements($classname, $parentclass, "functions");
+ $this->addInheritedElements($classname, $parentclass, "variables");
+ $this->addInheritedElements($classname, $parentclass, "consts");
+ $this->addInheritedElements($classname, $parentclass, "uses");
+
+ reset($this->classes[$parentclass]);
+ while (list($field, $value) = each($this->classes[$parentclass]))
+ if (!isset($this->notinherited["class"][$field]) && !isset($this->classes[$classname][$field]))
+ $this->classes[$classname][$field] = $value;
+
+ if ($undoc && !$this->classes[$parentclass]["undoc"]) {
+ $this->classes[$classname]["docinherited"] = true;
+ $this->classes[$classname]["undoc"] = false;
+ $undoc = false;
+ }
+
+ }
+
+ return true;
+ } // end func inheritClassElements
+
+ /**
+ * Adds inherited functions, variables, constants or included files to a class.
+ *
+ * @param string Name of the class that inherits the informations.
+ * @param string Name of the parentclass
+ * @param string Type of elements inherited: "functions", "variables", "uses", "consts"
+ * @return boolean $ok
+ * @see $classes, $notinherited, isUndocumented()
+ */
+ function addInheritedElements($classname, $parentclass, $type) {
+
+ if (!isset($this->classes[$parentclass][$type]))
+ return false;
+
+ reset($this->classes[$parentclass][$type]);
+ while (list($elementname, $data) = each($this->classes[$parentclass][$type])) {
+
+ if (!isset($this->classes[$classname][$type][$elementname])) {
+
+ $this->classes[$classname]["inherited"][$type][$parentclass][$elementname] = true;
+
+ } else {
+
+ $this->classes[$classname][$type][$elementname]["overrides"] = $parentclass;
+ $this->classes[$classname][$type][$elementname]["undoc"] = $this->isUndocumented($parentclass, $type, $elementname);
+ $this->classes[$classname]["overrides"][$type][$parentclass][$elementname] = true;
+
+ reset($data);
+ while (list($field, $value)=each($data)) {
+
+ if (!isset($this->classes[$classname][$type][$elementname][$field]) && !isset($this->notinherited[$type][$field])) {
+ $this->classes[$classname][$type][$elementname][$field] = $value;
+ if ("params" == $field && "functions" == $type) $this->classes[$classname][$type][$elementname]["paraminherited"] = true;
+ }
+
+ }
+ }
+
+ }
+
+ return true;
+ } // end func addInheritedElements
+
+ /**
+ * Returns true if the requested element is undocumented and false if it's documented.
+ *
+ * The function checks if the element might inherit documentation
+ * from any parentclass.
+ *
+ * @param string Name of the class of the element
+ * @param string Element type: functions, variables, uses, consts.
+ * @param string Element name
+ * @return boolean $ok
+ */
+ function isUndocumented($classname, $type, $elementname) {
+
+ if ( !isset($this->classes[$classname][$type][$elementname]) || $this->classes[$classname][$type][$elementname]["undoc"] || !isset($this->classes[$classname]["path"]) )
+ return true;
+
+ $path = $this->classes[$classname]["path"];
+ while (list($k, $parentclass) = each($path))
+ if ($this->isUndocumented($parentclass, $type, $elementname))
+ return true;
+
+ return false;
+ } // end func isUndocumented
+
+ function updateBrothersSisters() {
+
+ reset($this->classes);
+ while (list($classname, $data) = each($this->classes)) {
+ $this->updateBrotherSisterElements($classname, "functions");
+ $this->updateBrotherSisterElements($classname, "variables");
+ }
+
+ } // end func updateBrothersSisters
+
+ /**
+ * @param string Name of the class to update
+ * @param string Elementtype: functions, variables, ...
+ * @return boolean
+ */
+ function updateBrotherSisterElements($classname, $type) {
+
+ if (!isset($this->classes[$classname][$type]))
+ return false;
+
+ reset($this->classes[$classname][$type]);
+ while (list($elementname, $data) = each($this->classes[$classname][$type])) {
+
+ if (isset($data["brother"])) {
+
+ $name = ( "functions" == $type ) ? substr($data["brother"], 0, -2) : substr($data["brother"], 1);
+ $name = strtolower($name);
+
+ if (!isset($this->classes[$classname][$type][$name])) {
+
+ $this->warn->addDocWarning($this->classes[$classname]["filename"], $type, $elementname, "Brother '$name' is unknown. Tags gets ignored.", "mismatch");
+ unset($this->classes[$classname][$type][$elementname]["brother"]);
+
+ } else {
+
+ $this->classes[$classname][$type][$elementname]["brother"] = $name;
+ $this->classes[$classname][$type][$elementname] = $this->copyBrotherSisterFields($this->classes[$classname][$type][$elementname], $this->classes[$classname][$type][$name]);
+
+ }
+
+ }
+
+ }
+
+ } // end func updateBrotherSisterElements
+
+ function updateAccessReturn() {
+
+ reset($this->classes);
+ while (list($classname, $data) = each($this->classes)) {
+
+ if (!isset($data["access"]))
+ $this->classes[$classname]["access"] = "private";
+
+ $this->updateAccessReturnElements($classname, "functions");
+ $this->updateAccessElements($classname, "variables");
+ $this->updateAccessElements($classname, "consts");
+
+ }
+
+ } // end func updateAccessReturn
+
+ /**
+ * Updates access and return for certain elements.
+ *
+ * This function should only be used to update functions.
+ * Functions that have the same name as the class (constructors)
+ * get return void and access public. Functions without
+ * access get access public and functions without return get
+ * return void.
+ *
+ * @param string Classname
+ * @param string Element type: functions (, variables, consts, uses)
+ * @return boolean $ok
+ * @see updateAccessReturn()
+ */
+ function updateAccessReturnElements($classname, $type) {
+
+ if (!isset($this->classes[$classname][$type]))
+ return false;
+
+ reset($this->classes[$classname][$type]);
+ while (list($elementname, $data) = each($this->classes[$classname][$type])) {
+
+ if (!isset($data["access"]))
+ $this->classes[$classname][$type][$elementname]["access"] = ("functions" == $type && strtolower($elementname) == strtolower($classname)) ? "public" : "private";
+
+ if (!isset($data["return"]))
+ $this->classes[$classname][$type][$elementname]["return"] = "void";
+ else
+ if ("functions" == $type && $elementname == $classname) {
+ $this->warn->addDocWarning($this->classes[$classname]["filename"], "functions", $elementname, "The constructor can't have a return value. @return gets ignored.", "mismatch");
+ $this->classes[$classname]["functions"][$elementname]["return"] = "void";
+ }
+
+ }
+
+ } // end func updateAccessReturnElements
+
+ /**
+ * Updates access tags.
+ *
+ * @param string Classname
+ * @param string Element type: functions, variables, consts (, uses)
+ * @see updateAccessReturnElements()
+ */
+ function updateAccessElements($classname, $type) {
+
+ if (!isset($this->classes[$classname][$type]))
+ return false;
+
+ reset($this->classes[$classname][$type]);
+ while (list($elementname, $data) = each($this->classes[$classname][$type])) {
+
+ if (!isset($data["access"]))
+ $this->classes[$classname][$type][$elementname]["access"] = ("functions" == $type && $elementname == $classname) ? "public" : "private";
+
+ }
+
+ } // end func updateAccessElements
+
+ function checkSee() {
+
+ reset($this->classes);
+ while (list($classname, $class) = each($this->classes)) {
+
+ $this->buildElementlist($classname);
+
+ if (isset($class["functions"]))
+ $this->checkSeeElements($class["functions"], $classname, "functions");
+
+ if (isset($class["variables"]))
+ $this->checkSeeElements($class["variables"], $classname, "variables");
+
+ if (isset($class["consts"]))
+ $this->checkSeeElements($class["consts"], $classname, "consts");
+
+ if (isset($class["uses"]))
+ $this->checkSeeElements($class["uses"], $classname, "uses");
+
+ }
+
+ } // end func checkSee
+
+ /**
+ * Checks see references in the given element array (functions, variables...)
+ *
+ * References to variables and functions within the same class get checked.
+ * It the references element does not exist, the reference gets deleted and
+ * a doc warning gets generated.
+ *
+ * @param array List of functions, variables,...
+ * @param string Name of the class that contains the given elements.
+ * @param string Elementtype: functions, variables, consts, uses.
+ */
+ function checkSeeElements($elements, $classname, $eltype) {
+
+ reset($elements);
+ while (list($elname, $element) = each($elements)) {
+
+ if (isset($element["see"])) {
+
+ if (isset($element["see"]["var"])) {
+
+ reset($element["see"]["var"]);
+ while (list($k, $variable) = each($element["see"]["var"]))
+ if (!isset($this->elementlist["variables"][strtolower($variable["name"])])) {
+ $this->warn->addDocWarning($this->classes[$classname]["filename"], "variables", $elname, "@see referrs to the variable '" . $variable["name"] . "' which is not defined in the class. Entry gets ignored.", "mismatch");
+ unset($this->classes[$classname][$eltype][$elname]["see"]["var"][$k]);
+ }
+
+ }
+
+ if (isset($element["see"]["function"])) {
+
+ reset($element["see"]["function"]);
+ while (list($k, $function) = each($element["see"]["function"]))
+ if (!isset($this->elementlist["functions"][strtolower(substr($function["name"], 0, -2))])) {
+ $this->warn->addDocWarning($this->classes[$classname]["filename"], "functions", $elname, "@see referrs to the function '" . $function["name"] . "' which is not defined in the class. Entry gets ignored.", "mismatch");
+ unset($this->classes[$classname][$eltype][$elname]["see"]["function"][$k]);
+ }
+
+ }
+
+ }
+
+ }
+
+ } // end func checkSeeElement
+
+ /**
+ * Builds an array with all elements of a class and saves it to $this->elementlist.
+ *
+ * @param string Name of the class to scan.
+ */
+ function buildElementlist($classname) {
+
+ $elements = array();
+ $fields = array("functions", "variables", "consts", "uses");
+
+ reset($fields);
+ while (list($k, $field) = each($fields))
+ if (isset($this->classes[$classname][$field])) {
+
+ reset($this->classes[$classname][$field]);
+ while (list($element, ) = each($this->classes[$classname][$field]))
+ $elements[$field][$element] = true;
+
+ }
+
+ $this->elementlist = $elements;
+
+ } // end func buildElementlist
+
+} // end class PhpdocClassAnalyser
+?>
View
370 analyser/PhpdocModuleAnalyser.php
@@ -0,0 +1,370 @@
+<?php
+/**
+* Analyses a modulegroup.
+*
+* @version $Id$
+*/
+class PhpdocModuleAnalyser extends PhpdocAnalyser {
+
+ /**
+ * Module data
+ *
+ * @var array
+ */
+ var $modulegroup = array();
+
+ /**
+ * List of all modules in the modulegroup
+ *
+ * @var array
+ */
+ var $modulelist = array();
+
+ /**
+ * Puuuh - findUndocumented() needs this.
+ *
+ * @var array
+ * @see findUndocumented()
+ */
+ var $undocumentedFields = array(
+ "functions" => "function",
+ "uses" => "included file",
+ "consts" => "constant"
+ );
+
+ /**
+ * Sets the data of the modulegroup to analyse.
+ *
+ * @param array Raw modulegroup data from the parser.
+ * @access public
+ */
+ function setModulegroup($modulegroup) {
+
+ $this->modulegroup = $modulegroup;
+
+ } // end func setModulegroup
+
+ function analyse() {
+
+ $this->flag_get = false;
+
+ $this->buildModulelist();
+
+ $this->updateAccessReturn();
+ $this->updateBrothersSisters();
+ $this->checkSee();
+
+ $this->checkFunctionArgs();
+ $this->findUndocumented();
+
+ } // end func analyse
+
+ /**
+ * Returns a module from the modulegroup or false if there are no more modules.
+ *
+ * @return mixed False if there no more modules in the modulegroup otherwise
+ * an array with the data of a module.
+ * @access public
+ */
+ function getModule() {
+