Skip to content

Commit

Permalink
Merge pull request #749 from AmraniCh/master
Browse files Browse the repository at this point in the history
Support frame filters
  • Loading branch information
denis-sokolov committed Mar 3, 2023
2 parents b32e315 + 30fa50c commit ae8e309
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 10 deletions.
7 changes: 4 additions & 3 deletions src/Whoops/Exception/Formatter.php
Expand Up @@ -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 = [
Expand All @@ -29,7 +30,7 @@ public static function formatExceptionAsDataArray(InspectorInterface $inspector,
];

if ($shouldAddTrace) {
$frames = $inspector->getFrames();
$frames = $inspector->getFrames($frameFilters);
$frameData = [];

foreach ($frames as $frame) {
Expand Down
12 changes: 11 additions & 1 deletion src/Whoops/Exception/Inspector.php
Expand Up @@ -176,9 +176,12 @@ public function getPreviousExceptions()
/**
* 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);
Expand Down Expand Up @@ -234,6 +237,13 @@ public function getFrames()
$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;
Expand Down
6 changes: 4 additions & 2 deletions src/Whoops/Handler/JsonResponseHandler.php
Expand Up @@ -60,15 +60,17 @@ public function handle()
'errors' => [
Formatter::formatExceptionAsDataArray(
$this->getInspector(),
$this->addTraceToOutput()
$this->addTraceToOutput(),
$this->getRun()->getFrameFilters()
),
]
];
} else {
$response = [
'error' => Formatter::formatExceptionAsDataArray(
$this->getInspector(),
$this->addTraceToOutput()
$this->addTraceToOutput(),
$this->getRun()->getFrameFilters()
),
];
}
Expand Down
2 changes: 1 addition & 1 deletion src/Whoops/Handler/PlainTextHandler.php
Expand Up @@ -282,7 +282,7 @@ private function getTraceOutput()
return '';
}
$inspector = $this->getInspector();
$frames = $inspector->getFrames();
$frames = $inspector->getFrames($this->getRun()->getFrameFilters());

$response = "\nStack trace:";

Expand Down
2 changes: 1 addition & 1 deletion src/Whoops/Handler/PrettyPageHandler.php
Expand Up @@ -304,7 +304,7 @@ public function handle()
*/
protected function getExceptionFrames()
{
$frames = $this->getInspector()->getFrames();
$frames = $this->getInspector()->getFrames($this->getRun()->getFrameFilters());

if ($this->getApplicationPaths()) {
foreach ($frames as $frame) {
Expand Down
3 changes: 2 additions & 1 deletion src/Whoops/Handler/XmlResponseHandler.php
Expand Up @@ -43,7 +43,8 @@ public function handle()
$response = [
'error' => Formatter::formatExceptionAsDataArray(
$this->getInspector(),
$this->addTraceToOutput()
$this->addTraceToOutput(),
$this->getRun()->getFrameFilters()
),
];

Expand Down
5 changes: 4 additions & 1 deletion src/Whoops/Inspector/InspectorInterface.php
Expand Up @@ -62,7 +62,10 @@ public function getPreviousExceptions();
/**
* 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 = []);
}
28 changes: 28 additions & 0 deletions src/Whoops/Run.php
Expand Up @@ -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;
Expand Down Expand Up @@ -176,6 +181,17 @@ public function clearHandlers()
return $this;
}

public function getFrameFilters()
{
return $this->frameFilters;
}

public function clearFrameFilters()
{
$this->frameFilters = [];
return $this;
}

/**
* Registers this instance as an error handler.
*
Expand Down Expand Up @@ -511,6 +527,18 @@ public function setInspectorFactory(InspectorFactoryInterface $factory)
$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
Expand Down
18 changes: 18 additions & 0 deletions src/Whoops/RunInterface.php
Expand Up @@ -49,6 +49,16 @@ public function getHandlers();
*/
public function clearHandlers();

/**
* @return array<callable>
*/
public function getFrameFilters();

/**
* @return Run
*/
public function clearFrameFilters();

/**
* Registers this instance as an error handler.
*
Expand Down Expand Up @@ -137,4 +147,12 @@ public function handleError($level, $message, $file = null, $line = null);
* 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);
}
36 changes: 36 additions & 0 deletions tests/Whoops/Exception/InspectorTest.php
Expand Up @@ -95,6 +95,42 @@ public function testGetFramesReturnsCollection()
$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
Expand Down
39 changes: 39 additions & 0 deletions tests/Whoops/RunTest.php
Expand Up @@ -12,6 +12,7 @@
use Mockery as m;
use RuntimeException;
use Whoops\Handler\Handler;
use Whoops\Exception\Frame;

class RunTest extends TestCase
{
Expand Down Expand Up @@ -532,4 +533,42 @@ public function testSendExitCodeWrongCode()

$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);
}
}

0 comments on commit ae8e309

Please sign in to comment.