That was a good suggestion, especially since I had to remove the code above. (With redirectty, the page gets rendered first, before the redirect happens, so we were getting notifications even through the page was successfully redirected. Not very useful.)…
In any case, I ended up adding a handler to Whoops in order to generate info on the error any time there is an exception. Note that it only runs if debug is turned off and slack is working.
if (!c::get('debug') && c::get('slack.endpoint', false)) {
$run = new \Whoops\Run;
$run->pushHandler(function ($exception, $inspector, $run) {
sendSlackOnError($exception, $inspector, $run);
return \Whoops\Handler\Handler::DONE;
});
$run->register();
}
function sendSlackOnError($exception, $inspector, $run)
{
if (function_exists('slack')) {
$trace = $exception->getTrace();
$stackTrace = [];
foreach ($trace as $call) {
$out['title'] = $call['file'] . ':' . $call['line'];
$out['value'] = $call['class'] . $call['type'] . $call['function'] . '(';
$args = '';
foreach ($call['args'] as $arg) {
if (in_array(gettype($arg), ['boolean', 'integer', 'double', 'string', 'NULL'])) {
$args .= $arg . ',';
} else {
$args .= is_object($arg) ? get_class($arg) . ',' : gettype($arg) . ',';
}
}
$args = rtrim($args, ',');
$out['value'] .= $args . ')';
$stackTrace[] = $out;
}
$fields = array_merge([
[
'title' => 'Message',
'value' => html($exception->getMessage()),
],
[
'title' => 'File',
'value' => html($exception->getFile()),
],
[
'title' => 'Line',
'value' => html($exception->getLine()),
],
[
'title' => 'URL',
'value' => html(kirby()->request()->url()),
],
[
'title' => 'User Agent',
'value' => $_SERVER['HTTP_USER_AGENT'] ?? '',
],
[
'title' => 'Stack Trace',
'value' => $stackTrace,
],
], $stackTrace);
slack()->attach([
'fallback' => 'Exception occurred, file: ' . html($exception->getFile() . ' line:' . $exception->getLine()) .
'URL: ' . html(kirby()->request()->url()),
'text' => 'Exception Occurred',
'color' => 'red',
'fields' => $fields,
])->send('Unhandled Exception in Kirby Site!');
}
}