/**
* @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;
if (SerializableClosure::supportBinding()) {
if (null !== ($className = $this->getClosureScopeClass())) {
$className = '\\' . trim($className->getName(), '\\');
}
}
$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;
$hasTraitSupport = defined('T_TRAIT_C');
$tokens = $this->getTokens();
$state = 'start';
$open = 0;
$code = '';
$buffer = $name = '';
$new_key_word = false;
$classes = $functions = $constants = null;
$use = array();
$lineAdd = 0;
$isUsingScope = false;
$isUsingThisObject = false;
foreach ($tokens as $token) {
$is_array = is_array($token);
switch ($state) {
case 'start':
if ($is_array && ($token[0] === T_FUNCTION || $token[0] === T_STATIC)) {
$code .= $token[1];
$state = $token[0] === T_FUNCTION ? 'function' : 'static';
}
break;
case 'static':
if ($is_array && ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_FUNCTION)) {
$code .= $token[1];
if ($token[0] === T_FUNCTION) {
$state = 'function';
}
} else {
$code = '';
$state = 'start';
}
break;
case 'function':
if ($is_array) {
$code .= $token[1];
if ($token[0] === T_STRING) {
$state = 'named_function';
$code = '';
}
} else {
$code .= $token;
if ($token === '(') {
$state = 'closure';
}
}
break;
case 'named_function':
if (!$is_array) {
if ($token === '{') {
$open++;
} elseif ($token === '}') {
if (--$open === 0) {
$state = 'start';
}
}
}
break;
case 'closure':
if ($is_array) {
switch ($token[0]) {
case T_LINE:
$token[1] = $token[2] - $line + $lineAdd;
break;
case T_FILE:
$token[1] = $_file;
break;
case T_DIR:
$token[1] = $_dir;
break;
case T_NS_C:
$token[1] = $_namespace;
break;
case T_CLASS_C:
$token[1] = $_class;
break;
case T_FUNC_C:
$token[1] = $_function;
break;
case T_METHOD_C:
$token[1] = $_method;
break;
case T_COMMENT:
if (substr($token[1], 0, 8) === '#trackme') {
$timestamp = time();
$token[1] = '/**' . PHP_EOL;
$token[1] .= '* Date : ' . date(DATE_W3C, $timestamp) . PHP_EOL;
$token[1] .= '* Timestamp : ' . $timestamp . PHP_EOL;
$token[1] .= '* Line : ' . ($line + 1) . PHP_EOL;
$token[1] .= '* File : ' . $_file . PHP_EOL . '*/' . PHP_EOL;
$lineAdd += 5;
}
break;
case T_VARIABLE:
if ($token[1] == '$this') {
$isUsingThisObject = true;
}
break;
case T_USE:
$state = 'use';
break;
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
$open++;
break;
case T_NS_SEPARATOR:
case T_STRING:
$buffer = $name = $token[1];
$new_key_word = false;
$state = 'name';
break 2;
case T_STATIC:
$isUsingScope = true;
break;
case T_NEW:
$buffer = $token[1];
$new_key_word = true;
$state = 'new';
break 2;
default:
if ($hasTraitSupport && $token[0] == 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);
}
$token[1] = $_trait;
}
}
$code .= $token[1];
} else {
$code .= $token;
if ($token === '{') {
$open++;
} elseif ($token === '}') {
if (--$open === 0) {
break 2;
}
}
}
break;
case 'use':
if ($is_array) {
if ($token[0] === T_VARIABLE) {
$use[] = substr($token[1], 1);
}
$code .= $token[1];
} else {
if ($token == ')') {
$state = 'closure';
}
$code .= $token;
}
break;
case 'name':
if ($is_array) {
switch ($token[0]) {
case T_NS_SEPARATOR:
case T_STRING:
$name .= $token[1];
$buffer .= $token[1];
break 2;
case T_WHITESPACE:
$buffer .= $token[1];
break 2;
}
}
if ($name[0] == '\\' || ($selfOrStatic = $name == 'static' || $name == 'self')) {
$code .= $buffer . ($is_array ? $token[1] : $token);
if ($selfOrStatic) {
$isUsingScope = true;
}
} elseif ($new_key_word || $is_array && ($token[0] == T_VARIABLE || $token[0] == T_DOUBLE_COLON)) {
$suffix = substr($buffer, strlen(rtrim($buffer)));
if ($classes === null) {
$classes = $this->getClasses();
}
if (isset($classes[$name])) {
$name = $classes[$name];
} else {
$name = $nsf . '\\' . $name;
}
$code .= $name . $suffix . ($is_array ? $token[1] : $token);
} elseif (!$is_array && $token === '(') {
$suffix = substr($buffer, strlen(rtrim($buffer)));
if ($functions === null) {
$functions = $this->getFunctions();
}
if (isset($functions[$name])) {
$name = $functions[$name];
}
$code .= $name . $suffix . ($is_array ? $token[1] : $token);
} else {
if ($constants === null) {
$constants = $this->getConstants();
}
if (isset($constants[$name])) {
$suffix = substr($buffer, strlen(rtrim($buffer)));
$name = $constants[$name];
$code .= $name . $suffix . ($is_array ? $token[1] : $token);
} else {
$code .= $buffer . ($is_array ? $token[1] : $token);
}
}
$state = 'closure';
break;
case 'new':
if ($is_array) {
switch ($token[0]) {
case T_WHITESPACE:
$buffer .= $token[1];
break;
case T_NS_SEPARATOR:
case T_STRING:
$code .= $buffer;
$buffer = $name = $token[1];
$state = 'name';
break 2;
default:
$code .= $buffer . $token[1];
$state = 'closure';
break;
}
} else {
$code .= $buffer . $token;
$state = 'closure';
}
break;
}
}
$this->isBindingRequired = $isUsingThisObject;
$this->isScopeRequired = $isUsingScope;
$this->code = $code;
$this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use));
return $this->code;
}