Final Class Yiisoft\VarDumper\ClosureExporter
| Inheritance | Yiisoft\VarDumper\ClosureExporter |
|---|
ClosureExporter exports PHP {@see \Closure} as a string containing PHP code.
The string is a valid PHP expression that can be evaluated by PHP parser and the evaluation result will give back the closure instance.
Public Methods
| Method | Description | Defined By |
|---|---|---|
| __construct() | Yiisoft\VarDumper\ClosureExporter | |
| export() | Export closure as a string containing PHP code. | Yiisoft\VarDumper\ClosureExporter |
Method Details
| public mixed __construct ( ) |
public function __construct()
{
$this->useStatementParser = new UseStatementParser();
}
Export closure as a string containing PHP code.
| public string export ( Closure $closure, integer $level = 0 ) | ||
| $closure | Closure |
Closure to export. |
| $level | integer |
Level for padding. |
| return | string |
String containing PHP code. |
|---|---|---|
| throws | ReflectionException | |
public function export(Closure $closure, int $level = 0): string
{
$reflection = new ReflectionFunction($closure);
$fileName = $reflection->getFileName();
$start = $reflection->getStartLine();
$end = $reflection->getEndLine();
if ($fileName === false || $start === false || $end === false || ($fileContent = file($fileName)) === false) {
return 'function () {/* Error: unable to determine Closure source */}';
}
--$start;
$uses = $this->useStatementParser->fromFile($fileName);
$tokens = token_get_all('<?php ' . implode('', array_slice($fileContent, $start, $end - $start)));
array_shift($tokens);
$bufferUse = '';
$closureTokens = [];
$pendingParenthesisCount = 0;
/** @var int<1, max> $i */
foreach ($tokens as $i => $token) {
if (in_array($token[0], [T_FUNCTION, T_FN, T_STATIC], true)) {
$closureTokens[] = $token[1];
continue;
}
if ($closureTokens === []) {
continue;
}
$readableToken = is_array($token) ? $token[1] : $token;
if ($this->useStatementParser->isTokenIsPartOfUse($token)) {
if ($this->isUseConsistingOfMultipleParts($readableToken)) {
$readableToken = $this->processFullUse($readableToken, $uses);
$bufferUse = '';
} elseif (isset($uses[$readableToken])) {
if (isset($tokens[$i + 1]) && $this->useStatementParser->isTokenIsPartOfUse($tokens[$i + 1])) {
$bufferUse .= $uses[$readableToken];
continue;
}
$readableToken = $uses[$readableToken];
} elseif ($readableToken === '\\' && isset($tokens[$i - 1][1]) && $tokens[$i - 1][1] === '\\') {
continue;
} elseif (isset($tokens[$i + 1]) && $this->useStatementParser->isTokenIsPartOfUse($tokens[$i + 1])) {
$bufferUse .= $readableToken;
continue;
}
if (!empty($bufferUse)) {
if ($bufferUse !== $readableToken && !str_contains($readableToken, $bufferUse)) {
$readableToken = $bufferUse . $readableToken;
}
$bufferUse = '';
}
}
if (is_string($token)) {
if ($this->isOpenParenthesis($token)) {
$pendingParenthesisCount++;
} elseif ($this->isCloseParenthesis($token)) {
if ($pendingParenthesisCount === 0) {
break;
}
--$pendingParenthesisCount;
} elseif ($token === ',' || $token === ';') {
if ($pendingParenthesisCount === 0) {
break;
}
}
}
$closureTokens[] = $readableToken;
}
return $this->formatClosure(implode('', $closureTokens), $level);
}
Signup or Login in order to comment.