gluon-web-remote

Web remote Administration for big size of gluon routers
git clone git://archive.git.mtrnord.blog/MTRNord/gluon-web-remote.git
Log | Files | Refs | README

Stream.php (17525B)


      1 <?php
      2 /**
      3  * php-token-stream
      4  *
      5  * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  *   * Redistributions of source code must retain the above copyright
     13  *     notice, this list of conditions and the following disclaimer.
     14  *
     15  *   * Redistributions in binary form must reproduce the above copyright
     16  *     notice, this list of conditions and the following disclaimer in
     17  *     the documentation and/or other materials provided with the
     18  *     distribution.
     19  *
     20  *   * Neither the name of Sebastian Bergmann nor the names of his
     21  *     contributors may be used to endorse or promote products derived
     22  *     from this software without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  *
     37  * @package   PHP_TokenStream
     38  * @author    Sebastian Bergmann <sebastian@phpunit.de>
     39  * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
     40  * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
     41  * @since     File available since Release 1.0.0
     42  */
     43 
     44 /**
     45  * A stream of PHP tokens.
     46  *
     47  * @author    Sebastian Bergmann <sebastian@phpunit.de>
     48  * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
     49  * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
     50  * @version   Release: @package_version@
     51  * @link      http://github.com/sebastianbergmann/php-token-stream/tree
     52  * @since     Class available since Release 1.0.0
     53  */
     54 class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
     55 {
     56     /**
     57      * @var array
     58      */
     59     protected static $customTokens = array(
     60       '(' => 'PHP_Token_OPEN_BRACKET',
     61       ')' => 'PHP_Token_CLOSE_BRACKET',
     62       '[' => 'PHP_Token_OPEN_SQUARE',
     63       ']' => 'PHP_Token_CLOSE_SQUARE',
     64       '{' => 'PHP_Token_OPEN_CURLY',
     65       '}' => 'PHP_Token_CLOSE_CURLY',
     66       ';' => 'PHP_Token_SEMICOLON',
     67       '.' => 'PHP_Token_DOT',
     68       ',' => 'PHP_Token_COMMA',
     69       '=' => 'PHP_Token_EQUAL',
     70       '<' => 'PHP_Token_LT',
     71       '>' => 'PHP_Token_GT',
     72       '+' => 'PHP_Token_PLUS',
     73       '-' => 'PHP_Token_MINUS',
     74       '*' => 'PHP_Token_MULT',
     75       '/' => 'PHP_Token_DIV',
     76       '?' => 'PHP_Token_QUESTION_MARK',
     77       '!' => 'PHP_Token_EXCLAMATION_MARK',
     78       ':' => 'PHP_Token_COLON',
     79       '"' => 'PHP_Token_DOUBLE_QUOTES',
     80       '@' => 'PHP_Token_AT',
     81       '&' => 'PHP_Token_AMPERSAND',
     82       '%' => 'PHP_Token_PERCENT',
     83       '|' => 'PHP_Token_PIPE',
     84       '$' => 'PHP_Token_DOLLAR',
     85       '^' => 'PHP_Token_CARET',
     86       '~' => 'PHP_Token_TILDE',
     87       '`' => 'PHP_Token_BACKTICK'
     88     );
     89 
     90     /**
     91      * @var string
     92      */
     93     protected $filename;
     94 
     95     /**
     96      * @var array
     97      */
     98     protected $tokens = array();
     99 
    100     /**
    101      * @var integer
    102      */
    103     protected $position = 0;
    104 
    105     /**
    106      * @var array
    107      */
    108     protected $linesOfCode = array('loc' => 0, 'cloc' => 0, 'ncloc' => 0);
    109 
    110     /**
    111      * @var array
    112      */
    113     protected $classes;
    114 
    115     /**
    116      * @var array
    117      */
    118     protected $functions;
    119 
    120     /**
    121      * @var array
    122      */
    123     protected $includes;
    124 
    125     /**
    126      * @var array
    127      */
    128     protected $interfaces;
    129 
    130     /**
    131      * @var array
    132      */
    133     protected $traits;
    134 
    135     /**
    136      * @var array
    137      */
    138     protected $lineToFunctionMap = array();
    139 
    140     /**
    141      * Constructor.
    142      *
    143      * @param string $sourceCode
    144      */
    145     public function __construct($sourceCode)
    146     {
    147         if (is_file($sourceCode)) {
    148             $this->filename = $sourceCode;
    149             $sourceCode     = file_get_contents($sourceCode);
    150         }
    151 
    152         $this->scan($sourceCode);
    153     }
    154 
    155     /**
    156      * Destructor.
    157      */
    158     public function __destruct()
    159     {
    160         $this->tokens = array();
    161     }
    162 
    163     /**
    164      * @return string
    165      */
    166     public function __toString()
    167     {
    168         $buffer = '';
    169 
    170         foreach ($this as $token) {
    171             $buffer .= $token;
    172         }
    173 
    174         return $buffer;
    175     }
    176 
    177     /**
    178      * @return string
    179      * @since  Method available since Release 1.1.0
    180      */
    181     public function getFilename()
    182     {
    183         return $this->filename;
    184     }
    185 
    186     /**
    187      * Scans the source for sequences of characters and converts them into a
    188      * stream of tokens.
    189      *
    190      * @param string $sourceCode
    191      */
    192     protected function scan($sourceCode)
    193     {
    194         $line      = 1;
    195         $tokens    = token_get_all($sourceCode);
    196         $numTokens = count($tokens);
    197 
    198         $lastNonWhitespaceTokenWasDoubleColon = FALSE;
    199 
    200         for ($i = 0; $i < $numTokens; ++$i) {
    201             $token = $tokens[$i];
    202             unset($tokens[$i]);
    203 
    204             if (is_array($token)) {
    205                 $name = substr(token_name($token[0]), 2);
    206                 $text = $token[1];
    207 
    208                 if ($lastNonWhitespaceTokenWasDoubleColon && $name == 'CLASS') {
    209                     $name = 'CLASS_NAME_CONSTANT';
    210                 }
    211 
    212                 $tokenClass = 'PHP_Token_' . $name;
    213             } else {
    214                 $text       = $token;
    215                 $tokenClass = self::$customTokens[$token];
    216             }
    217 
    218             $this->tokens[] = new $tokenClass($text, $line, $this, $i);
    219             $lines          = substr_count($text, "\n");
    220             $line          += $lines;
    221 
    222             if ($tokenClass == 'PHP_Token_HALT_COMPILER') {
    223                 break;
    224             }
    225 
    226             else if ($tokenClass == 'PHP_Token_COMMENT' ||
    227                 $tokenClass == 'PHP_Token_DOC_COMMENT') {
    228                 $this->linesOfCode['cloc'] += $lines + 1;
    229             }
    230 
    231             if ($name == 'DOUBLE_COLON') {
    232                 $lastNonWhitespaceTokenWasDoubleColon = TRUE;
    233             }
    234 
    235             else if ($name != 'WHITESPACE') {
    236                 $lastNonWhitespaceTokenWasDoubleColon = FALSE;
    237             }
    238         }
    239 
    240         $this->linesOfCode['loc']   = substr_count($sourceCode, "\n");
    241         $this->linesOfCode['ncloc'] = $this->linesOfCode['loc'] -
    242                                       $this->linesOfCode['cloc'];
    243     }
    244 
    245     /**
    246      * @return integer
    247      */
    248     public function count()
    249     {
    250         return count($this->tokens);
    251     }
    252 
    253     /**
    254      * @return PHP_Token[]
    255      */
    256     public function tokens()
    257     {
    258         return $this->tokens;
    259     }
    260 
    261     /**
    262      * @return array
    263      */
    264     public function getClasses()
    265     {
    266         if ($this->classes !== NULL) {
    267             return $this->classes;
    268         }
    269 
    270         $this->parse();
    271 
    272         return $this->classes;
    273     }
    274 
    275     /**
    276      * @return array
    277      */
    278     public function getFunctions()
    279     {
    280         if ($this->functions !== NULL) {
    281             return $this->functions;
    282         }
    283 
    284         $this->parse();
    285 
    286         return $this->functions;
    287     }
    288 
    289     /**
    290      * @return array
    291      */
    292     public function getInterfaces()
    293     {
    294         if ($this->interfaces !== NULL) {
    295             return $this->interfaces;
    296         }
    297 
    298         $this->parse();
    299 
    300         return $this->interfaces;
    301     }
    302 
    303     /**
    304      * @return array
    305      * @since  Method available since Release 1.1.0
    306      */
    307     public function getTraits()
    308     {
    309         if ($this->traits !== NULL) {
    310             return $this->traits;
    311         }
    312 
    313         $this->parse();
    314 
    315         return $this->traits;
    316     }
    317 
    318     /**
    319      * Gets the names of all files that have been included
    320      * using include(), include_once(), require() or require_once().
    321      *
    322      * Parameter $categorize set to TRUE causing this function to return a
    323      * multi-dimensional array with categories in the keys of the first dimension
    324      * and constants and their values in the second dimension.
    325      *
    326      * Parameter $category allow to filter following specific inclusion type
    327      *
    328      * @param bool   $categorize OPTIONAL
    329      * @param string $category   OPTIONAL Either 'require_once', 'require',
    330      *                                           'include_once', 'include'.
    331      * @return array
    332      * @since  Method available since Release 1.1.0
    333      */
    334     public function getIncludes($categorize = FALSE, $category = NULL)
    335     {
    336         if ($this->includes === NULL) {
    337             $this->includes = array(
    338               'require_once' => array(),
    339               'require'      => array(),
    340               'include_once' => array(),
    341               'include'      => array()
    342             );
    343 
    344             foreach ($this->tokens as $token) {
    345                 switch (get_class($token)) {
    346                     case 'PHP_Token_REQUIRE_ONCE':
    347                     case 'PHP_Token_REQUIRE':
    348                     case 'PHP_Token_INCLUDE_ONCE':
    349                     case 'PHP_Token_INCLUDE': {
    350                         $this->includes[$token->getType()][] = $token->getName();
    351                     }
    352                     break;
    353                 }
    354             }
    355         }
    356 
    357         if (isset($this->includes[$category])) {
    358             $includes = $this->includes[$category];
    359         }
    360 
    361         else if ($categorize === FALSE) {
    362             $includes = array_merge(
    363               $this->includes['require_once'],
    364               $this->includes['require'],
    365               $this->includes['include_once'],
    366               $this->includes['include']
    367             );
    368         } else {
    369             $includes = $this->includes;
    370         }
    371 
    372         return $includes;
    373     }
    374 
    375     /**
    376      * Returns the name of the function or method a line belongs to.
    377      *
    378      * @return string or null if the line is not in a function or method
    379      * @since  Method available since Release 1.2.0
    380      */
    381     public function getFunctionForLine($line)
    382     {
    383         $this->parse();
    384 
    385         if (isset($this->lineToFunctionMap[$line])) {
    386             return $this->lineToFunctionMap[$line];
    387         }
    388     }
    389 
    390     protected function parse()
    391     {
    392         $this->interfaces = array();
    393         $this->classes    = array();
    394         $this->traits     = array();
    395         $this->functions  = array();
    396         $class            = FALSE;
    397         $classEndLine     = FALSE;
    398         $trait            = FALSE;
    399         $traitEndLine     = FALSE;
    400         $interface        = FALSE;
    401         $interfaceEndLine = FALSE;
    402 
    403         foreach ($this->tokens as $token) {
    404             switch (get_class($token)) {
    405                 case 'PHP_Token_HALT_COMPILER': {
    406                     return;
    407                 }
    408                 break;
    409 
    410                 case 'PHP_Token_INTERFACE': {
    411                     $interface        = $token->getName();
    412                     $interfaceEndLine = $token->getEndLine();
    413 
    414                     $this->interfaces[$interface] = array(
    415                       'methods'   => array(),
    416                       'parent'    => $token->getParent(),
    417                       'keywords'  => $token->getKeywords(),
    418                       'docblock'  => $token->getDocblock(),
    419                       'startLine' => $token->getLine(),
    420                       'endLine'   => $interfaceEndLine,
    421                       'package'   => $token->getPackage(),
    422                       'file'      => $this->filename
    423                     );
    424                 }
    425                 break;
    426 
    427                 case 'PHP_Token_CLASS':
    428                 case 'PHP_Token_TRAIT': {
    429                     $tmp = array(
    430                       'methods'   => array(),
    431                       'parent'    => $token->getParent(),
    432                       'interfaces'=> $token->getInterfaces(),
    433                       'keywords'  => $token->getKeywords(),
    434                       'docblock'  => $token->getDocblock(),
    435                       'startLine' => $token->getLine(),
    436                       'endLine'   => $token->getEndLine(),
    437                       'package'   => $token->getPackage(),
    438                       'file'      => $this->filename
    439                     );
    440 
    441                     if ($token instanceof PHP_Token_CLASS) {
    442                         $class                 = $token->getName();
    443                         $classEndLine          = $token->getEndLine();
    444                         $this->classes[$class] = $tmp;
    445                     } else {
    446                         $trait                = $token->getName();
    447                         $traitEndLine         = $token->getEndLine();
    448                         $this->traits[$trait] = $tmp;
    449                     }
    450                 }
    451                 break;
    452 
    453                 case 'PHP_Token_FUNCTION': {
    454                     $name = $token->getName();
    455                     $tmp  = array(
    456                       'docblock'  => $token->getDocblock(),
    457                       'keywords'  => $token->getKeywords(),
    458                       'visibility'=> $token->getVisibility(),
    459                       'signature' => $token->getSignature(),
    460                       'startLine' => $token->getLine(),
    461                       'endLine'   => $token->getEndLine(),
    462                       'ccn'       => $token->getCCN(),
    463                       'file'      => $this->filename
    464                     );
    465 
    466                     if ($class === FALSE &&
    467                         $trait === FALSE &&
    468                         $interface === FALSE) {
    469                         $this->functions[$name] = $tmp;
    470 
    471                         $this->addFunctionToMap(
    472                           $name, $tmp['startLine'], $tmp['endLine']
    473                         );
    474                     }
    475 
    476                     else if ($class !== FALSE) {
    477                         $this->classes[$class]['methods'][$name] = $tmp;
    478 
    479                         $this->addFunctionToMap(
    480                           $class . '::' . $name,
    481                           $tmp['startLine'],
    482                           $tmp['endLine']
    483                         );
    484                     }
    485 
    486                     else if ($trait !== FALSE) {
    487                         $this->traits[$trait]['methods'][$name] = $tmp;
    488 
    489                         $this->addFunctionToMap(
    490                           $trait . '::' . $name,
    491                           $tmp['startLine'],
    492                           $tmp['endLine']
    493                         );
    494                     }
    495 
    496                     else {
    497                         $this->interfaces[$interface]['methods'][$name] = $tmp;
    498                     }
    499                 }
    500                 break;
    501 
    502                 case 'PHP_Token_CLOSE_CURLY': {
    503                     if ($classEndLine !== FALSE &&
    504                         $classEndLine == $token->getLine()) {
    505                         $class        = FALSE;
    506                         $classEndLine = FALSE;
    507                     }
    508 
    509                     else if ($traitEndLine !== FALSE &&
    510                         $traitEndLine == $token->getLine()) {
    511                         $trait        = FALSE;
    512                         $traitEndLine = FALSE;
    513                     }
    514 
    515                     else if ($interfaceEndLine !== FALSE &&
    516                         $interfaceEndLine == $token->getLine()) {
    517                         $interface        = FALSE;
    518                         $interfaceEndLine = FALSE;
    519                     }
    520                 }
    521                 break;
    522             }
    523         }
    524     }
    525 
    526     /**
    527      * @return array
    528      */
    529     public function getLinesOfCode()
    530     {
    531         return $this->linesOfCode;
    532     }
    533 
    534     /**
    535      */
    536     public function rewind()
    537     {
    538         $this->position = 0;
    539     }
    540 
    541     /**
    542      * @return boolean
    543      */
    544     public function valid()
    545     {
    546         return isset($this->tokens[$this->position]);
    547     }
    548 
    549     /**
    550      * @return integer
    551      */
    552     public function key()
    553     {
    554         return $this->position;
    555     }
    556 
    557     /**
    558      * @return PHP_Token
    559      */
    560     public function current()
    561     {
    562         return $this->tokens[$this->position];
    563     }
    564 
    565     /**
    566      */
    567     public function next()
    568     {
    569         $this->position++;
    570     }
    571 
    572     /**
    573      * @param mixed $offset
    574      */
    575     public function offsetExists($offset)
    576     {
    577         return isset($this->tokens[$offset]);
    578     }
    579 
    580     /**
    581      * @param  mixed $offset
    582      * @return mixed
    583      */
    584     public function offsetGet($offset)
    585     {
    586         return $this->tokens[$offset];
    587     }
    588 
    589     /**
    590      * @param mixed $offset
    591      * @param mixed $value
    592      */
    593     public function offsetSet($offset, $value)
    594     {
    595         $this->tokens[$offset] = $value;
    596     }
    597 
    598     /**
    599      * @param mixed $offset
    600      */
    601     public function offsetUnset($offset)
    602     {
    603         unset($this->tokens[$offset]);
    604     }
    605 
    606     /**
    607      * Seek to an absolute position.
    608      *
    609      * @param  integer $position
    610      * @throws OutOfBoundsException
    611      */
    612     public function seek($position)
    613     {
    614         $this->position = $position;
    615 
    616         if (!$this->valid()) {
    617             throw new OutOfBoundsException('Invalid seek position');
    618         }
    619     }
    620 
    621     private function addFunctionToMap($name, $startLine, $endLine)
    622     {
    623         for ($line = $startLine; $line <= $endLine; $line++) {
    624             $this->lineToFunctionMap[$line] = $name;
    625         }
    626     }
    627 }