mirror of
https://github.com/filp/whoops.git
synced 2026-09-16 20:56:21 +00:00
feat: support frame filters
This commit is contained in:
@@ -14,10 +14,11 @@ class Formatter
|
||||
* Returns all basic information about the exception in a simple array
|
||||
* for further convertion to other languages
|
||||
* @param InspectorInterface $inspector
|
||||
* @param bool $shouldAddTrace
|
||||
* @param bool $shouldAddTrace
|
||||
* @param array<callable> $frameFilters
|
||||
* @return array
|
||||
*/
|
||||
public static function formatExceptionAsDataArray(InspectorInterface $inspector, $shouldAddTrace)
|
||||
public static function formatExceptionAsDataArray(InspectorInterface $inspector, $shouldAddTrace, array $frameFilters = [])
|
||||
{
|
||||
$exception = $inspector->getException();
|
||||
$response = [
|
||||
@@ -29,7 +30,7 @@ class Formatter
|
||||
];
|
||||
|
||||
if ($shouldAddTrace) {
|
||||
$frames = $inspector->getFrames();
|
||||
$frames = $inspector->getFrames($frameFilters);
|
||||
$frameData = [];
|
||||
|
||||
foreach ($frames as $frame) {
|
||||
|
||||
@@ -176,9 +176,12 @@ class Inspector implements InspectorInterface
|
||||
/**
|
||||
* Returns an iterator for the inspected exception's
|
||||
* frames.
|
||||
*
|
||||
* @param array<callable> $frameFilters
|
||||
*
|
||||
* @return \Whoops\Exception\FrameCollection
|
||||
*/
|
||||
public function getFrames()
|
||||
public function getFrames(array $frameFilters = [])
|
||||
{
|
||||
if ($this->frames === null) {
|
||||
$frames = $this->getTrace($this->exception);
|
||||
@@ -234,6 +237,13 @@ class Inspector implements InspectorInterface
|
||||
$newFrames->prependFrames($outerFrames->topDiff($newFrames));
|
||||
$this->frames = $newFrames;
|
||||
}
|
||||
|
||||
// Apply frame filters callbacks on the frames stack
|
||||
if (!empty($frameFilters)) {
|
||||
foreach ($frameFilters as $filterCallback) {
|
||||
$this->frames->filter($filterCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->frames;
|
||||
|
||||
@@ -60,7 +60,8 @@ class JsonResponseHandler extends Handler
|
||||
'errors' => [
|
||||
Formatter::formatExceptionAsDataArray(
|
||||
$this->getInspector(),
|
||||
$this->addTraceToOutput()
|
||||
$this->addTraceToOutput(),
|
||||
$this->getRun()->getFrameFilters()
|
||||
),
|
||||
]
|
||||
];
|
||||
@@ -68,7 +69,8 @@ class JsonResponseHandler extends Handler
|
||||
$response = [
|
||||
'error' => Formatter::formatExceptionAsDataArray(
|
||||
$this->getInspector(),
|
||||
$this->addTraceToOutput()
|
||||
$this->addTraceToOutput(),
|
||||
$this->getRun()->getFrameFilters()
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ class PlainTextHandler extends Handler
|
||||
return '';
|
||||
}
|
||||
$inspector = $this->getInspector();
|
||||
$frames = $inspector->getFrames();
|
||||
$frames = $inspector->getFrames($this->getRun()->getFrameFilters());
|
||||
|
||||
$response = "\nStack trace:";
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ class PrettyPageHandler extends Handler
|
||||
*/
|
||||
protected function getExceptionFrames()
|
||||
{
|
||||
$frames = $this->getInspector()->getFrames();
|
||||
$frames = $this->getInspector()->getFrames($this->getRun()->getFrameFilters());
|
||||
|
||||
if ($this->getApplicationPaths()) {
|
||||
foreach ($frames as $frame) {
|
||||
|
||||
@@ -43,7 +43,8 @@ class XmlResponseHandler extends Handler
|
||||
$response = [
|
||||
'error' => Formatter::formatExceptionAsDataArray(
|
||||
$this->getInspector(),
|
||||
$this->addTraceToOutput()
|
||||
$this->addTraceToOutput(),
|
||||
$this->getRun()->getFrameFilters()
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
@@ -62,7 +62,10 @@ interface InspectorInterface
|
||||
/**
|
||||
* Returns an iterator for the inspected exception's
|
||||
* frames.
|
||||
*
|
||||
* @param array<callable> $frameFilters
|
||||
*
|
||||
* @return \Whoops\Exception\FrameCollection
|
||||
*/
|
||||
public function getFrames();
|
||||
public function getFrames(array $frameFilters = []);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,11 @@ final class Run implements RunInterface
|
||||
*/
|
||||
private $inspectorFactory;
|
||||
|
||||
/**
|
||||
* @var array<callable>
|
||||
*/
|
||||
private $frameFilters = [];
|
||||
|
||||
public function __construct(SystemFacade $system = null)
|
||||
{
|
||||
$this->system = $system ?: new SystemFacade;
|
||||
@@ -176,6 +181,17 @@ final class Run implements RunInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFrameFilters()
|
||||
{
|
||||
return $this->frameFilters;
|
||||
}
|
||||
|
||||
public function clearFrameFilters()
|
||||
{
|
||||
$this->frameFilters = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an error handler.
|
||||
*
|
||||
@@ -511,6 +527,18 @@ final class Run implements RunInterface
|
||||
$this->inspectorFactory = $factory;
|
||||
}
|
||||
|
||||
public function addFrameFilter($filterCallback)
|
||||
{
|
||||
if (!is_callable($filterCallback)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
"A frame filter must be of type callable, %s type given.",
|
||||
gettype($filterCallback)
|
||||
));
|
||||
}
|
||||
|
||||
$this->frameFilters[] = $filterCallback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Throwable $exception
|
||||
|
||||
@@ -49,6 +49,16 @@ interface RunInterface
|
||||
*/
|
||||
public function clearHandlers();
|
||||
|
||||
/**
|
||||
* @return array<callable>
|
||||
*/
|
||||
public function getFrameFilters();
|
||||
|
||||
/**
|
||||
* @return Run
|
||||
*/
|
||||
public function clearFrameFilters();
|
||||
|
||||
/**
|
||||
* Registers this instance as an error handler.
|
||||
*
|
||||
@@ -137,4 +147,12 @@ interface RunInterface
|
||||
* Special case to deal with Fatal errors and the like.
|
||||
*/
|
||||
public function handleShutdown();
|
||||
|
||||
/**
|
||||
* Registers a filter callback in the frame filters stack.
|
||||
*
|
||||
* @param callable $filterCallback
|
||||
* @return \Whoops\Run
|
||||
*/
|
||||
public function addFrameFilter($filterCallback);
|
||||
}
|
||||
|
||||
@@ -95,6 +95,42 @@ class InspectorTest extends TestCase
|
||||
$this->assertInstanceOf('Whoops\\Exception\\FrameCollection', $inspector->getFrames());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Whoops\Exception\Inspector::getFrames
|
||||
*/
|
||||
public function testGetFramesWithFiltersReturnsCollection()
|
||||
{
|
||||
$exception = $this->getException();
|
||||
$inspector = $this->getInspectorInstance($exception);
|
||||
|
||||
$frames = $inspector->getFrames([
|
||||
function(Frame $frame) {
|
||||
return true;
|
||||
},
|
||||
]);
|
||||
|
||||
$this->assertInstanceOf('Whoops\\Exception\\FrameCollection', $frames);
|
||||
$this->assertNotEmpty($frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Whoops\Exception\Inspector::getFrames
|
||||
*/
|
||||
public function testGetFramesWithFiltersReturnsEmptyCollection()
|
||||
{
|
||||
$exception = $this->getException();
|
||||
$inspector = $this->getInspectorInstance($exception);
|
||||
|
||||
$frames = $inspector->getFrames([
|
||||
function(Frame $frame) {
|
||||
return false;
|
||||
},
|
||||
]);
|
||||
|
||||
$this->assertInstanceOf('Whoops\\Exception\\FrameCollection', $frames);
|
||||
$this->assertEmpty($frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Whoops\Exception\Inspector::hasPreviousException
|
||||
* @covers Whoops\Exception\Inspector::getPreviousExceptionInspector
|
||||
|
||||
@@ -12,6 +12,7 @@ use InvalidArgumentException;
|
||||
use Mockery as m;
|
||||
use RuntimeException;
|
||||
use Whoops\Handler\Handler;
|
||||
use Whoops\Exception\Frame;
|
||||
|
||||
class RunTest extends TestCase
|
||||
{
|
||||
@@ -532,4 +533,42 @@ class RunTest extends TestCase
|
||||
|
||||
$this->getRunInstance()->sendExitCode(255);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Whoops\Run::addFrameFilter
|
||||
* @covers Whoops\Run::getFrameFilters
|
||||
*/
|
||||
public function testAddFrameFilter()
|
||||
{
|
||||
$run = $this->getRunInstance();
|
||||
|
||||
$filterCallbackOne = function(Frame $frame) {};
|
||||
$filterCallbackTwo = function(Frame $frame) {};
|
||||
|
||||
$run
|
||||
->addFrameFilter($filterCallbackOne)
|
||||
->addFrameFilter($filterCallbackTwo);
|
||||
|
||||
$frameFilters = $run->getFrameFilters();
|
||||
|
||||
$this->assertCount(2, $frameFilters);
|
||||
$this->assertContains($filterCallbackOne, $frameFilters);
|
||||
$this->assertContains($filterCallbackTwo, $frameFilters);
|
||||
$this->assertInstanceOf("Whoops\\RunInterface", $run);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Whoops\Run::clearFrameFilters
|
||||
* @covers Whoops\Run::getFrameFilters
|
||||
*/
|
||||
public function testClearFrameFilters()
|
||||
{
|
||||
$run = $this->getRunInstance();
|
||||
$run->addFrameFilter(function(Frame $frame) {});
|
||||
|
||||
$run = $run->clearFrameFilters();
|
||||
|
||||
$this->assertEmpty($run->getFrameFilters());
|
||||
$this->assertInstanceOf("Whoops\\RunInterface", $run);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user