private static function Kint::_getCalleeInfo in Devel 8.2
Same name and namespace in other branches
- 8 kint/kint/Kint.class.php \Kint::_getCalleeInfo()
* returns parameter names that the function was passed, as well as any predefined symbols before function * call (modifiers) * *
Parameters
array $trace: * * @return array( $parameters, $modifier, $callee, $previousCaller )
1 call to Kint::_getCalleeInfo()
- Kint::dump in kint/
kint/ Kint.class.php - * Dump information about variables, accepts any number of parameters, supports modifiers: * * clean up any output before kint and place the dump at the top of page: * - Kint::dump() * ***** * expand all nodes on display: * !…
File
- kint/
kint/ Kint.class.php, line 383
Class
Code
private static function _getCalleeInfo($trace) {
$previousCaller = array();
$miniTrace = array();
$prevStep = array();
# go from back of trace to find first occurrence of call to Kint or its wrappers
while ($step = array_pop($trace)) {
if (self::_stepIsInternal($step)) {
$previousCaller = $prevStep;
break;
}
elseif (isset($step['file'], $step['line'])) {
unset($step['object'], $step['args']);
array_unshift($miniTrace, $step);
}
$prevStep = $step;
}
$callee = $step;
if (!isset($callee['file']) || !is_readable($callee['file'])) {
return false;
}
# open the file and read it up to the position where the function call expression ended
$file = fopen($callee['file'], 'r');
$line = 0;
$source = '';
while (($row = fgets($file)) !== false) {
if (++$line > $callee['line']) {
break;
}
$source .= $row;
}
fclose($file);
$source = self::_removeAllButCode($source);
if (empty($callee['class'])) {
$codePattern = $callee['function'];
}
else {
if ($callee['type'] === '::') {
$codePattern = $callee['class'] . "\7*" . $callee['type'] . "\7*" . $callee['function'];
}
else {
/*if ( $callee['type'] === '->' )*/
$codePattern = ".*\7*" . $callee['type'] . "\7*" . $callee['function'];
}
}
// todo if more than one call in one line - not possible to determine variable names
// todo does not recognize string concat
# get the position of the last call to the function
preg_match_all("\n [\n # beginning of statement\n [\7{(]\n\n # search for modifiers (group 1)\n ([-+!@~]*)?\n\n # spaces\n \7*\n\n # check if output is assigned to a variable (group 2) todo: does not detect concat\n (\n \\\$[a-z0-9_]+ # variable\n \7*\\.?=\7* # assignment\n )?\n\n # possibly a namespace symbol\n \\\\?\n\n\t\t\t# spaces again\n \7*\n\n # main call to Kint\n {$codePattern}\n\n\t\t\t# spaces everywhere\n \7*\n\n # find the character where kint's opening bracket resides (group 3)\n (\\()\n\n ]ix", $source, $matches, PREG_OFFSET_CAPTURE);
$modifiers = end($matches[1]);
$assignment = end($matches[2]);
$bracket = end($matches[3]);
$modifiers = $modifiers[0];
if ($assignment[1] !== -1) {
$modifiers .= '@';
}
$paramsString = preg_replace("[\7+]", ' ', substr($source, $bracket[1] + 1));
# we now have a string like this:
# <parameters passed>); <the rest of the last read line>
# remove everything in brackets and quotes, we don't need nested statements nor literal strings which would
# only complicate separating individual arguments
$c = strlen($paramsString);
$inString = $escaped = $openedBracket = $closingBracket = false;
$i = 0;
$inBrackets = 0;
$openedBrackets = array();
while ($i < $c) {
$letter = $paramsString[$i];
if (!$inString) {
if ($letter === '\'' || $letter === '"') {
$inString = $letter;
}
elseif ($letter === '(' || $letter === '[') {
$inBrackets++;
$openedBrackets[] = $openedBracket = $letter;
$closingBracket = $openedBracket === '(' ? ')' : ']';
}
elseif ($inBrackets && $letter === $closingBracket) {
$inBrackets--;
array_pop($openedBrackets);
$openedBracket = end($openedBrackets);
$closingBracket = $openedBracket === '(' ? ')' : ']';
}
elseif (!$inBrackets && $letter === ')') {
$paramsString = substr($paramsString, 0, $i);
break;
}
}
elseif ($letter === $inString && !$escaped) {
$inString = false;
}
# replace whatever was inside quotes or brackets with untypeable characters, we don't
# need that info. We'll later replace the whole string with '...'
if ($inBrackets > 0) {
if ($inBrackets > 1 || $letter !== $openedBracket) {
$paramsString[$i] = "\7";
}
}
if ($inString) {
if ($letter !== $inString || $escaped) {
$paramsString[$i] = "\7";
}
}
$escaped = !$escaped && $letter === '\\';
$i++;
}
# by now we have an un-nested arguments list, lets make it to an array for processing further
$arguments = explode(',', preg_replace("[\7+]", '...', $paramsString));
# test each argument whether it was passed literary or was it an expression or a variable name
$parameters = array();
$blacklist = array(
'null',
'true',
'false',
'array(...)',
'array()',
'"..."',
'[...]',
'b"..."',
);
foreach ($arguments as $argument) {
$argument = trim($argument);
if (is_numeric($argument) || in_array(str_replace("'", '"', strtolower($argument)), $blacklist, true)) {
$parameters[] = null;
}
else {
$parameters[] = $argument;
}
}
return array(
$parameters,
$modifiers,
$callee,
$previousCaller,
$miniTrace,
);
}