Kint::_getCalleeInfo PHP Method

_getCalleeInfo() private static method

returns parameter names that the function was passed, as well as any predefined symbols before function call (modifiers)
private static _getCalleeInfo ( array $trace ) : array(
$trace array
return array(
    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 array(null, null, $callee, $previousCaller, $miniTrace);
        }
        # 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'] . "*" . $callee['type'] . "*" . $callee['function'];
            } else {
                $codePattern = ".**" . $callee['type'] . "*" . $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            [{(]\n\n            # search for modifiers (group 1)\n            ([-+!@~]*)?\n\n            # spaces\n            *\n\n            # check if output is assigned to a variable (group 2) todo: does not detect concat\n            (\n                \\\$[a-z0-9_]+ # variable\n                *\\.?=*  # assignment\n            )?\n\n            # possibly a namespace symbol\n            \\\\?\n\n\t\t\t# spaces again\n            *\n\n            # main call to Kint\n            ({$codePattern})\n\n\t\t\t# spaces everywhere\n            *\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]);
        $callToKint = end($matches[3]);
        $bracket = end($matches[4]);
        if (empty($callToKint)) {
            # if a wrapper is misconfigured, don't display the whole file as variable name
            return array(array(), $modifiers, $callee, $previousCaller, $miniTrace);
        }
        $modifiers = $modifiers[0];
        if ($assignment[1] !== -1) {
            $modifiers .= '@';
        }
        $paramsString = preg_replace("[+]", ' ', 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] = "";
                }
            }
            if ($inString) {
                if ($letter !== $inString || $escaped) {
                    $paramsString[$i] = "";
                }
            }
            $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("[+]", '...', $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);
    }