/** * Перехватчик исключений. * * Ловит исключения, которые не были пойманы ранее. Последний шанс обработать ошибку. Например, записать в лог или * намылить админу. Можно так же вежливо откланяться юзеру. * * После выполнения этого обработчика программа остановится, обеспечено PHP. * * Если указано предыдущее исключение, отсюда не пишем в лог. Сей факт указывает на то, что реальное исключение * уже было поймано и обработано. Считаем, что необходимость логирования была решена в предыдущих обработчиках. * * Прим: для поддержки PHP 7.0 тип ожидаемого параметра расширен, * см. {@see http://php.net/manual/ru/function.set-exception-handler.php PHP::set_exception_handler()} * * @param \Throwable $ex */ public static function exceptionHandler($ex) { $class = get_class($ex); $message = nl2br($ex->getMessage()); $file = str_replace(ROOT_PATH, '/', $ex->getFile()); $line = $ex->getLine(); $trace = $ex->getTraceAsString(); if (isConsoleInterface()) { echo 'Исключение: ' . $class . PHP_EOL . PHP_EOL . $message . PHP_EOL . PHP_EOL . 'Стек вызовов:' . PHP_EOL . $trace . PHP_EOL; return; } if (!headers_sent()) { header('500 Internal Server Error'); header('Content-Type: text/html; charset=UTF-8'); } if (DEBUG) { echo Render::fetch('exception.htm', compact('class', 'message', 'file', 'line', 'trace')); } else { echo Render::fetch('exception_prod.htm', ['domain' => Env::domainName()]); if ($ex->getPrevious() === null) { $logger = App::logger(); $logger->addTyped("Class: {$class}" . PHP_EOL . "Message: {$message}" . PHP_EOL . "Source: {$file}:{$line}" . PHP_EOL . PHP_EOL . "Trace: {$trace}", $logger::EXCEPTION); } } }
/** * Редирект с выходом из приложения. * * Прим.: указание абсолютного URL - требование спецификации HTTP/1.1, * {@link http://php.net/manual/ru/function.header.php} * * Быстрая справка по кодам с редиректом {@link http://php.net/manual/ru/function.header.php#78470} * * Хитрый редирект на основе комментария {@link http://php.net/manual/ru/function.headers-sent.php#60450} * * @param string $url новый относительный адрес, с ведущим слешем * @param int $code код ответа HTTP */ public static function redirect($url, $code = 302) { $url = Env::domainUrl() . $url; if (!headers_sent()) { header('location:' . $url, true, $code); } else { echo "\n <script type='text/javascript'>\n window.location.href='{$url}'\n </script>\n <noscript>\n <meta http-equiv='refresh' content='0; url={$url}'/>\n </noscript>\n "; } App::end(); }
/** * Письмо админу с текущим сообщение лога. * * @return void */ private function mailToAdmin() { $logIt = $this->logIt; if (!($mailTo = $this->conf['_mail'])) { $this->addTyped('Не задан email админа, не могу отправить сообщение от логера.', ILogger::ENGINE); return; } $domain = Env::domainName(); $date = $logIt['ts']->format('Y/m/d H:i:s P'); $rn = PHP_EOL; $letters['text'] = 'Сообщение от логера' . $rn . $rn . $logIt['message'] . $rn . $rn . "Тип: {$logIt['type']}{$rn}" . "Источник: {$logIt['source']}" . $rn . $rn . "URL запроса:{$logIt['request']}" . $rn . "IP юзера: {$logIt['userIP']}" . $rn . $rn . "{$date} (c) {$domain}"; $vars = ['message' => nl2br($logIt['message']), 'type' => $logIt['type'], 'source' => $logIt['source'], 'request' => $logIt['request'], 'userIP' => $logIt['userIP'], 'date' => $date, 'homeURL' => Env::indexPage(), 'domain' => $domain]; $letters['html'] = Render::fetch('log_letter.htm', $vars); $from = App::conf('noreply_mail') ?: "noreply@{$domain}"; if (!Mailer::complex($from, $mailTo, "Сообщение от логера сайта {$domain}", $letters)) { $this->addTyped('Не удалось отправить сообщение от логера.', ILogger::ENGINE); } }
/** * Абсолютный URL текущей страницы. * * Если нет заголовка 'HTTP_HOST', вернем NULL. * * @copyright 2007-2010 SARITASA LLC <*****@*****.**> * @link http://www.saritasa.com * * @return string|null */ public static function absoluteURL() { if (!isset($_SERVER['HTTP_HOST'])) { return false; } $user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW'] . '@' : ''; $url = Env::scheme() . $user . $_SERVER['HTTP_HOST'] . Env::port(); $relatedUrl = ''; if (isset($_SERVER['X_ORIGINAL_URL'])) { $relatedUrl = $_SERVER['X_ORIGINAL_URL']; } else { if (isset($_SERVER['X_REWRITE_URL'])) { $relatedUrl = $_SERVER['X_REWRITE_URL']; } else { if (isset($_SERVER['IIS_WasUrlRewritten']) && $_SERVER['IIS_WasUrlRewritten'] == '1' && !empty($_SERVER['UNENCODED_URL'])) { $relatedUrl = $_SERVER['UNENCODED_URL']; } else { if (isset($_SERVER['REQUEST_URI'])) { $relatedUrl = $_SERVER['REQUEST_URI']; if (strpos($relatedUrl, $url) === 0) { $relatedUrl = substr($relatedUrl, strlen($url)); } } else { if (isset($_SERVER['ORIG_PATH_INFO'])) { $relatedUrl = $_SERVER['ORIG_PATH_INFO']; if (!empty($_SERVER['QUERY_STRING'])) { $relatedUrl .= '?' . $_SERVER['QUERY_STRING']; } } else { if (isset($_SERVER['PHP_SELF'])) { $relatedUrl = $_SERVER['PHP_SELF']; } } } } } } return $url . $relatedUrl; }