Separate and clean up frame handling logic

- separate the logic for adding missing file line info and removal of error handling frames
- added default file and line values other than null
- added method to validate next frame to utilize it's file and line values for current frame
This commit is contained in:
Adam Vercimak
2015-08-12 09:47:05 -05:00
parent e9742f909f
commit eb1b7a9945
+47 -13
View File
@@ -93,27 +93,37 @@ class Inspector
public function getFrames()
{
if ($this->frames === null) {
$frames = $this->getTrace($this->exception);
$frames = $this->getTrace($this->exception);
// Fill empty line/file info for call_user_func_array usages (PHP Bug #44428)
foreach ($frames as $k => $frame) {
if (empty($frame['file'])) {
// Default values when file and line are missing
$file = '[internal]';
$line = 0;
$next_frame = !empty($frames[$k + 1]) ? $frames[$k + 1] : array();
if ($this->isValidNextFrame($next_frame)) {
$file = $next_frame['file'];
$line = $next_frame['line'];
}
$frames[$k]['file'] = $file;
$frames[$k]['line'] = $line;
}
}
// Find latest non-error handling frame index ($i) used to remove error handling frames
// Also fill empty line/file info for call_user_func_array usages (PHP Bug #44428)
$i = 0;
foreach ($frames as $k => $frame) {
if (empty($frame['file'])) {
$file = null;
$line = null;
if (!empty($frames[$k + 1]) && !empty($frames[$k + 1]['file'])) {
$file = $frames[$k + 1]['file'];
$line = $frames[$k + 1]['line'];
}
$frame['file'] = $frames[$k]['file'] = $file;
$frame['line'] = $frames[$k]['line'] = $line;
}
if ($frame['file'] == $this->exception->getFile() && $frame['line'] == $this->exception->getLine()) {
$i = $k;
}
}
// Remove error handling frames
if ($i > 0) {
array_splice($frames, 0, $i);
@@ -209,4 +219,28 @@ class Inspector
'args' => array(),
);
}
/**
* Determine if the frame can be used to fill in previous frame's missing info
* happens for call_user_func and call_user_func_array usages (PHP Bug #44428)
*
* @param array $frame
* @return boolean
*/
protected function isValidNextFrame(array $frame)
{
if (empty($frame['file'])) {
return false;
}
if (empty($frame['line'])) {
return false;
}
if (empty($frame['function']) || !stristr($frame['function'], 'call_user_func')) {
return false;
}
return true;
}
}