/** * build an exception message and data, including details of * - who is throwing the exception * - who called the code that is throwing the exception * * @param string $formatString * the message for your exception * @param array $backtrace * the output of debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) * @param array $callerFilter * list of classes to ignore in the backtrace * @return array * - [0] is the modified format string * - [1] is the message data */ public static function from($formatString, array $backtrace, array $callerFilter = []) { // who called us? $callers = FilterBacktraceForTwoCodeCallers::from($backtrace, $callerFilter); // put it all together $exceptionData = ["thrownBy" => $callers[0], "thrownByName" => $callers[0]->getCaller(), "calledBy" => $callers[1], "calledByName" => $callers[1]->getCaller()]; $newFormat = "%calledByName\$s: %thrownByName\$s says {$formatString}"; return [$newFormat, $exceptionData]; }
/** * @covers ::from */ public function testReturnsTwoStackFrames() { // ---------------------------------------------------------------- // setup your test $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); $partials = [__CLASS__, 'ReflectionMethod']; $expectedClass = $expectedMethod = []; $expectedClass[0] = 'PHPUnit_Framework_TestCase'; $expectedMethod[0] = 'runTest'; $expectedClass[1] = 'PHPUnit_Framework_TestCase'; $expectedMethod[1] = 'runBare'; // ---------------------------------------------------------------- // perform the change $result = FilterBacktraceForTwoCodeCallers::from($backtrace, $partials); // ---------------------------------------------------------------- // test the results $this->assertInstanceOf(CodeCaller::class, $result[0]); $this->assertEquals($expectedClass[0], $result[0]->getClass()); $this->assertEquals($expectedMethod[0], $result[0]->getMethod()); $this->assertInstanceOf(CodeCaller::class, $result[1]); $this->assertEquals($expectedClass[1], $result[1]->getClass()); $this->assertEquals($expectedMethod[1], $result[1]->getMethod()); }