1023 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			1023 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			PHP
		
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								/* ===========================================================================
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2018-2019 Zindex Software
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Licensed under the MIT License
							 | 
						||
| 
								 | 
							
								 * =========================================================================== */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace Opis\Closure;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use Closure;
							 | 
						||
| 
								 | 
							
								use ReflectionFunction;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ReflectionClosure extends ReflectionFunction
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    protected $code;
							 | 
						||
| 
								 | 
							
								    protected $tokens;
							 | 
						||
| 
								 | 
							
								    protected $hashedName;
							 | 
						||
| 
								 | 
							
								    protected $useVariables;
							 | 
						||
| 
								 | 
							
								    protected $isStaticClosure;
							 | 
						||
| 
								 | 
							
								    protected $isScopeRequired;
							 | 
						||
| 
								 | 
							
								    protected $isBindingRequired;
							 | 
						||
| 
								 | 
							
								    protected $isShortClosure;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    protected static $files = array();
							 | 
						||
| 
								 | 
							
								    protected static $classes = array();
							 | 
						||
| 
								 | 
							
								    protected static $functions = array();
							 | 
						||
| 
								 | 
							
								    protected static $constants = array();
							 | 
						||
| 
								 | 
							
								    protected static $structures = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * ReflectionClosure constructor.
							 | 
						||
| 
								 | 
							
								     * @param Closure $closure
							 | 
						||
| 
								 | 
							
								     * @param string|null $code
							 | 
						||
| 
								 | 
							
								     * @throws \ReflectionException
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function __construct(Closure $closure, $code = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->code = $code;
							 | 
						||
| 
								 | 
							
								        parent::__construct($closure);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return bool
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function isStatic()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->isStaticClosure === null) {
							 | 
						||
| 
								 | 
							
								            $this->isStaticClosure = strtolower(substr($this->getCode(), 0, 6)) === 'static';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->isStaticClosure;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function isShortClosure()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->isShortClosure === null) {
							 | 
						||
| 
								 | 
							
								            $code = $this->getCode();
							 | 
						||
| 
								 | 
							
								            if ($this->isStatic()) {
							 | 
						||
| 
								 | 
							
								                $code = substr($code, 6);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $this->isShortClosure = strtolower(substr(trim($code), 0, 2)) === 'fn';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->isShortClosure;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return string
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function getCode()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if($this->code !== null){
							 | 
						||
| 
								 | 
							
								            return $this->code;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $fileName = $this->getFileName();
							 | 
						||
| 
								 | 
							
								        $line = $this->getStartLine() - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $match = ClosureStream::STREAM_PROTO . '://';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ($line === 1 && substr($fileName, 0, strlen($match)) === $match) {
							 | 
						||
| 
								 | 
							
								            return $this->code = substr($fileName, strlen($match));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $className = null;
							 | 
						||
| 
								 | 
							
								        $fn = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (null !== $className = $this->getClosureScopeClass()) {
							 | 
						||
| 
								 | 
							
								            $className = '\\' . trim($className->getName(), '\\');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if($php7 = PHP_MAJOR_VERSION === 7){
							 | 
						||
| 
								 | 
							
								            switch (PHP_MINOR_VERSION){
							 | 
						||
| 
								 | 
							
								                case 0:
							 | 
						||
| 
								 | 
							
								                    $php7_types = array('string', 'int', 'bool', 'float');
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 1:
							 | 
						||
| 
								 | 
							
								                    $php7_types = array('string', 'int', 'bool', 'float', 'void');
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 2:
							 | 
						||
| 
								 | 
							
								                default:
							 | 
						||
| 
								 | 
							
								                    $php7_types = array('string', 'int', 'bool', 'float', 'void', 'object');
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $fn = PHP_MINOR_VERSION === 4;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $class_keywords = ['self', 'static', 'parent'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $ns = $this->getNamespaceName();
							 | 
						||
| 
								 | 
							
								        $nsf = $ns == '' ? '' : ($ns[0] == '\\' ? $ns : '\\' . $ns);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $_file = var_export($fileName, true);
							 | 
						||
| 
								 | 
							
								        $_dir = var_export(dirname($fileName), true);
							 | 
						||
| 
								 | 
							
								        $_namespace = var_export($ns, true);
							 | 
						||
| 
								 | 
							
								        $_class = var_export(trim($className, '\\'), true);
							 | 
						||
| 
								 | 
							
								        $_function = $ns . ($ns == '' ? '' : '\\') . '{closure}';
							 | 
						||
| 
								 | 
							
								        $_method = ($className == '' ? '' : trim($className, '\\') . '::') . $_function;
							 | 
						||
| 
								 | 
							
								        $_function = var_export($_function, true);
							 | 
						||
| 
								 | 
							
								        $_method = var_export($_method, true);
							 | 
						||
| 
								 | 
							
								        $_trait = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $tokens = $this->getTokens();
							 | 
						||
| 
								 | 
							
								        $state = $lastState = 'start';
							 | 
						||
| 
								 | 
							
								        $inside_structure = false;
							 | 
						||
| 
								 | 
							
								        $isShortClosure = false;
							 | 
						||
| 
								 | 
							
								        $inside_structure_mark = 0;
							 | 
						||
| 
								 | 
							
								        $open = 0;
							 | 
						||
| 
								 | 
							
								        $code = '';
							 | 
						||
| 
								 | 
							
								        $id_start = $id_start_ci = $id_name = $context = '';
							 | 
						||
| 
								 | 
							
								        $classes = $functions = $constants = null;
							 | 
						||
| 
								 | 
							
								        $use = array();
							 | 
						||
| 
								 | 
							
								        $lineAdd = 0;
							 | 
						||
| 
								 | 
							
								        $isUsingScope = false;
							 | 
						||
| 
								 | 
							
								        $isUsingThisObject = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for($i = 0, $l = count($tokens); $i < $l; $i++) {
							 | 
						||
| 
								 | 
							
								            $token = $tokens[$i];
							 | 
						||
| 
								 | 
							
								            switch ($state) {
							 | 
						||
| 
								 | 
							
								                case 'start':
							 | 
						||
| 
								 | 
							
								                    if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) {
							 | 
						||
| 
								 | 
							
								                        $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = $token[0] === T_FUNCTION ? 'function' : 'static';
							 | 
						||
| 
								 | 
							
								                    } elseif ($fn && $token[0] === T_FN) {
							 | 
						||
| 
								 | 
							
								                        $isShortClosure = true;
							 | 
						||
| 
								 | 
							
								                        $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = 'closure_args';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'static':
							 | 
						||
| 
								 | 
							
								                    if ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_FUNCTION) {
							 | 
						||
| 
								 | 
							
								                        $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                        if ($token[0] === T_FUNCTION) {
							 | 
						||
| 
								 | 
							
								                            $state = 'function';
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    } elseif ($fn && $token[0] === T_FN) {
							 | 
						||
| 
								 | 
							
								                        $isShortClosure = true;
							 | 
						||
| 
								 | 
							
								                        $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = 'closure_args';
							 | 
						||
| 
								 | 
							
								                    } else {
							 | 
						||
| 
								 | 
							
								                        $code = '';
							 | 
						||
| 
								 | 
							
								                        $state = 'start';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'function':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $code = '';
							 | 
						||
| 
								 | 
							
								                            $state = 'named_function';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '(':
							 | 
						||
| 
								 | 
							
								                            $code .= '(';
							 | 
						||
| 
								 | 
							
								                            $state = 'closure_args';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $code .= is_array($token) ? $token[1] : $token;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'named_function':
							 | 
						||
| 
								 | 
							
								                    if($token[0] === T_FUNCTION || $token[0] === T_STATIC){
							 | 
						||
| 
								 | 
							
								                        $code = $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = $token[0] === T_FUNCTION ? 'function' : 'static';
							 | 
						||
| 
								 | 
							
								                    } elseif ($fn && $token[0] === T_FN) {
							 | 
						||
| 
								 | 
							
								                        $isShortClosure = true;
							 | 
						||
| 
								 | 
							
								                        $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = 'closure_args';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'closure_args':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $id_start = $token[1];
							 | 
						||
| 
								 | 
							
								                            $id_start_ci = strtolower($id_start);
							 | 
						||
| 
								 | 
							
								                            $id_name = '';
							 | 
						||
| 
								 | 
							
								                            $context = 'args';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_name';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'closure_args';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_USE:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $state = 'use';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_DOUBLE_ARROW:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            if ($isShortClosure) {
							 | 
						||
| 
								 | 
							
								                                $state = 'closure';
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case ':':
							 | 
						||
| 
								 | 
							
								                            $code .= ':';
							 | 
						||
| 
								 | 
							
								                            $state = 'return';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                            $code .= '{';
							 | 
						||
| 
								 | 
							
								                            $state = 'closure';
							 | 
						||
| 
								 | 
							
								                            $open++;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $code .= is_array($token) ? $token[1] : $token;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'use':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_VARIABLE:
							 | 
						||
| 
								 | 
							
								                            $use[] = substr($token[1], 1);
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                            $code .= '{';
							 | 
						||
| 
								 | 
							
								                            $state = 'closure';
							 | 
						||
| 
								 | 
							
								                            $open++;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case ':':
							 | 
						||
| 
								 | 
							
								                            $code .= ':';
							 | 
						||
| 
								 | 
							
								                            $state = 'return';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $code .= is_array($token) ? $token[1] : $token;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'return':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_WHITESPACE:
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                        case T_DOC_COMMENT:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $id_start = $token[1];
							 | 
						||
| 
								 | 
							
								                            $id_start_ci = strtolower($id_start);
							 | 
						||
| 
								 | 
							
								                            $id_name = '';
							 | 
						||
| 
								 | 
							
								                            $context = 'return_type';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_name';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'return';
							 | 
						||
| 
								 | 
							
								                            break 2;
							 | 
						||
| 
								 | 
							
								                        case T_DOUBLE_ARROW:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            if ($isShortClosure) {
							 | 
						||
| 
								 | 
							
								                                $state = 'closure';
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                            $code .= '{';
							 | 
						||
| 
								 | 
							
								                            $state = 'closure';
							 | 
						||
| 
								 | 
							
								                            $open++;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $code .= is_array($token) ? $token[1] : $token;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'closure':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_CURLY_OPEN:
							 | 
						||
| 
								 | 
							
								                        case T_DOLLAR_OPEN_CURLY_BRACES:
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                            $code .= '{';
							 | 
						||
| 
								 | 
							
								                            $open++;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '}':
							 | 
						||
| 
								 | 
							
								                            $code .= '}';
							 | 
						||
| 
								 | 
							
								                            if(--$open === 0 && !$isShortClosure){
							 | 
						||
| 
								 | 
							
								                                break 3;
							 | 
						||
| 
								 | 
							
								                            } elseif ($inside_structure) {
							 | 
						||
| 
								 | 
							
								                                $inside_structure = !($open === $inside_structure_mark);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '(':
							 | 
						||
| 
								 | 
							
								                        case '[':
							 | 
						||
| 
								 | 
							
								                            $code .= $token[0];
							 | 
						||
| 
								 | 
							
								                            if ($isShortClosure) {
							 | 
						||
| 
								 | 
							
								                                $open++;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case ')':
							 | 
						||
| 
								 | 
							
								                        case ']':
							 | 
						||
| 
								 | 
							
								                            if ($isShortClosure) {
							 | 
						||
| 
								 | 
							
								                                if ($open === 0) {
							 | 
						||
| 
								 | 
							
								                                    break 3;
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                --$open;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $code .= $token[0];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case ',':
							 | 
						||
| 
								 | 
							
								                        case ';':
							 | 
						||
| 
								 | 
							
								                            if ($isShortClosure && $open === 0) {
							 | 
						||
| 
								 | 
							
								                                break 3;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $code .= $token[0];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_LINE:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[2] - $line + $lineAdd;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_FILE:
							 | 
						||
| 
								 | 
							
								                            $code .= $_file;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_DIR:
							 | 
						||
| 
								 | 
							
								                            $code .= $_dir;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_NS_C:
							 | 
						||
| 
								 | 
							
								                            $code .= $_namespace;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_CLASS_C:
							 | 
						||
| 
								 | 
							
								                            $code .= $inside_structure ? $token[1] : $_class;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_FUNC_C:
							 | 
						||
| 
								 | 
							
								                            $code .= $inside_structure ? $token[1] : $_function;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_METHOD_C:
							 | 
						||
| 
								 | 
							
								                            $code .= $inside_structure ? $token[1] : $_method;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                            if (substr($token[1], 0, 8) === '#trackme') {
							 | 
						||
| 
								 | 
							
								                                $timestamp = time();
							 | 
						||
| 
								 | 
							
								                                $code .= '/**' . PHP_EOL;
							 | 
						||
| 
								 | 
							
								                                $code .= '* Date      : ' . date(DATE_W3C, $timestamp) . PHP_EOL;
							 | 
						||
| 
								 | 
							
								                                $code .= '* Timestamp : ' . $timestamp . PHP_EOL;
							 | 
						||
| 
								 | 
							
								                                $code .= '* Line      : ' . ($line + 1) . PHP_EOL;
							 | 
						||
| 
								 | 
							
								                                $code .= '* File      : ' . $_file . PHP_EOL . '*/' . PHP_EOL;
							 | 
						||
| 
								 | 
							
								                                $lineAdd += 5;
							 | 
						||
| 
								 | 
							
								                            } else {
							 | 
						||
| 
								 | 
							
								                                $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_VARIABLE:
							 | 
						||
| 
								 | 
							
								                            if($token[1] == '$this' && !$inside_structure){
							 | 
						||
| 
								 | 
							
								                                $isUsingThisObject = true;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_STATIC:
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $id_start = $token[1];
							 | 
						||
| 
								 | 
							
								                            $id_start_ci = strtolower($id_start);
							 | 
						||
| 
								 | 
							
								                            $id_name = '';
							 | 
						||
| 
								 | 
							
								                            $context = 'root';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_name';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'closure';
							 | 
						||
| 
								 | 
							
								                            break 2;
							 | 
						||
| 
								 | 
							
								                        case T_NEW:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $context = 'new';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_start';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'closure';
							 | 
						||
| 
								 | 
							
								                            break 2;
							 | 
						||
| 
								 | 
							
								                        case T_USE:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $context = 'use';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_start';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'closure';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_INSTANCEOF:
							 | 
						||
| 
								 | 
							
								                        case T_INSTEADOF:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $context = 'instanceof';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_start';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'closure';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_OBJECT_OPERATOR:
							 | 
						||
| 
								 | 
							
								                        case T_DOUBLE_COLON:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $lastState = 'closure';
							 | 
						||
| 
								 | 
							
								                            $state = 'ignore_next';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_FUNCTION:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $state = 'closure_args';
							 | 
						||
| 
								 | 
							
								                            if (!$inside_structure) {
							 | 
						||
| 
								 | 
							
								                                $inside_structure = true;
							 | 
						||
| 
								 | 
							
								                                $inside_structure_mark = $open;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_TRAIT_C:
							 | 
						||
| 
								 | 
							
								                            if ($_trait === null) {
							 | 
						||
| 
								 | 
							
								                                $startLine = $this->getStartLine();
							 | 
						||
| 
								 | 
							
								                                $endLine = $this->getEndLine();
							 | 
						||
| 
								 | 
							
								                                $structures = $this->getStructures();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                                $_trait = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                                foreach ($structures as &$struct) {
							 | 
						||
| 
								 | 
							
								                                    if ($struct['type'] === 'trait' &&
							 | 
						||
| 
								 | 
							
								                                        $struct['start'] <= $startLine &&
							 | 
						||
| 
								 | 
							
								                                        $struct['end'] >= $endLine
							 | 
						||
| 
								 | 
							
								                                    ) {
							 | 
						||
| 
								 | 
							
								                                        $_trait = ($ns == '' ? '' : $ns . '\\') . $struct['name'];
							 | 
						||
| 
								 | 
							
								                                        break;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                                $_trait = var_export($_trait, true);
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            $code .= $_trait;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $code .= is_array($token) ? $token[1] : $token;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'ignore_next':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_WHITESPACE:
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                        case T_DOC_COMMENT:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_CLASS:
							 | 
						||
| 
								 | 
							
								                        case T_NEW:
							 | 
						||
| 
								 | 
							
								                        case T_STATIC:
							 | 
						||
| 
								 | 
							
								                        case T_VARIABLE:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                        case T_CLASS_C:
							 | 
						||
| 
								 | 
							
								                        case T_FILE:
							 | 
						||
| 
								 | 
							
								                        case T_DIR:
							 | 
						||
| 
								 | 
							
								                        case T_METHOD_C:
							 | 
						||
| 
								 | 
							
								                        case T_FUNC_C:
							 | 
						||
| 
								 | 
							
								                        case T_FUNCTION:
							 | 
						||
| 
								 | 
							
								                        case T_INSTANCEOF:
							 | 
						||
| 
								 | 
							
								                        case T_LINE:
							 | 
						||
| 
								 | 
							
								                        case T_NS_C:
							 | 
						||
| 
								 | 
							
								                        case T_TRAIT_C:
							 | 
						||
| 
								 | 
							
								                        case T_USE:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $state = $lastState;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $state = $lastState;
							 | 
						||
| 
								 | 
							
								                            $i--;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'id_start':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_WHITESPACE:
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                        case T_DOC_COMMENT:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                        case T_STATIC:
							 | 
						||
| 
								 | 
							
								                            $id_start = $token[1];
							 | 
						||
| 
								 | 
							
								                            $id_start_ci = strtolower($id_start);
							 | 
						||
| 
								 | 
							
								                            $id_name = '';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_name';
							 | 
						||
| 
								 | 
							
								                            break 2;
							 | 
						||
| 
								 | 
							
								                        case T_VARIABLE:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $state = $lastState;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_CLASS:
							 | 
						||
| 
								 | 
							
								                            $code .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $state = 'anonymous';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $i--;//reprocess last
							 | 
						||
| 
								 | 
							
								                            $state = 'id_name';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'id_name':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]){
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $id_name .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_WHITESPACE:
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                        case T_DOC_COMMENT:
							 | 
						||
| 
								 | 
							
								                            $id_name .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '(':
							 | 
						||
| 
								 | 
							
								                            if ($isShortClosure) {
							 | 
						||
| 
								 | 
							
								                                $open++;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            if($context === 'new' || false !== strpos($id_name, '\\')){
							 | 
						||
| 
								 | 
							
								                                if($id_start_ci === 'self' || $id_start_ci === 'static') {
							 | 
						||
| 
								 | 
							
								                                    if (!$inside_structure) {
							 | 
						||
| 
								 | 
							
								                                        $isUsingScope = true;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                } elseif ($id_start !== '\\' && !in_array($id_start_ci, $class_keywords)) {
							 | 
						||
| 
								 | 
							
								                                    if ($classes === null) {
							 | 
						||
| 
								 | 
							
								                                        $classes = $this->getClasses();
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    if (isset($classes[$id_start_ci])) {
							 | 
						||
| 
								 | 
							
								                                        $id_start = $classes[$id_start_ci];
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    if($id_start[0] !== '\\'){
							 | 
						||
| 
								 | 
							
								                                        $id_start = $nsf . '\\' . $id_start;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            } else {
							 | 
						||
| 
								 | 
							
								                                if($id_start !== '\\'){
							 | 
						||
| 
								 | 
							
								                                    if($functions === null){
							 | 
						||
| 
								 | 
							
								                                        $functions = $this->getFunctions();
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    if(isset($functions[$id_start_ci])){
							 | 
						||
| 
								 | 
							
								                                        $id_start = $functions[$id_start_ci];
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $code .= $id_start . $id_name . '(';
							 | 
						||
| 
								 | 
							
								                            $state = $lastState;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_VARIABLE:
							 | 
						||
| 
								 | 
							
								                        case T_DOUBLE_COLON:
							 | 
						||
| 
								 | 
							
								                            if($id_start !== '\\') {
							 | 
						||
| 
								 | 
							
								                                if($id_start_ci === 'self' || $id_start_ci === 'parent'){
							 | 
						||
| 
								 | 
							
								                                    if (!$inside_structure) {
							 | 
						||
| 
								 | 
							
								                                        $isUsingScope = true;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                } elseif ($id_start_ci === 'static') {
							 | 
						||
| 
								 | 
							
								                                    if (!$inside_structure) {
							 | 
						||
| 
								 | 
							
								                                        $isUsingScope = $token[0] === T_DOUBLE_COLON;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                } elseif (!($php7 && in_array($id_start_ci, $php7_types))){
							 | 
						||
| 
								 | 
							
								                                    if ($classes === null) {
							 | 
						||
| 
								 | 
							
								                                        $classes = $this->getClasses();
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    if (isset($classes[$id_start_ci])) {
							 | 
						||
| 
								 | 
							
								                                        $id_start = $classes[$id_start_ci];
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                    if($id_start[0] !== '\\'){
							 | 
						||
| 
								 | 
							
								                                        $id_start = $nsf . '\\' . $id_start;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            $code .= $id_start . $id_name . $token[1];
							 | 
						||
| 
								 | 
							
								                            $state = $token[0] === T_DOUBLE_COLON ? 'ignore_next' : $lastState;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            if($id_start !== '\\' && !defined($id_start)){
							 | 
						||
| 
								 | 
							
								                                if($constants === null){
							 | 
						||
| 
								 | 
							
								                                    $constants = $this->getConstants();
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                if(isset($constants[$id_start])){
							 | 
						||
| 
								 | 
							
								                                    $id_start = $constants[$id_start];
							 | 
						||
| 
								 | 
							
								                                } elseif($context === 'use' ||
							 | 
						||
| 
								 | 
							
								                                    $context === 'instanceof' ||
							 | 
						||
| 
								 | 
							
								                                    $context === 'args' ||
							 | 
						||
| 
								 | 
							
								                                    $context === 'return_type' ||
							 | 
						||
| 
								 | 
							
								                                    $context === 'extends' ||
							 | 
						||
| 
								 | 
							
								                                    $context === 'root'
							 | 
						||
| 
								 | 
							
								                                ){
							 | 
						||
| 
								 | 
							
								                                    if($id_start_ci === 'self' || $id_start_ci === 'static' || $id_start_ci === 'parent'){
							 | 
						||
| 
								 | 
							
								                                        if (!$inside_structure && !$id_start_ci === 'static') {
							 | 
						||
| 
								 | 
							
								                                            $isUsingScope = true;
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                    } elseif (!($php7 && in_array($id_start_ci, $php7_types))){
							 | 
						||
| 
								 | 
							
								                                        if($classes === null){
							 | 
						||
| 
								 | 
							
								                                            $classes = $this->getClasses();
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                        if(isset($classes[$id_start_ci])){
							 | 
						||
| 
								 | 
							
								                                            $id_start = $classes[$id_start_ci];
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                        if($id_start[0] !== '\\'){
							 | 
						||
| 
								 | 
							
								                                            $id_start = $nsf . '\\' . $id_start;
							 | 
						||
| 
								 | 
							
								                                        }
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $code .= $id_start . $id_name;
							 | 
						||
| 
								 | 
							
								                            $state = $lastState;
							 | 
						||
| 
								 | 
							
								                            $i--;//reprocess last token
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'anonymous':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $id_start = $token[1];
							 | 
						||
| 
								 | 
							
								                            $id_start_ci = strtolower($id_start);
							 | 
						||
| 
								 | 
							
								                            $id_name = '';
							 | 
						||
| 
								 | 
							
								                            $state = 'id_name';
							 | 
						||
| 
								 | 
							
								                            $context = 'extends';
							 | 
						||
| 
								 | 
							
								                            $lastState = 'anonymous';
							 | 
						||
| 
								 | 
							
								                        break;
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                            $state = 'closure';
							 | 
						||
| 
								 | 
							
								                            if (!$inside_structure) {
							 | 
						||
| 
								 | 
							
								                                $inside_structure = true;
							 | 
						||
| 
								 | 
							
								                                $inside_structure_mark = $open;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $i--;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $code .= is_array($token) ? $token[1] : $token;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ($isShortClosure) {
							 | 
						||
| 
								 | 
							
								            $this->useVariables = $this->getStaticVariables();
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->isShortClosure = $isShortClosure;
							 | 
						||
| 
								 | 
							
								        $this->isBindingRequired = $isUsingThisObject;
							 | 
						||
| 
								 | 
							
								        $this->isScopeRequired = $isUsingScope;
							 | 
						||
| 
								 | 
							
								        $this->code = $code;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->code;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function getUseVariables()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if($this->useVariables !== null){
							 | 
						||
| 
								 | 
							
								            return $this->useVariables;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $tokens = $this->getTokens();
							 | 
						||
| 
								 | 
							
								        $use = array();
							 | 
						||
| 
								 | 
							
								        $state = 'start';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        foreach ($tokens as &$token) {
							 | 
						||
| 
								 | 
							
								            $is_array = is_array($token);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            switch ($state) {
							 | 
						||
| 
								 | 
							
								                case 'start':
							 | 
						||
| 
								 | 
							
								                    if ($is_array && $token[0] === T_USE) {
							 | 
						||
| 
								 | 
							
								                        $state = 'use';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'use':
							 | 
						||
| 
								 | 
							
								                    if ($is_array) {
							 | 
						||
| 
								 | 
							
								                        if ($token[0] === T_VARIABLE) {
							 | 
						||
| 
								 | 
							
								                            $use[] = substr($token[1], 1);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    } elseif ($token == ')') {
							 | 
						||
| 
								 | 
							
								                        break 2;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->useVariables;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * return bool
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function isBindingRequired()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if($this->isBindingRequired === null){
							 | 
						||
| 
								 | 
							
								            $this->getCode();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->isBindingRequired;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * return bool
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function isScopeRequired()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if($this->isScopeRequired === null){
							 | 
						||
| 
								 | 
							
								            $this->getCode();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->isScopeRequired;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return string
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getHashedFileName()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->hashedName === null) {
							 | 
						||
| 
								 | 
							
								            $this->hashedName = sha1($this->getFileName());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->hashedName;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getFileTokens()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $key = $this->getHashedFileName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!isset(static::$files[$key])) {
							 | 
						||
| 
								 | 
							
								            static::$files[$key] = token_get_all(file_get_contents($this->getFileName()));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return static::$files[$key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getTokens()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->tokens === null) {
							 | 
						||
| 
								 | 
							
								            $tokens = $this->getFileTokens();
							 | 
						||
| 
								 | 
							
								            $startLine = $this->getStartLine();
							 | 
						||
| 
								 | 
							
								            $endLine = $this->getEndLine();
							 | 
						||
| 
								 | 
							
								            $results = array();
							 | 
						||
| 
								 | 
							
								            $start = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            foreach ($tokens as &$token) {
							 | 
						||
| 
								 | 
							
								                if (!is_array($token)) {
							 | 
						||
| 
								 | 
							
								                    if ($start) {
							 | 
						||
| 
								 | 
							
								                        $results[] = $token;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    continue;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                $line = $token[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if ($line <= $endLine) {
							 | 
						||
| 
								 | 
							
								                    if ($line >= $startLine) {
							 | 
						||
| 
								 | 
							
								                        $start = true;
							 | 
						||
| 
								 | 
							
								                        $results[] = $token;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    continue;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            $this->tokens = $results;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->tokens;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getClasses()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $key = $this->getHashedFileName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!isset(static::$classes[$key])) {
							 | 
						||
| 
								 | 
							
								            $this->fetchItems();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return static::$classes[$key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getFunctions()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $key = $this->getHashedFileName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!isset(static::$functions[$key])) {
							 | 
						||
| 
								 | 
							
								            $this->fetchItems();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return static::$functions[$key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getConstants()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $key = $this->getHashedFileName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!isset(static::$constants[$key])) {
							 | 
						||
| 
								 | 
							
								            $this->fetchItems();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return static::$constants[$key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function getStructures()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $key = $this->getHashedFileName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!isset(static::$structures[$key])) {
							 | 
						||
| 
								 | 
							
								            $this->fetchItems();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return static::$structures[$key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    protected function fetchItems()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $key = $this->getHashedFileName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $classes = array();
							 | 
						||
| 
								 | 
							
								        $functions = array();
							 | 
						||
| 
								 | 
							
								        $constants = array();
							 | 
						||
| 
								 | 
							
								        $structures = array();
							 | 
						||
| 
								 | 
							
								        $tokens = $this->getFileTokens();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $open = 0;
							 | 
						||
| 
								 | 
							
								        $state = 'start';
							 | 
						||
| 
								 | 
							
								        $lastState = '';
							 | 
						||
| 
								 | 
							
								        $prefix = '';
							 | 
						||
| 
								 | 
							
								        $name = '';
							 | 
						||
| 
								 | 
							
								        $alias = '';
							 | 
						||
| 
								 | 
							
								        $isFunc = $isConst = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $startLine = $endLine = 0;
							 | 
						||
| 
								 | 
							
								        $structType = $structName = '';
							 | 
						||
| 
								 | 
							
								        $structIgnore = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        foreach ($tokens as $token) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            switch ($state) {
							 | 
						||
| 
								 | 
							
								                case 'start':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case T_CLASS:
							 | 
						||
| 
								 | 
							
								                        case T_INTERFACE:
							 | 
						||
| 
								 | 
							
								                        case T_TRAIT:
							 | 
						||
| 
								 | 
							
								                            $state = 'before_structure';
							 | 
						||
| 
								 | 
							
								                            $startLine = $token[2];
							 | 
						||
| 
								 | 
							
								                            $structType = $token[0] == T_CLASS
							 | 
						||
| 
								 | 
							
								                                                    ? 'class'
							 | 
						||
| 
								 | 
							
								                                                    : ($token[0] == T_INTERFACE ? 'interface' : 'trait');
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_USE:
							 | 
						||
| 
								 | 
							
								                            $state = 'use';
							 | 
						||
| 
								 | 
							
								                            $prefix = $name = $alias = '';
							 | 
						||
| 
								 | 
							
								                            $isFunc = $isConst = false;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_FUNCTION:
							 | 
						||
| 
								 | 
							
								                            $state = 'structure';
							 | 
						||
| 
								 | 
							
								                            $structIgnore = true;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_NEW:
							 | 
						||
| 
								 | 
							
								                            $state = 'new';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_OBJECT_OPERATOR:
							 | 
						||
| 
								 | 
							
								                        case T_DOUBLE_COLON:
							 | 
						||
| 
								 | 
							
								                            $state = 'invoke';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'use':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case T_FUNCTION:
							 | 
						||
| 
								 | 
							
								                            $isFunc = true;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_CONST:
							 | 
						||
| 
								 | 
							
								                            $isConst = true;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                            $name .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $name .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $alias = $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_AS:
							 | 
						||
| 
								 | 
							
								                            $lastState = 'use';
							 | 
						||
| 
								 | 
							
								                            $state = 'alias';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                            $prefix = $name;
							 | 
						||
| 
								 | 
							
								                            $name = $alias = '';
							 | 
						||
| 
								 | 
							
								                            $state = 'use-group';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case ',':
							 | 
						||
| 
								 | 
							
								                        case ';':
							 | 
						||
| 
								 | 
							
								                            if ($name === '' || $name[0] !== '\\') {
							 | 
						||
| 
								 | 
							
								                                $name = '\\' . $name;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            if ($alias !== '') {
							 | 
						||
| 
								 | 
							
								                                if ($isFunc) {
							 | 
						||
| 
								 | 
							
								                                    $functions[strtolower($alias)] = $name;
							 | 
						||
| 
								 | 
							
								                                } elseif ($isConst) {
							 | 
						||
| 
								 | 
							
								                                    $constants[$alias] = $name;
							 | 
						||
| 
								 | 
							
								                                } else {
							 | 
						||
| 
								 | 
							
								                                    $classes[strtolower($alias)] = $name;
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $name = $alias = '';
							 | 
						||
| 
								 | 
							
								                            $state = $token === ';' ? 'start' : 'use';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'use-group':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case T_NS_SEPARATOR:
							 | 
						||
| 
								 | 
							
								                            $name .= $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_STRING:
							 | 
						||
| 
								 | 
							
								                            $name .= $token[1];
							 | 
						||
| 
								 | 
							
								                            $alias = $token[1];
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case T_AS:
							 | 
						||
| 
								 | 
							
								                            $lastState = 'use-group';
							 | 
						||
| 
								 | 
							
								                            $state = 'alias';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case ',':
							 | 
						||
| 
								 | 
							
								                        case '}':
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            if ($prefix === '' || $prefix[0] !== '\\') {
							 | 
						||
| 
								 | 
							
								                                $prefix = '\\' . $prefix;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            if ($alias !== '') {
							 | 
						||
| 
								 | 
							
								                                if ($isFunc) {
							 | 
						||
| 
								 | 
							
								                                    $functions[strtolower($alias)] = $prefix . $name;
							 | 
						||
| 
								 | 
							
								                                } elseif ($isConst) {
							 | 
						||
| 
								 | 
							
								                                    $constants[$alias] = $prefix . $name;
							 | 
						||
| 
								 | 
							
								                                } else {
							 | 
						||
| 
								 | 
							
								                                    $classes[strtolower($alias)] = $prefix . $name;
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            $name = $alias = '';
							 | 
						||
| 
								 | 
							
								                            $state = $token === '}' ? 'use' : 'use-group';
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'alias':
							 | 
						||
| 
								 | 
							
								                    if ($token[0] === T_STRING) {
							 | 
						||
| 
								 | 
							
								                        $alias = $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = $lastState;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'new':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case T_WHITESPACE:
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                        case T_DOC_COMMENT:
							 | 
						||
| 
								 | 
							
								                            break 2;
							 | 
						||
| 
								 | 
							
								                        case T_CLASS:
							 | 
						||
| 
								 | 
							
								                            $state = 'structure';
							 | 
						||
| 
								 | 
							
								                            $structIgnore = true;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $state = 'start';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'invoke':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case T_WHITESPACE:
							 | 
						||
| 
								 | 
							
								                        case T_COMMENT:
							 | 
						||
| 
								 | 
							
								                        case T_DOC_COMMENT:
							 | 
						||
| 
								 | 
							
								                            break 2;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            $state = 'start';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'before_structure':
							 | 
						||
| 
								 | 
							
								                    if ($token[0] == T_STRING) {
							 | 
						||
| 
								 | 
							
								                        $structName = $token[1];
							 | 
						||
| 
								 | 
							
								                        $state = 'structure';
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                case 'structure':
							 | 
						||
| 
								 | 
							
								                    switch ($token[0]) {
							 | 
						||
| 
								 | 
							
								                        case '{':
							 | 
						||
| 
								 | 
							
								                        case T_CURLY_OPEN:
							 | 
						||
| 
								 | 
							
								                        case T_DOLLAR_OPEN_CURLY_BRACES:
							 | 
						||
| 
								 | 
							
								                            $open++;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        case '}':
							 | 
						||
| 
								 | 
							
								                            if (--$open == 0) {
							 | 
						||
| 
								 | 
							
								                                if(!$structIgnore){
							 | 
						||
| 
								 | 
							
								                                    $structures[] = array(
							 | 
						||
| 
								 | 
							
								                                        'type' => $structType,
							 | 
						||
| 
								 | 
							
								                                        'name' => $structName,
							 | 
						||
| 
								 | 
							
								                                        'start' => $startLine,
							 | 
						||
| 
								 | 
							
								                                        'end' => $endLine,
							 | 
						||
| 
								 | 
							
								                                    );
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                $structIgnore = false;
							 | 
						||
| 
								 | 
							
								                                $state = 'start';
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        default:
							 | 
						||
| 
								 | 
							
								                            if (is_array($token)) {
							 | 
						||
| 
								 | 
							
								                                $endLine = $token[2];
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        static::$classes[$key] = $classes;
							 | 
						||
| 
								 | 
							
								        static::$functions[$key] = $functions;
							 | 
						||
| 
								 | 
							
								        static::$constants[$key] = $constants;
							 | 
						||
| 
								 | 
							
								        static::$structures[$key] = $structures;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |