/web/vendors/PHP/DocBlockGenerator/Tokens.php
PHP | 481 lines | 199 code | 43 blank | 239 comment | 26 complexity | 143e93d3454bdc37d1e73e4aad22269c MD5 | raw file
Possible License(s): Apache-2.0
- <?php
- /**
- * DocBlock Generator
- *
- * PHP version 5
- *
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * + Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * + Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * + The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category PHP
- * @package PHP_DocBlockGenerator
- * @author Michel Corne <mcorne@yahoo.com>
- * @copyright 2007 Michel Corne
- * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
- * @version SVN: $Id: Tokens.php 31 2007-09-13 10:21:01Z mcorne $
- * @link http://pear.php.net/package/PHP_DocBlockGenerator
- */
- require_once 'PHP/DocBlockGenerator/Block.php';
- require_once 'PHP/CompatInfo.php';
- /**
- * Extraction of the PHP objects/tokens of the source code and creation of the DocBlocks
- *
- * @category PHP
- * @package PHP_DocBlockGenerator
- * @author Michel Corne <mcorne@yahoo.com>
- * @copyright 2007 Michel Corne
- * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/PHP_DocBlockGenerator
- */
- class PHP_DocBlockGenerator_Tokens
- {
- /**
- * The PHP_DocBlockGenerator_Block instance
- *
- * @var object
- * @access private
- */
- private $block;
- /**
- * The source code End-Of-Line character
- *
- * EOL = "\r\n" for DOS/Windows, "\r" for MAC, "\n" for Unix
- *
- * @var string
- * @access public
- */
- public $eol;
- /**
- * Flag indicating if the current token has a DocBlock or not
- *
- * @var boolean
- * @access public
- */
- public $hasBlock;
- /**
- * The current token information, including the token type, access type...
- *
- * @var array
- * @access public
- */
- public $id;
- /**
- * Flag indicating if the current token is within a class
- *
- * @var integer
- * @access public
- */
- public $inClass;
- /**
- * Flag indicating if the class is an interface
- *
- * @var boolean
- * @access public
- */
- public $isInterface;
- /**
- * The none relevant PHP code tokens
- *
- * @var array
- * @access private
- */
- private $noPHPCode = array(// /
- T_WHITESPACE, T_ENCAPSED_AND_WHITESPACE, // spaces
- T_DOC_COMMENT, T_COMMENT, // comments
- T_INLINE_HTML, // none PHP code
- );
- /**
- * Source code tokens excluding none relevant PHP code tokens
- *
- * @var array
- * @access private
- */
- private $phpTokens = array();
- /**
- * The file PHP version
- *
- * @var string
- * @access public
- */
- public $phpVersion = '';
- /**
- * Source code tokens
- *
- * @var array
- * @access private
- */
- private $tokens = array();
- /**
- * The class constructor
- *
- * @return void
- * @access public
- */
- public function __construct()
- {
- $this->block = new PHP_DocBlockGenerator_Block($this);
- $this->info = new PHP_CompatInfo('null');
- }
- /**
- * Gets the current token
- *
- * @param integer $id the token identification number
- * @return array the token type and value, false if invalid ID
- * @access public
- */
- public function get($id)
- {
- return $this->isValid($id)? $this->tokens[$id] : false;
- }
- /**
- * Gets all the source code tokens and tidies them
- *
- * @param string $data the source code
- * @return boolean true on success, false on failure
- * @access private
- */
- private function getAll($data)
- {
- // extracts the tokens, tidies the tokens, extracts the PHP code only tokens
- $this->tokens = token_get_all($data) and array_walk($this->tokens, array($this, 'tidy')) and
- $this->phpTokens = array_filter($this->tokens, array($this, 'isPHPCode'));
- // /
- // dump of all the tokens: un-comment for debugging purposes only
- //file_put_contents('tokens.txt', var_export($this->tokens, true));
- // /
- return (bool)$this->tokens;
- }
- /**
- * Determines the source code End Of Line character
- *
- * EOL = "\r\n" for DOS/Windows, "\r" for MAC, "\n" for Unix
- *
- * @access private
- */
- private function getEOL($data)
- {
- if (strpos($data, "\r\n") !== false) { // DOS/Windows EOL
- $this->eol = "\r\n";
- } else if (strpos($data, "\r") !== false) { // MAC EOL
- $this->eol = "\r";
- } else { // Unix EOL
- $this->eol = "\n";
- }
- }
- /**
- * Verifies that the token is a valid source code token
- *
- * @param integer $id the token identification number
- * @return boolean true if valid, false otherwise
- * @access private
- */
- private function isValid($id)
- {
- return isset($this->tokens[$id]);
- }
- /**
- * Checks if the token is relevant PHP code, excluding spaces and comments.
- *
- * This is an array_filter() callback function.
- *
- * @param array $token the token
- * @return boolean true if relevant PHP code, false otherwise
- * @access private
- */
- private function isPHPCode($token)
- {
- return !in_array($token['type'], $this->noPHPCode);
- }
- /**
- * Processes the source code tokens
- *
- * Gets all the source code tokens. Determines the source code EOL.
- * Determines the file PHP version. Initializes the Page-level tags.
- * Parses the file tokens and creates their DocBlocks.
- * Re-assembles all the tokens with their DocBlocks.
- *
- * @param string $data the source code
- * @param array $param the tags/parameters values
- * @return boolean true on success, false on failure
- * @access public
- */
- public function process($data, $param)
- {
- // get all the tokens
- if ($result = $this->getAll($data)) {
- // determines the source code EOL
- $this->getEOL($data);
- // extracts all the tokens
- $allTokens = $this->slice();
- // initializes the Page-level tags
- $this->block->init($param);
- $this->hasBlock = 0;
- $this->id = array();
- $this->inClass = null;
- $this->isInterface = false;
- $inFunct = null;
- $openTagID = null;
- $isPageBlock = false;
- foreach($this->tokens as $id => $token) {
- $value = $token['value'];
- switch ($type = $token['type']) {
- case '{': // class or function opening curly brace
- // note: none matching open and close curly braces will cause issues
- case T_CURLY_OPEN:
- case T_DOLLAR_OPEN_CURLY_BRACES: // ${
- // counting braces within the function, and the class
- is_null($inFunct) or $inFunct++;
- is_null($this->inClass) or $this->inClass++;
- break;
- case '}': // class or function closing curly brace
- // reached end of the function or class
- is_null($inFunct) or --$inFunct or $inFunct = null;
- is_null($this->inClass) or --$this->inClass or
- $this->inClass = null or $this->isInterface = false;
- break;
- case T_ABSTRACT: // abstract, class or function abstraction
- case T_FINAL: // final class or function
- $this->id[$type] = $id;
- break;
- case T_CONST: // const
- // sets the const DocBlock
- is_null($this->inClass) or $this->block->setConst($id);
- break;
- case T_CONSTANT_ENCAPSED_STRING: // "foo" or 'bar' string syntax
- // sets the include DocBlock
- isset($this->id[T_INCLUDE]) and $this->block->build($this->id[T_INCLUDE]);
- break;
- case T_DOC_COMMENT: // /** */ PHPDoc style comments (PHP 5 only)
- // spots the page block, realigns the DocBlock tags
- $this->hasBlock = true;
- $isPageBlock or $isPageBlock = (strpos($value, '@package') !== false);
- $this->block->realign($id, $value);
- break;
- case T_FUNCTION: // function or cfunction functions
- $inFunct = 0;
- $this->block->setFunction($id); // sets function DocBlock
- break;
- case T_INCLUDE: // include()
- case T_INCLUDE_ONCE: // include_once()
- case T_REQUIRE: // require()
- case T_REQUIRE_ONCE: // require_once()
- $type = T_INCLUDE;
- case T_GLOBAL: // global variable scope
- // only capturing includes and globals outside of classes and functions
- is_null($this->inClass) and is_null($inFunct) and $this->id[$type] = $id;
- break;
- case T_INTERFACE: // interface, Object Interface
- $this->isInterface = true;
- case T_CLASS: // class, classes and objects
- $this->inClass = 0;
- $this->block->setClass($id);
- break;
- case T_OPEN_TAG: // <?php, <? or <%
- $openTagID = $id;
- break;
- case T_PRIVATE: // private classes and objects. PHP 5 only.
- case T_PROTECTED: // protected classes and objects. PHP 5 only.
- case T_PUBLIC: // public classes and objects. PHP 5 only.
- // captures the class visibilty
- is_null($this->inClass) or $this->id['access'] = array($id, $value);
- break;
- case T_STATIC: // static variable scope
- if (!is_null($this->inClass) and is_null($inFunct)) {
- // captures the static property within a class and
- // outside of a function
- $this->id[$type] = $id;
- }
- break;
- case T_VAR: // var classes and objects
- // captures the class property
- is_null($this->inClass) or $this->id[$type] = $id;
- break;
- case T_STRING:
- // sets define DocBlock
- $value == 'define' and $this->block->setDefine($id);
- break;
- case T_VARIABLE: // $foo variables
- if (isset($this->id[T_INCLUDE])) {
- // including a variable instead of a string, sets the include DocBlock
- $this->block->build($this->id[T_INCLUDE]);
- } else if (isset($this->id[T_GLOBAL])) {
- // a global variable, sets the global DocBlock, e.g. global $var
- $this->block->setGlobal($this->id[T_GLOBAL], $token, $allTokens);
- } else if (is_null($this->inClass) and is_null($inFunct) and $value == '$GLOBALS') {
- // a GLOBALS variable outside of a class and function
- // sets the global variable DocBlock, e.g. $GLOBALS['foo']
- $this->block->setGLOBALS($id, $allTokens);
- } else if (isset($this->id['access']) or
- isset($this->id[T_VAR])or isset($this->id[T_STATIC])) {
- // a class property, sets the class variable
- $this->block->setVar($token);
- }
- break;
- }
- }
- if (!$isPageBlock) {
- // no Page-level DocBlock, determines the PHP version, sets the Page-level DocBlock
- $info = $this->info->parseString($data);
- list($this->phpVersion) = explode('.', $info['version']);
- $this->block->setPage($openTagID);
- }
- // re-assembles all the tokens
- $result = $this->putAll();
- }
- return $result;
- }
- /**
- * Re-assembles the source code tokens into a string
- *
- * @return boolean true on success, false on failure
- * @access private
- */
- private function putAll()
- {
- // creates the array_reduce callback, reduces the array to a string made of token values
- $callback = create_function('$string, $token', 'return $string .= $token[\'value\'];');
- return array_reduce($this->tokens, $callback);
- }
- /**
- * Sets the token value
- *
- * @param integer $id the token identification number
- * @param string $value the token value
- * @return boolean true if the token is valid, false otherwise
- * @access public
- */
- public function set($id, $value)
- {
- $isValid = $this->isValid($id) and $this->tokens[$id]['value'] = $value;
- return $isValid;
- }
- /**
- * Slices a subset of tokens
- *
- * @param integer $offset the token identification number to start looking at
- * @param string $openBracket the delimiter to start slicing at
- * @param mixed $closeBracket the delimiter to stop slicing at
- * @param integer $bracketCount to set to 1 if the offset is past the first delimiter
- * @return array the sliced tokens
- * @access private
- */
- public function slice($offset = 0, $openBracket = null, $closeBracket = null, $bracketCount = null)
- {
- $tokens = array();
- foreach($this->phpTokens as $token) {
- if ($token['id'] >= $offset) {
- // processes tokens after the offset
- $tokens[] = $token; // captures the token
- if ($openBracket !== null) {
- // only captures tokens delimited by the brackets
- // captures all types of open curly braces
- $openBracket == '{' and
- in_array($token['type'], array(T_CURLY_OPEN, T_DOLLAR_OPEN_CURLY_BRACES)) and
- $token['type'] = '{';
- // counts enclosed opening and closing brackets
- $token['type'] == $openBracket and $bracketCount++ or
- $token['type'] == $closeBracket and $bracketCount--;
- if ($bracketCount === 0) {
- // reached the last closing bracket
- break;
- }
- }
- }
- }
- return $tokens;
- }
- /**
- * Tidies a token
- *
- * An array_walk() callback function.
- *
- * @param array &$token the token
- * @param integer $id the token identification number
- * @return void
- * @access private
- * @see self::getAll()
- */
- private function tidy(&$token, $id)
- {
- if (is_array($token)) {
- // a PHP token
- // extracts the token type, e.g. T_CONSTANT_ENCAPSED_STRING
- $tidied['type'] = current($token);
- $tidied['type'] == T_PAAMAYIM_NEKUDOTAYIM and $tidied['type'] = T_DOUBLE_COLON;
- // extracts the token value, e.g. "foo"
- $tidied['value'] = next($token);
- // captures the token type as a string, note: only useful for debugging purposes
- $tidied['name'] = token_name($tidied['type']);
- } else {
- // a single character, e.g. ";"
- $tidied['type'] = $tidied['value'] = $token;
- }
- // captures the token position
- $tidied['id'] = $id;
- $token = $tidied;
- }
- }
- ?>