parentpackagename
* @see Converter::getLink()
*/
var $package_parents = array();
/**
* Used to determine the category for tutorials.
*
* WARNING: If more than one category exists, the last category
* encountered will overwrite the previous and will raise a big warning
* @var array Format: packagename => categoryname
*/
var $packagecategories = array();
/**
* list of all packages encountered while documenting. Used in automatic
* linking.
*
* Converter::getLink() first checks if an ambiguous link is found in the
* current package. If not, it then checks in parent packages, and if still
* not found, uses this array to check in the rest of the packages before
* giving up
* @var array Format: array(packagename => 1, packagename => 1,...)
* @see Converter::getLink()
*/
var $all_packages = array();
/**
* array of packages to parser and output documentation for, if not all
* packages should be documented
*
* Format:
* array(package1,package2,...)
* or false if not set
*
* Use this option to limit output similar to ignoring files. If you have
* some temporary files that you don't want to specify by name but don't
* want included in output, set a package name for all the elements in your
* project, and set packageoutput to that name. the default package will be
* ignored. Parsing speed does not improve. If you want to ignore files
* for speed reasons, use the ignore command-line option
* @tutorial phpDocumentor.howto.pkg#using.command-line.packageoutput
* @see Io
* @var false|array
*/
var $packageoutput = false;
/**
* the functions which handle output from the {@link Parser}
* @see handleEvent(), handleDocBlock(), handlePage(), handleClass()
* @see handleDefine(), handleFunction(), handleMethod(), handleVar()
* @see handlePackagePage(), handleInclude(), handleTutorial()
*/
var $event_handlers = array(
'docblock' => 'handleDocBlock',
'page' => 'handlePage',
'class' => 'handleClass',
'define' => 'handleDefine',
'function' => 'handleFunction',
'method' => 'handleMethod',
'var' => 'handleVar',
'const' => 'handleConst',
'packagepage' => 'handlePackagePage',
'include' => 'handleInclude',
'global' => 'handleGlobal',
'tutorial' => 'handleTutorial',
);
/**
* $data contains parsed structures for the current page being parsed
*
* In version 1.1+, $data is only used to store the current page information.
* All handling of documented elements is handled by the
* {@link ProceduralPages} and {@link Classes} classes.
* @var parserData
*/
var $data;
/**
* set in {@link Setup.inc.php} to the value of the quitemode commandline
* option.
*
* If this option is true, informative output while parsing will not be
* displayed (documentation is unaffected)
* @var boolean
* @tutorial phpDocumentor.howto.pkg#using.command-line.quiet
*/
var $quietMode = false;
/**
* used to keep track of inheritance at the smartest level possible for a
* dumb computer
* @var Classes
*/
var $classes = false;
/**
* used to keep track of all elements in a procedural page. Handles name
* conflicts with elegance
* @since 1.1
* @var ProceduralPages
*/
var $proceduralpages = false;
/**
* an array of template names indexed by converter name
*
* For example, if the default HTMLframesConverter is using the DOM/l0l33t
* template, the array will be
* $converters['frames'] = 'DOM/l0l33t'
* @var array Format: array(Convertername1 => templatename)
* @see Converter
*/
var $converters = false;
/**
* @var string Title of generated documentation, passed to Converters
*/
var $title = '';
var $uses = array();
var $db_template;
/**
* Stores parsed CHANGELOG/INSTALL/README files
* @var array Format: array(CHANGELOG => contents,
* INSTALL => contents,
* README => contents)
*/
var $ric = array();
/**
* Flag used to determine whether the last docblock
* was a page-level docblock.
* @var boolean
* @access private
*/
var $_lastDocBlockWasPageLevel = false;
/**
* Flag used to determine whether the Page-level
* DocBlock was declared in old or new style
* @var boolean
* @access private
*/
var $_oldPageLevel = false;
/**
* sets up basic data structures
* @param string Title of generated documentation, passed to Converters
* @see $title, $data, $classes, $proceduralpages
*/
function phpDocumentor_IntermediateParser($title='Generated Documentation')
{
$this->title = $title;
$this->data = new parserData;
$this->classes = new Classes;
$this->proceduralpages = new ProceduralPages;
}
/**
* Retrieve the relative path. If the path contains "pear/" it will
* be used as the base, otherwise the Program_Root string will be used.
* @global array uses 'Program_Root' option to replace it with '' for
* retrieving the source location of a file
* @param string path to file
* @return string
* @see $sourceLocation
* @access private
*/
function _getSourceLocation($sl, $sourceloc)
{
global $_phpDocumentor_options;
if (empty($sl)) return false;
$sl = str_replace('\\','/',$sl);
if (strpos($sl,'pear/'))
{
$sl = substr($sl,strpos($sl,'pear/') + 5);
if (dirname($sl) == '.')
{
return 'PEAR';
}
return dirname($sl);
} else
{
if (strpos(str_replace($_phpDocumentor_options['Program_Root'] . PATH_DELIMITER,'',$sourceloc),PATH_DELIMITER) === false)
return '';
return dirname(str_replace($_phpDocumentor_options['Program_Root'] . PATH_DELIMITER,'',$sourceloc));
}
}
/**
* Guess the package/subpackage based on subdirectory if the --pear option
*
* A file in pear/dir/file.php will be in package "dir." A file in
* pear/dir/subdir/file.php will be in package "dir," subpackage "subdir."
* @param string full path of file
* @param template-ready source location Program_Root/dir/file.php
* @global array uses the 'pear' option to determine whether to guess based
* on subdirectory
* @tutorial phpDocumentor.howto.pkg#using.command-line.pear
*/
function _guessPackage($path, $sourceloc)
{
global $_phpDocumentor_setting;
if ($_phpDocumentor_setting['pear'])
{
$subpath = explode(PATH_DELIMITER, $this->_getSourceLocation($path, $sourceloc));
if (!empty($subpath[0]))
{ // can only have package and subpackage in this version
$package = $subpath[0];
$subpackage = '';
if (isset($subpath[1])) $subpackage = $subpath[1];
return array($package,$subpackage);
} else return array($this->package, $this->subpackage);
} else return array($this->package, $this->subpackage);
}
/**
* handles post-parsing of include/require/include_once/include_once
*
* This function sets {@link $data}->clean to false to tell the
* phpDocumentor_IntermediateParser that a page-level DocBlock can't be
* found after this point on this page. It then sets the package
* to be the same as the page, and adds itself to the
* {@link ProceduralPages} class
* @param integer $event Event number from {@link Parser.inc}
* @param parserInclude $data
*/
function handleInclude($event,$data)
{
if ($this->_lastDocBlockWasPageLevel)
{
addWarning(PDERROR_DOCBLOCK_CONFLICT, $data->getName(), $data->getFile());
if (!$this->_oldPageLevel)
{
unset($this->last);
}
}
$this->_lastDocBlockWasPageLevel =
$this->data->clean = false;
// page was @ignored
if ($this->private_page)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
// $this->last->setLineNumber($data->getLineNumber());
if ($this->last->getKeyword('ignore'))
{
$this->last = false;
return;
// addWarning(PDERROR_IGNORE_TAG_IGNORED,'include',$data->getName().'('.$data->getValue().')');
}
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'include');
$data->setDocBlock($this->last);
$this->proceduralpages->addInclude($data);
$this->last = false;
}
/**
* handles post-parsing of global variables
*
* This function sets {@link $data}->clean to false to tell the
* phpDocumentor_IntermediateParser that a page-level DocBlock can't be
* found after this point on this page. It then sets the package
* to be the same as the page, and adds itself to the
* {@link ProceduralPages} class
* @param integer $event Event number from {@link Parser.inc}
* @param parserGlobal $data
*/
function handleGlobal($event,$data)
{
if ($this->_lastDocBlockWasPageLevel)
{
addWarning(PDERROR_DOCBLOCK_CONFLICT, 'global variable', $data->getName());
if (!$this->_oldPageLevel)
{
unset($this->last);
}
}
$this->_lastDocBlockWasPageLevel =
$this->data->clean = false;
if ($this->private_page)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
// $this->last->setLineNumber($data->getLineNumber());
if ($this->last->getKeyword('ignore'))
{
addWarning(PDERROR_IGNORE_TAG_IGNORED,'global variable - just don\'t document the',$data->getName());
$this->last = false;
return;
}
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'global');
$data->setDocBlock($this->last);
if ($data->docblock->getKeyword('name'))
{
$a = $data->docblock->getKeyword('name');
if (is_object($a)) $a = $a->value;
$data->setName($a);
}
$this->proceduralpages->addGlobal($data);
$this->last = false;
}
/**
* handles post-parsing of Package-level documentation pages.
*
* sets the {@link $package_pages}[$data->package] to $data
* @param integer $event Event number from {@link Parser.inc}
* @param parserPackagePage $data
*/
function handlePackagePage($event,$data)
{
$this->package_pages[$data->package] = &$data;
$this->last = false;
}
/**
* handle post-parsing of Tutorials.
*
* This adds the parsed tutorial to the tutorial tree
* @uses $tutorials sets the value of tutorials to parameter $data
* @param integer $event Event Number
* @param parserTutorial $data
* @since 1.2
*/
function handleTutorial($event,$data)
{
if (isset($this->packagecategories[$data->package]))
{
$data->category = $this->packagecategories[$data->package];
} else
{
$data->category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
}
$this->tutorials[$data->package][$data->subpackage][$data->tutorial_type][$data->name] = $data;
}
/**
* handles post-parsing of class vars
*
* This function sets up a @var tag if none is found, and aligns $data's
* $path var and packages to match the parent object
* @param integer $event Event number from {@link Parser.inc}
* @param parserVar $data
*/
function handleVar($event,$data)
{
global $_phpDocumentor_setting;
if ($this->private_class)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
{
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
} else {
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
}
// $this->last->setLineNumber($data->getLineNumber());
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'var');
$this->last->updateModifiers($data->getModifiers());
if ($this->last->getKeyword('ignore'))
{
$this->last = false;
return;
// addWarning(PDERROR_IGNORE_TAG_IGNORED,'var',$this->cur_class.'::'.$data->getName());
}
if (!$this->last->var)
{
$this->last->addVar('mixed',new parserStringWithInlineTags);
}
if ($_phpDocumentor_setting['pear'])
{
if (strpos($data->getName(), '_') == 1 && !$this->last->getKeyword('access'))
{
addWarning(PDERROR_PRIVATE_ASSUMED,'class variable',$data->class.'::'.$data->getName());
$this->last->addKeyword('access','private');
$data->setDocBlock($this->last);
}
}
$data->setDocBlock($this->last);
$data->path = $this->data->parent->path;
$this->classes->addVar($data);
$this->last = false;
}
/**
* handles post-parsing of class constants
*
* This function aligns $data's
* $path var and packages to match the parent object
* @param integer $event Event number from {@link Parser.inc}
* @param parserVar $data
*/
function handleConst($event,$data)
{
global $_phpDocumentor_setting;
if ($this->private_class)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
// $this->last->setLineNumber($data->getLineNumber());
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'const');
if ($this->last->getKeyword('ignore'))
{
$this->last = false;
return;
// addWarning(PDERROR_IGNORE_TAG_IGNORED,'var',$this->cur_class.'::'.$data->getName());
}
$data->setDocBlock($this->last);
$data->path = $this->data->parent->path;
$this->classes->addConst($data);
$this->last = false;
}
/**
* handles post-parsing of class methods
*
* This function first aligns $data's path and package to match the parent
* object, and also aligns the docblock's @param, @global, and @staticvar
* tags with the information parsed from the method source code. It also
* checks to see if the method is a constructor and sets the $isConstructor
* flag. If source code has been parsed by a {@}source} tag, the source is
* added to its docblock
*
* Finally, it adds the method to the {@link Classes} class.
* @param integer $event Event number from {@link Parser.inc}
* @param parserMethod $data
*/
function handleMethod($event,$data)
{
global $_phpDocumentor_setting;
if ($this->private_class)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
// $this->last->setLineNumber($data->getLineNumber());
if ($this->last->getKeyword('ignore'))
{
$this->last = false;
return;
// addWarning(PDERROR_IGNORE_TAG_IGNORED,'method',$this->cur_class.'::'.$data->getName());
}
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'method');
if ($data->hasSource())
{
$this->last->setSource($data->getSource(), $data->getClass());
}
foreach($data->listParams() as $param)
{
$update_params[] = $param[0];
}
foreach($data->listGlobals() as $param)
{
$update_globals[] = $param[1];
}
foreach($data->listStatics() as $param)
{
$update_statics[] = $param[0];
}
if (isset($update_params))
$this->last->updateParams($update_params);
if (isset($update_globals))
$this->last->updateGlobals($update_globals);
if (isset($update_statics))
$this->last->updateStatics($update_statics);
$this->last->updateModifiers($data->getModifiers());
unset($update_params);
unset($update_globals);
unset($update_statics);
if ($data->getName() == $this->cur_class) $data->setConstructor();
if ($data->getName() == '__construct') {
$data->setConstructor();
}
if ($data->getName() == '__destruct') {
$data->setDestructor();
}
if ($_phpDocumentor_setting['pear'])
{
if (strpos($data->getName(), '_') === 0 && substr($data->getName(), 1) == $data->class)
{ // is destructor
$data->setDestructor();
} elseif (strpos($data->getName(), '_') === 0 && !$this->last->getKeyword('access'))
{
if (strpos($data->getName(), '__') !== 0) {
addWarning(PDERROR_PRIVATE_ASSUMED,'method',$data->class.'::'.$data->getName().'()');
$this->last->addKeyword('access','private');
$data->setDocBlock($this->last);
}
}
}
$data->setDocBlock($this->last);
$data->path = $this->data->parent->path;
$this->classes->addMethod($data);
$this->last = false;
}
/**
* handles post-parsing of functions
*
* This function sets {@link $data}->clean to false to tell the
* phpDocumentor_IntermediateParser that a page-level DocBlock can't be
* found after this point on this page. It then sets the package to be the
* same as the page, aligns the docblock's @param, @global, and @staticvar
* tags with the information parsed from the function source code.
*
* If source code has been parsed by a {@}source} tag, the source is added
* to its docblock, and then the parserFunction adds itself to the
* {@link ProceduralPages} class
* @param integer $event Event number from {@link Parser.inc}
* @param parserFunction $data
*/
function handleFunction($event,$data)
{
if ($this->_lastDocBlockWasPageLevel)
{
addWarning(PDERROR_DOCBLOCK_CONFLICT, 'function', $data->getName());
if (!$this->_oldPageLevel)
{
unset($this->last);
}
}
$this->_lastDocBlockWasPageLevel =
$this->data->clean = false;
if ($this->private_page)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
// $this->last->setLineNumber($data->getLineNumber());
if ($this->last->getKeyword('ignore'))
{
unset($this->last);
return;
}
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'function');
foreach($data->listParams() as $param)
{
$update_params[] = $param[0];
}
foreach($data->listGlobals() as $param)
{
$update_globals[] = $param[1];
}
foreach($data->listStatics() as $param)
{
$update_statics[] = $param[0];
}
if (isset($update_params))
$this->last->updateParams($update_params);
if (isset($update_globals))
$this->last->updateGlobals($update_globals);
if (isset($update_statics))
$this->last->updateStatics($update_statics);
unset($update_params);
unset($update_globals);
unset($update_statics);
if ($data->hasSource())
{
$this->last->setSource($data->getSource());
}
if (count($this->last->params) == 1 && !count($data->listParams()))
{
// if the function has no parameters, and 1 @param, add it to the list as optional, default value is description from @param
$pars = $this->last->listParams();
$data->addParam($pars[0]['var'],$pars[0]['data']->getString());
}
$data->setDocBlock($this->last);
$this->proceduralpages->addFunction($data);
$this->last = false;
}
/**
* handles post-parsing of defines
*
* This function sets {@link $data}->clean to false to tell the
* phpDocumentor_IntermediateParser that a page-level DocBlock can't be
* found after this point on this page. It then sets the package to be the
* same as the page and adds itself to the {@link ProceduralPages} class
* @param integer $event Event number from {@link Parser.inc}
* @param parserDefine $data
*/
function handleDefine($event,$data)
{
if ($this->_lastDocBlockWasPageLevel)
{
addWarning(PDERROR_DOCBLOCK_CONFLICT, 'define', $data->getName());
if (!$this->_oldPageLevel)
{
unset($this->last);
}
}
$this->_lastDocBlockWasPageLevel =
$this->data->clean = false;
if ($this->private_page)
{
unset($this->last);
return;
}
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
}
// $this->last->setLineNumber($data->getLineNumber());
if ($this->last->getKeyword('ignore'))
{
unset($this->last);
return;
}
$this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'define');
$data->setDocBlock($this->last);
$this->proceduralpages->addDefine($data);
$this->last = false;
}
/**
* handles post-parsing of classes
*
* This function sets {@link $data}->clean to false to tell the
* phpDocumentor_IntermediateParser that a page-level DocBlock can't be
* found after this point on this page. It sets {@link $cur_class} to its
* name, and if an @ignore tag is found in the DocBlock, it sets
* {@link $private_class} to true, to prevent post-parsing of any of the
* class's vars or methods. Then it checks for the existence of a package
* page for the class's package
* @param integer $event Event number from {@link Parser.inc}
* @param parserClass $data
*/
function handleClass($event,$data)
{
global $_phpDocumentor_setting;
if ($this->_lastDocBlockWasPageLevel)
{
if (!$this->_oldPageLevel)
{
addWarning(PDERROR_DOCBLOCK_GOES_CLASS, $data->getName());
$doc = new parserDocBlock;
$doc->category = $this->category;
$doc->package = $this->package;
$doc->subpackage = $this->subpackage;
if ($_phpDocumentor_setting['sourcecode']) {
$doc->canSource();
$doc->addFileSource($this->data->parent->path, $this->data->parent->source);
}
$this->data->setDocBlock($doc);
unset($doc);
$this->last->cantSource();
}
}
$this->_lastDocBlockWasPageLevel =
$this->data->clean = false;
if (empty($this->last))
{
if (isset($this->db_template))
// use the docblock template
$this->last = phpDocumentor_clone($this->db_template);
else
// we don't have a docblock, create an empty one to get rid of errors
$this->last = new parserDocblock();
list($this->last->package, $this->last->subpackage) = $this->_guessPackage($this->data->parent->path, $this->data->parent->getSourceLocation('dummy'));
addWarning(PDERROR_NO_PACKAGE_TAG,'class',$data->getName(),$this->last->package);
} else
{
if (!$this->last->getExplicitPackage())
{
list($this->last->package, $this->last->subpackage) = $this->_guessPackage($this->data->parent->path, $this->data->parent->getSourceLocation('dummy'));
addWarning(PDERROR_NO_PACKAGE_TAG,'class',$data->getName(),$this->last->package);
} else
{
if (isset($this->packagecategories[$this->package])
&& $this->packagecategories[$this->package] != $this->category)
addWarning(PDERROR_PACKAGECAT_SET,$this->package,
$this->packagecategories[$this->package],
$this->category);
$this->packagecategories[$this->package] = $this->category;
}
}
$this->last->updateModifiers($data->getModifiers());
// $this->last->setLineNumber($data->getLineNumber());
$data->setDocBlock($this->last);
$this->cur_class = $name = $data->getName();
if ($this->last->getKeyword('ignore'))
{
$this->private_class = true;
unset($this->last);
return;
}
$data->path = $this->data->parent->path;
$this->classes->addClass($data);
$this->private_class = false;
if ($this->last->package)
{
$this->parsePackagePage($this->last->package, $this->data->parent->getPath());
}
$this->last = false;
}
/**
* handles post-parsing of procedural pages
*
* this event is called at the start of a new page, before the Parser knows
* whether the page will contain any procedural pages or not
* @param integer $event Event number from {@link Parser.inc}
* @param parserPage $data
*/
function handlePage($event,$data)
{
$type = 'page';
$this->private_page = false;
$this->data = new parserData;
$data->category = $this->category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
$this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
$this->subpackage = '';
$this->proceduralpages->addPage($data);
$this->data->setParent($data);
$this->pages[$data->getPath()] = $this->data;
$this->classes->nextFile($data->getPath());
$this->packageoutput = $data->getPackageOutput();
}
/**
* handles post-parsing of DocBlocks
*
* This function sets {@link $last} to the DocBlock represented by $data, to
* allow the next documentable element passed to
* phpDocumentor_IntermediateParser to link the DocBlock into its $docblock
* property. This function also checks for two special cases of DocBlocks:
*