get('ERROR.trace'); $errorTraceArray = preg_split('/$\R?^/m', $errorTraceString); $maximalStringIndex = 0; $maximalStringLength = 0; $iters = count($errorTraceArray); for ($i = 0; $i < $iters; ++$i) { $currentStringLength = strlen($errorTraceArray[$i]); if ($maximalStringLength < $currentStringLength) { $maximalStringIndex = $i; $maximalStringLength = $currentStringLength; } } if ($iters > 1) { array_splice($errorTraceArray, $maximalStringIndex, 1); } $iters = count($errorTraceArray); for ($i = 0; $i < $iters; ++$i) { $errorTraceArray[$i] = strip_tags($errorTraceArray[$i]); $errorTraceArray[$i] = str_replace(['>', '<'], ['>', '<'], $errorTraceArray[$i]); } $errorCode = $f3->get('ERROR.code'); $errorMessage = join(', ', ['ERROR_' . $errorCode, $f3->get('ERROR.text')]); return [ 'ip' => $f3->IP, 'code' => $errorCode, 'message' => $errorMessage, 'trace' => join('
', $errorTraceArray), 'date' => date('l jS \of F Y h:i:s A'), 'post' => $f3->get('POST'), 'get' => $f3->get('GET'), ]; } public static function saveErrorInformation(\Base $f3, array $errorData): void { \Utils\Logger::log(null, $errorData['message']); $errorTraceArray = explode('
', $errorData['trace']); $printErrorTraceToLog = $f3->get('PRINT_ERROR_TRACE_TO_LOG'); if ($printErrorTraceToLog) { $iters = count($errorTraceArray); for ($i = 0; $i < $iters; ++$i) { \Utils\Logger::log(null, $errorTraceArray[$i]); } } $db = $f3->get('API_DATABASE'); if ($db) { $errorData['sql_log'] = $db->log(); $logModel = new \Models\Log(); $logModel->add($errorData); \Utils\Logger::log('SQL', $errorData['sql_log']); } if ($errorData['code'] === 500) { $toName = 'Admin'; $toAddress = \Utils\Variables::getAdminEmail(); if ($toAddress === null) { \Utils\Logger::log('Log mail error', 'ADMIN_EMAIL is not set'); return; } $subject = $f3->get('error_email_subject'); $subject = sprintf($subject, $errorData['code']); $currentTime = date('d-m-Y H:i:s'); $errorMessage = $errorData['message']; $errorTrace = $errorData['trace']; $message = $f3->get('error_email_body_template'); $message = sprintf($message, $currentTime, $errorMessage, $errorTrace); \Utils\Mailer::send($toName, $toAddress, $subject, $message); } } protected static function getAjaxErrorMessage(array $errorData): string|false { return json_encode( [ 'status' => false, 'code' => $errorData['code'], 'message' => sprintf('Request finished with code %s', $errorData['code']), ], ); } public static function getOnErrorHandler(): callable { /** * Custom onError handler: http://stackoverflow.com/questions/19763414/fat-free-framework-f3-custom-404-page-and-others-errors, https://groups.google.com/forum/#!topic/f3-framework/BOIrLs5_aEA * We can can use $f3->get('ERROR.text'), and decide which template should be displayed. * * @param $f3 */ return function (\Base $f3): void { $hive = $f3->hive(); $isAjax = $hive['AJAX']; $errorData = self::getErrorDetails($f3); self::saveErrorInformation($f3, $errorData); if ($errorData['code'] === 403 && $isAjax) { echo self::getAjaxErrorMessage($errorData); return; } if ($errorData['code'] === 403 && !$isAjax) { $f3->reroute('/logout'); return; } // Add handling 404 error if ($errorData['code'] === 404) { } if ($isAjax) { echo self::getAjaxErrorMessage($errorData); return; } $response = new \Views\Frontend(); $pageController = new \Controllers\Pages\Error(); $errorData['message'] = 'ERROR_' . $errorData['code']; unset($errorData['trace']); $pageParams = $pageController->getPageParams($errorData); $response->data = $pageParams; echo $response->render(); }; } public static function getCronErrorHandler(): callable { return function (\Base $f3): void { $errorData = self::getErrorDetails($f3); self::saveErrorInformation($f3, $errorData); }; } public static function exceptionErrorHandler(int $severity, string $message, string $file, int $line): bool { if (!(error_reporting() & $severity)) { return false; } throw new \ErrorException($message, 0, $severity, $file, $line); return true; } }