<?php /** * Parser Data Structures * * phpDocumentor :: automatic documentation generator * * PHP versions 4 and 5 * * Copyright (c) 2002-2008 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 * @subpackage ParserData * @author Gregory Beaver <cellog@php.net> * @copyright 2002-2008 Gregory Beaver * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version CVS: $Id: ParserData.inc 253814 2008-02-26 12:15:56Z ashnazg $ * @link http://www.phpdoc.org * @link http://pear.php.net/PhpDocumentor * @since 1.0rc1 * @todo CS cleanup - change package to PhpDocumentor */ /** * Contains information about a PHP file, used to group procedural elements * together. * * @category ToolsAndUtilities * @package phpDocumentor * @subpackage ParserData * @author Gregory Beaver <cellog@php.net> * @copyright 2002-2008 Gregory Beaver * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version Release: 1.4.3 * @filesource * @link http://www.phpdoc.org * @link http://pear.php.net/PhpDocumentor * @since 1.0rc1 * @todo CS cleanup - change package to PhpDocumentor * @todo CS cleanup - change classname to PhpDocumentor_* */ class parserPage { /** * Type is used by many functions to skip the hassle of if * <code>phpDocumentor_get_class($blah) == 'parserBlah'</code> * @var string */ var $type = 'page'; /** * not implemented in this version, will be used to link xml output pages * @var string */ var $id = ''; /** * filename.ext (no path) * @var string */ var $file = ''; /** * relative source location * @var string */ var $sourceLocation = ''; /** * phpdoc-safe name (only letters, numbers and _) * @var string */ var $name = ''; /** * original phpdoc-safe name (only letters, numbers and _) * * This fixes [ 1391432 ] Too many underscores in include links. * @var string */ var $origName = ''; /** * @var string */ var $category = 'default'; /** * @var string */ var $package = 'default'; /** * @var string */ var $subpackage = ''; /** * @var string */ var $parserVersion = PHPDOCUMENTOR_VER; /** * not implemented yet * file modification date, will be used for makefiles * @var string */ var $modDate = ''; /** * @var string full path this page represents */ var $path = ''; /** * Tokenized source code of the file * @var array */ var $source = array(); /** * Used to limit output, contains contents of --packageoutput commandline. * Does not increase parsing time. Use --ignore for that * @see phpDocumentor_IntermediateParser::$packageoutput, * Converter::$package_output * @var mixed either false or an array of packages */ var $packageOutput = false; /** * sets package to default package * * @global string default package name */ function parserPage() { global $phpDocumentor_DefaultPackageName; $this->package = $GLOBALS['phpDocumentor_DefaultPackageName']; } /** * gets the tag type * * @return string always "page" */ function getType() { return 'page'; } /** * Sets the source code of the file for highlighting. * * PHP 4.3.0+ passes an array of tokenizer tokens by line number. PHP * 4.2.3- passes a string to be passed to {@link highlight_string()} * * @param string|array $source the token array/string * * @return void */ function setSource($source) { $this->source = $source; } /** * Sets the name to display in documentation (can be an alias set with @name) * * @param string $file the file name * * @return void */ function setFile($file) { $this->file = $file; } /** * gets the file name * * @return string|bool filename.ext or @name alias, * or FALSE if it's not set */ function getFile() { if (!isset($this->file)) { return false; } return $this->file; } /** * sets the path to the file * * @param string $path full path to file * * @return void */ function setPath($path) { // look for special windows case if (SMART_PATH_DELIMITER === '\\') { $this->path = strtr($path, '/', '\\'); } else { $this->path = $path; } } /** * gets the path * * @return string fully delimited path (OS-dependent format), * or FALSE if it's not set */ function getPath() { if (!isset($this->path)) { return false; } return $this->path; } /** * loads the package output array * * @param array $packages array of packages to display in documentation * (package1,package2,...) * * @return void * @see phpDocumentor_IntermediateParser::$packageoutput */ function setPackageOutput($packages) { $this->packageOutput = $packages; } /** * gets the package output array * * @return array array of packages (package1,package2,...) * @see phpDocumentor_IntermediateParser::$packageoutput */ function getPackageOutput() { return $this->packageOutput; } /** * sets the name * * @param string $name phpdoc-safe name (only _, numbers and letters) * set by Parser::parse() * * @return void * @see Parser::parse() */ function setName($name) { $this->origName = $name; $this->name = $name; } /** * gets the name * * @return string phpdoc-safe name (only _, numbers and letters), * or FALSE if it's not set */ function getName() { if (!isset($this->name)) { return false; } return $this->name; } /** * sets the source location * * @param string $source path of this file relative to program root * * @return void */ function setSourceLocation($source) { $this->sourceLocation = $source; } /** * gets the source location * * @param Converter $c the output converter * @param bool $pearize if this parameter is true, * it will truncate the source location * to the subdirectory of pear * * @return string path of this file relative to program root * @todo determine if the str_replace in the 'pear/' ELSE branch should be * removed (see Documentation/tests/bug1574043.php). It does NOT exist * in the similar function parserClass->getSourceLocation() in * ParserElements.inc. */ function getSourceLocation ($c, $pearize = false) { global $_phpDocumentor_options; if (!isset($this->sourceLocation)) { $sl = false; } else { $sl = $this->sourceLocation; if ($pearize) { if (strpos($sl, 'pear/')) { $sl = substr($sl, strpos($sl, 'pear/') + 5); } else { $sl = str_replace($_phpDocumentor_options['Program_Root'] . PATH_DELIMITER, '', $sl); } } } return $sl; } /** * Not implemented in this version * * @return bool tell the parser whether to parse the file, * otherwise this function will retrieve the parsed data * from external file */ function getParseData() { return true; } } /** * Contains an in-memory representation of all documentable elements * ({@link parserPage}, {@link parserFunction}, {@link parserDefine}, * {@link parserInclude}, {@link parserClass}, {@link parserMethod}, * {@link parserVar}) and their DocBlocks ({@link parserDocBlock}). * * This class works in coordination with {@link phpDocumentor_IntermediateParser} * to take output from {@link Parser::handleEvent()} and create indexes, links, * and other assorted things (all documented in phpDocumentor_IntermediateParser * and {@link Converter}) * * @category ToolsAndUtilities * @package phpDocumentor * @subpackage ParserData * @author Gregory Beaver <cellog@php.net> * @copyright 2002-2008 Gregory Beaver * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version Release: 1.4.3 * @filesource * @link http://www.phpdoc.org * @link http://pear.php.net/PhpDocumentor * @since 1.0rc1 * @todo CS cleanup - change package to PhpDocumentor */ class parserData { /** * {@link parserPage} element that is this parserData's parent, or false if * not set. * @var false|parserPage */ var $parent = false; /** * array of parsed elements * @var array */ var $elements = array(); /** * @var boolean * @access private */ var $_hasclasses = false; /** * @var boolean * @access private */ var $_hasinterfaces = false; /** * array of parsed elements with @access private * @var array */ var $privateelements = array(); /** * array of parsed class elements * @var array */ var $classelements = array(); /** * @var parserTutorial|false */ var $tutorial = false; /** * array of parsed class elements with @access private * @var array */ var $privateclasselements = array(); /** * array of links descended from {@link abstractLink} * @var array * @see pageLink, defineLink, classLink, functionLink, methodLink, varLink */ var $links = array(); /** * used by {@link phpDocumentor_IntermediateParser::handleDocBlock()} to * determine whether a docblock is a page-level docblock or not. $clean is * true as long as only 0 or 1 docblock has been parsed, and no element * other than parserPage has been parsed * @var boolean */ var $clean = true; /** * DocBlock ({@link parserDocBlock}) for this page, or false if not set * @var mixed */ var $docblock = false; /** * Flag used to determine whether a page-level docblock is present * @var boolean * @access private */ var $_explicitdocblock = false; /** * Type is used by many functions to skip the hassle of if * <code>phpDocumentor_get_class($blah) == 'parserBlah'</code> * always 'page', used in element indexing and conversion functions found in * {@link Converter} * @var string */ var $type = 'page'; /** * add a new element to the tracking array * * @param parserElement &$element add a parsed element to the * {@link $elements} array, * also sets {@link $clean} to false * * @return void */ function addElement(&$element) { $element->setPath($this->parent->path); if ($element->getType() == 'class' || $element->getType() == 'method' || $element->getType() == 'var' || $element->getType() == 'const' ) { if ($element->getType() == 'class') { if ($element->isInterface()) { $this->_hasinterfaces = true; } else { $this->_hasclasses = true; } } $this->classelements[] = $element; } else { $this->elements[] = $element; } $this->clean = false; } /** * Does this package have interfaces? * * @return bool */ function hasInterfaces() { return $this->_hasinterfaces; } /** * Does this package have classes? * * @return boolean */ function hasClasses() { return $this->_hasclasses; } /** * adds a tutorial parser * * @param parserTutorial $t a tutorial parser * @param Converter &$c the output converter * * @return void */ function addTutorial($t, &$c) { $this->tutorial = new tutorialLink; $this->tutorial->addLink('', $t->path, $t->name, $t->package, $t->subpackage, $t->getTitle($c)); } /** * If this file has a tutorial associated with it, * returns a link to the tutorial. * * @return tutorialLink */ function getTutorial() { return $this->tutorial; } /** * If the page-level DocBlock was present in the source, returns true * * @return bool */ function hasExplicitDocBlock() { return $this->_explicitdocblock; } /** * Tells this page that its DocBlock was not implicit * * @return bool */ function explicitDocBlock() { $this->_explicitdocblock = true; } /** * adds a link * * @param parserElement &$element element to add a new link (descended from * {@link abstractLink}) to the * {@link $links} array * @param string $classorpackage classname for elements that are * class-based (this may be deprecated in * the future, as the classname should be * contained within the element. if * $element is a page, this parameter is a * package name * @param string $subpackage subpackage name for page elements * * @return string */ function addLink(&$element, $classorpackage = '', $subpackage = '') { switch($element->type) { case 'function': $x = new functionLink; $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage); return $x; break; case 'define': $x = new defineLink; $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage); return $x; break; case 'global': $x = new globalLink; $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage); return $x; break; case 'class': $x = new classLink; $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage); return $x; break; case 'method': $x = new methodLink; $x->addLink($classorpackage, $this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage); return $x; break; case 'var': $x = new varLink; $x->addLink($classorpackage, $this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage); return $x; break; case 'page': if (empty($classorpackage)) { $classorpackage = $GLOBALS['phpDocumentor_DefaultPackageName']; } $x = new pageLink; $x->addLink($element->path, $element->name, $element->file, $classorpackage, $subpackage); return $x; break; } } /** * returns a link * * @param Converter &$c the output converter * @param bool $text a text flag * * @return string */ function &getLink(&$c, $text = false) { $a = $c->getPageLink($this->parent->file, $this->docblock->package, $this->parent->path, $text); return $a; } /** * returns a list of all classes declared in a file * * @param Converter &$c output converter * * @return array Format: array( * packagename => parserClass, * packagename => parserClass, * ... * ) */ function getClasses(&$c) { $r = $c->classes->getClassesInPath($this->parent->path); $rr = array(); if ($r) { foreach ($r as $class => $obj) { $rr[$obj->docblock->package][] = $obj; } } return $rr; } /** * Get the output-safe filename (. changed to _) * * @return string */ function getName() { if (isset($this->parent) && $this->parent) { return $this->parent->getName(); } } /** * sets the parent * * @param parserPage &$parent parent element of this parsed data * * @return void */ function setParent(&$parent) { $this->parent = $parent; } /** * checks if the element is "cleaned" already * * @return bool returns the value of {@link $clean} */ function isClean() { return $this->clean; } /** * sets the docblock * * @param parserDocBlock &$docblock docblock element * * @return void * @see parserDocBlock */ function setDocBlock(&$docblock) { $this->docblock = $docblock; } } /** * Base class for all elements * * @category ToolsAndUtilities * @package phpDocumentor * @subpackage ParserData * @author Gregory Beaver <cellog@php.net> * @copyright 2002-2008 Gregory Beaver * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version Release: 1.4.3 * @filesource * @link http://www.phpdoc.org * @link http://pear.php.net/PhpDocumentor * @since 1.0rc1 * @todo CS cleanup - change package to PhpDocumentor * @abstract */ class parserBase { /** * Type is used by many functions to skip the hassle of if * phpDocumentor_get_class($blah) == 'parserBlah'... always base * @var string */ var $type = 'base'; /** * set to different things by its descendants * @abstract * @var mixed */ var $value = false; /** * gets the type * * @return string returns value of {@link $type} */ function getType() { return $this->type; } /** * sets the given value * * @param mixed $value set the value of this element * * @return void */ function setValue($value) { $this->value = $value; } /** * gets the value * * @return mixed get the value of this element (element-dependent) */ function getValue() { return $this->value; } } /** * Used to represent strings that contain inline tags, * so that they can be properly parsed at link time * * @category ToolsAndUtilities * @package phpDocumentor * @subpackage ParserData * @author Gregory Beaver <cellog@php.net> * @copyright 2002-2008 Gregory Beaver * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version Release: 1.4.3 * @filesource * @link http://www.phpdoc.org * @link http://pear.php.net/PhpDocumentor * @since 1.0rc1 * @todo CS cleanup - change package to PhpDocumentor */ class parserStringWithInlineTags extends parserBase { /** * Type is used by many functions to skip the hassle of * if phpDocumentor_get_class($blah) == 'parserBlah'... * always '_string' * @var string */ var $type = '_string'; /** * @access private */ var $cache = false; /** * array of strings and {@link parserInlineTag}s * Format: * array(string1,string2,parserInlineTag1,string3,parserInlineTag2,...) * @var array */ var $value = array(); /** * equivalent to the . operator ($a = $b . $c) * * @param mixed $stringOrInlineTag either a string or a {@link parserInlineTag} * * @return void */ function add($stringOrInlineTag) { if (is_string($stringOrInlineTag)) { if (!count($this->value)) { $this->value[] = $stringOrInlineTag; return; } if (is_string($this->value[count($this->value) - 1])) { $this->value[count($this->value) - 1] .= $stringOrInlineTag; return; } else { $this->value[] = $stringOrInlineTag; return; } } else { if (is_a($stringOrInlineTag, 'parserinlinetag') && phpDocumentor_setup::checkIgnoreTag($stringOrInlineTag-> inlinetype, true) ) { return; } $this->value[] = $stringOrInlineTag; } } /** * Determine whether the string contains any inline tags * * @return bool * @tutorial inlinetags.pkg */ function hasInlineTag() { for ($i=0; $i<count($this->value); $i++) { if (is_a($this->value[$i], 'parserinlinetag')) { return true; } } return false; } /** * Pass source code to any {@}source} tags contained within the string * for later conversion. * * @param string|array $source source code ready to be highlighted * * @return void */ function setSource($source) { for ($i=0; $i<count($this->value); $i++) { if (phpDocumentor_get_class($this->value[$i]) == 'parsersourceinlinetag' ) { $this->value[$i]->setSource($source); } } } /** * equivalent to trim(strlen($string)) * * @return integer length of the string this object represents */ function trimmedStrlen() { $a = 0; for ($i=0; $i<count($this->value); $i++) { if (is_string($this->value[$i])) { if ($i == 0) { $a += strlen(ltrim($this->value[$i])); } elseif ($i == count($this->value[$i]) - 1) { $a += strlen(chop($this->value[$i])); } } else { $a += $this->value[$i]->Strlen(); } } return $a; } /** * return the string unconverted (all inline tags are taken out - this * should only be used in pre-parsing to see if any other text * is in the string) * * @param bool $trim whether to trim the string * * @return string trimmed value * @uses parserInlineTag::getString() removes inline tag length, as it is * indeterminate until conversion. */ function getString($trim = true) { $a = ''; for ($i=0; $i<count($this->value); $i++) { if (is_string($this->value[$i])) { $a .= $this->value[$i]; } else { $a .= $this->value[$i]->getString(); } } if ($trim) { $a = trim($a); } return $a; } /** * Use to convert the string to a real string * with all inline tags parsed and linked * * @param Converter &$converter the output converter * @param bool $postprocess true if one needs to postprocess * @param bool $trim false if the output should not be trimmed * * @return string * @see Converter::returnSee() * @todo CS cleanup - rename to convert for camelCase rule */ function Convert(&$converter, $postprocess = true, $trim = true) { if ($this->cache) { if ($converter->name == $this->cache['name'] && $converter->outputformat == $this->cache['output'] && $converter->checkState($this->cache['state']) && $this->cache['postprocess'] === $postprocess ) { return $this->cache['contents']; } if ($converter->name != $this->cache['name']) { $this->cache = false; } } if (is_string($this->value)) { return $this->value; } $a = ''; for ($i=0; $i<count($this->value); $i++) { if (is_string($this->value[$i])) { if ($postprocess && !method_exists($converter, 'postProcess')) { var_dump('a', $converter); } if ($postprocess) { $a .= $converter->postProcess($this->value[$i]); } else { $a .= $this->value[$i]; } } else { $a .= $this->value[$i]->Convert($converter, $postprocess); } } if ($trim) { $a = trim($a); } $this->cache = array( 'name' => $converter->name, 'output' => $converter->outputformat, 'contents' => $a, 'state' => $converter->getState(), 'postprocess' => $postprocess ); return $a; } } ?>